sokolov-sbs-flowserver/flow/dido_controller_sbs.js
2025-08-07 21:49:01 +02:00

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
}
]