Dank @starfish haben wir nun eine Möglichkeit modbus Daten zu pollen. Das ist uU ganz hilfreich (zumindest bis ein Modbus-Adapter fertig ist).
Ich habe für meine Zwecke das Python-Script angepasst, da ich serielle Geräte am Bus habe. Zudem wollte ich mehrere Werte abfragen.
Hier das Python-Script 'pymodhaus.py' (liegt bei mir in /home/pi/modbus-crawler):
#!/usr/bin/env python
import sys, time, json
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.transaction import ModbusRtuFramer
def decode32(decval):
decoder = BinaryPayloadDecoder.fromRegisters(decval.registers, endian=Endian.Big)
return decoder.decode_32bit_float()
def decode64(decval):
decoder = BinaryPayloadDecoder.fromRegisters(decval.registers, endian=Endian.Big)
return decoder.decode_64bit_int()
client = ModbusClient(method='rtu', port='/dev/ttyUSB0', stopbits=1, bytesize=8, timeout=0.05, baudrate=19200, parity='N')
connection = client.connect()
#print "Connection: ", connection * Only for debug
try:
timestamp = str(time.time()).split('.')[0]
# iEM3155 Haus --> Adresse immer 1 kleiner als im Schneider Datenblatt; weiss der Geier warum
# HausL01 = decode32(client.read_holding_registers(3028-1, 2, unit=10))
# HausL02 = decode32(client.read_holding_registers(3030-1, 2, unit=10))
# HausL03 = decode32(client.read_holding_registers(3032-1, 2, unit=10))
HausLNM = decode32(client.read_holding_registers(3036-1, 2, unit=10))
HausP01 = decode32(client.read_holding_registers(3054-1, 2, unit=10)) * 1000
HausP02 = decode32(client.read_holding_registers(3056-1, 2, unit=10)) * 1000
HausP03 = decode32(client.read_holding_registers(3058-1, 2, unit=10)) * 1000
HausPower = decode32(client.read_holding_registers(3060-1, 2, unit=10)) * 1000
# HausPowerB = decode32(client.read_holding_registers(3068-1, 2, unit=10)) * 1000
# HausPowerS = decode32(client.read_holding_registers(3076-1, 2, unit=10)) * 1000
HausImport = decode64(client.read_holding_registers(3204-1, 4, unit=10)) / 1000
HausExport = decode64(client.read_holding_registers(3208-1, 4, unit=10)) / 1000
except:
print 6
else:
json_string = json.dumps({'ts': timestamp, 'HausLNM': round(HausLNM,2),
'HausP01': round(HausP01,0), 'HausP02': round(HausP02,0), 'HausP03': round(HausP03,0),
'HausPower': round(HausPower,0),'HausImport': HausImport, 'HausExport': HausExport})
print json_string
client.close()
Nun zum iobroker.javascript:
// Create Datenpunkte für PV-Anlage
createState('javascript.1.Solar.pi1Result', '');
createState('javascript.1.Solar.modPoll', 1);
// Create Datenpunkte für Schneider EnergyMeter 'Haus'
createState('javascript.1.Solar.Schneider.HausLNM', 0);
createState('javascript.1.Solar.Schneider.HausP01', 0);
createState('javascript.1.Solar.Schneider.HausP02', 0);
createState('javascript.1.Solar.Schneider.HausP03', 0);
createState('javascript.1.Solar.Schneider.HausPower', 0);
createState('javascript.1.Solar.Schneider.HausImport', 0);
createState('javascript.1.Solar.Schneider.HausExport', 0);
createState('javascript.1.Solar.Schneider.HausTimeStamp', 0);
schedule({astro: "sunrise"}, function () {
setState('javascript.1.Solar.modPoll', 1, true);
});
schedule({astro: "sunset"}, function () {
setState('javascript.1.Solar.modPoll', 0, true);
});
//Schedule Script Run Haus
schedule("*/1 * * * *", function (Haus) {
var enabled = getState("javascript.1.Solar.modPoll"/*javascript.1.Solar.modPoll*/).val;
if (enabled == 1) {
var python = require('child_process').spawn('python', ["/home/pi/modbus-crawler/pymodhaus.py"]);
// second argument is array of parameters, e.g.:
var result = '';
python.stdout.on('data', function(data){ result += data.toString(); });
python.on('close', function(code1){
if (code1 !== 0) {
log('Error: ' + code1, 'error');
} else {
if (result == 6) {
log('Error: Fehler im Modbus Python Script -Haus-', 'warn');
} else {
log('Modbus Python Script -Haus- erfolgreich gelaufen, Werte akzeptiert');
setState('javascript.1.Solar.pi1Result', result);
var solar1 = JSON.parse(result);
setState('javascript.1.Solar.Schneider.HausLNM', solar1.HausLNM, true);
setState('javascript.1.Solar.Schneider.HausP01', solar1.HausP01, true);
setState('javascript.1.Solar.Schneider.HausP02', solar1.HausP02, true);
setState('javascript.1.Solar.Schneider.HausP03', solar1.HausP03, true);
setState('javascript.1.Solar.Schneider.HausPower', solar1.HausPower, true);
setState('javascript.1.Solar.Schneider.HausImport', solar1.HausImport, true);
setState('javascript.1.Solar.Schneider.HausExport', solar1.HausExport, true);
setState('javascript.1.Solar.Schneider.HausTimeStamp', solar1.ts, true);
}
}
});
}
});
Etwas komplexer hat sich dann der Umstand erwiesen, dass ich das Script (mangels tcp) lokal am Solar-PI laufen lassen muss. Daher musste ein iobroker als remote-host auf den PI. Aber dass ist ein ganz anderes Thema.
Version 0.1.0 2015-06-22 First release