diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a2ae8b7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +serial +modbus_tk +configparser +pymodbus +paho-mqtt diff --git a/sdm630-mqtt.conf b/sdm630-mqtt.conf index 548f728..2e058fe 100644 --- a/sdm630-mqtt.conf +++ b/sdm630-mqtt.conf @@ -5,8 +5,15 @@ keepalive=10 topic_prefix=/sdm630 [sdm630] -host=localhost -port=5002 regfile=registers.csv num_meters=1 id1=1 +connection_type=tcp + +[tcp] +host=localhost +port=5002 + +[rs485] +PORT=/dev/usbserial/sdm630 +BAUDRATE=9600 diff --git a/sdm630-mqtt.py b/sdm630-mqtt.py old mode 100644 new mode 100755 index 19e25ea..e95cb74 --- a/sdm630-mqtt.py +++ b/sdm630-mqtt.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf_8 -*- -from sdm630 import SDM630 +from sdm630 import * import sys import serial @@ -28,7 +28,7 @@ def publish(topic,value): config = ConfigParser.ConfigParser() confread = config.read(CONFIG_FILE) logging.info("Read config {}".format(confread)) -logging.info("Opening port {}".format(config.get("sdm630","port"))) + logging.info("Connecting to MQTT server...") mqclient = mqtt.Client() @@ -45,12 +45,22 @@ def publish(topic,value): logging.info("Setup...") num_meters = config.getint("sdm630","num_meters") meters = [] +connection_type = config.get("sdm630", "connection_type") + for i in range(num_meters): - meter = SDM630(config.get("sdm630","host"), - config.get("sdm630","port"), - config.getint("sdm630","id"+str(i+1)), - config.get("sdm630","regfile")) - meter.connect() + if connection_type == 'tcp': + logging.info("Opening port {}".format(config.get("tcp","port"))) + meter = SDM630TCP(host=config.get("tcp","host"), + port=config.get("tcp","port"), + aid=config.getint("sdm630","id"+str(i+1)), + regfile=config.get("sdm630", "regfile")) + elif connection_type == 'rs485': + logging.info("Opening port {}".format(config.get("rs485","port"))) + meter = SDM630RS485(config.get("rs485","PORT"), + config.getint("rs485","BAUDRATE"), + config.getint("sdm630","id"+str(i+1)), + regfile=config.get("sdm630", "regfile")) + meters.append(meter) logging.info("Entering endless loop") diff --git a/sdm630.py b/sdm630.py index 027a07a..1f206a6 100644 --- a/sdm630.py +++ b/sdm630.py @@ -1,28 +1,25 @@ # -*- coding: utf_8 -*- from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client.sync import ModbusSerialClient from pymodbus.payload import BinaryPayloadDecoder from pymodbus.constants import Endian + import serial import time import csv class SDM630(object): - def __init__(self,host,port,aid,regfile): + def __init__(self, regfile): + self.__fill_registers__(regfile) + + def __fill_registers__(self, regfile): self.registers = {} with open(regfile) as regs: reader = csv.reader(regs,delimiter=';') for line in reader: self.registers[line[1]] = int(line[0],base=16) - self.aid = aid - self.host = host - self.port = port - - def connect(self): - self.master = ModbusTcpClient(host=self.host,port=self.port) -# self.master.set_timeout(1.0) -# self.master.set_verbose(True) - + def __getattr__(self,attr): if attr == "voltx3": @@ -46,3 +43,27 @@ def read_registers(self,addr,count): return decoder.decode_32bit_float() return tuple(decoder.decode_32bit_float() for _ in range(count)) +# connecting using tcp +class SDM630TCP(SDM630): + def __init__(self,host,port,aid,regfile): + SDM630.__init__(self,regfile) + + self.aid = aid + self.host = host + self.port = port + + self.master = ModbusTcpClient(host=self.host,port=self.port) + + +# connecting using serial port +class SDM630RS485(SDM630): + def __init__(self, port, baudrate, aid, regfile): + SDM630.__init__(self,regfile) + + self.port = port + self.baudrate = baudrate + self.aid = aid + + self.master = ModbusSerialClient("rtu", port=self.port, baudrate=self.baudrate, timeout=1) + + diff --git a/test.py b/test.py old mode 100644 new mode 100755 index 85fea6d..1106b06 --- a/test.py +++ b/test.py @@ -8,9 +8,11 @@ from struct import * import serial +import sys import modbus_tk import modbus_tk.defines as cst from modbus_tk import modbus_rtu +import configparser def read_float(arrRegs): reg1 = arrRegs[1] @@ -32,17 +34,31 @@ def bcdDigits(chars): return yield val -PORT = '/dev/usbserial/sdm630' SLAVE = 1 def main(): """main""" logger = modbus_tk.utils.create_logger("console") + CONFIG_FILE = 'sdm630-mqtt.conf' + if ((len(sys.argv) == 3) and sys.argv[1] == '-c'): + CONFIG_FILE = sys.argv[2] + + config = configparser.ConfigParser() + config.read(CONFIG_FILE) + rs485 = config['rs485'] + PORT=rs485.get('PORT') + BAUDRATE=rs485.getint('BAUDRATE', 9600) + BYTESIZE=rs485.getint('BYTESIZE', 8) + PARITY=rs485.get('PARITY', 'N') + STOPBITS=rs485.getint('STOPBITS', 1) + XONXOFF=rs485.getint('XONXOFF', 0) + DSRDTR=rs485.getboolean('DSRDTR', True) + try: #Connect to the slave master = modbus_rtu.RtuMaster( - serial.Serial(port=PORT, baudrate=9600, bytesize=8, parity='N', stopbits=1, xonxoff=0, dsrdtr=True) + serial.Serial(port=PORT, baudrate=BAUDRATE, bytesize=BYTESIZE, parity=PARITY, stopbits=STOPBITS, xonxoff=XONXOFF, dsrdtr=DSRDTR) ) master.set_timeout(1.0) # master.set_verbose(True)