1128 lines
35 KiB
JavaScript
1128 lines
35 KiB
JavaScript
|
|
exports.id = 'modbus_citysys';
|
|||
|
|
exports.title = 'Modbus_citysys';
|
|||
|
|
exports.version = '1.0.0';
|
|||
|
|
exports.group = 'Worksys';
|
|||
|
|
exports.color = '#2134B0';
|
|||
|
|
exports.input = 1;
|
|||
|
|
exports.output = ["red", "white", "blue", "orange"];
|
|||
|
|
exports.click = false;
|
|||
|
|
exports.author = 'Jakub Klena';
|
|||
|
|
exports.icon = 'bolt';
|
|||
|
|
exports.options = { edge: "undefined" };
|
|||
|
|
|
|||
|
|
exports.html = `<div class="padding">
|
|||
|
|
<div class="row">
|
|||
|
|
<div class="col-md-6">
|
|||
|
|
<div data-jc="textbox" data-jc-path="edge" data-jc-config="placeholder:undefined;required:true" class="m">Edge TB Name</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>`;
|
|||
|
|
|
|||
|
|
exports.readme = `# Energomonitor
|
|||
|
|
## Outputs
|
|||
|
|
|
|||
|
|
- *Red* - ERROR output (can connect to filewriter or something)
|
|||
|
|
- *White* - STATUS output (answers to your commands, ERRORS and WARNINGS from your commands go both to this and to their own outputs, so they get logged)
|
|||
|
|
- *Blue* - TB output (pure data for TB)
|
|||
|
|
`;
|
|||
|
|
|
|||
|
|
|
|||
|
|
const instanceSendTo = {
|
|||
|
|
error: 0,
|
|||
|
|
debug: 1,
|
|||
|
|
tb: 2,
|
|||
|
|
di_do_controller: 3
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const DataToTbHandler = require('./helper/DataToTbHandler.js');
|
|||
|
|
const { sendNotification } = require('./helper/notification_reporter.js');
|
|||
|
|
const dbRelays = TABLE("relays");
|
|||
|
|
const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js');
|
|||
|
|
let tbname;
|
|||
|
|
|
|||
|
|
async function loadSettings()
|
|||
|
|
{
|
|||
|
|
//todo global FLOW.OMS_edgeName is making problem, so we load it here as well, it should not be
|
|||
|
|
let responseRelays = await promisifyBuilder(dbRelays.find());
|
|||
|
|
FLOW.OMS_edgeName = responseRelays[0]["tbname"];
|
|||
|
|
tbname = FLOW.OMS_edgeName;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
loadSettings();
|
|||
|
|
|
|||
|
|
exports.install = function(instance) {
|
|||
|
|
const SerialPort = require('serialport');
|
|||
|
|
const { exec } = require('child_process');
|
|||
|
|
const fs = require("fs");
|
|||
|
|
const filepath = F.path.root("saved_data/modbus_settings");
|
|||
|
|
const backup_filepath = F.path.root("saved_data/modbus_settings_backup");
|
|||
|
|
|
|||
|
|
const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler.js');
|
|||
|
|
const errorHandler = new ErrorToServiceHandler();
|
|||
|
|
|
|||
|
|
let receivedDataArray = [];
|
|||
|
|
|
|||
|
|
|
|||
|
|
instance.CONFIG = {
|
|||
|
|
"isRunning": false,
|
|||
|
|
"debug": true,
|
|||
|
|
"timeoutTime": 10000,
|
|||
|
|
"msgWaitTime": 1000,
|
|||
|
|
"port": "/dev/ttymxc1",
|
|||
|
|
//"port_options": "stty -F /dev/ttymxc1 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke"
|
|||
|
|
"port_options": "stty -F /dev/ttymxc1 9600 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let PRIVATEVARS = {
|
|||
|
|
"errBuffer": [], // Buffer for error messages
|
|||
|
|
"tbBuffer": [], // Buffer for TB push messages
|
|||
|
|
"device_index": 0,
|
|||
|
|
"cmd_index": -1,
|
|||
|
|
"devices": [
|
|||
|
|
/*{
|
|||
|
|
"name": "Elektrometer 1",
|
|||
|
|
"tb_name": "EOzNMgZ9n43qPbjXmy7zwdA2DKdYvW5e6pxGRrVa",
|
|||
|
|
"type": "EM111",
|
|||
|
|
"address": 1,
|
|||
|
|
"data":[],
|
|||
|
|
"cmd":[],
|
|||
|
|
"timeoutcount":0,
|
|||
|
|
"status":"virtual"
|
|||
|
|
},*/
|
|||
|
|
// {
|
|||
|
|
// "name": "Elektrometer 2",
|
|||
|
|
// "tb_name": "pJX1ObgmqGZ54DMyYL7aDdkEVdve38WKRzwjNrQ9",
|
|||
|
|
// "type": "EM111",
|
|||
|
|
// "address": 2,
|
|||
|
|
// "data":[],
|
|||
|
|
// "cmd":[],
|
|||
|
|
// "timeoutcount":0,
|
|||
|
|
// "status":"virtual"
|
|||
|
|
// },
|
|||
|
|
// {
|
|||
|
|
// "name": "Elektrometer 3",
|
|||
|
|
// "tb_name": "XRvmwNz8QPblKp41GD7lKVkJrLVYoBO92dMegn6W",
|
|||
|
|
// "type": "EM111",
|
|||
|
|
// "address": 3,
|
|||
|
|
// "data":[],
|
|||
|
|
// "cmd":[],
|
|||
|
|
// "timeoutcount":0,
|
|||
|
|
// "status":"virtual"
|
|||
|
|
// },
|
|||
|
|
// {
|
|||
|
|
// "name": "Elektrometer 4",
|
|||
|
|
// "tb_name": "oRO8rjaBDy21qPQJzW7oD9ApK3xmNleVZg9Ed4Gw",
|
|||
|
|
// "type": "EM111",
|
|||
|
|
// "address": 4,
|
|||
|
|
// "data":[],
|
|||
|
|
// "cmd":[],
|
|||
|
|
// "timeoutcount":0,
|
|||
|
|
// "status":"virtual"
|
|||
|
|
// },
|
|||
|
|
{
|
|||
|
|
"name": "Elektrometer 1",
|
|||
|
|
"tb_name": "KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV",
|
|||
|
|
"type": "EM340",
|
|||
|
|
"address": 1,
|
|||
|
|
"data":[],
|
|||
|
|
"cmd":[],
|
|||
|
|
"timeoutcount":0,
|
|||
|
|
"status":"virtual"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"cmd_tables": [
|
|||
|
|
{
|
|||
|
|
"type":"EM340",
|
|||
|
|
"cmd":[
|
|||
|
|
{
|
|||
|
|
"name": "Voltage L1",
|
|||
|
|
"tb_name": "a",
|
|||
|
|
"register": 0,
|
|||
|
|
"size": 2,
|
|||
|
|
"multiplier": 0.1
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Voltage L2",
|
|||
|
|
"tb_name": "b",
|
|||
|
|
"register": 2,
|
|||
|
|
"size": 2,
|
|||
|
|
"multiplier": 0.1
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Voltage L3",
|
|||
|
|
"tb_name": "c",
|
|||
|
|
"register": 4,
|
|||
|
|
"size": 2,
|
|||
|
|
"multiplier": 0.1
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Current L1",
|
|||
|
|
"tb_name": "d",
|
|||
|
|
"register": 12,
|
|||
|
|
"size": 2,
|
|||
|
|
"multiplier": 0.001
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Current L2",
|
|||
|
|
"tb_name": "e",
|
|||
|
|
"register": 14,
|
|||
|
|
"size": 2,
|
|||
|
|
"multiplier": 0.001
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Current L3",
|
|||
|
|
"tb_name": "f",
|
|||
|
|
"register": 16,
|
|||
|
|
"size": 2,
|
|||
|
|
"multiplier": 0.001
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// {
|
|||
|
|
// "name": "Power factor",
|
|||
|
|
// "tb_name": "power_factor",
|
|||
|
|
// "register": 14,
|
|||
|
|
// "size": 1,
|
|||
|
|
// "multiplier": 0.001
|
|||
|
|
// },
|
|||
|
|
// {
|
|||
|
|
// "name": "Frequency",
|
|||
|
|
// "tb_name": "frequency",
|
|||
|
|
// "register": 15,
|
|||
|
|
// "size": 1,
|
|||
|
|
// "multiplier": 0.1
|
|||
|
|
// },
|
|||
|
|
// {
|
|||
|
|
// "name": "Energy",
|
|||
|
|
// "tb_name": "consumption",
|
|||
|
|
// "register": 16,
|
|||
|
|
// "size": 2,
|
|||
|
|
// "multiplier": 0.1
|
|||
|
|
// }
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let ERRWEIGHT = {
|
|||
|
|
EMERGENCY: "emergency", // System unusable
|
|||
|
|
ALERT: "alert", // Action must be taken immidiately
|
|||
|
|
CRITICAL: "critical", // Component unable to function
|
|||
|
|
ERROR: "error", // Error, but component able to recover from it
|
|||
|
|
WARNING: "warning", // Possibility of error, system running futher
|
|||
|
|
NOTICE: "notice", // Significant message but not an error, things user might want to know about
|
|||
|
|
INFO: "informational", // Info
|
|||
|
|
DEBUG: "debug" // Debug - only if CONFIG.debug is enabled
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
instance.currentData = function(){
|
|||
|
|
let resp = [];
|
|||
|
|
for (let f = 0; f < PRIVATEVARS.devices.length; f++){
|
|||
|
|
let dev = PRIVATEVARS.devices[f];
|
|||
|
|
for (let e = 0; e < dev.data.length; e++){
|
|||
|
|
let d = dev.data[e];
|
|||
|
|
resp.push({
|
|||
|
|
"name": dev.name+" - "+d.name,
|
|||
|
|
"value": d.value
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return resp;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
instance.configList = function(){
|
|||
|
|
let resp = [];
|
|||
|
|
/*let data = PRIVATEVARS.feeds;
|
|||
|
|
for (let a = 0; a < data.length; a++){
|
|||
|
|
for (let i = 0; i < instance.CONFIG.feeds.length; i++){
|
|||
|
|
let feed = instance.CONFIG.feeds[i];
|
|||
|
|
if (feed.name === data[a].id){
|
|||
|
|
for (let b = 0; b < data[a].streams.length; b++){
|
|||
|
|
for (let j = 0; j < feed.streams.length; j++){
|
|||
|
|
let stream = feed.streams[j];
|
|||
|
|
if (stream.name === data[a].streams[b].id){
|
|||
|
|
data[a].streams[b]["exists"] = true;
|
|||
|
|
data[a].streams[b]["currently"] = stream;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
resp.push({
|
|||
|
|
"name":"Device manager",
|
|||
|
|
"icon":"tasks",
|
|||
|
|
"_show":false,
|
|||
|
|
"js_func":"energoDevManager",
|
|||
|
|
"data": data
|
|||
|
|
});*/
|
|||
|
|
|
|||
|
|
return resp;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let timeoutInterval = null;
|
|||
|
|
let msgWaitInterval = null;
|
|||
|
|
let port = null;
|
|||
|
|
let myEdge = "undefined";
|
|||
|
|
let starter = null;
|
|||
|
|
instance.status("Loading...", "red");
|
|||
|
|
|
|||
|
|
|
|||
|
|
instance.availableCommands = [
|
|||
|
|
{
|
|||
|
|
"name": "Status",
|
|||
|
|
"cmd": "qStatus",
|
|||
|
|
"icon": "stream",
|
|||
|
|
"func": function(body){
|
|||
|
|
let a = true;
|
|||
|
|
if (timeoutInterval === null){
|
|||
|
|
a = false;
|
|||
|
|
}
|
|||
|
|
let b = true;
|
|||
|
|
if (msgWaitInterval === null){
|
|||
|
|
b = false;
|
|||
|
|
}
|
|||
|
|
let st = {
|
|||
|
|
"isRunning":instance.CONFIG.isRunning,
|
|||
|
|
"timeoutInterval":a,
|
|||
|
|
"msgWaitInterval":b,
|
|||
|
|
"CONFIG":instance.CONFIG
|
|||
|
|
};
|
|||
|
|
return {
|
|||
|
|
"type": "ok",
|
|||
|
|
"timestamp": humanReadableTimeAndDate(),
|
|||
|
|
"resp": st
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Start Reading",
|
|||
|
|
"cmd": "sStart",
|
|||
|
|
"icon": "play",
|
|||
|
|
"func": function(body){
|
|||
|
|
/*if (running === false){
|
|||
|
|
startCmdWaitInterval();
|
|||
|
|
running = true;
|
|||
|
|
return "Reading started !";
|
|||
|
|
} else {
|
|||
|
|
return "Reading already active !";
|
|||
|
|
}*/
|
|||
|
|
return {
|
|||
|
|
"type": "ok",
|
|||
|
|
"timestamp": humanReadableTimeAndDate(),
|
|||
|
|
"resp": "WIP"
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Stop Reading",
|
|||
|
|
"cmd": "sStop",
|
|||
|
|
"icon": "stop",
|
|||
|
|
"func": function(body){
|
|||
|
|
/*if (running === true){
|
|||
|
|
stopCmdWaitInterval();
|
|||
|
|
stopTimeoutInterval();
|
|||
|
|
running = false;
|
|||
|
|
return "Reading stopped !";
|
|||
|
|
} else {
|
|||
|
|
return "Reading already inactive !";
|
|||
|
|
}*/
|
|||
|
|
return {
|
|||
|
|
"type": "ok",
|
|||
|
|
"timestamp": humanReadableTimeAndDate(),
|
|||
|
|
"resp": "WIP"
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Read current data",
|
|||
|
|
"cmd": "qCurrentData",
|
|||
|
|
"icon": "chart-bar",
|
|||
|
|
"func": function(body){
|
|||
|
|
let resp = instance.currentData();
|
|||
|
|
return {
|
|||
|
|
"type": "ok",
|
|||
|
|
"timestamp": humanReadableTimeAndDate(),
|
|||
|
|
"resp": resp
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Save current config",
|
|||
|
|
"cmd": "saveConfig",
|
|||
|
|
"icon": "save",
|
|||
|
|
"func": function(body){
|
|||
|
|
|
|||
|
|
instance.set("config", JSON.stringify(instance.CONFIG));
|
|||
|
|
instance.set("private", JSON.stringify(PRIVATEVARS));
|
|||
|
|
return {
|
|||
|
|
"type": "ok",
|
|||
|
|
"timestamp": humanReadableTimeAndDate(),
|
|||
|
|
"resp": "done"
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "Toggle debug",
|
|||
|
|
"cmd": "sDebug",
|
|||
|
|
"icon": "comment-dots",
|
|||
|
|
"func": function(body){
|
|||
|
|
|
|||
|
|
if (instance.CONFIG.debug){
|
|||
|
|
instance.CONFIG.debug = false;
|
|||
|
|
instance.set("config", JSON.stringify(instance.CONFIG));
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"type": "ok",
|
|||
|
|
"timestamp": humanReadableTimeAndDate(),
|
|||
|
|
"resp": "debug OFF"
|
|||
|
|
};
|
|||
|
|
} else {
|
|||
|
|
instance.CONFIG.debug = true;
|
|||
|
|
instance.set("config", JSON.stringify(instance.CONFIG));
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"type": "ok",
|
|||
|
|
"timestamp": humanReadableTimeAndDate(),
|
|||
|
|
"resp": "debug ON"
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
function saveData(){
|
|||
|
|
if (checkFile(filepath)){
|
|||
|
|
let content = undefined;
|
|||
|
|
try {
|
|||
|
|
content = fs.readFileSync(filepath);
|
|||
|
|
} catch (err){
|
|||
|
|
console.log("saveData", myEdge, ERRWEIGHT.ERROR, "Unable to read original configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message});
|
|||
|
|
|
|||
|
|
//sendError("saveData", myEdge, ERRWEIGHT.ERROR, "Unable to read original configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (content !== undefined){
|
|||
|
|
try {
|
|||
|
|
fs.writeFileSync(backup_filepath, content, "utf8");
|
|||
|
|
} catch (err) {
|
|||
|
|
//sendError("saveData", myEdge, ERRWEIGHT.ERROR, "Unable to save backup of configuration !", {"name":instance.name, "id":instance.id, "file":backup_filepath, "err":err.message});
|
|||
|
|
console.log("saveData", myEdge, ERRWEIGHT.ERROR, "Unable to save backup of configuration !", {"name":instance.name, "id":instance.id, "file":backup_filepath, "err":err.message});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let a = {
|
|||
|
|
"config":instance.CONFIG,
|
|||
|
|
"private":PRIVATEVARS
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
fs.writeFileSync(filepath, JSON.stringify(a), "utf8");
|
|||
|
|
} catch (err) {
|
|||
|
|
//sendError("saveData", myEdge, ERRWEIGHT.CRITICAL, "Unable to save configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message});
|
|||
|
|
console.log("saveData", myEdge, ERRWEIGHT.CRITICAL, "Unable to save configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function loadData(){
|
|||
|
|
let content = undefined;
|
|||
|
|
//console.log(filepath);
|
|||
|
|
if (checkFile(filepath)){
|
|||
|
|
try {
|
|||
|
|
content = fs.readFileSync(filepath);
|
|||
|
|
} catch (err){
|
|||
|
|
//sendError("loadData", myEdge, ERRWEIGHT.ERROR, "Unable to read original configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message});
|
|||
|
|
console.log("loadData", myEdge, ERRWEIGHT.ERROR, "Unable to read original configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message});
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
if (checkFile(backup_filepath)){
|
|||
|
|
try {
|
|||
|
|
content = fs.readFileSync(backup_filepath);
|
|||
|
|
} catch (err){
|
|||
|
|
//sendError("loadData", myEdge, ERRWEIGHT.CRITICAL, "Unable to read backup configuration !", {"name":instance.name, "id":instance.id, "file":backup_filepath, "err":err.message});
|
|||
|
|
console.log("loadData", myEdge, ERRWEIGHT.CRITICAL, "Unable to read backup configuration !", {"name":instance.name, "id":instance.id, "file":backup_filepath, "err":err.message});
|
|||
|
|
}
|
|||
|
|
if (content !== undefined){
|
|||
|
|
//sendError("loadData", myEdge, ERRWEIGHT.WARNING, "No configuration, loading from backup !", {"name":instance.name, "id":instance.id});
|
|||
|
|
console.log("loadData", myEdge, ERRWEIGHT.WARNING, "No configuration, loading from backup !", {"name":instance.name, "id":instance.id});
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
//sendError("loadData", myEdge, ERRWEIGHT.CRITICAL, "No configuration, not even backup !", {"name":instance.name, "id":instance.id});
|
|||
|
|
console.log("loadData", myEdge, ERRWEIGHT.CRITICAL, "No configuration, not even backup !", {"name":instance.name, "id":instance.id, "filepath": filepath});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (content !== undefined){
|
|||
|
|
let a = JSON.parse(content);
|
|||
|
|
instance.send(instanceSendTo.debug, a);
|
|||
|
|
let c = a.config;
|
|||
|
|
let p = a.private;
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (c === undefined){
|
|||
|
|
//sendError("loadData", myEdge, ERRWEIGHT.CRITICAL, "Configuration not found !", {"name":instance.name, "id":instance.id});
|
|||
|
|
console.log("loadData", myEdge, ERRWEIGHT.CRITICAL, "Configuration not found !", {"name":instance.name, "id":instance.id});
|
|||
|
|
instance.status("Error - no config", "red");
|
|||
|
|
} else if (p === undefined){
|
|||
|
|
//sendError("loadData", myEdge, ERRWEIGHT.CRITICAL, "Privatevars not found !", {"name":instance.name, "id":instance.id});
|
|||
|
|
console.log("loadData", myEdge, ERRWEIGHT.CRITICAL, "Privatevars not found !", {"name":instance.name, "id":instance.id});
|
|||
|
|
instance.status("Error - no private vars", "red");
|
|||
|
|
} else {
|
|||
|
|
instance.CONFIG = c;
|
|||
|
|
PRIVATEVARS = p;
|
|||
|
|
|
|||
|
|
// Daj kazdemu device jeho tabulku prikazu
|
|||
|
|
for (let i = 0; i < PRIVATEVARS.devices.length; i++){
|
|||
|
|
let device = PRIVATEVARS.devices[i];
|
|||
|
|
for (let j = 0; j < PRIVATEVARS.cmd_tables.length; j++){
|
|||
|
|
let table = PRIVATEVARS.cmd_tables[j];
|
|||
|
|
|
|||
|
|
if (device.type === table.type){
|
|||
|
|
PRIVATEVARS.devices[i].cmd = table.cmd;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (myEdge === "undefined"){
|
|||
|
|
instance.status("Unconfigured", "red");
|
|||
|
|
} else {
|
|||
|
|
instance.status("Running", "green");
|
|||
|
|
startCmdWaitInterval();
|
|||
|
|
|
|||
|
|
instance.CONFIG.isRunning = true;
|
|||
|
|
console.log("modbus loaded: ", PRIVATEVARS.devices);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function checkFile(name){
|
|||
|
|
try {
|
|||
|
|
fs.accessSync(name, fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK);
|
|||
|
|
return true;
|
|||
|
|
} catch (err) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//Zapina slucku vycitavania dat
|
|||
|
|
function readDeviceData(){
|
|||
|
|
stopCmdWaitInterval();
|
|||
|
|
|
|||
|
|
// let tbname = FLOW.OMS_edgeName;
|
|||
|
|
|
|||
|
|
// Check port existance
|
|||
|
|
if (port === null)
|
|||
|
|
{
|
|||
|
|
port = new SerialPort(instance.CONFIG.port);
|
|||
|
|
|
|||
|
|
port.on('error', function(err) {
|
|||
|
|
//logger.debug("rsPort opened error - failed", err.message);
|
|||
|
|
//instance.send(instanceSendTo.debug, err.message);
|
|||
|
|
|
|||
|
|
errorHandler.sendMessageToService( exports.title + " MODBUS RS485 open - failed: " + err.message);
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
port.on('open', function() {
|
|||
|
|
|
|||
|
|
console.log("--->MODBUS RS485 READY - port opened");
|
|||
|
|
|
|||
|
|
exec("sudo halfduplex /dev/ttymxc1", (error, stdout, stderr) => {
|
|||
|
|
instance.send(instanceSendTo.debug, {"err": error});
|
|||
|
|
|
|||
|
|
if (error) {
|
|||
|
|
console.log("--->MODBUS RS485", error, stderr);
|
|||
|
|
errorHandler.sendMessageToService( exports.title + " sudo halfduplex /dev/ttymxc1 - failed: " + error);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
exec(instance.CONFIG.port_options, (error, stdout, stderr) => {
|
|||
|
|
instance.send(instanceSendTo.debug, {"stdout":stdout,"stderr":stderr,"err":error});
|
|||
|
|
|
|||
|
|
if (error) {
|
|||
|
|
console.log("--->MODBUS RS485", error, stderr);
|
|||
|
|
errorHandler.sendMessageToService( exports.title + " " + instance.CONFIG.port_options + " - failed: " + error);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
port.on('data', receivedData);
|
|||
|
|
|
|||
|
|
//sendError("readDeviceData", myEdge, ERRWEIGHT.DEBUG, "Serial port open!", {});
|
|||
|
|
//console.log("-->MODBUS readDeviceData", myEdge, ERRWEIGHT.DEBUG, "Serial port open!", {});
|
|||
|
|
|
|||
|
|
startCmdWaitInterval();
|
|||
|
|
return; // Cakame na port aby sa spravne otvoril a rozbehol
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Skontroluj existenciu device listu
|
|||
|
|
if (PRIVATEVARS.devices.length > 0){
|
|||
|
|
// Ponastavuj indexy
|
|||
|
|
PRIVATEVARS.cmd_index++;
|
|||
|
|
if (PRIVATEVARS.cmd_index >= PRIVATEVARS.devices[PRIVATEVARS.device_index].cmd.length){
|
|||
|
|
// Kedže všetky príkazy pre daný device sú vybavené, je treba odoslat vyčítané data do TB
|
|||
|
|
updateDataInTB();
|
|||
|
|
|
|||
|
|
PRIVATEVARS.cmd_index = 0;
|
|||
|
|
PRIVATEVARS.device_index++;
|
|||
|
|
|
|||
|
|
if (PRIVATEVARS.device_index >= PRIVATEVARS.devices.length){
|
|||
|
|
PRIVATEVARS.device_index = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let device = PRIVATEVARS.devices[PRIVATEVARS.device_index];
|
|||
|
|
|
|||
|
|
// Skontroluj existenciu príkazú pre daný device type
|
|||
|
|
if (device.cmd.length < 1){
|
|||
|
|
//sendError("readDeviceData", tbname, ERRWEIGHT.ERROR, "No commands for this device type !", {"type": device.type});
|
|||
|
|
console.log("readDeviceData", tbname, ERRWEIGHT.ERROR, "No commands for this device type !", {"type": device.type});
|
|||
|
|
startCmdWaitInterval();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Odešli nasledujúci príkaz
|
|||
|
|
sendCommand();
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
instance.CONFIG.isRunning = false;
|
|||
|
|
//sendError("readDeviceData", myEdge, ERRWEIGHT.CRITICAL, "Modbus has no devices registered!", {});
|
|||
|
|
console.log("modbus_citys: readDeviceData", myEdge, ERRWEIGHT.CRITICAL, "Modbus has no devices registered!", {});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function readingTimeouted(){
|
|||
|
|
stopCmdWaitInterval();
|
|||
|
|
stopTimeoutInterval();
|
|||
|
|
|
|||
|
|
// let tbname = FLOW.OMS_edgeName;
|
|||
|
|
|
|||
|
|
let device = PRIVATEVARS.devices[PRIVATEVARS.device_index];
|
|||
|
|
let com = device.cmd[PRIVATEVARS.cmd_index];
|
|||
|
|
//sendError("readingTimeouted", tbame, ERRWEIGHT.WARNING, "Reading timeouted !", {"device": device.address, "cmd": com.register});
|
|||
|
|
console.log("modbus_citys: readingTimeouted", tbname, ERRWEIGHT.WARNING, "Reading timeouted !", {"device": device.address, "cmd": com.register});
|
|||
|
|
|
|||
|
|
device.timeoutcount++;
|
|||
|
|
//console.log("device.timeoutcount", device.timeoutcount);
|
|||
|
|
if (device.timeoutcount === 16)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
//sendError("modbus_citys: readingTimeouted", tbname, ERRWEIGHT.CRITICAL, "Electrometer is not responding - reading timeouted", "");
|
|||
|
|
sendNotification("modbus_citys: readingTimeouted", tbname, "electrometer_is_not_responding", {}, "", instanceSendTo.tb, instance );
|
|||
|
|
|
|||
|
|
if (device.status === "OK"){
|
|||
|
|
device.status === "NOK";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
startCmdWaitInterval();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function receivedData(data){
|
|||
|
|
|
|||
|
|
//let array = [...data];
|
|||
|
|
//console.log("received data", array);
|
|||
|
|
|
|||
|
|
// let tbname = FLOW.OMS_edgeName;
|
|||
|
|
|
|||
|
|
//!if received data are less than 9 bytes, we store it in array variable and return. than we concatenate second incoming
|
|||
|
|
// data and then length of array is 9
|
|||
|
|
receivedDataArray = [...receivedDataArray, ...data];
|
|||
|
|
//if (array.length < 9) return;
|
|||
|
|
let l = receivedDataArray.length;
|
|||
|
|
//console.log("received",receivedDataArray, l)
|
|||
|
|
|
|||
|
|
if ( l < 7 || l > 9 || l == 8 ) return;
|
|||
|
|
|
|||
|
|
let device = PRIVATEVARS.devices[PRIVATEVARS.device_index];
|
|||
|
|
let com = device.cmd[PRIVATEVARS.cmd_index];
|
|||
|
|
|
|||
|
|
if (device.timeoutcount > 16) {
|
|||
|
|
//sendError("Modbus_citysys: receivedData", tbname, ERRWEIGHT.NOTICE, "Electrometer is responding again", "");
|
|||
|
|
sendNotification("modbus_citys: receivedData", tbname, "electrometer_is_responding_again", {}, "", instanceSendTo.tb, instance );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
device.timeoutcount = 0;
|
|||
|
|
|
|||
|
|
if ((l == 7 && com.size != 1) || ( l == 9 && com.size != 2)) return;
|
|||
|
|
|
|||
|
|
stopTimeoutInterval();
|
|||
|
|
|
|||
|
|
//sendError("receivedData", tbname, ERRWEIGHT.DEBUG, "Received data !", {"cmd": receivedDataArray});
|
|||
|
|
//console.log("receivedData", tbname, ERRWEIGHT.DEBUG, "Received data !", {"cmd": receivedDataArray});
|
|||
|
|
|
|||
|
|
// Skontroluj či sedí počet bytú v správe
|
|||
|
|
//console.log("com size", com.size*2, "array2", receivedDataArray[2]);
|
|||
|
|
if (receivedDataArray[2] !== (com.size*2)){
|
|||
|
|
//sendError("receivedData", tbname, ERRWEIGHT.ERROR, "Received data of incorrect size !", {"expected": (com.size*2), "received": receivedDataArray[2], "cmd": com.register, "whole_msg": receivedDataArray});
|
|||
|
|
console.log("modbus_citys: receivedData", tbname, ERRWEIGHT.ERROR, "Received data of incorrect size !", {"expected": (com.size*2), "received": receivedDataArray[2], "cmd": com.register, "whole_msg": receivedDataArray});
|
|||
|
|
startTimeoutInterval();
|
|||
|
|
} else {
|
|||
|
|
// Konvertuj raw data na human readable
|
|||
|
|
|
|||
|
|
let v = (receivedDataArray[3] << 8) | receivedDataArray[4];
|
|||
|
|
if (com.size == 2){
|
|||
|
|
v = v | (receivedDataArray[5] << 24) | (receivedDataArray[6] << 16);
|
|||
|
|
}
|
|||
|
|
v = Math.round((v * com.multiplier) * 100) / 100;
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Pokad device nemá ešte žádné hodnoty vyčítané, pushni túto hodnotu do pola
|
|||
|
|
if (device.data.length < 1){
|
|||
|
|
device.data.push({ // Vždy ked správne zakomunikuje obnov status na OK
|
|||
|
|
"changed": true,
|
|||
|
|
"name": "status",
|
|||
|
|
"value": "OK"
|
|||
|
|
});
|
|||
|
|
device.data.push({
|
|||
|
|
"changed": true,
|
|||
|
|
"name": com.tb_name,
|
|||
|
|
"value": v
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
// Kedže už neco v poli má, kukni sa či je tam aj táto hodnota
|
|||
|
|
let found = false;
|
|||
|
|
for (let i = 0; i < device.data.length; i++){
|
|||
|
|
let d = device.data[i];
|
|||
|
|
if (d.name == "status"){ // Ked natrefíš na status (vždy tam musí byt) prepíš ho na OK lebo zakomunikoval správne
|
|||
|
|
device.data[i].changed = true;
|
|||
|
|
device.data[i].value = "OK";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (d.name == com.tb_name){
|
|||
|
|
found = true;
|
|||
|
|
device.data[i].changed = true;
|
|||
|
|
device.data[i].value = v;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Pole existuje, ale táto hodnota tam neni, pridaj ju
|
|||
|
|
if (found === false){
|
|||
|
|
device.data.push({
|
|||
|
|
"changed": true,
|
|||
|
|
"name": com.tb_name,
|
|||
|
|
"value": v
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//Správne sme prijali odpoveď, je čas na další msg
|
|||
|
|
startCmdWaitInterval();
|
|||
|
|
}
|
|||
|
|
//console.log('received data array', receivedDataArray);
|
|||
|
|
receivedDataArray = [];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function updateDataInTB(){
|
|||
|
|
let device = PRIVATEVARS.devices[PRIVATEVARS.device_index];
|
|||
|
|
|
|||
|
|
// console.log("---- MB device", device);
|
|||
|
|
// console.log("---MB device data", device.data);
|
|||
|
|
|
|||
|
|
let values = "";
|
|||
|
|
for (let i = 0; i < device.data.length; i++){
|
|||
|
|
let data = device.data[i];
|
|||
|
|
if (data.changed){
|
|||
|
|
if (values !== ""){
|
|||
|
|
values += ", ";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (data.name === "status"){
|
|||
|
|
values += "\""+data.name+"\":\""+data.value+"\"";
|
|||
|
|
// This makes sure, that if this device doesn’t respond even once in next reading cycle, it will be marked as NOK
|
|||
|
|
device.data[i].changed = true;
|
|||
|
|
device.data[i].value = "NOK";
|
|||
|
|
} else {
|
|||
|
|
values += "\""+data.name+"\":"+data.value;
|
|||
|
|
device.data[i].changed = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//console.log("values modbus", values);
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (values !== ""){
|
|||
|
|
|
|||
|
|
// let tbname = FLOW.OMS_edgeName;
|
|||
|
|
// if(tbname == "" || tbname === undefined )
|
|||
|
|
// {
|
|||
|
|
// console.log("!!!!!!FLOW.OMS_edgeName is empty - 1");
|
|||
|
|
// return;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
let tbmsg = "{\"" + tbname + "\":[{\"ts\":"+Date.now()+", \"values\":{"+values+"}}] }";
|
|||
|
|
tbmsg = JSON.parse(tbmsg);
|
|||
|
|
|
|||
|
|
values = tbmsg[tbname][0]["values"];
|
|||
|
|
|
|||
|
|
//console.log("modbus", Object.keys(values));
|
|||
|
|
|
|||
|
|
//sum Phase_1_power, Phase_2_power, Phase_3_power (if one of them is undefined, we handle it)
|
|||
|
|
const numOr0 = n => isNaN(n) ? 0 : n;
|
|||
|
|
let calculated_total_power = [values["Phase_1_power"], values["Phase_2_power"], values["Phase_3_power"]].reduce((a, b) => numOr0(a) + numOr0(b));
|
|||
|
|
values["total_power"] = parseFloat(calculated_total_power.toFixed(2));
|
|||
|
|
tbmsg[tbname][0]["values"] = values;
|
|||
|
|
|
|||
|
|
Object.keys(values).map(singleValue => {
|
|||
|
|
if (["Phase_1_voltage", "Phase_2_voltage", "Phase_3_voltage"].includes(singleValue))
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
let l = singleValue.split("_");
|
|||
|
|
let phase = parseInt(l[1]);
|
|||
|
|
|
|||
|
|
if(FLOW.OMS_no_voltage == undefined) FLOW.OMS_no_voltage = new Set();
|
|||
|
|
|
|||
|
|
if(values[singleValue] == 0)
|
|||
|
|
{
|
|||
|
|
sendNotification("modbus_citys: updateDataInTB", tbname, "no_voltage_detected_on_phase", {phase: phase}, "", instanceSendTo.tb, instance, "voltage" + phase );
|
|||
|
|
|
|||
|
|
FLOW.OMS_no_voltage.add(phase);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
FLOW.OMS_no_voltage.delete(phase);
|
|||
|
|
sendNotification("modbus_citys: updateDataInTB", tbname, "voltage_on_phase_has_been_restored", {phase: phase}, "", instanceSendTo.tb, instance, "voltage" + phase);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
sendThingsBoard(tbmsg);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
let electrometerNotResponding = 0;
|
|||
|
|
function sendCommand(){
|
|||
|
|
let device = PRIVATEVARS.devices[PRIVATEVARS.device_index];
|
|||
|
|
let com = device.cmd[PRIVATEVARS.cmd_index];
|
|||
|
|
let array = [device.address, 3, ((com.register >> 8) & 0xFF), (com.register & 0xFF), ((com.size >> 8) & 0xFF), (com.size & 0xFF)];
|
|||
|
|
array = modbusCRC(array);
|
|||
|
|
|
|||
|
|
//console.log('---device--', device);
|
|||
|
|
//console.log('---device type--', device.type);
|
|||
|
|
|
|||
|
|
//sendError("sendCommand", device.tb_name, ERRWEIGHT.DEBUG, "Sending command !", {"cmd": array});
|
|||
|
|
//console.log("sendCommand", device.tb_name, ERRWEIGHT.DEBUG, "Sending command !", {"cmd": array});
|
|||
|
|
|
|||
|
|
// let tbname = FLOW.OMS_edgeName;
|
|||
|
|
// if(tbname == "" || tbname === undefined )
|
|||
|
|
// {
|
|||
|
|
// console.log("!!!!!!FLOW.OMS_edgeName is empty - 2");
|
|||
|
|
// return;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
startTimeoutInterval();
|
|||
|
|
port.write(Buffer.from(array), function(err) {
|
|||
|
|
|
|||
|
|
//! poslany command
|
|||
|
|
//console.log("poslany tento commant", array, err, device.type);
|
|||
|
|
|
|||
|
|
if (err) {
|
|||
|
|
stopTimeoutInterval();
|
|||
|
|
stopCmdWaitInterval();
|
|||
|
|
|
|||
|
|
|
|||
|
|
// elektromer neodpoveda viac ako 5 minut (15 commands za minutu sa posiela)
|
|||
|
|
if (device.type === "EM111" || device.type === "EM340")
|
|||
|
|
{
|
|||
|
|
electrometerNotResponding++;
|
|||
|
|
|
|||
|
|
if (electrometerNotResponding > 15 && electrometerNotResponding < 17)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
//sendError("Modbus_citys: sendCommand", tbname, ERRWEIGHT.CRITICAL, "Electrometer is not responding", {"err": err.message, "info": "No response more than 5 minutes"});
|
|||
|
|
sendNotification("modbus_citys: sendCommand", tbname, "electrometer_is_not_responding", {}, {"err": err.message, "info": "No response more than 5 minutes"}, instanceSendTo.tb, instance );
|
|||
|
|
|
|||
|
|
let tbmsg = {
|
|||
|
|
[tbname]: [
|
|||
|
|
{
|
|||
|
|
"ts": Date.now(),
|
|||
|
|
"values": {
|
|||
|
|
"status": "NOK"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sendThingsBoard(tbmsg)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (device.type === "EM111")
|
|||
|
|
{
|
|||
|
|
if (electrometerNotResponding > 15)
|
|||
|
|
{
|
|||
|
|
//sendError("Modbus_citys: sendCommand", tbname, ERRWEIGHT.NOTICE, "Electrometer is responding again", "");
|
|||
|
|
sendNotification("modbus_citys: sendCommand", tbname, "electrometer_is_responding_again", {}, "", instanceSendTo.tb, instance );
|
|||
|
|
}
|
|||
|
|
electrometerNotResponding = 0;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function modbusCRC(array){
|
|||
|
|
let crc = 0xFFFF;
|
|||
|
|
for (let i = 0; i < array.length; i++){
|
|||
|
|
let b = array[i];
|
|||
|
|
crc = crc ^ b;
|
|||
|
|
|
|||
|
|
for (let j = 8; j>0; j--){
|
|||
|
|
if ((crc & 0x0001) != 0){
|
|||
|
|
crc = crc >> 1;
|
|||
|
|
crc = crc ^ 0xA001;
|
|||
|
|
} else {
|
|||
|
|
crc = crc >> 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
array.push(crc & 0xFF);
|
|||
|
|
array.push((crc >> 8) & 0xFF);
|
|||
|
|
|
|||
|
|
return array;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
instance.on('data', function(flowdata) {
|
|||
|
|
|
|||
|
|
console.log("flowdata on data", flowdata);
|
|||
|
|
sendStatus({"CONFIG": instance.CONFIG, "PRIVATEVARS":PRIVATEVARS})
|
|||
|
|
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
instance.reconfigure = function() {
|
|||
|
|
|
|||
|
|
//TODO remove ftom options
|
|||
|
|
myEdge = instance.options.edge;
|
|||
|
|
if (starter === null){
|
|||
|
|
starter = setInterval(function(){
|
|||
|
|
loadData();
|
|||
|
|
clearInterval(starter);
|
|||
|
|
starter = null;
|
|||
|
|
}, 5000);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
instance.close = function() {
|
|||
|
|
// close sockets and such
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
function sendError(func, device, weight, str, extra){
|
|||
|
|
if ((weight === ERRWEIGHT.DEBUG) && (instance.CONFIG.debug === false)){
|
|||
|
|
return; // Allow debug messages only if CONFIG.debug is active
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let content = {
|
|||
|
|
"type": weight,
|
|||
|
|
"status": "new",
|
|||
|
|
"source": {
|
|||
|
|
"func":func,
|
|||
|
|
"component":instance.id,
|
|||
|
|
"component_name":instance.name,
|
|||
|
|
"edge":myEdge
|
|||
|
|
},
|
|||
|
|
"message":str,
|
|||
|
|
"message_data": extra
|
|||
|
|
};
|
|||
|
|
let msg = {};
|
|||
|
|
msg[device] = [
|
|||
|
|
{
|
|||
|
|
"ts": Date.now(),
|
|||
|
|
"values": {
|
|||
|
|
"_event":content
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
// Msg can be outputted from components only after configuration
|
|||
|
|
/*if (canSendErrData()){
|
|||
|
|
sendBufferedErrors();
|
|||
|
|
} else {
|
|||
|
|
bufferError(msg);
|
|||
|
|
}*/
|
|||
|
|
instance.send(instanceSendTo.tb, msg); // Even if error server is unavailable, send this message to output, for other possible component connections
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
function sendBufferedErrors(){
|
|||
|
|
if (PRIVATEVARS.errBuffer === undefined){
|
|||
|
|
console.log("errBuffer undefined");
|
|||
|
|
console.log("private: ", PRIVATEVARS);
|
|||
|
|
}
|
|||
|
|
console.log("errBuffer size: ", PRIVATEVARS.errBuffer.length);
|
|||
|
|
if (PRIVATEVARS.errBuffer.length > 0){
|
|||
|
|
for (let i = 0; i < PRIVATEVARS.errBuffer.length; i++){
|
|||
|
|
instance.send(instanceSendTo.error, PRIVATEVARS.errBuffer[i]);
|
|||
|
|
}
|
|||
|
|
PRIVATEVARS.errBuffer = []; //Clear the buffer
|
|||
|
|
saveData();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function bufferError(msg){
|
|||
|
|
PRIVATEVARS.errBuffer.push(msg);
|
|||
|
|
saveData();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function canSendErrData(){
|
|||
|
|
//if (FLOW.errServerAvailable)
|
|||
|
|
return true;
|
|||
|
|
//else
|
|||
|
|
// return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function sendStatus(str){
|
|||
|
|
instance.send(instanceSendTo.debug, str);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function sendThingsBoard(obj){
|
|||
|
|
// Msg can be outputted from components only after configuration
|
|||
|
|
/*if (canSendTbData()){
|
|||
|
|
sendBufferedTB();
|
|||
|
|
} else {
|
|||
|
|
console.log("cant send data");
|
|||
|
|
bufferTB(str);
|
|||
|
|
}*/
|
|||
|
|
//console.log("send thingsboard", str);
|
|||
|
|
|
|||
|
|
//console.log("FLOW.OMS_edgeName", FLOW.OMS_edgeName, obj);
|
|||
|
|
|
|||
|
|
if(obj.hasOwnProperty(FLOW.OMS_edgeName) && FLOW.OMS_edgeName != "")
|
|||
|
|
{
|
|||
|
|
//send it to di_do_controller
|
|||
|
|
instance.send(instanceSendTo.di_do_controller, {sender: "modbus_citysys", tbdata: obj});
|
|||
|
|
}
|
|||
|
|
// else
|
|||
|
|
{
|
|||
|
|
instance.send(instanceSendTo.tb, obj); // Even if TB server is unavailable, send this message to output, for other possible component connections
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//instance.send(2, str); // Even if TB server is unavailable, send this message to output, for other possible component connections
|
|||
|
|
|
|||
|
|
|
|||
|
|
function sendBufferedTB(){
|
|||
|
|
if (PRIVATEVARS.tbBuffer.length > 0){
|
|||
|
|
console.log("sending buffered: ", PRIVATEVARS.tbBuffer.length );
|
|||
|
|
for (let i = 0; i < PRIVATEVARS.tbBuffer.length; i++){
|
|||
|
|
instance.send(instanceSendTo.tb, PRIVATEVARS.tbBuffer[i]);
|
|||
|
|
}
|
|||
|
|
PRIVATEVARS.tbBuffer = []; //Clear the buffer
|
|||
|
|
saveData();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function bufferTB(str){
|
|||
|
|
PRIVATEVARS.tbBuffer.push(str);
|
|||
|
|
saveData();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function canSendTbData(){
|
|||
|
|
//if (FLOW.tbAvailable)
|
|||
|
|
return true;
|
|||
|
|
//else
|
|||
|
|
// return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function startTimeoutInterval(){
|
|||
|
|
if (!timeoutInterval){
|
|||
|
|
timeoutInterval = setInterval(readingTimeouted, instance.CONFIG.timeoutTime);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function stopTimeoutInterval(){
|
|||
|
|
if (timeoutInterval){
|
|||
|
|
clearInterval(timeoutInterval);
|
|||
|
|
timeoutInterval = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function startCmdWaitInterval(){
|
|||
|
|
if (!msgWaitInterval){
|
|||
|
|
msgWaitInterval = setInterval(readDeviceData, instance.CONFIG.msgWaitTime);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function stopCmdWaitInterval(){
|
|||
|
|
if (msgWaitInterval){
|
|||
|
|
clearInterval(msgWaitInterval);
|
|||
|
|
msgWaitInterval = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
instance.on('options', instance.reconfigure);
|
|||
|
|
instance.reconfigure();
|
|||
|
|
|
|||
|
|
// LAST SECTION FOR COMMON FUNCTIONS
|
|||
|
|
function humanReadableTimeAndDate(){
|
|||
|
|
let date_ob = new Date();
|
|||
|
|
|
|||
|
|
let date = ("0" + date_ob.getDate()).slice(-2);
|
|||
|
|
let month = ("0" + (date_ob.getMonth() + 1)).slice(-2);
|
|||
|
|
let year = date_ob.getFullYear();
|
|||
|
|
|
|||
|
|
let hours = ("0" + date_ob.getHours()).slice(-2);
|
|||
|
|
let minutes = ("0" + date_ob.getMinutes()).slice(-2);
|
|||
|
|
let seconds = ("0" + date_ob.getSeconds()).slice(-2);
|
|||
|
|
|
|||
|
|
return date+"."+month+"."+year+" "+hours+":"+minutes+":"+seconds;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (starter === null){
|
|||
|
|
starter = setInterval(function(){
|
|||
|
|
loadData();
|
|||
|
|
clearInterval(starter);
|
|||
|
|
starter = null;
|
|||
|
|
}, 5000);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//setTimeout(loadData, 5000);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|