# ParamTemplLibs

ID: base
NAME: Main templates
uk#NAME: Базові шаблони
uk#DESCR:
  Автор: Роман Савоченко <rom_as@oscada.org>
  Версія: 1.0.1
  Надає реалізацію базових шаблонів.

DB: tmplib_base
ru#NAME: Базовые шаблоны
ru#DESCR:
  Автор: Роман Савоченко <rom_as@oscada.org>
  Версия: 1.0.1
  Предоставляет реализацию базовых шаблонов.

DESCR:
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.0.1
  Allow realisation of the main templates.


ID: DevLib
NAME: Devices lib
uk#NAME: Бібліотека пристроїв
DB: tmplib_DevLib
ru#NAME: Библиотека устройств
DESCR:
  The templates library provides common templates and related functions for custom access to wide range of devices' data with simple protocol to implement into User Protocol module, present complex protocols (ModBus, OPC_UA, HTTP) or direct at internal language and also for some integration the devices data.
  Version: 1.8.0


# UserFuncLibs

ID: techApp
NAME: Technological devices
DB: techApp
uk#NAME: Технологічні апарати
ru#NAME: Технологические аппараты
DESCR:
  The models of the technological process devices.
  Founded: october 2005
  Author: Roman Savochenko
  Version: 1.0.0
  License: GPL

uk#DESCR:
  Моделі апаратів технологічних процесів.

  Засновано: жовтень 2005р
  Автор: Роман Савоченко
  Ліцензія: GPL

ru#DESCR:
  Модели аппаратов технологических процессов.

  Основан: октябрь 2005г
  Автор: Роман Савоченко
  Лицензия: GPL


ID: servProc
NAME: Service procedures
DB: lib_servProc
uk#NAME: Сервісні процедури
uk#DESCR: Бібліотека різноманітних сервісних процедур.
ru#NAME: Сервисные процедуры
ru#DESCR: Библиотека различных сервисных процедур.
DESCR:
  Library of service procedures for different using.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.0.0
  License: GPL


ID: doc
NAME: Report's documents
DB: flb_doc
uk#NAME: Звітна документація
ru#NAME: Отчётная документация
DESCR:
  Library of functions to facilitate the implementation of typical computations the primitive form of reporting documentation VCA "Document".
  Founded: January 2008
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.1.0
  License: GPL

uk#DESCR:
  Бібліотека функцій для полегшення виконання типових обчислень примітиву формування звітної документації СВК "Документ".
  Засновано: січень 2008р
  Автор: Роман Савоченко <rom_as@oscada.org>
  Версія: 1.1.0
  Ліцензія: GPL

ru#DESCR:
  Библиотека функций для облегчения выполнения типовых
  вычислений примитива формирования отчётной документации
  СВУ "Документ".
  Основана: январь 2008г
  Автор: Роман Савоченко <rom_as@oscada.org>
  Версия: 1.1.0
  Лицензия: GPL


ID: regEl
NAME: Regulation elements
DB: flb_regEl
uk#NAME: Елементи регулювання
uk#DESCR: Бібліотека елементів регулювання
ru#NAME: Элементы регулирования
ru#DESCR: Библиотека элементов регулирования
DESCR:
  Regulation elements library.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.0.0
  License: GPL


ID: Controller
NAME: Controllers
DB: lib_Controllers
uk#NAME: Контролери
uk#DESCR: Програми контролерів базованих на JavaLikeCalc.
ru#NAME: Контроллеры
ru#DESCR: Программы контроллеров основанных на JavaLikeCalc.
DESCR:
  Library of programs of controllers based on JavaLikeCalc.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.1.0
  License: GPL


ID: web
NAME: XHTML-template
DB: flb_web
uk#NAME: XHTML-шаблон
uk#DESCR: Бібліотека функцій обробки сторінок XHTML-шаблонів користувацткого Web-інтерфейсу.
ru#NAME: XHTML-шаблон
ru#DESCR: Библиотека функций обработки страниц XHTML-шаблонов пользовательского Web-интерфейса.
DESCR:
  Pages processing functions library for XHTML-template user's Web-interface.
  Author: Roman Savochenko
  Version: 0.1.0
  License: GPL


# techApp

ID: noise
NAME: Noise (2 harmonic + rand)
uk#NAME: Шум (2 гарм. + випадк.)
ru#NAME: Шум (2 гарм. + случ)
DESCR:
  Noise model. Contain three parts:
  - first harmonic part;
  - second harmonic part;
  - noise based on randomize generator of numbers.

FORMULA:
  tmp_g1=(tmp_g1>6.28)?0:tmp_g1+6.28/(per_g1*f_frq);
  tmp_g2=(tmp_g2>6.28)?0:tmp_g2+6.28/(per_g2*f_frq);
  out=off+a_g1*sin(tmp_g1)+a_g2*sin(tmp_g2)+a_rnd*(rand(2)-1);

uk#DESCR:
  Модель шуму. Містить три складові:
  - перша гармоніка;
  - друга гармоніка;
  - шум на основі генератору випадкових чисел.

ru#DESCR:
  Модель шума. Содержит три составляющие:
  - первая гармоника;
  - вторая гармоника;
  - шум на основе генератора случайных чисел.


ID: ballCrane
NAME: Ball crane
DESCR: Ball crane model. Include going and estrangement time.
uk#NAME: Кульовий кран
uk#DESCR: Модель кульового крану. Включає час ходу та час відриву.
ru#NAME: Шаровый кран
ru#DESCR: Модель шарового крана. Включает время хода и время отрыва.
FORMULA:
  if( !(st_close && !com) && !(st_open && com) )
  {
    tmp_up=(pos>0&&pos<100)?0:(tmp_up>0&&lst_com==com)?tmp_up-1./f_frq:t_up;
    pos+=(tmp_up>0)?0:(100.*(com?1.:-1.))/(t_full*f_frq);
    pos=(pos>100)?100:(pos<0)?0:pos;
    st_open=(pos>=100)?true:false;
    st_close=(pos<=0)?true:false;
    lst_com=com;
  }


ID: separator
NAME: Separator
DESCR: Separator model included two phase: liquid and gas.
uk#NAME: Сепаратор
uk#DESCR: Модель сепаратору з двома фазами рідинною та газовою.
ru#NAME: Сепаратор
ru#DESCR: Модель сепаратора с двумя фазами, жидкой и газовой.
FORMULA:
  Fж=max(0,Fi*ProcЖ);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi,Pi,293,Si,Fo+Fж,Po,293,So,lo,Q0,0.95,0.01,f_frq);
  Lж = max(0,min(100,Lж+0.27*(Fж-Fo_ж)/(Vap*Qж*f_frq)));
  Po_ж = Po + Lж*Vap/Qж;


ID: klap
NAME: Valve
uk#NAME: Засувка
ru#NAME: Задвижка
DESCR:
  Valve model, include:
  - two valve in one;
  - super-critical speed;
  - temperature change on baffling;
  - work to one side, back valve;
  - valve position speed control;
  - nonlinear cut changing by open position.

FORMULA:
  Qr=Q0+Q0*Kpr*(Pi-1);
  tmp_l1 += (abs(l_kl1-tmp_l1) > 5) ? 100*sign(l_kl1-tmp_l1)/(t_kl1*f_frq) : (l_kl1-tmp_l1)/(t_kl1*f_frq);
  tmp_l2 += (abs(l_kl2-tmp_l2) > 5) ? 100*sign(l_kl2-tmp_l2)/(t_kl2*f_frq) : (l_kl2-tmp_l2)/(t_kl2*f_frq);
  Sr=(S_kl1*pow(tmp_l1,Kln)+S_kl2*pow(tmp_l2,Kln))/pow(100,Kln);

  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi,Pi,Ti,Sr,EVAL_REAL,Po,293,So,lo,Q0,Kpr,0.01,f_frq);
  if( noBack ) Fi = max(0,Fi);
  Po = max(0,min(100,Po+0.27*(Fi-Fo)/(Q0*Kpr*So*lo*f_frq)));

  To = max(0,min(2e3,To+(abs(Fi)*(Ti*pow(Po/Pi,0.02)-To)+(Fwind+1)*(Twind-To)/Riz)/(Ct*So*lo*Qr*f_frq)));

uk#DESCR:
  Модель клапану яка враховує:
  - два клапана в одному; 
  - зверхкритичне витікання; 
  - зміна температури при дроселюванні; 
  - робота тільки у одному напрямку, зворотний клапан;
  - керування швидкісттю зміни положення;
  - нелінійність прохідного перетину від положення.

ru#DESCR:
  Модель клапана, учитывающая:
  - два клапана в одном; 
  - сверхкритическое истечение; 
  - изменение температуры при дросселировании; 
  - работа только в одном направлении, обратный клапан; 
  - управляемая скорость изменения положения; 
  - нелинейность проходного сечения от положения.


ID: lagClean
NAME: Lag (clear)
uk#NAME: Затримка (чиста)
ru#NAME: Запаздывание (чистое)
DESCR:
  Model of clear lag (transportable). Realised by include some simple lag links. Appointed for lags into long pipes.

FORMULA:
  cl1-=(cl1-in)/(t_lg*f_frq/4);
  cl2-=(cl2-cl1)/(t_lg*f_frq/4);
  cl3-=(cl3-cl2)/(t_lg*f_frq/4);
  out-=(out-cl3)/(t_lg*f_frq/4);

uk#DESCR:
  Модель чистої(транспортної) затримки. Реалізується шляхом включення декількох ланок простої затримки. Призначено для імітації затримок у довгих трубопроводах.

ru#DESCR:
  Модель чистого(транспортного) запаздывания. Реализуется путём включения нескольких простых звеньев запаздывания. Предназначен для имитации запаздывания в длинных трубопроводах.


ID: cooler
NAME: Air cooler
DESCR: Model of the air cooler for gas flow.
uk#NAME: Повітряний холодильник
uk#DESCR: Модель повітряного охолоджувача газового потоку.
ru#NAME: Возд. холодильник
ru#DESCR: Модель воздушного охладителя газового потока.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi,Pi,293,Si,Fo,Po,293,So,lo,Q0,0.95,0.01,f_frq);
  Qr = Q0+Q0*0.95*(Pi-1);
  To+=(Fi*(Ti-To)+Wc*(Tair-To)/Rt)/(Ct*(Si*li+So*lo)*Qr*f_frq);


ID: compressor
NAME: Gas compressor
uk#NAME: Компресор газовий
ru#NAME: Компрессор газовый
DESCR:
  Model of the gas compressor. Realised surge effect.
  Sarge count from the dynamic-gas curve, and next count coefficient of sarge margin.

FORMULA:
  Pmax = max(Pi,Po);
  Pmin = min(Pi,Po);
  Qr = Q0+Q0*Kpr*(Pi-1);
  Qrf = Q0+Q0*Kpr*(Pmax-1);
  Ftmp=(N>0.1)?(1-10*(Po-Pi)/(Qr*(pow(N,3)+0.1)*Kpmp)):1;
  Kzp=1-Ftmp;  //Коэффиц. запаса
  Fi=V*N*Qr*sign(Ftmp)*pow(abs(Ftmp),Kslp)+
       0.3*(4*So*Qrf/(0.01*lo*1.7724+4*Qrf))*sign(Pi-Po)*pow(Qrf*(Pmax-max(Pmax*0.528,Pmin)),0.5);
  Fit -= (Fit-Fi)/max(1,(lo*f_frq)/max(1e-4,abs(Fi/(Qrf*So))));
  Po = max(0,min(100,Po+0.27*(Fi-Fo)/(Q0*Kpr*So*lo*f_frq)));

  To+=(abs(Fi)*(Ti*pow(Po/Pi,0.3)-To)+(Fwind+1)*(Twind-To)/Riz)/(Ct*(V+So*lo)*Qr*f_frq);

uk#DESCR:
  Модель газового компресора. Враховує ефект помпажу. 
  Помпаж розраховується за газово-динамічною кривою, виходячи з якої розраховується коефіцієнт запасу по помпажу.

ru#DESCR:
  Модель газового компрессора. Учитывает эффект помпажа. Помпаж вычисляется по газо-динамической кривой, исходя из которой получается коэффициент запаса по помпажу.


ID: pipe1_1
NAME: Pipe 1->1
DESCR: Model of the pipe by scheme: 1 -> 1.
uk#NAME: Труба 1->1
uk#DESCR: Модель вузла труб за схемою: 1 -> 1.
ru#NAME: Труба 1->1
ru#DESCR: Модель узла труб по схеме: 1 -> 1.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi,Pi,293,So,Ft1,Pti,293,So,0.33*lo,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Ft1,Pti,293,So,Fto,Pt1,293,So,0.33*lo,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fto,Pt1,293,So,Fo,Po,293,So,0.33*lo,Q0,Kpr,0.01,f_frq);


ID: pipe1_2
NAME: Pipe 1->2
DESCR: Model of the pipe by scheme: 1 -> 2.
uk#NAME: Труба 1->2
uk#DESCR: Модель вузла труб за схемою: 1 -> 2.
ru#NAME: Труба 1->2
ru#DESCR: Модель узла труб по схеме: 1 -> 2.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(F1tmp,Pi,293,So1,Fo1,Po1,293,So1,lo1,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(F2tmp,Pi,293,So2,Fo2,Po2,293,So2,lo2,Q0,Kpr,0.01,f_frq);
  Fi=F1tmp+F2tmp;


ID: pipe1_3
NAME: Pipe 1->3
DESCR: Model of the pipe by scheme: 1 -> 3.
uk#NAME: Труба 1->3
uk#DESCR: Модель вузла труб за схемою: 1 -> 3.
ru#NAME: Труба 1->3
ru#DESCR: Модель узла труб по схеме: 1 -> 3.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(F1tmp,Pi,293,So1,Fo1,Po1,293,So1,lo1,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(F2tmp,Pi,293,So2,Fo2,Po2,293,So2,lo2,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(F3tmp,Pi,293,So3,Fo3,Po3,293,So3,lo3,Q0,Kpr,0.01,f_frq);
  Fi=F1tmp+F2tmp+F3tmp;


ID: pipe1_4
NAME: Pipe 1->4
DESCR: Model of the pipe by scheme: 1 -> 4.
uk#NAME: Труба 1->4
uk#DESCR: Модель вузла труб за схемою: 1 -> 4.
ru#NAME: Труба 1->4
ru#DESCR: Модель узла труб по схеме: 1 -> 4.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(F1tmp,Pi,293,So1,Fo1,Po1,293,So1,lo1,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(F2tmp,Pi,293,So2,Fo2,Po2,293,So2,lo2,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(F3tmp,Pi,293,So3,Fo3,Po3,293,So3,lo3,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(F4tmp,Pi,293,So4,Fo4,Po4,293,So4,lo4,Q0,Kpr,0.01,f_frq);
  Fi=F1tmp+F2tmp+F3tmp+F4tmp;


ID: klapMech
NAME: Valve proc. mechanism
uk#NAME: Виконавчий мех. клапану
uk#DESCR: Модель виконавчого механізму клапана. Включає час ходу та час відриву.
ru#NAME: Исполн. мех. клапана
ru#DESCR: Модель исполнительного механизма клапана. Включает время хода и время отрыва.
DESCR:
  Model of the valve process mechanism.
  Include going time (aperiodic links of two level) and estrangement time.

FORMULA:
  if( (pos >= 99 && com >= 99) || (pos <= 1 && com <=1 ) )
  { 
    tmp_up = t_up;
    if(pos>=99) { pos=100; st_open=true; }
    else { pos = 0; st_close=true; }
  }
  else if( tmp_up > 0 ) tmp_up-=1./f_frq;
  else
  {
    st_open=st_close=false;
    lst_com+=(com-lst_com)/(0.5*t_full*f_frq);
    pos+=(lst_com-pos)/(0.5*t_full*f_frq);
  }
  pos_sensor+=(pos-pos_sensor)/(t_sensor*f_frq);


ID: diafragma
NAME: Diaphragm
DESCR: Diaphragm model.
uk#NAME: Діафрагма
uk#DESCR: Модель діафрагми.
ru#NAME: Диафрагма
ru#DESCR: Модель диафрагмы.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi,Pi,293,Sdf,Fo,Po,293,So,lo,Q0,Kpr,0.01,f_frq);
  dP -= (dP-100*(Pi-Po))/f_frq;


ID: pipe3_1
NAME: Pipe 3->1
DESCR: Model of the pipe by scheme: 3 -> 1.
uk#NAME: Труба 3->1
uk#DESCR: Модель вузла труб за схемою: 3 -> 1.
ru#NAME: Труба 3->1
ru#DESCR: Модель узла труб по схеме: 3 -> 1.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi1,Pi1,293,Si1,EVAL_REAL,Po,293,So,lo,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi2,Pi2,293,Si2,EVAL_REAL,Po,293,So,lo,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi3,Pi3,293,Si3,EVAL_REAL,Po,293,So,lo,Q0,Kpr,0.01,f_frq);
  Po = max(0,min(100,Po+0.27*(Fi1+Fi2+Fi3-Fo)/(Q0*Kpr*So*lo*f_frq)));
  To = max(0,To+(Fi1*(Ti1-To)+Fi2*(Ti2-To)+Fi3*(Ti3-To)+(Fwind+1)*(Twind-To)/Riz)/(Ct*So*lo*Q0*f_frq));


ID: pipeBase
NAME: Pipe-base
uk#NAME: Труба-база
ru#NAME: Труба-база
DESCR:
  Implementation of the basic foundations of the model pipe:
  - Flow in the pipe, taking into account the speed, pressure drop, resistance due to friction and the critical flow.
  - Calculation of pressure.
  - Accounting for medium density and degree of compressibility for both gases and liquids.

FORMULA:
  Pmax = max(Pi,Po);
  Pmin = min(Pi,Po);
  Qr = Q0+Q0*Kpr*(Pmax-1);
  Fit = 630*(4*Si*So*Qr/(Ktr*lo*1.7724*Si+4*So*Qr))*sign(Pi-Po)*pow(Qr*(Pmax-max(Pmax*0.528,Pmin)),0.5);
  Fi -= (Fi-Fit)/max(1,(lo*f_frq)/max(1,abs(Fit/(Qr*So))));
  if( !Fo.isEVal() ) Po = max(0,min(100,Po+0.27*(Fi-Fo)/(Q0*Kpr*So*lo*f_frq)));

uk#DESCR:
  Реалізація базових основ моделі труби:
  - Витрати у трубі з урахуванням швидкості руху, різниці тиску, опору за рахунок тертя та критичної течі.
  - Розрахунок тиску. 
  - Урахування щільності середовища та ступеня його стиснення як для газів, так і для рідин.

ru#DESCR:
  Реализация базовых основ модели трубы:
  - Расход в трубе с учётом скорости движения, перепада давления, сопротивления за счёт трения и критического истечения.
  - Расчёт давления.
  - Учёт плотности среды и степени её сжимаемости как для газов, так и для жидкостей.


ID: heatExch
NAME: Heat exchanger
DESCR: The model of the heat exchanger, it calculates the heat exchange of the two streams.
uk#NAME: Теплообмінник
uk#DESCR: Модель теплообміннику, яка розраховує теплообмін двох потоків.
ru#NAME: Теплообменник
ru#DESCR: Модель теплообменника, рассчитывающая теплообмен двух потоков.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi1,Pi1,Ti1,Si1,Fo1,Po1,293,So1,lo1,Q0i1,Kpr1,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi2,Pi2,Ti2,Si2,Fo2,Po2,293,So2,lo2,Q0i2,Kpr2,0.01,f_frq);

  To1=max(0,min(1e4,(Fi1*Ti1*Ci1+ki*Fi2*Ti2*Ci2)/(Fi1*Ci1+ki*Fi2*Ci2)));
  To2=max(0,min(1e4,(ki*Fi1*Ti1*Ci1+Fi2*Ti2*Ci2)/(ki*Fi1*Ci1+Fi2*Ci2)));


ID: boilerBarrel
NAME: Boiler: barrel
DESCR: The model of the boiler's barrel.
uk#NAME: Котел: барабан
uk#DESCR: Модель барабану котлоагрегату.
ru#NAME: Котёл: барабан
ru#DESCR: Модель барабана котлоагрегата.
FORMULA:
  // Water
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi1,Pi1,293,Si1,EVAL_REAL,Po1,293,So1,lo1,1e3,0.001,0.01,f_frq);
  Fi1 = max(0,Fi1);

  // Steam
  Lo = max(0,min(100,Lo+(Fi1-Fpara)*100/(Vi1*1000*f_frq)));
  To1 = (100*pow(Po1,0.241)+5)+273;

  if( Tv<To1 )
  {
    Tv+=(k*S*(Ti2-Tv)-Fi1*0.00418*(Tv-Ti1))/f_frq;
    Fpara=0;
  }
  if( Tv >= To1 )
  {
    Tv=To1;
    Lambda=2750.0-0.00418*(Tv-273);
    Fpara=(5*S*Fi2*(Ti2-Tv)-Fi1*0.00418*(Tv-Ti1))/(Po1*Lambda);
  }

  To2=Ti2-Tv/k;
  Po1 = max(0,min(100,Po1+0.27*(Fpara-Fo)/(1.2*0.98*((1-Lo/100)*Vi1+So1*lo1)*f_frq)));

  // Smoke gas
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi2,Pi2,293,Si2,Fo2,Po2,293,Si2,30,1.2,0.98,0.01,f_frq);


ID: boilerBurner
NAME: Boiler: burner
uk#NAME: Котел: топка
ru#NAME: Котёл: топка
ru#DESCR: Модель топки котлоагрегата, работающего на трех видах топлива: доменном, коксовом и природном газе.
DESCR:
  The fire chamber's of the boiler model which works with three fuels: blast-furnace gas, coke and natural gas. 

FORMULA:
  using DAQ.JavaLikeCalc.lib_techApp;
  pipeBase(Fi1,Pi1,Ti1,Si1,EVAL_REAL,Po,293,So,lo,1.2,0.95,0.01,f_frq); Fi1 = max(0,Fi1);
  pipeBase(Fi2,Pi2,Ti2,Si2,EVAL_REAL,Po,293,So,lo,0.7,0.95,0.01,f_frq); Fi2 = max(0,Fi2);
  pipeBase(Fi3,Pi3,Ti3,Si3,EVAL_REAL,Po,293,So,lo,1.33,0.95,0.01,f_frq); Fi3 = max(0,Fi3);
  pipeBase(Fi4,Pi4,Ti4,Si4,EVAL_REAL,Po,293,So,lo,1.293,0.95,0.01,f_frq); Fi4 = max(0,Fi4);

  Neobhod_vzd = Fi1+10*Fi2+4*Fi3;
  F_DG = Fi1+Fi2+Fi3+Fi4;
  O2 = max(0,min(100,(Fi4-Neobhod_vzd)*100/F_DG));
  CO = min(100, (O2<1) ? (1.2*abs(O2)) : 0);
  koef = min(1,Fi4/Neobhod_vzd);
  Q = koef*(8050*Fi2+3900*Fi3+930*Fi1);
  delta_t = Q/(F_DG*1.047);
  To = max(0,min(2000,(delta_t+(Ti4-273)+(Ti3-273)*(Fi3/Fi1)+(Ti2-273)*(Fi2/Fi1)+(Ti1-273)*(Fi1/Fi4))+273));

  Po = max(0,min(10,Po+0.27*(F_DG-Fo)/(1.2*0.95*(So*lo+V)*f_frq)));

uk#DESCR:
  Модель топки котлоагрегату, який працює на трьох видах палива: доменному, коксовому та природному газах.


ID: pipe2_1
NAME: Pipe 2->1
DESCR: Model of the pipe by scheme: 2 -> 1.
uk#NAME: Труба 2->1
uk#DESCR: Модель вузла труб за схемою: 2 -> 1.
ru#NAME: Труба 2->1
ru#DESCR: Модель узла труб по схеме: 2 -> 1.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi1,Pi1,293,Si1,EVAL_REAL,Po,293,So,lo,Q0,Kpr,0.01,f_frq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi2,Pi2,293,Si2,EVAL_REAL,Po,293,So,lo,Q0,Kpr,0.01,f_frq);
  Po = max(0,min(100,Po+0.27*(Fi1+Fi2-Fo)/(Q0*Kpr*So*lo*f_frq)));
  To = max(0,To+(Fi1*(Ti1-To)+Fi2*(Ti2-To)+(Fwind+1)*(Twind-To)/Riz)/(Ct*So*lo*Q0*f_frq));


# tmplib_DevLib_io

TMPL_ID: 1602A
ID: transport
VALUE: i2c
NAME:
  Transport of the I2C, Serial (i2c) or
  GPIO address with function put(), mostly it's BCM2835 (DAQ.BCM2835.pi.pi)


# tmplib_S7

ID: ai_simple
NAME: Simple AI
DESCR: Simple analog parameter.
uk#NAME: Простий AI
uk#DESCR: Простий аналоговий параметр.
ru#NAME: Простой AI
ru#DESCR: Простой аналоговый параметр.
PROGRAM:
  JavaLikeCalc.JavaScript
  val=val_cod;
  if(val!=EVAL_REAL)
  {
    val=bDwn+(bUp-bDwn)*(val/27648.0);
    if(bUp!=bDwn && val>bUp)		f_err="101:Upper work border violation";
    else if(bUp!=bDwn && val<bDwn)	f_err="102:Lower work border violation";
    else if(bErrUp!=bErrDwn && val>bErrUp)	f_err="103:Upper alarm border violation";
    else if(bErrUp!=bErrDwn && val<bErrDwn)	f_err="104:Lower alarm border violation";
    else if(bWUp!=bWDwn && val>bWUp)	f_err="105:Upper warning border violation";
    else if(bWUp!=bWDwn && val<bWDwn)	f_err="106:Lower warning border violation";
    else f_err="0";
  }

uk#PROGRAM:
  JavaLikeCalc.JavaScript
  val=val_cod;
  if(val!=EVAL_REAL)
  {
    val=bDwn+(bUp-bDwn)*(val/27648.0);
    if(bUp!=bDwn && val>bUp)		f_err="101:Порушення верхньої робочої границі";
    else if(bUp!=bDwn && val<bDwn)	f_err="102:Порушення нижньої робочої границі";
    else if(bErrUp!=bErrDwn && val>bErrUp)	f_err="103:Порушення верхньої аварійної границі";
    else if(bErrUp!=bErrDwn && val<bErrDwn)	f_err="104:Порушення нижньої аварійної границі";
    else if(bWUp!=bWDwn && val>bWUp)	f_err="105:Порушення верхньої попереджувальної границі";
    else if(bWUp!=bWDwn && val<bWDwn)	f_err="106:Порушення нижньої попереджувальної границі";
    else f_err="0";
  }

ru#PROGRAM:
  JavaLikeCalc.JavaScript
  val=val_cod;
  if(val!=EVAL_REAL)
  {
    val=bDwn+(bUp-bDwn)*(val/27648.0);
    if(bUp!=bDwn && val>bUp)		f_err="101:Нарушение верхней рабочей границы";
    else if(bUp!=bDwn && val<bDwn)	f_err="102:Нарушение нижней рабочей границы";
    else if(bErrUp!=bErrDwn && val>bErrUp)	f_err="103:Нарушение верхней аварийной границы";
    else if(bErrUp!=bErrDwn && val<bErrDwn)	f_err="104:Нарушение нижней аварийной границы";
    else if(bWUp!=bWDwn && val>bWUp)	f_err="105:Нарушение верхней предупредительной границы";
    else if(bWUp!=bWDwn && val<bWDwn)	f_err="106:Нарушение нижней предупредительной границы";
    else f_err="0";
  }


ID: ai_man
NAME: Manual input of AI
DESCR: Manual input of a standard analog parameter.
uk#NAME: Ручний ввід AI
uk#DESCR: Стандартний аналоговий параметр ручного вводу.
ru#NAME: Ручной ввод AI
ru#DESCR: Стандартный аналоговый параметр ручного ввода.
PROGRAM:
  JavaLikeCalc.JavaScript
  //Check and write new value
  if(val!=val_o)
  {
    val_cod=(27648.0*(val-bDwn))/(bUp-bDwn);
    val_o=val;
  }
  else
  {
    val=val_cod;
  }

  if(val!=EVAL_REAL)
  {
    val=val_o=bDwn+(bUp-bDwn)*(val/27648.0);
    if(bUp!=bDwn && val>bUp)		f_err="101:Upper work border violation";
    else if(bUp!=bDwn && val<bDwn)	f_err="102:Lower work border violation";
    else if(bErrUp!=bErrDwn && val>bErrUp)	f_err="103:Upper alarm border violation";
    else if(bErrUp!=bErrDwn && val<bErrDwn)	f_err="104:Lower alarm border violation";
    else if(bWUp!=bWDwn && val>bWUp)	f_err="105:Upper warning border violation";
    else if(bWUp!=bWDwn && val<bWDwn)	f_err="106:Lower warning border violation";
    else f_err="0";
  }

uk#PROGRAM:
  JavaLikeCalc.JavaScript
  //Check and write new value
  if(val!=val_o)
  {
    val_cod=(27648.0*(val-bDwn))/(bUp-bDwn);
    val_o=val;
  }
  else
  {
    val=val_cod;
  }

  if(val!=EVAL_REAL)
  {
    val=val_o=bDwn+(bUp-bDwn)*(val/27648.0);
    if(bUp!=bDwn && val>bUp)		f_err="101:Порушення верхньої робочої границі";
    else if(bUp!=bDwn && val<bDwn)	f_err="102:Порушення нижньої робочої границі";
    else if(bErrUp!=bErrDwn && val>bErrUp)	f_err="103:Порушення верхньої аварійної границі";
    else if(bErrUp!=bErrDwn && val<bErrDwn)	f_err="104:Порушення нижньої аварійної границі";
    else if(bWUp!=bWDwn && val>bWUp)	f_err="105:Порушення верхньої попереджувальної границі";
    else if(bWUp!=bWDwn && val<bWDwn)	f_err="106:Порушення нижньої попереджувальної границі";
    else f_err="0";
  }

ru#PROGRAM:
  JavaLikeCalc.JavaScript
  //Check and write new value
  if(val!=val_o)
  {
    val_cod=(27648.0*(val-bDwn))/(bUp-bDwn);
    val_o=val;
  }
  else
  {
    val=val_cod;
  }

  if(val!=EVAL_REAL)
  {
    val=val_o=bDwn+(bUp-bDwn)*(val/27648.0);
    if(bUp!=bDwn && val>bUp)		f_err="101:Нарушение верхней рабочей границы";
    else if(bUp!=bDwn && val<bDwn)	f_err="102:Нарушение нижней рабочей границы";
    else if(bErrUp!=bErrDwn && val>bErrUp)	f_err="103:Нарушение верхней аварийной границы";
    else if(bErrUp!=bErrDwn && val<bErrDwn)f_err="104:Нарушение нижней аварийной границы";
    else if(bWUp!=bWDwn && val>bWUp)	f_err="105:Нарушение верхней предупредительной границы";
    else if(bWUp!=bWDwn && val<bWDwn)	f_err="106:Нарушение нижней предупредительной границы";
    else f_err="0";
  }


# flb_web

ID: alarms
NAME: Alarms
ru#NAME: Сигнализации
uk#NAME: Сигналізації
FORMULA:
  //> Load rules
  var alarmsTree = SYS.XMLNode("ALARMS");
  alarmsTree.load(rules);
  for(i_rl = 0; i_rl < alarmsTree.childSize(); i_rl++)
  {
  	if(!alarmsTree.childGet(i_rl).text().length) continue;
  	var subId = alarmsTree.childGet(i_rl).attr("id").parse(0,".");
  	var devId =  alarmsTree.childGet(i_rl).attr("id").parse(1,".");
  	var curAttrVal = SYS.DAQ.ModBus.ZegBee[subId][devId].get();
  	var curErr = "";
  	if(curAttrVal.isEVal()) curErr = "Value error. Perhaps the device is missing.";
  	else
  	{
  		var progArgs = new Object();
  		progArgs.err = "";
  		progArgs.x = curAttrVal;
  		SYS.DAQ.funcCall("JavaLikeCalc.JavaScript",progArgs,alarmsTree.childGet(i_rl).text());
  		if(progArgs.err.length) curErr = progArgs.err;
  	}
  	//> Create alarm
  	if(curErr.length && curErr != alarmsTree.childGet(i_rl).attr("err"))
  	{
  		SYS.message("ALARM:House:"+alarmsTree.childGet(i_rl).attr("id"),-4,curErr);
  		//>> Send SMS for new alarm messages to users
  		var smsReq = SYS.XMLNode("send").setAttr("ProtIt","SMS").setText(alarmsTree.childGet(i_rl).attr("id")+": "+curErr);
  		var userLst = SYS.XMLNode("get").setAttr("path","/sub_Security/grp_Web/%2fprm%2fusers");
  		SYS.cntrReq(userLst);
  		for(var i = 0; i < userLst.childSize(); i++)
  		{
  			var isSelAdmin = SYS.Security.access(userLst.childGet(i).text(),4,"root","WebRoot",0440);
  			var treeEl = SYS.XMLNode("get").setAttr("path","/sub_Security/usr_"+userLst.childGet(i).text()+"/%2fprm%2fldscr");
  			SYS.cntrReq(treeEl);
  			var re = treeEl.text().match("SMS:\\s+([^\\n]*)");
  			if(!re.length || re[1] != "true") continue;
  			if(!isSelAdmin)
  			{
  				re=treeEl.text().match("sub_"+subId+":\\s+([^\\n]*)");
  				if(!re.length || re[1] == "--") continue;
  			}
  			re = treeEl.text().match("TEL:\\s+([^\\n]*)");
  			if(!re.length) continue;
  			var telLs = re[1].split(new RegExp("\\s+"));
  			for(var i_t = 0; i_t < telLs.length; i_t++)
  			{
  				smsReq.setAttr("tel",telLs[i_t]);
  				SYS.Transport.Serial.out_GSM.messIO(smsReq,"UserProtocol");
  				if(smsReq.attr("err") != "0") SYS.messWarning("SMS send",smsReq.attr("err"));
  			}
  		}
  	}
  	//> Clear alarm
  	else if(!curErr.length && !alarmsTree.childGet(i_rl).attr("err").isEVal())
  		SYS.message("ALARM:House:"+alarmsTree.childGet(i_rl).attr("id"),1,"Norma");
  	alarmsTree.childGet(i_rl).setAttr("err",curErr);	
  }
  rules = alarmsTree.save();


ID: devMon
NAME: Devices monitor
ru#NAME: Монитор устройств
uk#NAME: Монітор пристроїв
FORMULA:
  var treeEl = false;

  //> Parse template
  var pgTree = SYS.XMLNode();
  var err = pgTree.load(tmpl,false,true);

  //> Access
  var isAdmin = SYS.Security.access(user,4,"root","WebRoot",0440);
  treeEl = SYS.XMLNode("get").setAttr("path","/sub_Security/usr_"+user+"/%2fprm%2fldscr");
  SYS.cntrReq(treeEl);
  re=treeEl.text().match("sub_"+pgTree.attr("class")+":\\s+([^\\n]*)");
  var subAccess = re.length ? re[1] : "--";

  //> Devices list place to template
  var cntrPrm = SYS.DAQ.ModBus.ZegBee[pgTree.attr("class")];
  catAttrReq = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/"+pgTree.attr("class")+"/%2fprm%2fcfg%2fATTR_LS");
  SYS.cntrReq(catAttrReq);
  catAttrLs = catAttrReq.text();

  //> Direct requests by XML process
  if(!urlPrms["com"].isEVal())
  {
  	var xmlRespTree = SYS.XMLNode(urlPrms["com"]);
  	if(urlPrms["com"] == "info")
  	{
  		//> Get timers
  		var timersList = SYS.XMLNode("get").setAttr("path","/sub_DAQ/mod_JavaLikeCalc/cntr_timers/prm_rules/%2fval%2fvar");
  		SYS.cntrReq(timersList);
  		var timersTree = SYS.XMLNode("TIMERS");
  		timersTree.load(timersList.text());

  		//> Devices process
  		for(var off = 0; (catAttrId=catAttrLs.parse(0,"\n",off)).length; )
  		{
  			if((catAttrId.parse(2,":") == "r" && (isAdmin || subAccess != "--")) || (catAttrId.parse(2,":") == "rw" && (isAdmin || subAccess == "rw")))
  			{
  				var xmlRespEl = xmlRespTree.childAdd(catAttrId.parse(5,":")).setAttr("name",catAttrId.parse(4,":")).setAttr("id",catAttrId.parse(3,":")).setAttr("acs",catAttrId.parse(2,":"));
  				if(catAttrId.parse(5,":") == "bin")
  					xmlRespEl.setAttr("vl1",catAttrId.parse(6,":")).setAttr("nm1",catAttrId.parse(7,":"))
  								  .setAttr("vl2",catAttrId.parse(8,":")).setAttr("nm2",catAttrId.parse(9,":")).setAttr("sensorPos",catAttrId.parse(10,":"));
  				else if(catAttrId.parse(5,":") == "dec") xmlRespEl.setAttr("ed",catAttrId.parse(6,":")).setAttr("sensorPos",catAttrId.parse(8,":"));;
  				//> Timer get
  				var timerNd = timersTree.getElementBy(pgTree.attr("class")+"."+catAttrId.parse(3,":"));
  				if(typeof(timerNd)=="XMLNode" && timerNd.attr("tm").toInt(10) > 0) xmlRespEl.setAttr("tm",timerNd.attr("tm"));
  			}
  		}
  	}
  	else if(urlPrms["com"] == "vals")
  		for(var off = 0; (catAttrId=catAttrLs.parse(0,"\n",off)).length; )
  		{
  			if((catAttrId.parse(2,":") == "r" && (isAdmin || subAccess != "--")) || (catAttrId.parse(2,":") == "rw" && (isAdmin || subAccess == "rw")))
  			{
  				var curAttrVal = cntrPrm[catAttrId.parse(3,":")].get();
  				var xmlRespEl = xmlRespTree.childAdd(catAttrId.parse(5,":")).setAttr("id",catAttrId.parse(3,":"));
  				//>>> Value error
  				if(curAttrVal.isEVal()) xmlRespEl.setAttr("val","<err>").setText("Ошибка");
  				else
  				{
  					xmlRespEl.setAttr("val",curAttrVal);
  					//>>> Prepare value for different type
  					if(catAttrId.parse(5,":") == "dec")
  					{
  						//>>>> Calc by formule add
  						var calcProg = catAttrId.parse(7,":").replace("%3A",":");
  						if(calcProg.length && catAttrId.parse(2,":") != "rw")
  						{
  							var progArgs = new Object();
  							progArgs.y = curAttrVal;
  							progArgs.x = curAttrVal;
  							SYS.DAQ.funcCall("JavaLikeCalc.JavaScript",progArgs,calcProg);
  							curAttrVal = progArgs.y;
  						}
  						xmlRespEl.setText(curAttrVal);
  					}
  					else if(catAttrId.parse(5,":") == "bin")
  					{
  						if(curAttrVal == catAttrId.parse(6,":").replace("%3A",":")) curAttrVal = catAttrId.parse(7,":").replace("%3A",":");
   						else if(curAttrVal == catAttrId.parse(8,":").replace("%3A",":")) curAttrVal = catAttrId.parse(9,":").replace("%3A",":");
  						else curAttrVal = "Неизвестно";
  						xmlRespEl.setText(curAttrVal);
  					}
  				}
  			}
  		}
  	else if(urlPrms["com"] == "set")
  		for(var off = 0; (catAttrId=catAttrLs.parse(0,"\n",off)).length; )
  		{
  			if(catAttrId.parse(2,":") != "rw" || catAttrId.parse(3,":") != urlPrms["dev"]) continue;
  			var setVal = EVAL_BOOL;
  			if(catAttrId.parse(5,":") == "bin")
  			{
  				if(urlPrms["val"] != cntrPrm[urlPrms["dev"]].get())	setVal = urlPrms["val"];
  			}
  			else if(catAttrId.parse(5,":") == "dec")
  			{
  				var calcProg = catAttrId.parse(7,":").replace("%3A",":");
  				if(!calcProg.length)
  				{
  					if(urlPrms["val"] != cntrPrm[urlPrms["dev"]].get()) setVal = urlPrms["val"];
  				}
  				else
  				{
  					var progArgs = new Object();
  					progArgs.y = urlPrms["val"];
  					progArgs.x = urlPrms["val"];
  					SYS.DAQ.funcCall("JavaLikeCalc.JavaScript",progArgs,calcProg);
  					setVal = progArgs.y;
  				}
  			}
  			if(!setVal.isEVal())
  			{				
  				if(urlPrms["tm"].toInt(10) <= 0)
  				{
  					cntrPrm[urlPrms["dev"]].set(setVal);
  					SYS.message("SET:House:"+pgTree.attr("class")+"."+urlPrms["dev"],2,user+": "+pgTree.attr("class")+"."+urlPrms["dev"]+": установлен в: "+setVal);
  				}
  				else
  				{
  					var timersList = SYS.XMLNode("get").setAttr("path","/sub_DAQ/mod_JavaLikeCalc/cntr_timers/prm_rules/%2fval%2fvar");
  					SYS.cntrReq(timersList);
  					var timersTree = SYS.XMLNode("TIMERS");
  					timersTree.load(timersList.text());

  					var timerNd = timersTree.getElementBy(pgTree.attr("class")+"."+urlPrms["dev"]);
  					if(typeof(timerNd) != "XMLNode") timerNd = timersTree.childAdd("timer").setAttr("id",pgTree.attr("class")+"."+urlPrms["dev"]);
  					timerNd.setAttr("tm",urlPrms["tm"]).setAttr("user",user).setText(setVal);
  					timersList = SYS.XMLNode("set").setAttr("path","/sub_DAQ/mod_JavaLikeCalc/cntr_timers/prm_rules/%2fval%2fvar").setText(timersTree.save());
  					SYS.cntrReq(timersList);
  					SYS.message("SET:House:"+pgTree.attr("class")+"."+urlPrms["dev"],2,user+": "+pgTree.attr("class")+"."+urlPrms["dev"]+": установка в: "+setVal+", по таймеру: "+urlPrms["tm"]+"секунд.");
  				}
  			}
  			break;
  		}
  	else if(urlPrms["com"] == "timerClear")
  		for(var off = 0; (catAttrId=catAttrLs.parse(0,"\n",off)).length; )
  		{
  			if(catAttrId.parse(2,":") != "rw" || catAttrId.parse(3,":") != urlPrms["dev"]) continue;
  			var timersList = SYS.XMLNode("get").setAttr("path","/sub_DAQ/mod_JavaLikeCalc/cntr_timers/prm_rules/%2fval%2fvar");
  			SYS.cntrReq(timersList);
  			var timersTree = SYS.XMLNode("TIMERS");
  			timersTree.load(timersList.text());

  			var timerNd = timersTree.getElementBy(pgTree.attr("class")+"."+urlPrms["dev"]);
  			if(typeof(timerNd) == "XMLNode")
  			{
  				timerNd.setAttr("tm",0);
  				timersList = SYS.XMLNode("set").setAttr("path","/sub_DAQ/mod_JavaLikeCalc/cntr_timers/prm_rules/%2fval%2fvar").setText(timersTree.save());
  				SYS.cntrReq(timersList);
  			}
  			break;
  		}

  	return "200 OK\nContent-Type:text/xml\n\n"+xmlRespTree.save();
  }

  //Save template
  rez = pgTree.save();
  //SYS.messDebug("TEST Dev","TEST 00: "+typeof(devLs[formEl["cat"]+"."+itId]));


ID: devices
NAME: Devices dispatcher
ru#NAME: Диспетчер устройств
uk#NAME: Диспетчер пристроїв
FORMULA:
  var treeEl = false;

  //> Parse template
  var pgTree = SYS.XMLNode();
  var err = pgTree.load(tmpl,false,true);

  //> Get categories list
  var catLs = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/%2fprm%2fprm");
  SYS.cntrReq(catLs);

  //> Get devices list
  var devLs = new Object();
  for(var i = 0; i < catLs.childSize(); i++)
  {
  	var curCat = catLs.childGet(i).attr("id");
  	catAttrReq = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/"+curCat+"/%2fprm%2fcfg%2fATTR_LS");
  	SYS.cntrReq(catAttrReq);
  	catAttrLs = catAttrReq.text();
  	for(var off = 0; (catAttrId=catAttrLs.parse(0,"\n",off)).length; )
  		devLs[curCat+"."+catAttrId.parse(3,":")] = true;
  }

  //> Process page
  //>> Place categories list
  if(typeof(treeEl=pgTree.getElementBy("cat","name")) == "XMLNode")
  	for(var i = 0; i < catLs.childSize(); i++)
  		treeEl.childAdd("OPTION").setAttr("value",catLs.childGet(i).attr("id")).setText(catLs.childGet(i).text());

  //> Check POST content for commands
  if(cnts.length)
  {
  	var formEl = new Object();
  	re = new RegExp("name=\"(.+)\"");
  	//>> POST form elements process
  	for(var i = 0; i < cnts.length; i++)
  		formEl[re.exec(cnts[i].attr("Content-Disposition"))[1]] = cnts[i].text();
  	//>> Check for apply
  	if(!formEl["apply"].isEVal())
  	{
  		var applyOK = true;
  		//>> ID: Check for correct form's values
  		var itId = formEl["id"].match("[^\\s].+[^\\s]");
  		if(!itId.length)
  		{
  			treeEl = pgTree.getElementBy("idNm","name");
  			treeEl.childAdd("br");
  			treeEl.childAdd("span").setAttr("style","color : red;").setText("(Пустое значение недопустимо)");
  			itId = "";
  			applyOK = false;
  		}
  		else itId = itId[0];
  		pgTree.getElementBy("id","name").setAttr("value",itId);

  		//>> Name: Check for correct form's values
  		var itName = formEl["name"].match("[^\\s].+[^\\s]");
  		if(!itName.length)
  		{
  			treeEl = pgTree.getElementBy("nameNm","name");
  			treeEl.childAdd("br");
  			treeEl.childAdd("span").setAttr("style","color : red;").setText("(Пустое значение недопустимо)");
  			itName = "";
  			applyOK = false;
  		}
  		else itName = itName[0];
  		pgTree.getElementBy("name","name").setAttr("value",itName);

  		//>> Address: Check for correct form's values
  		var itAddr = formEl["addr"].toInt();
  		if(itAddr < 0 || itAddr > 65535)
  		{
  			treeEl = pgTree.getElementBy("addrNm","name");
  			treeEl.childAdd("br");
  			treeEl.childAdd("span").setAttr("style","color : red;").setText("(Адрес ModBus должен быть в диапазоне (1-65535))");
  			applyOK = false;
  		}
  		pgTree.getElementBy("addr","name").setAttr("value",itAddr);

  		//>> Type: Check for correct form's values
  		pgTree.getElementBy(formEl["type"],"value").setAttr("selected","selected");

  		//>> sensorPos: Check for correct form's values
  		pgTree.getElementBy("sensorPos","name").setAttr("value",formEl["sensorPos"]);

  		//>> Category: Check for correct form's values
  		pgTree.getElementBy(formEl["cat"],"value").setAttr("selected","selected");

  		//>> Data type: 
  		pgTree.getElementBy(formEl["typeData"],"value").setAttr("selected","selected");
  		pgTree.getElementBy("in1").setAttr("style","display: "+((formEl["typeData"] == "bin")?"":"none"));
  		pgTree.getElementBy("in2").setAttr("style","display: "+((formEl["typeData"] == "bin")?"":"none"));
  		pgTree.getElementBy("ed").setAttr("style","display: "+((formEl["typeData"] == "dec")?"":"none"));
  		pgTree.getElementBy("formul").setAttr("style","display: "+((formEl["typeData"] == "dec")?"":"none"));

  		//>> Binary type properties
  		pgTree.getElementBy("in1","name").setAttr("value",formEl["in1"]);
  		pgTree.getElementBy("view1","name").setAttr("value",formEl["view1"]);
  		pgTree.getElementBy("in2","name").setAttr("value",formEl["in2"]);
  		pgTree.getElementBy("view2","name").setAttr("value",formEl["view2"]);

  		//>> Digital type properties
  		pgTree.getElementBy("ed","name").setAttr("value",formEl["ed"]);
  		pgTree.getElementBy("formul","name").setAttr("value",formEl["formul"]);	

  		//>> Alarm
  		pgTree.getElementBy("alarm","name").childGet(0).setText(formEl["alarm"]);

  		//> Add or update device
  		if(applyOK)
  		{
  			//>> Get curent attributes list for category
  			catAttrReq = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/"+formEl["cat"]+"/%2fprm%2fcfg%2fATTR_LS");
  			SYS.cntrReq(catAttrReq);
  			catAttrLs = catAttrReq.text();
  			var newAttrReq = "R:"+itAddr+":"+(formEl["type"]=="out"?"rw":"r")+":"+itId+":"+itName.replace(":","%3A")+":"+formEl["typeData"];
  			if(formEl["typeData"] == "bin") newAttrReq += ":"+formEl["in1"].replace(":","%3A")+":"+formEl["view1"].replace(":","%3A")+":"+formEl["in2"].replace(":","%3A")+":"+formEl["view2"].replace(":","%3A");
  			else if(formEl["typeData"] == "dec") newAttrReq += ":"+formEl["ed"].replace(":","%3A")+":"+formEl["formul"].replace(":","%3A");
  			newAttrReq += ":"+formEl["sensorPos"]+"\n";
  			//>> Append record
  			var isAppend = typeof(devLs[formEl["cat"]+"."+itId]) == "null";
  			if(isAppend)
  			{
  				catAttrLs += newAttrReq;
  				devLs[formEl["cat"]+"."+itId] = true;
  			}
  			//>> Replace
  			else catAttrLs = catAttrLs.replace(new RegExp("R:[^:]*:[^:]*:"+itId+":[^\n]*\n"),newAttrReq);
  			//>> Write new attributes list
  			catAttrReq = SYS.XMLNode("CntrReqs").setAttr("path","/DAQ/ModBus/ZegBee/"+formEl["cat"]);
  			catAttrReq.childAdd("set").setAttr("path","/%2fprm%2fcfg%2fATTR_LS").setText(catAttrLs);
  			catAttrReq.childAdd("set").setAttr("path","/%2fprm%2fst%2fen").setText(0);
  			catAttrReq.childAdd("set").setAttr("path","/%2fprm%2fst%2fen").setText(1);
  			catAttrReq.childAdd("save").setAttr("path","/%2fobj");
  			//XMLNode("set").setAttr("path","/DAQ/ModBus/ZegBee/"+formEl["cat"]+"/%2fprm%2fcfg%2fATTR_LS").setText(catAttrLs);
  			SYS.cntrReq(catAttrReq);
  			//>> Set message about correct apply
  			treeEl=pgTree.getElementBy("mess","name");
  			treeEl.childAdd("span").setAttr("style","color : green;").setText(
  				isAppend?"Новое устройство успешно добавлено. Можно продолжать.":"Устройство успешно обновлено. Можно продолжать.");
  			//>> Set alarm procedure
  			var alarmsList = SYS.XMLNode("get").setAttr("path","/sub_DAQ/mod_JavaLikeCalc/cntr_alarms/prm_rules/%2fval%2fvar");
  			SYS.cntrReq(alarmsList);
  			var alarmsTree = SYS.XMLNode("ALARMS");
  			alarmsTree.load(alarmsList.text());
  			var alarmNd = alarmsTree.getElementBy(formEl["cat"]+"."+formEl["id"]);
  			if(typeof(alarmNd)=="XMLNode") alarmNd.setText(formEl["alarm"]);
  			else alarmsTree.childAdd("it").setAttr("id",formEl["cat"]+"."+formEl["id"]).setText(formEl["alarm"]);
  			alarmsList = SYS.XMLNode("CntrReqs").setAttr("path","/sub_DAQ/mod_JavaLikeCalc/cntr_alarms/prm_rules");
  			alarmsList.childAdd("set").setAttr("path","/%2fval%2fvar").setText(alarmsTree.save());
  			alarmsList.childAdd("save").setAttr("path","/%2fobj");
  			SYS.cntrReq(alarmsList);
  		}
  		//> Form error
  		else
  		{
  			treeEl=pgTree.getElementBy("mess","name");
  			treeEl.childAdd("span").setAttr("style","color : red;").setText("Ошибка в формировании формы! Исправьте отмеченные поля и повторите.");
  		}
  	}
  	else if(!formEl["edDel"].isEVal())
  	{
  		if(formEl["edId"].length && typeof(devLs[formEl["edId"]]) != "null")
  		{
  			//>> Get curent attributes list for category
  			catAttrReq = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/"+(formEl["edId"].parse(0))+"/%2fprm%2fcfg%2fATTR_LS");
  			SYS.cntrReq(catAttrReq);
  			catAttrLs = catAttrReq.text();
  			catAttrLs = catAttrLs.replace(new RegExp("R:[^:]*:[^:]*:"+formEl["edId"].parse(1)+":[^\n]*\n"),"");
  			//>> Write new attributes list
  			catAttrReq = SYS.XMLNode("set").setAttr("path","/DAQ/ModBus/ZegBee/"+(formEl["edId"].parse(0))+"/%2fprm%2fcfg%2fATTR_LS").setText(catAttrLs);
  			SYS.cntrReq(catAttrReq);
  			//>> Set message about correct apply
  			treeEl=pgTree.getElementBy("mess","name");
  			treeEl.childAdd("span").setAttr("style","color : green;").setText("Устройство успешно удалено. Можно продолжать.");
  			devLs[formEl["edId"]] = false;
  		}
  		else
  		{
  			treeEl=pgTree.getElementBy("mess","name");
  			treeEl.childAdd("span").setAttr("style","color : red;").setText("Устройство для удаления отсутствует.");
  		}
  	}
  }

  //>> Devices list place to template
  treeEl=pgTree.getElementBy("edId","name");
  treeEl.childAdd("OPTION");
  for(var i_o in devLs)
  	if(devLs[i_o]) treeEl.childAdd("OPTION").setAttr("value",i_o).setText(i_o);

  //>> Load variables for select device
  if(!cnts.length && !urlPrms["selDev"].isEVal() && urlPrms["selDev"].length) 
  {
  	//> Select device
  	pgTree.getElementBy(urlPrms["selDev"],"value").setAttr("selected","selected");
  	//> Load values for select device
  	catAttrReq = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/"+(urlPrms["selDev"].parse(0))+"/%2fprm%2fcfg%2fATTR_LS");
  	SYS.cntrReq(catAttrReq);
  	catAttrLs = catAttrReq.text().match("R:([^:]*):([^:]*):"+urlPrms["selDev"].parse(1)+":([^\n]*)");
  	//>> ID: Check for correct form's values
  	pgTree.getElementBy("id","name").setAttr("value",urlPrms["selDev"].parse(1));
  	//>> Name: Check for correct form's values
  	pgTree.getElementBy("name","name").setAttr("value",catAttrLs[3].parse(0,":").replace("%3A",":"));
  	//>> Address: Check for correct form's values
  	pgTree.getElementBy("addr","name").setAttr("value",catAttrLs[1]);
  	//>> Type: Check for correct form's values
  	pgTree.getElementBy(((catAttrLs[2]=="rw")?"out":"sensor"),"value").setAttr("selected","selected");
  	//>> Category: Check for correct form's values
  	pgTree.getElementBy(urlPrms["selDev"].parse(0),"value").setAttr("selected","selected");
  	//>> Data type: 
  	var dtType = catAttrLs[3].parse(1,":");
  	pgTree.getElementBy(dtType,"value").setAttr("selected","selected");
  	if(dtType == "bin")
  	{
  		pgTree.getElementBy("in1","name").setAttr("value",catAttrLs[3].parse(2,":").replace("%3A",":"));
  		pgTree.getElementBy("view1","name").setAttr("value",catAttrLs[3].parse(3,":").replace("%3A",":"));
  		pgTree.getElementBy("in2","name").setAttr("value",catAttrLs[3].parse(4,":").replace("%3A",":"));
  		pgTree.getElementBy("view2","name").setAttr("value",catAttrLs[3].parse(5,":").replace("%3A",":"));
  		pgTree.getElementBy("sensorPos","name").setAttr("value",catAttrLs[3].parse(6,":"));
  	}
  	else if(dtType == "dec")
  	{
  		pgTree.getElementBy("ed","name").setAttr("value",catAttrLs[3].parse(2,":").replace("%3A",":"));
  		pgTree.getElementBy("formul","name").setAttr("value",catAttrLs[3].parse(3,":").replace("%3A",":"));
  		pgTree.getElementBy("sensorPos","name").setAttr("value",catAttrLs[3].parse(4,":"));
  	}
  	pgTree.getElementBy("in1").setAttr("style","display: "+((dtType == "bin")?"":"none"));
  	pgTree.getElementBy("in2").setAttr("style","display: "+((dtType == "bin")?"":"none"));
  	pgTree.getElementBy("ed").setAttr("style","display: "+((dtType == "dec")?"":"none"));
  	pgTree.getElementBy("formul").setAttr("style","display: "+((dtType == "dec")?"":"none"));

  	//>> Get alarm procedure
  	alarmsList = SYS.XMLNode("get").setAttr("path","/sub_DAQ/mod_JavaLikeCalc/cntr_alarms/prm_rules/%2fval%2fvar");
  	SYS.cntrReq(alarmsList);
  	var alarmsTree = SYS.XMLNode();
  	alarmsTree.load(alarmsList.text());
  	var alarmNd = alarmsTree.getElementBy(urlPrms["selDev"]);
  	pgTree.getElementBy("alarm","name").childGet(0).setText((typeof(alarmNd)=="XMLNode")?alarmNd.text():"");
  }
  else pgTree.getElementBy("edDel","name").setAttr("style","visibility : hidden;");

  //Save template
  rez = pgTree.save();
  //SYS.messDebug("TEST Dev","TEST 00: "+typeof(devLs[formEl["cat"]+"."+itId]));


ID: mess
NAME: Alarm messages
ru#NAME: Сообщения сигнализаций
uk#NAME: Повідомлення сигналізацій
FORMULA:
  var treeEl = false;

  //> Parse template
  var pgTree = SYS.XMLNode();
  var err = pgTree.load(tmpl,false,true);
  treeEl = pgTree.getElementBy("mess");

  var curTime = SYS.time();
  var messAr = SYS.Archive.messGet(curTime,curTime,"ALARM:House:*",-1);
  var trEl = treeEl.childAdd("tr");
  trEl.childAdd("th").setText("Время");
  trEl.childAdd("th").setText("Категория");
  trEl.childAdd("th").setText("Уровень");
  trEl.childAdd("th").setText("Сообщение");
  for(i = 0; i < messAr.length; i++)
  {
  	var trEl = treeEl.childAdd("tr");
  	trEl.childAdd("td").setAttr("class","mTm").setText(SYS.strftime(messAr[i].tm));
  	trEl.childAdd("td").setAttr("class","mCat").setText(messAr[i].categ);
  	trEl.childAdd("td").setAttr("class","mLev").setText(messAr[i].level);
  	trEl.childAdd("td").setAttr("class","mMess").setText(messAr[i].mess);
  }

  //Save template
  rez = pgTree.save();
  //SYS.messDebug("TEST Dev","TEST 00: "+typeof(devLs[formEl["cat"]+"."+itId]));


ID: report
NAME: Reports
ru#NAME: Отчёты
uk#NAME: Звіти
FORMULA:
  var treeEl = false;
  var pgDir = "./HouseSpirit/Web/";

  //> Parse template
  var pgTree = SYS.XMLNode();
  var err = pgTree.load(tmpl,false,true);

  //> Load default values
  pgTree.getElementBy("btm","name").setAttr("value",SYS.strftime(SYS.time()));
  pgTree.getElementBy("etm","name").setAttr("value",SYS.strftime(SYS.time()));
  var catLs = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/%2fprm%2fprm");
  SYS.cntrReq(catLs);
  treeEl = pgTree.getElementBy("subsys");
  for(var i = 0; i < catLs.childSize(); i++)
  {
  	treeEl.childAdd("span").setText(catLs.childGet(i).text());
  	treeEl.childAdd("input").setAttr("type","checkbox").setAttr("name",catLs.childGet(i).attr("id"));
  	treeEl.childAdd("br");
  }

  //> Check POST content for commands - forming report
  if(cnts.length)
  {
  	var formEl = new Object();
  	var re = new RegExp("name=\"(.+)\"");
  	//>> POST form elements process
  	for(i_c = 0; i_c < cnts.length; i_c++)
  		formEl[re.exec(cnts[i_c].attr("Content-Disposition"))[1]] = cnts[i_c].text();

  	//>> Check for apply
  	if(!formEl["show"].isEVal())
  	{
  		var reqRule = "";
  		var applyOK = true;
  		//>> Time: begin and end time check
  		var btm = SYS.strptime(formEl["btm"]);
  		pgTree.getElementBy("btm","name").setAttr("value",SYS.strftime(btm));
  		var etm = SYS.strptime(formEl["etm"]);
  		pgTree.getElementBy("etm","name").setAttr("value",SYS.strftime(etm));

  		//>> System
  		if(formEl["sys"].length)
  		{
  			pgTree.getElementBy("sys","name").setAttr("checked","checked");
  			reqRule = "\\/sub_Protocol\\/mod_HTTP\\/";
  		}

  		//>> Subsystems
  		var catLs = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/%2fprm%2fprm");
  		SYS.cntrReq(catLs);
  		for(var i = 0; i < catLs.childSize(); i++)
  		{
  			var subId = catLs.childGet(i).attr("id");
  			if(formEl[subId].length)
  			{
  				pgTree.getElementBy(subId,"name").setAttr("checked","checked");
  				if(reqRule.length) reqRule += "|";
  				reqRule += "(ALARM|SET)\\:House\\:"+subId;
  			}
  		}

  		//>> Report generate
  		if(btm < etm && (etm-btm) < (365*24*60*60) && reqRule.length)
  		{
  			var messAr = SYS.Archive.messGet(btm,etm,"/("+reqRule+")/",1);
  			treeEl = pgTree.getElementBy("report");
  			var trEl = treeEl.childAdd("tr");
  			trEl.childAdd("th").setText("Время");
  			trEl.childAdd("th").setText("Категория");
  			trEl.childAdd("th").setText("Уровень");
  			trEl.childAdd("th").setText("Сообщение");
  			for(i = 0; i < messAr.length; i++)
  			{
  				var trEl = treeEl.childAdd("tr");
  				trEl.childAdd("td").setAttr("class","mTm").setText(SYS.strftime(messAr[i].tm));
  				trEl.childAdd("td").setAttr("class","mCat").setText(messAr[i].categ);
  				trEl.childAdd("td").setAttr("class","mLev").setText(messAr[i].level);
  				trEl.childAdd("td").setAttr("class","mMess").setText(messAr[i].mess);
  			}
  			//>> Save report to file
  			var saveFile = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
  					"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"+
  					"<html xmlns='http://www.w3.org/1999/xhtml'>\n"+
  					"<head>\n"+
  					"  <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>\n"+
  					"  <title>Отчёт</title>\n"+
  					"  <style type='text/css'>\n"+
  					"    #report { width: 100%; border: 1px solid black; border-collapse: collapse; empty-cells: show; }\n"+
  					"    #report TH { border: 1px solid black; background-color: #E6E6E6; }\n"+
  					"    #report TD { border: 1px solid black; }\n"+
  					"    #report .mTm { white-space: nowrap; }\n"+
  					"    #report .mLev { text-align: center; }\n"+
  					"  </style>\n"+
  					"</head>\n"+
  					"<body>\n"+treeEl.save()+"\n</body>\n"+
  					"</html>";
  			SYS.fileWrite(pgDir+"reports/rep_"+user+".html",saveFile);
  			pgTree.getElementBy("saveFile").setAttr("href","reports/rep_"+user+".html").setText("rep_"+user+".html");
  		}
  	}
  }

  //Save template
  rez = pgTree.save();
  //SYS.messDebug("TEST Dev","TEST 00: "+typeof(devLs[formEl["cat"]+"."+itId]));


ID: test
NAME: Test
ru#NAME: Тест
uk#NAME: Тест
FORMULA:
  if(f_start)
  {
  	var req = SYS.XMLNode("send").setAttr("ProtIt","SMS").setAttr("tel","+380679859815").setText("Тестовое сообщение");
  	SYS.Transport.Serial.out_GSM.messIO(req,"UserProtocol");
  }


ID: timerWrite
NAME: Write by the timer
ru#NAME: Запись по таймеру
uk#NAME: Запис за таймером
FORMULA:
  //> Load rules
  var timersTree = SYS.XMLNode("TIMERS");
  timersTree.load(rules);
  for(i_rl = 0; i_rl < timersTree.childSize(); i_rl++)
  {
  	var curTm = timersTree.childGet(i_rl);
  	if(!curTm.text().length) continue;
  	var subId = curTm.attr("id").parse(0);
  	var devId = curTm.attr("id").parse(1);
  	var timer = curTm.attr("tm").toInt(10);
  	if(timer && max(0,timer-1) == 0)
  	{
  		SYS.DAQ.ModBus.ZegBee[subId][devId].set(curTm.text());
  		SYS.message("SET:House:"+curTm.attr("id"),2,curTm.attr("user")+": "+curTm.attr("id")+": установлен в: "+curTm.text());
  	}
  	curTm.setAttr("tm",max(0,timer-1));
  }
  rules = timersTree.save();


ID: user
NAME: Users dispatcher
ru#NAME: Диспетчер пользователей
uk#NAME: Диспетчер користувачів
FORMULA:
  var treeEl = false;

  //> Parse template
  var pgTree = SYS.XMLNode();
  var err = pgTree.load(tmpl,false,true);
  var isAdmin = SYS.Security.access(user,4,"root","WebRoot",0440);
  var curUser = user;

  //> Check POST content for commands
  if(cnts.length)
  {
  	var formEl = new Object();
  	re = new RegExp("name=\"(.+)\"");
  	//>> POST form elements process
  	for(var i = 0; i < cnts.length; i++)
  		formEl[re.exec(cnts[i].attr("Content-Disposition"))[1]] = cnts[i].text();
  	//>> Check for apply
  	if(!formEl["apply"].isEVal())
  	{
  		var applyOK = true;
  		//>> Login: Check for correct form's values
  		if(!(userLogin=formEl["login"].match("[^\\s].+[^\\s]")).length)
  		{
  			treeEl = pgTree.getElementBy("loginNm","name");
  			treeEl.childAdd("br");
  			treeEl.childAdd("span").setAttr("style","color : red;").setText("(Пустое значение недопустимо)");
  			userLogin = "";
  			applyOK = false;
  		}
  		else userLogin = userLogin[0];
  		if(userLogin.isEVal()) userLogin = user;
  		pgTree.getElementBy("login","name").setAttr("value",userLogin);
  		var isUserPres = (typeof(SYS.Security.nodeAt("usr_"+userLogin)) == "TCntrNode");
  		var isWebUser = isUserPres && SYS.Security.access(userLogin,4,"root","Web",0440);
  		var isWebRootUser = isUserPres && SYS.Security.access(userLogin,4,"root","WebRoot",0440);
  		if(isUserPres && !(isWebUser||isWebRootUser)) applyOK = false;
  		if(!isAdmin && userLogin != user) applyOK = false;

  		//>> Name: Check for correct form's values
  		var userName = formEl["fio"].match("[^\\s].+[^\\s]");
  		if(!userName.length)
  		{
  			treeEl = pgTree.getElementBy("fioNm","name");
  			treeEl.childAdd("br");
  			treeEl.childAdd("span").setAttr("style","color : red;").setText("(Пустое значение недопустимо)");
  			userName = "";
  			applyOK = false;
  		}
  		else userName = userName[0];
  		pgTree.getElementBy("fio","name").setAttr("value",userName);

  		//>> Password: Check for correct form's values
  		if((!isUserPres && formEl["pass"].length < 8) || (isUserPres && formEl["pass"].length && formEl["pass"].length < 8))
  		{
  			treeEl = pgTree.getElementBy("passNm","name");
  			treeEl.childAdd("br");
  			treeEl.childAdd("span").setAttr("style","color : red;").setText("(Пароль должен быть более 8 символов)");
  			userName = "";
  			applyOK = false;
  		}

  		if(isAdmin)
  		{
  			//>> Telepfons list, SMS send and report view
  			pgTree.getElementBy("tel","name").setAttr("value",formEl["tel"]);
  			if(formEl["sms"].length) pgTree.getElementBy("sms","name").setAttr("checked","checked");
  			if(formEl["report"].length) pgTree.getElementBy("report","name").setAttr("checked","checked");

  			if(!isWebRootUser)
  			{
  				//>> Subsystem's permition
  				var catLs = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/%2fprm%2fprm");
  				SYS.cntrReq(catLs);
  				treeEl = pgTree.getElementBy("sub_access");
  				for(var i = 0; i < catLs.childSize(); i++)
  				{
  					var subId = "sub_"+catLs.childGet(i).attr("id");
  					treeEl.childAdd("span").setText(catLs.childGet(i).text());
  					treeEl.childAdd("br");
  					treeEl1 = treeEl.childAdd("select").setAttr("name",subId);
  					treeEl.childAdd("br");
  					treeEl2 = treeEl1.childAdd("option").setAttr("value","--").setText("Нет доступа");
  					if(formEl[subId] == "--") treeEl2.setAttr("selected","selected");
  					treeEl2 = treeEl1.childAdd("option").setAttr("value","r-").setText("Наблюдение");
  					if(formEl[subId] == "r-") treeEl2.setAttr("selected","selected");
  					treeEl2 = treeEl1.childAdd("option").setAttr("value","rw").setText("Управление");
  					if(formEl[subId] == "rw") treeEl2.setAttr("selected","selected");
  				}
  			}
  			else
  			{
  				//> Session life time
  				treeEl = pgTree.getElementBy("sub_access");
  				treeEl.childAdd("span").setText("Время жизни сеанса аутентификации (минут)");
  				treeEl.childAdd("br");
  				treeEl.childAdd("input").setAttr("type","text").setAttr("name","sesAuth").setAttr("value",formEl["sesAuth"]);
  			}
  		}

  		//> Add or update user
  		if(applyOK)
  		{
  			//> Create new user if no present
  			if(!isUserPres)
  			{
  				userReq = SYS.XMLNode("CntrReqs").setAttr("path","/sub_Security");
  				userReq.childAdd("add").setAttr("path","%2fusgr%2fusers").setText(userLogin);
  				userReq.childAdd("add").setAttr("path","/grp_Web/%2fprm%2fusers").setText(userLogin);
  				SYS.cntrReq(userReq); 
  			}
  			//> Set user's properties
  			userReq = SYS.XMLNode("CntrReqs").setAttr("path","/sub_Security/usr_"+userLogin);
  			userReq.childAdd("set").setAttr("path","%2fprm%2fdscr").setText(userName);
  			if(formEl["pass"].length)
  				userReq.childAdd("set").setAttr("path","%2fprm%2fpass").setText(formEl["pass"]);
  			if(isAdmin)
  			{
  				var descrVal = "TEL: "+formEl["tel"]+"\n"+
  							"SMS: "+(formEl["sms"].length?"true":"false")+"\n"+
  							"Report: "+(formEl["report"].length?"true":"false")+"\n";
  				if(!isWebRootUser)
  				{
  					//>> Subsystem's permition
  					for(var i = 0; i < catLs.childSize(); i++)
  					{
  						var subId = "sub_"+catLs.childGet(i).attr("id");
  						descrVal += subId+": "+formEl[subId]+"\n";
  					}
  				}
  				else
  				{
  					var sessLife = SYS.XMLNode("CntrReqs").setAttr("path","/sub_Protocol/mod_HTTP");
  					sessLife.childAdd("set").setAttr("path","/%2fprm%2flf_tm").setText(max(1,formEl["sesAuth"].toInt()));
  					sessLife.childAdd("save").setAttr("path","/%2fobj");
  					SYS.cntrReq(sessLife);

  				}
  				userReq.childAdd("set").setAttr("path","%2fprm%2fldscr").setText(descrVal);
  			}
  			userReq.childAdd("save").setAttr("path","/%2fobj");
  			SYS.cntrReq(userReq); 
  			//>> Set message about correct apply
  			treeEl=pgTree.getElementBy("mess","name");
  			treeEl.childAdd("span").setAttr("style","color : green;").setText(
  				(!isUserPres)?"Новый пользователь успешно добавлен. Можно продолжать.":"Пользователь успешно обновлен. Можно продолжать.");
  		}
  		//> Form error
  		else
  		{
  			treeEl=pgTree.getElementBy("mess","name").childAdd("span").setAttr("style","color : red;");
  			if(!isAdmin && userLogin != user) treeEl.setText("Обычный пользователь может редактировать только собственную учётную запись.");
  			else if(isUserPres && !isWebUser) treeEl.setText("Пользователь присутствует, но не является Web-пользователем. Измените логин пользователя и повторите.");
  			else treeEl.setText("Ошибка в формировании формы! Исправьте отмеченные поля и повторите.");
  		}
  	}
  	else if(!formEl["edDel"].isEVal())
  	{
  		var isWebUser = SYS.Security.access(formEl["edLogin"],4,"root","Web",0440);
  		var isWebRootUser = SYS.Security.access(formEl["edLogin"],4,"root","WebRoot",0440);
  		if(isWebUser && !isWebRootUser)
  		{
  			userReq = SYS.XMLNode("CntrReqs").setAttr("path","/sub_Security");
  			userReq.childAdd("del").setAttr("path","%2fusgr%2fusers").setText(formEl["edLogin"]);
  			userReq.childAdd("del").setAttr("path","/grp_Web/%2fprm%2fusers").setText(formEl["edLogin"]);
  			userReq.childAdd("save").setAttr("path","/%2fobj");
  			SYS.cntrReq(userReq); 

  			//>> Set message about correct remove
  			treeEl=pgTree.getElementBy("mess","name");
  			treeEl.childAdd("span").setAttr("style","color : green;").setText("Пользователь успешно удален. Можно продолжать.");
  		}
  		else
  		{
  			treeEl=pgTree.getElementBy("mess","name").childAdd("span").setAttr("style","color : red;");
  			if(isWebRootUser) treeEl.setText("Удаление суперпользователя недопустимо!");
  			else treeEl.setText("Пользователь для удаления отсутствует.");
  		}
  	}
  }

  //>> Load variables for select device
  if(isAdmin)
  {
  	//> Load users list
  	var userLst = SYS.XMLNode("get").setAttr("path","/sub_Security/grp_Web/%2fprm%2fusers");
  	SYS.cntrReq(userLst);

  	treeEl = pgTree.getElementBy("edLogin","name");
  	treeEl.childAdd("OPTION").setAttr("value","").setText("");
  	treeEl.childAdd("OPTION").setAttr("value","new").setText("Новый пользователь");
  	for(var i = 0; i < userLst.childSize(); i++)
  	{
  		treeEl1 = SYS.XMLNode("get").setAttr("path","/sub_Security/usr_"+userLst.childGet(i).text()+"/%2fprm%2fdscr");
  		SYS.cntrReq(treeEl1);
  		treeEl.childAdd("OPTION").setAttr("value",userLst.childGet(i).text()).setText(treeEl1.text());
  	}
  }
  else
  {
  	//> Hide select input and block login edit
  	pgTree.getElementBy("edLogin","name").setAttr("style","display : none;");
  	pgTree.getElementBy("login","name").setAttr("disabled","disabled");
  	pgTree.getElementBy("tel").setAttr("style","visibility : hidden;");
  	pgTree.getElementBy("sms").setAttr("style","visibility : hidden;");
  	pgTree.getElementBy("report").setAttr("style","visibility : hidden;");
  }

  if(!cnts.length || !formEl["edDel"].isEVal())
  {
  	if(!urlPrms["selUser"].isEVal() && urlPrms["selUser"].length)
  	{
  		curUser = urlPrms["selUser"];
  		pgTree.getElementBy(curUser,"value").setAttr("selected","selected");
  	}
  	var isSelAdmin = SYS.Security.access(curUser,4,"root","WebRoot",0440);

  	//> Connect to user object
  	//>> User login
  	pgTree.getElementBy("login","name").setAttr("value",curUser);
  	if(isAdmin && SYS.Security.access(curUser,4,"root","WebRoot",0440))
  	{
  		pgTree.getElementBy("login","name").setAttr("disabled","disabled");
  		pgTree.getElementBy("edDel","name").setAttr("style","display : none;");
  	}
  	//>> User FN
  	treeEl = SYS.XMLNode("get").setAttr("path","/sub_Security/usr_"+curUser+"/%2fprm%2fdscr");
  	SYS.cntrReq(treeEl);
  	pgTree.getElementBy("fio","name").setAttr("value",treeEl.text());
  	if(isAdmin)
  	{
  		//>> Description
  		treeEl = SYS.XMLNode("get").setAttr("path","/sub_Security/usr_"+curUser+"/%2fprm%2fldscr");
  		SYS.cntrReq(treeEl);
  		//>> Phones, SMS and repor
  		re=treeEl.text().match("TEL:\\s+([^\\n]*)");
  		pgTree.getElementBy("tel","name").setAttr("value",re.length ? re[1] : "");
  		re=treeEl.text().match("SMS:\\s+([^\\n]*)");
  		if(re.length && re[1] == "true") pgTree.getElementBy("sms","name").setAttr("checked","checked");
  		re=treeEl.text().match("Report:\\s+([^\\n]*)");
  		if(re.length && re[1] == "true") pgTree.getElementBy("report","name").setAttr("checked","checked");
  		//>> Subsystem's permition
  		if(!isSelAdmin)
  		{
  			var catLs = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/%2fprm%2fprm");
  			SYS.cntrReq(catLs);
  			treeEl1 = pgTree.getElementBy("sub_access");
  			for(var i = 0; i < catLs.childSize(); i++)
  			{
  				var subId = "sub_"+catLs.childGet(i).attr("id");
  				re=treeEl.text().match(subId+":\\s+([^\\n]*)");
  				treeEl1.childAdd("span").setText(catLs.childGet(i).text());
  				treeEl1.childAdd("br");
  				treeEl2 = treeEl1.childAdd("select").setAttr("name",subId);
  				treeEl1.childAdd("br");
  				treeEl3 = treeEl2.childAdd("option").setAttr("value","--").setText("Нет доступа");
  				if(re.length && re[1] == "--") treeEl3.setAttr("selected","selected");
  				treeEl3 = treeEl2.childAdd("option").setAttr("value","r-").setText("Наблюдение");
  				if(re.length && re[1] == "r-") treeEl3.setAttr("selected","selected");
  				treeEl3 = treeEl3.childAdd("option").setAttr("value","rw").setText("Управление");
  				if(re.length && re[1] == "rw") treeEl3.setAttr("selected","selected");
  			}
  		}
  		else
  		{
  			//> Session life time
  			treeEl1 = pgTree.getElementBy("sub_access");
  			treeEl1.childAdd("span").setText("Время жизни сеанса аутентификации (минут)");
  			treeEl1.childAdd("br");
  			var sessLife = SYS.XMLNode("get").setAttr("path","/sub_Protocol/mod_HTTP/%2fprm%2flf_tm");
  			SYS.cntrReq(sessLife);
  			treeEl1.childAdd("input").setAttr("type","text").setAttr("name","sesAuth").setAttr("value",sessLife.text());
  		}
  	}
  }

  //> Delete button hide
  if(!isAdmin || cnts.length || urlPrms["selUser"].isEVal() || !urlPrms["selUser"].length)
  	pgTree.getElementBy("edDel","name").setAttr("style","display : none;");

  //Save template
  rez = pgTree.save();
  //SYS.messDebug("TEST Dev","TEST 00: "+typeof(devLs[formEl["cat"]+"."+itId]));


# WebUser_uPg

ID: tmpl
NAME: XHTML-template
uk#NAME: XHTML-шаблон
DESCR: Site from XHTML template.
uk#DESCR: Сайт із XHTML шаблону
ru#DESCR: Сайт из XHTML шаблона.
ru#NAME: XHTML-шаблон
PROG:
  JavaLikeCalc.JavaScript
  var pgDir = "Web/";
  var firstEl = url.parsePath(0);
  var procPg = false;
  var tmplPg = "";
  var tmplPrcPg = false;
  var pgTree = false;
  var treeEl = false;
  var err = false;
  var isUser = SYS.Security.access(user,4,"root","Web",0440);
  var isRootUser = SYS.Security.access(user,4,"root","WebRoot",0440);

  //> Pages requests process
  if(!firstEl.length || (tmplPg=SYS.fileRead(pgDir+firstEl+".html")).length)
  {
  	//> Early call page's script
  	if(tmplPg.length)
  	{
  		procPg = SYS.DAQ.JavaLikeCalc.lib_web[(URLprms["script"].isEVal() ? firstEl : URLprms["script"])];
  		if(typeof(procPg) == "TCntrNode")
  		{
  			tmplPrcPg = procPg.call(URLprms,tmplPg,cnts,user);
  			//>> Check for full XML or resource request
  			var poff = 0;
  			if(tmplPrcPg.parse(0,"\n",poff) == "200 OK")
  			{
  				while((pEl=tmplPrcPg.parse(0,"\n",poff)).length) HTTPvars[pEl.parse(0,":")] = pEl.parse(1,":");
  				page = tmplPrcPg.slice(poff);
  				return "200 OK";
  			}
  		}
  		else tmplPrcPg = tmplPg;
  	}

  	//> Parse template
  	pgTree = SYS.XMLNode();
  	err = pgTree.load(pgDir+"main.html",true,true);

  	//> Page time place
  	pgTree.getElementBy("time_vl").setAttr("value",SYS.time());
  	var sessLife = SYS.XMLNode("get").setAttr("path","/sub_Protocol/mod_HTTP/%2fprm%2flf_tm");
  	SYS.cntrReq(sessLife);
  	pgTree.getElementBy("ses_vl").setAttr("value",sessLife.text().toInt()*60);

  	//> Check access to WEB resource
  	if(!user.length || !isUser)
  	{
  		pgTree.getElementBy("ses_vl").setAttr("value",10);
  		pgTree.getElementBy("menu_l").setAttr("style","visibility : hidden;");
  		pgTree.getElementBy("menu_r").setAttr("style","visibility : hidden;");
  		pgTree.getElementBy("status").setAttr("style","visibility : hidden;");
  		tmplPrcPg = SYS.fileRead(pgDir+"loginError.html");
  	}
  	//> Process include page template
  	else if(tmplPg.length)
  	{
  		//>> Select page display
  		treeEl = pgTree.getElementBy(firstEl);
  		if(typeof(treeEl) == "XMLNode")
  			treeEl.setAttr("class",treeEl.attr("class").replace(new RegExp("menu([^\"]*)"),"menuSel$1"));
  	}
  	else tmplPrcPg = SYS.fileRead(pgDir+"welcome.html");

  	//> Status make
  	pgTree.getElementBy("path").setText("/"+firstEl);
  	pgTree.getElementBy("user_st").childIns(0,"span").setText(user+"("+(isRootUser?"суперпользователь":"пользователь")+")      ");

  	//> Super user access
  	if(isUser && !isRootUser)
  	{
  		pgTree.getElementBy("cfg").parent().setAttr("style","visibility : hidden;");
  		pgTree.getElementBy("devices").parent().setAttr("style","visibility : hidden;");

  		treeEl = SYS.XMLNode("get").setAttr("path","/sub_Security/usr_"+user+"/%2fprm%2fldscr");
  		SYS.cntrReq(treeEl);
  		//>> Report disable
  		re=treeEl.text().match("Report:\\s+([^\\n]*)");
  		if(!re.length || re[1] != "true") pgTree.getElementBy("report").parent().setAttr("style","visibility : hidden;");
  		//>> Subsystem's permition
  		var catLs = SYS.XMLNode("get").setAttr("path","/DAQ/ModBus/ZegBee/%2fprm%2fprm");
  		SYS.cntrReq(catLs);
  		for(var i = 0; i < catLs.childSize(); i++)
  		{
  			re=treeEl.text().match("sub_"+catLs.childGet(i).attr("id")+":\\s+([^\\n]*)");
  			if(!re.length || re[1] == "--") pgTree.getElementBy(catLs.childGet(i).attr("id")).parent().setAttr("style","visibility : hidden;");
  		}
  	}

  	//> Save template
  	page = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
  			"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"+
  			pgTree.save();
  	page = page.replace("#####CONTEXT#####",tmplPrcPg);
  	return "200 OK";
  }

  //> Resources get process
  if(HTTPreq == "GET")
  {
  	page = SYS.fileRead(pgDir+url);
  	if(!page.length) { page = "Resource '"+url+"' call error!"; return "404 Not Found"; }
  	//>> Extesion types processing
  	var fext = url.lastIndexOf(".");
  	fext = (fext > 0) ? url.slice(fext+1) : "";
  	if(fext == "png" || fext == "jpg" || fext == "ico") HTTPvars["Content-Type"] = "image/"+fext;
  	else if(fext == "css" || fext == "html" || fext == "xml") HTTPvars["Content-Type"] = "text/"+fext;
  	else if(fext == "js") HTTPvars["Content-Type"] = "text/javascript";
  	//SYS.messDebug("TEST Web","TEST 10: '"+fext+"' .");
  	return "200 OK";
  }

  return "404 Not Found";


# Trs

base:
  Frequency was bad (previous XtalStat was XPROB_FREQ) and frequency is now in range, but life is less than 3%.


base:
  Unable to determine rate because of a computation error, most likely caused by a parameter (density, z-ratio, etc) having a zero or otherwise invalid (non numeric or infinity) value.


# tmplib_DevLib

ID: SCU750
NAME: EDWARDS TURBOMOLECULAR PUMPS
DESCR:
  Typical EDWARDS TURBOMOLECULAR PUMPS (http://edwardsvacuum.com) data request by SCU750 Cotrol Unit protocol.
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Vasiliy Grigoriev from "Vacuum technologies laboratory (http://e-beam.ru)".

PROGRAM:
  JavaLikeCalc.JavaScript
  if(f_start) {
  	version = "";
  	operModes = new Object();
  	operModes[1] = tr("Levitation");
  	operModes[2] = tr("No Levitation");
  	operModes[3] = tr("Acceleration");
  	operModes[4] = tr("Normal");
  	operModes[5] = tr("Deceleration (Brake)");
  	operModes[6] = tr("Autotest");
  	operModes[7] = tr("Tuning");
  	operModes[8] = tr("Tuning Complete");
  }

  tr = SYS.Transport.Serial.nodeAt("out_"+transport);
  req = SYS.XMLNode("mess").setAttr("ProtIt","SCU750").setAttr("addr",addr);

  //======= Commands =========
  //START, STOP and RESET process
  if(comReset == true) req.setText(" E04");
  else if(comStop == true) req.setText(" E02");
  else if(comStart == true) req.setText(" E01");
  else req.setText("");
  if(req.text().length) { tr.messIO(req,"UserProtocol"); comReset=comStop=comStart=false; }

  //Speed setpoint set
  if(spSpeed != spSpeedPrev) {
  	req.setText(" h"+spSpeed.toString(16,4));
  	tr.messIO(req,"UserProtocol");
  	spSpeedPrev = spSpeed;
  }

  //======= Data getting (by self bigger period) ========
  if((cnt++)%max(1,perGet*f_frq))	return;
  t_err = "";

  //Read version, single
  if(!version.length || version.isEVal()) {
  	req.setText("?V");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); version = EVAL_STR; }
  	else {
  		if(req.text().length != 42) version = EVAL_STR;
  		else {
  			CUSv = "";
  			lstNoSp = 0;
  			for(i_s = 2; i_s < 32; i_s+=2) {
  				cod = req.text().slice(i_s,i_s+2).toInt(16);
  				CUSv += SYS.strFromCharCode(cod);
  				if(cod != 0x20) lstNoSp = i_s/2;
  			}
  			version = "Contr. Unit Soft V.="+CUSv.slice(0,lstNoSp)+"; "
  					    "Motor Drive Soft V.="+req.text().charAt(35)+"."+req.text().charAt(36)+"; "
  					    "DSP Soft V.="+req.text().charAt(39)+"."+req.text().charAt(40);
  		}
  	}
  }

  //Read rotational speed.
  if(t_err.length) tTMS = tMotor = rotSpeed = EVAL_INT;
  else {
  	req.setText("?[");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); tTMS = tMotor = rotSpeed = EVAL_INT; }
  	else {
  		tTMS = req.text().slice(32,36).toInt(16);
  		tMotor = req.text().slice(36,40).toInt(16);
  		rotSpeed = req.text().slice(50,54).toInt(16);
  	}
  }

  //Pump operation mode and errors read
  if(t_err.length) { operMode = EVAL_INT; errors = EVAL_STR; }
  else {
  	req.setText("?M");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); operMode = EVAL_INT; errors = EVAL_STR; }
  	else {
  		oMode = req.text().slice(2,4).toInt(16);
  		operMode = oMode.toString()+":"+(operModes[oMode].isEVal()?tr("Unknown"):operModes[oMode]);
  		//SYS.messDebug("CNTR","pumpOperMode: "+pumpOperMode);
  		
  		errCnt = req.text().slice(4,6).toInt(16);
  		errors = "";
  		for(i_e = 0; i_e < errCnt; i_e++)
  			errors += req.text().slice(6+i_e*2,8+i_e*2)+"; ";
  	}
  }

  //Events read
  if(t_err.length)	events = EVAL_STR;
  else {
  	req.setText("?g");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); events = EVAL_STR; }
  	else {
  		errCnt = req.text().slice(2,4).toInt(16);
  		events = "";
  		for(i_e = 0; i_e < errCnt; i_e++)
  			events += req.text().slice(4+i_e*2,6+i_e*2)+"; ";
  	}
  }

  //Counters
  if(t_err.length) { snCntrUnit = snPump = EVAL_STR; cntPumpHour = cntCntrUnitHour = cntStart = EVAL_REAL; }
  else {
  	req.setText("?c");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); snCntrUnit = snPump = EVAL_STR; cntPumpHour = cntCntrUnitHour = cntStart = EVAL_REAL; }
  	else {
  		snCntrUnit = req.text().slice(2,12);
  		snPump = req.text().slice(12,22);
  		cntPumpHour = req.text().slice(22,30).toInt(16);
  		cntCntrUnitHour = req.text().slice(30,38).toInt(16);
  		cntStart = req.text().slice(38,46).toInt(16);
  	}
  }

  //Read setpoints
  if(t_err.length)	spSpeed = spSpeedPrev = spTMSt = EVAL_INT;
  else {
  	req.setText("?d");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); spSpeed = spSpeedPrev = spTMSt = EVAL_INT; }
  	else {
  		spSpeed = spSpeedPrev = req.text().slice(2,6).toInt(16);
  		spTMSt = req.text().slice(6,10).toInt(16);
  	}
  }

  f_err = t_err;


ID: TMH
NAME: Power supply for turbomolecular pumps
DESCR:
  Power supply for turbomolecular pumps of firm SHIMADZU (http://www.shimadzu.com), model EI-R04M.
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Vasiliy Grigoriev from "Vacuum technologies laboratory (http://e-beam.ru)".

PROGRAM:
  JavaLikeCalc.JavaScript
  tr = SYS.Transport.Serial.nodeAt("out_"+transport);
  req = SYS.XMLNode("mess").setAttr("ProtIt","TMH").setAttr("addr",addr);

  if(f_start) {
  	modelID = "";
  	operModes = new Object();
  	//Modes
  	operModes["NS"] = "1:"+tr("Levitation");
  	operModes["NA"] = "3:"+tr("Acceleration");
  	operModes["NN"] = "4:"+tr("Normal");
  	operModes["NB"] = "5:"+tr("Deceleration");
  	operModes["FS"] = "6:"+tr("Stop operation failure");
  	operModes["FF"] = "7:"+tr("Idling failure");
  	operModes["FR"] = "8:"+tr("Regeneration breaking failure");
  	operModes["FB"] = "9:"+tr("Deceleration failure");
  	//Conrols
  	operModes["LL"] = tr("Local");
  	operModes["LR"] = tr("Remote");
  	operModes["LC"] = "RS-232C";
  	operModes["LD"] = "RS-485";

  	//Set to Interactive
  	req.setText("LN");
  	tr.messIO(req,"UserProtocol");
  }

  //======= Commands =========
  //START, STOP and RESET process
  if(comReset == true)			req.setText("RR");
  else if(comStop == true)		req.setText("RP");
  else if(comStart == true)	req.setText("RT");
  else req.setText("");
  if(req.text().length)	{ tr.messIO(req,"UserProtocol"); comReset = comStop = comStart = false; }

  //Interactive, Autonomous
  if(comInteract == true)		req.setText("LN");
  else if(comAutonom == true)	req.setText("LF");
  else req.setText("");
  if(req.text().length)	{ tr.messIO(req,"UserProtocol"); comInteract = comAutonom = false; }

  //======= Data getting (by self bigger period) ========
  if((cnt++)%max(1,perGet*f_frq))	return;
  t_err = "0";

  //Oper mode
  req.setText("CS");
  tr.messIO(req,"UserProtocol");
  if(req.attr("err").length) { t_err = req.attr("err"); operMode = EVAL_STR; }
  else operMode = /*req.text().slice(2)+":"+*/operModes[req.text().slice(0,2)];

  //Oper control
  if(t_err.toInt())	operCntr = EVAL_STR;
  else {
  	req.setText("LS");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); operCntr = EVAL_STR; }
  	else operCntr = operModes[req.text().slice(0,2)];
  }

  //Alarms list obtain
  if(t_err.toInt())	errors = EVAL_STR;
  else {
  	errors = "";
  	for(i = 0; true; i++) {
  		req.setText("CF"+i.toString(10,2));
  		tr.messIO(req,"UserProtocol");
  		if(req.attr("err").length) { t_err = req.attr("err"); errors = EVAL_STR; break; }
  		//SYS.messDebug("TMH","Result: "+req.text());
  		if(req.text().slice(0,2) != "CA")	break;
  		errors += req.text().slice(2)+";";
  		continue;
  	}
  }

  //Get parameters
  // Model ID
  if(t_err.toInt())	modelID = EVAL_STR;
  else if(!modelID.length || modelID == EVAL_STR) {
  	req.setText("PR01");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); modelID = EVAL_STR;}
  	else if(req.text().slice(0,2) != "PA") modelID = EVAL_STR;
  	else modelID = "TMP-"+req.text().slice(4);
  }

  // Rotation speed
  if(t_err.toInt())	rotSpeed = EVAL_INT;
  else {
  	req.setText("PR03");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); rotSpeed = EVAL_INT;}
  	else if(req.text().slice(0,2) != "PA") rotSpeed = EVAL_INT;
  	else rotSpeed = req.text().slice(4).toInt()*10;
  }

  // Current
  if(t_err.toInt())	I = EVAL_REAL;
  else {
  	req.setText("PR04");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); I = EVAL_REAL;}
  	else if(req.text().slice(0,2) != "PA") I = EVAL_REAL;
  	else I = req.text().slice(4).toInt()/10;
  }

  // Axle 1 disbalance
  if(t_err.toInt())	axle1disb = EVAL_INT;
  else {
  	req.setText("PR21");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); axle1disb = EVAL_INT;}
  	else if(req.text().slice(0,2) != "PA") axle1disb = EVAL_INT;
  	else axle1disb = req.text().slice(4).toInt();
  }

  // Axle 2 disbalance
  if(t_err.toInt())	axle2disb = EVAL_INT;
  else {
  	req.setText("PR22");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); axle2disb = EVAL_INT;}
  	else if(req.text().slice(0,2) != "PA") axle2disb = EVAL_INT;
  	else axle2disb = req.text().slice(4).toInt();
  }

  // MP X1
  if(t_err.toInt())	MP_X1 = EVAL_INT;
  else {
  	req.setText("PR26");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); MP_X1 = EVAL_INT;}
  	else if(req.text().slice(0,2) != "PA") MP_X1 = EVAL_INT;
  	else MP_X1 = req.text().slice(4).toInt();
  }

  // MP Y1
  if(t_err.toInt())	MP_Y1 = EVAL_INT;
  else {
  	req.setText("PR27");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); MP_Y1 = EVAL_INT;}
  	else if(req.text().slice(0,2) != "PA") MP_Y1 = EVAL_INT;
  	else MP_Y1 = req.text().slice(4).toInt();
  }

  // MP X2
  if(t_err.toInt())	MP_X2 = EVAL_INT;
  else {
  	req.setText("PR28");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); MP_X2 = EVAL_INT;}
  	else if(req.text().slice(0,2) != "PA") MP_X2 = EVAL_INT;
  	else MP_X2 = req.text().slice(4).toInt();
  }

  // MP Y2
  if(t_err.toInt())	MP_Y2 = EVAL_INT;
  else {
  	req.setText("PR29");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); MP_Y2 = EVAL_INT;}
  	else if(req.text().slice(0,2) != "PA") MP_Y2 = EVAL_INT;
  	else MP_Y2 = req.text().slice(4).toInt();
  }

  // MP Z
  if(t_err.toInt())	MP_Z = EVAL_INT;
  else {
  	req.setText("PR30");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length) { t_err = req.attr("err"); MP_Z = EVAL_INT;}
  	else if(req.text().slice(0,2) != "PA") MP_Z = EVAL_INT;
  	else MP_Z = req.text().slice(4).toInt();
  }

  f_err = t_err;


ID: TM510x
NAME: Elemer TM510x
DESCR:
  Multichannels thermometer Elemer TM5102 and TM5103 of firm Elemer (http://www.elemer.ru).
  Author: Roman Savochenko <rom_as@oscada.org>

PROGRAM:
  JavaLikeCalc.JavaScript
  if(f_start) devTp = EVAL_INT;

  tr = SYS.Transport.Serial.nodeAt("out_"+transport);
  req = SYS.XMLNode("mess").setAttr("ProtIt", "TM510x").setAttr("addr", addr);

  t_err = "";

  //Device type get
  if(devTp.isEVal() || !devTp) {
  	req.setText("0");
  	tr.messIO(req, "UserProtocol");
  	if(req.attr("err").length)	t_err = req.attr("err");
  	else devTp = req.text().toInt();
  }

  //Inputs read
  errors = "";
  if(t_err.length) in1 = in2 = in3 = in4 = in5 = in6 = in7 = in8 = EVAL_REAL;
  else {
  	req.setText("6;0;8");
  	tr.messIO(req,"UserProtocol");
  	if(req.attr("err").length)
  	{ t_err = req.attr("err"); in1 = in2 = in3 = in4 = in5 = in6 = in7 = in8 = EVAL_REAL; }
  	else {
  		off = 0;
  		tvl = "";
  		in1 = ((tvl=req.text().parse(0, ";", off))[0] == "$") ? EVAL_INT : tvl.toReal();
  		errors += ((tvl[0] == "$") ? tvl.slice(1) : "0")+";";
  		in2 = ((tvl=req.text().parse(0, ";", off))[0] == "$") ? EVAL_INT : tvl.toReal();
  		errors += ((tvl[0] == "$") ? tvl.slice(1) : "0")+";";
  		in3 = ((tvl=req.text().parse(0, ";", off))[0] == "$") ? EVAL_INT : tvl.toReal();
  		errors += ((tvl[0] == "$") ? tvl.slice(1) : "0")+";";
  		in4 = ((tvl=req.text().parse(0, ";", off))[0] == "$") ? EVAL_INT : tvl.toReal();
  		errors += ((tvl[0] == "$") ? tvl.slice(1) : "0")+";";
  		in5 = ((tvl=req.text().parse(0, ";", off))[0] == "$") ? EVAL_INT : tvl.toReal();
  		errors += ((tvl[0] == "$") ? tvl.slice(1) : "0")+";";
  		in6 = ((tvl=req.text().parse(0, ";", off))[0] == "$") ? EVAL_INT : tvl.toReal();
  		errors += ((tvl[0] == "$") ? tvl.slice(1) : "0")+";";
  		in7 = ((tvl=req.text().parse(0, ";", off))[0] == "$") ? EVAL_INT : tvl.toReal();
  		errors += ((tvl[0] == "$") ? tvl.slice(1) : "0")+";";
  		in8 = ((tvl=req.text().parse(0, ";", off))[0] == "$") ? EVAL_INT : tvl.toReal();
  		errors += ((tvl[0] == "$") ? tvl.slice(1) : "0")+";";
  	}
  }

  f_err = t_err;


ID: UPS
DESCR:
  Uninterruptible power supply unifying data for provide all the data into single attribute of object type "All items" for next the control as the object with the data provide as table, alarming and allowing set writable attributes. The template aimed for using with module "System" data source as "UPS" and widget "Main.objProps" as the data presenter. The template also you can use as example for create like other data unification as complex object with properties, alarming and writing.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.2.0

PROGRAM:
  JavaLikeCalc.JavaScript
  if(f_start)	{ srcPrm = false; items = new Object(); conDelay_ = 0; }

  alLev = 0;
  tErr = "";

  //Connect to source
  if(typeof(srcPrm) != "TCntrNode:TValue:TParamContr") srcPrm = SYS.DAQ.nodeAt(srcAddr,".");
  if(!srcPrm) { tErr = tr("No connection to source object"); alLev = 3; }
  else if(srcPrm.err.get() != 0)	 { tErr = tr("Source error")+": "+srcPrm.err.get().parse(1,":"); alLev = 3; }
  else {
  	//Attributes list get and "items" update
  	nLst = srcPrm.nodeList("a_");
  	for(i_n = 0; i_n < nLst.length; i_n++) {
  		aId = nLst[i_n].slice(2);
  		aNd = srcPrm[nLst[i_n]];
  		if(items[aId].isEVal()) {
  			items[aId] = itW = new Object();
  			itW.descr = aNd.descr();

  			// Writeable check
  			//SYS.messInfo("UPS test", aId+": aNd.flg()="+aNd.flg());
  			if((itW.wr=!(aNd.flg()&0x04)) && aNd.flg()&0x01) {
  				itW.wr = "";
  				for(off = 0, pos = 0; (selId=aNd.values().parse(0,";",off)).length; pos++)
  					itW.wr += ((selId==(selNm=aNd.selNames().parse(pos,";")))?selId:(selNm+" ("+selId+")"))+";";
  			}
  			itW.alarm = 0;
  		}
  		items[aId].val = aNd.get();
  	}

  	//Alarms process and mark
  	varS = "ups_status";
  	if(!(tP=srcPrm[varS]).isEVal() && !(tVl=tP.get()).isEVal()) {
  		if(tVl == "OB")	{ items[varS].alarm = 1; tErr += tr("Status")+" \""+tr("On battery")+"\"; "; }
  		else if(tVl == "LB")	{ items[varS].alarm = 2; tErr += tr("Status")+" \""+tr("Low battery")+"\"; "; }
  		else if(tVl == "SD")	{ items[varS].alarm = 2; tErr += tr("Status")+" \""+tr("Shutdown load")+"\"; "; }
  		else if(tVl.indexOf("ALARM") != -1)	{ items[varS].alarm = 2; tErr += tr("Status")+" \""+tr("ALARM")+"\"; "; }
  		else items[varS].alarm = 0;
  	}
  	varS = "battery_packs";
  	if(!(tP=srcPrm[varS]).isEVal() && !(tVl=tP.get()).isEVal()) {
  		if(tVl.toInt() == 0)	{ items[varS].alarm = 2; tErr += tr("None of good battery present")+"; "; }
  		else items[varS].alarm = 0;
  	}
  	varS = "battery_charge";
  	if(!(tP=srcPrm[varS]).isEVal() && !(tVl=tP.get()).isEVal()) {
  		if(tVl.toReal() < bChL) { items[varS].alarm = 1; tErr += tr("Battery charge low")+"; "; }
  		else if(tVl.toReal() < bChLL) { items[varS].alarm = 2; tErr += tr("Battery charge critical")+"; "; }
  		else items[varS].alarm = 0;
  	}
  	varS = "battery_packs_bad";
  	if(!(tP=srcPrm[varS]).isEVal() && !(tVl=tP.get()).isEVal()) {
  		if(tVl.toInt())	{ items[varS].alarm = 1; tErr += tr("Bad %1 batteries present").replace("%1",tVl); }
  		else items[varS].alarm = 0;
  	}
  	varS = "input_voltage";
  	if(!(tP=srcPrm[varS]).isEVal() && !(tVl=tP.get()).isEVal()) {
  		if(tVl.toReal() > 10 && tVl.toReal() < inVL) { items[varS].alarm = 1; tErr += tr("Input voltage low")+"; "; }
  		else if(tVl.toReal() > inVH) { items[varS].alarm = 1; tErr += tr("Input voltage high")+"; "; }
  		else items[varS].alarm = 0;
  	}
  	varS = "input_frequency";
  	if(!(tP=srcPrm[varS]).isEVal() && !(tVl=tP.get()).isEVal()) {
  		if(tVl.toReal() < inFLL) { items[varS].alarm = 2; tErr += tr("Input frequency too low")+"; "; }
  		else if(tVl.toReal() > inFHH)	{ items[varS].alarm = 2; tErr += tr("Input frequency too high")+"; "; }
  		else if(tVl.toReal() < inFL) { items[varS].alarm = 1; tErr += tr("Input frequency low")+"; "; }
  		else if(tVl.toReal() > inFH) { items[varS].alarm = 1; tErr += tr("Input frequency high")+"; "; }
  		else items[varS].alarm = 0;
  	}
  	varS = "ups_load";
  	if(!(tP=srcPrm[varS]).isEVal() && !(tVl=tP.get()).isEVal()) {
  		if(tVl.toReal() > loadHH)		{ items[varS].alarm = 2; tErr += tr("UPS overloaded")+"; "; }
  		else if(tVl.toReal() > loadH)	{ items[varS].alarm = 1; tErr += tr("UPS load high")+"; "; }
  		else items[varS].alarm = 0;
  	}
  	varS = "ups_temperature";
  	if(!(tP=srcPrm[varS]).isEVal() && !(tVl=tP.get()).isEVal()) {
  		if(tVl.toReal() > tHH) 		{ items[varS].alarm = 2; tErr += tr("UPS overheated")+"; "; }
  		else if(tVl.toReal() > tH)	{ items[varS].alarm = 1; tErr += tr("Temperature high")+"; "; }
  		else items[varS].alarm = 0;
  	}

  	//Set variables process
  	for(var aIt in items) {
  		it = items[aIt];
  		if(!it.set.isEVal()) {
  			aNd = srcPrm["a_"+it.id];
  			if(aNd.flg()&0x01 && (selV=it.set.match(".+\\((.+)\\)$")).length) it.set = selV[1];
  			aNd.set(it.set);
  			it.set = EVAL_REAL;
  		}
  		alLev = max(alLev, it.alarm);
  	}
  }

  //SYS.messInfo("UPS test", "tErr="+tErr+"; alLev="+alLev);
  tErr = tErr.length ? ""+alLev+":"+tErr : "0";

  //Alarms forming
  if(alDelay > 0 && conDelay_ <= 0 && tErr.toInt() != f_err.toInt())	tErr1 = tErr.toInt();
  if(alDelay > 0 && conDelay_ > 0 && tErr.toInt() != tErr1)	{ conDelay_ = 0; tErr1 = tErr.toInt(); }
  if(alDelay > 0 && conDelay_ < alDelay){ conDelay_ += 1/f_frq; return; }
  if(tErr.toInt() && tErr.toInt() != f_err.toInt())
  	this.cntr().alarmSet((NAME.length?NAME:SHIFR)+": "+DESCR+": "+tErr.parse(1,":"), -(2+alLev), SHIFR);
  else if(f_err.toInt() && !tErr.toInt())
  	this.cntr().alarmSet((NAME.length?NAME:SHIFR)+": "+DESCR+": "+tr("NORMA"), 1, SHIFR);
  f_err = tErr;
  conDelay_ = 0;


ID: VKT7
NAME: VKT-7
uk#DESCR: Фірма "Teplocom" (http://www.teplocom.spb.ru) комп'ютер "VKT-7", St.Peterburg.
ru#DESCR: Фирма "Teplocom" (http://www.teplocom.spb.ru) компьютер "VKT-7", St.Peterburg.
DESCR:
  Firm "Teplocom" (http://www.teplocom.spb.ru) computer "VKT-7" for complex heat measurement and the count. The device complex enough by provide more parameters, more history to its and access by nonlinear Serial-based protocol at low speed. The template implement acquisition for all significant parameters, get history by hours, days and result months. Also you can simple enough append for process other left parameters.
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Vladislav Chubuk

PROGRAM:
  JavaLikeCalc.JavaScript
  using Special.FLibSYS;

  if(f_start) {
  	//Variables list prepare
  	varsLs = new Object();
  	//Тв1
  	varsLs["t1_1"] = 0; varsLs["t2_1"] = 1; varsLs["t3_1"] = 2;		//t
  	varsLs["V1_1"] = 3; varsLs["V2_1"] = 4;	varsLs["V3_1"] = 5;		//V
  	varsLs["M1_1"] = 6;	varsLs["M2_1"] = 7;	varsLs["M3_1"] = 8;		//M
  	varsLs["P1_1"] = 9;	varsLs["P2_1"] = 10;	//P
  	varsLs["Mg_1"] = 11;	//Mg
  	varsLs["Qo_1"] = 12;	//Qo
  	varsLs["Qg_1"] = 13;	//Qg
  	varsLs["dt_1"] = 14;	//dt
  	varsLs["BNR_1"] = 17; varsLs["BOC_1"] = 18;//BNR and BOC
  	varsLs["G1_1"] = 19; varsLs["G2_1"] = 20;	//G
  	//Тв2
  	varsLs["t1_2"] = 22; varsLs["t2_2"] = 23; varsLs["t3_2"] = 24;	//t
  	varsLs["V1_2"] = 25; varsLs["V2_2"] = 26; varsLs["V3_2"] = 27;	//V
  	varsLs["M1_2"] = 28; varsLs["M2_2"] = 29; varsLs["M3_2"] = 30;	//M
  	varsLs["P1_2"] = 31; varsLs["P2_2"] = 32;	//P
  	varsLs["Mg_2"] = 33;	//Mg
  	varsLs["Qo_2"] = 34;	//Qo
  	varsLs["Qg_2"] = 35;	//Qg
  	varsLs["dt_2"] = 36;	//dt
  	varsLs["BNR_2"] = 39; varsLs["BOC_2"] = 40;//BNR and BOC
  	varsLs["G1_2"] = 41; varsLs["G2_2"] = 42;	//G

  	//Buffers create
  	bfH = vArhBuf(4/*Real*/, 10, 3600*1000000, true, false);
  	bfD = vArhBuf(4/*Real*/, 10, 24*3600*1000000, true, false);
  	bfM = vArhBuf(4/*Real*/, 10, 24*3600*1000000, true, false);
  }

  t_err = "";
  //Imitation for values
  if(imit > 0.1) {
  	//SYS.messDebug("/VKT7/TMPL","imit="+t1_1+"; dt="+(imit*(rand(t1_1)-t1_1/2)/100));
  	for(var cA in varsLs)
  		if(cA.slice(0,2) == "dt") arguments[cA] = arguments["t1_"+cA.slice(3)]-arguments["t2_"+cA.slice(3)];
  		else arguments[cA] += imit*(rand(arguments[cA])-arguments[cA]/2)/100;
  	f_err = "0";
  	return;
  }

  if(f_stop) {
  	f_err = "";
  	for(var cA in varsLs) arguments[cA] = EVAL_REAL;
  	return;
  }

  //Set transport and RTS
  if(f_start){ tr = SYS.nodeAt(trAddr,"."); tr.TS(true); valsPrec = false; valsSz = false; }
  if(!tr)	t_err = "1:"+tr("Transport '%1' error.").replace("%1",trAddr);

  req = SYS.XMLNode("mess").setAttr("ProtIt","VKT7").setAttr("addr",0);

  //Session start
  if(!t_err.length) {
  	SYS.messDebug("/VKT7/TMPL",tr("Start session."));
  	req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x3F,0xFF,0x00,0x00,0xCC,0x80,0x00,0x00,0x00));
  	tr.messIO(req,"UserProtocol");
  	t_err = req.attr("err");
  }

  //Request for service information
  if(!t_err.length && (f_start || firmVer.isEVal())) {
  	SYS.messDebug("/VKT7/TMPL",tr("Request for service info."));
  	req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x03,0x3f,0xf9,0x00,0x00));
  	tr.messIO(req,"UserProtocol");
  	t_err = req.attr("err");
  	if(!t_err.length) {
  		rez = req.text();
  		firmVer = (rez.charCodeAt(2)>>4)+(rez.charCodeAt(2)&0x0F)/10;
  		abonId = rez.slice(7,7+8);
  		netNum = rez.charCodeAt(15);
  		repDay = rez.charCodeAt(16);
  		modelImpl = rez.charCodeAt(17);
  	}
  }

  //Request for counter time and hour archive begin
  if(!t_err.length && (f_start || !lastHTm || !lastDTm || !lastResTm)) {
  	SYS.messDebug("/VKT7/TMPL",tr("Request for counter time and hour archive begin."));
  	req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x03,0x3f,0xf6,0x00,0x00));
  	tr.messIO(req,"UserProtocol");
  	t_err = req.attr("err");
  	if(!t_err.length) {
  		rez = req.text();
  		lastHTm = max(lastHTm, SYS.mktime(0,0,rez.charCodeAt(5),rez.charCodeAt(2),rez.charCodeAt(3)-1,2000+rez.charCodeAt(4)));
  		diffTm = floor((SYS.time()-SYS.mktime(0,0,rez.charCodeAt(9),rez.charCodeAt(6),rez.charCodeAt(7)-1,2000+rez.charCodeAt(8)))/3600);
  		leftHTm = (SYS.time()-lastHTm)/3600 - diffTm;
  	}
  	lastDTm = max(lastDTm, SYS.time()-maxDayDepth*24*3600);
  	leftDTm = (SYS.time()-lastDTm)/(24*3600);
  	lastResTm = max(lastResTm, SYS.time()-maxDayDepth*24*3600);
  	leftResTm = (SYS.time()-lastResTm)/(31*24*3600);
  }

  //Request for dimensions and precisions
  if(!t_err.length && (f_start || !valsPrec)) {
  	SYS.messDebug("/VKT7/TMPL",tr("Request for dimensions and precisions."));
  	req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10, 0x3F, 0xFF, 0x00, 0x00, 0x72,
  		0x2C, 0x00, 0x00, 0x40, 0x07, 0x00,	//tTypeM
  		0x2D, 0x00, 0x00, 0x40, 0x07, 0x00,	//GTypeM
  		0x2E, 0x00, 0x00, 0x40, 0x07, 0x00,	//VTypeM
  		0x2F, 0x00, 0x00, 0x40, 0x07, 0x00,	//MTypeM
  		0x30, 0x00, 0x00, 0x40, 0x07, 0x00,	//PTypeM
  		0x35, 0x00, 0x00, 0x40, 0x07, 0x00,	//QoTypeM
  		0x37, 0x00, 0x00, 0x40, 0x07, 0x00,	//QntTypeHIM
  		0x38, 0x00, 0x00, 0x40, 0x07, 0x00,	//QntTypeM
  		0x39, 0x00, 0x00, 0x40, 0x01, 0x00,	//tTypeFractDiNum
  		0x3B, 0x00, 0x00, 0x40, 0x01, 0x00,	//VTypeFractDigNum1
  		0x3C, 0x00, 0x00, 0x40, 0x01, 0x00,	//MTypeFractDigNum1
  		0x3D, 0x00, 0x00, 0x40, 0x01, 0x00,	//PTypeFractDigNum1
  		0x3E, 0x00, 0x00, 0x40, 0x01, 0x00,	//dtTypeFractDigNum1
  		0x42, 0x00, 0x00, 0x40, 0x01, 0x00,	//QoTypeFractDigNum1
  		0x45, 0x00, 0x00, 0x40, 0x01, 0x00,	//VTypeFractDigNum2
  		0x46, 0x00, 0x00, 0x40, 0x01, 0x00,	//MTypeFractDigNum2
  		0x47, 0x00, 0x00, 0x40, 0x01, 0x00,	//PTypeFractDigNum2
  		0x48, 0x00, 0x00, 0x40, 0x01, 0x00,	//dtTypeFractDigNum2
  		0x4C, 0x00, 0x00, 0x40, 0x01, 0x00));	//QoTypeFractDigNum2
  	tr.messIO(req,"UserProtocol");
  	t_err = req.attr("err");
  	if(!t_err.length) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x03,0x3F,0xFE,0x00,0x00));
  		tr.messIO(req,"UserProtocol");
  		t_err = req.attr("err");
  		if(!t_err.length) {
  			rez = req.text();	off = 2;
  			vLen = (rez.charCodeAt(off+1)<<8)|rez.charCodeAt(off);
  			tTypeM = SYS.strCodeConv(rez.slice(off+2,off+2+vLen),"CP866","");	off += vLen+4;
  			vLen = (rez.charCodeAt(off+1)<<8)|rez.charCodeAt(off);
  			GTypeM = SYS.strCodeConv(rez.slice(off+2,off+2+vLen),"CP866","");	off += vLen+4;
  			vLen = (rez.charCodeAt(off+1)<<8)|rez.charCodeAt(off);
  			VTypeM = SYS.strCodeConv(rez.slice(off+2,off+2+vLen),"CP866","");	off += vLen+4;
  			vLen = (rez.charCodeAt(off+1)<<8)|rez.charCodeAt(off);
  			MTypeM = SYS.strCodeConv(rez.slice(off+2,off+2+vLen),"CP866","");	off += vLen+4;
  			vLen = (rez.charCodeAt(off+1)<<8)|rez.charCodeAt(off);
  			PTypeM = SYS.strCodeConv(rez.slice(off+2,off+2+vLen),"CP866","");	off += vLen+4;
  			vLen = (rez.charCodeAt(off+1)<<8)|rez.charCodeAt(off);
  			QoTypeM = SYS.strCodeConv(rez.slice(off+2,off+2+vLen),"CP866","");	off += vLen+4;
  			vLen = (rez.charCodeAt(off+1)<<8)|rez.charCodeAt(off);
  			QntTypeHIM = SYS.strCodeConv(rez.slice(off+2,off+2+vLen),"CP866","");	off += vLen+4;
  			vLen = (rez.charCodeAt(off+1)<<8)|rez.charCodeAt(off);
  			QntTypeM = SYS.strCodeConv(rez.slice(off+2,off+2+vLen),"CP866","");	off += vLen+4;
  			valsPrec = new Object();
  			valsPrec["tTypeFractDiNum"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["VTypeFractDigNum1"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["MTypeFractDigNum1"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["PTypeFractDigNum1"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["dtTypeFractDigNum1"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["QoTypeFractDigNum1"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["VTypeFractDigNum2"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["MTypeFractDigNum2"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["PTypeFractDigNum2"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["dtTypeFractDigNum2"] = rez.charCodeAt(off);	off += 3;
  			valsPrec["QoTypeFractDigNum2"] = rez.charCodeAt(off);	off += 3;
  		}
  	}
  }

  //Request for values present list and size.
  if(!t_err.length && (f_start || !valsSz || !valsSz.length)) {
  	SYS.messDebug("/VKT7/TMPL",tr("Request for values present list and size."));
  	req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x03,0x3f,0xfc,0x00,0x00));
  	tr.messIO(req,"UserProtocol");
  	t_err = req.attr("err");
  	if(!t_err.length) {
  		rez = req.text();
  		valsSz = new Array();
  		for(off = 2; off < rez.length; off += 6)
  			valsSz[rez.charCodeAt(off)] = rez.charCodeAt(off+4);
  	}
  }

  //Readed items list write
  if(!t_err.length) {
  	SYS.messDebug("/VKT7/TMPL",tr("Readed items list write."));
  	data = "";
  	for(var cA in varsLs) {
  		itId = varsLs[cA];
  		if(!valsSz[itId].isEVal())	data += SYS.strFromCharCode(itId, 0x00, 0x00, 0x40, valsSz[itId], 0x00);
  	}

  	if(!data.length) {
  		for(var cA in varsLs) arguments[cA] = EVAL_REAL;
  		f_err = "10:"+tr("Data list for request empty.");
  		return;
  	}
  	req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x3f,0xff,0x00,0x00,data.length)+data);
  	//SYS.messDebug("/VKT7/TMPL","SetDataList: "+Special.FLibSYS.strDec4Bin(req.text()));
  	tr.messIO(req,"UserProtocol");
  	t_err = req.attr("err");
  }

  //Read 0-current value(4), 1-hour archive(0) and 2-result month archive(3)
  errAttrs = "";
  for(i_dt = 0; !t_err.length && i_dt < 4; i_dt++) {
  	tpReq = 4;																						//current
  	if(i_dt == 1)			{ tpReq = 0; if(!arhH.length) continue; }		//hour archive
  	else if(i_dt == 2)	{ tpReq = 1; if(!arhD.length) continue; }		//day archive
  	else if(i_dt == 3)	{ tpReq = 3; if(!arhRes.length) continue; }	//result archive

  	//Request for curent values (4).
  	if(tpReq == 4 && !t_err.length) {
  		SYS.messDebug("/VKT7/TMPL",tr("Request for curent values."));
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x3f,0xfd,0x00,0x00,0x02,0x04,0x00));
  		tr.messIO(req,"UserProtocol");
  		t_err = req.attr("err");
  	}

  	//Request for archive values hour
  	if(tpReq == 0) {
  		if(!t_err.length) {
  			if((SYS.time()-lastHTm-diffTm*3600)/3600 < 2) continue;	//No more ready hours present
  			SYS.messDebug("/VKT7/TMPL",tr("Request for hour archive values."));
  			req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x3f,0xfd,0x00,0x00,0x02,tpReq,0x00));
  			tr.messIO(req,"UserProtocol");
  			t_err = req.attr("err");
  		}

  		// Set for hour archive value data
  		if(!t_err.length) {
  			SYS.messDebug("/VKT7/TMPL",tr("Request for set archive data."));
  			stHour = stDay = stMonth = stYear = 0;
  			SYS.localtime(lastHTm, 0, 0, stHour, stDay, stMonth, stYear);
  			stHour++;
  			rdTime = SYS.mktime(0, 0, stHour, stDay, stMonth, stYear);

  			req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x3f,0xfb,0x00,0x00,0x04,stDay,stMonth+1,stYear-2000,stHour));
  			tr.messIO(req,"UserProtocol");
  			t_err = req.attr("err");
  			if(t_err.parse(1,":").toInt() == 3) { lastHTm = rdTime; leftHTm = (SYS.time()-lastHTm)/3600 - diffTm; t_err = ""; continue; }
  		}
  	}

  	//Request for archive values day
  	if(tpReq == 1) {
  		if(!t_err.length) {
  			if((SYS.time()-lastDTm-diffTm*3600)/(24*3600) < 1) continue;	//No more ready days present
  			SYS.messDebug("/VKT7/TMPL",tr("Request for day archive values."));
  			req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x3f,0xfd,0x00,0x00,0x02,tpReq,0x00));
  			tr.messIO(req,"UserProtocol");
  			t_err = req.attr("err");
  		}

  		// Set for day archive value data
  		if(!t_err.length) {
  			SYS.messDebug("/VKT7/TMPL",tr("Request for set archive data."));
  			stDay = stMonth = stYear = 0;
  			SYS.gmtime(lastDTm, 0, 0, 0, stDay, stMonth, stYear);
  			stDay++;
  			rdDTime = SYS.timegm(0, 0, 0, stDay, stMonth, stYear);

  			req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x3f,0xfb,0x00,0x00,0x04,stDay,stMonth+1,stYear-2000,stHour));
  			tr.messIO(req,"UserProtocol");
  			t_err = req.attr("err");
  			if(t_err.parse(1,":").toInt() == 3) { lastDTm = rdDTime; leftDTm = (SYS.time()-lastDTm)/(24*3600) - diffTm; t_err = ""; continue; }
  		}
  	}

  	//Request for results month archive
  	if(tpReq == 3) {
  		if(!t_err.length) {
  			if((SYS.time()-lastResTm-diffTm*3600)/(24*3600) < 31) continue;	//No more ready month present
  			SYS.messDebug("/VKT7/TMPL",tr("Request for results month archive values."));
  			req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x3f,0xfd,0x00,0x00,0x02,tpReq,0x00));
  			tr.messIO(req,"UserProtocol");
  			t_err = req.attr("err");
  		}
  		// Set for month results archive value data
  		if(!t_err.length) {
  			SYS.messDebug("/VKT7/TMPL",tr("Request for set archive data."));
  			stMonth = stYear = 0;
  			SYS.gmtime(lastResTm, 0, 0, 0, 0, stMonth, stYear);
  			stMonth++;
  			rdResTime = SYS.timegm(0, 0, 0, repDay, stMonth, stYear);

  			req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x3f,0xfb,0x00,0x00,0x04,repDay,stMonth+1,stYear-2000,0));
  			tr.messIO(req,"UserProtocol");
  			t_err = req.attr("err");
  			if(t_err.parse(1,":").toInt() == 3) { lastResTm = rdResTime; leftResTm = (SYS.time()-lastResTm)/(31*24*3600); t_err = ""; continue; }
  		}
  	}

  	//Request for data read
  	if(!t_err.length) {
  		SYS.messDebug("/VKT7/TMPL",tr("Request for data read."));
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x03,0x3F,0xFE,0x00,0x00));
  		tr.messIO(req,"UserProtocol");
  		t_err = req.attr("err");
  		if(!t_err.length) {
  			rez = req.text(); off = 2; vSz = 0;
  			for(var cA in varsLs) {
  				itId = varsLs[cA]; vSz = valsSz[itId];
  				if(vSz.isEVal()) {
  					if(tpReq == 4) arguments[cA] = EVAL_REAL;
  					continue;
  				}
  				//SYS.messDebug("/VKT7/TMPL","off: "+off+"; itId: "+itId+"; vSz: "+vSz);
  				if(rez.charCodeAt(off+vSz) == 0xC0) {
  					for(pVal = 0, i_b = 0; i_b < vSz; i_b++) pVal = pVal | rez.charCodeAt(off+i_b)<<(i_b*8);
  					//Float type values
  					if(cA[0] == "G") pVal = floatMergeWord(pVal&0xFFFF, (pVal>>16)&0xFFFF);
  					//Integer type values, negative process
  					else if(pVal&(0x80<<(8*(vSz-1))))	pVal -= (1<<(8*vSz));
  					// Type specific
  					if(cA[0] == "t")						tmpVl = pVal/pow(10,valsPrec["tTypeFractDiNum"]);
  					else if(cA[0] == "V")				tmpVl = pVal/pow(10,valsPrec["VTypeFractDigNum"+cA[3]]);
  					else if(cA[0] == "M")				tmpVl = pVal/pow(10,valsPrec["MTypeFractDigNum"+cA[3]]);
  					else if(cA[0] == "P")				tmpVl = pVal/pow(10,valsPrec["PTypeFractDigNum"+cA[3]]);
  					else if(cA[0] == "Q")				tmpVl = pVal/pow(10,valsPrec["QoTypeFractDigNum"+cA[3]]);
  					else if(cA.slice(0,2) == "dt")tmpVl = pVal/pow(10,valsPrec["dtTypeFractDigNum"+cA[3]]);
  					else tmpVl = pVal;

  					// Write current or archive
  					if(tpReq == 4) {
  						arguments[cA] = tmpVl;
  						SYS.messDebug("/VKT7/TMPL",tr("Set current")+" "+cA+": "+tmpVl);
  					}
  					else if(!(aObj=vArh(this.nodePath(".")+"."+cA)).isNull()) {
  						if(tpReq == 0) {
  							bfH.set(tmpVl, rdTime, 0); aObj.copy(bfH, rdTime, 0, rdTime, 0, arhH);
  							SYS.messDebug("/VKT7/TMPL",tr("Write to hour archive for time")+": "+rdTime+"; "+cA+": "+tmpVl);
  						}
  						if(tpReq == 1) {
  							bfD.set(tmpVl, rdDTime, 0); aObj.copy(bfD, rdDTime, 0, rdDTime, 0, arhD);
  							SYS.messDebug("/VKT7/TMPL",tr("Write to day archive for time")+": "+rdDTime+"; "+cA+": "+tmpVl);
  						}
  						else if(tpReq == 3) {
  							bfM.set(tmpVl, rdResTime, 0); aObj.copy(bfM, rdResTime, 0, rdResTime, 0, arhRes);
  							SYS.messDebug("/VKT7/TMPL",tr("Write to result month archive for time")+": "+rdResTime+"; "+cA+": "+tmpVl);
  						}
  					}
  				}
  				else if(tpReq == 4) { arguments[cA] = EVAL_REAL; errAttrs += ""+itId+"="+rez.charCodeAt(off+vSz).toString(16)+"; "; }
  				off += vSz+2;
  			}
  			if(tpReq == 0) { lastHTm = rdTime; leftHTm = (SYS.time()-lastHTm)/3600 - diffTm; }
  			else if(tpReq == 1) { lastDTm = rdDTime; leftDTm = (SYS.time()-lastDTm)/(24*3600) - diffTm; }
  			else if(tpReq == 3) { lastResTm = rdResTime; leftResTm = (SYS.time()-lastResTm)/(31*24*3600); }
  		}
  	}
  }

  if(t_err.length) {
  	SYS.messDebug("/VKT7/TMPL",tr("Error response")+": "+t_err);
  	f_err = t_err;
  	for(var cA in varsLs) arguments[cA] = EVAL_REAL;
  }
  else f_err = errAttrs.length ? "11:"+tr("Quality errors")+": "+errAttrs : "0";


ID: SMDP
NAME: Sycon Multi Drop Protocol
DESCR:
  STM devices for resonant frequency measurement for mass of deposited films attached to its surface by Sycon Instruments, Inc. (http://www.sycon.com).
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Vasiliy Grigoriev from "Vacuum technologies laboratory (http://e-beam.ru)".

PROGRAM:
  JavaLikeCalc.JavaScript
  if(f_stop) return;
  if(f_start) {
  	cnt = 0;
  	version = "";
  	SessId_ = SessId = QlvlTrip_ = QlvlTrip = SlvlTrip_ = SlvlTrip = EVAL_INT;
  	Fq_ = Fq = Fm_ = Fm = Density_ = Density = Zratio_ = Zratio = Tooling_ = Tooling = RateReq_ = RateReq = EVAL_REAL;
  }

  tr = SYS.Transport.Serial.nodeAt("out_"+transport);
  req = SYS.XMLNode("mess").setAttr("ProtIt","SMDP").setAttr("addr",addr).setAttr("try",3);

  t_err = "";

  //Configurations first write
  // Session ID.
  if(SessId != SessId_) {
  	SYS.messDebug("/SMDP/tmpl",""+SessId+"!="+SessId_);	
  	req.setAttr("err","1:"+tr("No connect")).setText("\xD0\x41"+SessId); tr.messIO(req,"UserProtocol");
  	if(!(t_err=req.attr("err")).length) SessId_ = SessId; else SessId = SessId_;
  }
  // Xtal start freq. (Hz)
  if(Fq != Fq_) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xD0\x42"+Fq); tr.messIO(req,"UserProtocol");
  	if(!(t_err=req.attr("err")).length) Fq_ = Fq; else Fq = Fq_;
  }
  // Xtal min freq. (Hz)
  if(Fm != Fm_) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xD0\x43"+Fm); tr.messIO(req,"UserProtocol");
  	if(!(t_err=req.attr("err")).length) Fm_ = Fm; else Fm = Fm_;
  }
  // Material density (gm/cc).
  if(Density != Density_) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xD0\x44"+Density); tr.messIO(req,"UserProtocol");
  	if(!(t_err=req.attr("err")).length) Density_ = Density; else Density = Density_;
  }
  // Material Z ratio. Not scaled or unitized.
  if(Zratio != Zratio_) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xD0\x45"+Zratio); tr.messIO(req,"UserProtocol");
  	if(!(t_err=req.attr("err")).length) Zratio_ = Zratio; else Zratio = Zratio_;
  }
  // 1.000 is 100 % tooling (unity).
  if(Tooling != Tooling_) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xD0\x46"+Tooling); tr.messIO(req,"UserProtocol");
  	if(!(t_err=req.attr("err")).length) Tooling_ = Tooling; else Tooling = Tooling_;
  }
  // Requested rate (A/S).
  if(RateReq != RateReq_) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xD0\x47"+RateReq); tr.messIO(req,"UserProtocol");
  	if(!(t_err=req.attr("err")).length) RateReq_ = RateReq; else RateReq = RateReq_;
  }
  // Quality threshold, if non 0 and exceeded, xtal fail occurs.
  if(QlvlTrip != QlvlTrip_) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xD0\x48"+QlvlTrip); tr.messIO(req,"UserProtocol");
  	if(!(t_err=req.attr("err")).length) QlvlTrip_ = QlvlTrip; else QlvlTrip = QlvlTrip_;
  }
  // Stability threshold, if non 0 and exceeded, xtal fail occurs.
  if(SlvlTrip != SlvlTrip_) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xD0\x49"+SlvlTrip); tr.messIO(req,"UserProtocol");
  	if(!(t_err=req.attr("err")).length) SlvlTrip_ = SlvlTrip; else SlvlTrip = SlvlTrip_;
  }

  //======= Data getting (by self bigger period) ========
  if((cnt++)%max(1,perGet*f_frq))	return;

  //Configurations first read
  // Session ID.
  if(!t_err.length && SessId.isEVal()) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x41"); tr.messIO(req,"UserProtocol");
  	SessId = SessId_ = (t_err=req.attr("err")).length ? EVAL_INT : req.text().slice(2).toInt(10);
  }
  // Xtal start freq. (Hz)
  if(!t_err.length && Fq.isEVal()) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x42"); tr.messIO(req,"UserProtocol");
  	Fq = Fq_ = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }
  // Xtal min freq. (Hz)
  if(!t_err.length && Fm.isEVal()) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x43"); tr.messIO(req,"UserProtocol");
  	Fm = Fm_ = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }
  // Material density (gm/cc).
  if(!t_err.length && Density.isEVal()) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x44"); tr.messIO(req,"UserProtocol");
  	Density = Density_ = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }
  // Material Z ratio. Not scaled or unitized.
  if(!t_err.length && Zratio.isEVal()) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x45"); tr.messIO(req,"UserProtocol");
  	Zratio = Zratio_ = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }
  // 1.000 is 100 % tooling (unity).
  if(!t_err.length && Tooling.isEVal()) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x46"); tr.messIO(req,"UserProtocol");
  	Tooling = Tooling_ = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }
  // Requested rate (A/S).
  if(!t_err.length && RateReq.isEVal()) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x47"); tr.messIO(req,"UserProtocol");
  	RateReq = RateReq_ = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }
  // Quality threshold, if non 0 and exceeded, xtal fail occurs.
  if(!t_err.length && QlvlTrip.isEVal()) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x48"); tr.messIO(req,"UserProtocol");
  	QlvlTrip = QlvlTrip_ = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toInt(10);
  }
  // Stability threshold, if non 0 and exceeded, xtal fail occurs.
  if(!t_err.length && SlvlTrip.isEVal()) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x49"); tr.messIO(req,"UserProtocol");
  	SlvlTrip = SlvlTrip_ = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toInt(10);
  }

  //Runtime variables
  // Read version, single
  if(!t_err.length && (!version.length || version.isEVal())) {
  	req.setAttr("err","1:"+tr("No connect")).setText("\x40"); tr.messIO(req,"UserProtocol");
  	version = (t_err=req.attr("err")).length ? EVAL_STR : req.text().slice(1);
  }

  // Read Configuration parameter session ID
  if(t_err.length) CfgPrmSSID = EVAL_INT;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x61"); tr.messIO(req,"UserProtocol");
  	CfgPrmSSID = (t_err=req.attr("err")).length ? EVAL_INT : req.text().slice(2).toInt(10);
  	//SYS.messDebug("/SMDP/tmpl","CfgPrmSSID: "+req.text());
  }

  // Read Measurement serial number
  if(t_err.length) Srlno = EVAL_INT;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x62"); tr.messIO(req,"UserProtocol");
  	Srlno = (t_err=req.attr("err")).length ? EVAL_INT : req.text().slice(2).toInt(10);
  }

  // Read Channel freq.
  if(t_err.length) RawFreq = EVAL_REAL;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x63"); tr.messIO(req,"UserProtocol");
  	RawFreq = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }

  // Read Last used, good channel freq. (Hz)
  if(t_err.length) GoodFreq = EVAL_REAL;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x64"); tr.messIO(req,"UserProtocol");
  	GoodFreq = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }

  // Read Computed raw thickness, from frequency. (A)
  if(t_err.length) RawThick = EVAL_REAL;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x65"); tr.messIO(req,"UserProtocol");
  	RawThick = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }

  // Read Computed material related thickness, can be zeroed. (A)
  if(t_err.length) XtalThick = EVAL_REAL;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x66"); tr.messIO(req,"UserProtocol");
  	XtalThick = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }

  // Read Filtered computed material related thickness, can be zeroed. (A)
  if(t_err.length) XtalThick_F = EVAL_REAL;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x67"); tr.messIO(req,"UserProtocol");
  	XtalThick_F = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }

  // Read Rate, angstroms per second.
  if(t_err.length) XtalRate = EVAL_REAL;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x68"); tr.messIO(req,"UserProtocol");
  	XtalRate = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }

  // Read Rate, angstroms per second, filtered.
  if(t_err.length) XtalRate_F = EVAL_REAL;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x69"); tr.messIO(req,"UserProtocol");
  	XtalRate_F = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }

  // Read XtalLife (%)
  if(t_err.length) XtalLife = EVAL_REAL;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x6A"); tr.messIO(req,"UserProtocol");
  	XtalLife = (t_err=req.attr("err")).length ? EVAL_REAL : req.text().slice(2).toReal();
  }

  // Read Quality level (0-9).
  if(t_err.length) XtalQual = EVAL_INT;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x6B"); tr.messIO(req,"UserProtocol");
  	XtalQual = (t_err=req.attr("err")).length ? EVAL_INT : req.text().slice(2).toInt(10);
  }

  // Read Highest quality level seen (0-9).
  if(t_err.length) XtalQualPeak = EVAL_INT;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x6C"); tr.messIO(req,"UserProtocol");
  	XtalQualPeak = (t_err=req.attr("err")).length ? EVAL_INT : req.text().slice(2).toInt(10);
  }

  // Read Stability level (0-9).
  if(t_err.length) XtalStab = EVAL_INT;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x6D"); tr.messIO(req,"UserProtocol");
  	XtalStab = (t_err=req.attr("err")).length ? EVAL_INT : req.text().slice(2).toInt(10);
  }

  // Read Highest stability level seen (0-9).
  if(t_err.length) XtalStabPeak = EVAL_INT;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x6E"); tr.messIO(req,"UserProtocol");
  	XtalStabPeak = (t_err=req.attr("err")).length ? EVAL_INT : req.text().slice(2).toInt(10);
  }

  // Read Channel status.
  if(t_err.length) XtalStat = EVAL_STR;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x6F"); tr.messIO(req,"UserProtocol");
  	if((t_err=req.attr("err")).length) XtalStat = EVAL_STR;
  	else {
  		stCd = req.text().slice(2).toInt(10);
  		stLab = tr("Unknown");
  		if(stCd == 0)			stLab = "XPROB_NONE: "+tr("No Problems. The rest below are prioritized.");
  		else if(stCd == 1)	stLab = "XPROB_FREQ: "+tr("Frequency of xtal is > Fq or < Fm. Halts all other calculations.");
  		else if(stCd == 2)	stLab = "XPROB_LOWLIFE: "+tr("Frequency was bad (previous XtalStat was XPROB_FREQ) and frequency is now in range, but life is less than 3%.");
  		else if(stCd == 3)	stLab = "XPROB_S_FAIL: "+tr("Stability level XtalStab of xtal >= SlvlTrip.");
  		else if(stCd == 4)	stLab = "XPROB_MATH: "+tr("Unable to determine rate because of a computation error, most likely caused by a parameter (density, z-ratio, etc) having a zero or otherwise invalid (non numeric or infinity) value.");
  		else if(stCd == 5)	stLab = "XPROB_Q_FAIL: "+tr("XtalQual of xtal >= QlvlTrip.");
  		XtalStat = ""+stCd+":"+stLab;
  	}
  }

  // Read XtalLife (%).
  if(t_err.length) XtalLife_C = EVAL_INT;
  else {
  	req.setAttr("err","1:"+tr("No connect")).setText("\xC0\x70"); tr.messIO(req,"UserProtocol");
  	XtalLife_C = (t_err=req.attr("err")).length ? EVAL_INT : req.text().slice(2).toInt(10);
  }

  f_err = t_err.length ? t_err : "0";


ID: IT3
NAME: Temperature measurement IT-3
DESCR:
  Temperature measurement IT-3 from OmskEtalon (http://www.omsketalon.ru).
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Vasiliy Grigoriev from "Vacuum technologies laboratory (http://e-beam.ru)".
  Version: 1.2.0

PROGRAM:
  JavaLikeCalc.JavaScript
  if(mdPass)	{
  	if(f_start) { f_err = EVAL; this.cnt.set(0, 0, 0, true); cnt_ = 0; tDl = 5; }
  	if((cnt=this.cnt.get()) != cnt_)	{ tDl = 5; cnt_ = cnt; }
  	else if(tDl > 0 && (tDl=tDl-1/f_frq) <= 0) {
  		this.err.set("1:"+tr("No a data"), 0, 0, true);
  		this.T.set(EVAL, 0, 0, true);
  		this.H.set(EVAL, 0, 0, true);
  		this.L.set(EVAL, 0, 0, true);
  		this.relSt.set(EVAL, 0, 0, true);
  	}
  	return;
  }

  //Set transport
  if(f_start)	tr = SYS.Transport.Serial.nodeAt("out_"+transport);
  if(!tr)	t_err = "1:"+tr("Serial output transport '%1' error.").replace("%1",transport);

  req = SYS.XMLNode("mess").setAttr("ProtIt","IT3").setAttr("addr",addr);

  SYS.messDebug("/IT3/TMPL",tr("Request: TRANSL_TEMP."));
  req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0xC3));
  tr.messIO(req, "UserProtocol");
  if(!(t_err=req.attr("err")).length && req.text().charCodeAt(0) == 0x85) {
  	cntrB = req.text().charCodeAt(3);
  	T = (req.text().charCodeAt(2)<<8)+req.text().charCodeAt(1);
  	T = T/((cntrB&0x8)?100:10);
  	relSt = (cntrB&0x1);
  	L = (cntrB&0x2);
  	H = (cntrB&0x4);
  	//SYS.messDebug("/IT3/TMPL",tr("Request: TRANSL_TEMP: "+req.text().length));
  }
  else {
  	T = H = L = EVAL_STR;
  	if(t_err.parse(1,":").toInt() == 8) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x00));
  		tr.messIO(req, "UserProtocol");
  	}
  }

  if(t_err.length) { SYS.messDebug("/IT3/TMPL",tr("Error response")+": "+t_err); f_err = t_err; }
  else f_err = "0";


ID: IVE_452HS_02
NAME: IVE-452HS-02
DESCR:
  Power supply of beam-electrons evaporator of "Plasma Tech" Ltd, from Moskov.
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Vasiliy Grigoriev from "Vacuum technologies laboratory (http://e-beam.ru)".

PROGRAM:
  JavaLikeCalc.JavaScript
  //Set transport
  if(f_start) {
  	addr_ = addr;
  	transport_ = transport;
  	COIA = COIA_ = COUA = COUA_ = COPA = COPA_ = DIA = DUA = DPA = DFA = EVAL_INT;
  	COM_DEW = COM_DEW_ = COM_OUT = COM_OUT_ = COM_DEP	= COM_DEP_ = COM_DEL = COM_DEL_ = COM_UF = COM_UF_ =
  					DKW = DKZ = DK = DE = EVAL_BOOL;
  	tr = SYS.Transport.nodeAt(transport,".");
  }

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.nodeAt(transport,".");
  	transport_ = transport;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else {
  	req = SYS.XMLNode("mess").setAttr("ProtIt","IVE_452HS_02").setAttr("addr",addr);

  	//Check for the address need to change
  	if(addr != addr_) {
  		hwReg = 0x00;
  		req.setAttr("err","2:"+tr("No connection")).setAttr("addr",addr_)
  			.setText(SYS.strFromCharCode(0x57,0x04,0x00,hwReg,hwReg,0x06,addr));
  		tr.messIO(req, "UserProtocol");
  		req.setText(SYS.strFromCharCode(0x57,0x04,0x00,hwReg,hwReg,0x08,0x00));
  		tr.messIO(req, "UserProtocol");
  		req.setAttr("addr", addr);
  		addr_ = addr;
  	}

  	//Check and write commands
  	if(COIA != COIA_ && !(t_err=req.attr("err")).length)	{
  		hwReg = 0x01;
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x57,0x04,0x00,hwReg,hwReg,COIA&0xFF,(COIA>>8)&0xFF));
  		tr.messIO(req, "UserProtocol");
  	}
  	if(COUA != COUA_ && !(t_err=req.attr("err")).length) {
  		hwReg = 0x02;
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x57,0x04,0x00,hwReg,hwReg,COUA&0xFF,(COUA>>8)&0xFF));
  		tr.messIO(req, "UserProtocol");
  	}
  	if(COPA != COPA_ && !(t_err=req.attr("err")).length) {
  		hwReg = 0x03;
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x57,0x04,0x00,hwReg,hwReg,COPA&0xFF,(COPA>>8)&0xFF));
  		tr.messIO(req, "UserProtocol");
  	}
  	if((COM_DEW != COM_DEW_ || COM_OUT != COM_OUT_ || COM_DEP != COM_DEP_ || COM_DEL != COM_DEL_ || COM_UF != COM_UF_) && !(t_err=req.attr("err")).length) {
  		tmp = 0;
  		if(COM_DEW)	tmp = tmp | 0x8000;
  		if(COM_OUT)	tmp = tmp | 0x4000;
  		if(COM_DEP)	tmp = tmp | 0x1000;
  		if(COM_DEL)	tmp = tmp | 0x0800;
  		if(COM_UF)	tmp = tmp | 0x0004;
  		hwReg = 0x15;
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x57,0x04,0x00,hwReg,hwReg,tmp&0xFF,(tmp>>8)&0xFF));
  		tr.messIO(req, "UserProtocol");
  	}

  	//Read data
  	if(!(t_err=req.attr("err")).length) {
  		SYS.messDebug("/IVE452HS02/TMPL",tr("Read all data."));
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x52,0x02,0x00,0x01,0x16));
  		tr.messIO(req, "UserProtocol");
  		if(!(t_err=req.attr("err")).length) {
  			if(req.text().length < (0x16*2+5))	req.setAttr("err", "10:"+tr("Reply is not full"));
  			else {
  				hwReg = 0x01; COIA = COIA_ = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				hwReg = 0x02; COUA = COUA_ = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				hwReg = 0x03; COPA = COPA_ = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				hwReg = 0x07; DIA = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				hwReg = 0x08; DUA = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				hwReg = 0x0E; DAC = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				hwReg = 0x10; DPA = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				hwReg = 0x11; DFA = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				hwReg = 0x15; tmp = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				COM_DEW = COM_DEW_ = tmp&0x8000;
  				COM_OUT = COM_OUT_ = tmp&0x4000;
  				COM_DEP = COM_DEP_ = tmp&0x1000;
  				COM_DEL = COM_DEL_ = tmp&0x0800;
  				COM_UF = COM_UF_ = tmp&0x0004;
  				hwReg = 0x16; tmp = (req.text().charCodeAt((hwReg-1)*2+6)<<8)+req.text().charCodeAt((hwReg-1)*2+5);
  				DKW = !(tmp&0x8); DKZ = !(tmp&0x4); DK = !(tmp&0x2); DE = tmp&0x1;
  			}
  		}
  	}
  }

  if(t_err.length) {
  	COIA = COIA_ = COUA = COUA_ = COPA = COPA_ = DIA = DUA = DAC = DPA = DFA = EVAL_INT;
  	COM_DEW = COM_DEW_ = COM_OUT = COM_OUT_ = COM_DEP	= COM_DEP_ = COM_DEL = COM_DEL_ = COM_UF = COM_UF_ = 
  					DKW = DKZ = DK = DE = EVAL_BOOL;
  	SYS.messDebug("/IVE452HS02/TMPL",tr("Error response")+": "+t_err);
  	f_err = t_err;
  }
  else f_err = "0";


ID: OPTRIS
NAME: OPTRIS CT/CTL
DESCR:
  OPTRIS CT/CTL communication interface of "Optris" GmbH, from Berlin.
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Vasiliy Grigoriev from "Vacuum technologies laboratory (http://e-beam.ru)".

PROGRAM:
  JavaLikeCalc.JavaScript
  //Set transport
  if(f_start) {
  	transport_ = transport;
  	Tproc = Thead = Tbox = Tact = eps = eps_ = trans = trans_ = EVAL_REAL;
  	spIll = spIll_ = EVAL_BOOL;
  	tr = SYS.Transport.nodeAt(transport,".");
  }

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.nodeAt(transport, ".");
  	transport_ = transport;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else {
  	req = SYS.XMLNode("mess").setAttr("ProtIt", "OPTRIS").setAttr("addr", addr).setAttr("cs", "1");

  	//Check and write
  	// Epsilon
  	if(eps != eps_ && !(t_err=req.attr("err")).length) {
  		epsH = eps*1000;
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x84,epsH/256,epsH%256));
  		tr.messIO(req, "UserProtocol");
  	}
  	// Transmission
  	if(trans != trans_ && !(t_err=req.attr("err")).length) {
  		transH = trans*1000;
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x85,transH/256,transH%256));
  		tr.messIO(req, "UserProtocol");
  	}
  	// Spot illumination
  	if(spIll != spIll_ && !(t_err=req.attr("err")).length) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0xA5,spIll));
  		tr.messIO(req, "UserProtocol");
  	}

  	//Read data
  	req.setAttr("cs", "0");
  	// Tproc
  	if(!(t_err=req.attr("err")).length) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x01));
  		tr.messIO(req, "UserProtocol");
  		Tproc = (!(t_err=req.attr("err")).length && req.text().length >= 2) ? (req.text().charCodeAt(0)*256+req.text().charCodeAt(1)-1000)/10 : EVAL_REAL;
  	}
  	// Thead
  	if(!(t_err=req.attr("err")).length) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x02));
  		tr.messIO(req, "UserProtocol");
  		Thead = (!(t_err=req.attr("err")).length && req.text().length >= 2) ? (req.text().charCodeAt(0)*256+req.text().charCodeAt(1)-1000)/10 : EVAL_REAL;
  	}
  	// Tbox
  	if(!(t_err=req.attr("err")).length) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x03));
  		tr.messIO(req, "UserProtocol");
  		Tbox = (!(t_err=req.attr("err")).length && req.text().length >= 2) ? (req.text().charCodeAt(0)*256+req.text().charCodeAt(1)-1000)/10 : EVAL_REAL;
  	}
  	// Tact
  	if(!(t_err=req.attr("err")).length) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x81));
  		tr.messIO(req, "UserProtocol");
  		Tact = (!(t_err=req.attr("err")).length && req.text().length >= 2) ? (req.text().charCodeAt(0)*256+req.text().charCodeAt(1)-1000)/10 : EVAL_REAL;
  	}
  	// IR epsilon
  	if(!(t_err=req.attr("err")).length) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x04));
  		tr.messIO(req, "UserProtocol");
  		eps = eps_ = (!(t_err=req.attr("err")).length && req.text().length >= 2) ? (req.text().charCodeAt(0)*256+req.text().charCodeAt(1))/1000 : EVAL_REAL;
  	}
  	// IR transmission
  	if(!(t_err=req.attr("err")).length) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x05));
  		tr.messIO(req, "UserProtocol");
  		trans = trans_ = (!(t_err=req.attr("err")).length && req.text().length >= 2) ? (req.text().charCodeAt(0)*256+req.text().charCodeAt(1))/1000 : EVAL_REAL;
  	}
  	// Spot illumination
  	if(!(t_err=req.attr("err")).length) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x25));
  		tr.messIO(req, "UserProtocol");
  		spIll = spIll_ = (!(t_err=req.attr("err")).length && req.text().length >= 1) ? req.text().charCodeAt(0) : EVAL_BOOL;
  	}
  }

  //Error set
  if(t_err.length) {
  	Tproc = Thead = Tbox = Tact = eps = eps_ = trans = trans_ = spIll = spIll_ = EVAL_REAL;
  	spIll = spIll_ = EVAL_BOOL;
  	SYS.messDebug("/OPTRIS/TMPL",tr("Error response")+": "+t_err);
  	f_err = t_err;
  }
  else f_err = "0";


ID: CTR
NAME: CTR 100, 101
uk#NAME: CTR 100, 101
DESCR:
  The RS232C Serial Interface permits the communication between the digital Oerlikon Leybold Vacuum CERAVAC, from Köln.
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Vasiliy Grigoriev from "Vacuum technologies laboratory (http://e-beam.ru)".

uk#DESCR:
  The RS232C Serial Interface permits the communication between the digital Oerlikon Leybold Vacuum CERAVAC, from Köln.
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Vasiliy Grigoriev from "Vacuum technologies laboratory (http://e-beam.ru)".

PROGRAM:
  JavaLikeCalc.JavaScript
  //Set transport
  if(f_start) {
  	transport_ = transport;
  	press = FSR_Mantissa = FSR_Exp = EVAL_REAL;
  	tr = SYS.Transport.nodeAt(transport, ".");
  }

  u_err = "";

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.nodeAt(transport, ".");
  	transport_ = transport;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else {
  	req = SYS.XMLNode("mess").setAttr("ProtIt","CTR");

  	//Read data
  	// F.S.R Mantisa
  	if(!(t_err=req.attr("err")).length && FSR_Mantissa.isEVal()) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x00,0x39,0x00));
  		tr.messIO(req, "UserProtocol");
  		if(!(t_err=req.attr("err")).length) {
  			if((cV=req.text().charCodeAt(5)) == 0) FSR_Mantissa = 1.0;
  			else if(cV == 1) FSR_Mantissa = 1.1;
  			else if(cV == 2) FSR_Mantissa = 2.0;
  			else if(cV == 3) FSR_Mantissa = 2.5;
  			else if(cV == 4) FSR_Mantissa = 5.0;
  		}
  	}
  	// F.S.R Exp
  	if(!(t_err=req.attr("err")).length && FSR_Exp.isEVal()) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x00,0x38,0x00));
  		tr.messIO(req, "UserProtocol");
  		if(!(t_err=req.attr("err")).length) {
  			if((cV=req.text().charCodeAt(5)) == 2) FSR_Exp = -1;
  			else if(cV == 3) FSR_Exp = 0;
  			else if(cV == 4) FSR_Exp = 1;
  			else if(cV == 5) FSR_Exp = 2;
  			else if(cV == 6) FSR_Exp = 3;
  		}
  	}
  	// Main value
  	if(!(t_err=req.attr("err")).length && !FSR_Mantissa.isEVal() && !FSR_Exp.isEVal()) {
  		req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x00,0x00,0x00));
  		tr.messIO(req, "UserProtocol");
  		if(!(t_err=req.attr("err")).length) {
  			press = ((req.text().charCodeAt(3)*256+req.text().charCodeAt(4))/32000)*FSR_Mantissa*pow(10,FSR_Exp);
  			//  Error process
  			cV = req.text().charCodeAt(2);
  			if(cV&0x7F) {
  				if(cV&0x01)	u_err += tr("RS232 synchronization error. ");
  				if(cV&0x02)	u_err += tr("Incorrect command, e.g. inadmissible address (syntax error). ");
  				if(cV&0x04)	u_err += tr("Inadmissible read command. ");
  				if(cV&0x08)	u_err += tr("SP1 status. ");
  				if(cV&0x10)	u_err += tr("SP2 status. ");
  			}
  			else {
  				//   Extended Error L-Byte
  				req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x00,0x36,0x00));
  				tr.messIO(req, "UserProtocol");
  				if(!(t_err=req.attr("err")).length) {
  					cV = req.text().charCodeAt(5);
  					if(cV&0x01)	u_err += tr("Atm. pressure out of range. ");
  					if(cV&0x02)	u_err += tr("Temperature out of range. ");
  					if(cV&0x10)	u_err += tr("Cal. mode wrong. ");
  					if(cV&0x20)	u_err += tr("Pressure underflow. ");
  					if(cV&0x40)	u_err += tr("Pressure overflow. ");
  					if(cV&0x80)	u_err += tr("Zero adjust warning. ");
  				}
  				//   Extended Error H-Byte
  				req.setAttr("err","2:"+tr("No connection")).setText(SYS.strFromCharCode(0x00,0x37,0x00));
  				tr.messIO(req, "UserProtocol");
  				cV = req.text().charCodeAt(5);
  				if(cV&0x01)	u_err += tr("PT1000 fault (CTR 101 only). ");
  				if(cV&0x02)	u_err += tr("Heaterblock overtemp. ");
  				if(cV&0x04)	u_err += tr("Electronic overtemp. ");
  				if(cV&0x08)	u_err += tr("Zero adjust error. ");
  			}
  		}
  	}

  	//Check and write commands
  	// Zero-adjust
  	if(!(t_err=req.attr("err")).length && zeroSet) {
  		req.setAttr("err", "2:"+tr("No connection")).setText(SYS.strFromCharCode(0x40,0x02,0x00));
  		tr.messIO(req, "UserProtocol");
  		if(!(t_err=req.attr("err")).length) zeroSet = false;
  	}

  	//Check and set poll mode
  	if((t_err=req.attr("err")).length && t_err.toInt() == 4) {
  		req.setAttr("err", "2:"+tr("No connection")).setText(SYS.strFromCharCode(0x10,0x00,0x01));
  		tr.messIO(req, "UserProtocol");
  	}
  }

  if(t_err.length) {
  	press = EVAL_REAL;
  	f_err = t_err + " " + u_err;
  }
  else f_err = "0: " + u_err;


ID: IEC60870
NAME: IEC-60870
DESCR:
  IEC 60870 part 5 is one of the IEC 60870 set of standards which define systems used for telecontrol (supervisory control and data acquisition) in electrical engineering and power system automation applications. Part 5 provides a communication profile for sending basic telecontrol messages between two systems, which uses permanent directly connected data circuits between the systems. The template implements part 104 (Ethernet transport) for client and followed services: STARTDT, STOPDT, TESTFR, Ack, C_IC_NA_1, C_CI_NA_1, C_SC_NA_1, M_SP_NA_1, M_ME_NB_1, C_CS_NA_1. For acquired and control data primarily used an object into attribute "items" for next the control as the object with the data provide as table, alarming and allowing set writable attributes. To the data control by attributes at once you can its describe into "itemsSet". Into the template for the first time used the non request mode of an output transport and free attributes creation wile performing.
  Version: 1.0.2
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Ustijancev Michael.

PROGRAM:
  JavaLikeCalc.JavaScript
  if(f_start)	{
  	transport_ = transport;
  	tr = SYS.Transport.nodeAt(transport,".");
  	if(tr) tr.start(false);
  	itemsSet_ = "";
  	tmRetr_ = tmRetr;
  	t1_ = t1__ = t2_ = t3_ = w_ = 0;
  	TESTFR_Act = false;
  	STARTDT_act = STARTDT_con = false;
  	bufIn = bufOut = "";
  	cntTx = cntRx = 0;
  	destAddr = addr.parse(0,".").toInt();
  	destOA = addr.parse(1,".").toInt();
  	//C_IC_NA_1_req = 0;
  	C_IC_NA_1 = C_SC_NA_1 = 0;
  	C_IC_NA_1con = C_CS_NA_1 = C_CS_NA_1con = C_CI_NA_1 = C_CI_NA_1con = false;
  	items = new Object();
  	oAVals = new Object();
  }

  //Items set changing process
  if(itemsSet != itemsSet_) {
  	for(off = 0; (iIt=itemsSet.parse(0,"\n",off)).length; ) {
  		iIt_tp = iIt.parse(0, ":");
  		iIt_IOA = iIt.parse(1, ":");
  		iIt_flgs = iIt.parse(2, ":");
  		iIt_nmBase = iIt.parse(3, ":");
  		iIt_sDscr = false;
  		if((iIt_EndIOA=iIt_IOA.indexOf("-")) >= 0) {
  			iIt_EndIOA = iIt_IOA.slice(iIt_EndIOA+1).toInt();
  			iIt_IOA = iIt_IOA.slice(0,iIt_EndIOA).toInt();
  		}
  		else { iIt_IOA = iIt_EndIOA = iIt_IOA.toInt(); iIt_sDscr = iIt_nmBase.length; }
  		if(iIt_tp == "ai")			{ iIt_nmBase = iIt_nmBase.length ? iIt_nmBase : "AI"; iIt_vtp = "integer,ro"; }
  		else if(iIt_tp == "di")	{ iIt_nmBase = iIt_nmBase.length ? iIt_nmBase : "DI"; iIt_vtp = "boolean,ro"; }
  		else if(iIt_tp == "do")	{ iIt_nmBase = iIt_nmBase.length ? iIt_nmBase : "DO"; iIt_vtp = "boolean"; }
  		else continue;
  		while(iIt_IOA <= iIt_EndIOA) {
  			aId = iIt_tp+iIt_IOA; aDscr = iIt_nmBase+(iIt_sDscr?"":"["+iIt_IOA+"]"); aWr = (iIt_tp == "do");
  			if(items[aId].isEVal()) { items[aId] = itW = new Object(); itW.descr = aDscr; itW.wr = aWr; itW.alarm = 0; }
  			if(iIt_flgs.indexOf("a") >= 0) {
  				this.attrAdd(aId, aDscr, iIt_vtp);
  				if(aWr)	oAVals[aId] = EVAL_INT;
  				this[aId].set(EVAL_INT, 0, 0, true);
  			}
  			iIt_IOA++;
  		}
  	}
  	itemsSet_ = itemsSet;
  }

  //Check for the transport change and connect
  t_err = "";
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.nodeAt(transport, ".");
  	transport_ = transport;
  	if(tr) tr.start(false);
  	itemsSet_ = "";
  	tmRetr_ = tmRetr;
  	STARTDT_act = false;
  	items = new Object();
  	oAVals = new Object();
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else if(!tr.start()) {
  	if(tmRetr_ >= tmRetr) {
  		tr.start(true);
  		bufIn = bufOut = itemsSet_ = "";
  		tmRetr_ = t1_ = t1__ = t2_ = t3_ = w_ = 0;
  	}
  	else tmRetr_ += 1/f_frq;
  	if(tr.start()) STARTDT_act = false;
  	else t_err = "1:"+tr("Output transport '%1' stoped.").replace("%1",transport);
  }
  else {
  	//Check and finish, U (STOPDT, Act)
  	if(f_stop && STARTDT_con) bufOut += SYS.strFromCharCode(0x68, 0x04, 0x10|0x03, 0, 0, 0);

  	//Send output buffer and read the transport for an input data
  	if(bufOut.length) SYS.messDebug("/IEC60870",tr("Good output sequence")+": "+SYS.strDecode(bufOut,"Bin"," "));
  	bufIn += tr.messIO(bufOut, -0.001);
  	bufOut = "";
  	//Input requests processing
  	while(bufIn.length) {
  		if(bufIn.length >= 2 && (bufIn.charCodeAt(0) != 0x68 || (seqSz=bufIn.charCodeAt(1)) > 253)) {
  			SYS.messDebug("/IEC60870",tr("Wrong sequence, rejected")+": "+SYS.strDecode(bufIn,"Bin"," "));
  			bufIn = "";
  			break;
  		}
  		if(bufIn.length < 6 || (bufIn.length-2) < seqSz)	break;	//Not full, wait

  		SYS.messDebug("/IEC60870",tr("Good input sequence")+": "+SYS.strDecode(bufIn.slice(0,seqSz+2),"Bin"," "));

  		cntRx_ = -1;
  		sB1 = bufIn.charCodeAt(2);
  		if((sB1&0x3) == 0x3 && (sB1&0x40))			TESTFR_Act = true;	//U (TESTFR, Act)
  		else if((sB1&0x3) == 0x3 && (sB1&0x80))	t1__ = 0;					//U (TESTFR, Con)
  		else if((sB1&0x3) == 0x3 && (sB1&0x08)) {	//U (STARTDT, Con)
  			STARTDT_con = true;
  			t1_ = t1__ = t2_ = t3_ = 0;
  			cntTx = cntRx = 0;
  			destAddr = addr.parse(0,".").toInt();
  			destOA = addr.parse(1,".").toInt();
  			C_IC_NA_1 = C_SC_NA_1 = 0;
  			C_CS_NA_1 = C_CI_NA_1 = false;
  		}
  		else if(STARTDT_con && (sB1&0x3) == 1)	cntRx_ = (bufIn.charCodeAt(5)>>1)*128 + (bufIn.charCodeAt(4)>>1);		//S (Ack)
  		else if(STARTDT_con && (sB1&0x1) == 0) {	//I
  			cntTx_ = bufIn.charCodeAt(3)*128 + (sB1>>1);
  			if(cntTx_ != cntRx)
  				t_err = "2:"+tr("Connection terminated by the input sequence broken, lost input packages, S(R)=%1, S(T)=%2").replace("%1",cntRx.toString()).replace("%2",cntTx_.toString());
  			cntRx_ = bufIn.charCodeAt(5)*128 + (bufIn.charCodeAt(4)>>1);
  			ASDU_id = bufIn.charCodeAt(6);
  			ASDU_els = bufIn.charCodeAt(7);			//7=SQ, 0...6=number
  			ASDU_reas = bufIn.charCodeAt(8);		//7=TEST, 6=P/N, 0...5=number
  			ASDU_addr = bufIn.charCodeAt(9);
  			ASDU_OA = bufIn.charCodeAt(11)*256 + bufIn.charCodeAt(10);
  			//destAddr = ASDU_addr, destOA = ASDU_OA;
  			cntRx = (cntRx+1)&0x7FFF;
  			t2_ = 1/f_frq;	
  			w_++;

  			if(ASDU_id == 100) {
  				if(ASDU_reas == 7)			C_IC_NA_1con = true;	//ActCon
  				else if(ASDU_reas == 10)	C_IC_NA_1 = -1;// 1;				//ActTerm, repeate after 1 second
  			}
  			else if(ASDU_id == 101) {
  				if(ASDU_reas == 7)			C_CI_NA_1con = true;	//ActCon
  				//else if(ASDU_reas == 10)	C_CI_NA_1 = false;		//ActTerm, repeate after some timeout
  			}
  			else if(ASDU_id == 103 && ASDU_reas == 7)	C_CS_NA_1con = true;
  			else if(ASDU_id == 1) {	//M_SP_NA_1, Single-point information
  				if(ASDU_els&0x80) SYS.messDebug("/IEC60870",tr("M_SP_NA_1: No the SQ mode implemented yet"));
  				else if((10+ASDU_els*4) != seqSz)	SYS.messDebug("/IEC60870",tr("M_SP_NA_1: Items number discrepancy to the package size"));
  				else for(iEl = 0, iOff = 12; iEl < ASDU_els; iEl++, iOff+=4) {
  					IOA = (bufIn.charCodeAt(iOff+2)<<16) + (bufIn.charCodeAt(iOff+1)<<8) + bufIn.charCodeAt(iOff);
  					SIQ = bufIn.charCodeAt(iOff+3);
  					aid = "di"+IOA;
  					if(items[aid].isEVal()) {
  						items[aid] = itW = new Object();
  						itW.descr = "DI["+IOA+"]";
  						itW.wr = false; itW.alarm = 0;
  					}
  					items[aid].val = SIQ&0x01;
  					items[aid].SIQ = SIQ;	//For a specific quality processing
  					if((aO=this[aid])) aO.set(items[aid].val, 0, 0, true);
  				}
  			}
  			else if(ASDU_id == 11) {	//M_ME_NB_1, Measured value, scaled value
  				if(ASDU_els&0x80) SYS.messDebug("/IEC60870",tr("M_ME_NB_1: No the SQ mode implemented yet"));
  				else if((10+ASDU_els*6) != seqSz)	SYS.messDebug("/IEC60870",tr("M_ME_NB_1: Items number discrepancy to the package size"));
  				else for(iEl = 0, iOff = 12; iEl < ASDU_els; iEl++, iOff+=6) {
  					IOA = (bufIn.charCodeAt(iOff+2)<<16) + (bufIn.charCodeAt(iOff+1)<<8) + bufIn.charCodeAt(iOff);
  					val = (bufIn.charCodeAt(iOff+4)<<8) + bufIn.charCodeAt(iOff+3);
  					if(val > 32767) val -= 65536;
  					SIQ = bufIn.charCodeAt(iOff+5);
  					aid = "ai"+IOA;

  					if(items[aid].isEVal()) {
  						items[aid] = itW = new Object();
  						itW.descr = "AI["+IOA+"]";
  						itW.wr = false; itW.alarm = 0;
  					}
  					items[aid].val = val;
  					items[aid].SIQ = SIQ;	//For a specific quality processing
  					if((aO=this[aid])) aO.set(items[aid].val, 0, 0, true);
  				}
  			}
  			else if(ASDU_id == 45) {	//C_SC_NA_1, Single-point confirm
  				if(ASDU_els&0x80) SYS.messDebug("/IEC60870", tr("C_SC_NA_1: No the SQ mode implemented yet"));
  				else if((10+ASDU_els*4) != seqSz)	SYS.messDebug("/IEC60870", tr("C_SC_NA_1: Items number discrepancy to the package size"));
  				else for(iEl = 0, iOff = 12; iEl < ASDU_els; iEl++, iOff+=4) {
  					IOA = (bufIn.charCodeAt(iOff+2)<<16) + (bufIn.charCodeAt(iOff+1)<<8) + bufIn.charCodeAt(iOff);
  					SIQ = bufIn.charCodeAt(iOff+3);
  					aid = "do" + IOA;
  					items[aid].val = SIQ&0x01;
  					items[aid].SIQ = SIQ;	//For a specific quality processing
  					if((aO=this[aid])) { aO.set(items[aid].val, 0, 0, true); oAVals[aid] = items[aid].val; }
  				}
  				C_SC_NA_1 = 0;
  			}
  			//else ...
  		}
  		if(cntRx_ >= 0 && cntRx_ == cntTx) t1_ = 0;

  		t3_ = 0;
  		bufIn = bufIn.slice(seqSz+2);
  	}
  	//Check and the service negotiation perform.
  	while(!t_err.length) {
  		if(TESTFR_Act) {
  			bufOut += SYS.strFromCharCode(0x68, 0x04, 0x80|0x03, 0, 0, 0);
  			TESTFR_Act = false;
  		}
  		else if(!STARTDT_act)	{	//U (STARTDT, Act);
  			bufOut += SYS.strFromCharCode(0x68, 0x04, 0x04|0x03, 0, 0, 0);
  			STARTDT_act = true; STARTDT_con = false;
  		}
  		else if(t1_ > t1)
  			t_err = "3:" + tr("Connection terminated by not acknowledge transmited package '%1' by timeout t1 (%2).").replace("%1",cntTx.toString()).replace("%2",t1.toFixed(2));
  		else if(t1__ > t1)
  			t_err = "4:" + tr("Connection terminated by not confirmed TEST package by timeout t1 (%1).").replace("%1",t1.toFixed(2));
  		else if(t3_ > t3) {						//U (TESTFR, Act);
  			bufOut += SYS.strFromCharCode(0x68, 0x04, 0x40|0x03, 0, 0, 0);
  			t3_ = 0; t1__ = 1/f_frq;
  		}
  		else if(t2_ > t2 || w_ >= w) {	//S (Ack)
  			bufOut += SYS.strFromCharCode(0x68, 0x04, 0x01, 0, (cntRx<<1)&0xFF, cntRx>>7);
  			t2_ = w_ = 0;
  		}
  		else if(STARTDT_con /*&& destAddr >= 0*/) {	//I
  			ASDU_ = "";
  			// Services process
  			if(C_IC_NA_1 > 0)	C_IC_NA_1 = max(0, C_IC_NA_1-1/f_frq);
  			else if(C_IC_NA_1 == 0) {
  				//Generic acquisition request (20)
  				ASDU_ = SYS.strFromCharCode(100, 0x01, 0x06, destAddr, destOA&0xFF, destOA>>8, 0x00, 0x00, 0x00, 0x14);
  				C_IC_NA_1 = -1; C_IC_NA_1con = false;
  			}
  			else if(!C_CI_NA_1) {
  				//Generic counters request (5)
  				ASDU_ = SYS.strFromCharCode(101, 0x01, 0x06, destAddr, destOA&0xFF, destOA>>8, 0x00, 0x00, 0x00, 0x05);
  				C_CI_NA_1 = true; C_CI_NA_1con = false;
  			}
  			else if(!C_CS_NA_1) {
  				//Time sync
  				tmMs = 0; tm = SYS.time(tmMs); tmMs = (tm%60)*1000+tmMs/1000;
  				tmMin = tmHour = tmDay = tmMonth = tmYear = tmWDay = tmIsDst = 0;
  				SYS.localtime(tm, 0, tmMin, tmHour, tmDay, tmMonth, tmYear, tmWDay, 0, tmIsDst);
  				ASDU_ = SYS.strFromCharCode(103, 0x01, 0x06, destAddr, destOA&0xFF, destOA>>8, 0, 0, 0, tmMs&0xFF, tmMs>>8, tmMin, tmHour|(tmIsDst?0x80:0), tmDay|((tmWDay?tmWDay:7)<<5), tmMonth+1, tmYear-2000);
  				C_CS_NA_1 = true; C_CS_NA_1con = false;
  			}
  			else if((C_SC_NA_1=max(0,C_SC_NA_1-1/f_frq)) == 0) {
  				//Check for commands set, C_SC_NA_1 (45)
  				cItN = 0; cItSeq = "";
  				// By attributes
  				for(iIt in oAVals)
  					if((aO=this[iIt]) && !(aOval=aO.get()).isEVal() && aOval != oAVals[iIt] && !cItN) {
  						IOA = iIt.slice(2).toInt();
  						cItSeq += SYS.strFromCharCode(IOA&0xFF, (IOA>>8)&0xFF, IOA>>16, aOval?0x01:0);
  						//oAVals[iIt] = aOval;
  						cItN++;
  					}
  				// By items object
  				for(iIt in items)
  					if((aO=items[iIt]) && !(aOval=aO.set).isEVal() && !cItN) {
  						IOA = iIt.slice(2).toInt();
  						cItSeq += SYS.strFromCharCode(IOA&0xFF, (IOA>>8)&0xFF, IOA>>16, aOval.toInt()?0x01:0);
  						aO.set = EVAL_BOOL;
  						cItN++;
  					}
  				// Finish the request
  				if(cItN) {
  					ASDU_ = SYS.strFromCharCode(45, cItN, 0x06, destAddr, destOA&0xFF, destOA>>8) + cItSeq;
  					C_SC_NA_1 = 1;	//After one second repeat
  				}
  			}

  			// Append header and place to output
  			if(ASDU_.length) {
  				bufOut += SYS.strFromCharCode(0x68, 4+ASDU_.length, (cntTx<<1)&0xFF, cntTx>>7, (cntRx<<1)&0xFF, cntRx>>7) + ASDU_;
  				cntTx = (cntTx+1)&0x7FFF;
  				t1_ = 1/f_frq;
  				//t2_ = w_ = 0;
  			} else break;
  		}
  		else break;
  	}

  	if(t1_)		t1_ += 1/f_frq;
  	if(t1__)	t1__ += 1/f_frq;
  	if(t2_)		t2_ += 1/f_frq;
  	t3_ += 1/f_frq;
  }

  //Error set
  if(t_err.length) {
  	if(tr && tr.start()) tr.start(false);
  	if(f_err != t_err) {
  		items = new Object();
  		oAVals = new Object();
  		aLs = this.nodeList("a_");
  		for(iA = 0; iA < aLs.length; iA++)
  			if((aPref=aLs[iA].slice(2,4)) == "di" || aPref == "do" || aPref == "ai")
  				this[aLs[iA].slice(2)].set(EVAL_INT, 0, 0, true);
  		SYS.messDebug("/IEC60870", tr("Error")+": "+t_err);
  	}
  	f_err = t_err;
  }
  else f_err = "0";


ID: PCF8591
NAME: I2C: PCF8591
DESCR:
  I2C 8-bit 4xA/D and D/A converter. Connect through a Serial output transport into the I2C mode.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.0.1

PROGRAM:
  JavaLikeCalc.JavaScript
  //Set transport
  if(f_start) {
  	f_err = "0";
  	transport_ = transport;
  	tr = SYS.Transport.Serial["out_"+transport];
  }

  t_err = "0";

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.Serial["out_"+transport];
  	transport_ = transport;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else if(addr < 0 || addr > 119)	t_err = "2:"+tr("Device address '%1' out of range [0...119].").replace("%1",addr);
  else {
  	for(i = 0; i < 4 && !t_err.toInt(); i++) {
  		//Select next channel and the output
  		tr.messIO(SYS.strFromCharCode(addr,0x40|((i+1)&0x3),255*max(0,min(1,ao/vRef))), 0, 0);
  		SYS.sleep(1e-3);
  		rez = tr.messIO("", 0, 1);
  		if(rez.length)	arguments["ai"+i] = vRef*(rez.charCodeAt(0)/255);
  		else t_err = "3:"+tr("No read result.");
  	}
  }

  if(t_err.toInt() && !f_err.toInt())
  	for(i = 0; i < 4; i++)
  		arguments["ai"+i] = EVAL;

  f_err = t_err;


ID: SSCP
NAME: Shark Slave Communication Protocol
uk#NAME: Shark Slave Communication Protocol
DESCR:
  Shark Slave Communication Protocol from EnergoCentrum PLUS, s.r.o.
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Costumer Faster CZ (http://faster.cz)
  Version: 0.6.2

uk#DESCR:
  Shark Slave Communication Protocol from EnergoCentrum PLUS, s.r.o.
  Author: Roman Savochenko <rom_as@oscada.org>
  Sponsored: Costumer Faster CZ (http://faster.cz)

PROGRAM:
  JavaLikeCalc.JavaScript
  //Same request to the device
  function req(tr, addr, func, data) {
  	req = SYS.strFromCharCode(addr, (func>>8)&0xFF, func&0xFF, (data.length>>8)&0xFF, data.length&0xFF) + data;
  	//SYS.messInfo("/SSCP",tr("Request")+": "+SYS.strDecode(req,"Bin"," "));
  	resp = tr.messIO(req);
  	while(resp.length && (resp.length < 5 || (resp.length-5) < ((resp.charCodeAt(3)<<8)|resp.charCodeAt(4))) &&
  		(tresp=tr.messIO("")).length) resp += tresp;
  	//SYS.messInfo("/SSCP",tr("Response")+": "+SYS.strDecode(resp,"Bin"," "));
  	data = resp;
  	if(resp.length < 5)
  		return tr("3:No a response or the response short.");
  	if((resp.length-5) < ((resp.charCodeAt(3)<<8)|resp.charCodeAt(4)))
  		return tr("3:Incomplete response.");
  	if(resp.charCodeAt(0) != addr)	return tr("4:Invalid host's address received.");
  	func_ = ((resp.charCodeAt(1)&0xFF)<<8) | resp.charCodeAt(2);
  	if(func_ == 0xfffe)						return tr("4:Unknown function.");
  	if(func_ == 0xffff)						return tr("4:Insufficient rights.");
  	if((func_&0x3FFF) != func)			return tr("4:Invalid function received.");
  	if((func_&0xC000) != 0x8000) {
  		opErr = tr("5:Operation error.");
  		if(resp.length >= 9) {
  			errCod = (resp.charCodeAt(5)<<24) | (resp.charCodeAt(6)<<16) | (resp.charCodeAt(7)<<8) | resp.charCodeAt(8);
  			if(errCod == 0x0101)		opErr += " "+tr("Wrong login.");
  			else if(errCod == 0x103)	opErr += " "+tr("No such variable.");
  			else if(errCod == 0x112)	opErr += " "+tr("Size mismatch.");
  			//... Append here for needs
  			else opErr += " "+tr("Unknown error %1.").replace("%1",errCod.toString());
  		}
  		if(resp.length >= 17)	opErr += " "+tr("Destination:")+" "+SYS.strDecode(resp.slice(9),"Bin","")+"h";
  		return opErr;
  	}
  	data = resp.slice(5);
  	return "0";
  }

  //Set transport and init
  if(f_start) {
  	transport_ = transport;
  	tr = SYS.Transport.Sockets["out_"+transport];
  	vlist = new Object();
  	prcVList = new Array();
  	isLogin = false;
  	toLoadVarLsts = true;
  	aSelList = false;
  	list_ = "";
  }
  if(f_stop) return;

  t_err = "0";

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.Sockets["out_"+transport];
  	transport_ = transport;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else if(addr < 0 || addr > 255)
  	t_err = "2:"+tr("Address '%1' out of range [0...255].").replace("%1",addr.toString());
  else {
  	//Generic information update.
  	if(toLoadVarLsts) {
  		toLoadVarLsts = false;
  		fLs = SYS.system("ls -1 "+listsDir+"/*.vlist");
  		for(off = 0; (fln=fLs.parse(0,"\n",off)).length; ) {
  			//stTm = SYS.time();
  			fl = SYS.fileRead(fln);
  			//fl = fl.split("\x0D\x0A");
  			//for(iL = 0; iL < fl.length; iL++) {
  				//ln = fl[iL];
  			for(off1 = 0; (ln=fl.parse(0,"\x0D\x0A",off1)).length; ) {
  			//for(off1 = 0; (ln=Special.FLibSYS.strParse(fl,0,"\x0D\x0A",off1)).length; ) {
  				off2 = 0;
  				vid = ln.parse(0, ";", off2);
  				if(vid == "Project" || !(tVl=ln.parse(0,";",off2)).length) continue;
  				vid += ":"+tVl;
  				//SYS.messInfo("SSCP","vid="+vid);
  				vlist[vid] = vO = new Object();
  				vO.Type = ln.parse(0, ";", off2);
  				vO.CommUid = ln.parse(0, ";", off2).toInt();
  				vO.Offset = ln.parse(0, ";", off2).toInt();
  				vO.Length = ln.parse(0, ";", off2).toInt();
  				vO.ParentTypeFamily = ln.parse(0, ";", off2);
  				vO.HistoryId = ln.parse(0, ";", off2);
  			}
  			//SYS.messInfo("SSCP", "Time="+(SYS.time()-stTm)+"s; length="+fl.length);
  		}
  		fl = selLst = "";
  		//for(tVl in vlist) selLst += tVl+";";
  		//this.attrAdd("selList", tr("Appending variable"), "string|sel", selLst+"\n"+selLst);
  		//aSelList = this.selList;
  		//aSelList.set("");
  		for(tVl in vlist) selLst += tVl+"\n";
  		this.attrAdd("selList", tr("Allowed variables"), "text|ro");
  		aSelList = this.selList;
  		aSelList.set(selLst,0,0,true);
  	}
  	//Check for select a varable and append it to the processing list
  	/*if(aSelList && (tVl=aSelList.get()).length) {
  		if(list.indexOf(tVl) == -1)
  			list += ((list.length && list[list.length-1] != "\n")?"\n":"")+ tVl+"\n";
  		aSelList.set("");
  	}*/
  	//The processing variables list update/form
  	if(list != list_) {
  		list_ = list;
  		prcVList = new Array();
  		for(off = 0; (vid=list.parse(0,"\n",off)).length; ) {
  			if((vO=vlist[vid]).isEVal()) continue;
  			prcVList.push(vO);
  			vO.aId = vid.replace(new RegExp("[\\.\\:]+","g"),"_").replace(new RegExp("[\\$\\-]+","g"),"");
  			vTp = "string";
  			if(vO.Type.indexOf("bool") != -1)			vTp = "boolean";
  			else if(vO.Type.indexOf("real") != -1)	vTp = "real";
  			else if(vO.Type.indexOf("int") != -1)		vTp = "integer";
  			this.attrAdd(vO.aId, vid, vTp+"|ro");
  			vO.aO = this[vO.aId];
  			//SYS.messInfo("/SSCP","aId="+vO.aId);
  		}
  	}

  	//Same requests
  	if(!isLogin) {
  		io = SYS.strFromCharCode(0x01, (maxDtFrm>>8)&0xFF, maxDtFrm&0xFF, user.length) +
  				user + SYS.strFromCharCode(0x10) + Special.FLibSYS.MD5(pass);
  		if(!(t_err=req(tr,addr,0x0100,io)).toInt()) {
  			verPrt = io.charCodeAt(0);
  			maxDtFrmServ = (io.charCodeAt(1)<<8) | io.charCodeAt(2);
  			isLogin = true;
  		}
  	}
  	if(isLogin && !t_err.toInt()) {
  		for(iV0 = iV1 = 0; iV0 < prcVList.length; iV0 = iV1) {
  			frmSz = frmSzServ = 0;
  			io = Special.FLibSYS.IO("", "", "b");
  			io.wr(0x80);
  			for(iV1 = iV0; iV1 < prcVList.length; iV1++) {
  				vO = prcVList[iV1];
  				frmSz += vO.Length; frmSzServ += 12;
  				if(frmSz >= maxDtFrm || frmSzServ >= maxDtFrmServ) break;
  				io.wr(vO.CommUid, "uint32").wr(vO.Offset, "uint32").wr(vO.Length, "uint32");
  			}
  			//SYS.messInfo("/SSCP","req="+SYS.strDecode(io.string,"Bin"," "));
  			t_err = req(tr, addr, 0x0500, io.string); io.pos = 0;
  			//SYS.messInfo("/SSCP","resp="+SYS.strDecode(io.string,"Bin"," "));
  			for(iV2 = iV0; iV2 < iV1; iV2++) {
  				vO = prcVList[iV2];
  				//SYS.messInfo("/SSCP","aId="+vO.aId+"; pos="+io.pos);
  				if(t_err.toInt()) tVl = EVAL;
  				else {
  					if(vO.Type.indexOf("bool") != -1 && vO.Length == 1)
  						tVl = io.read("int8", 1);
  					else if(vO.Type.indexOf("real") != -1 && (vO.Length == 4 || vO.Length == 8))
  						tVl = io.read((vO.Length==8)?"double":"float", 1);
  					else if(vO.Type.indexOf("int") != -1 && (vO.Length == 2 || vO.Length == 4))
  						tVl = io.read((vO.Length==4)?"int32":"int16", 1);
  					else if(vO.Type.indexOf("dt") != -1 && vO.Length == 8) {
  						tVl = io.read("int64", 1);
  						tVl = SYS.strftime(tVl*1e-7-62135596800) + "." + (tVl%10000000).toString(10,7);
  					}
  					else if(vO.Type.indexOf("time") != -1 && vO.Length == 8) {
  						tm = io.read("int64",1)*1e-7;
  						lev = 0;
  						days = floor(tm/(24*60*60));
  						hours = floor(tm/(60*60))%24;
  						mins = floor(tm/(60))%60;
  						usec = 1e6 * (tm - days*24*60*60 - hours*60*60 - mins*60);
  						tVl = "";
  						if(days)	{ tVl += days+tr("day"); lev = max(lev,6); }
  						if(hours)	{ tVl += (tVl.length?" ":"")+hours+tr("hour"); lev = max(lev,5); }
  						if(mins && lev < 6)	{ tVl += (tVl.length?" ":"")+mins+tr("min"); lev = max(lev,4); }
  						if((1e-6*usec) > 0.5 && lev < 5)		{ tVl += (tVl.length?" ":"")+(1e-6*usec).toPrecision(3)+tr("s"); lev = max(lev,3); }
  						else if((1e-3*usec) > 0.5 && !lev)	{ tVl += (tVl.length?" ":"")+(1e-3*usec).toPrecision(4)+tr("ms"); lev = max(lev,2); }
  						else if(usec > 0.5 && !lev)				{ tVl += (tVl.length?" ":"")+usec.toPrecision(4)+tr("us"); lev = max(lev,1); }
  						else if(!lev)	tVl += (tVl.length?" ":"")+(1e3*usec).toPrecision(4)+tr("ns");
  					}
  					else tVl = SYS.strDecode(io.read("char", vO.Length), "Bin", " ");;
  				}
  				vO.aO.set(tVl, 0, 0, true);
  			}
  		}
  	}
  }

  f_err = t_err;


ID: 1W_DS9097U
NAME: One Wire by DS9097U
uk#NAME: One Wire by DS9097U
DESCR:
  One Wire sensors bus implementing by 1Wire-adapter DS9097U. Supported direct and parasite powering for the temperature sensors.
  Supported 1Wire-devices: DS1820, DS1820/DS18S20/DS1920 (not tested), DS1822 (not tested), DS2413, DS2408, DS2450, DS2438.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.2.0

PROGRAM:
  JavaLikeCalc.JavaScript
  //Functions
  function reset(tr) {
  	req = (isData?SYS.strFromCharCode(0xE3):"") +
  				SYS.strFromCharCode(0xC5);	//CMD_COMM(0x81) | FUNCTSEL_RESET(0x40) | SPEEDSEL_FLEX(0x04)
  	isData = false;
  	resp = tr.messIO(req);
  	return (resp.charCodeAt(0)&0x03) == 0x01;	//RB_PRESENCE
  }

  function io(tr, mess, bits) {
  	if(bits == EVAL) {
  		req = isData ? "" : SYS.strFromCharCode(0xE1);	//MODE_DATA
  		isData = true;
  		for(iB = 0; iB < mess.length; iB++) {
  			req += SYS.strFromCharCode(tVl=mess.charCodeAt(iB));
  			if(tVl == 0xE3) req += SYS.strFromCharCode(0xE3);	//duplication to the COMMAND mode
  		}
  		for(resp = tr.messIO(req); resp.length && resp.length < mess.length && (tresp=tr.messIO("")).length; resp += tresp) ;
  		return resp;
  	}
  	else {
  		req = (isData?SYS.strFromCharCode(0xE3):"") + SYS.strFromCharCode(0x3F);	//MODE_COMMAND, CMD_CONFIG(0x01) | PARMSEL_5VPULSE(0x30) | PARMSET_infinite(0x0E)
  		isData = false;
  		for(iB = 0; iB < ceil(bits/8); iB++) {
  			vB = mess.charCodeAt(iB);
  			bB = ((iB+1)*8 > bits) ? bits-floor(bits/8)*8 : 8;
  			for(iBi = 0; iBi < bB; iBi++)
  				//{BITPOL_ONE(0x10)|BITPOL_ZERO(0x00)}|CMD_COMM(0x81)|FUNCTSEL_BIT(0x00)|SPEEDSEL_FLEX(0x04)|{PRIME5V_TRUE(0x02)|PRIME5V_FALSE(0x00)}
  				req += SYS.strFromCharCode(((vB&(1<<iBi))?0x10:0x00)|0x85/*|((iB==(ceil(bits/8)-1)&&iBi==(bB-1))?0x02:0x00)*/);
  		}
  		for(resp = tr.messIO(req); resp.length && resp.length < (bits+1) && (tresp=tr.messIO("")).length; resp += tresp) ;
  		rez = "";
  		if(resp.length && !(resp.charCodeAt(0)&0x81))
  			for(iR = 1;  iR < resp.length; ) {
  				vB = 0;
  				for(ib = 0; ib < 8 && iR < resp.length; iR++, ib++)
  					if(resp.charCodeAt(iR)&1) vB = vB | (1<<ib);
  				rez += SYS.strFromCharCode(vB);
  			}
  	}
  	return rez;
  }

  function scan(tr, sn, lstDiscr) {
  	if(!reset(tr)) return "";
  	
  	//Set the bits in the added buffer
  	asn = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  	for(i = 0; lstDiscr >= 0 && i < 64; i++)
  		if((i < (lstDiscr-1) && sn[floor(i/8)]&(1<<(i%8))) || i == (lstDiscr-1))
  			asn[(i*2+1)/8] = asn[(i*2+1)/8] | (1<<((i*2+1)%8));

  	req = isData ? "" : SYS.strFromCharCode(0xE1);	//MODE_DATA
  	req += SYS.strFromCharCode(0xF0, 0xE3, 0xB5, 0xE1,
  				asn[0], asn[1], asn[2], asn[3], asn[4], asn[5], asn[6], asn[7],
  				asn[8], asn[9], asn[10], asn[11], asn[12], asn[13], asn[14], asn[15],
  				0xE3, 0xA5);
  	isData = false;
  	for(resp = tr.messIO(req); resp.length && resp.length < 17 && (tresp=tr.messIO("")).length; resp += tresp) ;

  	tmpLastDesc = -1;
  	for(i = 0; i < 64; i++) {
  		if(resp.charCodeAt(floor((i*2+1)/8)+1)&(1<<((i*2+1)%8)))	sn[floor(i/8)] = sn[floor(i/8)] | (1<<(i%8));
  		else sn[floor(i/8)] = sn[floor(i/8)] & (~(1<<(i%8)));
  		// Check LastDiscrepancy
  		if((resp.charCodeAt(floor((i*2)/8)+1)&(1<<((i*2)%8))) && !(resp.charCodeAt(floor((i*2+1)/8)+1)&(1<<((i*2+1)%8))))
  			tmpLastDesc = i + 1;
  	}

  	rez = "";
  	for(iB = 0; iB < 8; iB++) rez += SYS.strFromCharCode(sn[iB]);
  	if(sn[0] && lstDiscr != 63 && !Special.FLibSYS.CRC(rez,0x8C,8,0))	lstDiscr = tmpLastDesc;
  	else { rez = ""; lstDiscr = 0; }

  	return rez;
  }

  //Set transport and init
  if(f_start) {
  	tmResc_ = 0;
  	devLs = new Object();
  	transport_ = transport;
  	tr = SYS.Transport.Serial["out_"+transport];
  	DS2480 = isData = false;
  }
  if(f_stop) {
  	for(var devID in devLs) {
  		if((dO=devLs[devID]).isEVal()) continue;
  		aLs = dO.dP.nodeList("a_");
  		for(iA = 0; iA < aLs.length; iA++)
  			if(!dO.dP[aLs[iA]].isCfg()) dO.dP[aLs[iA]].set(EVAL, 0, 0, true);
  	}
  	devLs = tr = false;
  	return;
  }

  t_err = "0";

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.Serial["out_"+transport];
  	transport_ = transport;
  	DS2480 = false;
  }
  //Try DS2480
  if(tr && !DS2480)	{
  	tr.addr(tr.addr().parse(0,":")+":9600:8N1");	tr.timings("500:20");
  	if(tr.start(true)) {
  		tr.sendbreak(); SYS.sleep(2e-3);
  		tr.messIO(SYS.strFromCharCode(0xC1));	SYS.sleep(4e-3);	//Send timing byte
  		//PDSRC=1.37Vus; W1LT=10us; DSO/WORT=8us;
  		//read the baud rate (to test command block); do 1 bit operation (to test 1-Wire block)
  		req = SYS.strFromCharCode(0x17, 0x45, 0x5B, 0x0F, 0x91);
  		for(resp = tr.messIO(req); resp.length && resp.length < 5 && (tresp=tr.messIO("")).length; resp += tresp) ;
  		if(resp.length == 5 && (resp.charCodeAt(3)&0xF1) == 0x00 && (resp.charCodeAt(3)&0x0E) == 0x00/*9600*/ &&
  				(resp.charCodeAt(4)&0xF0) == 0x90 && (resp.charCodeAt(4)&0x0C) == 0x00/*9600*/)
  			DS2480 = true;
  	}
  	isData = false;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else if(!DS2480)	t_err = "2:"+tr("DS2480 is not detected.");
  else {
  	//Generic information update.
  	if(f_start || (tmResc && (tmResc_=tmResc_-1/f_frq) <= 0)) {
  		tmResc_ = tmResc;
  		tmSc = SYS.time();
  		// Check for power
  		if(!reset(tr) ||
  		 	io(tr,(req=SYS.strFromCharCode(0xCC))) != req ||
  			io(tr,(req=SYS.strFromCharCode(0xB4))) != req ||
  			!(resp=io(tr,SYS.strFromCharCode(1),1)).length) power = EVAL;
  		else power = resp.charCodeAt(0);
  		// Scan for allowed devices on the bus.
  		sn = new Array(0, 0, 0, 0, 0, 0, 0, 0);
  		for(devID = "start", lstDiscr = 0; devID.length && lstDiscr >= 0; ) {
  			if((devID=scan(tr,sn,lstDiscr)).length)	{
  				//SYS.messInfo("OneWire","lstDiscr="+lstDiscr+"; devID="+SYS.strDecode(devID,"Bin"," "));
  				if((dO=devLs[devID]).isEVal()) {
  					devLs[devID] = dO = new Object();
  					devFamily = devID.charCodeAt(0); devNm = tr("1W device"); dO.isT = false;
  					if(devFamily == 0x10)			{ devNm = "DS1820/DS18S20/DS1920"; dO.isT = true; }
  					else if(devFamily == 0x20)	devNm = "DS2450";		//4AI
  					else if(devFamily == 0x22)	{ devNm = "DS1822"; dO.isT = true; }
  					else if(devFamily == 0x26)	devNm = "DS2438";		//SmartBat
  					else if(devFamily == 0x28)	{ devNm = "DS18B20"; dO.isT = true; }
  					else if(devFamily == 0x29)	devNm = "DS2408";		//8DIO
  					else if(devFamily == 0x3A)	devNm = "DS2413";		//2DIO

  					// Create the device's parameter object
  					decId = SYS.strDecode(devID,"Bin","");
  					SYS.cntrReq(SYS.XMLNode("add").setAttr("path",this.nodePath()+"/%2fbr%2fprm_").setAttr("id",decId).setText(devNm+": "+decId));
  					SYS.cntrReq(SYS.XMLNode("set").setAttr("path",this.nodePath()+"/prm_"+decId+"/%2fprm%2fst%2fen").setText("1"));
  					// Create the device's proper attributes
  					dO.dP = dP = this["prm_"+decId];
  					if(dO.isT) {	//Temperature
  						dP.attrAdd("val", tr("Temperature, °С"), "real|ro");
  						dP.attrAdd("m", tr("User cell [0...65535]"), "integer");
  						dP.attrAdd("res", tr("Resolution")+" [9...12]", "integer");
  					}
  					else if(devFamily == 0x20)		//DS2450
  						for(iN = 0; iN < 4; iN++) {
  							dP.attrAdd("ai"+iN, tr("AI, V")+iN, "real|ro");
  							dP.attrAdd("res"+iN, tr("Resolution")+iN+" [1...16]", "integer");
  							dP.attrAdd("md"+iN, tr("Mode")+iN, "integer|sel", "0;1;2\n2.55V;5.10V;DO");
  							dP.attrAdd("do"+iN, tr("DO")+iN, "boolean");
  						}
  					else if(devFamily == 0x26) {	//DS2438
  						dP.attrAdd("t", tr("Temperature, °С"), "real|ro");
  						dP.attrAdd("v", tr("Voltage, V"), "real|ro");
  						dP.attrAdd("i", tr("Current, A"), "real|ro");
  						dP.attrAdd("ICA", tr("Current Accumulator"), "integer");
  						dP.attrAdd("thr", tr("Accumulation threshold"), "integer|sel", "0;1;2;3\nNone;±2LSB;±4LSB;±8LSB");
  						dP.attrAdd("ETM", tr("Elapsed time meter"), "integer");
  						dP.attrAdd("TM_DISC", tr("Disconnect time"), "integer");
  						dP.attrAdd("TM_END", tr("End of charge time"), "integer");
  						dP.attrAdd("OFF", tr("Current Offset"), "integer");
  						dP.attrAdd("IAD", tr("Enable Current A/D"), "boolean");
  						dP.attrAdd("CA", tr("Enable Current Accumulator"), "boolean");
  						dP.attrAdd("EE", tr("Enable Current Accumulator Shadow"), "boolean");
  						dP.attrAdd("AD", tr("Voltage A/D (0-VAD,1-VDD)"), "boolean");
  					}
  					else if(devFamily == 0x29)		//DS2408
  						for(iD = 0; iD < 8; iD++) {
  							dP.attrAdd("di"+iD, tr("DI")+iD, "boolean|ro");
  							dP.attrAdd("do"+iD, tr("DO")+iD, "boolean");
  						}
  					else if(devFamily == 0x3A)		//DS2413
  						for(iD = 0; iD < 2; iD++) {
  							dP.attrAdd("di"+iD, tr("DI")+iD, "boolean|ro");
  							dP.attrAdd("do"+iD, tr("DO")+iD, "boolean");
  						}
  				}
  				if(dO.tmSc == tmSc)	break;	//Somthing wrong into the scan but repeat, interruption
  				dO.tmSc = tmSc;
  				dO.try = tryEVAL;
  			}
  		}
  		//Check for removed devices
  		for(devID in devLs) {
  			if((dO=devLs[devID]).isEVal()) continue;
  			if(dO.tmSc != tmSc)	{
  				devLs[devID] = EVAL;
  				aLs = dO.dP.nodeList("a_");
  				for(iA = 0; iA < aLs.length; iA++)
  					if(!dO.dP[aLs[iA]].isCfg())	dO.dP[aLs[iA]].set(EVAL, 0, 0, true);
  			}
  		}
  	}
  	else {
  		//Process devices for reading current value and set modifable
  		for(devID in devLs) {
  			if((dO=devLs[devID]).isEVal()) continue;
  			devFamily = devID.charCodeAt(0);
  			if(dO.isT) {	//Temperature
  				dP = dO.dP;
  				//SYS.messInfo("OneWire","devID="+SYS.strDecode(devID,"Bin"," "));
  				//Check for a modifications
  				isMdf = false;
  				m_ = dP.m.get(), res_ = max(9,min(12,dP.res.get()));
  				if(!dO.m.isEVal() && !dO.res.isEVal() && (m_ != dO.m || res_ != dO.res)) {
  					//Set scratchpad
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x4E,m_&0xFF,(m_>>8)&0xFF,((res_-9)<<5)|0x1F))) != req) continue;
  					//Copy scratchpad part to the EEPROM
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x48))) != req) continue;
  					isMdf = true;
  				}

  				//Read current
  				// Call the transmission
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x44))) != req) continue;
  				if(!power) SYS.sleep(0.094*pow(2,(dO.res.isEVal()?12:dO.res)-9));
  				// Get scratchpad
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				/*out*/io(tr, SYS.strFromCharCode(0xBE));
  				resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  				//SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," "));
  				if(!Special.FLibSYS.CRC(resp,0x8C,8,0)) {
  					val = resp.charCodeAt(1)*256 + resp.charCodeAt(0);
  					if(val > 32767) val -= 65536;
  					dP.val.set(val/16, 0, 0, true);
  					if(dO.m.isEVal() || dO.res.isEVal() || isMdf) {
  						dO.m = resp.charCodeAt(3)*256 + resp.charCodeAt(2); dP.m.set(dO.m, 0, 0, true);
  						dO.res = ((resp.charCodeAt(4)>>5)&0x3)+9; dP.res.set(dO.res, 0, 0, true);
  					}
  					dO.try = 0;
  				}
  				else if((dO.try=dO.try+1) > tryEVAL) {
  					dP.val.set(EVAL, 0, 0, true); dP.m.set(EVAL, 0, 0, true); dP.res.set(EVAL, 0, 0, true);
  					dO.m = dO.res = EVAL;
  				}
  			}
  			else if(devFamily == 0x20) {	//DS2450
  				dP = dO.dP;
  				//Check for a modifications
  				for(iN = 0; iN < 4; iN++) {
  					if(dO["st1"+iN].isEVal())	continue;
  					if((tRes=max(0,min(16,dP["res"+iN].get()))) == 16)	tRes = 0;
  					tSt = (dO["st1"+iN]&(~0xCF)) + tRes + ((dP["md"+iN].get()==2)?0x80:0) + (dP["do"+iN].get()?0x40:0);
  					if(tSt != dO["st1"+iN]) {	//Same write and check the result
  						if(!reset(tr)) continue;
  						if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  						if(io(tr,(req=SYS.strFromCharCode(0x55,8+iN*2,0,tSt))) != req) continue;
  						resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF));
  						if(((~((resp.charCodeAt(1)<<8) + resp.charCodeAt(0)))&0xFFFF) == Special.FLibSYS.CRC(req,0xA001,16,0) && resp.charCodeAt(2) == tSt)
  							dO["st1"+iN] = tSt;
  					}
  					tSt = (dO["st2"+iN]&(~0x01)) + (dP["md"+iN].get()?1:0);
  					if(tSt != dO["st2"+iN]) {	//Same write and check the result
  						if(!reset(tr)) continue;
  						if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  						if(io(tr,(req=SYS.strFromCharCode(0x55,8+iN*2+1,0,tSt))) != req) continue;
  						resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF));
  						if(((~((resp.charCodeAt(1)<<8) + resp.charCodeAt(0)))&0xFFFF) == Special.FLibSYS.CRC(req,0xA001,16,0) && resp.charCodeAt(2) == tSt)
  							dO["st2"+iN] = tSt;
  					}
  				}

  				//Read control status data
  				if(dP["res0"].get().isEVal()) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xAA,0x08,0x00))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  					CRC_OK = (~((resp.charCodeAt(resp.length-1)<<8) + resp.charCodeAt(resp.length-2)))&0xFFFF;
  					CRC_OK = (Special.FLibSYS.CRC(SYS.strFromCharCode(0xAA,0x08,0x00)+resp.slice(0,-2),0xA001,16,0) == CRC_OK);
  					for(iN = 0; iN < 4; iN++) {
  						dP["res"+iN].set(CRC_OK?((tVl=resp.charCodeAt(iN*2)&0xF)?tVl:16):EVAL, 0, 0, true);
  						dP["md"+iN].set(CRC_OK?((resp.charCodeAt(iN*2)&0x80)?2:resp.charCodeAt(iN*2+1)&1):EVAL, 0, 0, true);
  						dP["do"+iN].set(CRC_OK?((resp.charCodeAt(iN*2)&0x40)?true:false):EVAL, 0, 0, true);
  						dO["st1"+iN] = resp.charCodeAt(iN*2); dO["st2"+iN] = resp.charCodeAt(iN*2+1);
  					}
  				} else CRC_OK = true;

  				//Read AI value
  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xAA,0x00,0x00))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  					//SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," ")/*+"; CRC="+Special.FLibSYS.CRC(SYS.strFromCharCode(0x3C,0x08,0x00)/*+resp.slice(0,-2),0xA001,16,0).toString(16)*/);
  					CRC_OK = (~((resp.charCodeAt(resp.length-1)<<8) + resp.charCodeAt(resp.length-2)))&0xFFFF;
  					CRC_OK = (Special.FLibSYS.CRC(SYS.strFromCharCode(0xAA,0x00,0x00)+resp.slice(0,-2),0xA001,16,0) == CRC_OK);
  				}
  				for(iN = 0; iN < 4; iN++)
  					if(CRC_OK) {
  						tVl = (resp.charCodeAt(iN*2+1)<<8) + resp.charCodeAt(iN*2);
  						vlMax = dP["md"+iN].get() ? 5.1 : 2.55;
  						dP["ai"+iN].set(tVl*vlMax/65536, 0, 0, true);
  					} else dP["ai"+iN].set(EVAL, 0, 0, true);

  				//Start A/D conversion for prepare data for next iteration
  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x3C,0x0F,0x00))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF));
  				}
  			}
  			else if(devFamily == 0x26) {	//DS2438
  				dP = dO.dP;
  				//Check for a modifications
  				//????

  				//Recall memory page 0
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0xB8,0))) != req) continue;
  				//Read current state
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0xBE,0))) != req) continue;
  				resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  				CRC_OK = !Special.FLibSYS.CRC(resp, 0x8C, 8, 0);
  				if(CRC_OK) {
  					if((tVl=(resp.charCodeAt(2)<<8)+resp.charCodeAt(1)) >= 32767) tVl -= 65536;
  					dP["t"].set(tVl/256, 0, 0, true);
  					if((tVl=(resp.charCodeAt(6)<<8)+resp.charCodeAt(5)) >= 32767) tVl -= 65536;
  					dP["i"].set(tVl, 0, 0, true);
  				}
  				else {
  					dP["t"].set(EVAL, 0, 0, true);
  					dP["i"].set(EVAL, 0, 0, true);
  				}
  				dP["v"].set(CRC_OK?((resp.charCodeAt(4)<<8)+resp.charCodeAt(3))/100:EVAL, 0, 0, true);
  				dP["IAD"].set(CRC_OK?(resp.charCodeAt(0)&0x01):EVAL, 0, 0, true);
  				dP["CA"].set(CRC_OK?(resp.charCodeAt(0)&0x02):EVAL, 0, 0, true);
  				dP["EE"].set(CRC_OK?(resp.charCodeAt(0)&0x04):EVAL, 0, 0, true);
  				dP["AD"].set(CRC_OK?(resp.charCodeAt(0)&0x08):EVAL, 0, 0, true);
  				dP["thr"].set(CRC_OK?(resp.charCodeAt(7)>>6):EVAL, 0, 0, true);

  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xBE,1))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  					CRC_OK = !Special.FLibSYS.CRC(resp, 0x8C, 8, 0);
  					SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," "));
  				}
  				dP["ETM"].set(CRC_OK?((resp.charCodeAt(3)<<24)+(resp.charCodeAt(2)<<16)+(resp.charCodeAt(1)<<8)+resp.charCodeAt(0)):EVAL, 0, 0, true);
  				dP["ICA"].set(CRC_OK?resp.charCodeAt(4):EVAL, 0, 0, true);
  				if(CRC_OK) {
  					if((tVl=(resp.charCodeAt(6)<<8)+resp.charCodeAt(5)) >= 32767) tVl -= 65536;
  					dP["OFF"].set(tVl, 0, 0, true);
  				} else dP["OFF"].set(EVAL, 0, 0, true);

  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xBE,2))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  					CRC_OK = !Special.FLibSYS.CRC(resp, 0x8C, 8, 0);
  					SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," "));
  				}
  				dP["TM_DISC"].set(CRC_OK?((resp.charCodeAt(3)<<24)+(resp.charCodeAt(2)<<16)+(resp.charCodeAt(1)<<8)+resp.charCodeAt(0)):EVAL, 0, 0, true);
  				dP["TM_END"].set(CRC_OK?((resp.charCodeAt(7)<<24)+(resp.charCodeAt(6)<<16)+(resp.charCodeAt(5)<<8)+resp.charCodeAt(4)):EVAL, 0, 0, true);

  				//Start T ant V conversion for prepare the data for next iteration
  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x44))) != req) continue;
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xB4))) != req) continue;
  				}
  			}
  			else if(devFamily == 0x29) {	//DS2408
  				dP = dO.dP;
  				//Check for a modifications
  				isMdf = false; tVl = 0; do_ = new Array();
  				for(iD = 0; iD < 8; iD++) {
  					if(dO["do"+iD].isEVal())	{ isMdf = false; break; }
  					do_[iD] = dP["do"+iD].get();
  					if(do_[iD] != dO["do"+iD])	isMdf = true;
  					if(do_[iD])	tVl = tVl | (1<<iD);
  				}
  				if(isMdf) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x5A,tVl,~tVl))) != req) continue;
  					// Verify the correct writing, pass by that can be wrong
  					//resp = io(tr, SYS.strFromCharCode(0xFF,0xFF));
  					//SYS.messInfo("OneWire","Write resp="+SYS.strDecode(resp,"Bin"," "));
  				}

  				//Read current state
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0xF0,0x88,0x00))) != req) continue;
  				resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  				//SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," "));//+"; CRC="+Special.FLibSYS.CRC(SYS.strFromCharCode(0xF0,0x88,0x00)+resp.slice(0,-2),0xA001,16,0).toString(16));
  				CRC_OK = (~((resp.charCodeAt(resp.length-1)<<8) + resp.charCodeAt(resp.length-2)))&0xFFFF;
  				CRC_OK = (Special.FLibSYS.CRC(SYS.strFromCharCode(0xF0,0x88,0x00)+resp.slice(0,-2),0xA001,16,0) == CRC_OK);
  				for(iD = 0; iD < 8; iD++) {
  					dP["di"+iD].set(CRC_OK?resp.charCodeAt(0)&(1<<iD):EVAL, 0, 0, true);
  					if(dO["do"+iD].isEVal() || isMdf || !CRC_OK) {
  						dO["do"+iD] = CRC_OK ? ((resp.charCodeAt(1)&(1<<iD))?true:false) : EVAL;
  						dP["do"+iD].set(dO["do"+iD], 0, 0, true);
  					}
  				}
  			}
  			else if(devFamily == 0x3A) {	//DS2413
  				dP = dO.dP;
  				//SYS.messInfo("OneWire","devID="+SYS.strDecode(devID,"Bin"," "));
  				//Check for a modifications
  				isMdf = false;
  				do0_ = dP.do0.get(), do1_ = dP.do1.get();
  				if(!dO.do0.isEVal() && !dO.do1.isEVal() && (do0_ != dO.do0 || do1_ != dO.do1)) {
  					tVl = (do1_<<1) | do0_;
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x5A,tVl,(~tVl)&0xFF))) != req) continue;
  					isMdf = true;
  				}

  				//Read current state
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0xF5))) != req) continue;
  				resp = io(tr, SYS.strFromCharCode(0xFF));
  				//SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," "));
  				if(((tVl=resp.charCodeAt(0))&0xF) == ((~(tVl>>4))&0xF)) {
  					dP.di0.set(tVl&0x01, 0, 0, true); dP.di1.set(tVl&0x04, 0, 0, true);
  					if(dO.do0.isEVal() || dO.do1.isEVal() || isMdf) {
  						dO.do0 = (tVl&0x02)?true:false; dP.do0.set(dO.do0, 0, 0, true);
  						dO.do1 = (tVl&0x08)?true:false; dP.do1.set(dO.do1, 0, 0, true);
  					}
  				}
  				else {
  					dP.di0.set(EVAL, 0, 0, true); dP.di1.set(EVAL, 0, 0, true);
  					dP.do0.set(EVAL, 0, 0, true); dP.do1.set(EVAL, 0, 0, true);
  					dO.do0 = dO.do1 = EVAL;
  				}
  			}
  		}
  	}
  }

  f_err = t_err;


ID: 1W_DS9097
NAME: One Wire by DS9097
DESCR:
  One Wire sensors bus implementing by 1Wire-adapter DS9097. Supported direct and parasite powering for the temperature sensors.
  Supported 1Wire-devices: DS1820, DS1820/DS18S20/DS1920 (not tested), DS1822 (not tested), DS2413, DS2408, DS2450, DS2438.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.2.0

PROGRAM:
  JavaLikeCalc.JavaScript
  //Functions
  function reset(tr) {
  	tr.addr(tr.addr().parse(0,":")+":9600:8N1"); tr.start(true);
  	rez = tr.messIO(SYS.strFromCharCode(0xF0));
  	tr.addr(tr.addr().parse(0,":")+":115200:8N1"); tr.timings("100:2-0"); tr.start(true);
  	tr.messIO("");
  	return rez.length && rez.charCodeAt(0) != 0xF0;
  }

  function io(tr, mess, bits) {
  	if(bits == EVAL) bits = mess.length * 8;
  	req = "";
  	for(iB = 0; iB < ceil(bits/8); iB++) {
  		vB = mess.charCodeAt(iB);
  		bB = ((iB+1)*8 > bits) ? bits-floor(bits/8)*8 : 8;
  		for(iBi = 0; iBi < bB; iBi++) req += SYS.strFromCharCode((vB&(1<<iBi)) ? 0xFF : 0x00);
  	}
  	//SYS.messInfo("OneWire","bits="+bits+"; req="+SYS.strDecode(req,"Bin"," "));
  	for(resp = tr.messIO(req); resp.length < req.length && (tresp=tr.messIO("")).length; resp += tresp) ;
  	//SYS.messInfo("OneWire","bits="+bits+"; resp="+SYS.strDecode(resp,"Bin"," "));
  	rez = "";
  	for(iR = 0; iR < resp.length; ) {
  		vB = 0;
  		for(ib = 0; ib < 8 && iR < resp.length; iR++, ib++)
  			if(resp.charCodeAt(iR)&1) vB = vB | (1<<ib);
  		rez += SYS.strFromCharCode(vB);
  	}		
  	return rez;
  }

  function scan(tr, sn, lstDiscr) {
  	if(!reset(tr)) return "";
  	io(tr, SYS.strFromCharCode(0xF0));
  	for(nByte = 0, nBit = 1, tBit = 0, sDir = false, mskByte = 1, lstZero = 0; nByte < 8; ) {
  		tBit = io(tr, SYS.strFromCharCode(0xFF), 1).charCodeAt(0) << 1;
  		tBit = tBit | io(tr, SYS.strFromCharCode(0xFF), 1).charCodeAt(0);
  		//SYS.messInfo("OneWire","nByte="+nByte+"; nBit="+nBit+"; tBit="+tBit);
  		if(tBit == 3) break;
  		if(tBit > 0) sDir = !(tBit&0x01);
  		else {
  			//SYS.messInfo("OneWire","nByte="+nByte+"; nBit="+nBit+"; lstDiscr="+lstDiscr);
  			if(nBit < lstDiscr) sDir = sn[nByte]&mskByte;
  			else sDir = (nBit == lstDiscr);
  			if(!sDir) lstZero = nBit;
  			//if(lstZero < 9) lstDiscr = lstZero;
  			//SYS.messInfo("OneWire","nByte="+nByte+"; nBit="+nBit+"; sDir="+sDir+"; mskByte="+mskByte);
  		}
  		if(sDir) sn[nByte] = sn[nByte] | mskByte;
  		else sn[nByte] = sn[nByte] & (~mskByte);
  		tr.messIO(SYS.strFromCharCode(sDir?0xFF:0x00));
  		nBit++;
       mskByte = (mskByte<<1)&0xFF;
  		if(!mskByte) { nByte++; mskByte = 1; }
  	}

  	rez = "";
  	if(nByte == 8) {
  		for(iB = 0; iB < nByte; iB++) rez += SYS.strFromCharCode(sn[iB]);
  		if(!Special.FLibSYS.CRC(rez,0x8C,8,0))	lstDiscr = lstZero;
  		else { rez = ""; lstDiscr = 0; }
  	}

  	return rez;
  }

  //Set transport and init
  if(f_start) {
  	tmResc_ = tmResc;
  	devLs = new Object();
  	transport_ = transport;
  	tr = SYS.Transport.Serial["out_"+transport];
  }
  if(f_stop) {
  	for(var devID in devLs) {
  		if((dO=devLs[devID]).isEVal()) continue;
  		aLs = dO.dP.nodeList("a_");
  		for(iA = 0; iA < aLs.length; iA++)
  			if(!dO.dP[aLs[iA]].isCfg()) dO.dP[aLs[iA]].set(EVAL, 0, 0, true);
  	}
  	devLs = tr = false;
  	return;
  }

  t_err = "0";

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.Serial["out_"+transport];
  	transport_ = transport;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else {
  	//Generic information update.
  	if(f_start || (tmResc && (tmResc_=tmResc_-1/f_frq) <= 0)) {
  		tmResc_ = tmResc;
  		tmSc = SYS.time();
  		// Check for power
  		if(!reset(tr) ||
  		 	io(tr,(req=SYS.strFromCharCode(0xCC))) != req ||
  			io(tr,(req=SYS.strFromCharCode(0xB4))) != req ||
  			!(resp=io(tr,SYS.strFromCharCode(1),1)).length) power = EVAL;
  		else power = resp.charCodeAt(0);
  		// Scan for allowed devices on the bus.
  		sn = new Array(0, 0, 0, 0, 0, 0, 0, 0);
  		for(devID = "start", lstDiscr = -1; devID.length && lstDiscr; ) {
  			if(lstDiscr < 0) lstDiscr = 0;
  			if((devID=scan(tr,sn,lstDiscr)).length)	{
  				//SYS.messInfo("OneWire","devID="+SYS.strDecode(devID,"Bin"," "));
  				if((dO=devLs[devID]).isEVal()) {
  					devLs[devID] = dO = new Object();
  					devFamily = devID.charCodeAt(0); devNm = tr("1W device"); dO.isT = false;
  					if(devFamily == 0x10)			{ devNm = "DS1820/DS18S20/DS1920"; dO.isT = true; }
  					else if(devFamily == 0x20)	devNm = "DS2450";		//4AI
  					else if(devFamily == 0x22)	{ devNm = "DS1822"; dO.isT = true; }
  					else if(devFamily == 0x26)	devNm = "DS2438";		//SmartBat
  					else if(devFamily == 0x28)	{ devNm = "DS18B20"; dO.isT = true; }
  					else if(devFamily == 0x29)	devNm = "DS2408";		//8DIO
  					else if(devFamily == 0x3A)	devNm = "DS2413";		//2DIO

  					// Create the device's parameter object
  					decId = SYS.strDecode(devID,"Bin","");
  					SYS.cntrReq(SYS.XMLNode("add").setAttr("path",this.nodePath()+"/%2fbr%2fprm_").setAttr("id",decId).setText(devNm+": "+decId));
  					SYS.cntrReq(SYS.XMLNode("set").setAttr("path",this.nodePath()+"/prm_"+decId+"/%2fprm%2fst%2fen").setText("1"));
  					// Create the device's proper attributes
  					dO.dP = dP = this["prm_"+decId];
  					if(dO.isT) {	//Temperature
  						dP.attrAdd("val", tr("Temperature, °С"), "real|ro");
  						dP.attrAdd("m", tr("User cell [0...65535]"), "integer");
  						dP.attrAdd("res", tr("Resolution")+" [9...12]", "integer");
  					}
  					else if(devFamily == 0x20)		//DS2450
  						for(iN = 0; iN < 4; iN++) {
  							dP.attrAdd("ai"+iN, tr("AI, V")+iN, "real|ro");
  							dP.attrAdd("res"+iN, tr("Resolution")+iN+" [1...16]", "integer");
  							dP.attrAdd("md"+iN, tr("Mode")+iN, "integer|sel", "0;1;2\n2.55V;5.10V;DO");
  							dP.attrAdd("do"+iN, tr("DO")+iN, "boolean");
  						}
  					else if(devFamily == 0x26) {	//DS2438
  						dP.attrAdd("t", tr("Temperature, °С"), "real|ro");
  						dP.attrAdd("v", tr("Voltage, V"), "real|ro");
  						dP.attrAdd("i", tr("Current, A"), "real|ro");
  						dP.attrAdd("ICA", tr("Current Accumulator"), "integer");
  						dP.attrAdd("thr", tr("Accumulation threshold"), "integer|sel", "0;1;2;3\nNone;±2LSB;±4LSB;±8LSB");
  						dP.attrAdd("ETM", tr("Elapsed time meter"), "integer");
  						dP.attrAdd("TM_DISC", tr("Disconnect time"), "integer");
  						dP.attrAdd("TM_END", tr("End of charge time"), "integer");
  						dP.attrAdd("OFF", tr("Current Offset"), "integer");
  						dP.attrAdd("IAD", tr("Enable Current A/D"), "boolean");
  						dP.attrAdd("CA", tr("Enable Current Accumulator"), "boolean");
  						dP.attrAdd("EE", tr("Enable Current Accumulator Shadow"), "boolean");
  						dP.attrAdd("AD", tr("Voltage A/D (0-VAD,1-VDD)"), "boolean");
  					}
  					else if(devFamily == 0x29)		//DS2408
  						for(iD = 0; iD < 8; iD++) {
  							dP.attrAdd("di"+iD, tr("DI")+iD, "boolean|ro");
  							dP.attrAdd("do"+iD, tr("DO")+iD, "boolean");
  						}
  					else if(devFamily == 0x3A)		//DS2413
  						for(iD = 0; iD < 2; iD++) {
  							dP.attrAdd("di"+iD, tr("DI")+iD, "boolean|ro");
  							dP.attrAdd("do"+iD, tr("DO")+iD, "boolean");
  						}
  				}
  				if(dO.tmSc == tmSc)	break;	//Somthing wrong into the scan but repeat, interruption
  				dO.tmSc = tmSc;
  				dO.try = tryEVAL;
  			}
  		}
  		//Check for removed devices
  		for(devID in devLs) {
  			if((dO=devLs[devID]).isEVal()) continue;
  			if(dO.tmSc != tmSc)	{
  				devLs[devID] = EVAL;
  				aLs = dO.dP.nodeList("a_");
  				for(iA = 0; iA < aLs.length; iA++)
  					if(!dO.dP[aLs[iA]].isCfg())	dO.dP[aLs[iA]].set(EVAL, 0, 0, true);
  			}
  		}
  	}
  	else {
  		//Process devices for reading current value and set modifable
  		for(devID in devLs) {
  			if((dO=devLs[devID]).isEVal()) continue;
  			devFamily = devID.charCodeAt(0);
  			if(dO.isT) {	//Temperature
  				dP = dO.dP;
  				//SYS.messInfo("OneWire","devID="+SYS.strDecode(devID,"Bin"," "));
  				//Check for a modifications
  				isMdf = false;
  				m_ = dP.m.get(), res_ = max(9,min(12,dP.res.get()));
  				if(!dO.m.isEVal() && !dO.res.isEVal() && (m_ != dO.m || res_ != dO.res)) {
  					//Set scratchpad
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x4E,m_&0xFF,(m_>>8)&0xFF,((res_-9)<<5)|0x1F))) != req) continue;
  					//Copy scratchpad part to the EEPROM
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x48))) != req) continue;
  					isMdf = true;
  				}

  				//Read current
  				// Call the transmission
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x44))) != req) continue;
  				if(!power) SYS.sleep(0.094*pow(2,(dO.res.isEVal()?12:dO.res)-9));
  				// Get scratchpad
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				io(tr, SYS.strFromCharCode(0xBE));
  				resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  				//SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," "));
  				if(!Special.FLibSYS.CRC(resp,0x8C,8,0)) {
  					val = resp.charCodeAt(1)*256 + resp.charCodeAt(0);
  					if(val > 32767) val -= 65536;
  					dP.val.set(val/16, 0, 0, true);
  					if(dO.m.isEVal() || dO.res.isEVal() || isMdf) {
  						dO.m = resp.charCodeAt(3)*256 + resp.charCodeAt(2); dP.m.set(dO.m, 0, 0, true);
  						dO.res = ((resp.charCodeAt(4)>>5)&0x3)+9; dP.res.set(dO.res, 0, 0, true);
  					}
  					dO.try = 0;
  				}
  				else if((dO.try=dO.try+1) > tryEVAL) {
  					dP.val.set(EVAL, 0, 0, true); dP.m.set(EVAL, 0, 0, true); dP.res.set(EVAL, 0, 0, true);
  					dO.m = dO.res = EVAL;
  				}
  			}
  			else if(devFamily == 0x20) {	//DS2450
  				dP = dO.dP;
  				//Check for a modifications
  				for(iN = 0; iN < 4; iN++) {
  					if(dO["st1"+iN].isEVal())	continue;
  					if((tRes=max(0,min(16,dP["res"+iN].get()))) == 16)	tRes = 0;
  					tSt = (dO["st1"+iN]&(~0xCF)) + tRes + ((dP["md"+iN].get()==2)?0x80:0) + (dP["do"+iN].get()?0x40:0);
  					if(tSt != dO["st1"+iN]) {	//Same write and check the result
  						if(!reset(tr)) continue;
  						if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  						if(io(tr,(req=SYS.strFromCharCode(0x55,8+iN*2,0,tSt))) != req) continue;
  						resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF));
  						if(((~((resp.charCodeAt(1)<<8) + resp.charCodeAt(0)))&0xFFFF) == Special.FLibSYS.CRC(req,0xA001,16,0) && resp.charCodeAt(2) == tSt)
  							dO["st1"+iN] = tSt;
  					}
  					tSt = (dO["st2"+iN]&(~0x01)) + (dP["md"+iN].get()?1:0);
  					if(tSt != dO["st2"+iN]) {	//Same write and check the result
  						if(!reset(tr)) continue;
  						if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  						if(io(tr,(req=SYS.strFromCharCode(0x55,8+iN*2+1,0,tSt))) != req) continue;
  						resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF));
  						if(((~((resp.charCodeAt(1)<<8) + resp.charCodeAt(0)))&0xFFFF) == Special.FLibSYS.CRC(req,0xA001,16,0) && resp.charCodeAt(2) == tSt)
  							dO["st2"+iN] = tSt;
  					}
  				}

  				//Read control status data
  				if(dP["res0"].get().isEVal()) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xAA,0x08,0x00))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  					CRC_OK = (~((resp.charCodeAt(resp.length-1)<<8) + resp.charCodeAt(resp.length-2)))&0xFFFF;
  					CRC_OK = (Special.FLibSYS.CRC(SYS.strFromCharCode(0xAA,0x08,0x00)+resp.slice(0,-2),0xA001,16,0) == CRC_OK);
  					for(iN = 0; iN < 4; iN++) {
  						dP["res"+iN].set(CRC_OK?((tVl=resp.charCodeAt(iN*2)&0xF)?tVl:16):EVAL, 0, 0, true);
  						dP["md"+iN].set(CRC_OK?((resp.charCodeAt(iN*2)&0x80)?2:resp.charCodeAt(iN*2+1)&1):EVAL, 0, 0, true);
  						dP["do"+iN].set(CRC_OK?((resp.charCodeAt(iN*2)&0x40)?true:false):EVAL, 0, 0, true);
  						dO["st1"+iN] = resp.charCodeAt(iN*2); dO["st2"+iN] = resp.charCodeAt(iN*2+1);
  					}
  				} else CRC_OK = true;

  				//Read AI value
  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xAA,0x00,0x00))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  					//SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," ")/*+"; CRC="+Special.FLibSYS.CRC(SYS.strFromCharCode(0x3C,0x08,0x00)/*+resp.slice(0,-2),0xA001,16,0).toString(16)*/);
  					CRC_OK = (~((resp.charCodeAt(resp.length-1)<<8) + resp.charCodeAt(resp.length-2)))&0xFFFF;
  					CRC_OK = (Special.FLibSYS.CRC(SYS.strFromCharCode(0xAA,0x00,0x00)+resp.slice(0,-2),0xA001,16,0) == CRC_OK);
  				}
  				for(iN = 0; iN < 4; iN++)
  					if(CRC_OK) {
  						tVl = (resp.charCodeAt(iN*2+1)<<8) + resp.charCodeAt(iN*2);
  						vlMax = dP["md"+iN].get() ? 5.1 : 2.55;
  						dP["ai"+iN].set(tVl*vlMax/65536, 0, 0, true);
  					} else dP["ai"+iN].set(EVAL, 0, 0, true);

  				//Start A/D conversion for prepare data for next iteration
  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x3C,0x0F,0x00))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF));
  				}
  			}
  			else if(devFamily == 0x26) {	//DS2438
  				dP = dO.dP;
  				//Check for a modifications
  				//????

  				//Recall memory page 0
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0xB8,0))) != req) continue;
  				//Read current state
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0xBE,0))) != req) continue;
  				resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  				CRC_OK = !Special.FLibSYS.CRC(resp, 0x8C, 8, 0);
  				if(CRC_OK) {
  					if((tVl=(resp.charCodeAt(2)<<8)+resp.charCodeAt(1)) >= 32767) tVl -= 65536;
  					dP["t"].set(tVl/256, 0, 0, true);
  					if((tVl=(resp.charCodeAt(6)<<8)+resp.charCodeAt(5)) >= 32767) tVl -= 65536;
  					dP["i"].set(tVl, 0, 0, true);
  				}
  				else {
  					dP["t"].set(EVAL, 0, 0, true);
  					dP["i"].set(EVAL, 0, 0, true);
  				}
  				dP["v"].set(CRC_OK?((resp.charCodeAt(4)<<8)+resp.charCodeAt(3))/100:EVAL, 0, 0, true);
  				dP["IAD"].set(CRC_OK?(resp.charCodeAt(0)&0x01):EVAL, 0, 0, true);
  				dP["CA"].set(CRC_OK?(resp.charCodeAt(0)&0x02):EVAL, 0, 0, true);
  				dP["EE"].set(CRC_OK?(resp.charCodeAt(0)&0x04):EVAL, 0, 0, true);
  				dP["AD"].set(CRC_OK?(resp.charCodeAt(0)&0x08):EVAL, 0, 0, true);
  				dP["thr"].set(CRC_OK?(resp.charCodeAt(7)>>6):EVAL, 0, 0, true);

  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xBE,1))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  					CRC_OK = !Special.FLibSYS.CRC(resp, 0x8C, 8, 0);
  					SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," "));
  				}
  				dP["ETM"].set(CRC_OK?((resp.charCodeAt(3)<<24)+(resp.charCodeAt(2)<<16)+(resp.charCodeAt(1)<<8)+resp.charCodeAt(0)):EVAL, 0, 0, true);
  				dP["ICA"].set(CRC_OK?resp.charCodeAt(4):EVAL, 0, 0, true);
  				if(CRC_OK) {
  					if((tVl=(resp.charCodeAt(6)<<8)+resp.charCodeAt(5)) >= 32767) tVl -= 65536;
  					dP["OFF"].set(tVl, 0, 0, true);
  				} else dP["OFF"].set(EVAL, 0, 0, true);

  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xBE,2))) != req) continue;
  					resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  					CRC_OK = !Special.FLibSYS.CRC(resp, 0x8C, 8, 0);
  					SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," "));
  				}
  				dP["TM_DISC"].set(CRC_OK?((resp.charCodeAt(3)<<24)+(resp.charCodeAt(2)<<16)+(resp.charCodeAt(1)<<8)+resp.charCodeAt(0)):EVAL, 0, 0, true);
  				dP["TM_END"].set(CRC_OK?((resp.charCodeAt(7)<<24)+(resp.charCodeAt(6)<<16)+(resp.charCodeAt(5)<<8)+resp.charCodeAt(4)):EVAL, 0, 0, true);

  				//Start T ant V conversion for prepare the data for next iteration
  				if(CRC_OK) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x44))) != req) continue;
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0xB4))) != req) continue;
  				}
  			}
  			else if(devFamily == 0x29) {	//DS2408
  				dP = dO.dP;
  				//Check for a modifications
  				isMdf = false; tVl = 0; do_ = new Array();
  				for(iD = 0; iD < 8; iD++) {
  					if(dO["do"+iD].isEVal())	{ isMdf = false; break; }
  					do_[iD] = dP["do"+iD].get();
  					if(do_[iD] != dO["do"+iD])	isMdf = true;
  					if(do_[iD])	tVl = tVl | (1<<iD);
  				}
  				if(isMdf) {
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x5A,tVl,~tVl))) != req) continue;
  					// Verify the correct writing, pass by that can be wrong
  					//resp = io(tr, SYS.strFromCharCode(0xFF,0xFF));
  					//SYS.messInfo("OneWire","Write resp="+SYS.strDecode(resp,"Bin"," "));
  				}

  				//Read current state
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0xF0,0x88,0x00))) != req) continue;
  				resp = io(tr, SYS.strFromCharCode(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF));
  				//SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," ")+"; CRC="+Special.FLibSYS.CRC(SYS.strFromCharCode(0xF0,0x88,0x00)+resp.slice(0,-2),0xA001,16,0).toString(16));
  				CRC_OK = (~((resp.charCodeAt(resp.length-1)<<8) + resp.charCodeAt(resp.length-2)))&0xFFFF;
  				CRC_OK = (Special.FLibSYS.CRC(SYS.strFromCharCode(0xF0,0x88,0x00)+resp.slice(0,-2),0xA001,16,0) == CRC_OK);
  				for(iD = 0; iD < 8; iD++) {
  					dP["di"+iD].set(CRC_OK?resp.charCodeAt(0)&(1<<iD):EVAL, 0, 0, true);
  					if(dO["do"+iD].isEVal() || isMdf || !CRC_OK) {
  						dO["do"+iD] = CRC_OK ? ((resp.charCodeAt(1)&(1<<iD))?true:false) : EVAL;
  						dP["do"+iD].set(dO["do"+iD], 0, 0, true);
  					}
  				}
  			}
  			else if(devFamily == 0x3A) {	//DS2413
  				dP = dO.dP;
  				//SYS.messInfo("OneWire","devID="+SYS.strDecode(devID,"Bin"," "));
  				//Check for a modifications
  				isMdf = false;
  				do0_ = dP.do0.get(), do1_ = dP.do1.get();
  				if(!dO.do0.isEVal() && !dO.do1.isEVal() && (do0_ != dO.do0 || do1_ != dO.do1)) {
  					tVl = (do1_<<1) | do0_;
  					if(!reset(tr)) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  					if(io(tr,(req=SYS.strFromCharCode(0x5A,tVl,(~tVl)&0xFF))) != req) continue;
  					isMdf = true;
  				}

  				//Read current state
  				if(!reset(tr)) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0x55)+devID)) != req) continue;
  				if(io(tr,(req=SYS.strFromCharCode(0xF5))) != req) continue;
  				resp = io(tr, SYS.strFromCharCode(0xFF));
  				//SYS.messInfo("OneWire","resp="+SYS.strDecode(resp,"Bin"," "));
  				if(((tVl=resp.charCodeAt(0))&0xF) == ((~(tVl>>4))&0xF)) {
  					dP.di0.set(tVl&0x01, 0, 0, true); dP.di1.set(tVl&0x04, 0, 0, true);
  					if(dO.do0.isEVal() || dO.do1.isEVal() || isMdf) {
  						dO.do0 = (tVl&0x02)?true:false; dP.do0.set(dO.do0, 0, 0, true);
  						dO.do1 = (tVl&0x08)?true:false; dP.do1.set(dO.do1, 0, 0, true);
  					}
  				}
  				else {
  					dP.di0.set(EVAL, 0, 0, true); dP.di1.set(EVAL, 0, 0, true);
  					dP.do0.set(EVAL, 0, 0, true); dP.do1.set(EVAL, 0, 0, true);
  					dO.do0 = dO.do1 = EVAL;
  				}
  			}
  		}
  	}
  }

  f_err = t_err;


ID: PCF8574
NAME: I2C: PCF8574
DESCR:
  I2C 8-bit 8DIO. Connect through a Serial output transport into the I2C mode.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.0.0

PROGRAM:
  JavaLikeCalc.JavaScript
  //Set transport
  if(f_start) {
  	f_err = "0";
  	transport_ = transport;
  	tr = SYS.Transport.Serial["out_"+transport];
  	di0 = di1 = di2 = di3 = di4 = di5 = di6 = di7 = EVAL;
  	do0 = do1 = do2 = do3 = do4 = do5 = do6 = do7 = true;
  	do0_ = do1_ = do2_ = do3_ = do4_ = do5_ = do6_ = do7_ = true;
  }

  t_err = "0";

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.Serial["out_"+transport];
  	transport_ = transport;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else if(addr < 0 || addr > 119)	t_err = "2:"+tr("Device address '%1' out of range [0...119].").replace("%1",addr);
  else {
  	if(do0 != do0_ || do1 != do1_ || do2 != do2_ || do3 != do3_ || do4 != do4_ || do5 != do5_ || do6 != do6_ || do7 != do7_) {
  		tr.messIO(SYS.strFromCharCode(addr,(do0?0x01:0)|(do1?0x02:0)|(do2?0x04:0)|(do3?0x08:0)|
  																(do4?0x10:0)|(do5?0x20:0)|(do6?0x40:0)|(do7?0x80:0)), 0, 0);
  		do0_ = do0; do1_ = do1; do2_ = do2; do3_ = do3; do4_ = do4; do5_ = do5; do6_ = do6; do7_ = do7;
  	}
  	rez = tr.messIO(SYS.strFromCharCode(addr), 0, 1);
  	if(rez.length) {
  		vl = rez.charCodeAt(0);
  		di0 = (vl&0x01); di1 = (vl&0x02); di2 = (vl&0x04); di3 = (vl&0x08);
  		di4 = (vl&0x10); di5 = (vl&0x20); di6 = (vl&0x40); di7 = (vl&0x80);
  	}
  	else t_err = "3:"+tr("No read result.");
  }

  if(t_err.toInt() && !f_err.toInt())
  	di0 = di1 = di2 = di3 = di4 = di5 = di6 = di7 = EVAL;

  f_err = t_err;


ID: BMP180
NAME: I2C: BMP180
DESCR:
  I2C Pressure and Temperature sensor. Connect through a Serial output transport into the I2C mode.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.0.0

PROGRAM:
  JavaLikeCalc.JavaScript
  //Set transport
  if(f_start) {
  	f_err = "0";
  	transport_ = transport;
  	tr = SYS.Transport.Serial["out_"+transport];
  	AC1 = 0;
  }

  t_err = "0";

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.Serial["out_"+transport];
  	transport_ = transport;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else if(addr < 0 || addr > 119)	t_err = "2:"+tr("Device address '%1' out of range [0...119].").replace("%1",addr);
  else {
  	resp = Special.FLibSYS.IO("", "", "b");
  	//Calibration data, from register 0xAA and to 0xBF
  	if(!AC1) {
  		resp.string = tr.messIO(SYS.strFromCharCode(addr,0xAA), 0, 22);
  		if(resp.string.length != 22) t_err = "3:"+tr("Wrong or empty respond to the calibration request.");
  		else {
  			AC1 = resp.read("int16",1);	AC2 = resp.read("int16",1);	AC3 = resp.read("int16",1);
  			AC4 = resp.read("uint16",1);	AC5 = resp.read("uint16",1);	AC6 = resp.read("uint16",1);
  			B1 = resp.read("int16",1);	B2 = resp.read("int16",1);
  			MB = resp.read("int16",1);	MC = resp.read("int16",1);	MD = resp.read("int16",1);
  			//SYS.messInfo("BMP180","AC1="+AC1+"; AC2="+AC2+"; AC3="+AC3+"; AC4="+AC4+"; AC5="+AC5+"; AC6="+AC6);
  		}
  	}

  	//Read and calculate temperature
  	if(AC1 && !t_err.toInt()) {
  		// Start conversion
  		tr.messIO(SYS.strFromCharCode(addr,0xF4,0x2E), 0, 0);	SYS.sleep(4.5e-3);
  		// Read value
  		resp.pos = 0; resp.string = tr.messIO(SYS.strFromCharCode(addr,0xF6), 0, 2);
  		if(resp.string.length != 2) t_err = "3:"+tr("Wrong or empty respond to the temperature data.");
  		else {
  			UT = resp.read("int16",1);
  			X1 = (UT-AC6)*AC5/pow(2,15);	X2 = MC*pow(2,11)/(X1+MD);
  			B5 = X1 + X2;
  			t = 0.1*((B5+8)/pow(2,4));
  			//SYS.messInfo("BMP180","UT="+UT+"; X1="+X1+"; X2="+X2+"; B5="+B5+"; t="+t);
  		}
  	}
  	
  	//Read and calculate temperature
  	if(AC1 && !t_err.toInt()) {
  		oss = max(0,min(3,oss));
  		// Start conversion
  		tr.messIO(SYS.strFromCharCode(addr,0xF4,0x34+(oss<<6)), 0, 0);	SYS.sleep((1.5+3*pow(2,oss))*1e-3);
  		// Read value
  		resp.pos = 0; resp.string = tr.messIO(SYS.strFromCharCode(addr,0xF6), 0, 4);
  		UP = resp.read("int32",1)>>(16-oss);
  		B6 = B5 - 4000;
  		X1 = (B2*(B6*floor(B6/pow(2,12))))/pow(2,11);
  		X2 = AC2*B6/pow(2,11);
  		X3 = X1 + X2;
  		B3 = (((AC1*4+X3)<<oss)+2)/4;
  		X1 = AC3*B6/pow(2,13);
  		X2 = (B1*(B6*B6/pow(2,12)))/pow(2,16);
  		X3 = ((X1+X2)+2)/pow(2,2);
  		B4 = AC4*(X3+32768)/pow(2,15);
  		B7 = (UP-B3)*(50000>>oss);
  		p = (B7 < 0x80000000) ? (B7*2)/B4 : (B7/B4)*2;
  		X1 = (p/pow(2,8))*(p/pow(2,8));
  		X1 = (X1*3038)/pow(2,16);
  		X2 = (-7357*p)/pow(2,16);
  		p = p + (X1+X2+3791)/pow(2,4);
  	}
  }

  if(t_err.toInt() && !f_err.toInt()) t = p = EVAL;
  f_err = t_err;


ID: DS3231
NAME: I2C: DS3231
DESCR:
  I2C RTC chip with Temperature sensor and calibration on it. Connect through a Serial output transport into the I2C mode.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.0.0

PROGRAM:
  JavaLikeCalc.JavaScript
  //Set transport
  if(f_start) {
  	f_err = "0";
  	transport_ = transport;
  	tr = SYS.Transport.Serial["out_"+transport];
  	tm_ = tm = "";
  	agOff_ = agOff = 0;
  	p32k_ = p32k = false;
  	pSQW_ = pSQW = false;
  	pSQWf_ = pSQWf = 0;
  }

  t_err = "0";

  //Check for the transport change and connect
  if(!tr || transport != transport_)	{
  	tr = SYS.Transport.Serial["out_"+transport];
  	transport_ = transport;
  }
  if(!tr)	t_err = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
  else if(addr < 0 || addr > 119)	t_err = "2:"+tr("Device address '%1' out of range [0...119].").replace("%1",addr);
  else {
  	//Check for modification
  	if(tm != tm_) {
  		off = 0; sdt = tm.parse(0,"T",off); stm = tm.parse(0,"T",off);
  		off = 0; year = sdt.parse(0,"-",off).toInt(16); month = sdt.parse(0,"-",off).toInt(16); day = sdt.parse(0,"-",off).toInt(16);
  		off = 0; hour = stm.parse(0,":",off).toInt(16); min = stm.parse(0,":",off).toInt(16); sec = stm.parse(0,":",off).toInt(16);
  		tr.messIO(SYS.strFromCharCode(addr,0,sec,min,hour,0,day,month+((year&0xF00)?0x80:0),year&0xFF), 0, 0);
  		tm_ = tm;
  	}
  	if(agOff != agOff_) {
  		tr.messIO(SYS.strFromCharCode(addr,16,agOff), 0, 0);
  		agOff_ = agOff;
  	}
  	if(p32k != p32k_) {
  		resp = tr.messIO(SYS.strFromCharCode(addr,15), 0, 1);
  		if(resp.length != 1) t_err = "3:"+tr("Wrong or empty read respond.");
  		else {
  			cntrB = resp.charCodeAt(0);
  			cntrB = p32k ?	cntrB|0x08 : cntrB&(~0x08);
  			tr.messIO(SYS.strFromCharCode(addr,15,cntrB), 0, 0);
  		}
  		p32k_ = p32k;
  	}
  	if(pSQW != pSQW_) {
  		resp = tr.messIO(SYS.strFromCharCode(addr,14), 0, 1);
  		if(resp.length != 1) t_err = "3:"+tr("Wrong or empty read respond.");
  		else {
  			cntrB = resp.charCodeAt(0);
  			cntrB = pSQW ? cntrB&(~0x04) : cntrB|0x04;
  			tr.messIO(SYS.strFromCharCode(addr,14,cntrB), 0, 0);
  		}
  		pSQW_ = pSQW;
  	}
  	if(pSQWf != pSQWf_) {
  		pSQWf = max(0,min(3,pSQWf));
  		resp = tr.messIO(SYS.strFromCharCode(addr,14), 0, 1);
  		if(resp.length != 1) t_err = "3:"+tr("Wrong or empty read respond.");
  		else {
  			cntrB = (resp.charCodeAt(0)&(~0x18)) + (pSQWf<<3);
  			tr.messIO(SYS.strFromCharCode(addr,14,cntrB), 0, 0);
  		}
  		pSQWf_ = pSQWf;
  	}

  	//Get current
  	resp = tr.messIO(SYS.strFromCharCode(addr,0), 0, 19);
  	if(resp.length != 19) t_err = "3:"+tr("Wrong or empty read respond.");
  	else {
  		// Get current time
  		tm_ = tm = (20+(resp.charCodeAt(5)>>7)).toString(10,2)+resp.charCodeAt(6).toString(16,2)+"-" +
  				(resp.charCodeAt(5)&0x7F).toString(16,2)+"-" + 
  				resp.charCodeAt(4).toString(16,2)+"T" +
  				(resp.charCodeAt(2)&0x3F).toString(16,2)+":" +
  				resp.charCodeAt(1).toString(16,2)+":" + 
  				resp.charCodeAt(0).toString(16,2);
  		// Aging offset
  		if((agOff=resp.charCodeAt(16)) >= 128)	agOff = agOff-256;
  		agOff_ = agOff;

  		// Miscellaneous
  		p32k = p32k_ = resp.charCodeAt(15)&0x08;
  		pSQW = pSQW_ = !(resp.charCodeAt(14)&0x04);
  		pSQWf = pSQWf_ = (resp.charCodeAt(14)>>3)&0x3;

  		// Get temperature
  		t = (resp.charCodeAt(17)<<2)+(resp.charCodeAt(18)>>6);
  		if(t >= 128) t = t-256;
  		t = t/4;
  	}
  }

  if(t_err.toInt() && !f_err.toInt()) t = p = EVAL;
  f_err = t_err;


ID: DHT
NAME: GPIO: DHT11,22 (AM23XX)
DESCR:
  Digital Temperature and Humidity Sensor for models: DHT11, DHT12, AM2302, AM2320, ...
  The module designed for the sensors connect through GPIO, mostly it's Raspberry PI BCM2835 GPIO.
  Conditions: Exclusively realtime planing in the priority 199 (FIFO-99).
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.0.0

PROGRAM:
  JavaLikeCalc.JavaScript
  using Special.FLibSYS;

  //Set link to fast external functions
  if(f_start)	f_err = "0", addr_ = "";

  t_err = "0";

  //Check for the address change and link
  if(addr != addr_)	{
  	addr_ = addr;
  	function mode = addr+".fnc_mode";
  	function get = addr+".fnc_get";
  	function put = addr+".fnc_put";
  }

  //Read sensor's data function declaration
  function read() {
  	vl = 0;						//Meassured value
  	cntHoldMax = 100;		//Maximum wait counter

  	//Call the device to a respond
  	mode(pin, 4); put(pin, true); tmSleep(500e-3);	//Set pin to output mode and next to true for 500ms
  	put(pin, false); tmSleep(20e-3);							//Set output to false for 20ms
  	mode(pin, 2);														//Set pin to input mode

  	//Read
  	// Wait for pull pin low.
  	for(cntHold = 0; get(pin); cntHold++)
  		if(cntHold > cntHoldMax) return 0;

  	//Meassure the typical pulse length
  	for(cntHold = 0; !get(pin); cntHold++)
  		if(cntHold > cntHoldMax) return 0;
  	for(cntHold = 0; get(pin); cntHold++)
  		if(cntHold > cntHoldMax) return 0;
  	cntPulse = cntHold;

  	//Read meassured value
  	for(iB = 0; iB < 40; iB++) {
  		//stg = iB;
  		for(cntHold = 0; !get(pin); cntHold++)
  			if(cntHold > cntHoldMax) return 0;
  		for(cntHold = 0; get(pin); cntHold++)
  			if(cntHold > cntHoldMax) return 0;
  		vl = vl << 1;
  		if(cntHold > cntPulse/2)	vl = vl | 1;
  	}

  	return vl;
  }

  //Main processing
  if(!mode)	t_err = "1:"+tr("No link to external functions on '%1'.").replace("%1",addr);
  else if(!(dev == 0 || dev == 1))	t_err = "2:"+tr("Unknown device %1 [0-DHT11, 1-DHT22].").replace("%1",dev.toString());
  else if(tries < 1 || tries > 5)	t_err = "3:"+tr("Tries number %1 out of range [1...5].").replace("%1",tries.toString());
  else {
  	for(i = 0; i < tries; i++) {
  		if(i) tmSleep(2);	//Retry after two seconds
  		if((vl=read()) && (vl&0xFF) == ((((vl>>8)&0xFF)+((vl>>16)&0xFF)+((vl>>24)&0xFF)+((vl>>32)&0xFF))&0xFF)) {
  			//SYS.messInfo("/DHT","vl="+vl.toString(16));
  			if(dev == 1) {
  				h = 0.1*(((vl>>32)&0xFF)*256+((vl>>24)&0xFF));
  				t = 0.1*(((vl>>16)&0xFF)*256+((vl>>8)&0xFF));
  				break;
  			}
  			h = ((vl>>32)&0xFF) + 20; t = (vl>>16)&0xFF;
  		}
  	}
  	if(i >= tries)	t_err = "10:"+tr("Get data after %1 tries error.").replace("%1",tries.toString());
  }

  if(t_err.toInt() && !f_err.toInt()) t = h = EVAL;
  f_err = t_err;


ID: 1602A
NAME: GPIO|I2C: 1602A(HD44780)
DESCR:
  LCD Module 1602A, STN, BLUB, 16 Character x 2 Line,  5 x 8 Dots, by the direct (Raspberry PI BCM2835 GPIO) or I2C (PCF8574) wiring.
  Conditions: Default planing policy but realtime one preferred.
  Author: Roman Savochenko <rom_as@oscada.org>
  Version: 1.1.0

PROGRAM:
  JavaLikeCalc.JavaScript
  using Special.FLibSYS;

  //Set link to fast external functions
  if(f_start)	f_err = "0", transport_ = ln1_ = ln2_ = "";

  t_err = "0";

  //Check for the transport change and the link update
  if(transport != transport_)	{
  	transport_ = transport;
  	if(!(tr=SYS.Transport.Serial["out_"+transport]))
  		function put = transport+".fnc_put";
  }

  //Write a byte function declaration
  function byte(tr, vl, md, dl) {
  	if(md == EVAL_BOOL) md = false;
  	if(dl == EVAL_BOOL) dl = 50e-6;
  	if(tr) {
  		//RS(md) | RW(false) | E(false) | BackLight(true) | D4 | D5 | D6 | D7
  		com = (md?0x01:0) | 0x8 | (vl&0xF0);
  		tr.messIO(SYS.strFromCharCode(addr,com), 0, 0);			tmSleep(dl);
  		tr.messIO(SYS.strFromCharCode(addr,com|0x04), 0, 0);	tmSleep(dl);	//E toggle
  		tr.messIO(SYS.strFromCharCode(addr,com), 0, 0);			tmSleep(dl);
  		//RS(md) | RW(false) | E(false) | BackLight(true) | D0 | D1 | D2 | D3
  		com = (md?0x01:0) | 0x8 | ((vl<<4)&0xF0);
  		tr.messIO(SYS.strFromCharCode(addr,com), 0, 0);			tmSleep(dl);
  		tr.messIO(SYS.strFromCharCode(addr,com|0x04), 0, 0);	tmSleep(dl);	//E toggle
  		tr.messIO(SYS.strFromCharCode(addr,com), 0, 0);			tmSleep(dl);
  	}
  	else if(put) {
  		put(RS, md);
  		put(D4, vl&0x10); put(D5, vl&0x20); put(D6, vl&0x40); put(D7, vl&0x80);
  		tmSleep(dl); put(E, true); tmSleep(dl); put(E, false); tmSleep(dl);
  		put(D4, vl&0x01); put(D5, vl&0x02); put(D6, vl&0x04); put(D7, vl&0x08);
  		tmSleep(dl); put(E, true); tmSleep(dl); put(E, false); tmSleep(dl);
  	}
  }

  //Main processing
  if(!tr && !put)
  	t_err = "1:"+tr("Error for '%1' as an output transport of I2C or a link to external functions of GPIO.").replace("%1",transport);
  else if(ln1 != ln1_ || ln2 != ln2_) {
  	ln1_ = ln1; ln2_ = ln2;	

  	//Init
  	byte(tr, 0x33); byte(tr, 0x32); byte(tr, 0x28); byte(tr, 0x0C); byte(tr, 0x06); byte(tr, 0x01);
  	//Line 1
  	if(ln1.length) {
  		tmSleep(2e-3);
  		byte(tr, 0x80);
  		for(iC = 0; iC < min(16,ln1.length); iC++)
  			byte(tr, ln1.charCodeAt(iC), true);
  	}
  	//Line 2
  	if(ln2.length) {
  		tmSleep(2e-3);
  		byte(tr, 0xC0);
  		for(iC = 0; iC < min(16,ln2.length); iC++)
  			byte(tr, ln2.charCodeAt(iC), true);
  	}
  }

  f_err = t_err;


ID: m200
NAME: Mercury 200
ru#NAME: Меркурий 200
DESCR:
  One phase counter of electricity Mercury 200, 203.2Т, 206 from firm Incotex (http://www.incotexcom.ru).
  Author: Arsen Zakojan <godzilla919@gmail.com>
  Version: 1.0

ru#DESCR:
  Однофазные счетчики электроэнергии Меркурий 200,  203.2Т,  206 компании Инкотекс (http://www.incotexcom.ru).
  Автор: Арсен Закоян <godzilla919@gmail.com>
  Версия 1.0

PROGRAM:
  JavaLikeCalc.JavaScript
  if(naladchik)//если счетчик закондирован программой Наладчик+
  {first=250;
  second=3+(8*netaddr);}
  else//если обычный сетевой адрес(с завода 6 последних цифр)
  {first= floor(netaddr/16777216);//результат деления с округлением в меньшую сторону
  second=netaddr-(first*16777216);}//результат вычисления остатка от деления
  if(f_start){;t1= EVAL_STR;t2= EVAL_STR;t3= EVAL_STR;t4= EVAL_STR;s= EVAL_STR;U= EVAL_STR;I= EVAL_STR;P= EVAL_STR;}//обнуляем значения
  if(tarif)//если выбрано считывание показаний тарифов
  {req = SYS.XMLNode("mess").setAttr("ProtIt","m200").setAttr("first",first).setAttr("second",second).setAttr("data",SYS.strFromCharCode(0x27));}
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(req.text().length <23){ answer = EVAL_STR;t1= EVAL_STR;t2= EVAL_STR;t3= EVAL_STR;t4= EVAL_STR;s= EVAL_STR;}//если нет ответа
  else //если ответ получен
  {t1 =Special.FLibSYS.str2real( req.text().slice(15,17)+req.text().slice(18,20)+req.text().slice(21,23)+req.text().slice(24,26))/100;
  t2 =Special.FLibSYS.str2real( req.text().slice(27,29)+req.text().slice(30,32)+req.text().slice(33,35)+req.text().slice(36,38))/100;
  t3 =Special.FLibSYS.str2real( req.text().slice(39,41)+req.text().slice(42,44)+req.text().slice(45,47)+req.text().slice(48,50))/100;
  t4 =Special.FLibSYS.str2real( req.text().slice(51,53)+req.text().slice(54,56)+req.text().slice(57,59)+req.text().slice(60,62))/100;
  s=t1+t2+t3+t4;}
  if(UIP)//{//если выбрано считывание мгновенных показаний
  {req = SYS.XMLNode().setAttr("ProtIt","m200").setAttr("first",first).setAttr("second",second).setAttr("data",SYS.strFromCharCode(0x63));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");}
  if(req.text().length <14){U= EVAL_STR;I= EVAL_STR;P= EVAL_STR;}//если нет ответа
  else//если ответ получен
  {U =Special.FLibSYS.str2real( req.text().slice(15,17)+req.text().slice(18,20))/10;
  I =Special.FLibSYS.str2real( req.text().slice(21,23)+req.text().slice(24,26))/100;
  P =Special.FLibSYS.str2real( req.text().slice(27,29)+req.text().slice(30,32)+req.text().slice(33,35));}


ID: m230
NAME: Mercury 230
ru#NAME: Меркурий 230
DESCR:
  Three phase counter of electricity Mercury 230, 231, 232, 233, 234, 236 from firm Incotex (http://www.incotexcom.ru).
  Author: Arsen Zakojan <godzilla919@gmail.com>
  Version: 1.0

ru#DESCR:
  Трехфазные счетчики электроэнергии Меркурий 230, 231, 232, 233,  234,  236  компании Инкотекс (http://www.incotexcom.ru).
  Автор: Арсен Закоян <godzilla919@gmail.com>
  Версия 1.0

PROGRAM:
  JavaLikeCalc.JavaScript
  if(f_start)
  //очищаем все данные
  {answer = EVAL_STR;TSAp  = EVAL_STR;TSAm = EVAL_STR;TSRp = EVAL_STR;TSRm = EVAL_STR;
  T1Ap  = EVAL_STR;T1Am = EVAL_STR;T1Rp = EVAL_STR;T1Rm = EVAL_STR;T2Ap  = EVAL_STR;T2Am = EVAL_STR;
  T2Rp = EVAL_STR;T2Rm = EVAL_STR; T3Ap  = EVAL_STR;T3Am = EVAL_STR;T3Rp = EVAL_STR;T3Rm = EVAL_STR;
  T4Ap  = EVAL_STR;T4Am = EVAL_STR;T4Rp = EVAL_STR;T4Rm = EVAL_STR;
  PS = EVAL_STR;P1= EVAL_STR;P2= EVAL_STR;P3= EVAL_STR;U1= EVAL_STR;U2= EVAL_STR;U3= EVAL_STR;
  I1= EVAL_STR;I2= EVAL_STR;I3= EVAL_STR;QS= EVAL_STR;Q1= EVAL_STR;Q2= EVAL_STR;Q3= EVAL_STR;
  SS= EVAL_STR;S1= EVAL_STR;S2= EVAL_STR;S3= EVAL_STR;KS= EVAL_STR;K1= EVAL_STR;K2= EVAL_STR;
  K3= EVAL_STR;F1= EVAL_STR;N1= EVAL_STR;}
  //отправка пароля
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x01,0x01,Special.FLibSYS.str2int(password.slice(0,1)),Special.FLibSYS.str2int(password.slice(1,2)),Special.FLibSYS.str2int(password.slice(2,3)),Special.FLibSYS.str2int(password.slice(3,4)),Special.FLibSYS.str2int(password.slice(4,5)),Special.FLibSYS.str2int(password.slice(5,6))));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()) {answer = EVAL_STR;TSAp  = EVAL_STR;TSAm = EVAL_STR;TSRp = EVAL_STR;TSRm = EVAL_STR;
  T1Ap  = EVAL_STR;T1Am = EVAL_STR;T1Rp = EVAL_STR;T1Rm = EVAL_STR;T2Ap  = EVAL_STR;T2Am = EVAL_STR;
  T2Rp = EVAL_STR;T2Rm = EVAL_STR; T3Ap  = EVAL_STR;T3Am = EVAL_STR;T3Rp = EVAL_STR;T3Rm = EVAL_STR;
  T4Ap  = EVAL_STR;T4Am = EVAL_STR;T4Rp = EVAL_STR;T4Rm = EVAL_STR;
  PS = EVAL_STR;P1= EVAL_STR;P2= EVAL_STR;P3= EVAL_STR;U1= EVAL_STR;U2= EVAL_STR;U3= EVAL_STR;
  I1= EVAL_STR;I2= EVAL_STR;I3= EVAL_STR;QS= EVAL_STR;Q1= EVAL_STR;Q2= EVAL_STR;Q3= EVAL_STR;
  SS= EVAL_STR;S1= EVAL_STR;S2= EVAL_STR;S3= EVAL_STR;KS= EVAL_STR;K1= EVAL_STR;K2= EVAL_STR;
  K3= EVAL_STR;F1= EVAL_STR;N1= EVAL_STR;return;}
  else answer =req.text();
  //Энергия от сброса сумма Т
  if(TS){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x05,0x00,0x00));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){TSAp  = EVAL_STR;TSAm = EVAL_STR;TSRp = EVAL_STR;TSRm = EVAL_STR; }
  else {
  if(req.text().slice(0,10)!=2147483647)TSAp=req.text().slice(0,10)/1000;
  else TSAp= EVAL_STR;
  if(req.text().slice(10,20)!=2147483647)TSAm=req.text().slice(10,20)/1000;
  else TSAm= EVAL_STR;
  if(req.text().slice(20,30)!=2147483647)TSRp=req.text().slice(20,30)/1000;
  else TSRp= EVAL_STR;
  if(req.text().slice(30,40)!=2147483647)TSAm=req.text().slice(30,40)/1000;
  else TSRm= EVAL_STR;}
  }
  if(T1){
  //Энергия от сброса Т1
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x05,0x00,0x01));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){T1Ap  = EVAL_STR;T1Am = EVAL_STR;T1Rp = EVAL_STR;T1Rm = EVAL_STR; }
  else {
  if(req.text().slice(0,10)!=2147483647)T1Ap=req.text().slice(0,10)/1000;
  else T1Ap= EVAL_STR;
  if(req.text().slice(10,20)!=2147483647)T1Am=req.text().slice(10,20)/1000;
  else T1Am= EVAL_STR;
  if(req.text().slice(20,30)!=2147483647)T1Rp=req.text().slice(20,30)/1000;
  else T1Rp= EVAL_STR;
  if(req.text().slice(30,40)!=2147483647)T1Am=req.text().slice(30,40)/1000;
  else T1Rm= EVAL_STR;}
  }
  //Энергия от сброса Т2
  if(T2){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x05,0x00,0x02));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){T2Ap  = EVAL_STR;T2Am = EVAL_STR;T2Rp = EVAL_STR;T2Rm = EVAL_STR; }
  else {
  if(req.text().slice(0,10)!=2147483647)T2Ap=req.text().slice(0,10)/1000;
  else T2Ap= EVAL_STR;
  if(req.text().slice(10,20)!=2147483647)T2Am=req.text().slice(10,20)/1000;
  else T2Am= EVAL_STR;
  if(req.text().slice(20,30)!=2147483647)T2Rp=req.text().slice(20,30)/1000;
  else T2Rp= EVAL_STR;
  if(req.text().slice(30,40)!=2147483647)T2Am=req.text().slice(30,40)/1000;
  else T2Rm= EVAL_STR;}
  }
  //Энергия от сброса Т3
  if(T3){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x05,0x00,0x03));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){T3Ap  = EVAL_STR;T3Am = EVAL_STR;T3Rp = EVAL_STR;T3Rm = EVAL_STR; }
  else {
  if(req.text().slice(0,10)!=2147483647)T3Ap=req.text().slice(0,10)/1000;
  else T3Ap= EVAL_STR;
  if(req.text().slice(10,20)!=2147483647)T3Am=req.text().slice(10,20)/1000;
  else T3Am= EVAL_STR;
  if(req.text().slice(20,30)!=2147483647)T3Rp=req.text().slice(20,30)/1000;
  else T3Rp= EVAL_STR;
  if(req.text().slice(30,40)!=2147483647)T3Am=req.text().slice(30,40)/1000;
  else T3Rm= EVAL_STR;}
  }
  //Энергия от сброса Т4
  if(T4){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x05,0x00,0x04));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){T4Ap  = EVAL_STR;T4Am = EVAL_STR;T4Rp = EVAL_STR;T4Rm = EVAL_STR; }
  else {
  if(req.text().slice(0,10)!=2147483647)T4Ap=req.text().slice(0,10)/1000;
  else T4Ap= EVAL_STR;
  if(req.text().slice(10,20)!=2147483647)T4Am=req.text().slice(10,20)/1000;
  else T4Am= EVAL_STR;
  if(req.text().slice(20,30)!=2147483647)T4Rp=req.text().slice(20,30)/1000;
  else T4Rp= EVAL_STR;
  if(req.text().slice(30,40)!=2147483647)T4Am=req.text().slice(30,40)/1000;
  else T4Rm= EVAL_STR;}
  }
  //Мощность P
  if(P){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x08,0x16,0x00));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){PS=EVAL_STR;P1=EVAL_STR;P2=EVAL_STR;P3=EVAL_STR;}
  else PS=req.text().slice(0,7)/100;P1=req.text().slice(7,14)/100;P2=req.text().slice(14,21)/100;P3=req.text().slice(21,28)/100;}
  //Мощность Q
  if(Q){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x08,0x16,0x04));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){QS=EVAL_REAL;Q1=EVAL_REAL;Q2=EVAL_REAL;Q3=EVAL_REAL;}
  else 
  {if (req.text().slice(28,29)==4||req.text().slice(28,29)=="C")QS=(req.text().slice(0,7)/100)*-1;
  else QS=(req.text().slice(0,7)/100);
  if (req.text().slice(29,30)==4||req.text().slice(29,30)=="C")Q1=(req.text().slice(7,14)/100)*-1;
  else Q1=(req.text().slice(7,14)/100);
  if (req.text().slice(30,31)==4||req.text().slice(30,31)=="C")Q2=(req.text().slice(14,21)/100)*-1;
  else Q2=(req.text().slice(14,21)/100);
  if (req.text().slice(31,32)==4||req.text().slice(31,32)=="C")Q3=(req.text().slice(21,28)/100)*-1;
  else Q3=(req.text().slice(21,28)/100);}}
  //Мощность S
  if(S){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x08,0x16,0x08));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){SS=EVAL_STR;S1=EVAL_STR;S2=EVAL_STR;S3=EVAL_STR;}
  else SS=req.text().slice(0,7)/100;S1=req.text().slice(7,14)/100;S2=req.text().slice(14,21)/100;S3=req.text().slice(21,28)/100;}
  // Напряжение U
  if(U){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x08,0x16,0x11));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){U1=EVAL_STR;U2=EVAL_STR;U3=EVAL_STR;}
  else U1=req.text().slice(0,8)/100;U2=req.text().slice(8,16)/100;U3=req.text().slice(16,24)/100;}
  //Ток I
  if(I){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x08,0x16,0x21));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){I1=EVAL_STR;I2=EVAL_STR;I3=EVAL_STR;}
  else I1=req.text().slice(0,8)/1000;I2=req.text().slice(8,16)/1000;I3=req.text().slice(16,24)/1000;}
  //Коэффициент мощности
  if(K){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x08,0x16,0x30));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text()){KS=EVAL_STR;K1=EVAL_STR;K2=EVAL_STR;K3=EVAL_STR;}
  else KS=req.text().slice(0,7)/1000;K1=req.text().slice(7,14)/1000;K2=req.text().slice(14,21)/1000;K3=req.text().slice(21,28)/1000;}
  //частота F
  if(F){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x08,0x16,0x40));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text())F1= EVAL_STR;
  else F1 =req.text();}
  //серийный номер
  if(N){
  req = SYS.XMLNode().setAttr("ProtIt","m230").setAttr("netaddr",netaddr).setAttr("data",SYS.strFromCharCode(0x08,0x00));
  SYS.Transport["Serial"]["out_"+transport].messIO(req,"UserProtocol");
  if(!req.text())N1= EVAL_STR;
  else N1 =req.text();}


