Page 2 of 3

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Sun Feb 23, 2014 1:30 am
by Bwired
Ok check part 2:
Bwired Log Smartmeter data to MYSQL using Nodejs and MQTT
http://blog.bwired.nl/?p=1049

http://www.mijnsmartmeter.nl

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Mon May 18, 2015 11:14 am
by mikeyn
Hi there,

I have the setup as descriped on http://blog.bwired.nl/?p=913 but i get an error when i run smartmeter.js. Invalid number of lines in telegram (14). I assume this has to do that my gasmeter is not connected. Can you give some advise how to solve this?

Code: Select all

Received: /ISk5\2MT382-1004
Received:
Received: 0-0:96.1.1(xxxx)
Received: 1-0:1.8.1(02805.714*kWh)
Received: 1-0:1.8.2(03042.136*kWh)
Received: 1-0:2.8.1(00000.000*kWh)
Received: 1-0:2.8.2(00000.001*kWh)
Received: 0-0:96.14.0(0002)
Received: 1-0:1.7.0(0000.35*kW)
Received: 1-0:2.7.0(0000.00*kW)
Received: 0-0:17.0.0(0999.00*kW)
Received: 0-0:96.3.10(1)
Received: 0-0:96.13.1()
Received: 0-0:96.13.0()
Received: !
Invalid number of lines in telegram (14)

thanks in advance

regards,

Mike

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Mon May 18, 2015 8:56 pm
by Bwired
try to change this one

if (telegram.length === 19)

make it 18, not working then 17 and so on :)
but let it run 30 secs, the firts package received is mostly not valid

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Mon May 18, 2015 9:07 pm
by mikeyn
Thanks. I will test it. I like your work very much btw .

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Tue May 19, 2015 6:29 pm
by mikeyn
Hi again,

I tried and i found i think the right one only it gives again an error what i do not understand. i even did a full reinstall from scratch.

Code: Select all

createClient is deprecated, use connect instead
Starting Smart Meter
Received: /ISk5\2MT382-1004
Received:
Received: 0-0:96.1.1(5A424556303035313834303830353133)
Received: 1-0:1.8.1(02807.594*kWh)
Received: 1-0:1.8.2(03050.524*kWh)
Received: 1-0:2.8.1(00000.000*kWh)
Received: 1-0:2.8.2(00000.001*kWh)
Received: 0-0:96.14.0(0002)
Received: 1-0:1.7.0(0000.39*kW)
Received: 1-0:2.7.0(0000.00*kW)
Received: 0-0:17.0.0(0999.00*kW)
Received: 0-0:96.3.10(1)
Received: 0-0:96.13.1()
Received: 0-0:96.13.0()
Received: !
/home/pi/smartmeter.js:111
            parseInt(telegram[16].substr(11,2)) +  2000,
                                 ^
TypeError: Cannot read property 'substr' of undefined
    at processTelegram (/home/pi/smartmeter.js:111:34)
    at SerialPort.<anonymous> (/home/pi/smartmeter.js:156:13)
    at SerialPort.emit (events.js:107:17)
    at /home/pi/node_modules/serialport/parsers.js:25:17
    at Array.forEach (native)
    at Object.parser (/home/pi/node_modules/serialport/parsers.js:24:13)
    at Object.SerialPort.opts.dataCallback (/home/pi/node_modules/serialport/serialport.js:181:12)
    at SerialPortFactory.SerialPort._emitData (/home/pi/node_modules/serialport/serialport.js:396:20)
    at afterRead (/home/pi/node_modules/serialport/serialport.js:372:20)
    at /home/pi/node_modules/serialport/serialport.js:388:9
what can this be?

thanks in advance

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Tue May 19, 2015 7:08 pm
by Bwired
ok you need to loose a lot more in your code, all what is related to the Gas
put the complete code in as "code" and i will adjust it for you

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Tue May 19, 2015 7:50 pm
by mikeyn
Many thanks for this. I am not able to measure gas. I live in a appartment and the gasmeter is quite far from my home in a central room. So that will not be happening soon i think.

Do we need to adjust the other files as well?

here is the code:

Code: Select all

 
serialport = require('serialport'); var mqtt = require('mqtt');
 
var mclient,
    config,
    SerialPort,
    smartMeter;
 
mclient = mqtt.createClient(1883, '192.168.178.38'); //set ip of the Rasp or localhost
var net = require('net');
var client = new net.Socket();
 
function SmartMeter() {
  this.ConsumedPowerRate1 = 0;
  this.ConsumedPowerRate2 = 0;
  this.ProducedPowerRate1 = 0;
  this.ProducedPowerRate2 = 0;
  this.ActualPowerRate = 0;
  this.ActualConsumedPower = 0;
  this.ActualProducedPower = 0;
  this.GasTimestamp = 0;
  this.ConsumedGas = 0;
}
 
SmartMeter.prototype.update = function(data) {
    //publish the complete telegram to a different topic for logging to for example a mysql dbase (handled in my next blog)
    mclient.publish('historical/smartmeter/data', JSON.stringify(data));
     
    if(data.ConsumedPowerRate1 != this.ConsumedPowerRate1) {
        this.ConsumedPowerRate1 = data.ConsumedPowerRate1;
        mclient.publish('smartmeter/consumed_low', data.ConsumedPowerRate1.toString(), {retain: true});
        //console.log(data.ConsumedPowerRate1)
    }
  
    if(data.ConsumedPowerRate2 != this.ConsumedPowerRate2) {
        this.ConsumedPowerRate2 = data.ConsumedPowerRate2;
        mclient.publish('smartmeter/consumed_high', data.ConsumedPowerRate2.toString(), {retain: true});
        //console.log(data.ConsumedPowerRate2)
    }
  
    if(data.ProducedPowerRate1 != this.ProducedPowerRate1) {
        this.ProducedPowerRate1 = data.ProducedPowerRate1;
        mclient.publish('smartmeter/produced_low', data.ProducedPowerRate1.toString(), {retain: true});
        //console.log(data.ProducedPowerRate1)
    }
  
    if(data.ProducedPowerRate2 != this.ProducedPowerRate2) {
        this.ProducedPowerRate2 = data.ProducedPowerRate2;
        mclient.publish('smartmeter/produced_high', data.ProducedPowerRate2.toString(), {retain: true});
        //console.log(data.ProducedPowerRate2)
    }
  
    if(data.ActualPowerRate != this.ActualPowerRate) {
        //console.log(this.ActualPowerRate);
        if (data.ActualPowerRate == 1) {var new_ActualPowerRate = 'Low'}
        else {var new_ActualPowerRate = 'High'}; 
        this.ActualPowerRate = data.ActualPowerRate;
        mclient.publish('smartmeter/actual_rate', new_ActualPowerRate, {retain: true});
        //console.log(new_ActualPowerRate);
        }
  
    if(data.ActualConsumedPower != this.ActualConsumedPower) {
        this.ActualConsumedPower = data.ActualConsumedPower;
        mclient.publish('smartmeter/actual_consumed', data.ActualConsumedPower.toString(), {retain: true});
        console.log(data.ActualConsumedPower)
        }
  
    if(data.ActualProducedPower != this.ActualProducedPower) {
        this.ActualProducedPower = data.ActualProducedPower;
        mclient.publish('smartmeter/actual_produced', data.ActualProducedPower.toString(), {retain: true});
        //console.log(data.ActualProducedPower)
    }
  
    if(this.GasTimestamp != data.GasTimestamp) {
        this.ConsumedGas = data.ConsumedGas;
        this.GasTimestamp = data.GasTimestamp;
        mclient.publish('smartmeter/gas', data.ConsumedGas.toString(), {retain: true});
        //console.log(data.ConsumedGas)
    }
};
function processTelegram(telegram) {
    var smartMeterId,
        consumedPowerRate1,
        consumedPowerRate2,
        actualConsumedPower,
        actualPowerRate,
        producedPowerRate1,
        producedPowerRate2,
        actualProducedPower,
        gasTimestamp,
        consumedGas;
 
    if(telegram.length === 14) {
        // Process equipment label
        smartMeterId = telegram[0].substr(1);
 
        // Process consumed power
        consumedPowerRate1 = parseFloat(telegram[3].substr(10,9));
        consumedPowerRate2 = parseFloat(telegram[4].substr(10,9));
        actualConsumedPower = parseFloat(telegram[8].substr(10,9));
        actualPowerRate = parseInt(telegram[7].substr(12,4));
 
        // Process produced power
        producedPowerRate1 = parseFloat(telegram[5].substr(10,9));
        producedPowerRate2 = parseFloat(telegram[6].substr(10,9));
        actualProducedPower = parseFloat(telegram[9].substr(10,9));
 
        // Process gas related items
        // Get timestamp last report and convert it to epoch UTC format
        gasTimestamp = new Date(
            parseInt(telegram[16].substr(11,2)) +  2000,
            parseInt(telegram[16].substr(13,2)) - 1,
            parseInt(telegram[16].substr(15,2)),
            parseInt(telegram[16].substr(17,2)),
            parseInt(telegram[16].substr(19,2)),
            parseInt(telegram[16].substr(21,2))
        );
        gasTimestamp = Math.round(gasTimestamp.getTime() / 1000);
        consumedGas = parseFloat(telegram[17].substr(1,9));
        //console.log('Gas Timestamp: ' + gasTimestamp);
        smartMeter.update({
            ConsumedPowerRate1: consumedPowerRate1,
            ConsumedPowerRate2: consumedPowerRate2,
            ProducedPowerRate1: producedPowerRate1,
            ProducedPowerRate2: producedPowerRate2,
            ActualConsumedPower: actualConsumedPower,
            ActualProducedPower: actualProducedPower,
            ActualPowerRate: actualPowerRate,
            GasTimestamp: gasTimestamp,
            ConsumedGas: consumedGas
        }); 
    } else {
        console.log('Invalid number of lines in telegram (' + 
            telegram.length + ')');
    }
}
 
function main() {
     
    var telegram = [];
    console.log('Starting Smart Meter');
 
    SerialPort = serialport.SerialPort;
    smartMeter = new SmartMeter();
 
    serialPort = new SerialPort("/dev/ttyAMA0", {
        baudrate: 9600,
        databits: 7,
        parity: 'even',
        parser: serialport.parsers.readline('\n')
    });
 
    serialPort.on('data', function(line) {
        console.log('Received: ' + line);
        if(line[0] === '!') {
            processTelegram(telegram);
            telegram.length = 0;
        } else {
            telegram.push(line);
        }
    });
}
main();

  

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Tue May 19, 2015 8:18 pm
by Bwired
i think this should work
no need for other adjustments i think, lets see

Code: Select all

serialport = require('serialport'); var mqtt = require('mqtt');

var mclient,
    config,
    SerialPort,
    smartMeter;

mclient = mqtt.createClient(1883, '192.168.178.38'); //set ip of the Rasp or localhost
var net = require('net');
var client = new net.Socket();

function SmartMeter() {
  this.ConsumedPowerRate1 = 0;
  this.ConsumedPowerRate2 = 0;
  this.ProducedPowerRate1 = 0;
  this.ProducedPowerRate2 = 0;
  this.ActualPowerRate = 0;
  this.ActualConsumedPower = 0;
  this.ActualProducedPower = 0;
  this.GasTimestamp = 0;
  this.ConsumedGas = 0;
}

SmartMeter.prototype.update = function(data) {
    //publish the complete telegram to a different topic for logging to for example a mysql dbase (handled in my next blog)
    mclient.publish('historical/smartmeter/data', JSON.stringify(data));
     
    if(data.ConsumedPowerRate1 != this.ConsumedPowerRate1) {
        this.ConsumedPowerRate1 = data.ConsumedPowerRate1;
        mclient.publish('smartmeter/consumed_low', data.ConsumedPowerRate1.toString(), {retain: true});
        //console.log(data.ConsumedPowerRate1)
    }
  
    if(data.ConsumedPowerRate2 != this.ConsumedPowerRate2) {
        this.ConsumedPowerRate2 = data.ConsumedPowerRate2;
        mclient.publish('smartmeter/consumed_high', data.ConsumedPowerRate2.toString(), {retain: true});
        //console.log(data.ConsumedPowerRate2)
    }
  
    if(data.ProducedPowerRate1 != this.ProducedPowerRate1) {
        this.ProducedPowerRate1 = data.ProducedPowerRate1;
        mclient.publish('smartmeter/produced_low', data.ProducedPowerRate1.toString(), {retain: true});
        //console.log(data.ProducedPowerRate1)
    }
  
    if(data.ProducedPowerRate2 != this.ProducedPowerRate2) {
        this.ProducedPowerRate2 = data.ProducedPowerRate2;
        mclient.publish('smartmeter/produced_high', data.ProducedPowerRate2.toString(), {retain: true});
        //console.log(data.ProducedPowerRate2)
    }
  
    if(data.ActualPowerRate != this.ActualPowerRate) {
        //console.log(this.ActualPowerRate);
        if (data.ActualPowerRate == 1) {var new_ActualPowerRate = 'Low'}
        else {var new_ActualPowerRate = 'High'}; 
        this.ActualPowerRate = data.ActualPowerRate;
        mclient.publish('smartmeter/actual_rate', new_ActualPowerRate, {retain: true});
        //console.log(new_ActualPowerRate);
        }
  
    if(data.ActualConsumedPower != this.ActualConsumedPower) {
        this.ActualConsumedPower = data.ActualConsumedPower;
        mclient.publish('smartmeter/actual_consumed', data.ActualConsumedPower.toString(), {retain: true});
        console.log(data.ActualConsumedPower)
        }
  
    if(data.ActualProducedPower != this.ActualProducedPower) {
        this.ActualProducedPower = data.ActualProducedPower;
        mclient.publish('smartmeter/actual_produced', data.ActualProducedPower.toString(), {retain: true});
        //console.log(data.ActualProducedPower)
    }
     
};
function processTelegram(telegram) {
    var smartMeterId,
        consumedPowerRate1,
        consumedPowerRate2,
        actualConsumedPower,
        actualPowerRate,
        producedPowerRate1,
        producedPowerRate2,
        actualProducedPower,
        gasTimestamp,
        consumedGas;

    if(telegram.length === 14) {
        // Process equipment label
        smartMeterId = telegram[0].substr(1);

        // Process consumed power
        consumedPowerRate1 = parseFloat(telegram[3].substr(10,9));
        consumedPowerRate2 = parseFloat(telegram[4].substr(10,9));
        actualConsumedPower = parseFloat(telegram[8].substr(10,9));
        actualPowerRate = parseInt(telegram[7].substr(12,4));

        // Process produced power
        producedPowerRate1 = parseFloat(telegram[5].substr(10,9));
        producedPowerRate2 = parseFloat(telegram[6].substr(10,9));
        actualProducedPower = parseFloat(telegram[9].substr(10,9));
        
        smartMeter.update({
            ConsumedPowerRate1: consumedPowerRate1,
            ConsumedPowerRate2: consumedPowerRate2,
            ProducedPowerRate1: producedPowerRate1,
            ProducedPowerRate2: producedPowerRate2,
            ActualConsumedPower: actualConsumedPower,
            ActualProducedPower: actualProducedPower,
            ActualPowerRate: actualPowerRate
        }); 
    } else {
        console.log('Invalid number of lines in telegram (' + 
            telegram.length + ')');
    }
}

function main() {
     
    var telegram = [];
    console.log('Starting Smart Meter');

    SerialPort = serialport.SerialPort;
    smartMeter = new SmartMeter();

    serialPort = new SerialPort("/dev/ttyAMA0", {
        baudrate: 9600,
        databits: 7,
        parity: 'even',
        parser: serialport.parsers.readline('\n')
    });

    serialPort.on('data', function(line) {
        console.log('Received: ' + line);
        if(line[0] === '!') {
            processTelegram(telegram);
            telegram.length = 0;
        } else {
            telegram.push(line);
        }
    });
}
main();

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Wed May 20, 2015 2:43 pm
by mikeyn
Hi,

Thanks again. making progress now.
I think the code works. i combined the 2 files. I do not know yet how to use upstart or something like that and want to fuocus first to get this running. i copied the webserver.js into the smartmeter.js and this is the output in shell. seems quite ok i guess.

Code: Select all

 pi@raspberrypi ~ $ node smartmeter.js
createClient is deprecated, use connect instead
Option log level is not valid. Please refer to the README.
createClient is deprecated, use connect instead
Starting Smart Meter
Received: /ISk5\2MT382-1004
Received:
Received: 0-0:96.1.1(5A424556303035313834303830353133)
Received: 1-0:1.8.1(02810.484*kWh)
Received: 1-0:1.8.2(03059.122*kWh)
Received: 1-0:2.8.1(00000.000*kWh)
Received: 1-0:2.8.2(00000.001*kWh)
Received: 0-0:96.14.0(0002)
Received: 1-0:1.7.0(0000.72*kW)
Received: 1-0:2.7.0(0000.00*kW)
Received: 0-0:17.0.0(0999.00*kW)
Received: 0-0:96.3.10(1)
Received: 0-0:96.13.1()
Received: 0-0:96.13.0()
Received: !
0.72
Received: /ISk5\2MT382-1004
Received:
Received: 0-0:96.1.1(5A424556303035313834303830353133)
Received: 1-0:1.8.1(02810.484*kWh)
Received: 1-0:1.8.2(03059.125*kWh)
Received: 1-0:2.8.1(00000.000*kWh)
Received: 1-0:2.8.2(00000.001*kWh)
Received: 0-0:96.14.0(0002)
Received: 1-0:1.7.0(0000.72*kW)
Received: 1-0:2.7.0(0000.00*kW)
Received: 0-0:17.0.0(0999.00*kW)
Received: 0-0:96.3.10(1)
Received: 0-0:96.13.1()
Received: 0-0:96.13.0()
Received: !
Received: /ISk5\2MT382-1004
Received:
Received: 0-0:96.1.1(5A424556303035313834303830353133)
Received: 1-0:1.8.1(02810.484*kWh)
Received: 1-0:1.8.2(03059.126*kWh)
Received: 1-0:2.8.1(00000.000*kWh)
Received: 1-0:2.8.2(00000.001*kWh)
Received: 0-0:96.14.0(0002)
Received: 1-0:1.7.0(0000.70*kW)
Received: 1-0:2.7.0(0000.00*kW)
Received: 0-0:17.0.0(0999.00*kW)
Received: 0-0:96.3.10(1)
Received: 0-0:96.13.1()
Received: 0-0:96.13.0()
Received: !
0.7
now the folling problem is that my smartmeter.html shows not the data.
smartmeter.jpg
smartmeter.jpg (37.79 KiB) Viewed 15352 times

i am still missing something but i do not see it.

smartmeter.js:

Code: Select all

var url = require('url');
var path = require('path');
var mqtt = require('mqtt');
var httpd = require('http').createServer(handler),
    io = require('socket.io').listen(httpd),
    fs = require('fs');
httpd.listen(8300);
var client = mqtt.createClient(1883, '192.168.178.38');
io.set('log level', 1);
var consumedValues = new Array();
var tmpValue;
var tmpValue1;
                 
// HTTP server
var MIMETYPES = {
    "html": "text/html",
    "jpeg": "image/jpeg",
    "jpg" : "image/jpeg",
    "png" : "image/png",
    "js"  : "text/javascript",
    "css" : "text/css"};
     
function handler(req, res) {
   
  function html404(uri, res){
    console.log("404 not found: " + uri);
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write('404 Not Found\n');
    res.end();
  }    
   
  var uri = url.parse(req.url).pathname;
  if(uri != '/'){
    var filename = path.join(process.cwd(), uri);
    fs.exists(filename, function(exists) {
        if(!exists) {
            html404(filename, res);
            return;
        }
        var mimeType = MIMETYPES[path.extname(filename).split(".")[1]];
        res.writeHead(200, {'Content-Type':mimeType});
        var fileStream = fs.createReadStream(filename);
        fileStream.pipe(res);
    });
  } else {
    html404(uri, res);
    return;
  }
  }
 
  httpd.on('clientError', function (exception, socket) { 
  console.log('Client error occurred');
});
   
io.sockets.on('connection', function (socket) {
  var clientbb = socket.handshake.address;
  console.log("New connection from " + clientbb.address + ":" + clientbb.port);
  socket.on('subscribe', function (data) {
    console.log('Subscribing to '+data.topic);
    //socket.join(data.topic);
    client.subscribe(data.topic);
  });
   
});
 
client.on('message', function(topic, payload){
    io.sockets.emit('mqtt', {'topic': String(topic),'payload':String(payload) });
    var newPayload = payload;
    switch (topic) { //settings for the graph
        case 'smartmeter/actual_produced':
            if (tmpValue1 == newPayload || newPayload == 0 ) {
                return;
            };  
            tmpValue = newPayload;          
            newPayload = newPayload - (newPayload * 2); //make produced value negative for chart
            break;
        case 'smartmeter/actual_consumed':
            if (tmpValue == newPayload) {
                return;
            };  
            tmpValue1 = newPayload;         
            break;
        default:
            return;
    };
         
    //if (tmpValue != newPayload || tmpValue1 != newPayload) {
        consumedValues.push(newPayload);
        //console.log(consumedValues);
        if (consumedValues.length >= 50) {
            //console.log ('Powervalue shifted');
            consumedValues.shift();
        }
    //};                    
     
    io.sockets.emit('mqtt', {'topic': "smartmeter/graph",'payload':consumedValues });   
         
});


serialport = require('serialport'); var mqtt = require('mqtt');

var mclient,
    config,
    SerialPort,
    smartMeter;

mclient = mqtt.createClient(1883, '192.168.178.38'); //set ip of the Rasp or localhost
var net = require('net');
var client = new net.Socket();

function SmartMeter() {
  this.ConsumedPowerRate1 = 0;
  this.ConsumedPowerRate2 = 0;
  this.ProducedPowerRate1 = 0;
  this.ProducedPowerRate2 = 0;
  this.ActualPowerRate = 0;
  this.ActualConsumedPower = 0;
  this.ActualProducedPower = 0;
  this.GasTimestamp = 0;
  this.ConsumedGas = 0;
}

SmartMeter.prototype.update = function(data) {
    //publish the complete telegram to a different topic for logging to for example a mysql dbase (handled in my next blog)
    mclient.publish('historical/smartmeter/data', JSON.stringify(data));
     
    if(data.ConsumedPowerRate1 != this.ConsumedPowerRate1) {
        this.ConsumedPowerRate1 = data.ConsumedPowerRate1;
        mclient.publish('smartmeter/consumed_low', data.ConsumedPowerRate1.toString(), {retain: true});
        //console.log(data.ConsumedPowerRate1)
    }
  
    if(data.ConsumedPowerRate2 != this.ConsumedPowerRate2) {
        this.ConsumedPowerRate2 = data.ConsumedPowerRate2;
        mclient.publish('smartmeter/consumed_high', data.ConsumedPowerRate2.toString(), {retain: true});
        //console.log(data.ConsumedPowerRate2)
    }
  
    if(data.ProducedPowerRate1 != this.ProducedPowerRate1) {
        this.ProducedPowerRate1 = data.ProducedPowerRate1;
        mclient.publish('smartmeter/produced_low', data.ProducedPowerRate1.toString(), {retain: true});
        //console.log(data.ProducedPowerRate1)
    }
  
    if(data.ProducedPowerRate2 != this.ProducedPowerRate2) {
        this.ProducedPowerRate2 = data.ProducedPowerRate2;
        mclient.publish('smartmeter/produced_high', data.ProducedPowerRate2.toString(), {retain: true});
        //console.log(data.ProducedPowerRate2)
    }
  
    if(data.ActualPowerRate != this.ActualPowerRate) {
        //console.log(this.ActualPowerRate);
        if (data.ActualPowerRate == 1) {var new_ActualPowerRate = 'Low'}
        else {var new_ActualPowerRate = 'High'}; 
        this.ActualPowerRate = data.ActualPowerRate;
        mclient.publish('smartmeter/actual_rate', new_ActualPowerRate, {retain: true});
        //console.log(new_ActualPowerRate);
        }
  
    if(data.ActualConsumedPower != this.ActualConsumedPower) {
        this.ActualConsumedPower = data.ActualConsumedPower;
        mclient.publish('smartmeter/actual_consumed', data.ActualConsumedPower.toString(), {retain: true});
        console.log(data.ActualConsumedPower)
        }
  
    if(data.ActualProducedPower != this.ActualProducedPower) {
        this.ActualProducedPower = data.ActualProducedPower;
        mclient.publish('smartmeter/actual_produced', data.ActualProducedPower.toString(), {retain: true});
        //console.log(data.ActualProducedPower)
    }
     
};
function processTelegram(telegram) {
    var smartMeterId,
        consumedPowerRate1,
        consumedPowerRate2,
        actualConsumedPower,
        actualPowerRate,
        producedPowerRate1,
        producedPowerRate2,
        actualProducedPower,
        gasTimestamp,
        consumedGas;

    if(telegram.length === 14) {
        // Process equipment label
        smartMeterId = telegram[0].substr(1);

        // Process consumed power
        consumedPowerRate1 = parseFloat(telegram[3].substr(10,9));
        consumedPowerRate2 = parseFloat(telegram[4].substr(10,9));
        actualConsumedPower = parseFloat(telegram[8].substr(10,9));
        actualPowerRate = parseInt(telegram[7].substr(12,4));

        // Process produced power
        producedPowerRate1 = parseFloat(telegram[5].substr(10,9));
        producedPowerRate2 = parseFloat(telegram[6].substr(10,9));
        actualProducedPower = parseFloat(telegram[9].substr(10,9));
        
        smartMeter.update({
            ConsumedPowerRate1: consumedPowerRate1,
            ConsumedPowerRate2: consumedPowerRate2,
            ProducedPowerRate1: producedPowerRate1,
            ProducedPowerRate2: producedPowerRate2,
            ActualConsumedPower: actualConsumedPower,
            ActualProducedPower: actualProducedPower,
            ActualPowerRate: actualPowerRate
        }); 
    } else {
        console.log('Invalid number of lines in telegram (' + 
            telegram.length + ')');
    }
}

function main() {
     
    var telegram = [];
    console.log('Starting Smart Meter');

    SerialPort = serialport.SerialPort;
    smartMeter = new SmartMeter();

    serialPort = new SerialPort("/dev/ttyAMA0", {
        baudrate: 9600,
        databits: 7,
        parity: 'even',
        parser: serialport.parsers.readline('\n')
    });

    serialPort.on('data', function(line) {
        console.log('Received: ' + line);
        if(line[0] === '!') {
            processTelegram(telegram);
            telegram.length = 0;
        } else {
            telegram.push(line);
        }
    });
}
main();
&

smartmeter.html:

Code: Select all

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript" src="http://192.168.178.38:8300/node_modules/socket.io/node_modules/socket.io-client/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://192.168.178.38:8300/js/jquery.sparkline.min.js"></script>
<link href='http://fonts.googleapis.com/css?family=Orbitron:700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="styl.css" type="text/css" />
<script type='text/javascript'>
var powerValues = new Array();
var socket = io.connect('http://localhost:8300');
socket.on('connect', function () {
    //$("#sockconn").html("Connected");
        socket.on('mqtt', function (msg) {
            var tp_arr=msg.topic.split("/");
            var d = new Date();
            var now = d.toLocaleTimeString();
            var tp=tp_arr[1];
            switch (tp) {
                case 'graph':
                    $('.hpowerValue').sparkline(msg.payload, {
                        type: 'bar',
                        //zeroAxis: false,
                        barColor: '#ff0000',
                        negBarColor: '#009933',
                        zeroColor: '#009933',
                        width: '200',
                        height: '50',
                    });
                    break;
                     
                default:
                    $('#message').html(msg.topic + ', ' + msg.payload + ' at: ' + now);
                    var payloadOld = $('#'.concat(tp)).html();  
                    $('#'.concat(tp)).html(msg.payload);                    
                    if(payloadOld != $('#'.concat(tp)).html())  {       
                        $("#".concat(tp)).effect("highlight", { color: "#2C3539" }, 1000);
                        }
                };
        });
         
        socket.on('disconnect', function (msg) {
        //$("#sockconn").html("Disconnected");
         
    });
    socket.emit('subscribe',{topic:'smartmeter/#'});
  });
</script>
</head>
<body>
<div id="cnt">
    <div style="margin-bottom:5px;">
        <div id="frame">
            <div id="consumed_high" style="font-size:35px;color:#ff3333;"></div>
            <div id="label_lg">Power High Rate counter (kWh)</div>
        </div>
        <div id="frame">
            <div id="actual_consumed"></div>
            <div id="label_lg" style="font-size:18px;">Current Power consuming (kW)</div>
        </div>
        <div id="frame">
            <div id="consumed_low" style="font-size:35px;color:#ff3333;"></div>
            <div id="label_lg">Power Low Rate counter (kWh)</div>
        </div>
        <div id="frame">
            <div id="produced_high" style="font-size:35px;color:#009933;"></div>
            <div id="label_lg">Produced High Rate counter (kWh)</div>
        </div>
        <div id="frame">
            <div id="actual_produced"></div>
            <div id="label_lg" style="font-size:18px;">Current Power producing (kW)</div>
        </div>
        <div id="frame">
            <div id="produced_low" style="font-size:35px;color:#009933;"></div>
            <div id="label_lg">Produced Low Rate counter (kWh)</div>
        </div>
        <div id="frame">
            <div id="gas" style="font-size:35px;;color:#ff3333;"></div>
            <div id="label_lg">Gas Usage counter (m3)</div>
        </div>
        <div id="frame">
            <div id="sockconn" style="font-size:35px"></div>
            <div id="label_lg">Current Usage/Producing graph (kW)</div>
            <div id="graph_lg" class="hpowerValue"></div>
        </div>
        <div id="frame">
            <div id="actual_rate" style="font-size:35px"></div>
            <div id="label_lg">Actual Power Rate</div>
        </div>
        <div id="frame">
            <div style="font-size:15px;color:#999;">Latest MQTT message: <small id="message">no message received</small></div>
        </div>
         
        </div><br>
    </div>
</div>
</body>
</html> 

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Thu May 21, 2015 9:09 pm
by Bwired
Ok you need to check if your Mosquitto (mqtt) broker is working... are te topics received?
also you use the newest version MQTT nodejs and when i tried that a while back version i could not get it to work with Mosquitto... not sure if its only my problem...but tried a lot!
i use mqtt
"version": "0.3.11",

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Sat May 23, 2015 9:35 am
by Rene
It's your problem Pieter ;-) It still works with mosquitto but had some breaking changes, so you need to adapt your code.

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Sat May 23, 2015 11:47 am
by mikeyn
I have to start over. i got everytime npm errors. All different ones. I will do this tomorrow. Thanks

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Sat May 23, 2015 1:53 pm
by Bwired
@Rene
i know about the Mqtt changes regarding the connect, but even if i do these it was not working with Mosquitto at that time.
perhaps new Mqtt version solved the problem, havent checked yet.
are you working with Mosquitto en latest MQTT version now?
Thanks Pieter

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Sat May 23, 2015 7:11 pm
by Rene
Yes I do.

Re: Bwired Nodejs, MQTT, Websockets Iskra Smartmeter solution

Posted: Wed Sep 09, 2015 12:12 pm
by mikeyn
Hi All,

it is been a wile but i picked up this project again. i still not receiving any data on the website. I will explain what i did.
I followed every bit of the instructions on the website. also on the end i created 1 file for the smartmeter and webserverfile.

Code: Select all

serialport = require('serialport'); var mqtt = require('mqtt');

var mclient,
    config,
    SerialPort,
    smartMeter;

mclient = mqtt.createClient(1883, 'localhost'); //set ip of the Rasp or localhost
var net = require('net');
var client = new net.Socket();

function SmartMeter() {
  this.ConsumedPowerRate1 = 0;
  this.ConsumedPowerRate2 = 0;
  this.ProducedPowerRate1 = 0;
  this.ProducedPowerRate2 = 0;
  this.ActualPowerRate = 0;
  this.ActualConsumedPower = 0;
  this.ActualProducedPower = 0;
  this.GasTimestamp = 0;
  this.ConsumedGas = 0;
}

SmartMeter.prototype.update = function(data) {
    //publish the complete telegram to a different topic for logging to for example a mysql dbase (handled in my next blog)
    mclient.publish('historical/smartmeter/data', JSON.stringify(data));
     
    if(data.ConsumedPowerRate1 != this.ConsumedPowerRate1) {
        this.ConsumedPowerRate1 = data.ConsumedPowerRate1;
        mclient.publish('smartmeter/consumed_low', data.ConsumedPowerRate1.toString(), {retain: true});
        //console.log(data.ConsumedPowerRate1)
    }
  
    if(data.ConsumedPowerRate2 != this.ConsumedPowerRate2) {
        this.ConsumedPowerRate2 = data.ConsumedPowerRate2;
        mclient.publish('smartmeter/consumed_high', data.ConsumedPowerRate2.toString(), {retain: true});
        //console.log(data.ConsumedPowerRate2)
    }
  
    if(data.ProducedPowerRate1 != this.ProducedPowerRate1) {
        this.ProducedPowerRate1 = data.ProducedPowerRate1;
        mclient.publish('smartmeter/produced_low', data.ProducedPowerRate1.toString(), {retain: true});
        //console.log(data.ProducedPowerRate1)
    }
  
    if(data.ProducedPowerRate2 != this.ProducedPowerRate2) {
        this.ProducedPowerRate2 = data.ProducedPowerRate2;
        mclient.publish('smartmeter/produced_high', data.ProducedPowerRate2.toString(), {retain: true});
        //console.log(data.ProducedPowerRate2)
    }
  
    if(data.ActualPowerRate != this.ActualPowerRate) {
        //console.log(this.ActualPowerRate);
        if (data.ActualPowerRate == 1) {var new_ActualPowerRate = 'Low'}
        else {var new_ActualPowerRate = 'High'}; 
        this.ActualPowerRate = data.ActualPowerRate;
        mclient.publish('smartmeter/actual_rate', new_ActualPowerRate, {retain: true});
        //console.log(new_ActualPowerRate);
        }
  
    if(data.ActualConsumedPower != this.ActualConsumedPower) {
        this.ActualConsumedPower = data.ActualConsumedPower;
        mclient.publish('smartmeter/actual_consumed', data.ActualConsumedPower.toString(), {retain: true});
        console.log(data.ActualConsumedPower)
        }
  
    if(data.ActualProducedPower != this.ActualProducedPower) {
        this.ActualProducedPower = data.ActualProducedPower;
        mclient.publish('smartmeter/actual_produced', data.ActualProducedPower.toString(), {retain: true});
        //console.log(data.ActualProducedPower)
    }
     
};
function processTelegram(telegram) {
    var smartMeterId,
        consumedPowerRate1,
        consumedPowerRate2,
        actualConsumedPower,
        actualPowerRate,
        producedPowerRate1,
        producedPowerRate2,
        actualProducedPower,
        gasTimestamp,
        consumedGas;

    if(telegram.length === 14) {
        // Process equipment label
        smartMeterId = telegram[0].substr(1);

        // Process consumed power
        consumedPowerRate1 = parseFloat(telegram[3].substr(10,9));
        consumedPowerRate2 = parseFloat(telegram[4].substr(10,9));
        actualConsumedPower = parseFloat(telegram[8].substr(10,9));
        actualPowerRate = parseInt(telegram[7].substr(12,4));

        // Process produced power
        producedPowerRate1 = parseFloat(telegram[5].substr(10,9));
        producedPowerRate2 = parseFloat(telegram[6].substr(10,9));
        actualProducedPower = parseFloat(telegram[9].substr(10,9));
        
        smartMeter.update({
            ConsumedPowerRate1: consumedPowerRate1,
            ConsumedPowerRate2: consumedPowerRate2,
            ProducedPowerRate1: producedPowerRate1,
            ProducedPowerRate2: producedPowerRate2,
            ActualConsumedPower: actualConsumedPower,
            ActualProducedPower: actualProducedPower,
            ActualPowerRate: actualPowerRate
        }); 
    } else {
        console.log('Invalid number of lines in telegram (' + 
            telegram.length + ')');
    }
}

function main() {
     
    var telegram = [];
    console.log('Starting Smart Meter');

    SerialPort = serialport.SerialPort;
    smartMeter = new SmartMeter();

    serialPort = new SerialPort("/dev/ttyAMA0", {
        baudrate: 9600,
        databits: 7,
        parity: 'even',
        parser: serialport.parsers.readline('\n')
    });

    serialPort.on('data', function(line) {
        console.log('Received: ' + line);
        if(line[0] === '!') {
            processTelegram(telegram);
            telegram.length = 0;
        } else {
            telegram.push(line);
        }
    });
}

main();
var url = require('url');
var path = require('path');
var mqtt = require('mqtt');
var httpd = require('http').createServer(handler),
    io = require('socket.io').listen(httpd),
    fs = require('fs');
httpd.listen(8300);
var client = mqtt.createClient(1883, 'localhost');
io.set('log level', 1);
var consumedValues = new Array();
var tmpValue;
var tmpValue1;
                 
// HTTP server
var MIMETYPES = {
    "html": "text/html",
    "jpeg": "image/jpeg",
    "jpg" : "image/jpeg",
    "png" : "image/png",
    "js"  : "text/javascript",
    "css" : "text/css"};
     
function handler(req, res) {
   
  function html404(uri, res){
    console.log("404 not found: " + uri);
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write('404 Not Found\n');
    res.end();
  }    
   
  var uri = url.parse(req.url).pathname;
  if(uri != '/'){
    var filename = path.join(process.cwd(), uri);
    fs.exists(filename, function(exists) {
        if(!exists) {
            html404(filename, res);
            return;
        }
        var mimeType = MIMETYPES[path.extname(filename).split(".")[1]];
        res.writeHead(200, {'Content-Type':mimeType});
        var fileStream = fs.createReadStream(filename);
        fileStream.pipe(res);
    });
  } else {
    html404(uri, res);
    return;
  }
  }
 
  httpd.on('clientError', function (exception, socket) { 
  console.log('Client error occurred');
});
   
io.sockets.on('connection', function (socket) {
  var clientbb = socket.handshake.address;
  console.log("New connection from " + clientbb.address + ":" + clientbb.port);
  socket.on('subscribe', function (data) {
    console.log('Subscribing to '+data.topic);
    //socket.join(data.topic);
    client.subscribe(data.topic);
  });
   
});
 
client.on('message', function(topic, payload){
    io.sockets.emit('mqtt', {'topic': String(topic),'payload':String(payload) });
    var newPayload = payload;
    switch (topic) { //settings for the graph
        case 'smartmeter/actual_produced':
            if (tmpValue1 == newPayload || newPayload == 0 ) {
                return;
            };  
            tmpValue = newPayload;          
            newPayload = newPayload - (newPayload * 2); //make produced value negative for chart
            break;
        case 'smartmeter/actual_consumed':
            if (tmpValue == newPayload) {
                return;
            };  
            tmpValue1 = newPayload;         
            break;
        default:
            return;
    };
         
    //if (tmpValue != newPayload || tmpValue1 != newPayload) {
        consumedValues.push(newPayload);
        //console.log(consumedValues);
        if (consumedValues.length >= 50) {
            //console.log ('Powervalue shifted');
            consumedValues.shift();
        }
    //};                    
     
    io.sockets.emit('mqtt', {'topic': "smartmeter/graph",'payload':consumedValues });   
         
});
and as server.js

Code: Select all

var url = require('url');
var path = require('path');
var mqtt = require('mqtt');
var httpd = require('http').createServer(handler),
    io = require('socket.io').listen(httpd),
    fs = require('fs');
httpd.listen(8300);
var client = mqtt.createClient(1883, 'localhost');
io.set('log level', 1);
var consumedValues = new Array();
var tmpValue;
var tmpValue1;
                 
// HTTP server
var MIMETYPES = {
    "html": "text/html",
    "jpeg": "image/jpeg",
    "jpg" : "image/jpeg",
    "png" : "image/png",
    "js"  : "text/javascript",
    "css" : "text/css"};
     
function handler(req, res) {
   
  function html404(uri, res){
    console.log("404 not found: " + uri);
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write('404 Not Found\n');
    res.end();
  }    
   
  var uri = url.parse(req.url).pathname;
  if(uri != '/'){
    var filename = path.join(process.cwd(), uri);
    fs.exists(filename, function(exists) {
        if(!exists) {
            html404(filename, res);
            return;
        }
        var mimeType = MIMETYPES[path.extname(filename).split(".")[1]];
        res.writeHead(200, {'Content-Type':mimeType});
        var fileStream = fs.createReadStream(filename);
        fileStream.pipe(res);
    });
  } else {
    html404(uri, res);
    return;
  }
  }
 
  httpd.on('clientError', function (exception, socket) { 
  console.log('Client error occurred');
});
   
io.sockets.on('connection', function (socket) {
  var clientbb = socket.handshake.address;
  console.log("New connection from " + clientbb.address + ":" + clientbb.port);
  socket.on('subscribe', function (data) {
    console.log('Subscribing to '+data.topic);
    //socket.join(data.topic);
    client.subscribe(data.topic);
  });
   
});
 
client.on('message', function(topic, payload){
    io.sockets.emit('mqtt', {'topic': String(topic),'payload':String(payload) });
    var newPayload = payload;
    switch (topic) { //settings for the graph
        case 'smartmeter/actual_produced':
            if (tmpValue1 == newPayload || newPayload == 0 ) {
                return;
            };  
            tmpValue = newPayload;          
            newPayload = newPayload - (newPayload * 2); //make produced value negative for chart
            break;
        case 'smartmeter/actual_consumed':
            if (tmpValue == newPayload) {
                return;
            };  
            tmpValue1 = newPayload;         
            break;
        default:
            return;
    };
         
    //if (tmpValue != newPayload || tmpValue1 != newPayload) {
        consumedValues.push(newPayload);
        //console.log(consumedValues);
        if (consumedValues.length >= 50) {
            //console.log ('Powervalue shifted');
            consumedValues.shift();
        }
    //};                    
     
    io.sockets.emit('mqtt', {'topic': "smartmeter/graph",'payload':consumedValues });   
         
});
the html

Code: Select all

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript" src="http://192.168.2.104:8300/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://192.168.2.104:8300/js/jquery.sparkline.min.js"></script>
<link href='http://fonts.googleapis.com/css?family=Orbitron:700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="style.css" type="text/css" />
<script type='text/javascript'>
var powerValues = new Array();
var socket = io.connect('http://192.168.2.104:8300');
socket.on('connect', function () {
    //$("#sockconn").html("Connected");
        socket.on('mqtt', function (msg) {
            var tp_arr=msg.topic.split("/");
            var d = new Date();
            var now = d.toLocaleTimeString();
            var tp=tp_arr[1];
            switch (tp) {
                case 'graph':
                    $('.hpowerValue').sparkline(msg.payload, {
                        type: 'bar',
                        //zeroAxis: false,
                        barColor: '#ff0000',
                        negBarColor: '#009933',
                        zeroColor: '#009933',
                        width: '200',
                        height: '50',
                    });
                    break;
                     
                default:
                    $('#message').html(msg.topic + ', ' + msg.payload + ' at: ' + now);
                    var payloadOld = $('#'.concat(tp)).html();  
                    $('#'.concat(tp)).html(msg.payload);                    
                    if(payloadOld != $('#'.concat(tp)).html())  {       
                        $("#".concat(tp)).effect("highlight", { color: "#2C3539" }, 1000);
                        }
                };
        });
         
        socket.on('disconnect', function (msg) {
        //$("#sockconn").html("Disconnected");
         
    });
    socket.emit('subscribe',{topic:'smartmeter/#'});
  });
</script>
</head>
<body>
<div id="cnt">
    <div style="margin-bottom:5px;">
        <div id="frame">
            <div id="consumed_high" style="font-size:35px;color:#ff3333;"></div>
            <div id="label_lg">Power High Rate counter (kWh)</div>
        </div>
        <div id="frame">
            <div id="actual_consumed"></div>
            <div id="label_lg" style="font-size:18px;">Current Power consuming (kW)</div>
        </div>
        <div id="frame">
            <div id="consumed_low" style="font-size:35px;color:#ff3333;"></div>
            <div id="label_lg">Power Low Rate counter (kWh)</div>
        </div>
        <div id="frame">
            <div id="produced_high" style="font-size:35px;color:#009933;"></div>
            <div id="label_lg">Produced High Rate counter (kWh)</div>
        </div>
        <div id="frame">
            <div id="actual_produced"></div>
            <div id="label_lg" style="font-size:18px;">Current Power producing (kW)</div>
        </div>
        <div id="frame">
            <div id="produced_low" style="font-size:35px;color:#009933;"></div>
            <div id="label_lg">Produced Low Rate counter (kWh)</div>
        </div>
        <div id="frame">
            <div id="gas" style="font-size:35px;;color:#ff3333;"></div>
            <div id="label_lg">Gas Usage counter (m3)</div>
        </div>
        <div id="frame">
            <div id="sockconn" style="font-size:35px"></div>
            <div id="label_lg">Current Usage/Producing graph (kW)</div>
            <div id="graph_lg" class="hpowerValue"></div>
        </div>
        <div id="frame">
            <div id="actual_rate" style="font-size:35px"></div>
            <div id="label_lg">Actual Power Rate</div>
        </div>
        <div id="frame">
            <div style="font-size:15px;color:#999;">Latest MQTT message: <small id="message">no message received</small></div>
        </div>
         
        </div><br>
    </div>
</div>
</body>
</html>
The output on the site is still blank.
Knipsel.JPG
Knipsel.JPG (49.81 KiB) Viewed 13873 times
the node file gives some errors but after googling i found out that it is not an issue only it would be better to upgrade the files.
Knipsel2.JPG
Knipsel2.JPG (56.24 KiB) Viewed 13873 times
The files are working because when i load the website i get the line "New connection from undefined:undefined"


after some digging and trying to get aquainted with nodeJS and the rest i tried to debug the file on the socket.io. maybe it gives some information for you to help out if possible
Knipsel3.JPG
Knipsel3.JPG (142 KiB) Viewed 13873 times
Knipsel4.JPG
Knipsel4.JPG (110.41 KiB) Viewed 13873 times
I really like to work with this and tried a lot by myself but i can't figure it out. (sorry for that)

Can you help me?