951 lines
24 KiB
JavaScript
951 lines
24 KiB
JavaScript
// https://medium.com/voodoo-engineering/websockets-on-production-with-node-js-bdc82d07bb9f
|
|
// https://evok-14.api-docs.io/1.11/bdymrhx7kgihpxpgm/websocket
|
|
exports.id = 'dido_controller_sbs';
|
|
exports.title = 'DI_DO_controller';
|
|
exports.group = 'Worksys';
|
|
exports.color = '#2134B0';
|
|
exports.input = 2;
|
|
exports.output = 3;
|
|
exports.icon = 'bolt';
|
|
exports.version = '1.0.3';
|
|
exports.readme = `# DI DO controller receives periodically status of digital inputs (state of main switch, rotary switch, state of braker)
|
|
It is also able to set new state for contactors (switch it off or on via digital output). Version v1.0.3 - after getting departures from sokolov server and temperature from services-prod01.worksys.io`;
|
|
|
|
const SEND_TO = {
|
|
debug: 0,
|
|
prod01: 1,
|
|
qas01: 2,
|
|
};
|
|
|
|
exports.install = function(instance) {
|
|
|
|
const SerialPort = require('serialport');
|
|
const WebSocket = require('ws');
|
|
const dbPins = TABLE("pins");
|
|
const { exec } = require('child_process');
|
|
const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper');
|
|
const sunCalc = require('./helper/suncalc')
|
|
|
|
const WEBSOCKET_ADDRESS = 'ws:/10.0.0.30:1234/ws';
|
|
const WS_RECONNECT_DELAY = 5000;
|
|
const RSPORT_RECONNECT_DELAY = 5000;
|
|
let ws = null;
|
|
let previousValues = {};
|
|
let start;
|
|
|
|
let rsPort = null;
|
|
let rsPortReceivedData = [];
|
|
|
|
let pinsData = {};//key is pin
|
|
let tbName_prod;
|
|
|
|
|
|
function handleRsPort() {
|
|
|
|
if (rsPort) {
|
|
rsPort.removeAllListeners();
|
|
rsPort = null;
|
|
}
|
|
|
|
rsPort = new SerialPort("/dev/ttyACM0", { autoOpen: false });
|
|
|
|
rsPort.on('open', function() {
|
|
console.log("Setting up rsPort called !");
|
|
exec("stty -F /dev/ttyACM0 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke", (error, stdout, stderr) => {
|
|
console.log({ "stdout": stdout, "stderr": stderr, "err": error });
|
|
});
|
|
});
|
|
|
|
rsPort.on('data', function(data) {
|
|
rsPortReceivedData = [...rsPortReceivedData, ...data];
|
|
// console.log('rsport -----',rsPortReceivedData);
|
|
console.log("rsport ok");
|
|
|
|
if (rsPortReceivedData.length >= 11) {
|
|
instance.send(0, { "ADD": rsPortReceivedData.slice(0, 4), "RESP_STATUS": rsPortReceivedData.slice(4, 5), "DATA": rsPortReceivedData.slice(5, 9), "CRC": rsPortReceivedData.slice(9, 11) });
|
|
}
|
|
rsPortReceivedData = [];
|
|
});
|
|
|
|
rsPort.on('error', function(err) {
|
|
console.log("Error on rsPort", err);
|
|
});
|
|
|
|
rsPort.on("close", () => {
|
|
setTimeout(handleRsPort, RSPORT_RECONNECT_DELAY);
|
|
});
|
|
|
|
}
|
|
|
|
|
|
// pin:string|type:string|tbname_demo:string|tbname_qas01:string|tbname_prod01:string|contactor:number
|
|
// +|al_osvetlenie|state_of_relay|p2rwdP7aGoOQLJNgAynEdKD6xWXbmMe3nvZqlzkV|o8ZzVA4jrXLmRPnvGBkDDak6ayWbg32Y9KwdxqJN|nJL5lPMwBx23YpqRe0rpZ47damXvWVbOrD4gNzy8|1|.............
|
|
// +|al_defibrilator|state_of_relay|rQx3NGKgVMRaXYAo9y19OQyZzkWnj1le6bdOLE20|2qKyjDVBNowRvLzWxd5LBRk1JXY4mp9PA3gl6OGZ|XMBbew5z4ELrZa2mRAd3Q978vPN6gy3DdVYlpKjq|0|.............
|
|
async function loadAllDb() {
|
|
let responsePins = await promisifyBuilder(dbPins.find());
|
|
pinsData = makeMapFromDbResult(responsePins, "pin");
|
|
//console.log("-------pins data",pinsData);
|
|
|
|
// main tbname - can be accessed with anything else (breakers, ...)
|
|
tbName_prod = pinsData["al_dverovy_kontakt"].tbname_prod01;
|
|
handleRsPort();
|
|
|
|
//! for some reason mqtt server connects to tb for about 1 minute. Thats why we start websocket after 30 seconds
|
|
setTimeout(handleWebsocket, 15000);
|
|
}
|
|
|
|
setTimeout(loadAllDb, 15000);
|
|
|
|
|
|
function handleWebsocket() {
|
|
|
|
console.log("handleWebsocket function called");
|
|
if (ws) {
|
|
ws.removeAllListeners();
|
|
ws = null;
|
|
}
|
|
|
|
ws = new WebSocket(WEBSOCKET_ADDRESS);
|
|
|
|
ws.onopen = function open() {
|
|
|
|
//console.log('pins data', pinsData);
|
|
let relay;
|
|
let toSend;
|
|
|
|
//we switch off screen, when flow restarts, to make sure touchscreen works fine
|
|
//let cmd = { "cmd": "set", "dev": "relay", "circuit": "al_obrazovka", "value": 0 };
|
|
//ws.send(JSON.stringify(cmd));
|
|
|
|
//! turn on "al_poe_switch", "al_zasuvky", "al_obrazovka"
|
|
Object.keys(pinsData).map(item => {
|
|
|
|
toSend = false;
|
|
|
|
//if(["al_poe_switch", "al_zasuvky"].includes(item))
|
|
if (["al_poe_switch", "al_zasuvky", "al_obrazovka"].includes(item)) {
|
|
relay = 1;
|
|
toSend = true;
|
|
}
|
|
//else if(["al_osvetlenie", "al_defibrilator", "al_obrazovka"].includes(item))
|
|
else if (["al_osvetlenie", "al_defibrilator"].includes(item)) {
|
|
relay = 0;
|
|
toSend = true;
|
|
}
|
|
|
|
if (toSend) {
|
|
const values = {
|
|
"state_of_relay": relay,
|
|
"status": "OK"
|
|
}
|
|
|
|
let tbName = pinsData[item].tbname_prod01;
|
|
previousValues[item] = relay;
|
|
|
|
let cmd = { "cmd": "set", "dev": "relay", "circuit": item, "value": relay };
|
|
// console.log("--cmd ---------", cmd);
|
|
|
|
if (item == 'al_obrazovka') {
|
|
setTimeout(() => {
|
|
ws.send(JSON.stringify(cmd));
|
|
sendToTb(values, tbName);
|
|
}, 60000)
|
|
}
|
|
else {
|
|
ws.send(JSON.stringify(cmd));
|
|
sendToTb(values, tbName);
|
|
}
|
|
|
|
}
|
|
})
|
|
//ws.send(JSON.stringify({"cmd":"all"}))
|
|
startRequests();
|
|
};
|
|
|
|
ws.onmessage = function(data) {
|
|
data = JSON.parse(data.data);
|
|
//console.log("-------data web socket: ", data);
|
|
|
|
if (!Array.isArray(data)) return;
|
|
|
|
data.map(item => {
|
|
|
|
let value = item['value'];
|
|
let alias = item["alias"];
|
|
if (alias == undefined) return;
|
|
|
|
switchLogic(alias, value);
|
|
})
|
|
}
|
|
|
|
ws.on('error', (err) => {
|
|
console.log("Dido_controller_sbs: error on websocket, ", err);
|
|
})
|
|
|
|
ws.onclose = function() {
|
|
stopRequests();
|
|
console.log("ws connection closed, reconnecting in 5 seconds");
|
|
setTimeout(handleWebsocket, WS_RECONNECT_DELAY);
|
|
}
|
|
}
|
|
|
|
const startRequests = () => {
|
|
console.log("startRequest function called");
|
|
start = setInterval(() => {
|
|
// console.log("data from evok requested");
|
|
ws.send(JSON.stringify({ "cmd": "all" }));
|
|
// ws.send(JSON.stringify({"cmd":"filter", "devices":["input", "relay"]}));
|
|
}, 120000)
|
|
}
|
|
|
|
|
|
const stopRequests = () => {
|
|
console.log("stopRequests function called")
|
|
clearInterval(start);
|
|
}
|
|
|
|
instance.on("close", () => {
|
|
rsPort.close();
|
|
ws.close();
|
|
});
|
|
|
|
|
|
function generateCommand(rpcReceived) {
|
|
|
|
let values = deepGetByPaths(rpcReceived, 'content.data.params.entities[0].entity_type', 'content.data.params.entities[0].tb_name', 'content.data.params.payload.value');
|
|
let [entity_type, tb_name, value] = values;
|
|
|
|
if (value === undefined || tb_name === undefined || entity_type === undefined) {
|
|
console.log("Dido_controller_sbs: bad rpc received");
|
|
return;
|
|
}
|
|
|
|
value ? value = 1 : value = 0;
|
|
|
|
if (entity_type === "generic_relays") {
|
|
let entries = Object.entries(pinsData);
|
|
for (const [alias, data] of entries) {
|
|
|
|
//if(data.tbname_prod01 === tb_name || data.tbname_qas01 === tb_name) {
|
|
if (data.tbname_prod01 === tb_name) {
|
|
let cmd = { "cmd": "set", "dev": "relay", "circuit": alias, "value": value };
|
|
// console.log("--cmd ---------", cmd);
|
|
ws.send(JSON.stringify(cmd));
|
|
}
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
|
|
//function gets value of a nested property in an object and returns undefined if it does not exists:
|
|
function getNested(obj, ...args) {
|
|
return args.reduce((obj, level) => obj && obj[level], obj)
|
|
}
|
|
|
|
const deepGet = (obj, keys) => keys.reduce((xs, x) => xs?.[x] ?? undefined, obj);
|
|
|
|
const deepGetByPaths = (obj, ...paths) =>
|
|
paths.map(path =>
|
|
deepGet(
|
|
obj,
|
|
path
|
|
.replace(/\[([^\[\]]*)\]/g, '.$1.')
|
|
.split('.')
|
|
.filter(t => t !== '')
|
|
)
|
|
);
|
|
|
|
|
|
instance.on("data", flowdata => {
|
|
//console.log('flowdaaata: ', flowdata.data);
|
|
if (flowdata.data instanceof Object) {
|
|
if (flowdata.data.hasOwnProperty("topic") && flowdata.data.hasOwnProperty("content")) {
|
|
|
|
const entity_type = deepGetByPaths(flowdata.data, 'content.data.params.entities[0].entity_type')[0];
|
|
|
|
if (entity_type == "bus_stop_mmcite") {
|
|
|
|
if (!rsPort.isOpen) {
|
|
handleRsPort();// console.log("openning rsport asyn");
|
|
//rsPort.open();
|
|
}
|
|
|
|
console.log("running ..");
|
|
let toSend = true;
|
|
const beginning = [0, 0, 0, 0, 0, 0, 0];
|
|
let value = getNested(flowdata.data, "content", "data", "params", "payload", "value");
|
|
if (value === undefined) console.log("Dido_controller_sbs: flowdata.data value from platform is undefined");
|
|
|
|
let bytes = [];
|
|
|
|
if (value == 0) {
|
|
bytes = [0, 0, 0, 1];
|
|
}
|
|
else {
|
|
value = value * 1000;
|
|
bytes[0] = (value >> 24) & 0xFF;
|
|
bytes[1] = (value >> 16) & 0xFF;
|
|
bytes[2] = (value >> 8) & 0xFF;
|
|
bytes[3] = value & 0xFF;
|
|
}
|
|
|
|
let finalCommand = beginning.concat(bytes);
|
|
console.log(finalCommand);
|
|
|
|
// maybe not necessary - I started from 1, to make 0,2s delay in execution - just to make sure rsPort is set.
|
|
for (let i = 1; i < 4; i++) {
|
|
|
|
setTimeout(function timer() {
|
|
|
|
finalCommand[6] = i - 1;
|
|
rsPort.write(Buffer.from(calculateCRC16(finalCommand)), function(err) {
|
|
|
|
if (err === undefined) {
|
|
// console.log("data zapisane do rsPortu");
|
|
|
|
if (toSend) {
|
|
const values = { dimming: value / 1000 };
|
|
sendToTb(values, tbName_prod);
|
|
toSend = false;
|
|
}
|
|
|
|
}
|
|
else {
|
|
console.log("rsPort WRITE error", err);
|
|
}
|
|
});
|
|
|
|
finalCommand.splice(11, 2);
|
|
|
|
}, i * 200);
|
|
}
|
|
|
|
}
|
|
else {
|
|
generateCommand(flowdata.data);
|
|
}
|
|
|
|
}
|
|
else {
|
|
ws.send(JSON.stringify(flowdata.data));
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
setInterval(reportTimeAndVersion, 300000);
|
|
|
|
|
|
function reportTimeAndVersion() {
|
|
let values = {};
|
|
|
|
if (previousValues["edge_fw_version"] != exports.version) {
|
|
values["edge_fw_version"] = exports.version;
|
|
previousValues["edge_fw_version"] = exports.version;
|
|
}
|
|
|
|
let ts = Date.now();
|
|
values["edge_date_time"] = ts - ts % 60000 //round to full minute
|
|
|
|
sendToTb(values, tbName_prod);
|
|
}
|
|
|
|
|
|
let times = null;
|
|
|
|
function getSunriseSunsetTimes() {
|
|
const d = new Date();
|
|
//to make sure times are calculated for local timezone with current day and months, we add "d.getFullYear(), d.getMonth(), d.getDate(), 12, 0, 0, 0, 0"
|
|
times = sunCalc.getTimes(new Date(d.getFullYear(), d.getMonth(), d.getDate(), 12, 0, 0, 0, 0), '50.10', '12.38');
|
|
console.log("Sunrise and sunset times set: ", times);
|
|
}
|
|
|
|
|
|
// if new day comes, we get new dusk and dawn times
|
|
function checkForNewDay() {
|
|
// Get the current date and time
|
|
const currentDate = new Date();
|
|
|
|
// Get the date and time from 2 hours ago
|
|
const previousDate = new Date();
|
|
previousDate.setHours(currentDate.getHours() - 2);
|
|
|
|
// Compare the dates to check if a new day has started
|
|
if (currentDate.getDate() !== previousDate.getDate()) {
|
|
console.log("A new day has started!");
|
|
getSunriseSunsetTimes();
|
|
}
|
|
}
|
|
|
|
|
|
getSunriseSunsetTimes(); //to get times right after flow starts
|
|
setInterval(checkForNewDay, 2 * 60 * 60 * 1000);
|
|
|
|
|
|
function toggleBusLampIfSunriseOrSunset() {
|
|
|
|
const lampState = previousValues['al_osvetlenie'];
|
|
console.log('lampState', lampState)
|
|
|
|
const date = Date.now();
|
|
|
|
const sunrise = new Date(times.sunrise).getTime(); //1680236326458
|
|
const sunset = new Date(times.sunset).getTime(); //1680286387995
|
|
|
|
console.log(sunrise, sunset);
|
|
|
|
if (date > sunrise && date < sunset && lampState === 1) {
|
|
let cmd = { "cmd": "set", "dev": "relay", "circuit": "al_osvetlenie", "value": 0 };
|
|
ws.send(JSON.stringify(cmd));
|
|
console.log('---- Vypnute osvetlenie');
|
|
}
|
|
else if (date > sunset && lampState === 0) {
|
|
let cmd = { "cmd": "set", "dev": "relay", "circuit": "al_osvetlenie", "value": 1 };
|
|
ws.send(JSON.stringify(cmd));
|
|
console.log('++++ Zapnute osvetlenie');
|
|
}
|
|
else if (date < sunrise && lampState == 0) {
|
|
let cmd = { "cmd": "set", "dev": "relay", "circuit": "al_osvetlenie", "value": 1 };
|
|
ws.send(JSON.stringify(cmd));
|
|
console.log('---- Je novy den, nastavil sa novy sunset sunrise a zaplo sa osvetlenie');
|
|
}
|
|
else {
|
|
console.log('S osvetlenim sa nic nespravilo');
|
|
}
|
|
|
|
}
|
|
|
|
setTimeout(toggleBusLampIfSunriseOrSunset, 60000); // to switch light on, if neccessarry, after program starts, it must be after websocket started ( 30 seconds and more)
|
|
setInterval(toggleBusLampIfSunriseOrSunset, 900000); // than we check every 15 minutes if light needs to be turned on or off
|
|
|
|
|
|
const switchLogic = (alias, newValue) => {
|
|
|
|
let values = { status: "OK" };
|
|
let pinIndex = alias;
|
|
let newPinValue = newValue;
|
|
let obj = pinsData[pinIndex];
|
|
|
|
if (obj == undefined) {
|
|
previousValues[pinIndex] = newPinValue;
|
|
return;
|
|
}
|
|
|
|
let type = obj.type;
|
|
|
|
//default value
|
|
let value = true;
|
|
if (newPinValue === 0) value = false;
|
|
|
|
if (type == "state_of_relay") {
|
|
value ? value = 1 : value = 0;
|
|
pinsData[pinIndex].contactor = value;
|
|
}
|
|
|
|
values[obj.type] = value;
|
|
|
|
if (pinsData.hasOwnProperty(pinIndex)) {
|
|
let insertIntoTb = false;
|
|
if (newPinValue != previousValues[pinIndex]) insertIntoTb = true;
|
|
|
|
if (insertIntoTb) {
|
|
let tbName = obj.tbname_prod01;
|
|
|
|
sendToTb(values, tbName);
|
|
|
|
//pin was changed
|
|
previousValues[pinIndex] = newPinValue;
|
|
// console.log("previous ----", previousValues);
|
|
}
|
|
}
|
|
else {
|
|
console.log("no pinIndex", pinIndex, pinsData);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* @param {object} values - values to be sent to TB qas01 and demo
|
|
*/
|
|
const sendToTb = (values, tbName) => {
|
|
const tbarray = [
|
|
{
|
|
"ts": Date.now(),
|
|
"values": values
|
|
}
|
|
];
|
|
|
|
let dataToTb = { [tbName]: tbarray };
|
|
instance.send(SEND_TO.prod01, dataToTb);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
function calculateCRC16(bytes) {
|
|
let crc = 0;
|
|
let out = 0;
|
|
let CRC16 = 0x8005;
|
|
let bits_read = 0;
|
|
let bit_flag = 0;
|
|
|
|
for (let i = 0; i < bytes.length; i++) {
|
|
for (let j = 0; j < 8; j++) {
|
|
bit_flag = out >> 15;
|
|
|
|
out = out << 1;
|
|
out = out & 0xFFFF;
|
|
out = out | ((bytes[i] >> bits_read) & 1);
|
|
out = out & 0xFFFF;
|
|
|
|
bits_read = bits_read + 1;
|
|
if (bit_flag > 0) {
|
|
out = out ^ CRC16;
|
|
out = out & 0xFFFF;
|
|
}
|
|
}
|
|
|
|
bits_read = 0;
|
|
}
|
|
|
|
for (let i = 0; i < 16; i++) {
|
|
bit_flag = out >> 15;
|
|
out = out << 1;
|
|
out = out & 0xFFFF;
|
|
if (bit_flag > 0) {
|
|
out = out ^ CRC16;
|
|
out = out & 0xFFFF;
|
|
}
|
|
}
|
|
|
|
let i = 0x8000;
|
|
let j = 0x0001;
|
|
while (i > 0) {
|
|
if ((i & out) > 0) {
|
|
crc = crc | j;
|
|
}
|
|
|
|
i = i >> 1;
|
|
j = j << 1;
|
|
}
|
|
|
|
bytes.push((crc >> 8) & 0xFF);
|
|
bytes.push(crc & 0xFF);
|
|
|
|
return bytes;
|
|
}
|
|
|
|
|
|
|
|
const dimmer = {
|
|
"topic": "v1/gateway/rpc",
|
|
"content": {
|
|
"device": "L2jNOVpdARa9XvoeJDPELbybkmPBxqn7Ww3gzGQ1",
|
|
"data": {
|
|
"id": 11,
|
|
"method": "set_command",
|
|
"params": {
|
|
"entities": [
|
|
{
|
|
"entity_type": "bus_stop_mmcite",
|
|
"tb_name": "L2jNOVpdARa9XvoeJDPELbybkmPBxqn7Ww3gzGQ1"
|
|
}
|
|
],
|
|
"command": "dimming",
|
|
"payload": {
|
|
"value": 8
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let rpcReceived = {
|
|
"topic": "v1/gateway/rpc",
|
|
"content": {
|
|
"device": "mp93b2nvd7OoqgBeEyE7N18kjlAV1Y4ZNXwW0zLG",
|
|
"data": {
|
|
"id": 46,
|
|
"method": "set_command",
|
|
"params": {
|
|
"entities": [
|
|
{
|
|
"entity_type": "generic_relays",
|
|
"tb_name": "9YkRpoB2vVa0mKqEO8Zr198jW43eXnJML6GxzbwQ"
|
|
}
|
|
],
|
|
"command": "switch",
|
|
"payload": {
|
|
"value": 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const previous = {
|
|
al_breaker_12v: 1,
|
|
al_breaker_48: 1,
|
|
al_istic_obrazovka: 1,
|
|
al_istic_socket: 1,
|
|
al_dverovy_kontakt: 0,
|
|
'28667676E0013C21': 25.8,
|
|
temperature_out: 23.6,
|
|
'26A33E6802000081': 27.4
|
|
}
|
|
|
|
|
|
const pinsddata = {
|
|
al_osvetlenie: {
|
|
pin: 'al_osvetlenie',
|
|
type: 'state_of_relay',
|
|
tbname_demo: 'YnBzbeGaAL62jowRv59vVm8Xq9QpZ0K7O1dg4xVl',
|
|
tbname_qas01: 'o8ZzVA4jrXLmRPnvGBkDDak6ayWbg32Y9KwdxqJN',
|
|
contactor: 1
|
|
},
|
|
al_switch: {
|
|
pin: 'al_switch',
|
|
type: 'state_of_relay',
|
|
tbname_demo: 'zXBoWbEZjO0lrpqnRyoObvykmVeaNAGdL9g4QKxP',
|
|
tbname_qas01: '9rKRNEDXVYzWb0qZmlQjnqQn3jByxv42a6LPJ1oM',
|
|
contactor: 1
|
|
},
|
|
al_media_player: {
|
|
pin: 'al_media_player',
|
|
type: 'state_of_relay',
|
|
tbname_demo: 'p2rwdP7aGoOQLJNgAynE1wD6xWXbmMe3nvZqlzkV',
|
|
tbname_qas01: '2qKyjDVBNowRvLzWxd5LBRk1JXY4mp9PA3gl6OGZ',
|
|
contactor: 1
|
|
},
|
|
al_aibox: {
|
|
pin: 'al_aibox',
|
|
type: 'state_of_relay',
|
|
tbname_demo: 'rQx3NGKgVMRaXYAo9y19dpyZzkWnj1le6bdOLE20',
|
|
tbname_qas01: '1JD0MvzbwqAoZ36dPO7NBZ7LlmpgxGrBnNEK4Ry9',
|
|
contactor: 0
|
|
},
|
|
al_poe_switch1: {
|
|
pin: 'al_poe_switch1',
|
|
type: 'state_of_relay',
|
|
tbname_demo: 'nreBJ6PMqgz20pYEL82JeK8G1jkWwdQxZVNAOlmK',
|
|
tbname_qas01: '28LgqDR9braJKYmxd37EB95XBpEnyjNwPGAeO0o6',
|
|
contactor: 1
|
|
},
|
|
al_poe_switch2: {
|
|
pin: 'al_poe_switch2',
|
|
type: 'state_of_relay',
|
|
tbname_demo: 'klN4JpQAx362o9XYZDNPQ45grWw1P7GEbdBM0vRV',
|
|
tbname_qas01: 'P1Xabdx9AwGJr2WE4zQ2eV5NBmDMlvKoeLOqn8Z6',
|
|
contactor: 1
|
|
},
|
|
al_obrazovka1: {
|
|
pin: 'al_obrazovka1',
|
|
type: 'state_of_relay',
|
|
tbname_demo: 'ZmYXEbw9lVWRv1jLxDeJgzydgAMz4PKQnNJ6eB23',
|
|
tbname_qas01: 'dYBAenlq4zxv9jEZgaQqLq52ODyLoWKmGR06V1JP',
|
|
contactor: 1
|
|
},
|
|
al_obrazovka2: {
|
|
pin: 'al_obrazovka2',
|
|
type: 'state_of_relay',
|
|
tbname_demo: 'EonaKBOGbj9034MgJ8WvWe5qXvxNWVkAPQz21R6L',
|
|
tbname_qas01: 'GAqD3MNdpxwXVnj6z17J8yQrlKgZR0m9bB2aOWPY',
|
|
contactor: 1
|
|
},
|
|
al_breaker_12v: {
|
|
pin: 'al_breaker_12v',
|
|
type: 'breaker_12V_on',
|
|
tbname_demo: 'L2jNOVpdARa9XvoeJDPELbybkmPBxqn7Ww3gzGQ1',
|
|
tbname_qas01: '6nO4xlGE3zKVJdRXYZkMBK7BA28DoyMLg1pe9bar',
|
|
contactor: 0
|
|
},
|
|
al_breaker_48v: {
|
|
pin: 'al_breaker_48v',
|
|
type: 'breaker_48V_on',
|
|
tbname_demo: 'L2jNOVpdARa9XvoeJDPELbybkmPBxqn7Ww3gzGQ1',
|
|
tbname_qas01: '6nO4xlGE3zKVJdRXYZkMBK7BA28DoyMLg1pe9bar',
|
|
contactor: 0
|
|
},
|
|
al_istic_obrazovka: {
|
|
pin: 'al_istic_obrazovka',
|
|
type: 'screen_breaker_on',
|
|
tbname_demo: 'L2jNOVpdARa9XvoeJDPELbybkmPBxqn7Ww3gzGQ1',
|
|
tbname_qas01: '6nO4xlGE3zKVJdRXYZkMBK7BA28DoyMLg1pe9bar',
|
|
contactor: 0
|
|
},
|
|
al_istic_socket: {
|
|
pin: 'al_istic_socket',
|
|
type: 'socket_breaker_on',
|
|
tbname_demo: 'L2jNOVpdARa9XvoeJDPELbybkmPBxqn7Ww3gzGQ1',
|
|
tbname_qas01: '6nO4xlGE3zKVJdRXYZkMBK7BA28DoyMLg1pe9bar',
|
|
contactor: 0
|
|
},
|
|
al_dverovy_kontakt: {
|
|
pin: 'al_dverovy_kontakt',
|
|
type: 'door_condition',
|
|
tbname_demo: 'L2jNOVpdARa9XvoeJDPELbybkmPBxqn7Ww3gzGQ1',
|
|
tbname_qas01: '6nO4xlGE3zKVJdRXYZkMBK7BA28DoyMLg1pe9bar',
|
|
contactor: 0
|
|
},
|
|
'26A33E6802000081': {
|
|
pin: '26A33E6802000081',
|
|
type: 'humidity_out',
|
|
tbname_demo: 'L2jNOVpdARa9XvoeJDPELbybkmPBxqn7Ww3gzGQ1',
|
|
tbname_qas01: '6nO4xlGE3zKVJdRXYZkMBK7BA28DoyMLg1pe9bar',
|
|
contactor: 0
|
|
},
|
|
'28667676E0013C21': {
|
|
pin: '28667676E0013C21',
|
|
type: 'temperature',
|
|
tbname_demo: 'L2jNOVpdARa9XvoeJDPELbybkmPBxqn7Ww3gzGQ1',
|
|
tbname_qas01: '6nO4xlGE3zKVJdRXYZkMBK7BA28DoyMLg1pe9bar',
|
|
contactor: 0
|
|
}
|
|
}
|
|
|
|
|
|
const datawebsocket = [
|
|
{
|
|
glob_dev_id: 1,
|
|
modes: ['Simple'],
|
|
value: 0,
|
|
circuit: '1_08',
|
|
alias: 'al_obrazovka2',
|
|
pending: false,
|
|
relay_type: 'physical',
|
|
dev: 'relay',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
glob_dev_id: 1,
|
|
modes: ['Simple'],
|
|
value: 0,
|
|
circuit: '1_01',
|
|
alias: 'al_osvetlenie',
|
|
pending: false,
|
|
relay_type: 'physical',
|
|
dev: 'relay',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
glob_dev_id: 1,
|
|
modes: ['Simple'],
|
|
value: 0,
|
|
circuit: '1_02',
|
|
alias: 'al_switch',
|
|
pending: false,
|
|
relay_type: 'physical',
|
|
dev: 'relay',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
glob_dev_id: 1,
|
|
modes: ['Simple'],
|
|
value: 1,
|
|
circuit: '1_03',
|
|
alias: 'al_media_player',
|
|
pending: false,
|
|
relay_type: 'physical',
|
|
dev: 'relay',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
glob_dev_id: 1,
|
|
modes: ['Simple'],
|
|
value: 1,
|
|
circuit: '1_04',
|
|
alias: 'al_aibox',
|
|
pending: false,
|
|
relay_type: 'physical',
|
|
dev: 'relay',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
glob_dev_id: 1,
|
|
modes: ['Simple'],
|
|
value: 1,
|
|
circuit: '1_05',
|
|
alias: 'al_poe_switch1',
|
|
pending: false,
|
|
relay_type: 'physical',
|
|
dev: 'relay',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
glob_dev_id: 1,
|
|
modes: ['Simple'],
|
|
value: 1,
|
|
circuit: '1_06',
|
|
alias: 'al_poe_switch2',
|
|
pending: false,
|
|
relay_type: 'physical',
|
|
dev: 'relay',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
glob_dev_id: 1,
|
|
modes: ['Simple'],
|
|
value: 0,
|
|
circuit: '1_07',
|
|
alias: 'al_obrazovka1',
|
|
pending: false,
|
|
relay_type: 'physical',
|
|
dev: 'relay',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
counter_modes: ['Enabled', 'Disabled'],
|
|
glob_dev_id: 1,
|
|
modes: ['Simple', 'DirectSwitch'],
|
|
value: 0,
|
|
circuit: '1_08',
|
|
debounce: 50,
|
|
counter: 0,
|
|
counter_mode: 'Enabled',
|
|
dev: 'input',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
counter_mode: 'Enabled',
|
|
counter_modes: ['Enabled', 'Disabled'],
|
|
glob_dev_id: 1,
|
|
dev: 'input',
|
|
modes: ['Simple', 'DirectSwitch'],
|
|
debounce: 50,
|
|
counter: 0,
|
|
value: 0,
|
|
alias: 'al_breaker_12v',
|
|
mode: 'Simple',
|
|
circuit: '1_01'
|
|
},
|
|
{
|
|
counter_mode: 'Enabled',
|
|
counter_modes: ['Enabled', 'Disabled'],
|
|
glob_dev_id: 1,
|
|
dev: 'input',
|
|
modes: ['Simple', 'DirectSwitch'],
|
|
debounce: 50,
|
|
counter: 0,
|
|
value: 0,
|
|
alias: 'al_breaker_48',
|
|
mode: 'Simple',
|
|
circuit: '1_02'
|
|
},
|
|
{
|
|
counter_mode: 'Enabled',
|
|
counter_modes: ['Enabled', 'Disabled'],
|
|
glob_dev_id: 1,
|
|
dev: 'input',
|
|
modes: ['Simple', 'DirectSwitch'],
|
|
debounce: 50,
|
|
counter: 0,
|
|
value: 0,
|
|
alias: 'al_istic_obrazovka',
|
|
mode: 'Simple',
|
|
circuit: '1_03'
|
|
},
|
|
{
|
|
counter_mode: 'Enabled',
|
|
counter_modes: ['Enabled', 'Disabled'],
|
|
glob_dev_id: 1,
|
|
dev: 'input',
|
|
modes: ['Simple', 'DirectSwitch'],
|
|
debounce: 50,
|
|
counter: 0,
|
|
value: 0,
|
|
alias: 'al_istic_socket',
|
|
mode: 'Simple',
|
|
circuit: '1_04'
|
|
},
|
|
{
|
|
counter_modes: ['Enabled', 'Disabled'],
|
|
glob_dev_id: 1,
|
|
modes: ['Simple', 'DirectSwitch'],
|
|
value: 0,
|
|
circuit: '1_05',
|
|
debounce: 50,
|
|
counter: 0,
|
|
counter_mode: 'Enabled',
|
|
dev: 'input',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
counter_modes: ['Enabled', 'Disabled'],
|
|
glob_dev_id: 1,
|
|
modes: ['Simple', 'DirectSwitch'],
|
|
value: 0,
|
|
circuit: '1_06',
|
|
debounce: 50,
|
|
counter: 0,
|
|
counter_mode: 'Enabled',
|
|
dev: 'input',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
counter_modes: ['Enabled', 'Disabled'],
|
|
glob_dev_id: 1,
|
|
modes: ['Simple', 'DirectSwitch'],
|
|
value: 0,
|
|
circuit: '1_07',
|
|
debounce: 50,
|
|
counter: 0,
|
|
counter_mode: 'Enabled',
|
|
dev: 'input',
|
|
mode: 'Simple'
|
|
},
|
|
{
|
|
interval: 3,
|
|
value: 24.75,
|
|
circuit: '28667676E0013C21',
|
|
address: '28667676E0013C21',
|
|
time: 1645103817.127406,
|
|
typ: 'DS18B20',
|
|
lost: false,
|
|
dev: 'temp'
|
|
},
|
|
{
|
|
vis: '0.0209926',
|
|
dev: '1wdevice',
|
|
typ: 'DS2438',
|
|
lost: false,
|
|
temp: '24.7812',
|
|
interval: 3,
|
|
vad: '1.6',
|
|
humidity: 23.710019217090384,
|
|
vdd: '5.29',
|
|
circuit: '26A33E6802000081',
|
|
time: 1645103815.074027
|
|
},
|
|
{
|
|
bus: '/dev/i2c-2',
|
|
interval: 3,
|
|
dev: 'owbus',
|
|
scan_interval: 300,
|
|
circuit: '1',
|
|
do_scan: false,
|
|
do_reset: false
|
|
},
|
|
{
|
|
glob_dev_id: 1,
|
|
last_comm: 0.012907028198242188,
|
|
ver2: '0.1',
|
|
sn: 162,
|
|
circuit: '1',
|
|
model: 'S207',
|
|
dev: 'neuron',
|
|
board_count: 1
|
|
},
|
|
{
|
|
circuit: '1_01',
|
|
value: 0,
|
|
glob_dev_id: 1,
|
|
dev: 'wd',
|
|
timeout: 5000,
|
|
was_wd_reset: 0,
|
|
nv_save: 0
|
|
}
|
|
]
|
|
|