function init(){
    out = $("out");
    log = $("log");

    firstPKU=0;
    typePage=0;
    isConnect=true;

    currentPKU=0;
    currentDev=0;
    currentPart=0;
    currentGPart=0;

    mTable1 = document.createElement("table");
    var mTable2 = document.createElement("table");

    if (typeof pwd == "undefined") bPWD = false;
    else bPWD = true;

    if (bPWD)
    {
        mTable1.innerHTML = "<tr><td id=tableMP class=borderHid></td> <td class=borderHid style='text-align:left'> <p><label>Пароль оператора: <input id='pwdu' type='password'></label> <button onClick='wsUserID()'>Авторизоваться</button> <br>Статус авторизации: <a id=statusA></a></p> </td></tr>";
    }
    else
    {
        strLogin1Table  = "<tr> <td class=borderHid style='text-align:left'> <label>Логин: <input id='armId'></label> <label>Пароль: <input id='pwd' type='password'></label> <button onClick='wsARMID()'>Подключиться</button> </td> </tr>";
        strLogin2Table  = "<tr> <td id=tableMP class=borderHid> </td> <td class=borderHid style='text-align:left'> <p><label>Пароль оператора: <input id='pwdu' type='password'></label> <button onClick='wsUserID()'>Авторизоваться</button> <br>Статус авторизации: <a id=statusA></a></p> </td> </tr>";

        mTable1.innerHTML = strLogin1Table;
    }

    mTable2.innerHTML = "<tr><td id=tableM1 class=borderHid></td><td id=tableM2 class=borderHid></td><td id=tableM3 class=borderHid></td><td id=tableM4 class=borderHid></td></tr>";
    if (out){
        out.appendChild(mTable1);
        out.appendChild(mTable2);
    }

    if (bPWD) newWS();
}
//---------------------------------------------------------------------------
function setTypePage(type){ typePage=type; selectPKU( firstPKU ); }
//---------------------------------------------------------------------------
function newWS(){
    if (isConnect){
        isConnect=false;
        writeLog("Попытка подключения " + wsUri);
    }

    if (typeof websocket == "object") delete websocket;
    websocket = new WebSocket(wsUri);
    websocket.onopen   = function(evt) { onOpen   (evt) };
    websocket.onclose  = function(evt) { onClose  (evt) };
    websocket.onerror  = function(evt) { onError  (evt) };
    websocket.onmessage= function(evt) { onMessage(evt) };
}
//---------------------------------------------------------------------------
function wsSend(msg) {if (typeof websocket == "object") websocket.send( JSON.stringify(msg) );}
function wsUserID(){ var obj=$("pwdu"); if (obj) {wsSend({funct:"userId",pwd:b64_sha1( obj.value )}); obj.value="";}}
function onOpen(evt) {isConnect=true; writeLog("Удачно."); wsSend( {funct:"armId",id:armId,pwd:pwd} );}
function onError(evt){if (isConnect) writeLog("Ошибка.");}
//---------------------------------------------------------------------------
function wsARMID(){
    var obj1=$("armId");
    var obj2=$("pwd");

    if (obj1 && obj2) {
        armId = obj1.value;
        pwd   = b64_sha1( obj2.value );
        newWS()
    }
}
//---------------------------------------------------------------------------
function onClose(evt){
    if (typeof websocket == "object") delete websocket;
    if (isConnect){
        writeLog("Отключение.");

        if (bPWD)
        {
            var mtable = $("tableM1");
            if (mtable) mtable.innerHTML = "";

            mtable = $("tableM2");
            if (mtable) mtable.innerHTML = "";

            mtable = $("tableM3");
            if (mtable) mtable.innerHTML = "";

            mtable = $("tableM4");
            if (mtable) mtable.innerHTML = "";

            obj=$("statusA");
            if (obj) obj.innerHTML="не идентифицирован";
        }
        else
        {
            mTable1.innerHTML = strLogin1Table;
        }
    }
    window.setTimeout(newWS, 1000);
}
//---------------------------------------------------------------------------
function onMessage(evt)
{
    var data = JSON.parse(evt.data);

    switch(data.funct){
    case "armId":
        if (data.ret==true)
        {
            if (!bPWD)
                mTable1.innerHTML = strLogin2Table;
            wsSend( {funct:"getListPKU"} );
        }
        else writeLog("Неудачная авторизация рабочего места. Смотрите лог сервера.");

        break;
    case "userId": var obj=$("statusA"); if (obj){ if (data.ret==true) obj.innerHTML=data.pwd; else obj.innerHTML="не идентифицирован";} break;
    case "getListPKU": createPkuTable(data.ret); break;
    case "getPKUVersion":     var obj=$("verPKU"  +data.pku); if (obj) obj.innerHTML = data.ret/100; break;
    case "getPKUTypeStr":     var obj=$("typePKU" +data.pku); if (obj) obj.innerHTML = data.ret; break;
    case "getPKUDescription": var obj=$("descrPKU"+data.pku); if (obj) obj.innerHTML = data.ret; break;

    case "getListDevices":   createDevTable  (data.pku, data.ret); break;
    case "getListParts":     createPartTable (data.pku, data.ret); break;
    case "getListGParts":    createGPartTable(data.pku, data.ret); break;

    case "getListGPartParts":if (data.req==currentGPart) createPartTable(data.pku, data.ret); break;

    case "getListPartSh":    if (data.req==currentPart)  createShTable(data.pku, data.ret);    break;
    case "getListPartExit":  if (data.req==currentPart)  appendExitToShTable(data.pku, data.ret); break;
    case "getListPartDev":   if (data.req==currentPart)  appendDevToShTable (data.pku, data.ret); break;

    case "getListSh":        if (data.req==currentDev)   createShTable(data.pku, data.ret); break;
    case "getListRelay":     if (data.req==currentDev)   appendRlToShTable(data.pku, data.ret); break;
    case "getListReader":    if (data.req==currentDev)   appendRdToShTable(data.pku, data.ret); break;
    case "getListExit":      if (data.req==currentDev)   wsSend( {funct:"getExitState",pku:data.pku,req:data.ret} );break;

    case "getDeviceTypeStr":    updateDevType  (data.pku, data.req, data.ret); break;
    case "getDeviceVersion":    updateDevVer   (data.pku, data.req, data.ret); break;
    case "getDeviceDescription":updateDevDescr (data.pku, data.req, data.ret); break;
    case "getDeviceState":      updateDevState (data.pku, data.req, data.ret); break;
    case "getDeviceTamperState":updateDevTamper(data.pku, data.req, data.ret); break;
    case "getDevicePowerState": updateDevPower (data.pku, data.req, data.ret); break;

    case "getPartDescription":  updatePartDescr(data.pku, data.req, data.ret); break;
    case "getPartState":        updatePartState(data.pku, data.req, data.ret); break;

    case "getShDescription":    updateShDescr(data.pku, data.req, data.ret); break;
    case "getShState":          updateShState(data.pku, data.req, data.ret); break;
    case "getShADC":            updateShADC  (data.pku, data.sh,  data.ret, data.val); break;

    case "getRelayDescription": updateRelayDescr(data.pku, data.req, data.ret); break;
    case "getRelayState":       updateRelayState(data.pku, data.req, data.ret); break;
    case "getExitState":        updateExitState (data.pku, data.req, data.ret); break;

    case "getReaderDescription":updateReaderDescr(data.pku, data.req, data.ret); break;
    case "getReaderState":      updateReaderState(data.pku, data.req, data.ret); break;
    case "getEvents":           updateEvents(data.pku, data.first, data.count, data.total, data.ret); break;
    }
}
//---------------------------------------------------------------------------
function createPkuTable(listPKU) {
    firstPKU = listPKU[0];

    var mtable = $("tableMP");
    if (mtable) {
        var table = document.createElement("table");
        var str = "<tr><th>Пульт</th><th>Тип</th><th>Версия</th><th>Описание</th></tr>";

        for (var i=0; i<listPKU.length; i++){
            var pku = listPKU[i];
            str += "<tr><td class='hover' onClick='selectPKU(" +pku+ ")'>" +pku+ "</td><td id=typePKU" +pku+ "></td><td id=verPKU" +pku+ "></td><td id=descrPKU" +pku+ "></td></tr>";
            wsSend( {funct:"getPKUVersion",pku:pku} );
            wsSend( {funct:"getPKUTypeStr",pku:pku} );
            wsSend( {funct:"getPKUDescription",pku:pku} );
        }

        table.innerHTML = str;
        mtable.innerHTML = "";
        mtable.appendChild(table);

        selectPKU( firstPKU );
    }
}
//---------------------------------------------------------------------------
function createDevTable(pku, devs) {
    var mtable;
    if ( (pku==currentPKU) && (typePage==2) ) mtable = $("tableM1");

    if (mtable) {
        var table = document.createElement("table");
        var str = "<tr><th>Прибор</th><th>Тип</th><th>Версия</th><th>Описание</th><th>Тампер</th><th>Электропитание</th></tr>";

        for (var i=0; i<devs.length; i++){
            var dev = devs[i];
            var id = pku + "-" + dev;
            str += "<tr><td class='hover' onClick='selectDev(" +pku+ "," +dev+ ")'>" + dev + "</td><td id=typeDev" + id +"><td id=verDev" + id +"></td></td><td id=descrDev" + id +"></td><td id=state1Dev" + id +"></td><td id=state2Dev" + id +"></td></tr>";
        }

        table.innerHTML = str;
        mtable.innerHTML = "";
        mtable.appendChild(table);

        if (devs.length>0){
            wsSend( {funct:"getDeviceTypeStr",pku:pku,req:devs} );
            wsSend( {funct:"getDeviceVersion",pku:pku,req:devs} );
            wsSend( {funct:"getDeviceDescription",pku:pku,req:devs} );
            wsSend( {funct:"getDeviceTamperState",pku:pku,req:devs} );
            wsSend( {funct:"getDevicePowerState",pku:pku,req:devs} );
        }
    }
}
//---------------------------------------------------------------------------
function createPartTable(pku, parts) {
    var mtable;
    if (pku==currentPKU){
        if      (typePage==0) mtable = $("tableM1");
        else if (typePage==1) mtable = $("tableM2");
    }

    if (mtable) {
        var table = document.createElement("table");
        var str = "<tr><th>Раздел</th><th>Описание</th><th>Состояние</th></tr>";

        for (var i=0; i<parts.length; i++){
            var part = parts[i];
            var id = pku + "-" + part;
            str += "<tr><td class='hover' onClick='selectPart(" +pku+ "," +part+ ")'>" + part + "</td><td id=descrPart" +id+ "></td><td class='hover' id=statePart" +id+ " onClick='controlPart(" +pku+ "," +part+ ")'></td></tr>";
        }

        table.innerHTML = str;
        mtable.innerHTML = "";
        mtable.appendChild(table);

        if (parts.length>0){
            wsSend( {funct:"getPartDescription",pku:pku,req:parts} );
            wsSend( {funct:"getPartState",pku:pku,req:parts} );
        }
    }
}
//---------------------------------------------------------------------------
function createGPartTable(pku, gparts) {
    var mtable;
    if ( (pku==currentPKU) && (typePage==1) ) mtable = $("tableM1");

    if (mtable) {
        var table = document.createElement("table");
        var str = "<tr><th>Группа</th><th>Описание</th><th>Состояние</th></tr>";

        for (var i=0; i<gparts.length; i++){
            var gpart = gparts[i];
            var id = pku + "-" + gpart;
            str += "<tr><td onClick='selectGPart(" +pku+ "," +gpart+ ")' class='hover'>" + gpart + "</td><td id=descrPart" + id +"></td><td class='hover' id=statePart" +id+ " onClick='controlPart(" +pku+ "," +gpart+ ")'></td></tr>";
        }

        table.innerHTML = str;
        mtable.innerHTML = "";
        mtable.appendChild(table);

        if (gparts.length>0){
            wsSend( {funct:"getPartDescription",pku:pku,req:gparts} );
            wsSend( {funct:"getPartState",pku:pku,req:gparts} );
        }
    }
}
//---------------------------------------------------------------------------
function createShTable(pku, shs) {
    var mtable;
    if (pku==currentPKU){
        if      (typePage==0) mtable = $("tableM2");
        else if (typePage==1) mtable = $("tableM3");
        else if (typePage==2) mtable = $("tableM2");
    }

    if (mtable) {
        var table = document.createElement("table");
        table.id="tableSH";
        var str = "<tr><th>ШС</th><th>Описание</th><th>Состояние</th><th>АЦП</th></tr>";

        for (var i=0; i<shs.length; i++){
            var sh = shs[i];
            var id = pku + "-" + sh;
            str += "<tr><td>ШС " + (sh>>8) +"/" + (sh&0xff) + "</td><td id=descrSh" + id +"></td>\
                    <td class='hover' id=stateSh" + id +" onClick='controlSh(" +pku+ "," +sh+ ")'></td>\
                    <td class='hover' id=adcSh"   + id +" onClick='getShADC (" +pku+ "," +sh+ ")'></td></tr>";
        }

        table.innerHTML = str;
        mtable.innerHTML = "";
        mtable.appendChild(table);

        if (shs.length>0){
            wsSend( {funct:"getShDescription",pku:pku,req:shs} );
            wsSend( {funct:"getShState",pku:pku,req:shs} );
        }
    }
}
//---------------------------------------------------------------------------
function createRdControlTable(pku, rd) {
    var mtable = $("tableM4");
    if (mtable) {
        var table = document.createElement("table");
        var str = "<tr><th>Считыватель " +(rd>>8)+ "/" +(rd&0xff)+ "</th></tr>";

        str += "<tr><td class='hover' onClick='controlRd(" +pku+ "," +rd+ ",0)'>Открыть дверь для одного</td></tr>";
        str += "<tr><td class='hover' onClick='controlRd(" +pku+ "," +rd+ ",7)'>Открыть дверь для всех</td></tr>";
        str += "<tr><td class='hover' onClick='controlRd(" +pku+ "," +rd+ ",1)'>Венуться в обычный режим</td></tr>";
        str += "<tr><td class='hover' onClick='controlRd(" +pku+ "," +rd+ ",2)'>Разблокировать считыватель</td></tr>";
        str += "<tr><td class='hover' onClick='controlRd(" +pku+ "," +rd+ ",3)'>Разблокировать кнопку \"Выход\"</td></tr>";
        str += "<tr><td class='hover' onClick='controlRd(" +pku+ "," +rd+ ",4)'>Заблокировать дверь</td></tr>";
        str += "<tr><td class='hover' onClick='controlRd(" +pku+ "," +rd+ ",5)'>Заблокировать считыватель</td></tr>";
        str += "<tr><td class='hover' onClick='controlRd(" +pku+ "," +rd+ ",6)'>Заблокировать кнопку \"Выход\"</td></tr>";

        table.innerHTML = str;
        mtable.innerHTML = "";
        mtable.appendChild(table);
    }
}
//---------------------------------------------------------------------------
function createRlControlTable(pku, rl) {
    var mtable = $("tableM4");
    if (mtable) {
        var table = document.createElement("table");
        var str = "<tr><th>Реле " +(rl>>8)+ "/" +(rl&0xff)+ "</th></tr>";

        str += "<tr><td class='hover' onClick='controlRlp(" +pku+ "," +rl+ ",0)'>В исходное</td></tr>";
        str += "<tr><td class='hover' onClick='controlRlp(" +pku+ "," +rl+ ",1)'>Включить</td></tr>";
        str += "<tr><td class='hover' onClick='controlRlp(" +pku+ "," +rl+ ",2)'>Выключить</td></tr>";
        str += "<tr><td class='hover' onClick='controlRlp(" +pku+ "," +rl+ ",5)'>Переключать</td></tr>";

        table.innerHTML = str;
        mtable.innerHTML = "";
        mtable.appendChild(table);
    }
}
//---------------------------------------------------------------------------
function appendRlToShTable(pku, rls) {
    var mtable = $("tableSH");

    if (mtable && (rls.length>0)) {
        var str = mtable.innerHTML;

        for (var i=0; i<rls.length; i++){
            var rl = rls[i];
            var id = pku + "-" + rl;
            if (!$("descrRl"+id))
                str += "<tr><td class='hover' onClick='createRlControlTable(" +pku+ "," +rl+ ")'>Рл " + (rl>>8) +"/" + (rl&0xff) + "</td><td id=descrRl" + id +"></td><td><div class='hover' id=stateRl" + id + " onClick='controlRl(" +pku+ "," +rl+ ")'></div><div id=stateEx" + id +"></div></td><td></td></tr>";
        }

        mtable.innerHTML = str;
        wsSend( {funct:"getRelayDescription",pku:pku,req:rls} );
        wsSend( {funct:"getRelayState",pku:pku,req:rls} );
    }
}
//---------------------------------------------------------------------------
function appendRdToShTable(pku, rds) {
    var mtable = $("tableSH");

    if (mtable && (rds.length>0)) {
        var isSKD = false;
        var objDev = $("typeDev" +pku+ "-" +(rds[0]>>8));
        if (objDev){
            var type = objDev.innerHTML;
            if ( (type==arrDev[DT_S2000_4]) || (type==arrDev[DT_S2000_2])) isSKD=true;
        }

        var str = mtable.innerHTML;

        for (var i=0; i<rds.length; i++){
            var rd = rds[i];
            var id = pku + "-" + rd;
            if (!$("descrRd"+id)){
                if (isSKD)
                    str += "<tr><td class='hover' onClick='createRdControlTable(" +pku+ "," +rd+ ")'>Сч " + (rd>>8) +"/" + (rd&0xff) + "</td><td id=descrRd" + id +"></td><td id=stateRd" + id +"></td><td></td></tr>";
                else
                    str += "<tr><td>Сч " + (rd>>8) +"/" + (rd&0xff) + "</td><td id=descrRd" + id +"></td><td id=stateRd" + id +"></td><td></td></tr>";
            }
        }


        mtable.innerHTML = str;
        wsSend( {funct:"getReaderDescription",pku:pku,req:rds} );
        wsSend( {funct:"getReaderState",pku:pku,req:rds} );
    }
}
//---------------------------------------------------------------------------
function appendExitToShTable(pku, rls) {
    var mtable = $("tableSH");

    if (mtable && (rls.length>0)) {
        var str = mtable.innerHTML;

        for (var i=0; i<rls.length; i++){
            var rl = rls[i];
            var id = pku + "-" + rl;
            if (!$("descrRl"+id))
                str += "<tr><td>Кц " + (rl>>8) +"/" + (rl&0xff) + "</td><td id=descrRl" + id +"></td><td id=stateEx" + id +"></td><td></td></tr>";
        }

        mtable.innerHTML = str;
        wsSend( {funct:"getRelayDescription",pku:pku,req:rls} );
        wsSend( {funct:"getExitState",pku:pku,req:rls} );
    }
}
//---------------------------------------------------------------------------
function appendDevToShTable(pku, devs) {
    var mtable = $("tableSH");

    if (mtable && (devs.length>0)) {
        var str = mtable.innerHTML;

        for (var i=0; i<devs.length; i++){
            var dev = devs[i];
            var id = pku + "-" + dev;
            if (!$("descrDev"+id))
                str += "<tr><td>Пр " +dev+ "</td><td id=descrDev" + id +"></td><td id=stateDev" + id +"></td><td></td></tr>";
        }

        mtable.innerHTML = str;
        wsSend( {funct:"getDeviceDescription",pku:pku,req:devs} );
        wsSend( {funct:"getDeviceState",pku:pku,req:devs} );
    }
}
//---------------------------------------------------------------------------
function updateDevType(pku, devs, type){
    for (var i=0; i<devs.length; i++){
        var dev = devs[i];
        var obj  = $("typeDev" +pku+ "-" + dev);
        if (obj) obj.innerHTML = type[i];
    }
}
//---------------------------------------------------------------------------
function updateDevVer(pku, devs, ver){
    for (var i=0; i<devs.length; i++){
        var dev = devs[i];
        var obj  = $("verDev" +pku+ "-" + dev);
        if (obj) obj.innerHTML = ver[i]/100;
    }
}
//---------------------------------------------------------------------------
function updateDevDescr(pku, devs, descr){
    for (var i=0; i<devs.length; i++){
        var dev = devs[i];
        var obj  = $("descrDev" +pku+ "-" + dev);
        if (obj) obj.innerHTML = descr[i];
    }
}
//---------------------------------------------------------------------------
function updateDevState(pku, devs, states){
    for (var i=0; i<devs.length; i++){
        var dev = devs[i];
        var obj  = $("stateDev" +pku+ "-" + dev);
        if (obj) {
            state = states[i];
            obj.innerHTML  = strState(state);
            obj.style.color = evColorFG(state);
            obj.style.backgroundColor=evColorBG(state);
        }
    }
}
//---------------------------------------------------------------------------
function updateDevTamper(pku, devs, states){
    for (var i=0; i<devs.length; i++){
        var dev = devs[i];
        var obj  = $("state1Dev" +pku+ "-" + dev);
        if (obj) {
            state = states[i];
            obj.innerHTML  = strState(state);
            obj.style.color = evColorFG(state);
            obj.style.backgroundColor=evColorBG(state);
        }
    }
}
//---------------------------------------------------------------------------
function updateDevPower(pku, devs, states){
    for (var i=0; i<devs.length; i++){
        var dev = devs[i];
        var obj  = $("state2Dev" +pku+ "-" + dev);
        if (obj) {
            state = states[i];
            obj.innerHTML = strState(state);
            obj.style.color = evColorFG(state);
            obj.style.backgroundColor=evColorBG(state);
        }
    }
}
//---------------------------------------------------------------------------
function updatePartDescr(pku, parts, descr){
    for (var i=0; i<parts.length; i++){
        var part = parts[i];
        var obj  = $("descrPart" +pku+ "-" +part);
        if (obj) obj.innerHTML = descr[i];
    }
}
//---------------------------------------------------------------------------
function updatePartState(pku, parts, states){
    for (var i=0; i<parts.length; i++){
        var part = parts[i];
        var state = states[i];
        var obj  = $("statePart" +pku+ "-" +part);
        if (obj) {
            obj.innerHTML = strState(state);
            obj.style.color = evColorFG(state);
            obj.style.backgroundColor = evColorBG(state);
        }
    }
}
//---------------------------------------------------------------------------
function updateShDescr(pku, shs, descr){
    for (var i=0; i<shs.length; i++){
        var sh = shs[i];
        var obj  = $("descrSh" +pku+ "-" +sh);
        if (obj) obj.innerHTML = descr[i];
    }
}
//---------------------------------------------------------------------------
function updateShState(pku, shs, states){
    for (var i=0; i<shs.length; i++){
        var sh = shs[i];
        var state = states[i];
        var obj  = $("stateSh" +pku+ "-" +sh);
        if (obj) {
            obj.innerHTML = strState(state);
            obj.style.color = evColorFG(state);
            obj.style.backgroundColor = evColorBG(state);
        }
    }
}
//---------------------------------------------------------------------------
function updateShADC(pku, sh, adc, val){
    var obj  = $("adcSh" +pku+ "-" +sh);
    if (obj) {
        obj.innerHTML = val+" ("+adc+")";
    }
}
//---------------------------------------------------------------------------
function updateRelayDescr(pku, rls, descr){
    for (var i=0; i<rls.length; i++){
        var rl = rls[i];
        var obj  = $("descrRl" +pku+ "-" +rl);
        if (obj) obj.innerHTML = descr[i];
    }
}
//---------------------------------------------------------------------------
function updateRelayState(pku, rls, states){
    for (var i=0; i<rls.length; i++){
        var rl = rls[i];
        var state = states[i];
        var obj  = $("stateRl" +pku+ "-" +rl);
        if (obj) obj.innerHTML = strRelayState(state);
    }
}
//---------------------------------------------------------------------------
function updateExitState(pku, rls, states){
    for (var i=0; i<rls.length; i++){
        var rl = rls[i];
        var state = states[i];
        var obj  = $("stateEx" +pku+ "-" +rl);
        if (obj) {
            obj.innerHTML = strState(state);
            obj.style.color = evColorFG(state);
            obj.style.backgroundColor = evColorBG(state);
        }
    }
}
//---------------------------------------------------------------------------
function updateReaderDescr(pku, rds, descr){
    for (var i=0; i<rds.length; i++){
        var rd = rds[i];
        var obj  = $("descrRd" +pku+ "-" +rd);
        if (obj) obj.innerHTML = descr[i];
    }
}
//---------------------------------------------------------------------------
function updateReaderState(pku, rds, states){
    for (var i=0; i<rds.length; i++){
        var rd = rds[i];
        var state = states[i];
        var obj  = $("stateRd" +pku+ "-" +rd);
        if (obj) obj.innerHTML = strReaderState(state);
    }
}
//---------------------------------------------------------------------------
function updateEvents(pku, first, count, total, ret){
    var mtable;
    if ( (pku==currentPKU) && (typePage==3) ) mtable = $("tableM1");

    if (mtable) {
        var table = document.createElement("table");
        var str = "<tr><th>№</th><th>Дата</th><th>Время</th><th>Событие</th><th>Раздел</th><th>Зона</th><th>Описание</th><th>Прибор</th><th>Хозорган</th><th>Тревога</th></tr>";

        for (var i=0; i<count; i++){
            var obj = ret[i];
            if (obj){
                var n = first + i;
                var evnt = obj.evnt;
                var group= eventsGroup(evnt);
                var event = (obj.rvnt.length==0) ? strEvent(evnt) : obj.rvnt;
                var date = new Date(obj.date*1);

                str += "<tr style='background-color:"+evGColorBG(group)+";color:"+evGColorFG(group)+";'>"+
                        "<td>"+n+"</td>" +
                        "<td>"+date.toLocaleDateString()+"</td>" +
                        "<td>"+date.toLocaleTimeString()+"</td>" +
                        "<td>"+event   +"</td>" +
                        "<td>"+obj.part+"</td>" +
                        "<td>"+obj.zone+"</td>" +
                        "<td>"+obj.dscr+"</td>" +
                        "<td>"+obj.addr+"</td>" +
                        "<td>"+obj.user+"</td>" +
                        "<td>"+(eventsAlarm(evnt) ? "(!)" :"") +"</td></tr>";
            }
        }

        table.innerHTML = str;
        mtable.innerHTML = "";
        mtable.innerHTML = "<div style='text-align: left;'>Всего событий в базе: "+total+
                "<label>. Отображать: <select id='inpEConut'><option value='20'>20</option><option value='50'>50</option><option value='100'>100</option><option value='250'>250</option><option value='500'>500</option><option value='1000'>1000</option></select></label>"+
                "<label> Отображать c:<input id='inpENumb' type='text' size='6' value='-1'>  ('-1' - последние, автопрокрутка новых)  </label>"+
                "<input type='submit' value='Применить' onClick='updateTableEvents()'></div>";
        mtable.appendChild(table);
    }
}
//---------------------------------------------------------------------------
function updateTableEvents(){
    var objEConut  =$("inpEConut");
    var objENumb   =$("inpENumb");

    if (objEConut && objENumb)
        wsSend( {funct:"getEvents", pku:currentPKU, first:Number.parseInt(objENumb.value), count:Number.parseInt(objEConut.value)} );
}
//---------------------------------------------------------------------------
function selectPKU(pku) {
    currentPKU=pku;

    switch(typePage){
    case 0: wsSend( {funct:"getListParts",pku:pku} ); break;
    case 1: wsSend( {funct:"getListGParts",pku:pku} ); break;
    case 2: wsSend( {funct:"getListDevices",pku:pku} ); break;
    case 3: wsSend( {funct:"getEvents",pku:pku,first:-1,count:20} ); break;
    }

    var mtable = $("tableM1");
    if (mtable) mtable.innerHTML = "";

    mtable = $("tableM2");
    if (mtable) mtable.innerHTML = "";

    mtable = $("tableM3");
    if (mtable) mtable.innerHTML = "";

    mtable = $("tableM4");
    if (mtable) mtable.innerHTML = "";
}
//---------------------------------------------------------------------------
function selectPart(pku, part) {
    currentPart=part;
    wsSend( {funct:"getListPartSh",pku:pku,req:part} );
    wsSend( {funct:"getListPartExit",pku:pku,req:part} );
    wsSend( {funct:"getListPartDev",pku:pku,req:part} );
}
//---------------------------------------------------------------------------
function selectGPart(pku, gpart) {
    currentGPart=gpart;
    wsSend( {funct:"getListGPartParts",pku:pku,req:gpart} );

    mtable = $("tableM3");
    if (mtable) mtable.innerHTML = "";

    mtable = $("tableM4");
    if (mtable) mtable.innerHTML = "";
}
//---------------------------------------------------------------------------
function selectDev(pku, dev) {
    currentDev=dev;
    wsSend( {funct:"getListSh",pku:pku,req:dev} );
    wsSend( {funct:"getListRelay",pku:pku,req:dev} );
    wsSend( {funct:"getListExit",pku:pku,req:dev} );
    wsSend( {funct:"getListReader",pku:pku,req:dev} );

    mtable = $("tableM4");
    if (mtable) mtable.innerHTML = "";
}

//---------------------------------------------------------------------------
function controlPart(pku, part) {wsSend( {funct:"controlPart_Inv",pku:pku,part:part } );}
function controlSh  (pku, sh)   {wsSend( {funct:"controlSh_Inv", pku:pku,sh:sh } );}
function controlRl  (pku, rl)   {wsSend( {funct:"controlRelay_Inv", pku:pku,rl:rl } );}
function controlRlp (pku, rl, prog)  {wsSend( {funct:"controlRelay",  pku:pku,rl:rl,prog:prog } );}
function controlRd  (pku, rd, prog)  {wsSend( {funct:"controlReader", pku:pku,rd:rd,prog:prog } );}
function getShADC(pku, sh) {wsSend( {funct:"getShADC",pku:pku,req:[sh] } );}
//---------------------------------------------------------------------------
function writeLog(msg) {
    if (log){
        var date = new Date;
        var p = document.createElement("kbd");
        p.innerHTML = "["+date.toLocaleTimeString() +"] "+ msg + "<br>";
        log.appendChild(p);
    }
}
//---------------------------------------------------------------------------
function $(x){obj=document.getElementById(x); return (obj) ? obj:false}
//---------------------------------------------------------------------------
if (window.addEventListener) window.addEventListener("load", init, false);
else{
    window.onload =init;
    writeLog("Технология WebSocket поддерживается в Internet Explorer начиная с версии 10.");
}

