def testPayloadBuilderReset(self): """ Test basic bit message encoding/decoding """ builder = BinaryPayloadBuilder() builder.add_8bit_uint(0x12) builder.add_8bit_uint(0x34) builder.add_8bit_uint(0x56) builder.add_8bit_uint(0x78) self.assertEqual(b'\x12\x34\x56\x78', builder.to_string()) self.assertEqual([b'\x12\x34', b'\x56\x78'], builder.build()) builder.reset() self.assertEqual(b'', builder.to_string()) self.assertEqual([], builder.build())
def testPayloadBuilderReset(self): ''' Test basic bit message encoding/decoding ''' builder = BinaryPayloadBuilder() builder.add_8bit_uint(0x12) builder.add_8bit_uint(0x34) builder.add_8bit_uint(0x56) builder.add_8bit_uint(0x78) self.assertEqual('\x12\x34\x56\x78', str(builder)) self.assertEqual(['\x12\x34', '\x56\x78'], builder.build()) builder.reset() self.assertEqual('', str(builder)) self.assertEqual([], builder.build())
def testPayloadBuilderReset(self): """ Test basic bit message encoding/decoding """ builder = BinaryPayloadBuilder() builder.add_8bit_uint(0x12) builder.add_8bit_uint(0x34) builder.add_8bit_uint(0x56) builder.add_8bit_uint(0x78) self.assertEqual("\x12\x34\x56\x78", str(builder)) self.assertEqual(["\x12\x34", "\x56\x78"], builder.build()) builder.reset() self.assertEqual("", str(builder)) self.assertEqual([], builder.build())
class PayloadHandler: """ encodes/decodes values according to the way it is stored in registry SCALE stands for multiplying/dividing by a scaling factor COMB stands for storing the value of one field in two registers if none of those provided encodes only based on the type """ def __init__(self, env, store): self.byte_order = env["byte_order"] self.word_order = env["word_order"] self.d_s_factor = env["default_scaling_factor"] self.battery_store = store self.builder = BinaryPayloadBuilder(byteorder=self.byte_order, wordorder=self.word_order) def encode(self, value, encoding): self.builder.reset() encode_type = { INT8: lambda x: self.builder.add_8bit_int(x), UINT8: lambda x: self.builder.add_8bit_uint(x), INT16: lambda x: self.builder.add_16bit_int(x), UINT16: lambda x: self.builder.add_16bit_uint(x), INT32: lambda x: self.builder.add_32bit_int(x), UINT32: lambda x: self.builder.add_32bit_uint(x), FLOAT32: lambda x: self.builder.add_32bit_float(x), } if 'e_type' not in encoding or encoding['e_type'] == COMB: encode_type[encoding['d_type']](value) else: encode_type[encoding['d_type']](round( value * encoding.get('s_factor', self.d_s_factor))) return self.builder.to_registers() def decode(self, fx, addr, encoding): encoded_value = self.battery_store.getValues(fx, addr, 2) decoder = BinaryPayloadDecoder.fromRegisters(encoded_value, byteorder=self.byte_order, wordorder=self.word_order) decode_type = { INT8: lambda: decoder.decode_8bit_int(), UINT8: lambda: decoder.decode_8bit_uint(), INT16: lambda: decoder.decode_16bit_int(), UINT16: lambda: decoder.decode_16bit_uint(), INT32: lambda: decoder.decode_32bit_int(), UINT32: lambda: decoder.decode_32bit_uint(), FLOAT32: lambda: decoder.decode_32bit_float(), } if 'e_type' not in encoding or encoding['e_type'] == COMB: return decode_type[encoding['d_type']]() else: return decode_type[encoding['d_type']]() / encoding.get( 's_factor', self.d_s_factor)
def test_modbus_getting_values(self): test_modbus_config = { "attributes": [ { "string": { "byteOrder": "BIG", "tag": "string", "type": "string", "functionCode": 4, "registerCount": 4 } }, { "bits": { "byteOrder": "BIG", "tag": "bits", "type": "bits", "functionCode": 4, "registerCount": 1 } }, { "8int": { "byteOrder": "BIG", "tag": "8int", "type": "8int", "functionCode": 4, "registerCount": 1 } }, { "16int": { "byteOrder": "BIG", "tag": "16int", "type": "16int", "functionCode": 4, "registerCount": 1 } }, { "long": { "byteOrder": "BIG", "tag": "long", "type": "long", "functionCode": 4, "registerCount": 1 } }, { "long_with_divider": { "byteOrder": "BIG", "tag": "long", "type": "long", "functionCode": 4, "registerCount": 1, "divider": 10 } }, { "32int": { "byteOrder": "BIG", "tag": "32int", "type": "32int", "functionCode": 4, "registerCount": 2 } }, { "64int": { "byteOrder": "BIG", "tag": "64int", "type": "64int", "functionCode": 4, "registerCount": 4 } }, ], "timeseries": [ { "8uint": { "byteOrder": "BIG", "tag": "8uint", "type": "8uint", "functionCode": 4, "registerCount": 1 } }, { "16uint": { "byteOrder": "BIG", "tag": "16uint", "type": "16uint", "functionCode": 4, "registerCount": 2 } }, { "32uint": { "byteOrder": "BIG", "tag": "32uint", "type": "32uint", "functionCode": 4, "registerCount": 4 } }, { "64uint": { "byteOrder": "BIG", "tag": "64uint", "type": "64uint", "functionCode": 4, "registerCount": 1 } }, { "double": { "byteOrder": "BIG", "tag": "double", "type": "double", "functionCode": 4, "registerCount": 2 } }, { "16float": { "byteOrder": "BIG", "tag": "16float", "type": "16float", "functionCode": 4, "registerCount": 1 } }, { "32float": { "byteOrder": "BIG", "tag": "32float", "type": "32float", "functionCode": 4, "registerCount": 2 } }, { "64float": { "byteOrder": "BIG", "tag": "64float", "type": "64float", "functionCode": 4, "registerCount": 4 } }, ] } test_modbus_body_to_convert = {} test_modbus_convert_config = {} test_modbus_result = { 'deviceName': 'Modbus Test', 'deviceType': 'default', 'telemetry': [{ '8uint': 18 }, { '16uint': 4660 }, { '32uint': 305419896 }, { '64uint': 1311768468603649775 }, { 'double': 22.5 }, { '16float': 1.240234375 }, { '32float': 22.34000015258789 }, { '64float': -123.45 }], 'attributes': [{ 'string': 'abcdefgh' }, { 'bits': [False, True, False, True, True, False, True, False] }, { '8int': -18 }, { '16int': -22136 }, { 'long': -22136 }, { 'long_with_divider': -2213.6 }, { '32int': -4660 }, { '64int': -3735928559 }] } builder = BinaryPayloadBuilder(byteorder=Endian.Big) builder_registers = { "string": (builder.add_string, 'abcdefgh'), "bits": (builder.add_bits, [0, 1, 0, 1, 1, 0, 1, 0]), "8int": (builder.add_8bit_int, -0x12), "16int": (builder.add_16bit_int, -0x5678), "long": (builder.add_16bit_int, -0x5678), "long_with_divider": (builder.add_16bit_int, -0x5678), "32int": (builder.add_32bit_int, -0x1234), "64int": (builder.add_64bit_int, -0xDEADBEEF), "8uint": (builder.add_8bit_uint, 0x12), "16uint": (builder.add_16bit_uint, 0x1234), "32uint": (builder.add_32bit_uint, 0x12345678), "64uint": (builder.add_64bit_uint, 0x12345678DEADBEEF), "double": (builder.add_32bit_float, 22.5), "16float": (builder.add_16bit_float, 1.24), "32float": (builder.add_32bit_float, 22.34), "64float": (builder.add_64bit_float, -123.45), } class DummyResponse: def __init__(self, registers): self.registers = registers[:] for datatype in test_modbus_config: test_modbus_body_to_convert[datatype] = {} for tag_dict in test_modbus_config[datatype]: for tag in tag_dict: builder_registers[tag][0](builder_registers[tag][1]) test_modbus_body_to_convert[datatype].update({ tag: { "input_data": DummyResponse(builder.to_registers()), "data_sent": tag_dict[tag] } }) builder.reset() converter = BytesModbusUplinkConverter({ "deviceName": "Modbus Test", "deviceType": "default", "unitId": 1 }) result = converter.convert(test_modbus_convert_config, test_modbus_body_to_convert) self.assertDictEqual(result, test_modbus_result)
class modbusServer(): def __init__(self): self.__logging() self.cfg = yamlImport.importYAML("./cfg/modbusSettings.yaml") self.builder = BinaryPayloadBuilder(endian=Endian.Little) self.__setupContext() self.__serverInfo() self.__configureServer() def __logging(self): import logging logging.basicConfig() log = logging.getLogger() log.setLevel(logging.INFO) def __setupContext(self): #Setup Coils co = ModbusSequentialDataBlock(1, [0]*1) di = ModbusSequentialDataBlock(1, [0]*6) #Setup Registers (Inc floats) for i in range(0,3): self.builder.add_32bit_float(0.0) ir = ModbusSequentialDataBlock(1, self.builder.to_registers()) for i in range(0,3): self.builder.add_32bit_float(0.0) hr = ModbusSequentialDataBlock(1, self.builder.to_registers()) #Setup datastore store = ModbusSlaveContext(co=co,di=di,hr=hr,ir=ir) self.context = ModbusServerContext(slaves=store, single=True) def __serverInfo(self): self.identity = ModbusDeviceIdentification() self.identity.VendorName = self.cfg["VendorName"] self.identity.VendorUrl = self.cfg["VendorUrl"] self.identity.ProductName = self.cfg["ProductName"] self.identity.ModelName = self.cfg["ModelName"] self.identity.MajorMinorRevision = self.cfg["Revision"] def __getIPAddress(self): if self.cfg["manualIP"] == "N": return socket.gethostbyname(socket.gethostname()) return self.cfg["ip"] def __configureServer(self): if self.cfg["method"] == "tcp": self.servTCP = ModbusTcpServer(self.context, identity=self.identity, address=(self.__getIPAddress(), self.cfg["tcpPort"])) elif self.cfg["method"] == "rtu": self.servRTU = ModbusSerialServer(self.context, framer=ModbusRtuFramer, identity=self.identity, port=self.cfg["rtuPort"], stopbits=self.cfg["stopbits"], bytesize=self.cfg["bytesize"], parity=self.cfg["parity"], baudrate=self.cfg["baudrate"], timeout=self.cfg["timeout"]) else: raise ReferenceError("Invalid server type") def runServer(self): if self.cfg["method"] == "tcp": self.servTCP.serve_forever() elif self.cfg["method"] == "rtu": self.servRTU.serve_forever() else: raise ReferenceError("Invalid server type") def stopServer(self): if self.cfg["method"] == "tcp": self.servTCP.server_close() self.servTCP.shutdown() elif self.cfg["method"] == "rtu": self.servRTU.server_close() else: raise ReferenceError("Invalid server type") def encodeData(self,data): self.builder.reset() try: for i in range(0,len(data)): self.builder.add_32bit_float(data[i]) except TypeError: self.builder.add_32bit_float(data) return self.builder.to_registers() def decodeData(self,data): returnData = [0]*(len(data)/2) decoder = BinaryPayloadDecoder.fromRegisters(data, endian=Endian.Little) for i in range(0,len(data)/2): returnData[i] = round(decoder.decode_32bit_float(),2) return returnData
def write(self): try: lb = 00000000 hb = 00000000 #### byte besteht immer aus 16 bits for byte in self._db['out']: for bit in sorted(self._db['out'][byte]): if bit in self._db['out'][byte]: bitpos = bit[0] #startbit/bitposition des binärwertes type = bit[1] value = bit[2] name = bit[3] bit[2] = bit[3]() ##aktueller wert des items abrufen und value updaten! builder = BinaryPayloadBuilder(endian=Endian.Little) ##unterscheidung dateityp if type == '5' or type == '5.001' or type == '6' : ##8bit uint / int length = 8 if bitpos < 8: #lb lb = value else: #hb hb = value if type == '5': builder.add_8bit_uint(lb) builder.add_8bit_uint(hb) #logger.debug('MODBUS: 8bit uint {0} ; {1}'.format(lb,hb)) elif type == '5.001': ##0-100 in 0-255 umwandeln! #print(dpts.en5001(lb)) #print(dpts.en5001(hb)) lb = self.de5001(lb) hb = self.de5001(hb) #print("lb geschrieben", lb ) #print("hb geschrieben", hb ) builder.add_8bit_uint(lb) builder.add_8bit_uint(hb) #logger.debug('MODBUS: 8bit uint {0} ; {1}'.format(lb,hb)) elif type == '6': if lb > 127: lb = 127 elif lb < -128: lb = -128 if hb > 127: hb = 127 elif hb < -128: hb = -128 builder.add_8bit_int(lb) builder.add_8bit_int(hb) #logger.debug('MODBUS: 8bit int {0} ; {1}'.format(lb.hb)) elif type == '7' or type == '8': #16bit uint / int length = 16 if type == '7': #0...65535 builder.add_16bit_uint(value) #logger.debug('MODBUS: 16bit uint {0} '.format(value)) else: #-32768...32767 builder.add_16bit_int(value) #logger.debug('MODBUS: 16bit int {0}'.format(value)) elif type == '1': length = 1 #nur pro byte einmal die bits wandeln if bitpos < 8: #lb lb = lb | int(value) << bitpos #logger.debug('MODBUS: 8bit int{0}'.format(lb)) else: #hb hb = hb | int(value) << bitpos #logger.debug('MODBUS: 8bit int{0}'.format(hb)) builder.add_8bit_uint(lb) builder.add_8bit_uint(hb) payload = builder.build() logger.debug('MODBUS: write to PLC: WORD {0} set to {1} '.format(byte,payload)) self._modbuspy.write_registers(byte, payload, skip_encode=True) builder.reset() except Exception as e: logger.error('MODBUS: Could not write an OutWord, because {}'.format(e)) self._lock.release() return None
print 'speed (m/s) ', gpsd.fix.speed print 'climb ', gpsd.fix.climb print 'track ', gpsd.fix.track print 'mode ', gpsd.fix.mode print print 'sats ', gpsd.satellites builder.add_32bit_float(gpsd.fix.latitude) builder.add_32bit_float(gpsd.fix.longitude) payload = builder.build() #print payload client.write_registers(0, payload, skip_encode=True) time.sleep(1) #set to whatever payload = builder.reset() #except ConnectionException as e: #when you press ctrl+c # print "\nKilling Thread...Modbus server not running" # print e # gpsp.running=False # client.close() except (KeyboardInterrupt, SystemExit): print "\nKilling Thread..." gpsp.running = False client.close() gpsp.join() # wait for the thread to finish what it's doing print "Done.\nExiting."
bytesize=8, parity='N', baudrate=115200, timeout=0.5) #Connect to the serial modbus server connection = client.connect() print(connection) builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) builder.add_16bit_uint(5) #Type of packet payload = builder.to_registers() payload = builder.build() client.write_registers(0, payload, skip_encode=True, unit=mb_unit) builder.reset() #time.sleep(20) builder.add_16bit_uint(6) #Type of packet payload = builder.to_registers() payload = builder.build() client.write_registers(0, payload, skip_encode=True, unit=mb_unit) builder.reset() #time.sleep(20) builder.add_16bit_uint(0) #Type of packet payload = builder.to_registers() payload = builder.build() client.write_registers(0, payload, skip_encode=True, unit=mb_unit) builder.reset()
class modbusServer(): def __init__(self): self.__logging() self.cfg = yamlImport.importYAML("./cfg/modbusSettings.yaml") self.builder = BinaryPayloadBuilder(endian=Endian.Little) self.__setupContext() self.__serverInfo() self.__configureServer() def __logging(self): import logging logging.basicConfig() log = logging.getLogger() log.setLevel(logging.INFO) def __setupContext(self): #Setup Coils co = ModbusSequentialDataBlock(1, [0] * 1) di = ModbusSequentialDataBlock(1, [0] * 6) #Setup Registers (Inc floats) for i in range(0, 3): self.builder.add_32bit_float(0.0) ir = ModbusSequentialDataBlock(1, self.builder.to_registers()) for i in range(0, 3): self.builder.add_32bit_float(0.0) hr = ModbusSequentialDataBlock(1, self.builder.to_registers()) #Setup datastore store = ModbusSlaveContext(co=co, di=di, hr=hr, ir=ir) self.context = ModbusServerContext(slaves=store, single=True) def __serverInfo(self): self.identity = ModbusDeviceIdentification() self.identity.VendorName = self.cfg["VendorName"] self.identity.VendorUrl = self.cfg["VendorUrl"] self.identity.ProductName = self.cfg["ProductName"] self.identity.ModelName = self.cfg["ModelName"] self.identity.MajorMinorRevision = self.cfg["Revision"] def __getIPAddress(self): if self.cfg["manualIP"] == "N": return socket.gethostbyname(socket.gethostname()) return self.cfg["ip"] def __configureServer(self): if self.cfg["method"] == "tcp": self.servTCP = ModbusTcpServer(self.context, identity=self.identity, address=(self.__getIPAddress(), self.cfg["tcpPort"])) elif self.cfg["method"] == "rtu": self.servRTU = ModbusSerialServer(self.context, framer=ModbusRtuFramer, identity=self.identity, port=self.cfg["rtuPort"], stopbits=self.cfg["stopbits"], bytesize=self.cfg["bytesize"], parity=self.cfg["parity"], baudrate=self.cfg["baudrate"], timeout=self.cfg["timeout"]) else: raise ReferenceError("Invalid server type") def runServer(self): if self.cfg["method"] == "tcp": self.servTCP.serve_forever() elif self.cfg["method"] == "rtu": self.servRTU.serve_forever() else: raise ReferenceError("Invalid server type") def stopServer(self): if self.cfg["method"] == "tcp": self.servTCP.server_close() self.servTCP.shutdown() elif self.cfg["method"] == "rtu": self.servRTU.server_close() else: raise ReferenceError("Invalid server type") def encodeData(self, data): self.builder.reset() try: for i in range(0, len(data)): self.builder.add_32bit_float(data[i]) except TypeError: self.builder.add_32bit_float(data) return self.builder.to_registers() def decodeData(self, data): returnData = [0] * (len(data) / 2) decoder = BinaryPayloadDecoder.fromRegisters(data, endian=Endian.Little) for i in range(0, len(data) / 2): returnData[i] = round(decoder.decode_32bit_float(), 2) return returnData
print 'speed (m/s) ' , gpsd.fix.speed print 'climb ' , gpsd.fix.climb print 'track ' , gpsd.fix.track print 'mode ' , gpsd.fix.mode print print 'sats ' , gpsd.satellites builder.add_32bit_float(gpsd.fix.latitude) builder.add_32bit_float(gpsd.fix.longitude) payload = builder.build() #print payload client.write_registers(0, payload, skip_encode=True) time.sleep(1) #set to whatever payload = builder.reset() #except ConnectionException as e: #when you press ctrl+c # print "\nKilling Thread...Modbus server not running" # print e # gpsp.running=False # client.close() except (KeyboardInterrupt, SystemExit): print "\nKilling Thread..." gpsp.running = False client.close() gpsp.join() # wait for the thread to finish what it's doing print "Done.\nExiting."