eqeqwan21

obj.js

Sep 27th, 2025
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //v13_14 альтернатиная мнемосхема_маскировка команд
  2. //v11++фото заголовки со ссылками
  3. "use strict";
  4. let hulla = new hullabaloo();
  5. let box = null;
  6. let circuit = null;
  7. let stlog = null;
  8. let dayly = null;
  9. let lastip = null;
  10. let lastmeter = null;
  11. //Антон: отображение команд с учетом маски
  12. let deviceObj = null;
  13.  
  14. let dt = null, mdt = null;
  15. let liveMode = true;
  16. let renewTimer = null;
  17. let dtdt = null;
  18. let commands = null;
  19. var gallery_ro = true;
  20. let cmdQueued = false;
  21. let waitingForAnswer = false;
  22. let cmdSentMark = 0;
  23. let cmdDeliveredMark = 0;
  24. let sentCmdLetter = null;
  25. let get = parseQuery(window.location.search);
  26. let xhrRenew = null;
  27. let drawDebounce = null;
  28. let maxRequests = 100;
  29. let requestCount = localStorage.getItem('requestCount') ? parseInt(localStorage.getItem('requestCount')) : 0;
  30. moment.locale(environment.language || window.navigator.userLanguage || window.navigator.language);
  31.  
  32. $(async function () {
  33.   $("#btnLive").prop("disabled", true);
  34.   let result;
  35.   let userTown;
  36.   if (environment.login_name.indexOf("_") !== -1) {
  37.     userTown = '&town=' + environment.login_name.split('_')[0].toLowerCase()
  38.   } else {
  39.     userTown = ''
  40.   }
  41.   try {
  42.     result = await $.ajax({
  43.       url: environment.base_url + "/" + '?do=api&fn=devices&id=' + get['id'] + userTown,
  44.       type: 'GET',
  45.       dataType: "json"
  46.     });
  47. //Антон: отображение команд с учетом маски
  48.     deviceObj = result;
  49.   } catch (error) {
  50.     console.error(error);
  51.     $("#content").html("<h2>Device was not loaded</h2>");
  52.     return;
  53.   }
  54.  
  55.  
  56.   if (result.rows.length > 0)
  57.     box = result.rows.slice(0)[0];
  58.   else {
  59.     $("#content").html("<h2>Device not found</h2>");
  60.     return;
  61.   }
  62.  
  63.   if (box.DimProfile_id !== null) {
  64.     try {
  65.       dayly = await $.ajax({
  66.         url: environment.base_url + "/" + '?do=api&fn=dimdetail&now&id=' + box.DimProfile_id,
  67.         type: 'GET',
  68.         dataType: "json"
  69.       });
  70.     } catch (error) {
  71.       console.error(error);
  72.     }
  73.   }
  74.  
  75.   if (box.Type == 2)
  76.     $("#strongState").text(i18next.t("Brightness"));
  77.  
  78.   drawBoxInfo();
  79.   try {
  80.     result = await $.ajax({
  81.       url: environment.base_url + "/" + '?do=api&fn=circuit&id=' + get['id'],
  82.       type: 'GET',
  83.       dataType: "json"
  84.     });
  85.  
  86.   } catch (error) {
  87.     console.error(error);
  88.     $("#content").html("<h2>Pattern was not loaded</h2>");
  89.     return;
  90.   }
  91.  
  92.   if (result.rows.length > 0)
  93.     circuit = result.rows[0];
  94.   else
  95.     console.log("Pattern not found");
  96.  
  97.   let svg = "";
  98.   if (circuit !== null) {
  99.     let qs = circuit.qs;
  100.     if (environment.language !== "en") {
  101.       qs = qs.replace(/S/gi, "K");
  102.     }
  103.  
  104.     try {
  105.       svg = await $.ajax({
  106.         url: environment.base_url + `/images/galbox.svg?v=${config.version}&noxml&cnf=` + qs,
  107.         type: 'GET',
  108.         processData: false
  109.       });
  110.       $("#circuit").html(`${svg}`);
  111. // картинки мнемосхем
  112.       if (box.Name?.startsWith("TL") || box.Name?.startsWith("G") || box.Name?.startsWith("4L")) await attachBackground();
  113.     } catch (error) {
  114.       console.error(error);
  115.     }
  116.   }
  117.  
  118.   stdatatable();
  119.   meterdatatable();
  120.  
  121.   setTimeout(renew, 1);
  122.   setTimeout(iprenew, 10);
  123.  
  124.   $("#circuit svg").addClass("col-12");
  125.   $("#circuit svg").addClass("p-0");
  126.   //Ссылки в зоголовках "статистика" и "журнал состояния" в форме Объект
  127.   $("#statlink").attr("href", `${environment.base_url}/inlog?device=${get['id']}`);
  128.   $("#stlink").attr("href", `${environment.base_url}/stlog?device=${get['id']}`);
  129.   if (box.Smart) {
  130.     try {
  131.       result = await $.ajax({
  132.         url: environment.base_url + "/" + '?do=api&fn=ServerCommand&type=1,3&DeviceType=' + box.Type,
  133.         type: 'GET',
  134.         dataType: "json"
  135.       });
  136.  
  137.     } catch (error) {
  138.       console.error(error);
  139.       return;
  140.     }
  141.     commands = result.rows;
  142.     $("#cmd").find('option').remove();
  143.  
  144.     for (let key in commands) {
  145.       if (commands[key].Letter == "F")
  146.         continue;
  147.       $("#cmd").append($("<option></option>")
  148.           .attr("value", commands[key].id)
  149.           .text(i18next.t(commands[key].Name)));
  150.     }
  151.   } else {
  152.     $("#manualDiv").hide();
  153.   }
  154. //добавление картинки светильника из галлереи с проверкой её наличия, иначе - по умолчанию
  155.   if (box.Type !== 1) {
  156.     $.ajax({
  157.       url: `${environment.base_url}/?do=api&fn=picture_list&Devices_id=${get['id']}&order=ASC&limit=1`,
  158.       type: 'GET',
  159.       dataType: "json",
  160.       success: function (result) {
  161.         if (result['list'].length > 0) {
  162.           $("#circuit").html('<img class="img-fluid" src="' + result['list'][0].src + '">');
  163.         } else {
  164.           $("#circuit").html(`<img class="img-fluid" src="${environment.base_url}/images/lamp.png">`)
  165.         }
  166.       }
  167.     });
  168.     // $("#circuit").html(`<img class="img-fluid" src="${environment.base_url}/images/lamp.png">`);
  169.   }
  170.  
  171.   $(".picture").click(() => {
  172.     galleryOpen(get['id'])
  173.   });
  174.   /*
  175.   let pl = await getPictureList(get['id'], 'desc', 100);
  176.   if(pl.length == 0) {
  177.     $(".picture").click( ()=>{galleryOpen(get['id'])});
  178.   } else {
  179.     let html="";
  180.     let i=0;
  181.     pl.forEach(el => {
  182.       let title = "";
  183.       let opt = {month: "long", day:"numeric", year:"numeric"};
  184.       let separ=", ";
  185.       let opt2= {hour:"numeric", minute:"numeric"};
  186.       let disp="";
  187.  
  188.       if(el.Exiftime!==null) {
  189.         let dda = el.Exiftime.split(" ");
  190.         if(dda.length==2) {
  191.           let dds = dda[0].replaceAll(":","-") + " " + dda[1]+"Z";
  192.           let dd = new Date(dds);
  193.  
  194.           if(!(dd===NaN) && !dd!="Invalid Date") {
  195.             disp = "<i class='fa fa-camera'></i>&nbsp;" + dd.toLocaleDateString(environment.language, opt) + separ +
  196.             dd.toLocaleTimeString(environment.language, opt2);
  197.           }
  198.         }
  199.       }
  200.  
  201.       let dd = new Date(el.Loaded+"Z");
  202.       if(!(dd===NaN) && !dd!="Invalid Date") {
  203.         if(disp!="")
  204.           disp+="<br>";
  205.         disp += "<i class='fa fa-upload'></i>&nbsp;" + dd.toLocaleDateString(environment.language, opt) + separ +
  206.         dd.toLocaleTimeString(environment.language, opt2);
  207.       }
  208.  
  209.       title = `data-container="body" data-html="true" data-placement="top" data-toggle="tooltip" title="${disp}"`;
  210.  
  211.       html += `<div ${title}><img onclick="galleryOpen(${get['id']}, ${i})" class="border border-primary rounded imgpic" width="60px" height="60px" src="${el.src}&thumb"></div>`;
  212.       i++;
  213.     });
  214.     $("#pg").html(html);
  215.     $('[data-toggle="tooltip"]').tooltip({
  216.       boundary:"viewport",
  217.       html: true
  218.     });
  219.   }
  220.   */
  221.  
  222. });
  223.  
  224. async function runCmd() {
  225.   $("#btnCmd").prop("disabled", true);
  226.   setTimeout(() => $("#btnCmd").prop("disabled", false), 1500);
  227.   let srvcmd = {};
  228.   cmdQueued = false;
  229.   sentCmdLetter = null;
  230.   srvcmd.cmd = parseInt($("#cmd").val());
  231.   let selcmd = commands.find(x => x.id == srvcmd.cmd);
  232.   let cmdtext = i18next.t(selcmd.Name);
  233.  
  234.   srvcmd.devs = [box.id];
  235.  
  236.   let result = null;
  237.   try {
  238.     result = await $.ajax({
  239.       url: environment.base_url + "/" + '?do=api&fn=makecalls',
  240.       data: JSON.stringify(srvcmd),
  241.       type: 'PUT',
  242.       contentType: "application/json; charset=utf-8",
  243.       dataType: "json"
  244.     });
  245.  
  246.   } catch (error) {
  247.     console.error(error);
  248.     hulla.send(i18next.t("Device control error"));
  249.     return false;
  250.   }
  251.  
  252.   if (result.success) {
  253.     switch (result.queued) {
  254.       case 0:
  255.         hulla.send(i18next.t("Command not queued"));
  256.         break;
  257.       case 1:
  258.         hulla.send(`${i18next.t("Command")} "${cmdtext}" ${i18next.t("queued")}`, "success");
  259.         cmdQueued = true;
  260.         cmdSentMark = Date.now();
  261.         sentCmdLetter = selcmd.Letter;
  262.         break;
  263.       default:
  264.         hulla.send(`${cmdtext} - ${i18next.t("Command queued for multiple devices")} (${result.queued})`, "success");
  265.         break;
  266.     }
  267.   } else {
  268.     hulla.send(i18next.t("An error occurred while adding commands to the queue"));
  269.     console.log(result);
  270.   }
  271.  
  272.   return false;
  273. }
  274.  
  275. let pbox = null, plines = null;
  276.  
  277. async function drawBoxInfo() {
  278.   $("#Phone").html(number10html(box.Phone));
  279. //Добавление строки "Серийный номер"
  280.   for (let fld of ["CustomNum", "Name", "sn", "DimProfile_Name", "Station", "ControlTime"]) {
  281.     let val = box[fld];
  282.     if (val !== null) {
  283.       if (fld == "ControlTime")
  284.         $("#" + fld).text(val.substr(0, 5));
  285.       else
  286.         $("#" + fld).text(val);
  287.     }
  288.   }
  289.   if (box.Station == null && box.Lines_id) {
  290.     //let pbox =null, plines = null;
  291.     try {
  292.       pbox = await $.ajax({
  293.         url: environment.base_url + "/" + '?do=api&fn=devices&id=' + box.Box_id,
  294.         type: 'GET',
  295.         dataType: "json"
  296.       });
  297.  
  298.     } catch (error) {
  299.       console.error(error);
  300.       return;
  301.     }
  302.     try {
  303.       plines = await $.ajax({
  304.         url: environment.base_url + "/" + '?do=api&fn=lines&id=' + box.Box_id,
  305.         type: 'GET',
  306.         dataType: "json"
  307.       });
  308.  
  309.     } catch (error) {
  310.       console.error(error);
  311.       return;
  312.     }
  313.  
  314.     if (pbox && plines) {
  315.       let ln = plines.rows.find(x => x.id == box.Lines_id)
  316.       let txt = ln.Num.toString().padStart(2, "0") + ". " + i18next.t(appdata.LinesType.find(x => x.id == ln.Type).Name);
  317.  
  318.       if (ln.Switch > 0)
  319.         txt += " " + i18next.t(appdata.Switches.find(x => x.id == ln.Switch).Name);
  320.       if (ln.Phase > 0)
  321.         txt += ", " + i18next.t("Phase") + " " + appdata.Phases.find(x => x.id == ln.Phase).Name;
  322.  
  323.       $("#Station").html(`<a target="obj${box.Box_id}" href="${environment.base_url}/obj?id=${box.Box_id}" id="aStation"></a>, ${txt}`);
  324.       $("#aStation").text(`${i18next.t("Box")} № ${pbox.rows[0].CustomNum}`);
  325.     }
  326.   }
  327.   $("#Mode").text(i18next.t(appdata.AutoModes.find(x => x.id == box.Mode).Name));
  328.   $("#Location").text(makeAddress(box));
  329.  
  330.   $("#shiftdiv").hide();
  331.  
  332.   daylyTable();
  333. }
  334.  
  335.  
  336. function daylyTable() {
  337.   if (dayly == null)
  338.     return;
  339.  
  340.   let drw = dayly.rows;
  341.   let aShift = null;
  342.   if (box.PardShift)
  343.     aShift = box.PardShift.split(",");
  344.  
  345.   let str1 = "<tr>", str2 = "<tr>", str3 = "<tr>";
  346.   for (let i = 0; i < config.pard_maxvalue; i++) {
  347.     let time = '', val = '';
  348.     if (!(drw[i] === undefined)) {
  349.  
  350.       time = drw[i].Time.substr(0, 5);
  351.       if (box.Type == 2) //lamp
  352.         val = "" + drw[i].DimValue + "%";
  353.       else
  354.         val = SwitchStateForMask(drw[i].DimValue);//Антон: отображение команд с учетом маски
  355.     }
  356.     if (aShift) {
  357.       let tt = '';
  358.       if (aShift[i]) {
  359.         let tti = parseInt(aShift[i]);
  360.         let sign = "";
  361.         if (tti < 0)
  362.           sign = "-";
  363.         if (tti > 0)
  364.           sign = "+";
  365.         tti = Math.abs(tti);
  366.         let min = tti % 60;
  367.         let hr = (tti - min) / 60;
  368.  
  369.         tt = `${sign}${new Intl.NumberFormat(environment.language, {minimumIntegerDigits: 2}).format(hr)}:${new Intl.NumberFormat(environment.language, {minimumIntegerDigits: 2}).format(min)}`;
  370.       }
  371.       str3 += `<td class="text-center">${tt}</td>`;
  372.     }
  373.  
  374.  
  375.     str1 += `<td class="text-center">${time}</td>`;
  376.     str2 += `<td class="text-center">${val}</td>`;
  377.   }
  378.   str1 += "</tr>";
  379.   str2 += "</tr>";
  380.   $("#dimDetail").append(str1);
  381.  
  382.   if (aShift) {
  383.     str3 += "</tr>";
  384.     $("#dimDetail").append(str3);
  385.   }
  386.   $("#dimDetail").append(str2);
  387. }
  388.  
  389. let loadfail = 0;
  390.  
  391. async function dataload() {
  392.   let url = environment.base_url + "/" + "?do=api&fn=stlog&limit=64&device=" + get['id'];
  393.   let result, ret = false;
  394.   try {
  395.     if (xhrRenew && typeof xhrRenew.abort === 'function') {
  396.       xhrRenew.abort();
  397.     }
  398.     xhrRenew = await $.ajax({
  399.       url: url,
  400.       type: 'GET',
  401.       dataType: "json",
  402.       cache: false
  403.     });
  404.     result = await xhrRenew;
  405.     if (stlog == null || stlog.timestamp !== result.timestamp) {
  406.       stlog = result;
  407.       ret = true;
  408.     }
  409.     requestCount++;
  410.     localStorage.setItem('requestCount', requestCount);
  411.  
  412.     if (requestCount >= maxRequests) {
  413.       localStorage.removeItem('requestCount');
  414.       location.reload();
  415.     }
  416.   } catch (error) {
  417.     console.log("Error: ", error);
  418.  
  419.     if (error.status == 401) //unautorized
  420.       window.location = environment.base_url + "/" + "?do=login&b=" + encodeURIComponent(window.location);
  421.  
  422.     loadfail++;
  423.     if (stlog === null)
  424.       $("#content").html("<h2>Log was not loaded</h2>");
  425.     else if (loadfail > 1) {
  426.       hulla.send(i18next.t(`No connection to the server (${error.statusText})`));
  427.       loadfail = 0;
  428.     }
  429.     return ret;
  430.   }
  431.   loadfail = 0;
  432.   return ret;
  433. }
  434.  
  435.  
  436. async function ipload() {
  437.   let url = environment.base_url + "/" + "?do=api&fn=lastip&device=" + get['id'];
  438.   let result, ret = false;
  439.   try {
  440.     result = await $.ajax({
  441.       url: url,
  442.       type: 'GET',
  443.       dataType: "json",
  444.     });
  445.   } catch (error) {
  446.     console.log("Error: ", error);
  447.     return ret;
  448.   }
  449.   if (lastip == null || lastip.timestamp != result.timestamp) {
  450.     lastip = result;
  451.     ret = true;
  452.   }
  453.  
  454.   return ret;
  455. }
  456.  
  457. async function meterload() {
  458.   let url = environment.base_url + "/" + "?do=api&fn=lastmeter&device=" + get['id'];
  459.   let result, ret = false;
  460.   try {
  461.     result = await $.ajax({
  462.       url: url,
  463.       type: 'GET',
  464.       dataType: "json",
  465.     });
  466.   } catch (error) {
  467.     console.log("Error: ", error);
  468.     return ret;
  469.   }
  470.   if (lastmeter == null || result.timestamp != lastmeter.timestamp) {
  471.     lastmeter = result;
  472.     ret = true;
  473.   }
  474.  
  475.   return ret;
  476. }
  477.  
  478.  
  479. async function renew() {
  480.   // let nextt = 1000;
  481.   // let isnew = await dataload();
  482.   // if (isnew) {
  483.   //   onlogchane();
  484.   //   nextt = 2000;
  485.   // }
  486.   // setTimeout(renew, nextt);
  487.   if (!liveMode) return;
  488.  
  489.   const isnew = await dataload();
  490.   if (isnew) {
  491.     clearTimeout(drawDebounce);
  492.     drawDebounce = setTimeout(onlogchane, 300);
  493.   }
  494.   const next = isnew ? 4000 : 2000;
  495.   renewTimer = setTimeout(renew, next);
  496. }
  497.  
  498. async function iprenew() {
  499.  
  500.   let nextt = 2000;
  501.   let isnew = await ipload();
  502.  
  503.   if (isnew) {
  504.     if (lastip !== null && lastip.rowCount > 0) {
  505.       let li = lastip.rows[0];
  506.       let m = moment(li.unixtime * 1000);
  507.       $("#iptime").text(m.format("L LT"));
  508.       $("#ipdata").text(li.Msg);
  509.       $("#divstat").show();
  510.     } else
  511.       $("#divstat").hide();
  512.  
  513.     applyStatsVisibility($('#toggleStats').prop('checked'));
  514.  
  515.     let isnewmeter = await meterload();
  516.     if (isnewmeter) {
  517.       if (lastmeter !== null && lastmeter.rowCount > 0) {
  518.         let lm = lastmeter.rows[0];
  519.  
  520.         let dd = new Date(lm.Timestamp + "Z");
  521.         let disp = dd.toLocaleDateString(environment.language) + " " +
  522.             dd.toLocaleTimeString(environment.language, {hour: "numeric", minute: "numeric"});
  523.         $("#metertime").text(disp);
  524.         $("#meterlink").attr("href", `${environment.base_url}/meterlog?device=${get['id']}`);
  525. //Открытие новой вкладки для "Показания учета"
  526.         //$("#meterlink").attr("target", `meterlog${get['id']}`);
  527.         mdt.ajax.reload();
  528.         $("#meterstat").show();
  529.       } else
  530.         $("#meterstat").hide();
  531.     }
  532.  
  533.     nextt = 5000;
  534.   }
  535.   setTimeout(iprenew, nextt);
  536. }
  537.  
  538.  
  539. async function onlogchane() {
  540.   if (dt != null) {
  541.     dt.ajax.reload();
  542.     $('[data-toggle="tooltip"]').tooltip('dispose');
  543.     $(".tooltip").remove();
  544.     $('[data-toggle="tooltip"]').tooltip();
  545.   }
  546.   let result = null;
  547.  
  548.   try {
  549.     result = await $.ajax({
  550.       url: environment.base_url + "/" + "?do=api&fn=states&Devices_id=" + get['id'],
  551.       type: 'GET',
  552.       dataType: "json"
  553.     });
  554.   } catch (error) {
  555.     console.error(error);
  556.   }
  557.  
  558.   if (result !== null && result.rows.length > 0) {
  559.     let state = result.rows[0];
  560.     setSvgstate(state);
  561.     setTextstate(state);
  562.     if (cmdQueued) {
  563.       const ev = stlog?.rows?.find(r =>
  564.           r.OutgoingLog_id &&
  565.           r.unixtime * 1000 >= cmdSentMark - 3000
  566.       );
  567.       if (ev) {
  568.         cmdDeliveredMark = ev.unixtime * 1000;
  569.         waitingForAnswer = true;
  570.         cmdQueued = false;
  571.         $("#circuit").addClass("waiting");
  572.       }
  573.     }
  574.     if (waitingForAnswer) {
  575.       const lastAnswerTime = Math.max(
  576.           stlog?.rows?.[0]?.IncomingLog_id ? stlog.rows[0].unixtime * 1000 : 0,
  577.           state.unixtime * 1000
  578.       );
  579.  
  580.       if (lastAnswerTime > cmdDeliveredMark) {
  581.         $("#circuit").removeClass("waiting");
  582.         waitingForAnswer = false;
  583.         sentCmdLetter = null;
  584.       }
  585.     }
  586.   }
  587. }
  588.  
  589. function setTextstate(state) {
  590.   let m = moment(state.unixtime * 1000);
  591.   $("#StateTime").text(m.format("LT, L"));
  592.   if (box.Type == 2)
  593.     $("#SwState").text("" + state.State + "%");
  594.   else
  595.     $("#SwState").text(SwitchStateForMask(state.State));//Антон: отображение команд с учетом маски
  596.   let mode = state.Mode == 4 ? "Manual" : "Auto";
  597.   mode = i18next.t(mode);
  598.   if (state.Mode == 1)
  599.     mode += ", " + box.DimProfile_Name;
  600.   $("#CurrentMode").text(mode);
  601.  
  602.   let door = i18next.t("Closed");
  603.   if (!state.Door)
  604.     door = '<span class="text-danger">' + i18next.t("Open") + "</span>";
  605.   $("#DoorStatus").html(door);
  606.  
  607.  
  608.   let sync = i18next.t("Synced");
  609.   if (state.Ous)
  610.     sync = '<span class="text-danger">' + i18next.t("Out of sync") + "</span>";
  611.   $("#SyncStatus").html(sync);
  612.  
  613. }
  614.  
  615. function setSvgstate(state) {
  616.  
  617.   let onoff = SwitchState(state.State);
  618.  
  619.   const ruge = "#ecabab";
  620.   const salat = "#abecab";
  621.  
  622.   const errorColor = state.Trouble == STATE_ERROR_UNKNOWN ? ruge : "red";
  623.   const greenColor = state.Trouble == STATE_ERROR_UNKNOWN ? salat : "green";
  624.  
  625.   //const phasecolor = state.Power?"green":ruge;
  626.   let aphst = [];
  627.   for (let i = 0; i < 3; i++) {
  628.     let plet = String.fromCharCode("A".charCodeAt() + i);
  629.     let phst = state.Power & (1 << i);
  630.     aphst[i] = phst;
  631.     let phasecolor = phst ? greenColor : errorColor;
  632.     $(`#phase_${plet}`).css("stroke", phasecolor);
  633. //V11
  634.     $("#Volt" + i).text(plet);
  635.     if (state.PhaseV) {
  636.       let aVolt = JSON.parse(state.PhaseV);
  637.       if (aVolt[i] !== null && aVolt[i] > 1)
  638.         $("#Volt" + i).text(aVolt[i]);
  639.     }
  640.   }
  641.   //$(".phase").css("stroke",phasecolor);
  642.  
  643.  
  644. // КОНТАКТОРЫ
  645.   for (let i = 1; i <= 4; i++) {
  646.     let swtrouble = state.Trouble & (1 << (i - 1));     //аварийность контактора
  647.     let altsw = state.Trouble & (1 << (i + 27));        //альтернативное включение контактора
  648.     let on = (onoff[i - 1] !== '0');                    // значение управления on/off && aphst[0]; 20.07.21 - remove Phase A falsification
  649.     // Команда на включение ON
  650.     if (on) {
  651.       $(`.S${i}_on`).attr("visibility", "visible");     //видимость состояния on
  652.       $(`.S${i}_off`).attr("visibility", "hidden");     //скрыть состояние off
  653.       $(`.S${i}_onoff`).attr("visibility", "hidden");   //скрыть состояние onoff
  654.       $(`.S${i}_offon`).attr("visibility", "hidden");   //скрыть состояние offon
  655.       let swc = "green";
  656.       $(`#S${i}_rect1`).css("fill", "#AFEEEE");         // левый прямоугольник (голубой)
  657.       $(`#S${i}_rect2`).css("fill", swc);               // правый прямоугольник "зеленый"
  658.       $(`#S${i}_tilda`).css("stroke", swc);             //цвет контура синусоиды "зеленый"
  659.       $(`#S${i}_tilda`).css("fill", swc);               //цвет заполнения синусоиды "зеленый"
  660.       $(`.fuse_S${i}`).css("fill", swc);                    //предохранители под напряжением "зеленые"
  661.       //Отсутствие фазы «А»
  662.       if (!aphst[0]) {
  663.         $(`.S${i}_off`).attr("visibility", "hidden");       // не видимость контактора, как Off
  664.         $(`.S${i}_on`).attr("visibility", "hidden");        //не видимость контактора, как ON
  665.         $(`.S${i}_onoff`).attr("visibility", "visible");    //видимость состояния onoff
  666.         $(`.S${i}_offon`).attr("visibility", "hidden"); //скрыть состояние offon
  667.         swc = salat;
  668.         $(`#S${i}_rect1`).css("fill", "#AFEEEE");           // левый прямоугольник "голубой"
  669.         $(`#S${i}_rect2`).css("fill", swc);             // правый прямоугольник "салатный"
  670.         $(`#S${i}_tilda`).css("stroke", "white");           //белый синус
  671.         $(`#S${i}_tilda`).css("fill", "white");         //белый синус
  672.         $(`.fuse_S${i}`).css("fill", "white");              //предохранители "белые"
  673.         if (altsw) {                                            //если альтернативно-включенный контактор
  674.           $(`.S${i}_onoff`).attr("visibility", "hidden");   //не видимость состояния onoff
  675.           $(`.S${i}_offon`).attr("visibility", "visible");  //видимость состояния offon
  676.           $(`#S${i}_rect2`).css("fill", "red");             // правый прямоугольник
  677.           $(`.fuse_S${i}`).css("fill", "green");                //предохранители под напряжением "зеленые"_07_09
  678.         }
  679.       }
  680.       //аварийность контактора
  681.       if (swtrouble) {
  682.         $(`.S${i}_onoff`).attr("visibility", "visible");    // видимость контактора, как onoff
  683.         $(`.S${i}_offon`).attr("visibility", "hidden"); //скрыть состояние offon
  684.         $(`.S${i}_off`).attr("visibility", "hidden");       // не видимость контактора, как Off
  685.         $(`.S${i}_on`).attr("visibility", "hidden");        //не видимость включенного контактора
  686.         $(`#S${i}_rect1`).css("fill", errorColor);          // левый прямоугольник "красный"
  687.         $(`#S${i}_rect2`).css("fill", salat);               // правый прямоугольник "салатный"
  688.         $(`#S${i}_tilda`).css("stroke", "white");           //белый синус
  689.         $(`#S${i}_tilda`).css("fill", "white");         //белый синус
  690.         $(`.fuse_S${i}`).css("fill", "white");              //предохранители "белые"
  691.       }
  692.     }
  693.     // Команда на выключение OFF
  694.     else {
  695.       $(`.S${i}_on`).attr("visibility", "hidden");      //скрыть состояние ON
  696.       $(`.S${i}_onoff`).attr("visibility", "hidden");   //скрыть состояние onoff
  697.       $(`.S${i}_offon`).attr("visibility", "hidden");   //скрыть состояние offon
  698.       $(`.S${i}_off`).attr("visibility", "visible");        //показать состояние OFF
  699.       $(`#S${i}_rect2`).css("fill", "white");           // правый прямоугольник "белый"
  700.       $(`#S${i}_rect1`).css("fill", "#AFEEEE");         // левый прямоугольник голубой
  701.       $(`#S${i}_tilda`).css("stroke", "green");         //цвет контура синусоиды
  702.       $(`#S${i}_tilda`).css("fill", "green");           //цвет заполнения синусоиды
  703.       $(`.fuse_S${i}`).css("fill", "white");                //предохранители
  704.       // Отсутствие фазы А
  705.       if (!aphst[0]) {
  706.         $(`#S${i}_tilda`).css("stroke", "white");   //белый синус
  707.         $(`#S${i}_tilda`).css("fill", "white");
  708.       } //белый синус
  709.       // Авария контактора
  710.       if (swtrouble) {
  711.         $(`#S${i}_rect1`).css("fill", errorColor);      // левый прямоугольник красный
  712.         $(`#S${i}_tilda`).css("stroke", "white");       //белый синус
  713.         $(`#S${i}_tilda`).css("fill", "white");
  714.       }     //белый синус
  715.       // Альтернативное включение
  716.       if (altsw) {                                      //если есть альтернативно-включенный контактор
  717.         $(`.S${i}_off`).attr("visibility", "hidden");
  718.         $(`.S${i}_offon`).attr("visibility", "visible");
  719.         $(`#S${i}_rect2`).css("fill", "red");           // правый прямоугольник красный
  720.         $(`.fuse_S${i}`).css("green");              //предохранители под напряжением "зеленые"_07_09
  721.       }
  722.     }
  723.   }
  724.  
  725. //ПРЕДОХРАНИТЕЛИ
  726.   for (let i = 0; i < 3; i++)
  727.     if (!aphst[i])
  728.       $(`.fuse_P${i}`).css("fill", "none");
  729.  
  730. //V10__Отображение значений напряжения на линиях/предохранителях
  731.   let volt = null;
  732.   try {
  733.     volt = JSON.parse(state.Voltage);
  734.   } catch (e) {
  735.  
  736.   }
  737. //V11
  738.   $('[id^="fuse_"]').find("title").remove();
  739.   for (let i = 1; i <= 24; i++) {
  740.     let ftrouble = state.Trouble & (1 << (i + 3));
  741.     $(`.fuse_${i}_rect`).attr("visibility", "hidden");  //V14   Не видимость знака стрелок
  742.     if (volt) {
  743.       let fVolt = volt[i - 1];
  744.       if (fVolt) {
  745.         $(`#fuse_${i}_rect`).css("fill", "green");
  746.         let titlestr = fVolt > 1 ? fVolt + "V" : "⚡";
  747.         let title = document.createElementNS("http://www.w3.org/2000/svg", "title");
  748.         title.textContent = titlestr;
  749. //V11
  750.         $(`#fuse_${i}`).append(title);
  751.       } else
  752.         $(`#fuse_${i}_rect`).css("fill", "white");
  753.  
  754. //V14 окраска встречки градиентом "зеленого" и символ "стрелки"
  755.       if (ftrouble && fVolt) {
  756.         $(`#fuse_${i}_rect`).css("fill", "url(#MyGradient)");
  757.         $(`.fuse_${i}_rect`).attr("visibility", "visible");     // видимость знака стрелок
  758.       }
  759.  
  760. //V14  окраска пониженного напряжения градиентом2 "зеленого"
  761.       if (fVolt < 180 && fVolt > 30) {
  762.         $(`#fuse_${i}_rect`).css("fill", "url(#MyGradient2)");
  763.         $(`.fuse_${i}_rect`).attr("visibility", "hidden");  // не видимость знака стрелок
  764.       }
  765.  
  766.       if (ftrouble && !fVolt)
  767.         $(`#fuse_${i}_rect`).css("fill", errorColor);
  768.  
  769.     }
  770.  
  771.     //else {
  772.     //if(ftrouble)
  773.     //$(`#fuse_${ i }_rect`).css("fill",errorColor);}
  774.  
  775.   }
  776. }
  777.  
  778. function SwitchState(num) {
  779.   if (num === null)
  780.     return "-";
  781.  
  782.   num = Math.min(num, 0b1111);
  783.  
  784.   return num.toString(2).padStart("4", "0"); //For robot
  785. }
  786.  
  787. //Антон: отображение команд с учетом маски
  788. function SwitchStateForMask(num) {
  789.   if (num === null)
  790.     return "-";
  791.   let maskCommand = box ? box.Mask_Command : ''
  792.   if (!maskCommand) {
  793.     num = Math.min(num, 0b1111);
  794.  
  795.     return num.toString(2).padStart("4", "0");
  796.   }
  797.   let len = maskCommand ? maskCommand.length : 4;
  798.  
  799.   let binStr = num.toString(2).padStart(len, "0");
  800.  
  801.   let result = "";
  802.   for (let i = 0; i < len; i++) {
  803.     if (maskCommand[i] === "1") {
  804.       result += binStr[i];
  805.     }
  806.   }
  807.   return result;
  808. }
  809.  
  810. function meterdatatable() {
  811.   mdt = $('#meterlog').DataTable({
  812.     "ajax": function (data, callback, settings) {
  813.       let dt = [];
  814.       if (lastmeter !== null)
  815.         dt = lastmeter.rows;
  816.       callback({data: dt});
  817.     },
  818.     "info": false,
  819.     "rowId": "id",
  820.     "language": datatables_locale,
  821.     "paging": false,
  822.     "ordering": false,
  823.     "searching": false,
  824.     "scrollX": true,
  825.     "columns": [
  826.       {
  827.         "data": "Tag",
  828.         render: function (data, type, row) {
  829.           return i18next.t("msg_meter_" + data);
  830.         }
  831.       },
  832.       {
  833.         "data": "Value", className: 'text-right',
  834.         render: function (data, type, row) {
  835.           let tag = appdata.Meter[row.Tag];
  836.           if (tag.type == "decimal") {
  837.             let num = parseFloat(data);
  838.             if (type == "export")
  839.               return num;
  840.             return Intl.NumberFormat(environment.language, {minimumFractionDigits: 3}).format(num);
  841.           }
  842.           return data;
  843.         }
  844.       },
  845.     ],
  846.   });
  847.  
  848.   mdt.on("draw", function () {
  849.     $('[data-toggle="tooltip"]').tooltip();
  850.   });
  851.  
  852.   mdt.on("init", function () {
  853.     $('[data-toggle="tooltip"]').tooltip();
  854.   });
  855. }
  856.  
  857. function stdatatable() {
  858.  
  859.   dt = $('#stlog').DataTable({
  860.     "ajax": function (data, callback, settings) {
  861.       if (stlog !== null)
  862.         callback({data: stlog.rows});
  863.     },
  864.     "info": false,
  865.     "rowId": "id",
  866.     "language": datatables_locale,
  867.     "paging": false,
  868.     "ordering": false,
  869.     "searching": false,
  870.     "scrollX": true,
  871.     "scrollY": "27rem",
  872.     "scrollCollapse": true,
  873.     "deferRender": true,
  874.  
  875.     "columns": [
  876.       {"data": "id", visible: false},
  877.       {
  878.         "data": "Timestamp",
  879.         render: function (data, type, row) {
  880.           if (type == "display") {
  881.             let m = moment(row.unixtime * 1000);
  882.             let td = moment();
  883.             let fs = "L LT";
  884.             if (td.isSame(m, 'd'))
  885.               fs = "LT";
  886.             let tz = row.tz.charAt(0) == "-" ? "" : "+" + row.tz;
  887.             let stime = data + " " + tz;
  888.             return `<span data-toggle="tooltip" title="${stime}">${m.format(fs)}</span>`;
  889.           }
  890.           return data;
  891.         }
  892.       },
  893.  
  894.       {
  895.         "data": "Mode",
  896.         render: function (data, type, row) {
  897.           let strm = i18next.t("Unmanaged");
  898.           if (row.Smart)
  899.             strm = i18next.t(appdata.AutoModes.find(x => x.id == data).Name);
  900.  
  901.           return strm;
  902.         }
  903.       },
  904.  
  905.       {
  906.         "data": "State",
  907.         "className": "text-center",  //Антон: центровка отображения команд с учетом маски
  908.         render: function (data, type, row) {
  909.           let str = data + "%";
  910.           if (row.Type == 1) {//Box
  911.             str = SwitchStateForMask(data);//Антон: отображение команд с учетом маски
  912.           }
  913.           return str;
  914.         }
  915.  
  916.       },
  917.       {
  918.         "data": "Sip",
  919.         "className": "text-center text-nowrap",
  920.         render: function (data, type, row) {
  921.           if (type == "display") {
  922.             let ret = "";
  923.             if (row.Power >= 7 || (row.Power && box.Type == 2))
  924.               ret = `<span class="fa fa-plug text-success" data-toggle="tooltip" title="${i18next.t('Power Ok')}"></span>&nbsp;`;
  925.             else {
  926.               let title = i18next.t('Power Fail');
  927.               title += " (" + reverseString(row.Power.toString(2).padStart(3, "0")) + ")";
  928.  
  929.               ret = `<span class="fa fa-plug text-danger" data-toggle="tooltip" title="${title}"></span>&nbsp;`;
  930.             }
  931.  
  932.             if (!row.Trouble)
  933.               ret += `<span class="fa fa-check-circle text-success" data-toggle="tooltip" title="${i18next.t('Facility is Ok')}"></span>&nbsp;`;
  934.             else
  935.               ret += `<span class="fa fa-exclamation-triangle text-danger" data-html="true" data-toggle="tooltip" title="${errDecode(row.Trouble, box.Type)}"></span>&nbsp;`;
  936.  
  937.  
  938.             if (data)
  939.               ret += `<span class="fa fa-phone-square text-success" data-toggle="tooltip" title="${i18next.t('SIP is Ok')}"></span>&nbsp;`;
  940.             else
  941.               ret += `<span class="fa fa-phone-square text-danger" data-toggle="tooltip" title="${i18next.t('SIP fault')}"></span>&nbsp;`;
  942.  
  943.             if (row.Ip)
  944.               ret += `<span class="fa fa-wifi text-success" data-toggle="tooltip" title="${i18next.t('IP is Ok')}"></span>&nbsp;`;
  945.             else
  946.               ret += `<span class="fa fa-wifi text-danger" data-toggle="tooltip" title="${i18next.t('IP fault')}"></span>&nbsp;`;
  947.  
  948.             if (!row.Timeallert)
  949.               ret += `<span class="fa fa-clock-o text-success" data-toggle="tooltip" title="${i18next.t('Clock is Ok')}"></span>&nbsp;`;
  950.             else
  951.               ret += `<span class="fa fa-clock-o text-danger" data-toggle="tooltip" title="${i18next.t('Clock error')}"></span>&nbsp`;
  952.  
  953.             if (row.Controller)
  954.               ret += `<span class="fa fa-microchip text-success" data-toggle="tooltip" title="${i18next.t('Controller is OK')}"></span>&nbsp`;
  955.             else
  956.               ret += `<span class="fa fa-microchip text-danger" data-toggle="tooltip" title="${i18next.t('Controller error')}"></span>&nbsp`;
  957.  
  958.             if (row.Door)
  959.               ret += `<span class="fa fa-lock text-success" data-toggle="tooltip" title="${i18next.t('Case closed')}"></span>&nbsp`;
  960.             else
  961.               ret += `<span class="fa fa-unlock text-danger" data-toggle="tooltip" title="${i18next.t('Case open')}"></span>&nbsp`;
  962.  
  963.             if (row.Ous)
  964.               ret += `<span class="fa fa-refresh text-danger" data-toggle="tooltip" title="${i18next.t('Out of sync')}"></span>`;
  965.             else
  966.               ret += `<span class="fa fa-refresh text-success" data-toggle="tooltip" title="${i18next.t('Synced')}"></span>`;
  967.  
  968.             return ret;
  969.  
  970.           }
  971.           return data;
  972.         }
  973.       },
  974.  
  975.  
  976.       {
  977.         "data": "DimProfileName",
  978.         "className": "text-nowrap",
  979.         render: function (data, type, row) {
  980.           let strd = "";
  981.           let title = ""
  982.           if (row.Smart) {
  983.  
  984.             if (!(row.IncomingLog_id === null)) {
  985.               title = i18next.t("Notification");
  986.               if (!(row.Status_name === null))
  987.                 strd = escapeQuote(i18next.t(row.Status_Name)) + " ";
  988.               if (!(row.RemoteIP === null)) {
  989.                 strd = i18next.t("Statistics") + " ";
  990.                 title = "IP: " + row.RemoteIP;
  991.               }
  992.               strd += "(&lArr;)";
  993.  
  994.               if (type == "display")
  995.                 strd = `<span data-toggle="tooltip" title="${title}">${strd}</span>`;
  996.             }
  997.             if (!(row.OutgoingLog_id === null)) {
  998.               strd = "&rArr;";
  999.               strd = escapeQuote(i18next.t(row.Command_Name)) + " (" + strd + ")";
  1000.               if (row.IP_Name)
  1001.                 strd = escapeQuote(i18next.t(row.IP_Name)) + ", " + strd;
  1002.               title = i18next.t("Command");
  1003.               if (type == "display")
  1004.                 strd = `<span data-toggle="tooltip" title="${title}" class="text-${row.Hangupcause == 17 ? 'success' : 'danger'}">${strd}</span>`;
  1005.  
  1006.             }
  1007.             if (!(row.DimProfile_id === null)) {
  1008.               strd = data;
  1009.               title = i18next.t("Shedule");
  1010.               if (type == "display")
  1011.                 strd = `<span data-toggle="tooltip" title="${title}"}">${strd}</span>`;
  1012.            }
  1013.          }
  1014.          return strd;
  1015.        }
  1016.      }
  1017.  
  1018.    ]
  1019.  
  1020.  });
  1021.  
  1022.  dt.on("draw", function () {
  1023.    $('[data-toggle="tooltip"]').tooltip();
  1024.  
  1025.  });
  1026.  
  1027.  dt.on("init", function () {
  1028.    $('[data-toggle="tooltip"]').tooltip();
  1029.  });
  1030.  $('#stlog tbody').on('click', 'tr', function () {
  1031.  
  1032.    const rowData = dt.row(this).data();
  1033.    if (!rowData) return;
  1034.    liveMode = false;
  1035.    clearTimeout(renewTimer);
  1036.    $("#btnLive").prop("disabled", false);
  1037.    setSvgstate(rowData);
  1038.    setTextstate(rowData);
  1039.  
  1040.    $(this).addClass('table-primary').siblings().removeClass('table-primary');
  1041.  });
  1042.  $('#btnLive').on('click', () => {
  1043.    if (stlog?.rows?.length) {
  1044.      if (liveMode) return;
  1045.      liveMode = true;
  1046.      $("#btnLive").prop("disabled", true);
  1047.      $('#stlog tbody tr').removeClass('table-primary');
  1048.  
  1049.      onlogchane();
  1050.      renew();
  1051.    }
  1052.  });
  1053.  
  1054. }
  1055. // картинки мнемосхем
  1056. async function attachBackground() {
  1057.  const $svg = $("#circuit").children("svg");
  1058.  if (!$svg.length || $("#schemaWrapper").length) return;
  1059.  
  1060.  let typeCode = null;
  1061.  if (box.Name?.startsWith("TL"))      typeCode = "TL";
  1062.  else if (box.Name?.startsWith("G"))  typeCode = "G";
  1063.  else if (box.Name?.startsWith("4L"))  typeCode = "4L";
  1064.  
  1065.  let bgSrc = `${environment.base_url}/images/types/${typeCode || "default"}.png`;
  1066.  
  1067.  // картинка "заказного" фона мнемосхемы объекта
  1068.  $svg.wrap(
  1069.      '<div id="schemaWrapper" ' +
  1070.      '     style="position:relative; display: flex;\n' +
  1071.      '    align-items: flex-end;\n' +
  1072.      '    justify-content: center;\n' +
  1073.      '    padding-bottom: 75px;margin-top: 5px;">' +
  1074.      "</div>"
  1075.  );
  1076.  $("#schemaWrapper").prepend(
  1077.      `<img id="schemaBg" ` +
  1078.      `     src="${bgSrc}" ` +
  1079.      `     style="position:absolute;top:-10px; bottom: 0;left:-3px;width:100%;` +
  1080.       `            height:100%; object-fit: contain;object-position: left;z-index:1;pointer-events:none;" />`
  1081.  );
  1082.  $svg.css({position: "relative", zIndex: 2, maxWidth: '60%', marginRight: '30%', marginBottom: '-70px'});
  1083. }
  1084.  
  1085. $(async function () {
  1086.  const base = environment.base_uri;
  1087.  
  1088.  const resp = await $.getJSON(`${base}/?do=api&fn=user_settings`);
  1089.  const show = resp.rows[0].show_stats == 1;
  1090.  
  1091.  $('#toggleStats').prop('checked', show);
  1092.  applyStatsVisibility(show);
  1093.  
  1094.  $('#toggleStats').on('change', function () {
  1095.    const flag = this.checked ? 1 : 0;
  1096.    applyStatsVisibility(flag);
  1097.    $.post(`${base}/?do=api&fn=user_settings`, { show_stats: flag });
  1098.  });
  1099. });
  1100.  
  1101. function applyStatsVisibility (flag) {
  1102.  if (flag) {
  1103.    $('#divstat').show();
  1104.  } else {
  1105.    $('#divstat').hide();
  1106.  }
  1107. }
Advertisement
Add Comment
Please, Sign In to add comment