# tmplib_LowDevLib_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)


# techApp

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

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

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

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);


ID: ballCrane
NAME: Ball crane
uk#NAME: Кульовий кран
ru#NAME: Шаровый кран
DESCR: Model of the ball crane. Includes for the going and estrangement time.
uk#DESCR: Модель кульового крану. Включає час ходу та час відриву.
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
uk#NAME: Сепаратор
ru#NAME: Сепаратор
DESCR: Separator model with two phases, liquid and gas.
uk#DESCR: Модель сепаратору з двома фазами, рідинною та газовою.
ru#DESCR: Модель сепаратора с двумя фазами, жидкой и газовой.
FORMULA:
  Flq = max(0, Fi*PercLq);
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi, Pi, 293, Si, Fo+Flq, Po, 293, So, lo, Q0, 0.95, 0.01, f_frq);
  Llq = max(0, min(100,Llq+0.27*(Flq-Fo_lq)/(Vap*Qlq*f_frq)));
  Po_lq = Po + Llq*Vap/Qlq;


ID: valve
NAME: Valve
uk#NAME: Клапан
ru#NAME: Клапан
DESCR:
  Valve model, includes:
  - two valves in the one;
  - super-critical speed;
  - temperature changing at the throttling;
  - work in one direction, back valve;
  - speed control of the position changing;
  - nonlinearity of the intersection from the position.

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

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

FORMULA:
  Qr = Q0+Q0*Kpr*(Pi-1);
  tmp_l1 += (abs(l_v1-tmp_l1) > 5) ? 100*sign(l_v1-tmp_l1)/(t_v1*f_frq) : (l_v1-tmp_l1)/(t_v1*f_frq);
  tmp_l2 += (abs(l_v2-tmp_l2) > 5) ? 100*sign(l_v2-tmp_l2)/(t_v2*f_frq) : (l_v2-tmp_l2)/(t_v2*f_frq);
  Sr = (S_v1*pow(tmp_l1,Kln)+S_v2*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)));


ID: lagClean
NAME: Lag: clean
uk#NAME: Затримка: чиста
ru#NAME: Задержка: чистая
DESCR:
  Model of clean(transportable) lag. Realizes by incorporating several links of a simple delay. Appointed for lags into long pipes.

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

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

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);


ID: net
NAME: Network: load
uk#NAME: Мережа: навантаження
ru#NAME: Сеть: нагрузка
DESCR: Loading with constant pressure on the network. Contains a parameter for connection the noise.
uk#DESCR: Навантаження з фіксованим тиском мережі. Містить параметр для підключення шуму.
ru#DESCR: Нагрузка с фиксированным давлением сети. Содержит параметр для подключения шума.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fi, Pi, 293, So, EVAL_REAL, Po, 293, So, 10, Q0, Kpr, 0.01, f_frq);


ID: src_press
NAME: Source: pressure
uk#NAME: Джерело: тиск
ru#NAME: Источник: давление
DESCR: Source of the constant pressure. Contains a parameter for connection the noise.
uk#DESCR: Джерело з фіксованим тиском. Містить параметр для підключення шуму.
ru#DESCR: Источник с фиксированным давлением. Содержит параметр для подключения шума.
FORMULA:
  DAQ.JavaLikeCalc.lib_techApp.pipeBase(Fit, Pi*Noise, 293, So, Fo, Po, 293, So, lo, Q0, Kpr, 0.01, f_frq);


ID: cooler
NAME: Air cooler
uk#NAME: Повітряний холодильник
ru#NAME: Воздушный холодильник
DESCR: Model of the air cooler for gas flow.
uk#DESCR: Модель повітряного охолоджувача газового потоку.
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. Implements the surge effect.
  The surge counts from the dynamic-gas curve, and next there counts the surge margin coefficient.

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

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

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;
  Kmrg = 1-Ftmp;  //The margin coefficient
  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);


ID: pipe1_1
NAME: Pipe 1->1
uk#NAME: Труба 1->1
ru#NAME: Труба 1->1
DESCR: Model of the pipe by the scheme "1 -> 1".
uk#DESCR: Модель вузла труб за схемою "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
uk#NAME: Труба 1->2
ru#NAME: Труба 1->2
DESCR: Model of the pipe by the scheme "1 -> 2".
uk#DESCR: Модель вузла труб за схемою "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
uk#NAME: Труба 1->3
ru#NAME: Труба 1->3
DESCR: Model of the pipe by the scheme "1 -> 3".
uk#DESCR: Модель вузла труб за схемою "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
uk#NAME: Труба 1->4
ru#NAME: Труба 1->4
DESCR: Model of the pipe by the scheme "1 -> 4".
uk#DESCR: Модель вузла труб за схемою "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: valveMech
NAME: Valve: processing mechanism
uk#NAME: Клапан: виконавчий механізм
ru#NAME: Клапан: исполнительный механизм
DESCR: Model of the valve processing mechanism. Includes the going and estrangement time.
uk#DESCR: Модель виконавчого механізму клапана. Включає час ходу та час відриву.
ru#DESCR: Модель исполнительного механизма клапана. Включает время хода и время отрыва.
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: diaphragm
NAME: Diaphragm
uk#NAME: Діафрагма
ru#NAME: Диафрагма
DESCR: Diaphragm model.
uk#DESCR: Модель діафрагми.
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
uk#NAME: Труба 3->1
ru#NAME: Труба 3->1
DESCR: Model of the pipe by the scheme "3 -> 1".
uk#DESCR: Модель вузла труб за схемою "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 pipe model:
  - flow in the pipe, taking into account: the speed, pressure difference, resistance due to friction and the critical flow;
  - calculation of the pressure;
  - accounting for the environment density and degree of the compressibility for both gases and liquids.

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

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

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)));


ID: heatExch
NAME: Heat exchanger
uk#NAME: Теплообмінник
ru#NAME: Теплообменник
DESCR: Model of the heat exchanger, calculating the heat exchange of the two streams.
uk#DESCR: Модель теплообміннику, що розраховує теплообмін двох потоків.
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
uk#NAME: Котел: барабан
ru#NAME: Котёл: барабан
DESCR: The model of the boiler's barrel.
uk#DESCR: Модель барабану котлоагрегату.
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-Fstm)*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;
    Fstm = 0;
  }
  if(Tv >= To1) {
    Tv = To1;
    Lambda = 2750-0.00418*(Tv-273);
    Fstm = (5*S*Fi2*(Ti2-Tv)-Fi1*0.00418*(Tv-Ti1))/(Po1*Lambda);
  }

  To2 = Ti2-Tv/k;
  Po1 = max(0, min(100,Po1+0.27*(Fstm-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: Котёл: топка
DESCR:
  The fire-chamber model of the boiler unit, which operates on three types of fuel, initially is: blast-furnace, coke and natural gases.

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

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

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)));


ID: pipe2_1
NAME: Pipe 2->1
uk#NAME: Труба 2->1
ru#NAME: Труба 2->1
DESCR: Model of the pipe by the scheme "2 -> 1".
uk#DESCR: Модель вузла труб за схемою "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));


# 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]));


ID: diagram
NAME: Diagram
FORMULA:
  im = SYS.XMLNode();
  im.load(tmpl, false, 3);
  if(!(drawArea=im.getElementBy("drawArea")) ||
  		!(scVert=im.getElementBy("scVert")) ||
  		!(scHor=im.getElementBy("scHor")))
  	return "";

  //Getting the trends data
  trends = new Array();
  for(off = 0; (tEl=srcs.parseLine(0,off)).length; ) {
  	elO = new Object();
  	elO.addr = tEl.parse(0, ":");
  	if(!(srcO=SYS.nodeAt(elO.addr)))	continue;
  	if(typeof(srcO) == "TCntrNode:TVal")	srcO = srcO.arch();
  	if(typeof(srcO) != "TCntrNode:TVArchive")	continue;
  	elO.srcO = srcO;
  	elO.min = tEl.parse(1, ":"); elO.max = tEl.parse(2, ":");
  	elO.color = tEl.parse(3, ":");
  	trends.push(elO);
  }

  im.setAttr("width", hsz).setAttr("height", vsz).setAttr("viewBox", "0 0 "+hsz+" "+vsz);

  mrkFontSize = 12;	//????
  mrkFontWRange = 0.7;
  mrkWidth = 5*mrkFontSize*mrkFontWRange;
  mrkHeight = mrkFontSize;

  tArMrg = 2;
  tArX	= tArMrg;
  tArW	= hsz - tArX - tArMrg;
  tArY	= tArMrg;
  tArH	= vsz - tArY - tArMrg - mrkHeight*2;

  scVert.childAdd("rect").setAttr("x",tArX).setAttr("y",tArY).setAttr("width",1).setAttr("height",tArH);
  scVert.childAdd("rect").setAttr("x",tArX+tArW).setAttr("y",tArY).setAttr("width",1).setAttr("height",tArH);
  scHor.childAdd("rect").setAttr("x",tArX).setAttr("y",tArY+tArH).setAttr("width",tArW).setAttr("height",1);
  scHor.childAdd("rect").setAttr("x",tArX).setAttr("y",tArY).setAttr("width",tArW).setAttr("height",1);

  if(!end)	end = SYS.time();
  begin = end - size;
  reqPer = size/vsz;

  //Calc and draw the horizontal scale
  hDiv = 1;			//Horisontal scale divisor
  hmax_ln = tArW / mrkWidth;
  if(hmax_ln >= 2) {
  	hvLev = 0;
  	hLen = end - begin;

  	if(hLen/2635200 >= 5)		{ hvLev = 7; hDiv = 2635200; }	//Month a unstrict interval !!!! to implement !!!!
  	else if(hLen/86400 >= 5)	{ hvLev = 6; hDiv =   86400; }	//More days and no time in the scale
  	else if(hLen/86400 >= 2)	{ hvLev = 5; hDiv =   86400; }	//Days
  	else if(hLen/3600 >= 2)	{ hvLev = 4; hDiv =    3600; }	//Hours
  	else if(hLen/60 >= 2)		{ hvLev = 3; hDiv =      60; }	//Minutes
  	else if(hLen/1 >= 2)		{ hvLev = 2; hDiv =       1; }	//Seconds
  	else if(hLen/0.001 >= 2)	{ hvLev = 1; hDiv =   0.001; }	//Milliseconds

  	hDiv_ = hDiv;
  	while(hLen/hDiv_ > hmax_ln)	hDiv_ *= 10;
  	while(hLen/hDiv_ < hmax_ln/5 && (hDiv_/5)%hDiv == 0) hDiv_ /= 5;
  	while(hLen/hDiv_ < hmax_ln/2 && (hvLev < 6 || (hDiv_/2)%hDiv == 0)) hDiv_ /= 2;
  	hDiv = hDiv_;

  	UTChourDt = SYS.strptimegm(SYS.strftime(end)) - end;

  	// Draw the horisontal grid and markers
  	tm_t = 0;
  	lab_tm = lab_dt = "";
  	//  Draw full trend's data and time to the trend end position
  	begMarkBrd = -5;
  	endMarkBrd = tArX + tArW;

  	lab_dt = SYS.strftime(end, "%d-%m-%Y");
  	if((end%60) == 0 && (end-floor(end)) == 0)
  		lab_tm = SYS.strftime(end, "%H:%M");
  	else if((end-floor(end)) == 0)
  		lab_tm = SYS.strftime(end, "%H:%M:%S");
  	else lab_tm = SYS.strftime(end, "%H:%M:%S")+"."+(end-floor(end));

  	if(hvLev < 6) {
  		scHor.childAdd("text").setAttr("text-anchor","end").setAttr("stroke","none")
  			.setAttr("fill", "black")
  			.setAttr("x",tArX+tArW).setAttr("y",tArY+tArH+2*mrkHeight).setText(lab_tm);
  		endMarkBrd = min(endMarkBrd, tArX + tArW - mrkFontSize*lab_tm.length*mrkFontWRange);
  	}
  	scHor.childAdd("text").setAttr("text-anchor","end").setAttr("stroke","none")
  		.setAttr("fill", "black")
  		.setAttr("x",tArX+tArW).setAttr("y",tArY+tArH+mrkHeight).setText(lab_dt);
  	endMarkBrd = min(endMarkBrd, tArX + tArW - mrkFontSize*lab_dt.length*mrkFontWRange);
  }

  //  Draw grid and/or markers
  first_m = true;
  ttm1 = new Object();
  for(i_h = begin; true; ) {
  	//   Draw grid
  	h_pos = tArX + tArW*(i_h-begin)/(end-begin);

  	if(i_h > begin && i_h < end)
  		scHor.childAdd("rect").setAttr("x",h_pos.toFixed(2)).setAttr("y",(tArY+tArH-3).toFixed(2)).setAttr("width",1).setAttr("height",6);

  	//   Draw markers
  	if(!((i_h+UTChourDt)%hDiv) && i_h != end) {
  		if(first_m)	SYS.localtime(begin-(end-begin), ttm1.sec, ttm1.min, ttm1.hour, ttm1.mday, ttm1.mon);
  		ttm = new Object();
  		SYS.localtime(i_h, ttm.sec, ttm.min, ttm.hour, ttm.mday, ttm.mon);

  		chLev = 0;
  		if((ttm.mon-ttm1.mon) || (ttm.year-ttm1.year)) chLev = 5;
  		else if(ttm.mday-ttm1.mday)	chLev = 4;
  		else if(ttm.hour-ttm1.hour)	chLev = 3;
  		else if(ttm.min-ttm1.min)		chLev = 2;
  		else if(ttm.sec-ttm1.sec)		chLev = 1;

  		//Checking for the data presence
  		lab_dt = lab_tm = "";
  		//Date
  		if(/*hvLev == 5 ||*/ chLev >= 4)
  			lab_dt = SYS.strftime(i_h, (chLev>=5)?"%d-%m-%Y":"%d");
  		//Hours and minuts
  		if((hvLev == 4 || hvLev == 3 || ttm.hour || ttm.min) && !ttm.sec)
  			lab_tm = SYS.strftime(i_h, "%H:%M");
  		//Seconds
  		else if((hvLev == 2 || ttm.sec) && !((i_h-floor(i_h))*1e6))
  			lab_tm = (chLev >= 2) ? SYS.strftime(i_h, "%H:%M:%S") : SYS.strftime(i_h, "%S");
  		//Milliseconds
  		else if(hvLev <= 1 || (i_h-floor(i_h))*1e6)
  			lab_tm = (chLev >= 2) ? SYS.strftime(i_h, "%H:%M:%S")+(i_h-floor(i_h)) :
  						(chLev >= 1) ? SYS.strftime(i_h, "%S")+"."+(i_h-floor(i_h))+tr("s") :
  											(1e3*i_h).toPrecision(6)+tr("ms");

  		endPosTm = endPosDt = 0, markY = tArY + tArH + mrkHeight;
  		if(hvLev < 6) {
  			if(lab_tm.length) {
  				wdth = mrkFontSize*lab_tm.length*mrkFontWRange;
  				tpos = max(h_pos-wdth/2, 0);
  				if((tpos+wdth) < endMarkBrd && tpos > begMarkBrd) {
  					scHor.childAdd("text").setAttr("text-anchor","middle").setAttr("stroke","none")
  						.setAttr("fill", "black")
  						.setAttr("x",h_pos.toFixed(2)).setAttr("y",markY.toFixed(2)).setText(lab_tm);
  					endPosTm = tpos+wdth;
  				}
  			}
  			markY += mrkHeight;
  		}
  		if(lab_dt.size()) {
  			wdth = mrkFontSize*lab_dt.length*mrkFontWRange;
  			tpos = max(h_pos-wdth/2, 0);
  			if((tpos+wdth) < endMarkBrd && tpos > begMarkBrd) {
  				scHor.childAdd("text").setAttr("text-anchor","middle").setAttr("stroke","none")
  					.setAttr("fill", "black")
  					.setAttr("x",h_pos.toFixed(2)).setAttr("y",markY.toFixed(2)).setText(lab_dt);
  				endPosDt = tpos+wdth;
  			}
  		}
  		begMarkBrd = max(begMarkBrd, max(endPosTm,endPosDt));
  		ttm1 = ttm;
  		first_m = false;
  	}

  	//   Next
  	if(i_h >= end) break;
  	i_h = floor((i_h+UTChourDt)/hDiv)*hDiv + hDiv - UTChourDt;
  	if(i_h > end)	i_h = end;
  }

  //Drawing the trends
  for(iTr = 0; iTr < trends.length; iTr++) {
  	elO = trends[iTr];
  	trBeg = begin*1e6; trPer = reqPer*1e6;
  	dataAr = elO.srcO.getVals(trBeg, end*1e6, trPer);

  	trPath = 0; prev_vl = EVAL; prev_pos = 0;
  	for(iDt = 0; iDt < dataAr.length; iDt++) {
  		c_val = dataAr[iDt];
  		c_tm = 1e-6*(trBeg + iDt*trPer);
  		if(c_tm < begin)	continue;
  		c_pos = floor(tArX + tArW*(c_tm-begin)/(end-begin));
  		if(!c_val.isEVal()) {
  			c_vpos = floor(tArY + tArH - tArH*(c_val-elO.min)/(elO.max-elO.min));
  			if(!trPath) trPath = drawArea.childAdd("path").setAttr("stroke", elO.color);
  			if(prev_vl.isEVal()) trPath.setAttr("d", trPath.attr("d")+"M"+c_pos+","+c_vpos);
  			else trPath.setAttr("d",trPath.attr("d")+"L"+c_pos+","+c_vpos);
  		}
  		else if(!prev_vl.isEVal()) {
  			c_vpos = floor(tArY + tArH - tArH*(prev_vl-elO.min)/(elO.max-elO.min));
  			trPath.setAttr("d", trPath.attr("d")+"L"+prev_pos+".1,"+c_vpos+".1");
  		}
  		prev_vl = c_val; prev_pos = c_pos;
  	}
  	//res += elO.addr+": ["+SYS.strftime(trBeg/1e6)+"-"+SYS.strftime(end)+"]("+reqPer+"->"+(trPer/1e6)+")"+dataAr.length+"\n";
  }

  return im.save();


