Actual flowserver on Senica rvo
This commit is contained in:
parent
67c503d980
commit
86619fbcff
29 changed files with 5833 additions and 9853 deletions
3
config
3
config
|
|
@ -1,4 +1,5 @@
|
||||||
name : Total.js Flow
|
name : Total.js Flow
|
||||||
|
default_timezone : Europe/Bratislava
|
||||||
|
|
||||||
// Packages settings
|
// Packages settings
|
||||||
package#flow (Object) : { url: '/' }
|
package#flow (Object) : { url: '/' }
|
||||||
|
|
@ -7,5 +8,5 @@ package#flow (Object) : { url: '/' }
|
||||||
table.relays : line:number|tbname:string|contactor:number|profile:string
|
table.relays : line:number|tbname:string|contactor:number|profile:string
|
||||||
table.nodes : node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean
|
table.nodes : node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean
|
||||||
table.settings : rvo_name:string|lang:string|temperature_adress:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number
|
table.settings : rvo_name:string|lang:string|temperature_adress:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number
|
||||||
table.pins : pin:number|type:string|line:number
|
table.pins : pin:string|type:string|line:number
|
||||||
table.notifications : key:string|weight:string|sk:string|en:string
|
table.notifications : key:string|weight:string|sk:string|en:string
|
||||||
|
|
|
||||||
113
databases/modbus_config.js
Normal file
113
databases/modbus_config.js
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
const timeoutInterval = 300000;
|
||||||
|
const deviceConfig = [
|
||||||
|
{
|
||||||
|
device: "em340",
|
||||||
|
deviceAddress: 1,
|
||||||
|
stream: [
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_1_voltage",
|
||||||
|
"register": 0,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_2_voltage",
|
||||||
|
"register": 2,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_3_voltage",
|
||||||
|
"register": 4,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_1_current",
|
||||||
|
"register": 12,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_2_current",
|
||||||
|
"register": 14,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_3_current",
|
||||||
|
"register": 16,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_1_power",
|
||||||
|
"register": 18,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_2_power",
|
||||||
|
"register": 20,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_3_power",
|
||||||
|
"register": 22,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "total_power",
|
||||||
|
"register": 40,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "total_energy",
|
||||||
|
"register": 52,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_1_pow_factor",
|
||||||
|
"register": 46,
|
||||||
|
"size": 1,
|
||||||
|
"multiplier": 0.001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_2_pow_factor",
|
||||||
|
"register": 47,
|
||||||
|
"size": 1,
|
||||||
|
"multiplier": 0.001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "Phase_3_pow_factor",
|
||||||
|
"register": 48,
|
||||||
|
"size": 1,
|
||||||
|
"multiplier": 0.001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tbAttribute": "power_factor",
|
||||||
|
"register": 49,
|
||||||
|
"size": 1,
|
||||||
|
"multiplier": 0.001
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
device: "twilight_sensor",
|
||||||
|
deviceAddress: 2,
|
||||||
|
stream: [
|
||||||
|
{
|
||||||
|
"tbAttribute": "twilight_sensor",
|
||||||
|
"register": 60,
|
||||||
|
"size": 2,
|
||||||
|
"multiplier": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = { timeoutInterval, deviceConfig };
|
||||||
|
|
@ -1,48 +1,31 @@
|
||||||
node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean
|
node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean
|
||||||
+|697|joqRYBVL30k9eQWOlZ5qwpD2KJpNEmA6gPxXzwaM|3||1|1|...........
|
+|3522|RO8rjaBDy21qPQJzW7oD96ApK3xmNleVZg9Ed4Gw|1||1|1|...........
|
||||||
+|659|Ymn9oleRxJ0vw17WzAyGwdyEBk4ObdMXj2VgpNLG|3||1|1|...........
|
+|4018|3JjOWdylwgNLzxVab7NEznkZ2vG64rq8PEB5QmDo|1||1|1|...........
|
||||||
+|636|M6ogKQW09bOXewAYvZyvJqyJrV1aRnPGE37p42Nx|2||1|1|...........
|
+|4019|Z5KyJe9nEg1QNbWlX0wWRB0oDjBLdqzR83VGv624|1||1|1|...........
|
||||||
+|648|gaMGN4x1e9JlZz0QPRDd9Rym6dVr3OpvqKnoWBbk|2||1|1|...........
|
+|4154|1JMYvnx2RzKEo4aWQ7DmN5AL8yZV3m9NBePXbrdj|1||1|0|...........
|
||||||
+|664|oGVzxNWP9lrjaQ7vKODQ7g51gqp62YZREmdw3XBM|1||1|1|...........
|
+|3907|PjLblDgRBO6WQqnxmkJ59r0Jv3ewZN4p5a89yKdY|1||1|1|...........
|
||||||
+|634|NGWamnYqlP1wbgrZQxDAWm5e2X7OVAK69koR04vL|2||1|1|...........
|
+|4148|dz4ojlpP85JMgDLZWkQOoGAaKYqQexEr62GXRV1y|1||1|1|...........
|
||||||
+|670|dlE1VQjYrNx9gZRmb38g1YyoLBO4qaAk2M6JPnG7|2||1|1|...........
|
+|4153|d5xjWYMwEJon6rLlK7yBYmAqgV4DaOeNB9ZX3Gzb|1||1|1|...........
|
||||||
+|641|vnmG4kJxaXWNBgMQq0D7Mz5e9oZzOAlr6LdR3w2V|2||1|1|...........
|
+|3938|gRoJEyXVx4qD9er287LP1v7wBzGldaPjLWQKm3Mv|1||1|1|...........
|
||||||
+|632|LpkVlmq4b3jMwJQxBZ8aM78rXAP6o97Ke0aOYEg2|2||1|1|...........
|
+|3802|K94XLav1glVRnyQ6r01BNzkme3YJwBxM5oOzdP2j|1||1|1|...........
|
||||||
+|667|MzXBoWbEZjO0lrpqnRyoJ4DkmVeaNAGdL9g4QKxP|1||1|1|...........
|
+|4015|d9x2V5LGYBzXp4mMRAOBDj7PloaqJwnQj6DgrNe3|1||1|0|...........
|
||||||
+|682|vnreBJ6PMqgz20pYEL82XQyG1jkWwdQxZVNAOlmK|1||1|1|...........
|
+|3929|B5EoxeMVp4zwr8nqW0GjDpARjvD1PNamOGbLg63Z|1||1|1|...........
|
||||||
+|643|oZmYXEbw9lVWRv1jLxDe9bDdgAMz4PKQnNJ6eB23|1||1|1|...........
|
+|3946|aw4eELG2DlPMdn1JW0B1DnAqQXOZRN3xB5yp8VKr|1||1|1|...........
|
||||||
+|642|pEonaKBOGbj9034MgJ8W3G8qXvxNWVkAPQz21R6L|1||1|1|...........
|
+|4014|ZmRwd93QL4gaezxEbAxW5971prn2XjlPvGyqJ6BO|1||1|1|...........
|
||||||
+|647|BLQal6Pn9oz1KmNgek5Yqd50vd2MAbqG3OV7Rp4j|1||1|1|...........
|
+|4155|eod9aRWLVl34Gx1Dn7VoaaA2rz6qjgmpEXwQJN5Z|1||1|1|...........
|
||||||
+|646|4agVJ9dPQkmp1R2X3EDJKxyrK6ZlNoM0n7qxBOev|1||1|1|...........
|
+|4149|3a5oqJN1bgnx4Ol9dk86NBAByE6jQ8mKDWMpGrLV|1||1|1|...........
|
||||||
+|666|9PpgLEnvk4WMV6RmOJybMGDaeAXzo2BQNG3K17Zw|1||1|1|...........
|
+|3642|EjgWGnXaLy9opPOz20n694086BlYM3w1deVQvbKr|1||1|1|...........
|
||||||
+|654|Mmp93b2nvd7OoqgBeEyEZq5kjlAV1Y4ZNXwW0zLG|1||1|1|...........
|
+|3636|wvKJdZML6mXP4DzWBAXWNW7jxNloa5g23Ve9Y1ry|1||1|1|...........
|
||||||
+|637|koW06PeGrLlBp2YJQE5Ogw5RmMaXKzj3wOAZg9n7|3||1|1|...........
|
+|3991|Nzp2OoJlqn6r1ZgvdA3GWdAabBwP5G4eE3RQmyxD|1||1|1|...........
|
||||||
+|680|KL2jNOVpdARa9XvoeJDPga8bkmPBxqn7Ww3gzGQ1|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:40","start_time":"13:00"},{"cct":3000,"value":-1,"end_time":"13:50","start_time":"13:40"},{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|0|...........
|
+|3994|PLBJzmK1r3Gynd6OW0gGdM0e5wV4vx9bDEqNgYR8|1||1|1|...........
|
||||||
+|645|jklN4JpQAx362o9XYZDN6wDgrWw1P7GEbdBM0vRV|1||1|1|...........
|
+|3990|52dD6ZlV1QaOpRBmbAqKZgkKnGzWMLj4eJq38Pgo|1||1|1|...........
|
||||||
+|660|gj7zbKV46oQ1p2e0AJ8XqZDG3YNWaRrlOEXvBxmM|3||1|1|...........
|
+|3967|rDbQ84xzwgdqEoPm3kbJw3k9anOZY1RXyBv2LVM6|1||1|1|...........
|
||||||
+|669|Y9aLW03wOZkABvKXbMyL0lyV1xdNj72r4egqGRzJ|3|{"intervals":[{"cct":3000,"value":0,"end_time":"13:40","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"07:20","start_time":"13:50"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"07:20"},{"cct":3000,"value":0,"end_time":"13:50","start_time":"13:40"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
+|3977|E6Kg9oDnLWyzPRMva7vrwa7Jxp4VG58qO2w1lZYe|1||1|1|...........
|
||||||
+|671|AvVdgzYJZaPx3oMqeED4Oj8NnmKkw716bRO90jLB|3||1|1|...........
|
+|3757|roKgWqY95V3mXMRzyAjm8D7bLjexpJPvaGDBw826|1||1|1|...........
|
||||||
+|638|9xgzG4Op1BrKZPmoQkDrmj8E73ndJNMjavAwX2Re|3||1|1|...........
|
+|3633|nJL5lPMwBx23YpqRe0rlKV7damXvWVbOrD4gNzy8|1||1|1|...........
|
||||||
+|639|BOjEzGRZ46bnp9wa2A8z76D0JkmW1QPNdrqevXVL|3||1|1|...........
|
+|3744|ZmRwd93QL4gaezxEbAxW5O71prn2XjlPvGyqJ6BO|1||1|1|...........
|
||||||
+|693|KjbN4q7JPZmexgdnz2yKdn5YAWwO0Q3BMX6ERLoV|2|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"22:10","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":30,"end_time":"02:40","start_time":"22:10"},{"cct":3000,"value":90,"end_time":"05:30","start_time":"02:40"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
+|4023|eod9aRWLVl34Gx1Dn7VoaMA2rz6qjgmpEXwQJN5Z|1||1|1|...........
|
||||||
+|649|0p2rwdP7aGoOQLJNgAynJNy6xWXbmMe3nvZqlzkV|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:40","start_time":"13:00"},{"cct":3000,"value":-1,"end_time":"13:50","start_time":"13:40"},{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
+|3720|3a5oqJN1bgnx4Ol9dk86NZAByE6jQ8mKDWMpGrLV|1||1|1|...........
|
||||||
+|698|mYnBzbeGaAL62jowRv59M35Xq9QpZ0K7O1dg4xVl|1||1|1|...........
|
+|3734|EjgWGnXaLy9opPOz20n69V086BlYM3w1deVQvbKr|1||1|1|...........
|
||||||
+|640|WjBL12pg63eX4N9P7zy0XYyEJKmlbkGwZMx0avQV|2||1|1|...........
|
+|3741|wvKJdZML6mXP4DzWBAXWN17jxNloa5g23Ve9Y1ry|1||1|1|...........
|
||||||
+|656|BrQx3NGKgVMRaXYAo9y1GE8ZzkWnj1le6bdOLE20|1|{"intervals":[{"cct":3000,"value":100,"end_time":"13:40","start_time":"13:00"},{"cct":3000,"value":-1,"end_time":"13:50","start_time":"13:40"},{"cct":3000,"value":100,"end_time":"13:00","start_time":"13:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
+|3721|Nzp2OoJlqn6r1ZgvdA3GWKAabBwP5G4eE3RQmyxD|1||0|0|...........
|
||||||
+|651|qaAOzENGrvpbe0VoK7D6Ld519PZmdg3nl24JLQMk|2||1|1|...........
|
|
||||||
+|691|lekrmdvO0BQG1ZW4AV8jzq8M39xnN2wEbRgPjXLp|1||1|1|...........
|
|
||||||
+|661|laYK7Pomn2bNZXEpedDxAqyOJkQ3WwV49gqxLrAR|3|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":60,"end_time":"05:30","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
|
||||||
+|665|gbv4nzqxW0XGAPKVNk8kr25ZQ2l3O6LRBprM97ew|3||1|1|...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
|
||||||
+|662|gbv4nzqxW0XGAPKVNk8kW48ZQ2l3O6LRBprM97ew|3|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"21:20","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":80,"end_time":"22:20","start_time":"21:50"},{"cct":3000,"value":70,"end_time":"22:50","start_time":"22:20"},{"cct":3000,"value":60,"end_time":"23:20","start_time":"22:50"},{"cct":3000,"value":50,"end_time":"23:50","start_time":"23:20"},{"cct":3000,"value":40,"end_time":"00:20","start_time":"23:50"},{"cct":3000,"value":100,"end_time":"05:30","start_time":"03:20"},{"cct":3000,"value":30,"end_time":"00:50","start_time":"00:20"},{"cct":3000,"value":20,"end_time":"01:20","start_time":"00:50"},{"cct":3000,"value":90,"end_time":"21:50","start_time":"21:20"},{"cct":3000,"value":30,"end_time":"01:50","start_time":"01:20"},{"cct":3000,"value":40,"end_time":"02:20","start_time":"01:50"},{"cct":3000,"value":50,"end_time":"02:50","start_time":"02:20"},{"cct":3000,"value":60,"end_time":"03:20","start_time":"02:50"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
|
||||||
+|668|lekrmdvO0BQG1ZW4AV8jeZ5M39xnN2wEbRgPjXLp|3|{"intervals":[{"cct":3000,"value":0,"end_time":"13:10","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"12:50","start_time":"13:10"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"12:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
|
||||||
+|689|q0rElBPdL6kxMAjnzVDRl95emNZY7oOv2wK9gb31|3|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"21:20","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":80,"end_time":"22:20","start_time":"21:50"},{"cct":3000,"value":70,"end_time":"22:50","start_time":"22:20"},{"cct":3000,"value":60,"end_time":"23:20","start_time":"22:50"},{"cct":3000,"value":50,"end_time":"23:50","start_time":"23:20"},{"cct":3000,"value":40,"end_time":"00:20","start_time":"23:50"},{"cct":3000,"value":100,"end_time":"05:30","start_time":"03:20"},{"cct":3000,"value":30,"end_time":"00:50","start_time":"00:20"},{"cct":3000,"value":20,"end_time":"01:20","start_time":"00:50"},{"cct":3000,"value":90,"end_time":"21:50","start_time":"21:20"},{"cct":3000,"value":30,"end_time":"01:50","start_time":"01:20"},{"cct":3000,"value":40,"end_time":"02:20","start_time":"01:50"},{"cct":3000,"value":50,"end_time":"02:50","start_time":"02:20"},{"cct":3000,"value":60,"end_time":"03:20","start_time":"02:50"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
|
||||||
+|683|XKQbz3WAwY21dGa0R453rWyJm9PZOjqlvpr6Nkeo|3|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"21:20","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":80,"end_time":"22:20","start_time":"21:50"},{"cct":3000,"value":70,"end_time":"22:50","start_time":"22:20"},{"cct":3000,"value":60,"end_time":"23:20","start_time":"22:50"},{"cct":3000,"value":50,"end_time":"23:50","start_time":"23:20"},{"cct":3000,"value":40,"end_time":"00:20","start_time":"23:50"},{"cct":3000,"value":100,"end_time":"05:30","start_time":"03:20"},{"cct":3000,"value":30,"end_time":"00:50","start_time":"00:20"},{"cct":3000,"value":20,"end_time":"01:20","start_time":"00:50"},{"cct":3000,"value":90,"end_time":"21:50","start_time":"21:20"},{"cct":3000,"value":30,"end_time":"01:50","start_time":"01:20"},{"cct":3000,"value":40,"end_time":"02:20","start_time":"01:50"},{"cct":3000,"value":50,"end_time":"02:50","start_time":"02:20"},{"cct":3000,"value":60,"end_time":"03:20","start_time":"02:50"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
|
||||||
+|688|PaGbQ3wBAZWOmRvK9VDpvz5endLJYopEqlkzNMxX|3|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"21:20","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":80,"end_time":"22:20","start_time":"21:50"},{"cct":3000,"value":70,"end_time":"22:50","start_time":"22:20"},{"cct":3000,"value":60,"end_time":"23:20","start_time":"22:50"},{"cct":3000,"value":50,"end_time":"23:50","start_time":"23:20"},{"cct":3000,"value":40,"end_time":"00:20","start_time":"23:50"},{"cct":3000,"value":100,"end_time":"05:30","start_time":"03:20"},{"cct":3000,"value":30,"end_time":"00:50","start_time":"00:20"},{"cct":3000,"value":20,"end_time":"01:20","start_time":"00:50"},{"cct":3000,"value":90,"end_time":"21:50","start_time":"21:20"},{"cct":3000,"value":30,"end_time":"01:50","start_time":"01:20"},{"cct":3000,"value":40,"end_time":"02:20","start_time":"01:50"},{"cct":3000,"value":50,"end_time":"02:50","start_time":"02:20"},{"cct":3000,"value":60,"end_time":"03:20","start_time":"02:50"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
|
||||||
+|672|0XYElWeKBNJn1gdoMG8lON5ALkPvj4V3xra2q6mO|2||1|1|.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
|
||||||
+|690|wGjQobgOK0n2YqBZmVDVR3DR9ep6EXA1ka3vzlP7|2||1|1|..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
|
||||||
+|692|l9YkRpoB2vVa0mKqEO8ZGGDjW43eXnJML6GxzbwQ|2|{"intervals":[{"cct":3000,"value":0,"end_time":"13:10","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"12:50","start_time":"13:10"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"12:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
|
||||||
+|655|RMgnK93rkoAazbqdQ4yBYpDZ1YXGx6pmwBeVEP2O|2||1|1|..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
|
||||||
+|694|Jm32GR1qpwQxlZza0N5mE15AP96YbOKLogrXVW4e|2|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"21:20","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":80,"end_time":"22:20","start_time":"21:50"},{"cct":3000,"value":70,"end_time":"22:50","start_time":"22:20"},{"cct":3000,"value":60,"end_time":"23:20","start_time":"22:50"},{"cct":3000,"value":50,"end_time":"23:50","start_time":"23:20"},{"cct":3000,"value":40,"end_time":"00:20","start_time":"23:50"},{"cct":3000,"value":100,"end_time":"05:30","start_time":"03:20"},{"cct":3000,"value":30,"end_time":"00:50","start_time":"00:20"},{"cct":3000,"value":20,"end_time":"01:20","start_time":"00:50"},{"cct":3000,"value":90,"end_time":"21:50","start_time":"21:20"},{"cct":3000,"value":30,"end_time":"01:50","start_time":"01:20"},{"cct":3000,"value":40,"end_time":"02:20","start_time":"01:50"},{"cct":3000,"value":50,"end_time":"02:50","start_time":"02:20"},{"cct":3000,"value":60,"end_time":"03:20","start_time":"02:50"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
|
||||||
+|635|Vq2JaWpw1OdBKmNeoj8w605XE40l3kgL76Azb9QP|2|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"21:20","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":80,"end_time":"22:20","start_time":"21:50"},{"cct":3000,"value":70,"end_time":"22:50","start_time":"22:20"},{"cct":3000,"value":60,"end_time":"23:20","start_time":"22:50"},{"cct":3000,"value":50,"end_time":"23:50","start_time":"23:20"},{"cct":3000,"value":40,"end_time":"00:20","start_time":"23:50"},{"cct":3000,"value":100,"end_time":"05:30","start_time":"03:20"},{"cct":3000,"value":30,"end_time":"00:50","start_time":"00:20"},{"cct":3000,"value":20,"end_time":"01:20","start_time":"00:50"},{"cct":3000,"value":90,"end_time":"21:50","start_time":"21:20"},{"cct":3000,"value":30,"end_time":"01:50","start_time":"01:20"},{"cct":3000,"value":40,"end_time":"02:20","start_time":"01:50"},{"cct":3000,"value":50,"end_time":"02:50","start_time":"02:20"},{"cct":3000,"value":60,"end_time":"03:20","start_time":"02:50"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
|
||||||
+|650|0XYElWeKBNJn1gdoMG8lYdDALkPvj4V3xra2q6mO|3|{"intervals":[{"cct":3000,"value":0,"end_time":"13:10","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"12:50","start_time":"13:10"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"12:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|...........
|
|
||||||
+|663|LpkVlmq4b3jMwJQxBZ8akayrXAP6o97Ke0aOYEg2|1|{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"21:20","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":80,"end_time":"22:20","start_time":"21:50"},{"cct":3000,"value":70,"end_time":"22:50","start_time":"22:20"},{"cct":3000,"value":60,"end_time":"23:20","start_time":"22:50"},{"cct":3000,"value":50,"end_time":"23:50","start_time":"23:20"},{"cct":3000,"value":40,"end_time":"00:20","start_time":"23:50"},{"cct":3000,"value":100,"end_time":"05:30","start_time":"03:20"},{"cct":3000,"value":30,"end_time":"00:50","start_time":"00:20"},{"cct":3000,"value":20,"end_time":"01:20","start_time":"00:50"},{"cct":3000,"value":90,"end_time":"21:50","start_time":"21:20"},{"cct":3000,"value":30,"end_time":"01:50","start_time":"01:20"},{"cct":3000,"value":40,"end_time":"02:20","start_time":"01:50"},{"cct":3000,"value":50,"end_time":"02:50","start_time":"02:20"},{"cct":3000,"value":60,"end_time":"03:20","start_time":"02:50"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|0|1|...........
|
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,10 @@ key:string|weight:string|sk:string|en:string
|
||||||
+|door_has_been_open_without_permision_alarm_is_on|WARNING|Dvere boli otvorené bez povolania - zapnutá siréna|Door has been open without permision - alarm is on|...............
|
+|door_has_been_open_without_permision_alarm_is_on|WARNING|Dvere boli otvorené bez povolania - zapnutá siréna|Door has been open without permision - alarm is on|...............
|
||||||
+|state_of_contactor_for_line|INFORMATIONAL|Stav stýkača pre líniu č. ${line} je ${value}|State of contactor for line no. ${line} is ${value}|...............
|
+|state_of_contactor_for_line|INFORMATIONAL|Stav stýkača pre líniu č. ${line} je ${value}|State of contactor for line no. ${line} is ${value}|...............
|
||||||
+|local_database_is_corrupted|CRITICAL|||...............
|
+|local_database_is_corrupted|CRITICAL|||...............
|
||||||
+|electrometer_is_not_responding|ERROR|Elektromer neodpovedá|Electrometer is not responding|...............
|
+|electrometer_nok|ERROR|Elektromer neodpovedá|Electrometer is not responding|...............
|
||||||
+|no_voltage_detected_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|...............
|
+|electrometer_ok|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|...............
|
||||||
+|electrometer_is_responding_again|NOTICE|Elektromer znovu odpovedá|Electrometer is responding again|...............
|
+|no_voltage_on_phase|CRITICAL|Na fáze č. ${phase} nie je napätie|No voltage detected on phase no. ${phase}|...............
|
||||||
+|voltage_on_phase_has_been_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|...............
|
+|voltage_on_phase_restored|NOTICE|Napätie na fáze č. ${phase} bolo obnovené|Voltage on phase no. ${phase} has been restored|...............
|
||||||
+|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |...............
|
+|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |...............
|
||||||
|
+|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|...............
|
||||||
|
+|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|...............
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
pin:number|type:string|line:number
|
pin:string|type:string|line:number
|
||||||
*|1|state_of_main_switch|0|...........
|
*|input1_01|door_condition|0|...........
|
||||||
*|2|rotary_switch_state|0|...........
|
*|input1_02|rotary_switch_state|0|...........
|
||||||
*|3|rotary_switch_state|0|...........
|
*|input1_03|rotary_switch_state|0|...........
|
||||||
*|4|power_supply|0|...........
|
*|intut1_04|power_supply|0|...........
|
||||||
*|5|battery|0|...........
|
*|input1_05|state_of_main_switch|0|...........
|
||||||
*|6|door_condition|0|...........
|
*|input1_06|state_of_breaker|1|...........
|
||||||
*|8|state_of_breaker|1|...........
|
*|input1_07|state_of_breaker|2|...........
|
||||||
*|9|state_of_breaker|2|...........
|
*|input1_08|state_of_breaker|3|...........
|
||||||
*|10|state_of_breaker|3|...........
|
*|relay1_02|state_of_contactor|1|...........
|
||||||
*|11|state_of_contactor|1|...........
|
*|relay1_03|state_of_contactor|2|...........
|
||||||
*|12|state_of_contactor|2|...........
|
*|relay1_04|state_of_contactor|3|...........
|
||||||
*|13|state_of_contactor|3|...........
|
*|28F46E9D0E00008B|temperature|0|...........
|
||||||
*|16|twilight_sensor|0|...........
|
*|twilight_sensor|twilight_sensor|0|...........
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
line:number|tbname:string|contactor:number|profile:string
|
line:number|tbname:string|contactor:number|profile:string
|
||||||
+|0|KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV|1||...........
|
+|0|6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq|1||...........
|
||||||
+|3|vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V|0||....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
+|1|JzwxZXOvDj1bVrN4nkWw9Qk8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........
|
||||||
+|1|RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O|0|{"intervals":[{"value":0,"end_time":"13:00","start_time":"13:00"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........................................................................................................................................................................................................................................................................................................................................................................................
|
+|2|g9OxBZ5KRwNznlY6pAp6mxkWXvjdEL4eGQobMDy2|1|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........
|
||||||
+|2|dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7|0||................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
+|3|OzNMgZ9n43qPbjXmy7zWMJA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
rvo_name:string|lang:string|temperature_adress:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number
|
rvo_name:string|lang:string|temperature_adress:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number
|
||||||
+|testpanel|en|28.427B45920702|48.70826502|17.28455203|192.168.252.4|showroom_test_panel_led|xmRd6RJxW53WZe4vMFLU|1883|0|1|lm|ttymxc4|1|20|5|...........................................
|
+|rvo_senica_39_10.0.0.132|en|28.427B45920702|48.70826502|17.28455203|192.168.252.1|rvo_senica_39_10.0.0.132|qzSNuCNrLP4OL1v47YEe|1883|0|68|unipi|ttyUSB0|1|20|5|...........................................
|
||||||
|
|
|
||||||
8152
flow/cmd_manager.js
8152
flow/cmd_manager.js
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,9 @@
|
||||||
exports.id = 'di_do_controller';
|
exports.id = 'dido_controller';
|
||||||
exports.title = 'DI_DO_Controller';
|
exports.title = 'DIDO_Controller';
|
||||||
exports.version = '1.0.0';
|
exports.version = '2.0.0';
|
||||||
exports.group = 'Worksys';
|
exports.group = 'Worksys';
|
||||||
exports.color = '#2134B0';
|
exports.color = '#2134B0';
|
||||||
exports.input = 1;
|
exports.input = 3;
|
||||||
exports.output = ["red", "white", "yellow"];
|
exports.output = ["red", "white", "yellow"];
|
||||||
exports.click = false;
|
exports.click = false;
|
||||||
exports.author = 'Daniel Segeš';
|
exports.author = 'Daniel Segeš';
|
||||||
|
|
@ -60,7 +60,7 @@ state_of_contactor - podľa indexu stykača sa reportuje jeho stav, teda
|
||||||
|
|
||||||
//globals
|
//globals
|
||||||
//FIRMWARE version
|
//FIRMWARE version
|
||||||
FLOW.OMS_edge_fw_version = "2022-05-12";//rok-mesiac-den
|
FLOW.OMS_edge_fw_version = "2023-10-18";//rok-mesiac-den
|
||||||
FLOW.OMS_edgeName = "";
|
FLOW.OMS_edgeName = "";
|
||||||
FLOW.OMS_maintenance_mode = false;
|
FLOW.OMS_maintenance_mode = false;
|
||||||
|
|
||||||
|
|
@ -142,7 +142,7 @@ exports.install = function(instance) {
|
||||||
let twilight_sensor_interval = 5;//minutes
|
let twilight_sensor_interval = 5;//minutes
|
||||||
let twilight_sensor = [];
|
let twilight_sensor = [];
|
||||||
const twilight_sensor_array = [];
|
const twilight_sensor_array = [];
|
||||||
let twighlightError = false;
|
let twilightError = false;
|
||||||
|
|
||||||
let edgeName = "";
|
let edgeName = "";
|
||||||
|
|
||||||
|
|
@ -178,7 +178,7 @@ exports.install = function(instance) {
|
||||||
deviceStatuses["state_of_main_switch"] = "Off";//Hlavný istič
|
deviceStatuses["state_of_main_switch"] = "Off";//Hlavný istič
|
||||||
deviceStatuses["rotary_switch_state"] = "Off";//Prevádzkový mód
|
deviceStatuses["rotary_switch_state"] = "Off";//Prevádzkový mód
|
||||||
deviceStatuses["door_condition"] = "closed";//Dverový kontakt
|
deviceStatuses["door_condition"] = "closed";//Dverový kontakt
|
||||||
deviceStatuses["rvo"] = {status: "OK"};//elektromer rvo
|
deviceStatuses["em"] = "OK";//elektromer rvo
|
||||||
deviceStatuses["temperature"] = "OK";//templomer
|
deviceStatuses["temperature"] = "OK";//templomer
|
||||||
deviceStatuses["battery"] = "OK";//Batéria
|
deviceStatuses["battery"] = "OK";//Batéria
|
||||||
deviceStatuses["power_supply"] = "OK";//Zdroj
|
deviceStatuses["power_supply"] = "OK";//Zdroj
|
||||||
|
|
@ -187,6 +187,7 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
deviceStatuses["state_of_breaker"] = {};//"Off";//Istič
|
deviceStatuses["state_of_breaker"] = {};//"Off";//Istič
|
||||||
deviceStatuses["state_of_contactor"] = {};//"Off";//Stykač
|
deviceStatuses["state_of_contactor"] = {};//"Off";//Stykač
|
||||||
|
deviceStatuses["twilight_sensor"] = "OK"; //lux sensor
|
||||||
|
|
||||||
/*
|
/*
|
||||||
dbRelays.on('change', function(doc, old) {
|
dbRelays.on('change', function(doc, old) {
|
||||||
|
|
@ -289,8 +290,6 @@ exports.install = function(instance) {
|
||||||
edgeName = relaysData[0].tbname;
|
edgeName = relaysData[0].tbname;
|
||||||
FLOW.OMS_edgeName = edgeName;
|
FLOW.OMS_edgeName = edgeName;
|
||||||
|
|
||||||
logger.debug("RVO tbname:", edgeName);
|
|
||||||
|
|
||||||
dataToTb = {
|
dataToTb = {
|
||||||
[edgeName]: [
|
[edgeName]: [
|
||||||
{
|
{
|
||||||
|
|
@ -304,13 +303,27 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
let time = 3*1000;
|
let time = 3*1000;
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "buildTasks"});
|
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "buildTasks"});
|
||||||
|
|
||||||
sendNotification("rsPort.open()", edgeName, "flow_start", {}, "", instanceSendTo.tb, instance );
|
sendNotification("rsPort.open()", edgeName, "flow_start", {}, "", instanceSendTo.tb, instance );
|
||||||
monitor.info("-->FLOW bol spustený", edgeName, FLOW.OMS_edge_fw_version);
|
monitor.info("-->FLOW bol spustený", edgeName, FLOW.OMS_edge_fw_version);
|
||||||
|
|
||||||
}, time);
|
}, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// we ensure, all tasks will be rebuild every day at 11. To set correct switch off and on times
|
||||||
|
let sendRebuildTasksAt11 = null;
|
||||||
|
const checkIf11Oclock = () =>
|
||||||
|
{
|
||||||
|
const d = new Date();
|
||||||
|
const h = d.getHours();
|
||||||
|
if(h === 11)
|
||||||
|
{
|
||||||
|
instance.send(instanceSendTo.cmd_manager, {sender:"dido_controller", cmd:"buildTasks"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sendRebuildTasksAt11 = setInterval(checkIf11Oclock, 3600000);
|
||||||
|
|
||||||
|
|
||||||
function handleRsPort()
|
function handleRsPort()
|
||||||
|
|
@ -402,9 +415,11 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
function handleWebSocket() {
|
function handleWebSocket() {
|
||||||
|
|
||||||
console.log("handleWebSocket function called");
|
//to keep websocket opened, we send request every 150 seconds
|
||||||
ws = new WebSocket('ws:/10.0.0.38:1234/ws')
|
let startRequests = null;
|
||||||
|
|
||||||
|
console.log("handleWebSocket function called");
|
||||||
|
ws = new WebSocket('ws:/0.0.0.0:1234/ws');
|
||||||
|
|
||||||
ws.onopen = function open() {
|
ws.onopen = function open() {
|
||||||
|
|
||||||
|
|
@ -416,7 +431,13 @@ exports.install = function(instance) {
|
||||||
initialSetting();
|
initialSetting();
|
||||||
ws.send(JSON.stringify({"cmd":"all"}));
|
ws.send(JSON.stringify({"cmd":"all"}));
|
||||||
|
|
||||||
// startRequests();
|
// we request dev info about neuron device from evok to keep websocket connection alive
|
||||||
|
// for some reason this request returns no data, but connection keeps alive
|
||||||
|
// https://evok.api-docs.io/1.0/mpqzDwPwirsoq7i5A/websocket
|
||||||
|
startRequests = setInterval(() => {
|
||||||
|
// console.log(" *** data from evok requested");
|
||||||
|
ws.send(JSON.stringify({"cmd":"filter", "dev": ["neuron"]}));
|
||||||
|
}, 150000)
|
||||||
};
|
};
|
||||||
|
|
||||||
// SAMPLE DATA FROM WEBSOCKET
|
// SAMPLE DATA FROM WEBSOCKET
|
||||||
|
|
@ -442,11 +463,9 @@ exports.install = function(instance) {
|
||||||
// dev: 'input',
|
// dev: 'input',
|
||||||
// mode: 'Simple'
|
// mode: 'Simple'
|
||||||
// },
|
// },
|
||||||
|
|
||||||
ws.onmessage = function(data) {
|
ws.onmessage = function(data) {
|
||||||
|
|
||||||
data = JSON.parse(data.data);
|
data = JSON.parse(data.data);
|
||||||
// console.log(data)
|
|
||||||
|
|
||||||
// data comes in array except of "temperature" ==> it comes as an object
|
// data comes in array except of "temperature" ==> it comes as an object
|
||||||
if(!Array.isArray(data))
|
if(!Array.isArray(data))
|
||||||
|
|
@ -485,32 +504,36 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
ws.on('error', (err) => {
|
ws.on('error', (err) => {
|
||||||
instance.send(instanceSendTo.debug, err.message);
|
instance.send(instanceSendTo.debug, err.message);
|
||||||
|
clearInterval(startRequests);
|
||||||
|
startRequests = null;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
ws.onclose = function(){
|
ws.onclose = function(){
|
||||||
// connection closed, discard old websocket and create a new one in 5s
|
// connection closed, discard old websocket and create a new one in 5s
|
||||||
// stopRequests();
|
// stopRequests();
|
||||||
|
clearInterval(startRequests);
|
||||||
ws = null;
|
ws = null;
|
||||||
console.log("ws is null now, reconnecting in 5 seconds");
|
console.log("ws is null now, reconnecting...");
|
||||||
setTimeout(handleWebSocket, 5000);
|
setTimeout(handleWebSocket, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! do we need requests every minute ???
|
// ! do we need requests every minute ???
|
||||||
// const startRequests = () => {
|
// const startRequests = () => {
|
||||||
// console.log("startRequest function called");
|
// console.log("startRequest function called");
|
||||||
// start = setInterval(() => {
|
// start = setInterval(() => {
|
||||||
// // console.log("data from evok requested");
|
// // console.log("data from evok requested");
|
||||||
// ws.send(JSON.stringify({"cmd":"all"}));
|
// ws.send(JSON.stringify({"cmd":"filter", "devices": "neuron"}));
|
||||||
// // ws.send(JSON.stringify({"cmd":"filter", "devices":["input", "relay"]}));
|
// // ws.send(JSON.stringify({"cmd":"filter", "devices":["input", "relay"]}));
|
||||||
// }, 60000)
|
// }, 150000)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
instance.on("close", () => {
|
instance.on("close", () => {
|
||||||
if(rsPort) rsPort.close();
|
if(rsPort) rsPort.close();
|
||||||
if(ws) ws.close();
|
if(ws) ws.close();
|
||||||
|
clearInterval(sendRebuildTasksAt11);
|
||||||
})
|
})
|
||||||
|
|
||||||
loadAllDb();
|
loadAllDb();
|
||||||
|
|
@ -555,7 +578,7 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
else if(ws)
|
else if(ws)
|
||||||
{
|
{
|
||||||
let cmd = {"cmd": "set", "dev": "relay", "circuit": "1_08", "value": 1};
|
let cmd = {"cmd": "set", "dev": "relay", "circuit": "1_01", "value": 1};
|
||||||
ws.send(JSON.stringify(cmd));
|
ws.send(JSON.stringify(cmd));
|
||||||
logger.debug("sirena zapnuta");
|
logger.debug("sirena zapnuta");
|
||||||
}
|
}
|
||||||
|
|
@ -579,7 +602,7 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
else if(ws)
|
else if(ws)
|
||||||
{
|
{
|
||||||
let cmd = {"cmd": "set", "dev": "relay", "circuit": "1_08", "value": 0};
|
let cmd = {"cmd": "set", "dev": "relay", "circuit": "1_01", "value": 0};
|
||||||
ws.send(JSON.stringify(cmd));
|
ws.send(JSON.stringify(cmd));
|
||||||
logger.debug("sirena vypnuta");
|
logger.debug("sirena vypnuta");
|
||||||
}
|
}
|
||||||
|
|
@ -709,7 +732,7 @@ exports.install = function(instance) {
|
||||||
//pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method
|
//pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method
|
||||||
let cmd = {"cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": 1};
|
let cmd = {"cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": 1};
|
||||||
ws.send(JSON.stringify(cmd));
|
ws.send(JSON.stringify(cmd));
|
||||||
switchLogic(pin, 1)
|
//switchLogic(pin, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -724,7 +747,7 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
let values = {};
|
let values = {};
|
||||||
values["statecode"] = calculateStateCode();
|
values["statecode"] = calculateStateCode();
|
||||||
values["power_mode"] = "Automatic";
|
values["power_mode"] = "automatic";
|
||||||
let tbname = relaysData[line].tbname;
|
let tbname = relaysData[line].tbname;
|
||||||
sendTelemetry(values, tbname);
|
sendTelemetry(values, tbname);
|
||||||
|
|
||||||
|
|
@ -783,71 +806,92 @@ exports.install = function(instance) {
|
||||||
else if(ws)
|
else if(ws)
|
||||||
{
|
{
|
||||||
//pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method
|
//pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method
|
||||||
monitor.info("turnOffLine pin (relay)", pin);
|
//monitor.info("turnOffLine pin (relay)", pin);
|
||||||
let cmd = {"cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": 0};
|
let cmd = {"cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": 0};
|
||||||
ws.send(JSON.stringify(cmd));
|
ws.send(JSON.stringify(cmd));
|
||||||
switchLogic(pin, 0)
|
//switchLogic(pin, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// we expect array as flowdata.data
|
//data from modbus_reader or temperature sensor or twilight sensor or other modbus device
|
||||||
instance.on("data", (flowdata) => {
|
instance.on("0", flowdata => {
|
||||||
|
|
||||||
console.log(flowdata.data);
|
if(!flowdata.data instanceof Object) return;
|
||||||
|
|
||||||
if(flowdata.data instanceof Object)
|
// console.log('***********************', flowdata.data)
|
||||||
|
instance.send(instanceSendTo.debug, flowdata.data);
|
||||||
|
|
||||||
|
// we handle nok status from modbus_reader component and thermometer
|
||||||
|
if(flowdata.data?.status)
|
||||||
{
|
{
|
||||||
|
const status = flowdata.data.status;
|
||||||
if(flowdata.data.hasOwnProperty("sender"))
|
if(status == "NOK-twilight_sensor")
|
||||||
{
|
{
|
||||||
//console.log("sender", flowdata.data);
|
deviceStatuses["twilight_sensor"] = "NOK";
|
||||||
|
}
|
||||||
if(flowdata.data.sender == "gettemperature")
|
else if(status == "NOK-em340" || status == "NOK-em111")
|
||||||
{
|
{
|
||||||
deviceStatuses["temperature"] = flowdata.data.status;
|
deviceStatuses["em"] = "NOK";
|
||||||
}
|
}
|
||||||
else if(flowdata.data.sender == "modbus_citysys")
|
else if(status == "NOK-thermometer")
|
||||||
{
|
{
|
||||||
//elektromer rvo
|
deviceStatuses["temperature"] = "NOK";
|
||||||
if(flowdata.data.tbdata.hasOwnProperty(edgeName))
|
|
||||||
{
|
|
||||||
//rvo
|
|
||||||
deviceStatuses["rvo"] = {status: flowdata.data.tbdata[edgeName][0]["values"]["status"], tbdata: flowdata.data.tbdata};
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
//posli do tb - to je vyriesene na urovni modbus_citysys
|
|
||||||
//instance.send(instanceSendTo.tb, flowdata.data.tbdata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.send(instanceSendTo.debug, flowdata.data );
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let obj = flowdata.data;
|
|
||||||
|
|
||||||
let line = obj.line;
|
|
||||||
let force = obj.force;
|
|
||||||
let info = obj.info;
|
|
||||||
|
|
||||||
if(obj.command == "turnOn") turnOnLine(line, undefined, force, info);
|
|
||||||
else if(obj.command == "turnOff") turnOffLine(line, undefined, force, info);
|
|
||||||
else if(obj.command == "turnOnAlarm") turnOnAlarm();
|
|
||||||
else if(obj.command == "turnOffAlarm") turnOffAlarm();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const values = flowdata.data.values;
|
||||||
|
if(values.hasOwnProperty("twilight_sensor"))
|
||||||
|
{
|
||||||
|
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: values["twilight_sensor"]});
|
||||||
|
deviceStatuses["twilight_sensor"] = "OK"
|
||||||
|
}
|
||||||
|
else if(values.hasOwnProperty("temperature"))
|
||||||
|
{
|
||||||
|
deviceStatuses["temperature"] = "OK";
|
||||||
|
}
|
||||||
|
// EM
|
||||||
|
else if(values.hasOwnProperty("total_power") || values.hasOwnProperty("total_energy") || values.hasOwnProperty("power_factor") || values.hasOwnProperty("Phase_1_voltage") || values.hasOwnProperty("Phase_1_current"))
|
||||||
|
{
|
||||||
|
deviceStatuses["em"] = "OK";
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateStatus = checkFinalRVOStatus();
|
||||||
|
if(updateStatus) values.status = "OK";
|
||||||
|
|
||||||
|
sendTelemetry(values, FLOW.OMS_rvo_tbname);
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// we expect array as flowdata.data
|
||||||
|
instance.on("1", flowdata => {
|
||||||
|
|
||||||
|
console.log(flowdata.data);
|
||||||
|
|
||||||
|
if(!flowdata.data instanceof Object) return;
|
||||||
|
|
||||||
|
let obj = flowdata.data;
|
||||||
|
let line = obj.line;
|
||||||
|
let force = obj.force;
|
||||||
|
let info = obj.info;
|
||||||
|
|
||||||
|
if(obj.command == "turnOn") turnOnLine(line, undefined, force, info);
|
||||||
|
else if(obj.command == "turnOff") turnOffLine(line, undefined, force, info);
|
||||||
|
else if(obj.command == "turnOnAlarm") turnOnAlarm();
|
||||||
|
else if(obj.command == "turnOffAlarm") turnOffAlarm();
|
||||||
|
|
||||||
|
|
||||||
//! ake data prichadzaju z cmd_manager.js ???
|
//! ake data prichadzaju z cmd_manager.js ???
|
||||||
//TODO transform to websocket
|
//TODO transform to websocket
|
||||||
if (Array.isArray(flowdata.data)){
|
if (Array.isArray(obj)){
|
||||||
|
|
||||||
rsPort.write(Buffer.from(flowdata.data), function(err) {
|
rsPort.write(Buffer.from(obj), function(err) {
|
||||||
switchLogic(flowdata.data);
|
switchLogic(obj);
|
||||||
|
|
||||||
instance.send(instanceSendTo.debug, {"WRITE":flowdata.data} );
|
instance.send(instanceSendTo.debug, {"WRITE":obj} );
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -859,12 +903,17 @@ exports.install = function(instance) {
|
||||||
let bytes = [];
|
let bytes = [];
|
||||||
let bits = [];
|
let bits = [];
|
||||||
|
|
||||||
|
|
||||||
//Hlavný istič - state_of_main_switch
|
//Hlavný istič - state_of_main_switch
|
||||||
if(deviceStatuses["state_of_main_switch"] == "On") bits.push(0);
|
if(deviceStatuses["state_of_main_switch"] == "On")
|
||||||
else if(deviceStatuses["state_of_main_switch"] == "Off") bits.push(1);
|
{
|
||||||
|
bits.push(0);
|
||||||
|
}
|
||||||
|
else if(deviceStatuses["state_of_main_switch"] == "Off")
|
||||||
|
{
|
||||||
|
bits.push(1);
|
||||||
|
}
|
||||||
|
|
||||||
//Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false
|
//Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY
|
||||||
if(!FLOW.OMS_maintenance_mode)
|
if(!FLOW.OMS_maintenance_mode)
|
||||||
{
|
{
|
||||||
if(deviceStatuses["rotary_switch_state"] == "Manual")
|
if(deviceStatuses["rotary_switch_state"] == "Manual")
|
||||||
|
|
@ -895,48 +944,95 @@ exports.install = function(instance) {
|
||||||
{
|
{
|
||||||
bits.push(0);
|
bits.push(0);
|
||||||
}
|
}
|
||||||
else bits.push(1);
|
else
|
||||||
|
{
|
||||||
|
bits.push(1);
|
||||||
|
}
|
||||||
|
|
||||||
//EM
|
//EM
|
||||||
if(deviceStatuses["rvo"].status == "NOK") bits.push(1);
|
if(deviceStatuses["em"] == "NOK")
|
||||||
else bits.push(0);
|
{
|
||||||
|
bits.push(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bits.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
//Teplomer
|
//Teplomer
|
||||||
if(deviceStatuses["temperature"] == "NOK") bits.push(1);
|
if(deviceStatuses["temperature"] == "NOK")
|
||||||
else bits.push(0);
|
{
|
||||||
|
bits.push(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bits.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
//Batéria
|
//Batéria
|
||||||
if(deviceStatuses["battery"] == "NOK") bits.push(1);
|
if(deviceStatuses["battery"] == "NOK")
|
||||||
else bits.push(0);
|
{
|
||||||
|
bits.push(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bits.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
//Zdroj
|
//Zdroj
|
||||||
if(deviceStatuses["power_supply"] == "NOK") bits.push(1);
|
if(deviceStatuses["power_supply"] == "NOK")
|
||||||
else bits.push(0);
|
{
|
||||||
|
bits.push(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bits.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
//MN
|
//MN
|
||||||
if(deviceStatuses["master_node"] == "NOK") bits.push(1);
|
if(deviceStatuses["master_node"] == "NOK")
|
||||||
else bits.push(0);
|
{
|
||||||
|
bits.push(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bits.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
//výpadok napätia na fáze
|
//výpadok napätia na fáze
|
||||||
if(deviceStatuses["no_voltage"] == "NOK") bits.push(1);
|
if(deviceStatuses["no_voltage"] == "NOK")
|
||||||
else bits.push(0);
|
{
|
||||||
|
bits.push(1);
|
||||||
bits.push(0);
|
}
|
||||||
bits.push(0);
|
else
|
||||||
bits.push(0);
|
{
|
||||||
bits.push(0);
|
bits.push(0);
|
||||||
bits.push(0);
|
}
|
||||||
bits.push(0);
|
|
||||||
|
|
||||||
//console.log("calculateStateCode - deviceStatuses", deviceStatuses);
|
if(deviceStatuses["twilight_sensor"] == "NOK")
|
||||||
//console.log("calculateStateCode", bits);
|
{
|
||||||
|
bits.push(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bits.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// doplnime do 16 bitov (2 byty)
|
||||||
|
for(let i = bits.length; i < 16; i++)
|
||||||
|
{
|
||||||
|
bits.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log("calculateStateCode - deviceStatuses", deviceStatuses);
|
||||||
|
// console.log("calculateStateCode", bits);
|
||||||
|
|
||||||
let byte0 = bitwise.byte.write(bits.slice(0,8).reverse());
|
let byte0 = bitwise.byte.write(bits.slice(0,8).reverse());
|
||||||
let byte1 = bitwise.byte.write(bits.slice(8).reverse());
|
let byte1 = bitwise.byte.write(bits.slice(8).reverse());
|
||||||
|
|
||||||
let byte = bytesToInt([byte1, byte0]);
|
let byte = bytesToInt([byte1, byte0]);
|
||||||
|
|
||||||
//console.log("calculateStateCode", byte);
|
//console.log("calculateStateCode -------------------", byte);
|
||||||
|
|
||||||
return byte;
|
return byte;
|
||||||
}
|
}
|
||||||
|
|
@ -951,10 +1047,18 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
let status = "OK";
|
let status = "OK";
|
||||||
|
|
||||||
if(deviceStatuses["rvo"].status == "NOK")
|
if(deviceStatuses["em"] == "NOK")
|
||||||
{
|
{
|
||||||
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: rvo status is NOK");
|
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: EM status is NOK");
|
||||||
if(writeToFile) errLogger.error("checkFinalRVOStatus: rvo status is NOK", deviceStatuses["rvo"].tbdata);
|
if(writeToFile) errLogger.error("checkFinalRVOStatus: EM status is NOK");
|
||||||
|
|
||||||
|
status = "NOK";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(deviceStatuses["twilight_sensor"] == "NOK")
|
||||||
|
{
|
||||||
|
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: twilight_sensor is NOK");
|
||||||
|
if(writeToFile) errLogger.error("checkFinalRVOStatus: twilight sensor is NOK");
|
||||||
|
|
||||||
status = "NOK";
|
status = "NOK";
|
||||||
}
|
}
|
||||||
|
|
@ -971,10 +1075,15 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
if(status == "OK")
|
if(status == "OK")
|
||||||
{
|
{
|
||||||
for (const pinIndex of [1, 4, 6]) {
|
let pinIndexes = [1, 4, 6];
|
||||||
|
if(controller_type == 'unipi') pinIndexes = ['input1_01', 'input1_04', 'input1_05'];
|
||||||
|
|
||||||
|
//console.log('-------- previousValues', previousValues);
|
||||||
|
|
||||||
|
for (const pinIndex of pinIndexes) {
|
||||||
if (previousValues[pinIndex] === 0) {
|
if (previousValues[pinIndex] === 0) {
|
||||||
|
|
||||||
if (pinIndex === 6 && FLOW.OMS_maintenance_mode) continue;
|
if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && FLOW.OMS_maintenance_mode) continue;
|
||||||
|
|
||||||
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: value is 0");
|
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: value is 0");
|
||||||
if(writeToFile) errLogger.error("checkFinalRVOStatus: value is 0", pinsData[pinIndex].type);
|
if(writeToFile) errLogger.error("checkFinalRVOStatus: value is 0", pinsData[pinIndex].type);
|
||||||
|
|
@ -986,7 +1095,7 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// battery status. If value is 1 - battery is not ok
|
// battery status. If value is 1 - battery is NOK
|
||||||
if (previousValues[5] === 1)
|
if (previousValues[5] === 1)
|
||||||
{
|
{
|
||||||
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: NOK status generated by battery");
|
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: NOK status generated by battery");
|
||||||
|
|
@ -995,18 +1104,6 @@ exports.install = function(instance) {
|
||||||
status = "NOK";
|
status = "NOK";
|
||||||
}
|
}
|
||||||
|
|
||||||
//ak mame telemetriu z elektromeru, posleme
|
|
||||||
if(deviceStatuses["rvo"].tbdata != undefined)
|
|
||||||
{
|
|
||||||
//deviceStatuses["rvo"] = {status: flowdata.data.tbdata[edgeName][0]["values"]["status"], tbdata: flowdata.data.tbdata};
|
|
||||||
|
|
||||||
deviceStatuses["rvo"].tbdata[edgeName][0]["values"]["status"] = status;
|
|
||||||
|
|
||||||
|
|
||||||
instance.send(instanceSendTo.tb, deviceStatuses["rvo"].tbdata);
|
|
||||||
delete deviceStatuses["rvo"].tbdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log("FLOW.OMS_masterNodeIsResponding", FLOW.OMS_masterNodeIsResponding);
|
//console.log("FLOW.OMS_masterNodeIsResponding", FLOW.OMS_masterNodeIsResponding);
|
||||||
|
|
||||||
if(!FLOW.OMS_masterNodeIsResponding)
|
if(!FLOW.OMS_masterNodeIsResponding)
|
||||||
|
|
@ -1033,17 +1130,7 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
if(status == "NOK")
|
if(status == "NOK")
|
||||||
{
|
{
|
||||||
|
sendTelemetry({status: "NOK"}, FLOW.OMS_rvo_tbname);
|
||||||
const dataToTb = {
|
|
||||||
[edgeName]: [
|
|
||||||
{
|
|
||||||
"ts": Date.now(),
|
|
||||||
"values": {status: "NOK"}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.send(instanceSendTo.tb, dataToTb);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1052,21 +1139,22 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]]
|
||||||
// we pass array to function in case of rsPort [[55,3,0,1]]
|
// we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1]
|
||||||
// we pass two values in case of websocket [3,1]
|
|
||||||
const switchLogic = (...args) => {
|
const switchLogic = (...args) => {
|
||||||
|
|
||||||
let values = {status: "OK"};
|
let values = {status: "OK"};
|
||||||
let dataToTb, pinIndex, newPinValue, twighlight;
|
let dataToTb, pinIndex, newPinValue, twilight;
|
||||||
|
|
||||||
|
//data from rsPort
|
||||||
if(args.length == 1)
|
if(args.length == 1)
|
||||||
{
|
{
|
||||||
pinIndex = args[0][1] + 1;
|
pinIndex = args[0][1] + 1;
|
||||||
if (pinIndex === 17) pinIndex--;
|
if (pinIndex === 17) pinIndex--;
|
||||||
newPinValue = args[0][3];
|
newPinValue = args[0][3];
|
||||||
twighlight = args[0][2];
|
twilight = args[0][2];
|
||||||
}
|
}
|
||||||
|
//data from websocket
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pinIndex = args[0];
|
pinIndex = args[0];
|
||||||
|
|
@ -1090,7 +1178,9 @@ exports.install = function(instance) {
|
||||||
if(newPinValue === 0) value = "Off";
|
if(newPinValue === 0) value = "Off";
|
||||||
|
|
||||||
//Hlavný istič
|
//Hlavný istič
|
||||||
if(type === "state_of_main_switch")
|
//! po novom uz 'state of main switch' nemame. Namiesto neho je 'door_condition', kedze mame dvoje dveri
|
||||||
|
//! takze ked pride z evoku signal pre 'input1_05', handlujeme ho ako 'door_condition'
|
||||||
|
if(type === "!!!state_of_main_switch")
|
||||||
{
|
{
|
||||||
if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
|
if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
|
||||||
{
|
{
|
||||||
|
|
@ -1116,16 +1206,26 @@ exports.install = function(instance) {
|
||||||
{
|
{
|
||||||
pin2 = newPinValue;
|
pin2 = newPinValue;
|
||||||
pin3 = previousValues[3] || previousValues["input1_03"];
|
pin3 = previousValues[3] || previousValues["input1_03"];
|
||||||
if (pin3 == undefined) pin3 = 0;
|
|
||||||
|
if(pin3 == undefined)
|
||||||
|
{
|
||||||
|
previousValues[pinIndex] = newPinValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(pinIndex == 3 || pinIndex == "input1_03")
|
else if(pinIndex == 3 || pinIndex == "input1_03")
|
||||||
{
|
{
|
||||||
pin3 = newPinValue;
|
pin3 = newPinValue;
|
||||||
pin2 = previousValues[2] || previousValues["input1_02"];
|
pin2 = previousValues[2] || previousValues["input1_02"];
|
||||||
if (pin2 == undefined) pin2 = 0;
|
|
||||||
|
if(pin2 == undefined)
|
||||||
|
{
|
||||||
|
previousValues[pinIndex] = newPinValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value = "Off";
|
//console.log('***********************', pin2, pin3)
|
||||||
if (pin2 == 1 && pin3 == 0) value = "Manual";
|
if (pin2 == 1 && pin3 == 0) value = "Manual";
|
||||||
if (pin2 == 0 && pin3 == 0) value = "Off";
|
if (pin2 == 0 && pin3 == 0) value = "Off";
|
||||||
if (pin2 == 0 && pin3 == 1) value = "Automatic";
|
if (pin2 == 0 && pin3 == 1) value = "Automatic";
|
||||||
|
|
@ -1136,7 +1236,7 @@ exports.install = function(instance) {
|
||||||
//ak je spracovany, a automatic - tak ho zapnem
|
//ak je spracovany, a automatic - tak ho zapnem
|
||||||
//ak nie je spracovany, iba profil zapisem
|
//ak nie je spracovany, iba profil zapisem
|
||||||
|
|
||||||
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "rotary_switch_state", value: value});
|
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "rotary_switch_state", value: value});
|
||||||
|
|
||||||
//console.log("rotary_switch_state pin", pin2, pin3, value);
|
//console.log("rotary_switch_state pin", pin2, pin3, value);
|
||||||
}
|
}
|
||||||
|
|
@ -1179,7 +1279,9 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Dverový kontakt - pin 6
|
//Dverový kontakt - pin 6
|
||||||
else if(type == "door_condition")
|
//! Po novom mame dva dverove kontakty, nie jeden. Druhy je teraz tam, kde bol digital input "state_of_main_switch"
|
||||||
|
//! preto ked pride z evoku signal z input1_05, co bol predytm "main switch" handlujeme ho teraz ako 'door_condition'
|
||||||
|
else if(type == "door_condition" || type === "state_of_main_switch")
|
||||||
{
|
{
|
||||||
newPinValue === 0 ? value = "open" : value = "closed";
|
newPinValue === 0 ? value = "open" : value = "closed";
|
||||||
|
|
||||||
|
|
@ -1202,8 +1304,9 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
//console.log(door_has_been_open_without_permision_alarm_is_on);
|
//console.log(door_has_been_open_without_permision_alarm_is_on);
|
||||||
|
|
||||||
//zapneme sirenu
|
// zapneme sirenu
|
||||||
turnOnAlarm();
|
// ak sa otvoria dvere len na elektromeri (type === "state_of_main_switch") alarm sa nema spustit. alarm sa spusti len ked sa otvoria hlavne dvere (type === "door_condition")
|
||||||
|
if(type === "door_condition") turnOnAlarm();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value === "closed")
|
if (value === "closed")
|
||||||
|
|
@ -1217,73 +1320,84 @@ exports.install = function(instance) {
|
||||||
deviceStatuses["door_condition"] = value;
|
deviceStatuses["door_condition"] = value;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//lux sensor
|
||||||
else if(type == "twilight_sensor")
|
else if(type == "twilight_sensor")
|
||||||
{
|
{
|
||||||
//lux sensor
|
//! TODO - to show nok status, if lux value is not changing more then 10 times. From unipi for example comes value from 0-1000.
|
||||||
value = parseFloat(newPinValue + (256*twighlight));
|
//Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK.
|
||||||
|
//This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK.
|
||||||
let now = new Date();
|
|
||||||
//new Date(dusk.getTime()
|
|
||||||
|
|
||||||
let obj = {timestamp: now.getTime(), value: value};
|
|
||||||
|
|
||||||
//test
|
|
||||||
//twilight_sensor_interval = 1;
|
|
||||||
|
|
||||||
twilight_sensor.push(obj);
|
|
||||||
twilight_sensor_array.push(value);
|
|
||||||
|
|
||||||
//check if we receive just 1 constant value from lux sensor ==> error
|
|
||||||
if(twilight_sensor_array.length > 10) {
|
|
||||||
|
|
||||||
let set = new Set(twilight_sensor_array);
|
|
||||||
if(set.size === 1 && !twighlightError)
|
|
||||||
{
|
|
||||||
twighlightError = true;
|
|
||||||
values["status"] = "NOK";
|
|
||||||
let value = twilight_sensor_array.shift();
|
|
||||||
//sendNotification("switchLogic", edgeName, ERRWEIGHT.ERROR, "Lux sensor error", {"Repeating value": value}, instanceSendTo.tb, instance );
|
|
||||||
newPinValue = 0;
|
|
||||||
}
|
|
||||||
else if (set.size !== 1 && twighlightError)
|
|
||||||
{
|
|
||||||
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Lux sensor is working again", "", instanceSendTo.tb, instance );
|
|
||||||
twighlightError = false;
|
|
||||||
twilight_sensor_array.shift();
|
|
||||||
newPinValue = value;
|
|
||||||
}
|
|
||||||
else if (set.size === 1 && twighlightError)
|
|
||||||
{
|
|
||||||
values["status"] = "NOK";
|
|
||||||
twilight_sensor_array.shift();
|
|
||||||
newPinValue = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let diff = twilight_sensor[ twilight_sensor.length - 1 ].timestamp - twilight_sensor[0].timestamp;
|
|
||||||
if(diff >= twilight_sensor_interval * 60 * 1000)
|
|
||||||
{
|
|
||||||
const average = twilight_sensor.reduce((acc, c) => acc + c.value, 0) / twilight_sensor.length;
|
|
||||||
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "lux_sensor", value: average});
|
|
||||||
|
|
||||||
twilight_sensor = [];
|
|
||||||
|
|
||||||
//console.log("lux_sensor send", average);
|
|
||||||
}
|
|
||||||
//else console.log("lux_sensor", value, diff);
|
|
||||||
|
|
||||||
values["status"] = "OK";
|
values["status"] = "OK";
|
||||||
|
value = newPinValue;
|
||||||
|
|
||||||
//
|
if(controller_type === 'lm')
|
||||||
|
{
|
||||||
|
value = parseFloat(newPinValue + (256*twilight));
|
||||||
|
|
||||||
|
let now = new Date();
|
||||||
|
//new Date(dusk.getTime()
|
||||||
|
|
||||||
|
let obj = {timestamp: now.getTime(), value: value};
|
||||||
|
|
||||||
|
//test
|
||||||
|
//twilight_sensor_interval = 1;
|
||||||
|
|
||||||
|
twilight_sensor.push(obj);
|
||||||
|
//twilight_sensor_array.push(value);
|
||||||
|
|
||||||
|
//check if we receive just 1 constant value from lux sensor ==> error
|
||||||
|
if(twilight_sensor_array.length > 10) {
|
||||||
|
|
||||||
|
let set = new Set(twilight_sensor_array);
|
||||||
|
if(set.size === 1 && !twilightError)
|
||||||
|
{
|
||||||
|
twilightError = true;
|
||||||
|
values["status"] = "NOK";
|
||||||
|
let value = twilight_sensor_array.shift();
|
||||||
|
//sendNotification("switchLogic", edgeName, ERRWEIGHT.ERROR, "Lux sensor error", {"Repeating value": value}, instanceSendTo.tb, instance );
|
||||||
|
newPinValue = 0;
|
||||||
|
}
|
||||||
|
else if (set.size !== 1 && twilightError)
|
||||||
|
{
|
||||||
|
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Lux sensor is working again", "", instanceSendTo.tb, instance );
|
||||||
|
twilightError = false;
|
||||||
|
twilight_sensor_array.shift();
|
||||||
|
newPinValue = value;
|
||||||
|
}
|
||||||
|
else if (set.size === 1 && twilightError)
|
||||||
|
{
|
||||||
|
values["status"] = "NOK";
|
||||||
|
twilight_sensor_array.shift();
|
||||||
|
newPinValue = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let diff = twilight_sensor[ twilight_sensor.length - 1 ].timestamp - twilight_sensor[0].timestamp;
|
||||||
|
if(diff >= twilight_sensor_interval * 60 * 1000)
|
||||||
|
{
|
||||||
|
const average = twilight_sensor.reduce((acc, c) => acc + c.value, 0) / twilight_sensor.length;
|
||||||
|
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: average});
|
||||||
|
|
||||||
|
twilight_sensor = [];
|
||||||
|
|
||||||
|
//console.log("lux_sensor send", average);
|
||||||
|
}
|
||||||
|
//else console.log("lux_sensor", value, diff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(type == "state_of_contactor")
|
else if(type == "state_of_contactor")
|
||||||
{
|
{
|
||||||
//sendNotification("switchLogic", edgeName, ERRWEIGHT.INFO, `State of contactor ${line} is now ${value}`, "", instanceSendTo.tb, instance );
|
//sendNotification("switchLogic", edgeName, ERRWEIGHT.INFO, `State of contactor ${line} is now ${value}`, "", instanceSendTo.tb, instance );
|
||||||
sendNotification("switchLogic", edgeName, "state_of_contactor_for_line", {line: line, value: value}, "", instanceSendTo.tb, instance );
|
|
||||||
|
|
||||||
deviceStatuses["state_of_contactor"][line] = value;
|
if(!(deviceStatuses["state_of_contactor"][line] == value))
|
||||||
|
{
|
||||||
|
sendNotification("switchLogic", edgeName, "state_of_contactor_for_line", {line: line, value: value}, "", instanceSendTo.tb, instance );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deviceStatuses["state_of_contactor"][line] = value;
|
||||||
|
}
|
||||||
|
|
||||||
//true, false
|
//true, false
|
||||||
if(value === "On") value = true;
|
if(value === "On") value = true;
|
||||||
else if(value === "Off") value = false;
|
else if(value === "Off") value = false;
|
||||||
|
|
@ -1319,7 +1433,7 @@ exports.install = function(instance) {
|
||||||
//a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor
|
//a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor
|
||||||
|
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged});
|
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged});
|
||||||
}, time);
|
}, time);
|
||||||
|
|
||||||
reportLineStatus(line);
|
reportLineStatus(line);
|
||||||
|
|
@ -1344,7 +1458,24 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
if(valueChanged)
|
if(valueChanged)
|
||||||
{
|
{
|
||||||
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "state_of_breaker", value: value, line: line});
|
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: line});
|
||||||
|
|
||||||
|
//mame 3 istice. ked je viac ako 3 linie, dalsie sa zapajaju paralelne. to znamena na istici 1 je linia 1 a 4, na istici 2 je linia 2 a 5, na istici 3 je linia 3 a 6 (key je string ("4"))
|
||||||
|
//vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia
|
||||||
|
const lineOnSameBraker = line + 3 + "";
|
||||||
|
|
||||||
|
if(relaysData.hasOwnProperty(lineOnSameBraker)) {
|
||||||
|
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "state_of_breaker", value: value, line: line + 3});
|
||||||
|
|
||||||
|
deviceStatuses["state_of_breaker"][line + 3] = value;
|
||||||
|
reportLineStatus(line + 3);
|
||||||
|
|
||||||
|
values[type] = value;
|
||||||
|
tbname = relaysData[lineOnSameBraker].tbname;
|
||||||
|
sendTelemetry(values, tbname);
|
||||||
|
|
||||||
|
delete values[type];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(value == "Off") values["status"] = "NOK";
|
if(value == "Off") values["status"] = "NOK";
|
||||||
|
|
@ -1352,25 +1483,27 @@ exports.install = function(instance) {
|
||||||
deviceStatuses["state_of_breaker"][line] = value;
|
deviceStatuses["state_of_breaker"][line] = value;
|
||||||
|
|
||||||
reportLineStatus(line);
|
reportLineStatus(line);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
values[type] = value;
|
values[type] = value;
|
||||||
|
|
||||||
let result = checkFinalRVOStatus();
|
|
||||||
if(!result && line == 0)
|
|
||||||
{
|
|
||||||
values["status"] = "NOK";
|
|
||||||
}
|
|
||||||
|
|
||||||
//--
|
|
||||||
|
|
||||||
//if(FLOW.OMS_rvo_tbname == tbname) values["statecode"] = calculateStateCode();
|
//if(FLOW.OMS_rvo_tbname == tbname) values["statecode"] = calculateStateCode();
|
||||||
|
|
||||||
if(pinsData.hasOwnProperty(pinIndex))
|
if(pinsData.hasOwnProperty(pinIndex))
|
||||||
{
|
{
|
||||||
let valueChanged = false;
|
let valueChanged = false;
|
||||||
if(newPinValue != previousValues[pinIndex]) valueChanged = true;
|
if(newPinValue != previousValues[pinIndex])
|
||||||
|
{
|
||||||
|
valueChanged = true;
|
||||||
|
//pin was changed
|
||||||
|
previousValues[pinIndex] = newPinValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = checkFinalRVOStatus();
|
||||||
|
if(!result && line == 0)
|
||||||
|
{
|
||||||
|
values["status"] = "NOK";
|
||||||
|
}
|
||||||
|
|
||||||
if(type == "state_of_contactor") valueChanged = true;
|
if(type == "state_of_contactor") valueChanged = true;
|
||||||
if(type == "rotary_switch_state") valueChanged = true;
|
if(type == "rotary_switch_state") valueChanged = true;
|
||||||
|
|
@ -1381,15 +1514,14 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
if(FLOW.OMS_rvo_tbname == "")
|
if(FLOW.OMS_rvo_tbname == "")
|
||||||
{
|
{
|
||||||
console.log("FLOW.OMS_rvo_tbname is EMPTY");
|
console.log("FLOW.OMS_rvo_tbname is EMPTY");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(FLOW.OMS_rvo_tbname == tbname)
|
if(FLOW.OMS_rvo_tbname == tbname)
|
||||||
{
|
{
|
||||||
values["statecode"] = calculateStateCode();
|
values["statecode"] = calculateStateCode();
|
||||||
//console.log(type, values, valueChanged, FLOW.OMS_rvo_tbname, tbname);
|
//console.log('**********************', type, values, valueChanged, FLOW.OMS_rvo_tbname, tbname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(valueChanged)
|
if(valueChanged)
|
||||||
{
|
{
|
||||||
|
|
@ -1412,11 +1544,8 @@ exports.install = function(instance) {
|
||||||
logger.debug("no pinIndex", pinsData[pinIndex], pinsData);
|
logger.debug("no pinIndex", pinsData[pinIndex], pinsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
//pin was changed
|
}
|
||||||
previousValues[pinIndex] = newPinValue;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendTelemetry(values, tbname)
|
function sendTelemetry(values, tbname)
|
||||||
{
|
{
|
||||||
|
|
@ -1431,8 +1560,6 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
instance.send(instanceSendTo.tb, dataToTb);
|
instance.send(instanceSendTo.tb, dataToTb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1695,22 +1822,18 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
//! pins.table --> from UNIPI
|
//! pins.table --> from UNIPI
|
||||||
// pin:string|type:string|line:number
|
// pin:string|type:string|line:number
|
||||||
// *|al_mswitch|state_of_main_switch|0|...........
|
// *|input1_01|state_of_main_switch|0|...........
|
||||||
// *|al_rswitch1|rotary_switch_state|0|...........
|
// *|input1_02|rotary_switch_state|0|...........
|
||||||
// *|al_rswitch2|rotary_switch_state|0|...........
|
// *|input1_03|rotary_switch_state|0|...........
|
||||||
// *|al_power|power_supply|0|...........
|
// *|intut1_04|power_supply|0|...........
|
||||||
// *|al_battery|battery|0|...........
|
// *|input1_05|door_condition|0|...........
|
||||||
// *|al_door|door_condition|0|...........
|
// *|input1_06|state_of_breaker|1|...........
|
||||||
// *|al_breaker1|state_of_breaker|1|...........
|
// *|input1_07|state_of_breaker|2|...........
|
||||||
// *|al_breaker2|state_of_breaker|2|...........
|
// *|input1_08|state_of_breaker|3|...........
|
||||||
// *|al_breaker3|state_of_breaker|3|...........
|
// *|relay1_02|state_of_contactor|1|...........
|
||||||
// *|al_breaker4|state_of_breaker|4|...........
|
// *|relay1_03|state_of_contactor|2|...........
|
||||||
// *|al_relay_1|state_of_contactor|1|...........
|
// *|relay1_04|state_of_contactor|3|...........
|
||||||
// *|al_relay_2|state_of_contactor|2|...........
|
// *|287D8776E0013CE9|temperature|0|...........
|
||||||
// *|al_relay_3|state_of_contactor|3|...........
|
|
||||||
// *|al_relay_4|state_of_contactor|4|...........
|
|
||||||
// *|16|twilight_sensor|0|...........
|
|
||||||
// *|28744F7791180257|temperature|0|...........
|
|
||||||
|
|
||||||
|
|
||||||
//! pins_data --> from UNIPI
|
//! pins_data --> from UNIPI
|
||||||
|
|
@ -1762,3 +1885,28 @@ exports.install = function(instance) {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [
|
||||||
|
// {
|
||||||
|
// "ts": 1700409326353,
|
||||||
|
// "values": {
|
||||||
|
// "_event": {
|
||||||
|
// "type": "notice",
|
||||||
|
// "status": "new",
|
||||||
|
// "source": {
|
||||||
|
// "func": "rsPort.open()",
|
||||||
|
// "component": "1700343402190",
|
||||||
|
// "component_name": "DIDO_Controller",
|
||||||
|
// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV"
|
||||||
|
// },
|
||||||
|
// "message": "al_shariff_10.0.0.38: FLOW has been started ",
|
||||||
|
// "message_data": ""
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
exports.id = 'gettemperature';
|
exports.id = 'thermometer';
|
||||||
exports.title = 'Thermometer';
|
exports.title = 'Thermometer';
|
||||||
exports.group = 'Worksys';
|
exports.group = 'Worksys';
|
||||||
exports.color = '#5CB36D';
|
exports.color = '#5CB36D';
|
||||||
exports.version = '1.0.2';
|
exports.version = '1.0.3';
|
||||||
exports.output = ["red", "white", "blue"];
|
exports.output = ["red", "white", "blue"];
|
||||||
exports.author = 'Rastislav Kovac';
|
exports.author = 'Rastislav Kovac';
|
||||||
exports.icon = 'thermometer-three-quarters';
|
exports.icon = 'thermometer-three-quarters';
|
||||||
|
|
||||||
exports.readme = `# Getting temperature values from RVO`;
|
exports.readme = `# Getting temperature values for RVO. In case of LM, you need device address. In case of unipi, evok sends values, in case thermometer is installed`;
|
||||||
|
|
||||||
const instanceSendTo = {
|
const instanceSendTo = {
|
||||||
debug: 0,
|
debug: 0,
|
||||||
tb: 1,
|
tb: 1,
|
||||||
di_do_controller: 2
|
dido_controller: 2
|
||||||
}
|
}
|
||||||
|
|
||||||
//read temperature - frequency
|
//read temperature - frequency
|
||||||
|
|
@ -43,7 +43,7 @@ const monitor = log4js.getLogger("monitorLogs");
|
||||||
//monitor.info('info');
|
//monitor.info('info');
|
||||||
//errLogger.error("some error");
|
//errLogger.error("some error");
|
||||||
|
|
||||||
const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js');
|
const { promisifyBuilder } = require('./helper/db_helper');
|
||||||
const dbSettings = TABLE("settings");
|
const dbSettings = TABLE("settings");
|
||||||
let temperatureAddress = "";
|
let temperatureAddress = "";
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ loadSettings();
|
||||||
exports.install = function(instance) {
|
exports.install = function(instance) {
|
||||||
|
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const { sendNotification, ERRWEIGHT } = require('./helper/notification_reporter.js');
|
const { sendNotification, ERRWEIGHT } = require('./helper/notification_reporter');
|
||||||
|
|
||||||
let startRead;
|
let startRead;
|
||||||
let dataToTb;
|
let dataToTb;
|
||||||
|
|
@ -76,9 +76,9 @@ exports.install = function(instance) {
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const start = function(){
|
const start = function() {
|
||||||
|
|
||||||
try{
|
try {
|
||||||
|
|
||||||
if(FLOW.OMS_controller_type === "unipi")
|
if(FLOW.OMS_controller_type === "unipi")
|
||||||
{
|
{
|
||||||
|
|
@ -130,8 +130,8 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
monitor.info("Thermometer is not responding", error, FLOW.OMS_brokerready);
|
monitor.info("Thermometer is not responding", error, FLOW.OMS_brokerready);
|
||||||
|
|
||||||
instance.send(instanceSendTo.tb, dataToTb);
|
// instance.send(instanceSendTo.tb, dataToTb); // poslat stav nok do tb, ak to handluje dido_controller ??
|
||||||
instance.send(instanceSendTo.di_do_controller, {sender: "gettemperature", status: status});
|
instance.send(instanceSendTo.dido_controller, {status: "NOK-thermometer"});
|
||||||
}
|
}
|
||||||
else parseData(stdout);
|
else parseData(stdout);
|
||||||
}
|
}
|
||||||
|
|
@ -162,10 +162,9 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
logger.debug("gettemperature", data);
|
logger.debug("gettemperature", data);
|
||||||
|
|
||||||
if (!isNaN(data)){
|
if(!isNaN(data)) {
|
||||||
|
|
||||||
|
if(counter > 290)
|
||||||
//if ( counter > 290 )
|
|
||||||
{
|
{
|
||||||
instance.send(instanceSendTo.debug, "[Get temperature component] - temperature data are comming again from RVO after more than 1 day break");
|
instance.send(instanceSendTo.debug, "[Get temperature component] - temperature data are comming again from RVO after more than 1 day break");
|
||||||
|
|
||||||
|
|
@ -174,21 +173,22 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("gettemperature", data);
|
logger.debug("gettemperature", data);
|
||||||
|
const values = {
|
||||||
|
"temperature": Number(data.toFixed(2)),
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
|
||||||
dataToTb = {
|
dataToTb = {
|
||||||
[edgeName]: [
|
[edgeName]: [
|
||||||
{
|
{
|
||||||
"ts": Date.now(),
|
"ts": Date.now(),
|
||||||
"values": {
|
"values":values
|
||||||
"temperature": Number(data.toFixed(2)),
|
|
||||||
"status": "OK"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.send(instanceSendTo.tb, dataToTb);
|
instance.send(instanceSendTo.tb, dataToTb);
|
||||||
instance.send(instanceSendTo.di_do_controller, {sender: "gettemperature", status: "OK"});
|
instance.send(instanceSendTo.dido_controller, values);
|
||||||
|
|
||||||
counter = 0;
|
counter = 0;
|
||||||
|
|
||||||
|
|
@ -204,9 +204,8 @@ exports.install = function(instance) {
|
||||||
sendNotification("parseData", edgeName, "thermometer_sends_invalid_data", {}, "", instanceSendTo.tb, instance, "thermometer");
|
sendNotification("parseData", edgeName, "thermometer_sends_invalid_data", {}, "", instanceSendTo.tb, instance, "thermometer");
|
||||||
|
|
||||||
instance.send(instanceSendTo.debug, "[Get temperature component] - no temperature data from RVO for more than 1 day");
|
instance.send(instanceSendTo.debug, "[Get temperature component] - no temperature data from RVO for more than 1 day");
|
||||||
instance.send(instanceSendTo.di_do_controller, {sender: "gettemperature", status: "NOK"});
|
instance.send(instanceSendTo.dido_controller, {status: "NOK-thermometer"});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -216,5 +215,4 @@ exports.install = function(instance) {
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
startRead = setInterval(start, timeoutMin * 1000 * 60);
|
startRead = setInterval(start, timeoutMin * 1000 * 60);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -1,124 +1,124 @@
|
||||||
const { MD5 } = require('./md5.js');
|
const { MD5 } = require('./md5.js');
|
||||||
const { networkInterfaces } = require('os');
|
const { networkInterfaces } = require('os');
|
||||||
|
|
||||||
class ErrorToServiceHandler
|
class ErrorToServiceHandler
|
||||||
{
|
{
|
||||||
constructor() {
|
constructor() {
|
||||||
this.previousValues = {};
|
this.previousValues = {};
|
||||||
|
|
||||||
this.projects_id = undefined;
|
this.projects_id = undefined;
|
||||||
this.message_type = "error_message";
|
|
||||||
|
const nets = networkInterfaces();
|
||||||
const nets = networkInterfaces();
|
this.ipAddresses = Object.create(null); // Or just '{}', an empty object
|
||||||
this.ipAddresses = Object.create(null); // Or just '{}', an empty object
|
|
||||||
|
for (const name of Object.keys(nets)) {
|
||||||
for (const name of Object.keys(nets)) {
|
for (const net of nets[name]) {
|
||||||
for (const net of nets[name]) {
|
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
|
||||||
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
|
if (net.family === 'IPv4' && !net.internal) {
|
||||||
if (net.family === 'IPv4' && !net.internal) {
|
if (!this.ipAddresses[name]) {
|
||||||
if (!this.ipAddresses[name]) {
|
this.ipAddresses[name] = [];
|
||||||
this.ipAddresses[name] = [];
|
}
|
||||||
}
|
this.ipAddresses[name].push(net.address);
|
||||||
this.ipAddresses[name].push(net.address);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//console.log(this.ipAddresses);
|
||||||
//console.log(this.ipAddresses);
|
|
||||||
|
}
|
||||||
}
|
|
||||||
|
setProjectsId(projects_id)
|
||||||
setProjectsId(projects_id)
|
{
|
||||||
{
|
this.projects_id = projects_id;
|
||||||
this.projects_id = projects_id;
|
}
|
||||||
}
|
|
||||||
|
processMessage(message, seconds, message_type)
|
||||||
processMessage(message, seconds, message_type)
|
{
|
||||||
{
|
if(message_type == undefined) message_type = "error_message";
|
||||||
if(Array.isArray(message)) message = message.join(', ');
|
if(Array.isArray(message)) message = message.join(', ');
|
||||||
//keep in memory - default value is 1h
|
|
||||||
if (seconds === undefined) seconds = 60*60;
|
let key = MD5(message);
|
||||||
if(message_type) this.message_type = message_type;
|
let timestamp = new Date().getTime();
|
||||||
|
|
||||||
let key = MD5(message);
|
//keep in memory - default value is 1h
|
||||||
let timestamp = new Date().getTime();
|
if (seconds === undefined) seconds = 60*60;
|
||||||
|
|
||||||
if(!this.previousValues.hasOwnProperty(key))
|
if(!this.previousValues.hasOwnProperty(key))
|
||||||
{
|
{
|
||||||
this.previousValues[key] = {ts: timestamp, duration: seconds};
|
this.previousValues[key] = {ts: timestamp, duration: seconds};
|
||||||
}
|
}
|
||||||
|
|
||||||
let diff = (timestamp - this.previousValues[key].ts);
|
let diff = (timestamp - this.previousValues[key].ts);
|
||||||
if(diff < this.previousValues[key].duration*1000) return false;
|
if(diff < this.previousValues[key].duration*1000) return false;
|
||||||
|
|
||||||
this.previousValues[key].ts = timestamp;
|
this.previousValues[key].ts = timestamp;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessageToService(message, seconds, message_type)
|
sendMessageToService(message, seconds, message_type)
|
||||||
{
|
{
|
||||||
|
|
||||||
let f = this.processMessage(message, seconds, message_type);
|
let f = this.processMessage(message, seconds, message_type);
|
||||||
if(!f) return;
|
if(!f) return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//-------------
|
//-------------
|
||||||
if(message_type == undefined) message_type = "error_message";
|
if(message_type == undefined) message_type = "error_message";
|
||||||
if(Array.isArray(message)) message = message.join(', ');
|
if(Array.isArray(message)) message = message.join(', ');
|
||||||
|
|
||||||
let key = MD5(message);
|
let key = MD5(message);
|
||||||
let timestamp = new Date().getTime();
|
let timestamp = new Date().getTime();
|
||||||
|
|
||||||
//keep in memory
|
//keep in memory
|
||||||
if (seconds === undefined) seconds = 60*60;
|
if (seconds === undefined) seconds = 60*60;
|
||||||
|
|
||||||
if(!this.previousValues.hasOwnProperty(key))
|
if(!this.previousValues.hasOwnProperty(key))
|
||||||
{
|
{
|
||||||
this.previousValues[key] = {ts: timestamp, duration: seconds};
|
this.previousValues[key] = {ts: timestamp, duration: seconds};
|
||||||
}
|
}
|
||||||
|
|
||||||
let diff = (timestamp - this.previousValues[key].ts);
|
let diff = (timestamp - this.previousValues[key].ts);
|
||||||
if(diff < this.previousValues[key].duration*1000) return;
|
if(diff < this.previousValues[key].duration*1000) return;
|
||||||
|
|
||||||
this.previousValues[key].ts = timestamp;
|
this.previousValues[key].ts = timestamp;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
//send to service
|
//send to service
|
||||||
|
|
||||||
let dataToInfoSender = {id: this.projects_id};
|
let dataToInfoSender = {id: this.projects_id};
|
||||||
|
|
||||||
//js_error || error_message
|
//js_error || error_message
|
||||||
dataToInfoSender[this.message_type] = message;
|
dataToInfoSender[message_type] = message;
|
||||||
dataToInfoSender.ipAddresses = this.ipAddresses;
|
dataToInfoSender.ipAddresses = this.ipAddresses;
|
||||||
|
|
||||||
console.log("ErrorToServiceHandler------------------------>send to service", dataToInfoSender);
|
console.log("ErrorToServiceHandler------------------------>send to service", dataToInfoSender);
|
||||||
|
|
||||||
//TODO UGLY!!!
|
//TODO UGLY!!!
|
||||||
if(this.projects_id === undefined) this.projects_id = FLOW.OMS_projects_id;
|
if(this.projects_id === undefined) this.projects_id = FLOW.OMS_projects_id;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if(this.projects_id === undefined)
|
if(this.projects_id === undefined)
|
||||||
{
|
{
|
||||||
console.log("this.projects_id is undefined");
|
console.log("this.projects_id is undefined");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
RESTBuilder.make(function(builder) {
|
RESTBuilder.make(function(builder) {
|
||||||
builder.method('POST');
|
builder.method('POST');
|
||||||
builder.post(dataToInfoSender);
|
builder.post(dataToInfoSender);
|
||||||
builder.url('http://192.168.252.2:8004/sentmessage');
|
builder.url('http://192.168.252.2:8004/sentmessage');
|
||||||
|
|
||||||
builder.callback(function(err, response, output) {
|
builder.callback(function(err, response, output) {
|
||||||
console.log("process.on error send", err, response, output, dataToInfoSender);
|
console.log("process.on error send", err, response, output, dataToInfoSender);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ErrorToServiceHandler;
|
module.exports = ErrorToServiceHandler;
|
||||||
|
|
@ -1,135 +1,137 @@
|
||||||
|
|
||||||
const { promisifyBuilder, makeMapFromDbResult } = require('./db_helper.js');
|
const { promisifyBuilder, makeMapFromDbResult } = require('./db_helper.js');
|
||||||
const dbNotifications = TABLE("notifications");
|
const dbNotifications = TABLE("notifications");
|
||||||
|
|
||||||
//key is device, value = str
|
//key is device, value = str
|
||||||
let sentValues= {};
|
let sentValues= {};
|
||||||
let notificationsData = {};
|
let notificationsData = {};
|
||||||
|
|
||||||
let ERRWEIGHT = {
|
let ERRWEIGHT = {
|
||||||
EMERGENCY: "emergency", // System unusable
|
EMERGENCY: "emergency", // System unusable
|
||||||
ALERT: "alert", // Action must be taken immidiately
|
ALERT: "alert", // Action must be taken immidiately
|
||||||
CRITICAL: "critical", // Component unable to function
|
CRITICAL: "critical", // Component unable to function
|
||||||
ERROR: "error", // Error, but component able to recover from it
|
ERROR: "error", // Error, but component able to recover from it
|
||||||
WARNING: "warning", // Possibility of error, system running futher
|
WARNING: "warning", // Possibility of error, system running futher
|
||||||
NOTICE: "notice", // Significant message but not an error, things user might want to know about
|
NOTICE: "notice", // Significant message but not an error, things user might want to know about
|
||||||
INFO: "informational", // Info
|
INFO: "informational", // Info
|
||||||
DEBUG: "debug" // Debug - only if CONFIG.debug is enabled
|
DEBUG: "debug" // Debug - only if CONFIG.debug is enabled
|
||||||
};
|
};
|
||||||
|
|
||||||
function getKey(map, val) {
|
function getKey(map, val) {
|
||||||
return Object.keys(map).findItem(key => map[key] === val);
|
return Object.keys(map).findItem(key => map[key] === val);
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable
|
//https://stackoverflow.com/questions/41117799/string-interpolation-on-variable
|
||||||
var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]);
|
var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]);
|
||||||
|
|
||||||
async function initNotifications()
|
async function initNotifications()
|
||||||
{
|
{
|
||||||
let response = await promisifyBuilder(dbNotifications.find());
|
let response = await promisifyBuilder(dbNotifications.find());
|
||||||
notificationsData = makeMapFromDbResult(response, "key");
|
notificationsData = makeMapFromDbResult(response, "key");
|
||||||
|
|
||||||
console.log("initNotifications done" );
|
console.log("initNotifications done" );
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) {
|
function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) {
|
||||||
|
|
||||||
let storeToSendValues = true;
|
// return;
|
||||||
if(saveKey == undefined) storeToSendValues = false;
|
|
||||||
|
let storeToSendValues = true;
|
||||||
let lang = FLOW.OMS_language;
|
if(saveKey == undefined) storeToSendValues = false;
|
||||||
if(lang != "en" || lang != "sk") lang = "en";
|
|
||||||
|
let lang = FLOW.OMS_language;
|
||||||
let tpl = key;
|
if(lang != "en" || lang != "sk") lang = "en";
|
||||||
let weight = "";
|
|
||||||
|
let tpl = key;
|
||||||
if(notificationsData[key])
|
let weight = "";
|
||||||
{
|
|
||||||
weight = notificationsData[key].weight;
|
if(notificationsData[key])
|
||||||
weight = weight.toLowerCase();
|
{
|
||||||
|
weight = notificationsData[key].weight;
|
||||||
tpl = notificationsData[key][lang];
|
weight = weight.toLowerCase();
|
||||||
tpl = template(tpl, params);
|
|
||||||
}
|
tpl = notificationsData[key][lang];
|
||||||
else
|
tpl = template(tpl, params);
|
||||||
{
|
}
|
||||||
console.error("sendNotification: Notifications: undefined key", key, func, notificationsData);
|
else
|
||||||
return false;
|
{
|
||||||
}
|
console.error("sendNotification: Notifications: undefined key", key, func, notificationsData);
|
||||||
|
return false;
|
||||||
//detect invalid err weight
|
}
|
||||||
if(getKey(ERRWEIGHT, weight) == undefined)
|
|
||||||
{
|
//detect invalid err weight
|
||||||
console.error("sendNotification: Notifications: undefined weight", weight, key, func);
|
if(getKey(ERRWEIGHT, weight) == undefined)
|
||||||
return false;
|
{
|
||||||
}
|
console.error("sendNotification: Notifications: undefined weight", weight, key, func);
|
||||||
|
return false;
|
||||||
if(sentValues.hasOwnProperty(saveKey))
|
}
|
||||||
{
|
|
||||||
if(sentValues[saveKey] == tpl)
|
if(sentValues.hasOwnProperty(saveKey))
|
||||||
{
|
{
|
||||||
return false;
|
if(sentValues[saveKey] == tpl)
|
||||||
}
|
{
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
if(sentValues[saveKey] == undefined)
|
}
|
||||||
{
|
|
||||||
if(storeToSendValues)
|
if(sentValues[saveKey] == undefined)
|
||||||
{
|
{
|
||||||
//do not send - flow is was started
|
if(storeToSendValues)
|
||||||
sentValues[saveKey] = tpl;
|
{
|
||||||
return false;
|
//do not send - flow is was started
|
||||||
}
|
sentValues[saveKey] = tpl;
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
if(saveKey == "rvo_door")
|
}
|
||||||
{
|
|
||||||
//console.log("******", saveKey, sentValues[saveKey], tpl);
|
if(saveKey == "rvo_door")
|
||||||
}
|
{
|
||||||
|
//console.log("******", saveKey, sentValues[saveKey], tpl);
|
||||||
if(storeToSendValues) sentValues[saveKey] = tpl;
|
}
|
||||||
|
|
||||||
let str = FLOW.OMS_rvo_name;
|
if(storeToSendValues) sentValues[saveKey] = tpl;
|
||||||
if(str != "") str = str + ": ";
|
|
||||||
str = str + tpl;
|
let str = FLOW.OMS_rvo_name;
|
||||||
|
if(str != "") str = str + ": ";
|
||||||
let content = {
|
str = str + tpl;
|
||||||
"type": weight,
|
|
||||||
"status": "new",
|
let content = {
|
||||||
"source": {
|
"type": weight,
|
||||||
"func":func,
|
"status": "new",
|
||||||
"component":instance.id,
|
"source": {
|
||||||
"component_name":instance.name,
|
"func":func,
|
||||||
"edge":device
|
"component":instance.id,
|
||||||
},
|
"component_name":instance.name,
|
||||||
"message":str,
|
"edge":device
|
||||||
"message_data": extra
|
},
|
||||||
};
|
"message":str,
|
||||||
|
"message_data": extra
|
||||||
let msg = {};
|
};
|
||||||
msg[device] = [
|
|
||||||
{
|
let msg = {};
|
||||||
"ts": Date.now(),
|
msg[device] = [
|
||||||
"values": {
|
{
|
||||||
"_event":content
|
"ts": Date.now(),
|
||||||
}
|
"values": {
|
||||||
}
|
"_event":content
|
||||||
];
|
}
|
||||||
|
}
|
||||||
// Msg can be outputted from components only after configuration
|
];
|
||||||
/*if (canSendErrData()){
|
|
||||||
sendBufferedErrors();
|
// Msg can be outputted from components only after configuration
|
||||||
} else {
|
/*if (canSendErrData()){
|
||||||
bufferError(msg);
|
sendBufferedErrors();
|
||||||
}*/
|
} else {
|
||||||
instance.send(tb_output, msg); // Even if error server is unavailable, send this message to output, for other possible component connections
|
bufferError(msg);
|
||||||
|
}*/
|
||||||
return true;
|
instance.send(tb_output, msg); // Even if error server is unavailable, send this message to output, for other possible component connections
|
||||||
|
|
||||||
}
|
return true;
|
||||||
|
|
||||||
module.exports = {
|
}
|
||||||
sendNotification,
|
|
||||||
initNotifications,
|
module.exports = {
|
||||||
ERRWEIGHT
|
sendNotification,
|
||||||
|
initNotifications,
|
||||||
|
ERRWEIGHT
|
||||||
}
|
}
|
||||||
|
|
@ -22,16 +22,12 @@ exports.html = `<div class="padding">
|
||||||
|
|
||||||
exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`;
|
exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`;
|
||||||
|
|
||||||
const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js');
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
exports.install = async function(instance) {
|
exports.install = async function(instance) {
|
||||||
|
|
||||||
let id;
|
|
||||||
let allValues = {};
|
let allValues = {};
|
||||||
let dbSettings;
|
|
||||||
|
|
||||||
let sendAllValuesInterval;
|
let sendAllValuesInterval;
|
||||||
|
|
||||||
let now = new Date();
|
let now = new Date();
|
||||||
|
|
@ -52,23 +48,11 @@ exports.install = async function(instance) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
let p = path.join(__dirname + "/../databases/", 'settings.table');
|
|
||||||
if (fs.existsSync(p)) {
|
|
||||||
|
|
||||||
dbSettings = TABLE("settings");
|
|
||||||
let responseSettings = await promisifyBuilder(dbSettings.find());
|
|
||||||
id = responseSettings[0]["projects_id"];
|
|
||||||
|
|
||||||
//console.log(exports.title, responseSettings, id);
|
|
||||||
}
|
|
||||||
} catch(err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function sendValues()
|
function sendValues()
|
||||||
{
|
{
|
||||||
|
const id = FLOW.OMS_projects_id;
|
||||||
|
|
||||||
if(Object.keys(allValues).length > 0)
|
if(Object.keys(allValues).length > 0)
|
||||||
{
|
{
|
||||||
if(id !== undefined)
|
if(id !== undefined)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
336
flow/modbus_reader.js
Normal file
336
flow/modbus_reader.js
Normal file
|
|
@ -0,0 +1,336 @@
|
||||||
|
exports.id = 'modbus_reader';
|
||||||
|
exports.title = 'Modbus reader';
|
||||||
|
exports.version = '2.0.0';
|
||||||
|
exports.group = 'Worksys';
|
||||||
|
exports.color = '#2134B0';
|
||||||
|
exports.output = ["red", "white"];
|
||||||
|
exports.click = false;
|
||||||
|
exports.author = 'Rastislav Kovac';
|
||||||
|
exports.icon = 'bolt';
|
||||||
|
exports.readme = `
|
||||||
|
Modbus requests to modbus devices (electromer, twilight sensor, thermometer.
|
||||||
|
Component keeps running arround deviceConfig array in "timeoutInterval" intervals. Array items are objects with single modbus devices.
|
||||||
|
Everything is sent to dido_controller. If requests to device fail (all registers must fail to send NOK status) , we send "NOK-'device'" status to dido_controller.
|
||||||
|
This device needs to be configured in dido_controller!!! Double check if it is. In dido_controller we calculate final status and all values with status are pushed to tb.
|
||||||
|
`;
|
||||||
|
|
||||||
|
const modbus = require('jsmodbus')
|
||||||
|
const SerialPort = require('serialport')
|
||||||
|
|
||||||
|
const { timeoutInterval, deviceConfig } = require("../databases/modbus_config");
|
||||||
|
|
||||||
|
const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler');
|
||||||
|
const errorHandler = new ErrorToServiceHandler();
|
||||||
|
|
||||||
|
const { sendNotification } = require('./helper/notification_reporter');
|
||||||
|
|
||||||
|
const instanceSendTo = {
|
||||||
|
debug: 0,
|
||||||
|
dido_controller: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
//to handle NOK and OK sendNotifications s
|
||||||
|
const numberOfNotResponding = {};
|
||||||
|
let tbName = null;
|
||||||
|
|
||||||
|
|
||||||
|
exports.install = function(instance) {
|
||||||
|
|
||||||
|
class SocketWithClients {
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
this.stream = null;
|
||||||
|
this.socket = null;
|
||||||
|
this.clients = {};
|
||||||
|
this.allValues = {};
|
||||||
|
this.errors = 0;
|
||||||
|
this.index = 0;
|
||||||
|
this.timeoutInterval = 5000;
|
||||||
|
|
||||||
|
// kedze potrebujeme ist stale dookola pre jednotlive zariadenia, potrebujeme ci uz index ako aj adresu zariadenia, a aj pocet registrov na vycitanie
|
||||||
|
this.deviceAddress = null; // adresa zariadenia (1 ma EM340 a 2 ma twilight_sensor)
|
||||||
|
this.indexInDeviceConfig = 0; // prvy item v deviceConfig
|
||||||
|
this.lengthOfActualDeviceStream = null;
|
||||||
|
this.device = null;
|
||||||
|
|
||||||
|
this.startSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
startSocket = () => {
|
||||||
|
|
||||||
|
let obj = this;
|
||||||
|
|
||||||
|
this.socket = new SerialPort("/dev/ttymxc0", {
|
||||||
|
baudRate: 9600,
|
||||||
|
})
|
||||||
|
|
||||||
|
// we create a client for every deviceAddress ( = address) in list and push them into dictionary
|
||||||
|
for( let i = 0; i < deviceConfig.length; i++)
|
||||||
|
{
|
||||||
|
this.clients[deviceConfig[i].deviceAddress] = new modbus.client.RTU(this.socket, deviceConfig[i].deviceAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.socket.on('error', function(e) {
|
||||||
|
console.log('socket connection error', e);
|
||||||
|
if(e.code == 'ECONNREFUSED' || e.code == 'ECONNRESET') {
|
||||||
|
console.log(exports.title + ' Waiting 10 seconds before trying to connect again');
|
||||||
|
setTimeout(obj.startSocket, 10000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('close', function() {
|
||||||
|
console.log('Socket connection closed ' + exports.title + ' Waiting 10 seconds before trying to connect again');
|
||||||
|
setTimeout(obj.startSocket, 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('open', function () {
|
||||||
|
console.log("socket connected");
|
||||||
|
obj.getActualStreamAndDevice();
|
||||||
|
obj.timeoutInterval = timeoutInterval;
|
||||||
|
})
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
getActualStreamAndDevice = () => {
|
||||||
|
const dev = deviceConfig[this.indexInDeviceConfig];
|
||||||
|
this.index = 0;
|
||||||
|
this.errors = 0;
|
||||||
|
this.stream = dev.stream;
|
||||||
|
this.lengthOfActualDeviceStream = dev.stream.length;
|
||||||
|
this.deviceAddress = dev.deviceAddress; // 1 or 2 or any number
|
||||||
|
this.device = dev.device; //em340, twilight_sensor
|
||||||
|
|
||||||
|
if(this.indexInDeviceConfig == 0) setTimeout(this.readRegisters, this.timeoutInterval);
|
||||||
|
else setTimeout(this.readRegisters, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
readRegisters = () => {
|
||||||
|
|
||||||
|
const str = this.stream[this.index];
|
||||||
|
const register = str.register;
|
||||||
|
const size = str.size;
|
||||||
|
const tbAttribute = str.tbAttribute;
|
||||||
|
|
||||||
|
let obj = this;
|
||||||
|
|
||||||
|
this.clients[this.deviceAddress].readHoldingRegisters(register, size)
|
||||||
|
.then( function (resp) {
|
||||||
|
|
||||||
|
resp = resp.response._body.valuesAsArray; //resp is array of length 1 or 2, f.e. [2360,0]
|
||||||
|
// console.log(deviceAddress, register, tbAttribute, resp);
|
||||||
|
|
||||||
|
//device is responding again after NOK status
|
||||||
|
if(numberOfNotResponding.hasOwnProperty(obj.device))
|
||||||
|
{
|
||||||
|
let message = "";
|
||||||
|
if(obj.device == "em340")
|
||||||
|
{
|
||||||
|
message = "electrometer_ok";
|
||||||
|
}
|
||||||
|
else if(obj.device == "twilight_sensor")
|
||||||
|
{
|
||||||
|
message = "twilight_sensor_ok";
|
||||||
|
}
|
||||||
|
message && sendNotification("modbus_reader: readRegisters", tbName, message, {}, "", instanceSendTo.tb, instance);
|
||||||
|
delete numberOfNotResponding[obj.device];
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.transformResponse(resp, register, obj.deviceAddress);
|
||||||
|
|
||||||
|
obj.error = 0;
|
||||||
|
obj.index++;
|
||||||
|
|
||||||
|
if(obj.index < obj.lengthOfActualDeviceStream) setTimeout(obj.readRegisters, 0);
|
||||||
|
else obj.setNewStream();
|
||||||
|
|
||||||
|
}).catch (function () {
|
||||||
|
|
||||||
|
console.log("error pri citani modbus registra", register, obj.indexInDeviceConfig, tbName, tbAttribute);
|
||||||
|
|
||||||
|
obj.error++;
|
||||||
|
if(obj.error == obj.lengthOfActualDeviceStream)
|
||||||
|
{
|
||||||
|
instance.send(instanceSendTo.dido_controller, {status: "NOK-" + obj.device}); // NOK-em340, NOK-em111, NOK-twilight_sensor, NOK-thermometer
|
||||||
|
|
||||||
|
//todo - neposlalo notification, ked sme vypojili twilight a neposle to do tb, ale do dido ??
|
||||||
|
if(!numberOfNotResponding.hasOwnProperty(obj.device))
|
||||||
|
{
|
||||||
|
let message = "";
|
||||||
|
if(obj.device == "twilight_sensor")
|
||||||
|
{
|
||||||
|
message = "twilight_sensor_nok";
|
||||||
|
}
|
||||||
|
else if(obj.device == "em340")
|
||||||
|
{
|
||||||
|
message = "electrometer_nok";
|
||||||
|
}
|
||||||
|
message && sendNotification("modbus_reader: readingTimeouted", tbName, message, {}, "", instanceSendTo.tb, instance);
|
||||||
|
numberOfNotResponding[obj.device] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.error = 0;
|
||||||
|
numberOfNotResponding[obj.device] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(require('util').inspect(arguments, {
|
||||||
|
depth: null
|
||||||
|
}))
|
||||||
|
|
||||||
|
obj.index++;
|
||||||
|
if(obj.index < obj.lengthOfActualDeviceStream) setTimeout(obj.readRegisters, 0);
|
||||||
|
else obj.setNewStream();
|
||||||
|
})
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
transformResponse = (response, register, deviceAddress) => {
|
||||||
|
|
||||||
|
for (let i = 0; i < this.lengthOfActualDeviceStream; i++) {
|
||||||
|
|
||||||
|
let a = this.stream[i];
|
||||||
|
if (a.register === register)
|
||||||
|
{
|
||||||
|
let tbAttribute = a.tbAttribute;
|
||||||
|
let multiplier = a.multiplier;
|
||||||
|
|
||||||
|
let value = this.calculateValue(response, multiplier);
|
||||||
|
// console.log(deviceAddress, register, tbName, tbAttribute, response, a.multiplier, value);
|
||||||
|
|
||||||
|
// if(tbName == undefined) return;
|
||||||
|
|
||||||
|
if(this.index + 1 + this.errors < this.lengthOfActualDeviceStream)
|
||||||
|
{
|
||||||
|
this.allValues[tbAttribute] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const values = {
|
||||||
|
...this.allValues,
|
||||||
|
[tbAttribute]: value,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.checkNullVoltage(values);
|
||||||
|
|
||||||
|
instance.send(instanceSendTo.dido_controller, {values: values});
|
||||||
|
|
||||||
|
this.allValues = {};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setNewStream = () =>
|
||||||
|
{
|
||||||
|
// console.log('------------',this.lengthOfActualDeviceStream, this.index);
|
||||||
|
// console.log('------------',this.indexInDeviceConfig, deviceConfig.length);
|
||||||
|
if(this.lengthOfActualDeviceStream == this.index)
|
||||||
|
{
|
||||||
|
if(this.indexInDeviceConfig + 1 == deviceConfig.length)
|
||||||
|
{
|
||||||
|
this.indexInDeviceConfig = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.indexInDeviceConfig += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getActualStreamAndDevice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// sendFinalObjects = (values) =>
|
||||||
|
// {
|
||||||
|
|
||||||
|
// const date = Date.now();
|
||||||
|
// // values["status"] = "OK";
|
||||||
|
|
||||||
|
// const dataToTB = {
|
||||||
|
// [tbName]: [
|
||||||
|
// {
|
||||||
|
// "ts": date,
|
||||||
|
// "values": values
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// };
|
||||||
|
|
||||||
|
// instance.send(instanceSendTo.tb, dataToTB);
|
||||||
|
|
||||||
|
// const dataToDiDo = {
|
||||||
|
// values: values
|
||||||
|
// }
|
||||||
|
|
||||||
|
// instance.send(instanceSendTo.dido_controller, dataToDiDo);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
calculateValue = (response, multiplier) =>
|
||||||
|
{
|
||||||
|
let value = 0;
|
||||||
|
|
||||||
|
let l = response.length;
|
||||||
|
if (l === 2)
|
||||||
|
{
|
||||||
|
value = (response[1]*(2**16) + response[0]);
|
||||||
|
|
||||||
|
if(value >= (2**31)) // ak je MSB bit nastavený, eventuálne sa dá použiť aj (value & 0x80000000), ak vieš robiť logický súčin
|
||||||
|
{
|
||||||
|
value = value - "0xFFFFFFFF" + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (l === 1)
|
||||||
|
{
|
||||||
|
value = response[0];
|
||||||
|
|
||||||
|
if(value >= (2**15)) // ak je MSB bit nastavený, eventuálne sa dá použiť aj (value & 0x8000), ak vieš robiť logický súčin
|
||||||
|
{
|
||||||
|
value = value - "0xFFFF" + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.round(value * multiplier * 10) / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
checkNullVoltage = (values) => {
|
||||||
|
|
||||||
|
if(!(values.hasOwnProperty("Phase_1_voltage") || values.hasOwnProperty("Phase_2_voltage") || values.hasOwnProperty("Phase_3_voltage"))) return;
|
||||||
|
|
||||||
|
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();
|
||||||
|
// console.log(values[singleValue], tbName);
|
||||||
|
|
||||||
|
if(values[singleValue] == 0)
|
||||||
|
{
|
||||||
|
FLOW.OMS_no_voltage.add(phase);
|
||||||
|
sendNotification("modbus_citys: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", instanceSendTo.tb, instance, "voltage" + phase );
|
||||||
|
// console.log('no voltage')
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FLOW.OMS_no_voltage.delete(phase);
|
||||||
|
// console.log('voltage detected')
|
||||||
|
sendNotification("modbus_citys: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", instanceSendTo.tb, instance, "voltage" + phase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// we use dataToTbHandler. Therefore we need to check, if objects we send to dido_controller are not empty
|
||||||
|
isObjectEmpty = (objectName) => {
|
||||||
|
return Object.keys(objectName).length === 0 && objectName.constructor === Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const newSocket = new SocketWithClients();
|
||||||
|
tbName = FLOW.OMS_rvo_tbname;
|
||||||
|
}, 25000);
|
||||||
|
}
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
exports.id = 'monitorcpu';
|
|
||||||
exports.title = 'CPU';
|
|
||||||
exports.version = '1.0.0';
|
|
||||||
exports.author = 'Peter Širka';
|
|
||||||
exports.group = 'Monitoring';
|
|
||||||
exports.color = '#F6BB42';
|
|
||||||
exports.output = 1;
|
|
||||||
exports.icon = 'microchip';
|
|
||||||
exports.options = { enabled: true };
|
|
||||||
exports.click = true;
|
|
||||||
exports.readme = `# CPU monitoring
|
|
||||||
|
|
||||||
This component monitors CPU \`% percentage\` consumption in Linux systems. It uses \`mpstat\` command.
|
|
||||||
|
|
||||||
__Data Example__:
|
|
||||||
|
|
||||||
\`\`\`javascript
|
|
||||||
{
|
|
||||||
cpu: 30, // percentage
|
|
||||||
cores: [4, 60, 0], // percentage
|
|
||||||
count: 3 // count of cores
|
|
||||||
}
|
|
||||||
\`\`\``;
|
|
||||||
|
|
||||||
exports.html = `<div class="padding">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3 m">
|
|
||||||
<div data---="textbox__interval__placeholder:10000;increment:true;type:number;required:true;maxlength:10;align:center">@(Interval in milliseconds)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
exports.install = function(instance) {
|
|
||||||
|
|
||||||
var fields = ['CPU', '%idle'];
|
|
||||||
var current = { cores: [], cpu: 0, count: 0 };
|
|
||||||
var proc = null;
|
|
||||||
var tproc = null;
|
|
||||||
|
|
||||||
instance.custom.kill = function() {
|
|
||||||
if (proc) {
|
|
||||||
proc.kill('SIGKILL');
|
|
||||||
proc = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.custom.run = function() {
|
|
||||||
|
|
||||||
if (tproc) {
|
|
||||||
clearTimeout(tproc);
|
|
||||||
tproc = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.custom.kill();
|
|
||||||
proc = require('child_process').spawn('mpstat', ['-P', 'ALL', 10]);
|
|
||||||
proc.stdout.on('data', U.streamer('\n\n', instance.custom.process));
|
|
||||||
proc.stdout.on('error', function(e) {
|
|
||||||
instance.error(e);
|
|
||||||
instance.custom.kill();
|
|
||||||
tproc = setTimeout(instance.custom.run, instance.options.interval || 5000);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.custom.process = function(chunk) {
|
|
||||||
current.cpu = 0;
|
|
||||||
chunk.toString('utf8').parseTerminal(fields, instance.custom.parse);
|
|
||||||
current.count = current.cores.length;
|
|
||||||
if (current.count) {
|
|
||||||
instance.send2(current);
|
|
||||||
instance.custom.status();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.custom.parse = function(values) {
|
|
||||||
var val = 100 - values[1].parseFloat2();
|
|
||||||
if (values[0] === 'all')
|
|
||||||
current.cpu = val;
|
|
||||||
else
|
|
||||||
current.cores[+values[0]] = val;
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.custom.status = function() {
|
|
||||||
if (instance.options.enabled)
|
|
||||||
instance.status(current.cpu.floor(1) + '%');
|
|
||||||
else
|
|
||||||
instance.status('Disabled', 'red');
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.on('click', function() {
|
|
||||||
instance.options.enabled = !instance.options.enabled;
|
|
||||||
instance.custom.status();
|
|
||||||
if (instance.options.enabled)
|
|
||||||
instance.custom.run();
|
|
||||||
else
|
|
||||||
instance.custom.kill();
|
|
||||||
});
|
|
||||||
|
|
||||||
instance.on('close', function() {
|
|
||||||
instance.custom.kill();
|
|
||||||
if (tproc) {
|
|
||||||
clearTimeout(tproc);
|
|
||||||
tproc = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(instance.custom.run, 1000);
|
|
||||||
};
|
|
||||||
441
flow/mqtt.js
441
flow/mqtt.js
|
|
@ -1,441 +0,0 @@
|
||||||
exports.id = 'mqtt';
|
|
||||||
exports.title = 'MQTT broker';
|
|
||||||
exports.group = 'MQTT';
|
|
||||||
exports.color = '#888600';
|
|
||||||
exports.version = '1.0.1';
|
|
||||||
exports.icon = 'exchange';
|
|
||||||
exports.input = true;
|
|
||||||
exports.output = 0;
|
|
||||||
exports.author = 'Martin Smola';
|
|
||||||
exports.variables = true;
|
|
||||||
exports.options = { host: '127.0.0.1', port: 1883 };
|
|
||||||
exports.traffic = false;
|
|
||||||
exports.npm = ['mqtt'];
|
|
||||||
|
|
||||||
exports.html = `<div class="padding">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="host" data-jc-config="placeholder:test.mosquitto.org;required:true" class="m">Hostname or IP address</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="port" data-jc-config="placeholder:1883;required:true" class="m">Port</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="clientid">@(Client id)</div>
|
|
||||||
<div class="help m">@(Supports variables, example: \`client_{device-id}\`)</div>
|
|
||||||
<div data-jc="checkbox" data-jc-path="secure" class="m">@(Secure (ssl))</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr/>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="checkbox" data-jc-path="auth" class="m">@(Require Authorization)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" data-bind="?.auth__show:value">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="username" class="m">@(Username)</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="password" data-jc-config="type:password" class="m">@(Password)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr/>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="checkbox" data-jc-path="lwt" class="m">@(LWT)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" data-bind="?.lwt__show:value">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="lwttopic">@(Last will topic)</div>
|
|
||||||
<div class="help m">@(Supports variables, example: \`lwt/{device-id}\`)</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="lwtmessage">@(Last will message)</div>
|
|
||||||
<div class="help m">@(Supports variables, example: \`{device-id} is offline\`)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
ON('save.mqtt', function(component, options) {
|
|
||||||
!component.name && (component.name = '{0} @ {1}:{2}'.format(options.username || '', options.host, options.port || '1883'));
|
|
||||||
});
|
|
||||||
</script>`;
|
|
||||||
|
|
||||||
exports.readme = `
|
|
||||||
# MQTT Broker
|
|
||||||
|
|
||||||
## Input
|
|
||||||
Allows to change connection programaticaly
|
|
||||||
\`\`\`javascipt
|
|
||||||
{
|
|
||||||
host: '1.2.3.4',
|
|
||||||
port: '',
|
|
||||||
secure: true/false,
|
|
||||||
username: 'john',
|
|
||||||
password: 'X',
|
|
||||||
lwttopic: '',
|
|
||||||
lwtmessage: '',
|
|
||||||
clientid: ''
|
|
||||||
}
|
|
||||||
\`\`\`
|
|
||||||
`;
|
|
||||||
|
|
||||||
var MQTT_BROKERS = [];
|
|
||||||
var mqtt;
|
|
||||||
|
|
||||||
global.MQTT = {};
|
|
||||||
|
|
||||||
exports.install = function(instance) {
|
|
||||||
|
|
||||||
var broker;
|
|
||||||
|
|
||||||
mqtt = require('mqtt');
|
|
||||||
|
|
||||||
instance.on('data', function(flowdata){
|
|
||||||
var data= flowdata.data;
|
|
||||||
var options = instance.options;
|
|
||||||
|
|
||||||
if (data.host && data.port)
|
|
||||||
return instance.custom.reconfigure(data, options);
|
|
||||||
|
|
||||||
if (data.close === true)
|
|
||||||
instance.close(NOOP);
|
|
||||||
});
|
|
||||||
|
|
||||||
instance.custom.reconfigure = function(o, old_options) {
|
|
||||||
|
|
||||||
if (old_options)
|
|
||||||
MQTT_BROKERS = MQTT_BROKERS.remove(function(b){
|
|
||||||
return b.id === old_options.id;
|
|
||||||
});
|
|
||||||
|
|
||||||
var options = instance.options;
|
|
||||||
|
|
||||||
if (!options.host || !options.port) {
|
|
||||||
instance.status('Not configured', 'red');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.id = (options.username || '') + '@' + options.host + ':' + options.port;
|
|
||||||
|
|
||||||
if (broker) {
|
|
||||||
broker.close();
|
|
||||||
EMIT('mqtt.brokers.status', 'reconfigured', old_options.id, options.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.custom.createBroker();
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.custom.createBroker = function() {
|
|
||||||
|
|
||||||
ON('mqtt.brokers.status', brokerstatus);
|
|
||||||
|
|
||||||
var o = instance.options;
|
|
||||||
var opts = {
|
|
||||||
host: o.host,
|
|
||||||
port: o.port,
|
|
||||||
id: o.id,
|
|
||||||
secure: o.secure,
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
reconnectPeriod: 3000,
|
|
||||||
resubscribe: false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (o.auth) {
|
|
||||||
opts.username = o.username;
|
|
||||||
opts.password = o.password;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o.lwt) {
|
|
||||||
opts.will = {
|
|
||||||
topic: instance.arg(o.lwttopic),
|
|
||||||
payload: instance.arg(o.lwtmessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o.clientid)
|
|
||||||
opts.clientId = instance.arg(o.clientid);
|
|
||||||
|
|
||||||
broker = new Broker(opts);
|
|
||||||
MQTT_BROKERS.push(broker);
|
|
||||||
|
|
||||||
instance.status('Ready');
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.close = function(done) {
|
|
||||||
|
|
||||||
broker && broker.close(function() {
|
|
||||||
MQTT_BROKERS = MQTT_BROKERS.remove('id', instance.options.id);
|
|
||||||
EMIT('mqtt.brokers.status', 'removed', instance.options.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
OFF('mqtt.brokers.status', brokerstatus);
|
|
||||||
|
|
||||||
done();
|
|
||||||
};
|
|
||||||
|
|
||||||
function brokerstatus(status, brokerid, err) {
|
|
||||||
if (brokerid !== instance.options.id)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case 'connecting':
|
|
||||||
instance.status('Connecting', '#a6c3ff');
|
|
||||||
break;
|
|
||||||
case 'connected':
|
|
||||||
instance.status('Connected', 'green');
|
|
||||||
break;
|
|
||||||
case 'disconnected':
|
|
||||||
instance.status('Disconnected', 'red');
|
|
||||||
break;
|
|
||||||
case 'connectionfailed':
|
|
||||||
instance.status('Connection failed', 'red');
|
|
||||||
break;
|
|
||||||
case 'error':
|
|
||||||
instance.error('MQTT Error, ID: ' + instance.id + '\n ' + err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.on('options', instance.custom.reconfigure);
|
|
||||||
instance.custom.reconfigure();
|
|
||||||
};
|
|
||||||
|
|
||||||
FLOW.trigger('mqtt.brokers', function(next) {
|
|
||||||
var brokers = [''];
|
|
||||||
MQTT_BROKERS.forEach(n => brokers.push(n.id));
|
|
||||||
next(brokers);
|
|
||||||
});
|
|
||||||
|
|
||||||
MQTT.add = function(brokerid, componentid) {
|
|
||||||
var broker = MQTT_BROKERS.findItem('id', brokerid);
|
|
||||||
|
|
||||||
if (broker)
|
|
||||||
broker.add(componentid);
|
|
||||||
};
|
|
||||||
|
|
||||||
MQTT.remove = function(brokerid, componentid) {
|
|
||||||
var broker = MQTT_BROKERS.findItem('id', brokerid);
|
|
||||||
broker && broker.remove(componentid);
|
|
||||||
};
|
|
||||||
|
|
||||||
MQTT.publish = function(brokerid, topic, data, options) {
|
|
||||||
var broker = MQTT_BROKERS.findItem('id', brokerid);
|
|
||||||
if (broker)
|
|
||||||
broker.publish(topic, data, options);
|
|
||||||
else
|
|
||||||
EMIT('mqtt.brokers.status', 'error', brokerid, 'No such broker');
|
|
||||||
};
|
|
||||||
|
|
||||||
MQTT.subscribe = function(brokerid, componentid, topic, qos) {
|
|
||||||
var broker = MQTT_BROKERS.findItem('id', brokerid);
|
|
||||||
|
|
||||||
if (!broker)
|
|
||||||
return;
|
|
||||||
|
|
||||||
broker.add(componentid);
|
|
||||||
broker.subscribe(componentid, topic, qos);
|
|
||||||
};
|
|
||||||
|
|
||||||
MQTT.unsubscribe = function(brokerid, componentid, topic, qos) {
|
|
||||||
var broker = MQTT_BROKERS.findItem('id', brokerid);
|
|
||||||
if (!broker)
|
|
||||||
return;
|
|
||||||
|
|
||||||
broker.unsubscribe(componentid, topic);
|
|
||||||
broker.remove(componentid);
|
|
||||||
};
|
|
||||||
|
|
||||||
MQTT.broker = function(brokerid) {
|
|
||||||
return MQTT_BROKERS.findItem('id', brokerid);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
https://github.com/mqttjs/MQTT.js/blob/master/examples/client/secure-client.js
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO
|
|
||||||
|
|
||||||
- add `birth` and `last will and testament` messages
|
|
||||||
- add options to self.client.connect(broker [,options]); - credentials, certificate etc.
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Broker(options) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (!options.host || !options.port)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
self.connecting = false;
|
|
||||||
self.connected = false;
|
|
||||||
self.closing = false;
|
|
||||||
self.components = [];
|
|
||||||
self.subscribtions = {};
|
|
||||||
self.id = options.id;
|
|
||||||
self.options = options;
|
|
||||||
setTimeout(function() {
|
|
||||||
EMIT('mqtt.brokers.status', 'new', self.id);
|
|
||||||
}, 500);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
Broker.prototype.connect = function() {
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
if (self.connected || self.connecting)
|
|
||||||
return EMIT('mqtt.brokers.status', self.connected ? 'connected' : 'connecting', self.id);
|
|
||||||
|
|
||||||
self.connecting = true;
|
|
||||||
var broker = self.options.secure ? 'mqtts://' : 'mqtt://' + self.options.host + ':' + self.options.port;
|
|
||||||
|
|
||||||
EMIT('mqtt.brokers.status', 'connecting', self.id);
|
|
||||||
|
|
||||||
self.client = mqtt.connect(broker, self.options);
|
|
||||||
|
|
||||||
self.client.on('connect', function() {
|
|
||||||
self.connecting = false;
|
|
||||||
self.connected = true;
|
|
||||||
if (self.reconnecting) {
|
|
||||||
EMIT('mqtt.brokers.status', 'reconnected', self.id);
|
|
||||||
self.reconnecting = false;
|
|
||||||
self.resubscribe();
|
|
||||||
}
|
|
||||||
EMIT('mqtt.brokers.status', 'connected', self.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.client.on('reconnect', function() {
|
|
||||||
self.connecting = true;
|
|
||||||
self.connected = false;
|
|
||||||
self.reconnecting = true;
|
|
||||||
EMIT('mqtt.brokers.status', 'connecting', self.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.client.on('message', function(topic, message) {
|
|
||||||
message = message.toString();
|
|
||||||
if (message[0] === '{') {
|
|
||||||
TRY(function() {
|
|
||||||
message = JSON.parse(message);
|
|
||||||
}, () => FLOW.debug('MQTT: Error parsing data', message));
|
|
||||||
}
|
|
||||||
EMIT('mqtt.brokers.message', self.id, topic, message);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.client.on('close', function(err) {
|
|
||||||
if (err && err.toString().indexOf('Error')) {
|
|
||||||
self.connecting = false;
|
|
||||||
self.connected = false;
|
|
||||||
EMIT('mqtt.brokers.status', 'error', self.id, err.code);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.connected || !self.connecting) {
|
|
||||||
self.connected = false;
|
|
||||||
EMIT('mqtt.brokers.status', 'disconnected', self.id);
|
|
||||||
} else if (self.connecting) {
|
|
||||||
self.connecting = false;
|
|
||||||
EMIT('mqtt.brokers.status', 'connectionfailed', self.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
self.client.on('error', function(err) {
|
|
||||||
|
|
||||||
if (self.connecting) {
|
|
||||||
self.client.end();
|
|
||||||
self.connecting = false;
|
|
||||||
EMIT('mqtt.brokers.status', 'error', self.id, err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Broker.prototype.disconnect = function(reconnect) {
|
|
||||||
var self = this;
|
|
||||||
if (!self.closing)
|
|
||||||
self.close(function(){
|
|
||||||
reconnect && self.connect();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Broker.prototype.close = function(callback) {
|
|
||||||
var self = this;
|
|
||||||
self.closing = true;
|
|
||||||
|
|
||||||
if ((self.connected || self.connecting) && self.client && self.client.end)
|
|
||||||
self.client.end(true, cb);
|
|
||||||
else
|
|
||||||
cb();
|
|
||||||
|
|
||||||
function cb() {
|
|
||||||
EMIT('mqtt.brokers.status', 'disconnected', self.id);
|
|
||||||
self.client && self.client.removeAllListeners();
|
|
||||||
self.components = [];
|
|
||||||
self.client = null;
|
|
||||||
callback && callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Broker.prototype.subscribe = function(componentid, topic) {
|
|
||||||
var self = this;
|
|
||||||
self.subscribtions[topic] = self.subscribtions[topic] || [];
|
|
||||||
if (self.subscribtions[topic].indexOf(componentid) > -1)
|
|
||||||
return;
|
|
||||||
self.client.subscribe(topic);
|
|
||||||
self.subscribtions[topic].push(componentid);
|
|
||||||
};
|
|
||||||
|
|
||||||
Broker.prototype.resubscribe = function() {
|
|
||||||
var self = this;
|
|
||||||
var topics = Object.keys(self.subscribtions);
|
|
||||||
for (var i = 0; i < topics.length; i++)
|
|
||||||
self.client.subscribe(topics[i]);
|
|
||||||
};
|
|
||||||
|
|
||||||
Broker.prototype.unsubscribe = function(componentid, topic) {
|
|
||||||
var self = this;
|
|
||||||
var sub = self.subscribtions[topic];
|
|
||||||
if (sub) {
|
|
||||||
self.subscribtions[topic] = sub.remove(componentid);
|
|
||||||
self.client.connected && !self.subscribtions[topic].length && self.client.unsubscribe(topic);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Broker.prototype.publish = function(topic, data, options) {
|
|
||||||
var self = this;
|
|
||||||
if (!self.connected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (typeof(data) === 'object') {
|
|
||||||
options.qos = parseInt(data.qos || options.qos);
|
|
||||||
options.retain = data.retain || options.retain;
|
|
||||||
topic = data.topic || topic;
|
|
||||||
data.payload && (data = typeof(data.payload) === 'string' ? data.payload : JSON.stringify(data.payload));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.qos !== 0 || options.qos !== 1 || options.qos !== 2)
|
|
||||||
options.qos = null;
|
|
||||||
|
|
||||||
if (typeof(data) !== 'string')
|
|
||||||
data = JSON.stringify(data);
|
|
||||||
|
|
||||||
self.client.publish(topic, data || '', options);
|
|
||||||
};
|
|
||||||
|
|
||||||
Broker.prototype.add = function(componentid) {
|
|
||||||
var self = this;
|
|
||||||
self.components.indexOf(componentid) === -1 && self.components.push(componentid);
|
|
||||||
self.connect();
|
|
||||||
};
|
|
||||||
|
|
||||||
Broker.prototype.remove = function(componentid) {
|
|
||||||
var self = this;
|
|
||||||
self.components = self.components.remove(componentid);
|
|
||||||
!self.components.length && self.disconnect();
|
|
||||||
};
|
|
||||||
|
|
@ -1,171 +0,0 @@
|
||||||
exports.id = 'mqttlistener';
|
|
||||||
exports.title = 'MQTT listener';
|
|
||||||
exports.group = 'MQTT';
|
|
||||||
exports.color = '#888600';
|
|
||||||
exports.version = '1.0.0';
|
|
||||||
exports.icon = 'sign-out';
|
|
||||||
exports.input = 1;
|
|
||||||
exports.output = ["red", "white"];
|
|
||||||
exports.author = 'Rastislav Kovac';
|
|
||||||
exports.options = { host: "", port: 1883, clientid: "", username: "" };
|
|
||||||
//exports.npm = ['mqtt', 'streamroller'];
|
|
||||||
|
|
||||||
|
|
||||||
exports.html = `<div class="padding">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="host" data-jc-config="placeholder:test.mosquitto.org;required:false" class="m">Hostname or IP address</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="port" data-jc-config="placeholder:1883;required:true" class="m">Port</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="clientid">@(Client id)</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div data-jc="textbox" data-jc-path="username" class="m">@(Username)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
|
|
||||||
exports.readme = `
|
|
||||||
# MQTT processor
|
|
||||||
|
|
||||||
Version 1.0.0
|
|
||||||
|
|
||||||
It serves as a client and subscribes to 'rpc' topic. It receives rpc calls from kovobel-prod01, which receives it from platform.
|
|
||||||
|
|
||||||
`;
|
|
||||||
|
|
||||||
const instanceSendTo = {
|
|
||||||
debug: 0,
|
|
||||||
rpcCall: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exports.install = function(instance) {
|
|
||||||
|
|
||||||
|
|
||||||
const mqtt = require("mqtt");
|
|
||||||
|
|
||||||
instance.on('options', loadNodes);
|
|
||||||
|
|
||||||
|
|
||||||
function loadNodes()
|
|
||||||
{
|
|
||||||
|
|
||||||
if(instance.options.host == "")
|
|
||||||
{
|
|
||||||
instance.status('No configuration', 'red');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var o = instance.options;
|
|
||||||
opts = {
|
|
||||||
host: o.host,
|
|
||||||
port: o.port,
|
|
||||||
clientId: o.clientid,
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
resubscribe: true
|
|
||||||
};
|
|
||||||
|
|
||||||
connectToServer();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function connectToServer()
|
|
||||||
{
|
|
||||||
var url = "mqtt://" + opts.host + ":" + opts.port;
|
|
||||||
console.log("MQTT URL: ", url);
|
|
||||||
|
|
||||||
client = mqtt.connect(url, opts);
|
|
||||||
|
|
||||||
client.on('connect', function() {
|
|
||||||
instance.status("Connected", "green");
|
|
||||||
client.subscribe('rpc', function (err) {
|
|
||||||
if (!err) {
|
|
||||||
client.publish('rpc', 'Hello mqtt');
|
|
||||||
console.log('message published');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('reconnect', function() {
|
|
||||||
instance.status("Reconnecting", "yellow");
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('message', function(topic, message) {
|
|
||||||
// message is type of buffer
|
|
||||||
message = message.toString();
|
|
||||||
|
|
||||||
// instance.send(1, message);
|
|
||||||
// return;
|
|
||||||
|
|
||||||
if (message[0] === '{') {
|
|
||||||
|
|
||||||
try {
|
|
||||||
message = JSON.parse(message);
|
|
||||||
|
|
||||||
if (Object.keys(message).length < 2 || !Object.keys(message).includes("message")) return;
|
|
||||||
|
|
||||||
message.message = JSON.parse(message.message);
|
|
||||||
instance.send(instanceSendTo.rpcCall, message);
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
instance.debug(`MQTT: Error parsing data, ${e}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('close', function(err) {
|
|
||||||
if (err && err.toString().indexOf('Error')) {
|
|
||||||
instance.status("Err: "+err.code, "red");
|
|
||||||
instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts });
|
|
||||||
} else {
|
|
||||||
instance.status("Disconnected", "red");
|
|
||||||
instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', function(err) {
|
|
||||||
instance.status("Err: "+ err.code, "red");
|
|
||||||
instance.send(instanceSendTo.debug, {"message":"Broker ERROR signal received !", "error":err, "opt":opts });
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//set opts accortding to options
|
|
||||||
instance.reconfigure = function() {
|
|
||||||
|
|
||||||
var o = instance.options;
|
|
||||||
opts = {
|
|
||||||
host: o.host,
|
|
||||||
port: o.port,
|
|
||||||
clientId: o.clientid,
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
resubscribe: true
|
|
||||||
};
|
|
||||||
|
|
||||||
connectToServer();
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.close = function(done) {
|
|
||||||
client.end();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
loadNodes();
|
|
||||||
|
|
||||||
instance.on('options', instance.reconfigure);
|
|
||||||
instance.reconfigure();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
exports.id = 'mqttpublish';
|
|
||||||
exports.title = 'MQTT publish';
|
|
||||||
exports.group = 'MQTT';
|
|
||||||
exports.color = '#888600';
|
|
||||||
exports.version = '1.1.0';
|
|
||||||
exports.icon = 'sign-out';
|
|
||||||
exports.input = true;
|
|
||||||
exports.output = 1;
|
|
||||||
exports.author = 'Martin Smola';
|
|
||||||
exports.options = {};
|
|
||||||
|
|
||||||
exports.html = `<div class="padding">
|
|
||||||
<div data-jc="dropdown" data-jc-path="broker" data-jc-config="datasource:mqttconfig.brokers;required:true" class="m">@(Brokers)</div>
|
|
||||||
<div data-jc="textbox" data-jc-path="topic" data-jc-config="placeholder:hello/world">Topic</div>
|
|
||||||
<div class="help m">@(Supports variables, example: \`device/{device-id}\`)</div>
|
|
||||||
<div data-jc="textbox" data-jc-path="staticmessage" data-jc-config="placeholder:123">Static message(string)</div>
|
|
||||||
<div class="help m">@(Supports variables), @(If specified then incoming data are ignored and this message is sent instead. Topic is required if static message is defined.)</div>
|
|
||||||
<div data-jc="dropdown" data-jc-path="qos" data-jc-config="items:,0,1,2" class="m">@(QoS)</div>
|
|
||||||
<div data-jc="checkbox" data-jc-path="retain" class="m">@(Retain)</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
var mqttconfig = { brokers: [] };
|
|
||||||
ON('open.mqttpublish', function(component, options) {
|
|
||||||
TRIGGER('mqtt.brokers', 'mqttconfig.brokers');
|
|
||||||
});
|
|
||||||
ON('save.mqttpublish', function(component, options) {
|
|
||||||
!component.name && (component.name = options.broker + (options.topic ? ' -> ' + options.topic : ''));
|
|
||||||
});
|
|
||||||
</script>`;
|
|
||||||
|
|
||||||
exports.readme = `# MQTT publish
|
|
||||||
|
|
||||||
If the topic field is left empty and the data object does not have a 'topic' property then nothing is send.
|
|
||||||
Also if data object has a valid topic property it is assumed the object also have data property which is send as a payload;
|
|
||||||
Example:
|
|
||||||
\`\`\`javacsript
|
|
||||||
{
|
|
||||||
topic: '/topic',
|
|
||||||
data: {
|
|
||||||
hello: 'world'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// in above case only { hello: 'world' } is published
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
If the topic field is not empty then the entire incomming data object is passed to the output.`;
|
|
||||||
|
|
||||||
|
|
||||||
exports.install = function(instance) {
|
|
||||||
|
|
||||||
var PUBLISH_OPTIONS = {};
|
|
||||||
|
|
||||||
var ready = false;
|
|
||||||
|
|
||||||
instance.custom.reconfigure = function() {
|
|
||||||
|
|
||||||
ready = false;
|
|
||||||
|
|
||||||
if (!MQTT.broker(instance.options.broker))
|
|
||||||
return instance.status('No broker', 'red');
|
|
||||||
|
|
||||||
if (instance.options.broker) {
|
|
||||||
|
|
||||||
MQTT.add(instance.options.broker, instance.id);
|
|
||||||
ready = true;
|
|
||||||
PUBLISH_OPTIONS.retain = instance.options.retain || false;
|
|
||||||
PUBLISH_OPTIONS.qos = parseInt(instance.options.qos || 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.status('Not configured', 'red');
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.on('options', instance.custom.reconfigure);
|
|
||||||
|
|
||||||
instance.on('data', function(flowdata) {
|
|
||||||
if (!ready)
|
|
||||||
return;
|
|
||||||
var msg = instance.options.staticmessage ? instance.arg(instance.options.staticmessage) : flowdata.data;
|
|
||||||
var topic = instance.arg(instance.options.topic || msg.topic);
|
|
||||||
if (topic) {
|
|
||||||
if (msg.topic)
|
|
||||||
msg = msg.data;
|
|
||||||
MQTT.publish(instance.options.broker, topic, msg, PUBLISH_OPTIONS);
|
|
||||||
} else
|
|
||||||
instance.debug('MQTT publish no topic');
|
|
||||||
|
|
||||||
instance.send(flowdata);
|
|
||||||
});
|
|
||||||
|
|
||||||
instance.on('close', function() {
|
|
||||||
MQTT.remove(instance.options.broker, instance.id);
|
|
||||||
OFF('mqtt.brokers.status', instance.custom.brokerstatus);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
instance.custom.brokerstatus = function(status, brokerid, msg) {
|
|
||||||
if (brokerid !== instance.options.broker)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case 'connecting':
|
|
||||||
instance.status('Connecting', '#a6c3ff');
|
|
||||||
break;
|
|
||||||
case 'connected':
|
|
||||||
instance.status('Connected', 'green');
|
|
||||||
break;
|
|
||||||
case 'disconnected':
|
|
||||||
instance.status('Disconnected', 'red');
|
|
||||||
break;
|
|
||||||
case 'connectionfailed':
|
|
||||||
instance.status('Connection failed', 'red');
|
|
||||||
break;
|
|
||||||
case 'new':
|
|
||||||
!ready && instance.custom.reconfigure();
|
|
||||||
break;
|
|
||||||
case 'removed':
|
|
||||||
instance.custom.reconfigure();
|
|
||||||
break;
|
|
||||||
case 'error':
|
|
||||||
instance.status(msg, 'red');
|
|
||||||
break;
|
|
||||||
case 'reconfigured':
|
|
||||||
instance.options.broker = msg;
|
|
||||||
instance.reconfig();
|
|
||||||
instance.custom.reconfigure();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ON('mqtt.brokers.status', instance.custom.brokerstatus);
|
|
||||||
|
|
||||||
instance.custom.reconfigure();
|
|
||||||
};
|
|
||||||
|
|
@ -1,168 +0,0 @@
|
||||||
exports.id = 'mqttsubscribe';
|
|
||||||
exports.title = 'MQTT subscribe';
|
|
||||||
exports.group = 'MQTT';
|
|
||||||
exports.color = '#888600';
|
|
||||||
exports.version = '1.1.0';
|
|
||||||
exports.icon = 'sign-in';
|
|
||||||
exports.output = 1;
|
|
||||||
exports.variables = true;
|
|
||||||
exports.author = 'Martin Smola';
|
|
||||||
exports.options = {};
|
|
||||||
|
|
||||||
exports.html = `<div class="padding">
|
|
||||||
<div data-jc="dropdown" data-jc-path="broker" data-jc-config="datasource:mqttconfig.brokers;required:true" class="m">@(Select a broker)</div>
|
|
||||||
<div data-jc="textbox" data-jc-path="topic" data-jc-config="placeholder:hello/world;required:true">Topic</div>
|
|
||||||
<div class="help m">@(Supports variables, example: \`device/{device-id}\`)</div>
|
|
||||||
<div data-jc="dropdown" data-jc-path="qos" data-jc-config="items:,0,1,2" class="m">@(QoS)</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
var mqttconfig = { brokers: [] };
|
|
||||||
ON('open.mqttsubscribe', function(component, options) {
|
|
||||||
TRIGGER('mqtt.brokers', 'mqttconfig.brokers');
|
|
||||||
});
|
|
||||||
ON('save.mqttsubscribe', function(component, options) {
|
|
||||||
!component.name && (component.name = options.broker + (options.topic ? ' -> ' + options.topic : ''));
|
|
||||||
});
|
|
||||||
</script>`;
|
|
||||||
|
|
||||||
exports.readme = `
|
|
||||||
# MQTT subscribe
|
|
||||||
|
|
||||||
The data recieved are passed to the output as follows:
|
|
||||||
\`\`\`javascript
|
|
||||||
{
|
|
||||||
topic: '/lights/on',
|
|
||||||
data: 'kitchen'
|
|
||||||
}
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
If the topic is wildcard then there's an array of matches in flowdata repository which can be used in Function component like so:
|
|
||||||
\`\`\`javascript
|
|
||||||
// wildcard -> /+/status
|
|
||||||
// topic -> /devicename/status
|
|
||||||
|
|
||||||
var match = flowdata.get('mqtt_wildcard');
|
|
||||||
// match === ['devicename']
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
More on wildcard topics [here](https://mosquitto.org/man/mqtt-7.html)
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports.install = function(instance) {
|
|
||||||
|
|
||||||
var old_topic;
|
|
||||||
var ready = false;
|
|
||||||
|
|
||||||
instance.custom.reconfigure = function(o, old_options) {
|
|
||||||
|
|
||||||
|
|
||||||
ready = false;
|
|
||||||
|
|
||||||
if (!MQTT.broker(instance.options.broker))
|
|
||||||
return instance.status('No broker', 'red');
|
|
||||||
|
|
||||||
if (instance.options.broker && instance.options.topic) {
|
|
||||||
|
|
||||||
if (old_topic)
|
|
||||||
MQTT.unsubscribe(instance.options.broker, instance.id, old_topic);
|
|
||||||
|
|
||||||
old_topic = instance.arg(instance.options.topic);
|
|
||||||
MQTT.subscribe(instance.options.broker, instance.id, old_topic);
|
|
||||||
ready = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.status('Not configured', 'red');
|
|
||||||
};
|
|
||||||
|
|
||||||
instance.on('options', instance.custom.reconfigure);
|
|
||||||
|
|
||||||
instance.on('close', function() {
|
|
||||||
MQTT.unsubscribe(instance.options.broker, instance.id, instance.options.topic);
|
|
||||||
OFF('mqtt.brokers.message', instance.custom.message);
|
|
||||||
OFF('mqtt.brokers.status', instance.custom.brokerstatus);
|
|
||||||
});
|
|
||||||
|
|
||||||
instance.custom.brokerstatus = function(status, brokerid, msg) {
|
|
||||||
if (brokerid !== instance.options.broker)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case 'connecting':
|
|
||||||
instance.status('Connecting', '#a6c3ff');
|
|
||||||
break;
|
|
||||||
case 'connected':
|
|
||||||
instance.status('Connected', 'green');
|
|
||||||
break;
|
|
||||||
case 'disconnected':
|
|
||||||
instance.status('Disconnected', 'red');
|
|
||||||
break;
|
|
||||||
case 'connectionfailed':
|
|
||||||
instance.status('Connection failed', 'red');
|
|
||||||
break;
|
|
||||||
case 'new':
|
|
||||||
!ready && instance.custom.reconfigure();
|
|
||||||
break;
|
|
||||||
case 'removed':
|
|
||||||
instance.custom.reconfigure();
|
|
||||||
break;
|
|
||||||
case 'error':
|
|
||||||
instance.status(msg, 'red');
|
|
||||||
break;
|
|
||||||
case 'reconfigured':
|
|
||||||
instance.options.broker = msg;
|
|
||||||
instance.reconfig();
|
|
||||||
instance.custom.reconfigure();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.custom.message = function(brokerid, topic, message) {
|
|
||||||
if (brokerid !== instance.options.broker)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var match = mqttWildcard(topic, old_topic);
|
|
||||||
if (match) {
|
|
||||||
var flowdata = instance.make({ topic: topic, data: message })
|
|
||||||
flowdata.set('mqtt_wildcard', match);
|
|
||||||
instance.send2(flowdata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ON('mqtt.brokers.message', instance.custom.message);
|
|
||||||
ON('mqtt.brokers.status', instance.custom.brokerstatus);
|
|
||||||
|
|
||||||
instance.custom.reconfigure();
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://github.com/hobbyquaker/mqtt-wildcard
|
|
||||||
function mqttWildcard(topic, wildcard) {
|
|
||||||
if (topic === wildcard) {
|
|
||||||
return [];
|
|
||||||
} else if (wildcard === '#') {
|
|
||||||
return [topic];
|
|
||||||
}
|
|
||||||
|
|
||||||
var res = [];
|
|
||||||
|
|
||||||
var t = String(topic).split('/');
|
|
||||||
var w = String(wildcard).split('/');
|
|
||||||
|
|
||||||
var i = 0;
|
|
||||||
for (var lt = t.length; i < lt; i++) {
|
|
||||||
if (w[i] === '+') {
|
|
||||||
res.push(t[i]);
|
|
||||||
} else if (w[i] === '#') {
|
|
||||||
res.push(t.slice(i).join('/'));
|
|
||||||
return res;
|
|
||||||
} else if (w[i] !== t[i]) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (w[i] === '#') {
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (i === w.length) ? res : null;
|
|
||||||
}
|
|
||||||
191
flow/nosql.js
191
flow/nosql.js
|
|
@ -1,191 +0,0 @@
|
||||||
exports.id = 'nosql';
|
|
||||||
exports.title = 'NoSQL';
|
|
||||||
exports.version = '1.2.1';
|
|
||||||
exports.group = 'Databases';
|
|
||||||
exports.author = 'Martin Smola';
|
|
||||||
exports.color = '#D770AD';
|
|
||||||
exports.icon = 'database';
|
|
||||||
exports.input = true;
|
|
||||||
exports.output = 2;
|
|
||||||
exports.options = {};
|
|
||||||
exports.readme = `# NoSQL embedded
|
|
||||||
|
|
||||||
## Outputs
|
|
||||||
|
|
||||||
First output is response from nosql engine and second is the data passed in.
|
|
||||||
|
|
||||||
## Collection
|
|
||||||
|
|
||||||
if the collection field is left empty, then we try to look at \`flowdata.get('collection')\`, to set this value you need to use \`flowdata.set('collection', '<collection-name>')\` in previous component (currently only \`function\` can be used)
|
|
||||||
|
|
||||||
## Insert
|
|
||||||
|
|
||||||
- will insert recieved data
|
|
||||||
- expects data to be an Object
|
|
||||||
- returns error, success, id
|
|
||||||
|
|
||||||
## Read
|
|
||||||
|
|
||||||
- will read a document by id
|
|
||||||
- expects data to be an Object with an \`id\` property
|
|
||||||
- returns error, response
|
|
||||||
|
|
||||||
## Update
|
|
||||||
|
|
||||||
- will update document by id
|
|
||||||
- expects data to be an Object with \`id\` property and all the props to be updated
|
|
||||||
- returns error, response
|
|
||||||
- if response is 0 then update failed
|
|
||||||
|
|
||||||
## Remove
|
|
||||||
|
|
||||||
- will remove document by id
|
|
||||||
- expects data to be an Object with an \`id\` property
|
|
||||||
- returns error, response
|
|
||||||
- if response is 0 then remove failed
|
|
||||||
|
|
||||||
## Query
|
|
||||||
|
|
||||||
- will query DB
|
|
||||||
- expects data to be an Array as shown bellow
|
|
||||||
- returns error, response
|
|
||||||
|
|
||||||
\`\`\`javascript
|
|
||||||
[
|
|
||||||
['where', 'sensor', 'temp'], // builder.where('sensor', 'temp');
|
|
||||||
['limit', 2] // builder.limit(2);
|
|
||||||
]
|
|
||||||
\`\`\``;
|
|
||||||
|
|
||||||
exports.html = `
|
|
||||||
<div class="padding">
|
|
||||||
<div data-jc="textbox" data-jc-path="collection" class="m mt10">DB collection name</div>
|
|
||||||
<div data-jc="dropdown" data-jc-path="method" data-jc-config="required:true;items:insert,update,read,query,remove" class="m">@(Method)</div>
|
|
||||||
<div data-jc="visible" data-jc-path="method" data-jc-config="if:value === 'insert'">
|
|
||||||
<div data-jc="checkbox" data-jc-path="addid">Add unique ID to data before insert</div>
|
|
||||||
</div>
|
|
||||||
<div data-jc="visible" data-jc-path="method" data-jc-config="if:value === 'update'">
|
|
||||||
<div data-jc="checkbox" data-jc-path="upsert">Insert document if it doesn't exist</div>
|
|
||||||
<div data-jc="checkbox" data-jc-path="upsertid">Add unique ID to data before insert (only if it doesn't exist)</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
exports.install = function(instance) {
|
|
||||||
|
|
||||||
instance.on('data', function(flowdata, next) {
|
|
||||||
|
|
||||||
instance.send2(1, flowdata.clone());
|
|
||||||
|
|
||||||
var options = instance.options;
|
|
||||||
var collection = options.collection || flowdata.get('collection');
|
|
||||||
if (!collection) {
|
|
||||||
flowdata.data = { err: '[DB] No collection specified' };
|
|
||||||
next(0, flowdata);
|
|
||||||
instance.error('[DB] No collection specified');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var nosql = NOSQL(collection);
|
|
||||||
var builder;
|
|
||||||
|
|
||||||
if (options.method === 'read') {
|
|
||||||
|
|
||||||
if (!flowdata.data.id) {
|
|
||||||
flowdata.data = { err: '[DB] Cannot get record by id: `undefined`' };
|
|
||||||
next(0, flowdata);
|
|
||||||
instance.error('[DB] Cannot get record by id: `undefined`');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder = nosql.find();
|
|
||||||
builder.where('id', flowdata.data.id);
|
|
||||||
builder.first();
|
|
||||||
builder.callback(function(err, response) {
|
|
||||||
if (err) {
|
|
||||||
instance.throw(err);
|
|
||||||
} else {
|
|
||||||
flowdata.data = { response: response };
|
|
||||||
next(0, flowdata);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.method === 'insert') {
|
|
||||||
|
|
||||||
options.addid && (flowdata.data.id = UID());
|
|
||||||
nosql.insert(flowdata.data).callback(function(err) {
|
|
||||||
if (err)
|
|
||||||
instance.throw(err);
|
|
||||||
else {
|
|
||||||
flowdata.data = { success: err ? false : true, id: flowdata.data.id };
|
|
||||||
next(0, flowdata);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.method === 'query') {
|
|
||||||
|
|
||||||
var query = flowdata.data;
|
|
||||||
builder = nosql.find();
|
|
||||||
|
|
||||||
query && query instanceof Array && query.forEach(function(q) {
|
|
||||||
if (q instanceof Array) {
|
|
||||||
var m = q[0];
|
|
||||||
var args = q.splice(1);
|
|
||||||
builder[m] && (builder[m].apply(builder, args));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.callback(function(err, response) {
|
|
||||||
if (err) {
|
|
||||||
instance.throw(err);
|
|
||||||
} else {
|
|
||||||
flowdata.data = { response: response || [] };
|
|
||||||
next(0, flowdata);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.method === 'update') {
|
|
||||||
|
|
||||||
if (!options.upsert && !flowdata.data.id) {
|
|
||||||
flowdata.data = { err: '[DB] Cannot update record by id: `undefined`' };
|
|
||||||
next(0, flowdata);
|
|
||||||
instance.error('[DB] Cannot update record by id: `undefined`');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.upsert && (options.upsertid && !flowdata.data.id)) {
|
|
||||||
flowdata.data.id = UID();
|
|
||||||
builder = nosql.modify(flowdata.data, options.upsert);
|
|
||||||
builder.where('id', flowdata.data.id);
|
|
||||||
builder.callback(function(err, count) {
|
|
||||||
if (err)
|
|
||||||
instance.throw(err);
|
|
||||||
else {
|
|
||||||
flowdata.data = { response: count || 0 };
|
|
||||||
next(0, flowdata);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (options.method === 'remove') {
|
|
||||||
|
|
||||||
if (!flowdata.data.id) {
|
|
||||||
flowdata.data = { err: '[DB] Cannot remove record by id: `undefined`' };
|
|
||||||
next(0, flowdata);
|
|
||||||
instance.error('[DB] Cannot remove record by id: `undefined`');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder = nosql.remove();
|
|
||||||
builder.where('id', flowdata.data.id);
|
|
||||||
builder.callback(function(err, count) {
|
|
||||||
if (err)
|
|
||||||
instance.throw(err);
|
|
||||||
else {
|
|
||||||
flowdata.data = { response: count || 0 };
|
|
||||||
next(0, flowdata);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
357
flow/relays.js
357
flow/relays.js
|
|
@ -1,357 +0,0 @@
|
||||||
exports.id = 'relay';
|
|
||||||
exports.title = 'DI_DO_Controller';
|
|
||||||
exports.version = '1.0.0';
|
|
||||||
exports.group = 'Worksys';
|
|
||||||
exports.color = '#2134B0';
|
|
||||||
exports.input = 1;
|
|
||||||
exports.output = ["red", "white", "yellow"];
|
|
||||||
exports.click = false;
|
|
||||||
exports.author = 'Daniel Segeš';
|
|
||||||
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 = `# Sets RS232 port and all digital pins on device. Then it starts to receive data from sensors.
|
|
||||||
It receives:
|
|
||||||
|
|
||||||
rotary_switch_state,
|
|
||||||
rotary_switch_state,
|
|
||||||
door_condition,
|
|
||||||
state_of_breaker,
|
|
||||||
state_of_contactor,
|
|
||||||
twilight_sensor
|
|
||||||
`;
|
|
||||||
|
|
||||||
/*
|
|
||||||
we open rsPort "/dev/ttymxc0" and set digital input and output pins with "setRSPortData"
|
|
||||||
Currently we are interested in pins no. 1,2,3,6,8,9,10,16
|
|
||||||
pins number 11, 12, 13 (we receive 10,11,12 in rsPortReceivedData) are "stykace"
|
|
||||||
When port receives data, it must be exactly 4 bytes long. Second byte is pin, that changed its value, fourth byte is value itself.
|
|
||||||
After that, we set this value to "previousValues[allPins[whichpin]]" variable
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
RVO objekt:
|
|
||||||
state_of_main_switch - sem sa bude reportovať stav hlavného ističa : 0-> off 1-> on (toto nie je na platforme, ale Rado to už do entity type doplnil)
|
|
||||||
rotary_switch_state - sem by sa mal reportovať stav vstupov manual a auto podľa nasledovnej logiky:
|
|
||||||
Manual = 1 a Auto = 0 -> vyreportuje Manual
|
|
||||||
Manual = 0 a Auto = 0 -> vyreportuje Off
|
|
||||||
Manual = 0 a Auto = 1 -> vyreportuje Automatic
|
|
||||||
|
|
||||||
door_condition - tuto ide pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Open
|
|
||||||
twilight_sensor - hodnotu, ktorú vracia ten analógový vstup (17) treba poslať sem ako float number. Zrejme tu potom pridáme nejaký koeficient prevodu na luxy
|
|
||||||
|
|
||||||
zjavne nám v jsone chýba stav hlavného ističa. Musíme to potom doplniť
|
|
||||||
|
|
||||||
Na každú líniu:
|
|
||||||
state_of_breaker - podľa indexu ističa sa reportuje jeho stav, teda istič 1 na líniu 1: 0-> off 1-> on
|
|
||||||
state_of_contactor - podľa indexu stykača sa reportuje jeho stav, teda stykač 1 na líniu 1: 0-> off 1-> on
|
|
||||||
momentálne sa stav zmení len keď vo flow klikneš aby sa zmenil, ale tá zmena by sa mala ukázať aj na platforme
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.install = function(instance) {
|
|
||||||
|
|
||||||
let previousValues = {};
|
|
||||||
let rsPortReceivedData = [];
|
|
||||||
|
|
||||||
console.log("DI_DO_Relay_Controller installed");
|
|
||||||
|
|
||||||
//key is PIN number
|
|
||||||
const conversionTable = {
|
|
||||||
"1": {tbname: "KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV", type: "state_of_main_switch"}, //state_of_main_switch pin1
|
|
||||||
"2": {tbname: "KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV", type: "rotary_switch_state"}, //rotary_switch_state - poloha manual = pin2
|
|
||||||
"3": {tbname: "KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV", type: "rotary_switch_state"}, //rotary_switch_state - poloha auto = pin3
|
|
||||||
"6": {tbname: "KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV", type: "door_condition"}, // door_condition = pin6, 1 -> vyreportuje Closed, 0 -> vyreportuje Open
|
|
||||||
"8": {tbname: "RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O", type: "state_of_breaker", "line": 1}, // state_of_breaker linia 1 0=off, 1=on
|
|
||||||
"9": {tbname: "dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7", type: "state_of_breaker", "line": 2}, // state_of_breaker linia 2 0=off, 1=on
|
|
||||||
"10": {tbname: "vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V", type: "state_of_breaker", "line": 3}, // state_of_breaker linia 3 0=off, 1=on
|
|
||||||
"11": {tbname: "RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O", type: "state_of_contactor", "line": 1}, // state_of_contactor linia 1 0=off, 1=on
|
|
||||||
"12": {tbname: "dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7", type: "state_of_contactor", "line": 2}, // state_of_contactor linia 2 0=off, 1=on
|
|
||||||
"13": {tbname: "vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V", type: "state_of_contactor", "line": 3}, // state_of_contactor linia 3 0=off, 1=on
|
|
||||||
"16": {tbname: "KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV", type: "state_of_main_switch"}, // twilight_sensor = pin16
|
|
||||||
};
|
|
||||||
|
|
||||||
const dbRelays = TABLE("relays");
|
|
||||||
dbRelays.on('change', function(doc, old) {
|
|
||||||
instance.send(2, "reload_relays");
|
|
||||||
});
|
|
||||||
|
|
||||||
//modify
|
|
||||||
|
|
||||||
const SerialPort = require('serialport');
|
|
||||||
//const { exec } = require('child_process');
|
|
||||||
const { openPort, runSyncExec, writeData } = require('./serialport_helper.js');
|
|
||||||
|
|
||||||
const setRSPortData = [0xAA,6,6,6,6,0,6,0,6,6,6,1,1,1,1,0,0,10,10,10,10,0,10,0,10,10,10,0,0,0,0,0,0,5,0,0,0,15,15,15,15,0,15,0,15,15,15,0,0,0,0,0,0,30,0,0,0];
|
|
||||||
const rsPort = new SerialPort("/dev/ttymxc0", { autoOpen: false });
|
|
||||||
|
|
||||||
rsPort.on('open', async function() {
|
|
||||||
|
|
||||||
await runSyncExec("stty -F /dev/ttymxc0 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke").then(function (status) {
|
|
||||||
instance.send(0, exports.title + " runSyncExec - Promise Resolved:" + status);
|
|
||||||
|
|
||||||
//set port
|
|
||||||
rsPort.write(Buffer.from(setRSPortData), function(err) {
|
|
||||||
instance.send(0, exports.title + " Digital in_out has been set");
|
|
||||||
|
|
||||||
//force turn off relays
|
|
||||||
let keys = Object.keys(conversionTable);
|
|
||||||
for(let i = 0; i < keys.length; i++)
|
|
||||||
{
|
|
||||||
let key = keys[i];
|
|
||||||
|
|
||||||
if(conversionTable[key].type == "state_of_contactor")
|
|
||||||
{
|
|
||||||
let pin = key - 1;
|
|
||||||
let line = conversionTable[key].line;
|
|
||||||
|
|
||||||
turnOff(line, pin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//dbRelays.modify({ contactor: 0 });
|
|
||||||
})
|
|
||||||
|
|
||||||
}).catch(function (reason) {
|
|
||||||
instance.send(0, exports.title + " runSyncExec - promise rejected:" + reason);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
rsPort.open();
|
|
||||||
|
|
||||||
rsPort.on('data', function (data){
|
|
||||||
|
|
||||||
rsPortReceivedData = [...rsPortReceivedData, ...data];
|
|
||||||
|
|
||||||
if (rsPortReceivedData[0] != 85) {
|
|
||||||
rsPortReceivedData = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let l = rsPortReceivedData.length;
|
|
||||||
|
|
||||||
if (l < 4 ) return;
|
|
||||||
|
|
||||||
if (l > 4 ) {
|
|
||||||
|
|
||||||
// if array length is greater than 4, we take first 4 byte and do the logic, second 4 bytes, do the logic and so on
|
|
||||||
let i, j, temparray, chunk = 4;
|
|
||||||
for ( i = 0, j = l; i < j; i += chunk ) {
|
|
||||||
temparray = rsPortReceivedData.slice(i, i + chunk);
|
|
||||||
|
|
||||||
if ( temparray.length < 4 ){
|
|
||||||
rsPortReceivedData = [...temparray];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switchLogic(temparray);
|
|
||||||
}
|
|
||||||
|
|
||||||
rsPortReceivedData = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switchLogic(rsPortReceivedData);
|
|
||||||
|
|
||||||
rsPortReceivedData = [];
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
rsPort.on('error', function(err) {
|
|
||||||
instance.send(0, err.message);
|
|
||||||
})
|
|
||||||
|
|
||||||
rsPort.on("close", () => {
|
|
||||||
rsPort.close();
|
|
||||||
})
|
|
||||||
|
|
||||||
instance.on("close", () => {
|
|
||||||
rsPort.close();
|
|
||||||
})
|
|
||||||
|
|
||||||
function getPin(line)
|
|
||||||
{
|
|
||||||
//conversionTable
|
|
||||||
let keys = Object.keys(conversionTable);
|
|
||||||
for(let i = 0; i < keys.length; i++)
|
|
||||||
{
|
|
||||||
let key = keys[i];
|
|
||||||
|
|
||||||
if(conversionTable[key].type == "state_of_contactor" && conversionTable[key].line == line)
|
|
||||||
{
|
|
||||||
return key - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("no pin detected");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function turnOn(line, pin)
|
|
||||||
{
|
|
||||||
if( pin === undefined) pin = getPin(line);
|
|
||||||
if( pin === undefined) return;
|
|
||||||
|
|
||||||
let arr = [0x55];
|
|
||||||
arr.push( pin );
|
|
||||||
arr.push( 0 );
|
|
||||||
arr.push( 1 );
|
|
||||||
|
|
||||||
if(!rsPort.isOpen)
|
|
||||||
{
|
|
||||||
console.log("port is not opened");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsPort.write(Buffer.from(arr), function(err) {
|
|
||||||
switchLogic(arr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function turnOff(line, pin)
|
|
||||||
{
|
|
||||||
if( pin === undefined) pin = getPin(line);
|
|
||||||
if( pin === undefined) return;
|
|
||||||
|
|
||||||
let arr = [0x55];
|
|
||||||
arr.push( pin );
|
|
||||||
arr.push( 0 );
|
|
||||||
arr.push( 0 );
|
|
||||||
|
|
||||||
if(!rsPort.isOpen)
|
|
||||||
{
|
|
||||||
console.log("port is not opened");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsPort.write(Buffer.from(arr), function(err) {
|
|
||||||
switchLogic(arr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// we expect array as flowdata.data
|
|
||||||
instance.on("data", (flowdata) => {
|
|
||||||
|
|
||||||
//console.log(flowdata.data);
|
|
||||||
|
|
||||||
if(flowdata.data instanceof Object)
|
|
||||||
{
|
|
||||||
let obj = flowdata.data;
|
|
||||||
|
|
||||||
let line = obj.line;
|
|
||||||
|
|
||||||
if(obj.command == "turnOn") turnOn(line);
|
|
||||||
else if(obj.command == "turnOff") turnOff(line);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(flowdata.data)){
|
|
||||||
rsPort.write(Buffer.from(flowdata.data), function(err) {
|
|
||||||
switchLogic(flowdata.data);
|
|
||||||
|
|
||||||
instance.send(0,{"WRITE":flowdata.data});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const switchLogic = (rsPortReceivedData) => {
|
|
||||||
|
|
||||||
let dataToTb;
|
|
||||||
let values = {};
|
|
||||||
|
|
||||||
let pinIndex = rsPortReceivedData[1] + 1;
|
|
||||||
if (pinIndex === 17) pinIndex--;
|
|
||||||
|
|
||||||
let newPinValue = rsPortReceivedData[3];
|
|
||||||
|
|
||||||
let obj = conversionTable[pinIndex];
|
|
||||||
|
|
||||||
if(obj == undefined)
|
|
||||||
{
|
|
||||||
//console.log("undefined pinIndex", pinIndex, rsPortReceivedData);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let type = obj.type;
|
|
||||||
let line = obj.line;
|
|
||||||
let tbname = obj.tbname;
|
|
||||||
|
|
||||||
//default value
|
|
||||||
let value = "On";
|
|
||||||
if(newPinValue === 0) value = "Off";
|
|
||||||
|
|
||||||
if(type == "rotary_switch_state")
|
|
||||||
{
|
|
||||||
// combination of these two pins required to get result
|
|
||||||
let pin2, pin3;
|
|
||||||
if(pinIndex == 2)
|
|
||||||
{
|
|
||||||
pin2 = newPinValue;
|
|
||||||
pin3 = previousValues[pinIndex];
|
|
||||||
if (pin3 == undefined) pin3 = 0;
|
|
||||||
}
|
|
||||||
else if(pinIndex == 3)
|
|
||||||
{
|
|
||||||
pin3 = newPinValue;
|
|
||||||
pin2 = previousValues[1];
|
|
||||||
if (pin2 == undefined) pin2 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pin2 == 1 && pin3 == 0) value = "Manual";
|
|
||||||
if (pin2 == 0 && pin3 == 0) value = "Off";
|
|
||||||
if (pin2 == 0 && pin3 == 1) value = "Automatic";
|
|
||||||
}
|
|
||||||
else if(type == "door_condition")
|
|
||||||
{
|
|
||||||
newPinValue === 0 ? value = "Open" : value = "Closed";
|
|
||||||
}
|
|
||||||
else if(type == "twilight_sensor")
|
|
||||||
{
|
|
||||||
value = parseFloat(newPinValue + (256*rsPortReceivedData[2]));
|
|
||||||
}
|
|
||||||
else if(type == "state_of_contactor")
|
|
||||||
{
|
|
||||||
//modify table relays
|
|
||||||
dbRelays.modify({ contactor: newPinValue }).where("line", line);
|
|
||||||
}
|
|
||||||
|
|
||||||
values[obj.type] = value;
|
|
||||||
|
|
||||||
if(conversionTable.hasOwnProperty(pinIndex))
|
|
||||||
{
|
|
||||||
let insertIntoTb = false;
|
|
||||||
if(newPinValue != previousValues[pinIndex]) insertIntoTb = true;
|
|
||||||
if(obj.hasOwnProperty("state_of_contactor")) insertIntoTb = true;
|
|
||||||
|
|
||||||
if(insertIntoTb)
|
|
||||||
{
|
|
||||||
dataToTb = {
|
|
||||||
[tbname]: [
|
|
||||||
{
|
|
||||||
"ts": Date.now(),
|
|
||||||
"values": values
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.send(1, dataToTb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//pin was changed
|
|
||||||
previousValues[pinIndex] = newPinValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
120
flow/test.js
120
flow/test.js
|
|
@ -1,120 +0,0 @@
|
||||||
const getTimezoneOffset = (timeZone, date = new Date()) => {
|
|
||||||
const tz = date.toLocaleString("en", {timeZone, timeStyle: "long"}).split(" ").slice(-1)[0];
|
|
||||||
const dateString = date.toString();
|
|
||||||
const offset = Date.parse(`${dateString} UTC`) - Date.parse(`${dateString} ${tz}`);
|
|
||||||
|
|
||||||
// return UTC offset in millis
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
let profile = {
|
|
||||||
"time_points": [
|
|
||||||
{
|
|
||||||
"start_time": "13:00",
|
|
||||||
"value": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"start_time": "16:00",
|
|
||||||
"value": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"astro_clock": true,
|
|
||||||
"dusk_astro_clock_offset": 0,
|
|
||||||
"dawn_astro_clock_offset": 0,
|
|
||||||
"dusk_lux_sensor": false,
|
|
||||||
"dawn_lux_sensor": false,
|
|
||||||
"dusk_lux_sensor_value": 5,
|
|
||||||
"dawn_lux_sensor_value": 5,
|
|
||||||
"dusk_lux_sensor_time_window": 30,
|
|
||||||
"dawn_lux_sensor_time_window": 30,
|
|
||||||
}
|
|
||||||
|
|
||||||
let now = new Date(); // Creates a Date Object using the clients current time
|
|
||||||
console.log(now, now.getTime());
|
|
||||||
|
|
||||||
//let [hours, minutes, seconds] = "18:19:02".split(':');
|
|
||||||
//d.setHours(+hours); // Set the hours, using implicit type coercion
|
|
||||||
//d.setMinutes(minutes); // You can pass Number or String. It doesn't really matter
|
|
||||||
//d.setSeconds(seconds);
|
|
||||||
|
|
||||||
let time_points = profile.time_points;
|
|
||||||
time_points.push( {"start_time": "1:00", "value": 1} );
|
|
||||||
|
|
||||||
time_points.sort(function (a, b) {
|
|
||||||
|
|
||||||
let [ahours, aminutes, aseconds] = a.start_time.split(':');
|
|
||||||
let [bhours, bminutes, bseconds] = b.start_time.split(':');
|
|
||||||
|
|
||||||
let ad = new Date();
|
|
||||||
ad.setHours( parseInt(ahours) );
|
|
||||||
ad.setMinutes( parseInt(aminutes) );
|
|
||||||
ad.setSeconds(0);
|
|
||||||
|
|
||||||
let bd = new Date();
|
|
||||||
bd.setHours( parseInt(bhours) );
|
|
||||||
bd.setMinutes( parseInt(bminutes) );
|
|
||||||
ad.setSeconds(0);
|
|
||||||
|
|
||||||
return ad.getTime() - bd.getTime();
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(time_points);
|
|
||||||
|
|
||||||
let value = time_points[ time_points.length - 1].value;
|
|
||||||
|
|
||||||
for(let i = 0; i < time_points.length; i++)
|
|
||||||
{
|
|
||||||
let [hours, minutes, seconds] = time_points[i].start_time.split(':');
|
|
||||||
|
|
||||||
let start_time = new Date();
|
|
||||||
start_time.setHours( parseInt(hours) );
|
|
||||||
start_time.setMinutes( parseInt(minutes) );
|
|
||||||
start_time.setSeconds(0);
|
|
||||||
|
|
||||||
if(now.getTime() > start_time.getTime())
|
|
||||||
{
|
|
||||||
value = time_points[i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log(start_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(value);
|
|
||||||
|
|
||||||
const offset = getTimezoneOffset("Europe/Bratislava");
|
|
||||||
console.log(offset);
|
|
||||||
|
|
||||||
|
|
||||||
function removeTask(obj)
|
|
||||||
{
|
|
||||||
|
|
||||||
let keys = Object.keys(obj);
|
|
||||||
tasks = tasks.filter((task) => {
|
|
||||||
|
|
||||||
let counter = 0;
|
|
||||||
for(let i = 0; i < keys.length; i++)
|
|
||||||
{
|
|
||||||
let key = keys[i];
|
|
||||||
if(task.hasOwnProperty(key) && obj.hasOwnProperty(key))
|
|
||||||
{
|
|
||||||
if(task[key] == obj[key]) counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(counter == keys.length) return false;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertUTCDateToLocalDate(date) {
|
|
||||||
var newDate = new Date(date);
|
|
||||||
newDate.setMinutes(date.getMinutes() - date.getTimezoneOffset());
|
|
||||||
return newDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
let d = convertUTCDateToLocalDate(new Date("2022-04-26T06:56:54.000Z"));
|
|
||||||
|
|
||||||
console.log(d, d.getHours());
|
|
||||||
220
flow/thermometer.js
Normal file
220
flow/thermometer.js
Normal file
|
|
@ -0,0 +1,220 @@
|
||||||
|
exports.id = 'thermometer';
|
||||||
|
exports.title = 'Thermometer';
|
||||||
|
exports.group = 'Worksys';
|
||||||
|
exports.color = '#5CB36D';
|
||||||
|
exports.version = '1.0.3';
|
||||||
|
exports.output = ["red", "white", "blue"];
|
||||||
|
exports.author = 'Rastislav Kovac';
|
||||||
|
exports.icon = 'thermometer-three-quarters';
|
||||||
|
|
||||||
|
exports.readme = `# Getting temperature values for RVO. In case of LM, you need device address. In case of unipi, evok sends values, in case thermometer is installed`;
|
||||||
|
|
||||||
|
const instanceSendTo = {
|
||||||
|
debug: 0,
|
||||||
|
tb: 1,
|
||||||
|
dido_controller: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
//read temperature - frequency
|
||||||
|
let timeoutMin = 5;//minutes
|
||||||
|
|
||||||
|
var path = require('path');
|
||||||
|
var log4js = require("log4js");
|
||||||
|
|
||||||
|
log4js.configure({
|
||||||
|
appenders: {
|
||||||
|
errLogs: { type: 'file', filename: path.join(__dirname + "/../", 'err.txt') },
|
||||||
|
monitorLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'monitor.txt') },
|
||||||
|
console: { type: 'console' }
|
||||||
|
},
|
||||||
|
categories: {
|
||||||
|
errLogs: { appenders: ['console', 'errLogs'], level: 'error' },
|
||||||
|
monitorLogs: { appenders: ['console', 'monitorLogs'], level: 'trace' },
|
||||||
|
//another: { appenders: ['console'], level: 'trace' },
|
||||||
|
default: { appenders: ['console'], level: 'trace' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const errLogger = log4js.getLogger("errLogs");
|
||||||
|
const logger = log4js.getLogger();
|
||||||
|
const monitor = log4js.getLogger("monitorLogs");
|
||||||
|
|
||||||
|
//logger.debug("text")
|
||||||
|
//monitor.info('info');
|
||||||
|
//errLogger.error("some error");
|
||||||
|
|
||||||
|
const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper');
|
||||||
|
const dbSettings = TABLE("settings");
|
||||||
|
let temperatureAddress = "";
|
||||||
|
|
||||||
|
async function loadSettings()
|
||||||
|
{
|
||||||
|
//todo global FLOW.OMS_edgeName is making problem, so we load it here as well, it should not be
|
||||||
|
let responseSettings = await promisifyBuilder(dbSettings.find());
|
||||||
|
temperatureAddress = responseSettings[0]["temperature_adress"];
|
||||||
|
}
|
||||||
|
|
||||||
|
loadSettings();
|
||||||
|
|
||||||
|
|
||||||
|
exports.install = function(instance) {
|
||||||
|
|
||||||
|
const { exec } = require('child_process');
|
||||||
|
const { sendNotification, ERRWEIGHT } = require('./helper/notification_reporter');
|
||||||
|
|
||||||
|
let startRead;
|
||||||
|
let dataToTb;
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
let edgeName = "";
|
||||||
|
|
||||||
|
|
||||||
|
logger.debug(exports.title, "installed");
|
||||||
|
|
||||||
|
instance.on("close", function(){
|
||||||
|
clearInterval(startRead);
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const start = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if(FLOW.OMS_controller_type === "unipi")
|
||||||
|
{
|
||||||
|
clearInterval(startRead);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(temperatureAddress === "") throw "gettemperature: temperatureAddress is not defined";
|
||||||
|
|
||||||
|
logger.debug("FLOW.OMS_temperature_adress", FLOW.OMS_temperature_adress);
|
||||||
|
|
||||||
|
exec(`owread -C ${temperatureAddress}/temperature`, (error, stdout, stderr) => {
|
||||||
|
|
||||||
|
edgeName = FLOW.OMS_edgeName;
|
||||||
|
|
||||||
|
if(edgeName !== "")
|
||||||
|
{
|
||||||
|
if(error)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(FLOW.OMS_brokerready == undefined)
|
||||||
|
{
|
||||||
|
logger.debug("gettemparature - FLOW.OMS_brokerready is undefined");
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
start();
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FLOW.OMS_brokerready)
|
||||||
|
{
|
||||||
|
//sendNotification("start", edgeName, ERRWEIGHT.WARNING, "Thermometer is not responding", {"Error": error}, instanceSendTo.tb, instance, "thermometer");
|
||||||
|
sendNotification("start", edgeName, "thermometer_is_not_responding", {}, {"Error": error}, instanceSendTo.tb, instance, "thermometer");
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = "NOK";
|
||||||
|
dataToTb = {
|
||||||
|
[edgeName]: [
|
||||||
|
{
|
||||||
|
"ts": Date.now(),
|
||||||
|
"values": {
|
||||||
|
"status": status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor.info("Thermometer is not responding", error, FLOW.OMS_brokerready);
|
||||||
|
|
||||||
|
// instance.send(instanceSendTo.tb, dataToTb); // poslat stav nok do tb, ak to handluje dido_controller ??
|
||||||
|
instance.send(instanceSendTo.dido_controller, {status: "NOK-thermometer"});
|
||||||
|
}
|
||||||
|
else parseData(stdout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
monitor.info("gettemperature: edgeName is not defined", FLOW.OMS_edgeName);
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
start();
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//instance.send({"Temp":stdout,"stderr":stderr,"err":error});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
errLogger.error(exports.title, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseData = function(data) {
|
||||||
|
|
||||||
|
data = parseFloat(data);
|
||||||
|
|
||||||
|
logger.debug("gettemperature", data);
|
||||||
|
|
||||||
|
if(!isNaN(data)) {
|
||||||
|
|
||||||
|
if(counter > 290)
|
||||||
|
{
|
||||||
|
instance.send(instanceSendTo.debug, "[Get temperature component] - temperature data are comming again from RVO after more than 1 day break");
|
||||||
|
|
||||||
|
//sendNotification("parseData", edgeName, ERRWEIGHT.NOTICE, "Thermometer is working again", "", instanceSendTo.tb, instance, "thermometer");
|
||||||
|
if(FLOW.OMS_brokerready) sendNotification("parseData", edgeName, "thermometer_is_responding_again", {}, "", instanceSendTo.tb, instance, "thermometer");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("gettemperature", data);
|
||||||
|
const values = {
|
||||||
|
"temperature": Number(data.toFixed(2)),
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
dataToTb = {
|
||||||
|
[edgeName]: [
|
||||||
|
{
|
||||||
|
"ts": Date.now(),
|
||||||
|
"values":values
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.send(instanceSendTo.tb, dataToTb);
|
||||||
|
instance.send(instanceSendTo.dido_controller, values);
|
||||||
|
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
monitor.info("gettemperature err", counter, data);
|
||||||
|
|
||||||
|
//ked je problem 1 den
|
||||||
|
let day = 24 * 60 / timeoutMin;
|
||||||
|
if ( counter > day && counter < day + 2 ) {
|
||||||
|
//sendNotification("parseData", edgeName, ERRWEIGHT.WARNING, "Thermometer receives invalid data", "", instanceSendTo.tb, instance, "thermometer");
|
||||||
|
sendNotification("parseData", edgeName, "thermometer_sends_invalid_data", {}, "", instanceSendTo.tb, instance, "thermometer");
|
||||||
|
|
||||||
|
instance.send(instanceSendTo.debug, "[Get temperature component] - no temperature data from RVO for more than 1 day");
|
||||||
|
instance.send(instanceSendTo.dido_controller, {status: "NOK-thermometer"});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
start();
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
startRead = setInterval(start, timeoutMin * 1000 * 60);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -119,6 +119,7 @@ process.on('uncaughtException', function (err) {
|
||||||
const nosql = NOSQL('tbdata');
|
const nosql = NOSQL('tbdata');
|
||||||
const nosqlBackup = NOSQL('/backup/tbdata');
|
const nosqlBackup = NOSQL('/backup/tbdata');
|
||||||
|
|
||||||
|
|
||||||
exports.install = function(instance) {
|
exports.install = function(instance) {
|
||||||
|
|
||||||
var broker;
|
var broker;
|
||||||
|
|
@ -186,7 +187,7 @@ exports.install = function(instance) {
|
||||||
let mqtt_clientid = responseSettings[0]["mqtt_clientid"];
|
let mqtt_clientid = responseSettings[0]["mqtt_clientid"];
|
||||||
let mqtt_username = responseSettings[0]["mqtt_username"];
|
let mqtt_username = responseSettings[0]["mqtt_username"];
|
||||||
let mqtt_port = responseSettings[0]["mqtt_port"];
|
let mqtt_port = responseSettings[0]["mqtt_port"];
|
||||||
|
|
||||||
console.log("wsmqttpublich -> loadSettings from db", responseSettings[0]);
|
console.log("wsmqttpublich -> loadSettings from db", responseSettings[0]);
|
||||||
|
|
||||||
opts = {
|
opts = {
|
||||||
|
|
@ -203,8 +204,7 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToTbServer();
|
connectToTbServer();
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function connectToTbServer()
|
function connectToTbServer()
|
||||||
{
|
{
|
||||||
|
|
@ -215,16 +215,18 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
broker.on('connect', function() {
|
broker.on('connect', function() {
|
||||||
instance.status("Connected", "green");
|
instance.status("Connected", "green");
|
||||||
brokerready = true;
|
monitor.info("MQTT broker connected");
|
||||||
|
|
||||||
|
brokerready = true;
|
||||||
FLOW.OMS_brokerready = brokerready;
|
FLOW.OMS_brokerready = brokerready;
|
||||||
wsmqtt_status = 'connected';
|
wsmqtt_status = 'connected';
|
||||||
});
|
});
|
||||||
|
|
||||||
broker.on('reconnect', function() {
|
broker.on('reconnect', function() {
|
||||||
instance.status("Reconnecting", "yellow");
|
instance.status("Reconnecting", "yellow");
|
||||||
brokerready = false;
|
brokerready = false;
|
||||||
|
|
||||||
FLOW.OMS_brokerready = brokerready;
|
FLOW.OMS_brokerready = brokerready;
|
||||||
});
|
});
|
||||||
|
|
||||||
broker.on('message', function(topic, message) {
|
broker.on('message', function(topic, message) {
|
||||||
|
|
@ -243,7 +245,6 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.send(instanceSendTo.rpcCall, {"topic":topic, "content":message });
|
instance.send(instanceSendTo.rpcCall, {"topic":topic, "content":message });
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
broker.on('close', function(err) {
|
broker.on('close', function(err) {
|
||||||
|
|
@ -258,11 +259,14 @@ exports.install = function(instance) {
|
||||||
instance.status("Disconnected", "red");
|
instance.status("Disconnected", "red");
|
||||||
instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts });
|
instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
broker.reconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
broker.on('error', function(err) {
|
broker.on('error', function(err) {
|
||||||
instance.status("Err: "+ err.code, "red");
|
instance.status("Err: "+ err.code, "red");
|
||||||
instance.send(instanceSendTo.debug, {"message":"Broker ERROR signal received !", "error":err, "opt":opts });
|
instance.send(instanceSendTo.debug, {"message":"Broker ERROR signal received !", "error":err, "opt":opts });
|
||||||
|
monitor.info('MQTT broker error', err);
|
||||||
|
|
||||||
brokerready = false;
|
brokerready = false;
|
||||||
FLOW.OMS_brokerready = brokerready;
|
FLOW.OMS_brokerready = brokerready;
|
||||||
|
|
@ -270,89 +274,66 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//broker = new Broker(opts);
|
|
||||||
//MQTT_BROKERS.push(broker);
|
|
||||||
|
|
||||||
//instance.status('Ready');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//set opts accortding to options
|
instance.on('data', function(data) {
|
||||||
/*
|
|
||||||
instance.reconfigure = function() {
|
|
||||||
|
|
||||||
|
if (brokerready)
|
||||||
var o = instance.options;
|
{
|
||||||
opts = {
|
//do we have some data in backup file?
|
||||||
host: o.host,
|
//if any, process data from database
|
||||||
port: o.port,
|
if(saveTelemetryOnError)
|
||||||
keepalive: 10,
|
|
||||||
clientId: o.clientid,
|
|
||||||
username: o.username,
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
resubscribe: false
|
|
||||||
};
|
|
||||||
|
|
||||||
//connectToTbServer();
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
instance.on('data', function(data) {
|
|
||||||
|
|
||||||
if (brokerready)
|
|
||||||
{
|
{
|
||||||
//do we have some data in backup file?
|
//read telemetry data and send back to server
|
||||||
//if any, process data from database
|
if(!processingData) processDataFromDatabase();
|
||||||
if(saveTelemetryOnError)
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (brokerready)
|
||||||
|
{
|
||||||
|
let stringifiedJson = JSON.stringify(data.data);
|
||||||
|
broker.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1});
|
||||||
|
|
||||||
|
//backup telemetry
|
||||||
|
if(createTelemetryBackup)
|
||||||
|
{
|
||||||
|
data.data.id = UID();
|
||||||
|
nosqlBackup.insert(data.data);
|
||||||
|
|
||||||
|
insertBackupNoSqlCounter++;
|
||||||
|
if(insertBackupNoSqlCounter > 150)
|
||||||
{
|
{
|
||||||
//read telemetry data and send back to server
|
let options = {compress: true};
|
||||||
if(!processingData) processDataFromDatabase();
|
let path = __dirname + "/../databases/backup/tbdata.nosql";
|
||||||
}
|
var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options);
|
||||||
|
stream.write("");
|
||||||
|
stream.end();
|
||||||
|
|
||||||
|
insertBackupNoSqlCounter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
if(logger) logger.debug("Broker unavailable. Data not sent !", data.data);
|
||||||
|
instance.send(instanceSendTo.debug, {"message":"Broker unavailable. Data not sent !", "data": data.data });
|
||||||
|
|
||||||
|
if(saveTelemetryOnError)
|
||||||
|
{
|
||||||
|
//create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql
|
||||||
|
makeBackupFromDbFile();
|
||||||
|
|
||||||
|
//write to tb
|
||||||
|
data.data.id = UID();
|
||||||
|
nosql.insert(data.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (brokerready)
|
}
|
||||||
{
|
});
|
||||||
let stringifiedJson = JSON.stringify(data.data);
|
|
||||||
broker.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1});
|
|
||||||
|
|
||||||
//backup telemetry
|
|
||||||
if(createTelemetryBackup)
|
|
||||||
{
|
|
||||||
data.data.id = UID();
|
|
||||||
nosqlBackup.insert(data.data);
|
|
||||||
|
|
||||||
insertBackupNoSqlCounter++;
|
|
||||||
if(insertBackupNoSqlCounter > 150)
|
|
||||||
{
|
|
||||||
let options = {compress: true};
|
|
||||||
let path = __dirname + "/../databases/backup/tbdata.nosql";
|
|
||||||
var stream = new rollers.RollingFileStream(path, noSqlFileSizeLimit, 150, options);
|
|
||||||
stream.write("");
|
|
||||||
stream.end();
|
|
||||||
|
|
||||||
insertBackupNoSqlCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
if(logger) logger.debug("Broker unavailable. Data not sent !", data.data);
|
|
||||||
instance.send(instanceSendTo.debug, {"message":"Broker unavailable. Data not sent !", "data": data.data });
|
|
||||||
|
|
||||||
if(saveTelemetryOnError)
|
|
||||||
{
|
|
||||||
//create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql
|
|
||||||
makeBackupFromDbFile();
|
|
||||||
|
|
||||||
//write to tb
|
|
||||||
data.data.id = UID();
|
|
||||||
nosql.insert(data.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
instance.close = function(done) {
|
instance.close = function(done) {
|
||||||
if (brokerready){
|
if (brokerready){
|
||||||
|
|
@ -449,7 +430,6 @@ exports.install = function(instance) {
|
||||||
fs.truncateSync(source, 0);
|
fs.truncateSync(source, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const processDataFromDatabase = async () => {
|
const processDataFromDatabase = async () => {
|
||||||
|
|
|
||||||
12
package.json
12
package.json
|
|
@ -4,12 +4,14 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "debug.js",
|
"main": "debug.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"easy-crc": "0.0.2",
|
|
||||||
"mqtt": "^4.2.6",
|
|
||||||
"serialport": "^9.0.0",
|
|
||||||
"total.js": "^3.4.5",
|
|
||||||
"bitwise": "^2.1.0",
|
"bitwise": "^2.1.0",
|
||||||
"log4js": "^6.3.0"
|
"easy-crc": "0.0.2",
|
||||||
|
"jsmodbus": "^4.0.6",
|
||||||
|
"log4js": "^6.3.0",
|
||||||
|
"mqtt": "^4.2.6",
|
||||||
|
"nodemailer": "^6.9.7",
|
||||||
|
"serialport": "^9.2.8",
|
||||||
|
"total.js": "^3.4.13"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
{
|
|
||||||
"config": {
|
|
||||||
"isRunning": false,
|
|
||||||
"debug": true,
|
|
||||||
"timeoutTime": 4000,
|
|
||||||
"msgWaitTime": 20000,
|
|
||||||
"port": "/dev/ttymxc1",
|
|
||||||
"port_options": "stty -F /dev/ttymxc1 9600 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke"
|
|
||||||
},
|
|
||||||
"private": {
|
|
||||||
"errBuffer": [],
|
|
||||||
"tbBuffer": [],
|
|
||||||
"device_index": 0,
|
|
||||||
"cmd_index": 0,
|
|
||||||
"devices": [{
|
|
||||||
"name": "Elektrometer 1",
|
|
||||||
"tb_name": "",
|
|
||||||
"type": "EM340",
|
|
||||||
"address": 1,
|
|
||||||
"data": [],
|
|
||||||
"cmd": [],
|
|
||||||
"timeoutcount": 0,
|
|
||||||
"status": "virtual"
|
|
||||||
}],
|
|
||||||
"cmd_tables": [{
|
|
||||||
"type": "EM340",
|
|
||||||
"cmd": [{
|
|
||||||
"name": "Voltage L1",
|
|
||||||
"tb_name": "Phase_1_voltage",
|
|
||||||
"register": 0,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Voltage L2",
|
|
||||||
"tb_name": "Phase_2_voltage",
|
|
||||||
"register": 2,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Voltage L3",
|
|
||||||
"tb_name": "Phase_3_voltage",
|
|
||||||
"register": 4,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Current L1",
|
|
||||||
"tb_name": "Phase_1_current",
|
|
||||||
"register": 12,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Current L2",
|
|
||||||
"tb_name": "Phase_2_current",
|
|
||||||
"register": 14,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Current L3",
|
|
||||||
"tb_name": "Phase_3_current",
|
|
||||||
"register": 16,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Power L1",
|
|
||||||
"tb_name": "Phase_1_power",
|
|
||||||
"register": 18,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Power L2",
|
|
||||||
"tb_name": "Phase_2_power",
|
|
||||||
"register": 20,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Power L3",
|
|
||||||
"tb_name": "Phase_3_power",
|
|
||||||
"register": 22,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Power tot",
|
|
||||||
"tb_name": "total_power",
|
|
||||||
"register": 40,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Energy in",
|
|
||||||
"tb_name": "total_energy",
|
|
||||||
"register": 52,
|
|
||||||
"size": 2,
|
|
||||||
"multiplier": 0.1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PowF L1",
|
|
||||||
"tb_name": "Phase_1_pow_factor",
|
|
||||||
"register": 46,
|
|
||||||
"size": 1,
|
|
||||||
"multiplier": 0.001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PowF L2",
|
|
||||||
"tb_name": "Phase_2_pow_factor",
|
|
||||||
"register": 47,
|
|
||||||
"size": 1,
|
|
||||||
"multiplier": 0.001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PowF L3",
|
|
||||||
"tb_name": "Phase_3_pow_factor",
|
|
||||||
"register": 48,
|
|
||||||
"size": 1,
|
|
||||||
"multiplier": 0.001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PowF",
|
|
||||||
"tb_name": "power_factor",
|
|
||||||
"register": 49,
|
|
||||||
"size": 1,
|
|
||||||
"multiplier": 0.001
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue