Skip to content

Instantly share code, notes, and snippets.

@Madsy
Last active July 13, 2019 21:02
Show Gist options
  • Save Madsy/e7ac7b63a509d0fe9e57673ecc1c3597 to your computer and use it in GitHub Desktop.
Save Madsy/e7ac7b63a509d0fe9e57673ecc1c3597 to your computer and use it in GitHub Desktop.
const SerialPort = require('serialport');
const fs = require('fs');
//request reset on address /?9999999
let request_init = [ 0x2f, 0x3f, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x21, 0x0d, 0x0a ];
//select register "51"
let request_select_register_51 = [0x06, 0x30, 0x35, 0x31, 0x0d, 0x0a];
//.R1.0030().
let request_register_R1_30 = [
0x01, 0x52, 0x31, 0x02, 0x30, 0x30, 0x33, 0x30, 0x28, 0x29, 0x03, 0x60
];
let request_register_R1_50 = [
0x01, 0x52, 0x31, 0x02, 0x30, 0x30, 0x35, 0x30, 0x28, 0x29, 0x03, 0x66
];
let request_register_R1_100 = [
0x01, 0x52, 0x31, 0x02, 0x30, 0x31, 0x30, 0x30, 0x28, 0x29, 0x03, 0x62
];
//select via serial number
let request_select = [ 0x2f, 0x3f, 0x31, 0x38, 0x30, 0x36, 0x30, 0x35, 0x38, 0x33, 0x21, 0x0d, 0x0a ];
//ack
let response1 = [0x2f, 0x41, 0x53, 0x0d, 0x0a];
//.P0.(18060583).a
let response2 = [0x01, 0x50, 0x30, 0x02, 0x28, 0x31, 0x38, 0x30, 0x36, 0x30, 0x35, 0x38, 0x33, 0x29, 0x03, 0x61];
//.0030(18060583).
let response3 = [0x02, 0x30, 0x30, 0x33, 0x30, 0x28, 0x31, 0x38, 0x30, 0x36, 0x30, 0x35, 0x38, 0x33, 0x29, 0x03, 00];
//.0100(0D010556).
let response4 = [0x02, 0x30, 0x31, 0x30, 0x30, 0x28, 0x30, 0x44, 0x30, 0x31, 0x30, 0x35, 0x35, 0x36, 0x29, 0x03, 0x70];
let response5 = [0x2f, 0x41, 0x53, 0x0d, 0x0a];
//.P0.(18060583).a
let response6 = [0x01, 0x50, 0x30, 0x02, 0x28, 0x31, 0x38, 0x30, 0x36, 0x30, 0x35, 0x38, 0x33, 0x29, 0x03, 0x61];
//.0050(+006511.71,+006511.71,+000000.00)..
//41 bytes
let response7 = [
0x02, 0x30, 0x30, 0x35, 0x30, 0x28, 0x2b, 0x30, 0x30, 0x36, 0x35, 0x31, 0x31, 0x2e, 0x37, 0x31, 0x2c, 0x2b,
0x30, 0x30, 0x36, 0x35, 0x31, 0x31, 0x2e, 0x37, 0x31, 0x2c, 0x2b, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2e,
0x30, 0x30, 0x29, 0x03,0x02
];
let requests = [
request_init,
request_select_register_51,
request_register_R1_30,
request_register_R1_100,
request_select,
request_select_register_51,
request_register_R1_50
];
let responses = [
response1,
response2,
response3,
response4,
response5,
response6
];
function byteArrayEquals(arr1, arr2){
if(arr1.length !== arr2.length){
return false;
}
for(let i = 0; i < arr1.length; i++){
if(arr1[i] !== arr2[i]){
return false;
}
}
return true;
}
function onPowerData(powerStr){
//powerStr.match(//);
let parts = powerStr.split(",");
let total = parseFloat(parts[0]);
let tarif1 = parseFloat(parts[1]);
let tarif2 = parseFloat(parts[2]);
let output = `${total}&nbsp;&nbsp;${new Date()} <br>`;
fs.appendFileSync('./htdocs/nord.html', output);
}
function main(){
let req_resp_index = 0;
let responseBuffer = [];
const port = new SerialPort('COM3', {
autoOpen: true,
baudRate: 4800,
dataBits: 7,
parity: 'even',
stopBits: 1
});
port.on('error', function(err) {
console.log('Serial Port Error: ', err.message);
});
port.on('data', function (data) {
console.log('Data:', data);
for(let i = 0; i < data.length; i++){
responseBuffer.push(data[i]);
}
if(req_resp_index === 6){
//last response which we want to actually parse
if(responseBuffer.length < 41){
return;
}
let withoutHeader = responseBuffer.slice(6, -3);
let powerStr = String.fromCharCode.apply(null, withoutHeader);
console.log(`Power stats: ${powerStr}`);
onPowerData(powerStr);
process.exit(0);
} else {
if(responseBuffer.length < responses[req_resp_index].length){
//need to read more
return;
}
if(byteArrayEquals(responseBuffer, responses[req_resp_index])){
console.log(`Response ${req_resp_index+1} matched.`);
//clear
responseBuffer = [];
//send next request
req_resp_index++;
port.write(Buffer.from(requests[req_resp_index]));
} else {
throw Error(`Response ${req_resp_index+1} contained unexpected data or bad length.`);
}
}
});
//initial write which starts everything
port.write(Buffer.from(requests[req_resp_index]));
}
main();
{
"name": "powerstats",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"serialport": "^7.1.5"
}
}
const SerialPort = require('serialport');
const fs = require('fs');
//request reset on address /?9999999
let request_init = [ 0x2f, 0x3f, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x21, 0x0d, 0x0a ];
//select register "51"
let request_select_register_51 = [0x06, 0x30, 0x35, 0x31, 0x0d, 0x0a];
//.R1.0030().
let request_register_R1_30 = [
0x01, 0x52, 0x31, 0x02, 0x30, 0x30, 0x33, 0x30, 0x28, 0x29, 0x03, 0x60
];
let request_register_R1_50 = [
0x01, 0x52, 0x31, 0x02, 0x30, 0x30, 0x35, 0x30, 0x28, 0x29, 0x03, 0x66
];
let request_register_R1_100 = [
0x01, 0x52, 0x31, 0x02, 0x30, 0x31, 0x30, 0x30, 0x28, 0x29, 0x03, 0x62
];
//select via serial number
let request_select = [ 0x2f, 0x3f, 0x31, 0x38, 0x30, 0x36, 0x30, 0x35, 0x38, 0x32, 0x21, 0x0d, 0x0a ];
//ack
let response1 = [0x2f, 0x41, 0x53, 0x0d, 0x0a];
//.P0.(18060583).a
let response2 = [0x01, 0x50, 0x30, 0x02, 0x28, 0x31, 0x38, 0x30, 0x36, 0x30, 0x35, 0x38, 0x32, 0x29, 0x03, 0x60];
//.0030(18060583).
let response3 = [0x02, 0x30, 0x30, 0x33, 0x30, 0x28, 0x31, 0x38, 0x30, 0x36, 0x30, 0x35, 0x38, 0x32, 0x29, 0x03, 0x01];
//.0100(0D010556).
let response4 = [0x02, 0x30, 0x31, 0x30, 0x30, 0x28, 0x30, 0x44, 0x30, 0x31, 0x30, 0x35, 0x35, 0x36, 0x29, 0x03, 0x70];
let response5 = [0x2f, 0x41, 0x53, 0x0d, 0x0a];
//.P0.(18060583).a
let response6 = [0x01, 0x50, 0x30, 0x02, 0x28, 0x31, 0x38, 0x30, 0x36, 0x30, 0x35, 0x38, 0x32, 0x29, 0x03, 0x60];
//.0050(+006511.71,+006511.71,+000000.00)..
//41 bytes
let response7 = [
0x02, 0x30, 0x30, 0x35, 0x30, 0x28, 0x2b, 0x30, 0x30, 0x36, 0x35, 0x31, 0x31, 0x2e, 0x37, 0x31, 0x2c, 0x2b,
0x30, 0x30, 0x36, 0x35, 0x31, 0x31, 0x2e, 0x37, 0x31, 0x2c, 0x2b, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2e,
0x30, 0x30, 0x29, 0x03,0x02
];
let requests = [
request_init,
request_select_register_51,
request_register_R1_30,
request_register_R1_100,
request_select,
request_select_register_51,
request_register_R1_50
];
let responses = [
response1,
response2,
response3,
response4,
response5,
response6
];
function byteArrayEquals(arr1, arr2){
if(arr1.length !== arr2.length){
return false;
}
for(let i = 0; i < arr1.length; i++){
if(arr1[i] !== arr2[i]){
return false;
}
}
return true;
}
function onPowerData(powerStr){
//powerStr.match(//);
let parts = powerStr.split(",");
let total = parseFloat(parts[0]);
let tarif1 = parseFloat(parts[1]);
let tarif2 = parseFloat(parts[2]);
let output = `${total}&#9;&#9;${new Date()} <br>`;
fs.appendFileSync('./htdocs/sor.html', output);
}
function main(){
let req_resp_index = 0;
let responseBuffer = [];
const port = new SerialPort('COM5', {
autoOpen: true,
baudRate: 4800,
dataBits: 7,
parity: 'even',
stopBits: 1
});
port.on('error', function(err) {
console.log('Serial Port Error: ', err.message);
});
port.on('data', function (data) {
console.log('Data:', data);
for(let i = 0; i < data.length; i++){
responseBuffer.push(data[i]);
}
if(req_resp_index === 6){
//last response which we want to actually parse
if(responseBuffer.length < 41){
return;
}
let withoutHeader = responseBuffer.slice(6, -3);
let powerStr = String.fromCharCode.apply(null, withoutHeader);
console.log(`Power stats: ${powerStr}`);
onPowerData(powerStr);
process.exit(0);
} else {
if(responseBuffer.length < responses[req_resp_index].length){
//need to read more
return;
}
if(byteArrayEquals(responseBuffer, responses[req_resp_index])){
console.log(`Response ${req_resp_index+1} matched.`);
//clear
responseBuffer = [];
//send next request
req_resp_index++;
port.write(Buffer.from(requests[req_resp_index]));
} else {
throw Error(`Response ${req_resp_index+1} contained unexpected data or bad length.`);
}
}
});
//initial write which starts everything
port.write(Buffer.from(requests[req_resp_index]));
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment