def on_btnSetPump_clicked(self,button): rr_p = self.client_p.read_holding_registers(500,100,unit=1) decoder = BinaryPayloadDecoder.fromRegisters(rr_p.registers[52:53],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() self.pmax = self.adjustPMax.get_value() _qmax = self.adjustQMax.get_value() self.p_count += 1 rr_p.registers[50] = self.p_count rr_p.registers[60] = int(self.pmax) if self.chkPAna.get_active(): self.qmax = getFlowRateAsVolts(_qmax) v = getVoltsFromFlowRate(self.qmax) print "_qmax => {0} self.qmax => {1} c => {2}".format(_qmax, self.qmax, v) rr_p.registers[64] = self.qmax rr_p.registers[62] = int(_qmax/litCiclo) bits_552[12] = True else: self.qmax = _qmax rr_p.registers[62] = int(self.qmax) rr_p.registers[64] = cicli_volt[int(self.qmax)] bits_552[12] = False b_builder = BinaryPayloadBuilder(endian=Endian.Little) # builder.add_bits(bits_502) b_builder.add_bits(bits_552) reg_552 = b_builder.to_registers() rr_p.registers[52:53] = reg_552 rr_p = self.client_p.write_registers(500,rr_p.registers,unit=1)
def default_pump_val_factory(): default_val = [0x00]*600 # DA 500 A 549 DATI SCRITTI DA PLC POMPE default_val[0] = 12345 default_val[1] = 1 default_val[2] = 2 default_val[3] = 3 # qui inizia default_val[500] = 1 # APP_PER VERIFICA COMUNICAZIONE as_bits_502 = [0]*16 as_bits_502[0] = 1 as_bits_502[6] = 1 as_bits_502[10] = 1 builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_bits(as_bits_502) reg=builder.to_registers() print " STATO MACCHINA 1 ( IN BIT ) %d" % reg[0] default_val[502] = reg[0] # STATO MACCHINA 1 ( IN BIT ) default_val[503] = 0 # %MW503 STATO MACCHINA 2 ( IN BIT ) default_val[504] = 0 # %MW504 ALLARMI MACHINA 1 ( IN BIT ) default_val[505] = 0 # %MW505 ALLARMI MACHINA 2 ( IN BIT ) default_val[506] = 0 # %MW506 COPIA STATO COMANDO REMOTO 1 MOMENTANEO ( bit ) default_val[507] = 1 # %MW507 COPIA STATO COMANDO REMOTO 2 MOMENTANEO ( bit ) default_val[508] = 1 # %MW508 COPIA STATO COMANDO REMOTO 1 CONTINUO ( bit ) default_val[509] = 1 # %MW509 COPIA STATO COMANDO REMOTO 2 CONTINUO ( bit ) default_val[512] = 1 # %MW512 TEMPO DI ATTIVITA' DELLA POMPA default_val[513] = 1 # %MW513 TEMPO DI ATTIVITA' DELLA POMPA INIETTORE default_val[514] = 2 # %MW514 TEMPO DI ATTIVITA' DELLA POMPA GIORNALIERO default_val[515] = 2 # %MW515 TEMPO DI ATTIVITA' DELLA INIETTORE GIORNALIERO default_val[516] = 1 # %MW516 PRESSIONE ATTUALE default_val[517] = 3 # %MW517 default_val[518] = 4 # %MW518 default_val[519] = 4 # %MW519 cicli_min = 29 default_val[520] = cicli_min # %MW519 %MW520 CICLI / MINUTO q_default = cicli_min*liters_cycle q_m_ch = 60.0*q_default/1000.0 # conversione float - Endian.Little il primo è il meno significativo builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_32bit_float(q_default) builder.add_32bit_float(q_m_ch) reg=builder.to_registers() default_val[522:526]=reg # DA 550 A 599 DATI LETTI DA PLC POMPE default_val[550] = 1 # %MW550 CONTATORE PER VERIFICA COMUNICAZIONE default_val[551] = 1 # %MW551 default_val[552] = 0 # %MW552 COMANDO MACCHINA DA REMOTO 1 MOMENTANEO ( bit ) default_val[553] = 2 # %MW553 COMANDO MACCHINA DA REMOTO 2 MOMENTANEO ( bit ) default_val[554] = 3 # %MW554 COMANDO MACCHINA DA REMOTO 1 CONTINUO ( bit ) default_val[555] = 3 # %MW555 COMANDO MACCHINA DA REMOTO 2 CONTINUO ( bit ) default_val[556] = 4 # %MW556 default_val[557] = 4 # %MW557 default_val[558] = 5 # %MW558 default_val[559] = 5 # %MW559 default_val[560] = 0 # %MW560 COMANDO BAR DA REMOTO default_val[561] = 6 # %MW561 default_val[562] = 0 # %MW562 COMANDO NUMERO CICLI MINUTO DA REMOTO default_val[599] = 600 # logInfo.debug("default values: " + str(default_val)) return default_val
def encode_field(self, value, mb_type='unit16'): builder = BinaryPayloadBuilder(endian=self.endian) if mb_type == 'bit' or mb_type == 'bits': builder.add_bits(value) elif mb_type == 'uint8': builder.add_8bit_uint(value) elif mb_type == 'uint16': builder.add_16bit_uint(value) elif mb_type == 'uint32': builder.add_32bit_uint(value) elif mb_type == 'uint64': builder.add_64bit_uint(value) elif mb_type == 'int8': builder.add_8bit_int(value) elif mb_type == 'int16': builder.add_16bit_int(value) elif mb_type == 'int32': builder.add_32bit_int(value) elif mb_type == 'int64': builder.add_64bit_int(value) elif mb_type == 'float32': builder.add_32bit_float(value) elif mb_type == 'float64': builder.add_64bit_float(value) elif mb_type == 'string' or mb_type == 'str': builder.add_string(value) else: log.warn('Not supported DataType: "%s"' % mb_type) return builder.build()
def on_switchPumpStatus_state_set(self, switch,gparam): self.ret_p=self.client_p.connect() rr = self.client_p.read_holding_registers(500,100,unit=1) # conversione in bit array da 552 decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[52:53],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[2:7],endian=Endian.Little) # 502 bits_502 = decoder.decode_bits() bits_502 += decoder.decode_bits() # 503 bits_503 = decoder.decode_bits() bits_503 += decoder.decode_bits() # 504 bits_504 = decoder.decode_bits() bits_504 += decoder.decode_bits() # 505 bits_505 = decoder.decode_bits() bits_505 += decoder.decode_bits() # 506 bits_506 = decoder.decode_bits() bits_506 += decoder.decode_bits() bSendCommand = False if switch.get_active(): # %MW552:X2 START INIET. DA REMOTO bSendCommand = not bits_502[7] bits_552[2] = True bits_552[3] = False bits_552[14] = True else: # %MW552:X2 STOP INIET. DA REMOTO bSendCommand = bits_502[7] bits_552[2] = False bits_552[3] = True bits_552[14] = False builder = BinaryPayloadBuilder(endian=Endian.Little) # builder.add_bits(bits_502) builder.add_bits(bits_552) reg_552 = builder.to_registers() rr.registers[52:53] = reg_552 self.p_count += 1 rr.registers[50] = self.p_count if bSendCommand: self.client_p.write_registers(500, rr.registers,unit=1) if bits_552[2]: bits_552[2] = False builder = BinaryPayloadBuilder(endian=Endian.Little) # builder.add_bits(bits_502) builder.add_bits(bits_552) reg_552 = builder.to_registers() self.client_p.write_register(552, reg_552[0]) print "pulsante rilasciato" self.client_p.close()
def checkPump(self,client_p): rr = client_p.read_holding_registers(500,100,unit=1) # conversione in bit array da 552 decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[52:53],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() bits_552[10] = True b_builder = BinaryPayloadBuilder(endian=Endian.Little) b_builder.add_bits(bits_552) reg_552 = b_builder.to_registers() rr.registers[52:53] = reg_552 for it in range(10): self.p_count += 1 rr.registers[50] = self.p_count rq = client_p.write_registers(500, rr.registers,unit=1) if rq.function_code < 0x80: rr_p = client_p.read_holding_registers(500,100,unit=1) if len(rr_p.registers)==100 and rr_p.registers[0]==self.p_count: decoder = BinaryPayloadDecoder.fromRegisters(rr_p.registers[2:7],endian=Endian.Little) # 502 bits_502 = decoder.decode_bits() bits_502 += decoder.decode_bits() # 503 bits_503 = decoder.decode_bits() bits_503 += decoder.decode_bits() # 504 bits_504 = decoder.decode_bits() bits_504 += decoder.decode_bits() # 505 bits_505 = decoder.decode_bits() bits_505 += decoder.decode_bits() # 506 bits_506 = decoder.decode_bits() bits_506 += decoder.decode_bits() if bits_502[7]: builder.get_object("switchPumpStatus").set_active(True) else: builder.get_object("switchPumpStatus").set_active(False) if bits_502[4] == False and bits_502[10] == True: builder.get_object("switchPumpStatus").set_sensitive(True) else: builder.get_object("switchPumpStatus").set_sensitive(False) else: print "errore checkPump %d" % self.p_count bits_552[10] = False print str(bits_552) b_builder = BinaryPayloadBuilder(endian=Endian.Little) b_builder.add_bits(bits_552) reg_552_2 = b_builder.to_registers() rr.registers[52:53] = reg_552_2 rq = client_p.write_registers(500, rr.registers,unit=1) if rq.function_code < 0x80: pass else: print "checkPump terminato con scrittura KO"
def stop_iniettore(p_client): b_ok = False bits_552 = [False]*16 bits_552[3] = True # %MW552:X3 STOP INIET.DA REMOTO builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_bits(bits_552) reg_552 = builder.to_registers() rq = p_client.write_register(552, reg_552[0],unit=1) b_ok = rq.function_code < 0x80 # test that we are not an error return b_ok
def start_iniettore(p_client): b_ok = False n_numReg = 5 # leggo 502 a 506 per verificare bit di controllo p_rr = p_client.read_holding_registers(502,n_numReg,unit=1) decoder = BinaryPayloadDecoder.fromRegisters(p_rr.registers,endian=Endian.Little) reg={} regnum = 502 for i in range(n_numReg): bits_50x = decoder.decode_bits() bits_50x += decoder.decode_bits() reg[regnum+i] = bits_50x if reg[502][4]: log.error("Pompa in allarme") else: if reg[502][6]: log.debug("Pompa olio on") if reg[502][7]: log.error("Ciclo Iniettore ON") else: log.debug("Ciclo Iniettore OFF") # %MW502:X10 Macchina pronta per comando remoto b_ok = reg[502][10] if b_ok: log.debug("Macchina pronta per comando remoto") else: log.error(u"Macchina non è pronta per comando remoto") b_ok &= check_alarms(reg[504]) if b_ok: log.debug("...nessun allarme rilevato") p_comandi_remoto = p_client.read_holding_registers(560,3,unit=1) remote_reg = [0]*3 remote_reg = p_comandi_remoto.registers log.debug("COMANDO BAR DA REMOTO IMPOSTATO a %d" % remote_reg[0]) # %MW560 16 bit 0-100 bar COMANDO BAR DA REMOTO log.debug("COMANDO NUMERO CICLI MINUTO DA REMOTO a %d" % remote_reg[2]) # %MW562 16 bit < 40 COMANDO NUMERO CICLI MINUTO DA REMOTO remote_reg[0] = DEFAULT_BAR remote_reg[2] = DEFAULT_CICLI rq = p_client.write_registers(560, remote_reg,unit=1) b_ok = rq.function_code < 0x80 # test that we are not an error if b_ok: bits_552 = [False]*16 bits_552[2] = True # %MW552:X2 START INIET. DA REMOTO builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_bits(bits_552) reg_552 = builder.to_registers() rq = p_client.write_register(552, reg_552[0],unit=1) b_ok = rq.function_code < 0x80 # test that we are not an error else: log.error("start_iniettore SET Comandi BAR e CICLI REMOTO fallito!") else: log.debug("...verificare allarmi rilevati") else: log.error("Pompa olio OFF") return b_ok
def make_block(section, test_val, test_params): #print("Format", section) builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big) # TYPES TO BE ADDED value = 0 data_size = 0 for s in section: field_name = test_params["field_name"].format(source=s[4], block=s[5], field=s[6] ) #print(field_name, test_val[field_name], s) print("Add: ", data_size, s, end="") value = test_val[field_name] #value += 1 if s[0] == "float16": builder.add_16bit_uint(round(value) ) data_size +=1 elif s[0] == "uint16": #print(value, float(value), s[2] , s[3] ) #print("values:", s, value) val = int( ( float(value) - float(s[3])) / float(s[2]) ) #print("values:", s, value, val) builder.add_16bit_uint(val) data_size+=1 elif s[0] == "uint32": val = int(float(value) / float(s[2]) - float(s[3]) ) builder.add_32bit_uint(val) data_size += 2 elif s[0] in ["int32", "sint32"]: val = int(float(value) / float(s[2]) - float(s[3]) ) builder.add_32bit_int(val) data_size +=2 elif s[0] == "float32": val = float(value) / float(s[2]) - float(s[3]) builder.add_32bit_float(val) data_size +=2 elif s[0] == "bit16": builder.add_bits([0, 0, 0, 0, 0, 0, 0, 0] ) builder.add_bits([0, 0, 0, 0, 0, 0, 0, 0] ) val = 0 data_size += 1 elif s[0][:3] == "str": data_length = int(s[1]) val = " " * (data_length - len(str(value))) + str(value) builder.add_string(val) data_size += data_length/2 else: print(" ------ ", s) print(val) #value += 1 block = ModbusSequentialDataBlock(1, builder.to_registers()) return block
def run_payload_server(): # ----------------------------------------------------------------------- # # build your payload # ----------------------------------------------------------------------- # builder = BinaryPayloadBuilder(byteorder=Endian.Little, wordorder=Endian.Little) builder.add_string('abcdefgh') builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0]) builder.add_8bit_int(-0x12) builder.add_8bit_uint(0x12) builder.add_16bit_int(-0x5678) builder.add_16bit_uint(0x1234) builder.add_32bit_int(-0x1234) builder.add_32bit_uint(0x12345678) builder.add_16bit_float(12.34) builder.add_16bit_float(-12.34) builder.add_32bit_float(22.34) builder.add_32bit_float(-22.34) builder.add_64bit_int(-0xDEADBEEF) builder.add_64bit_uint(0x12345678DEADBEEF) builder.add_64bit_uint(0xDEADBEEFDEADBEED) builder.add_64bit_float(123.45) builder.add_64bit_float(-123.45) # ----------------------------------------------------------------------- # # use that payload in the data store # ----------------------------------------------------------------------- # # Here we use the same reference block for each underlying store. # ----------------------------------------------------------------------- # block = ModbusSequentialDataBlock(1, builder.to_registers()) store = ModbusSlaveContext(di=block, co=block, hr=block, ir=block) context = ModbusServerContext(slaves=store, single=True) # ----------------------------------------------------------------------- # # initialize the server information # ----------------------------------------------------------------------- # # If you don't set this or any fields, they are defaulted to empty strings. # ----------------------------------------------------------------------- # identity = ModbusDeviceIdentification() identity.VendorName = 'Pymodbus' identity.ProductCode = 'PM' identity.VendorUrl = 'http://github.com/riptideio/pymodbus/' identity.ProductName = 'Pymodbus Server' identity.ModelName = 'Pymodbus Server' identity.MajorMinorRevision = version.short() # ----------------------------------------------------------------------- # # run the server you want # ----------------------------------------------------------------------- # StartTcpServer(context, identity=identity, address=("localhost", 5020))
def setValues(self, address, values): ''' Sets the requested values of the datastore :param address: The starting address :param values: The new values to be set ''' if not isinstance(values, list): values = [values] start = address - self.address self.values[start:start + len(values)] = values if start <= 550 < start + len(values): if self.values[500] != values[550-start]: logInfo.debug("ModbusMySequentialDataBlock.setValues updating 500({0}) with new value {1}".format(self.values[500],values[550-start])) self.values[500] = values[550-start] if start <= 552 < start + len(values): global g_Time global s_Time decoder = BinaryPayloadDecoder.fromRegisters(self.values[502:503],endian=Endian.Little) bits_502 = decoder.decode_bits() bits_502 += decoder.decode_bits() decoder = BinaryPayloadDecoder.fromRegisters(self.values[506:507],endian=Endian.Little) bits_506 = decoder.decode_bits() bits_506 += decoder.decode_bits() decoder = BinaryPayloadDecoder.fromRegisters(values[552-start:553-start],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() logInfo.debug("ModbusMySequentialDataBlock.setValues updating 552({0}) {1}".format(values[552-start], bits_552)) if bits_552[2]: print "ModbusMySequentialDataBlock.setValues start iniettore da remoto" logInfo.debug("ModbusMySequentialDataBlock.setValues start iniettore da remoto") g_Time = 0 bits_502[7] = 1 # START INIETTORE self.hndlr.pumpStarted = True bits_506[2] = 1 bits_506[3] = 0 bits_552[2] = 0 bits_builder = BinaryPayloadBuilder(endian=Endian.Little) bits_builder.add_bits(bits_502) bits_builder.add_bits(bits_506) bits_builder.add_bits(bits_552) bits_reg = bits_builder.to_registers() self.values[502:503]=[bits_reg[0]] self.values[506:507]=[bits_reg[1]] self.values[552:553]=[bits_reg[2]] if bits_552[3]: print "ModbusMySequentialDataBlock.setValues stop iniettore da remoto" logInfo.debug("ModbusMySequentialDataBlock.setValues stop iniettore da remoto") bits_502[7] = 0 # STOP INIETTORE bits_506[2] = 0 self.hndlr.pumpStarted = False bits_506[3] = 1 bits_552[3] = 0 bits_builder = BinaryPayloadBuilder(endian=Endian.Little) bits_builder.add_bits(bits_502) bits_builder.add_bits(bits_506) bits_builder.add_bits(bits_552) bits_reg=bits_builder.to_registers() self.values[502:503]=[bits_reg[0]] self.values[506:507]=[bits_reg[1]] self.values[552:553]=[bits_reg[2]]
def run_payload_server(): # ----------------------------------------------------------------------- # # build your payload # ----------------------------------------------------------------------- # builder = BinaryPayloadBuilder(byteorder=Endian.Little, wordorder=Endian.Little) builder.add_string('abcdefgh') builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0]) builder.add_8bit_int(-0x12) builder.add_8bit_uint(0x12) builder.add_16bit_int(-0x5678) builder.add_16bit_uint(0x1234) builder.add_32bit_int(-0x1234) builder.add_32bit_uint(0x12345678) builder.add_32bit_float(22.34) builder.add_32bit_float(-22.34) builder.add_64bit_int(-0xDEADBEEF) builder.add_64bit_uint(0x12345678DEADBEEF) builder.add_64bit_uint(0xDEADBEEFDEADBEED) builder.add_64bit_float(123.45) builder.add_64bit_float(-123.45) # ----------------------------------------------------------------------- # # use that payload in the data store # ----------------------------------------------------------------------- # # Here we use the same reference block for each underlying store. # ----------------------------------------------------------------------- # block = ModbusSequentialDataBlock(1, builder.to_registers()) store = ModbusSlaveContext(di=block, co=block, hr=block, ir=block) context = ModbusServerContext(slaves=store, single=True) # ----------------------------------------------------------------------- # # initialize the server information # ----------------------------------------------------------------------- # # If you don't set this or any fields, they are defaulted to empty strings. # ----------------------------------------------------------------------- # identity = ModbusDeviceIdentification() identity.VendorName = 'Pymodbus' identity.ProductCode = 'PM' identity.VendorUrl = 'http://github.com/bashwork/pymodbus/' identity.ProductName = 'Pymodbus Server' identity.ModelName = 'Pymodbus Server' identity.MajorMinorRevision = '1.5' # ----------------------------------------------------------------------- # # run the server you want # ----------------------------------------------------------------------- # StartTcpServer(context, identity=identity, address=("localhost", 5020))
def testBigEndianPayloadBuilder(self): ''' Test basic bit message encoding/decoding ''' builder = BinaryPayloadBuilder(endian=Endian.Big) builder.add_8bit_uint(1) builder.add_16bit_uint(2) builder.add_32bit_uint(3) builder.add_64bit_uint(4) builder.add_8bit_int(-1) builder.add_16bit_int(-2) builder.add_32bit_int(-3) builder.add_64bit_int(-4) builder.add_32bit_float(1.25) builder.add_64bit_float(6.25) builder.add_string(b'test') builder.add_bits(self.bitstring) self.assertEqual(self.big_endian_payload, builder.to_string())
def testLittleEndianPayloadBuilder(self): ''' Test basic bit message encoding/decoding ''' builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_8bit_uint(1) builder.add_16bit_uint(2) builder.add_32bit_uint(3) builder.add_64bit_uint(4) builder.add_8bit_int(-1) builder.add_16bit_int(-2) builder.add_32bit_int(-3) builder.add_64bit_int(-4) builder.add_32bit_float(1.25) builder.add_64bit_float(6.25) builder.add_string('test') builder.add_bits(self.bitstring) self.assertEqual(self.little_endian_payload, str(builder))
def testLittleEndianPayloadBuilder(self): """ Test basic bit message encoding/decoding """ builder = BinaryPayloadBuilder(byteorder=Endian.Little, wordorder=Endian.Little) builder.add_8bit_uint(1) builder.add_16bit_uint(2) builder.add_32bit_uint(3) builder.add_64bit_uint(4) builder.add_8bit_int(-1) builder.add_16bit_int(-2) builder.add_32bit_int(-3) builder.add_64bit_int(-4) builder.add_32bit_float(1.25) builder.add_64bit_float(6.25) builder.add_16bit_uint(1) # placeholder builder.add_string(b'test') builder.add_bits(self.bitstring) self.assertEqual(self.little_endian_payload, builder.to_string())
def on_btnSetPump_clicked(self,button): rr_p = self.client_p.read_holding_registers(500,100,unit=1) decoder = BinaryPayloadDecoder.fromRegisters(rr_p.registers[52:53],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() self.pmax = self.adjustPMax.get_value() self.qmax = self.adjustQMax.get_value() self.p_count += 1 rr_p.registers[50] = self.p_count rr_p.registers[60] = int(self.pmax) if self.chkPAna.get_active(): rr_p.registers[64] = int(self.qmax) # TODO rr_p.registers[62] = equivalente mappato bits_552[12] = True else: rr_p.registers[62] = int(self.qmax) rr_p.registers[64] = cicli_volt[int(self.qmax)] bits_552[12] = False b_builder = BinaryPayloadBuilder(endian=Endian.Little) # builder.add_bits(bits_502) b_builder.add_bits(bits_552) reg_552 = b_builder.to_registers() rr_p.registers[52:53] = reg_552 rr_p = self.client_p.write_registers(500,rr_p.registers,unit=1)
#!/usr/bin/env python3 from pymodbus.server.sync import StartTcpServer #from pymodbus.constants import Endian from pymodbus.payload import BinaryPayloadBuilder from pymodbus.device import ModbusDeviceIdentification from pymodbus.datastore import ModbusSequentialDataBlock from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext #builder_di = BinaryPayloadBuilder() #builder_di.add_bits([1,1,1,1,1,1,1,1]) # [heater,cooler,...] builder_co = BinaryPayloadBuilder() builder_co.add_bits([0, 0, 0, 0, 0, 0, 0, 0]) # temperature builder_hr = BinaryPayloadBuilder() builder_hr.add_8bit_int(70) # wanted to use input registers for temperature, but they are read only #builder_ir = BinaryPayloadBuilder() #builder_ir.add_8bit_int(70) #di_block = ModbusSequentialDataBlock(0x01, builder_di.to_coils()) co_block = ModbusSequentialDataBlock(0x101, builder_co.to_coils()) hr_block = ModbusSequentialDataBlock(0x201, builder_hr.to_registers()) #ir_block = ModbusSequentialDataBlock(0x301, builder_ir.to_registers()) #store = ModbusSlaveContext(di=di_block, co=co_block, hr=hr_block, ir=ir_block) store = ModbusSlaveContext(co=co_block, hr=hr_block)
def run_binary_payload_ex(): # ----------------------------------------------------------------------- # # We are going to use a simple client to send our requests # ----------------------------------------------------------------------- # client = ModbusClient('127.0.0.1', port=5020) client.connect() # ----------------------------------------------------------------------- # # If you need to build a complex message to send, you can use the payload # builder to simplify the packing logic. # # Here we demonstrate packing a random payload layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - another 16 bit unsigned int 0x5678 # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # - an 32 bit uint 0x12345678 # - an 32 bit signed int -0x1234 # - an 64 bit signed int 0x12345678 # The packing can also be applied to the word (wordorder) and bytes in each # word (byteorder) # The wordorder is applicable only for 32 and 64 bit values # Lets say we need to write a value 0x12345678 to a 32 bit register # The following combinations could be used to write the register # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # # Word Order - Big Byte Order - Big # word1 =0x1234 word2 = 0x5678 # Word Order - Big Byte Order - Little # word1 =0x3412 word2 = 0x7856 # Word Order - Little Byte Order - Big # word1 = 0x5678 word2 = 0x1234 # Word Order - Little Byte Order - Little # word1 =0x7856 word2 = 0x3412 # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # # ----------------------------------------------------------------------- # combos = [(wo, bo) for wo in [Endian.Big, Endian.Little] for bo in [Endian.Big, Endian.Little]] for wo, bo in combos: print("-" * 60) print("Word Order: {}".format(ORDER_DICT[wo])) print("Byte Order: {}".format(ORDER_DICT[bo])) print() builder = BinaryPayloadBuilder(byteorder=bo, wordorder=wo) strng = "abcdefgh" builder.add_string(strng) builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0]) builder.add_8bit_int(-0x12) builder.add_8bit_uint(0x12) builder.add_16bit_int(-0x5678) builder.add_16bit_uint(0x1234) builder.add_32bit_int(-0x1234) builder.add_32bit_uint(0x12345678) builder.add_16bit_float(12.34) builder.add_16bit_float(-12.34) builder.add_32bit_float(22.34) builder.add_32bit_float(-22.34) builder.add_64bit_int(-0xDEADBEEF) builder.add_64bit_uint(0x12345678DEADBEEF) builder.add_64bit_uint(0x12345678DEADBEEF) builder.add_64bit_float(123.45) builder.add_64bit_float(-123.45) payload = builder.to_registers() print("-" * 60) print("Writing Registers") print("-" * 60) print(payload) print("\n") payload = builder.build() address = 0 # Can write registers # registers = builder.to_registers() # client.write_registers(address, registers, unit=1) # Or can write encoded binary string client.write_registers(address, payload, skip_encode=True, unit=1) # ----------------------------------------------------------------------- # # If you need to decode a collection of registers in a weird layout, the # payload decoder can help you as well. # # Here we demonstrate decoding a random register layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - another 16 bit unsigned int which we will ignore # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # ----------------------------------------------------------------------- # address = 0x0 count = len(payload) result = client.read_holding_registers(address, count, unit=1) print("-" * 60) print("Registers") print("-" * 60) print(result.registers) print("\n") decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=bo, wordorder=wo) assert decoder._byteorder == builder._byteorder, \ "Make sure byteorder is consistent between BinaryPayloadBuilder and BinaryPayloadDecoder" assert decoder._wordorder == builder._wordorder, \ "Make sure wordorder is consistent between BinaryPayloadBuilder and BinaryPayloadDecoder" decoded = OrderedDict([ ('string', decoder.decode_string(len(strng))), ('bits', decoder.decode_bits()), ('8int', decoder.decode_8bit_int()), ('8uint', decoder.decode_8bit_uint()), ('16int', decoder.decode_16bit_int()), ('16uint', decoder.decode_16bit_uint()), ('32int', decoder.decode_32bit_int()), ('32uint', decoder.decode_32bit_uint()), ('16float', decoder.decode_16bit_float()), ('16float2', decoder.decode_16bit_float()), ('32float', decoder.decode_32bit_float()), ('32float2', decoder.decode_32bit_float()), ('64int', decoder.decode_64bit_int()), ('64uint', decoder.decode_64bit_uint()), ('ignore', decoder.skip_bytes(8)), ('64float', decoder.decode_64bit_float()), ('64float2', decoder.decode_64bit_float()), ]) print("-" * 60) print("Decoded Data") print("-" * 60) for name, value in iteritems(decoded): print("%s\t" % name, hex(value) if isinstance(value, int) else value) # ----------------------------------------------------------------------- # # close the client # ----------------------------------------------------------------------- # client.close()
if bits_502[4] == False and bits_502[10] == True: print "Macchina senza allarmi e pronta per comando remoto" # Leggo START INIETTORE DA REMOTO reg 522 rr = client.read_holding_registers(40552,1) decoder = BinaryPayloadDecoder.fromRegisters(rr.registers,endian=Endian.Little) as_bits = decoder.decode_bits() as_bits += decoder.decode_bits() print "522 " + str(as_bits) if bits_506[2]: print u"Macchina già avviata con comando remoto" if as_bits[3] == False: print u"STOP INIETTORE DA REMOTO è abassato" # Accendo bit STOP INIETTORE DA REMOTO as_bits[3] = 1 builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_bits(as_bits) reg=builder.to_registers() print reg rq = client.write_register(40552, reg[0]) assert(rq.function_code < 0x80) # test that we are not an error else: print u"STOP INIETTORE DA REMOTO è ancora alzato" else: if as_bits[2] == False: print u"START INIETTORE DA REMOTO è abassato" # Accendo bit START INIETTORE DA REMOTO as_bits[2] = 1 builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_bits(as_bits) reg=builder.to_registers() print reg
# configure the service logging #---------------------------------------------------------------------------# import logging logging.basicConfig() log = logging.getLogger() log.setLevel(logging.DEBUG) #---------------------------------------------------------------------------# # build your payload #---------------------------------------------------------------------------# builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_string('abcdefgh') builder.add_32bit_float(22.34) builder.add_16bit_uint(0x1234) builder.add_8bit_int(0x12) builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0]) #---------------------------------------------------------------------------# # use that payload in the data store #---------------------------------------------------------------------------# # Here we use the same reference block for each underlying store. #---------------------------------------------------------------------------# block = ModbusSequentialDataBlock(1, builder.to_registers()) store = ModbusSlaveContext(di=block, co=block, hr=block, ir=block) context = ModbusServerContext(slaves=store, single=True) #---------------------------------------------------------------------------# # initialize the server information #---------------------------------------------------------------------------# # If you don't set this or any fields, they are defaulted to empty strings.
#!/usr/bin/env python3 from pymodbus.server.sync import StartTcpServer #from pymodbus.constants import Endian from pymodbus.payload import BinaryPayloadBuilder from pymodbus.device import ModbusDeviceIdentification from pymodbus.datastore import ModbusSequentialDataBlock from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext builder_di = BinaryPayloadBuilder() #builder.add_bits([0,0,0,1,1,0,1,1]) builder_di.add_bits([1, 1, 1, 1, 1, 1, 1, 1]) builder_co = BinaryPayloadBuilder() #builder.add_bits([0,0,0,0,1,1,1,1]) builder_co.add_bits([0, 0, 0, 0, 0, 0, 0, 0]) builder_hr = BinaryPayloadBuilder() builder_hr.add_string('abcdefgh') builder_ir = BinaryPayloadBuilder() builder_ir.add_8bit_int(33) di_block = ModbusSequentialDataBlock(0x01, builder_di.to_coils()) co_block = ModbusSequentialDataBlock(0x101, builder_co.to_coils()) hr_block = ModbusSequentialDataBlock(0x201, builder_hr.to_registers()) ir_block = ModbusSequentialDataBlock(0x301, builder_ir.to_registers()) store = ModbusSlaveContext(di=di_block, co=co_block, hr=hr_block, ir=ir_block) context = ModbusServerContext(slaves=store, single=True)
def main(): # IP = input("Slave IP: ") # ID = input("Slave ID: ") IP = "192.168.0.13" ID = 2 client = ModbusCLient(IP, port=502) if client.connect() == False: debug.error("Unable to connect to PLC") return while True: payload = client.read_holding_registers(0, 1, unit=ID) # print(payload.bits) decoder = BinaryPayloadDecoder.fromRegisters(payload.registers, byteorder=Endian.Little, wordorder=Endian.Big) port_0 = decoder.decode_bits() payload = client.read_holding_registers(1, 1, unit=ID) decoder = BinaryPayloadDecoder.fromRegisters(payload.registers, byteorder=Endian.Big, wordorder=Endian.Little) port_1 = decoder.decode_bits() debug.info("Input 0: {}".format(port_0)) q_0 = port_0[0] debug.debug(q_0) debug.info("Input 1: {}".format(port_1)) # decoded = OrderedDict([ # ('Port_0', decoder.decode_bits()), # ('Port_1', decoder.decode_bits()), # # # ('Analog_1', decoder.decode_32bit_int()), # # # ('Analog_2', decoder.decode_16bit_int()), # ]) # # for name,value in iteritems(decoded): # debug.info("{}: {}\t".format(name,value)) # print("vida: {}".format(decoder.decode_bits())) # print(payload.registers) # print("Bits: {}".format(decoder.decode_bits(1))) payload = client.read_holding_registers(2, 2, unit=ID) debug.debug("Payload: {} {}".format(payload.getRegister(0), payload.getRegister(1))) # decoder = BinaryPayloadDecoder.fromRegisters(payload.registers, # byteorder = Endian.Little, # wordorder = Endian.Little) # decoded = OrderedDict([ # # ('Port_0', decoder.decode_bits()), # # ('Port_1', decoder.decode_bits()), # ('Analog_1', decoder.decode_16bit_int()), # ('Analog_2', decoder.decode_16bit_int()), # ]) # # sleep(10) builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) builder.add_bits([1, 1, 0, 0, 0, 0, 1, 0]) payload = builder.to_registers() debug.debug(payload) client.write_registers(4, payload, unit=ID)
def updating_writer(a): ''' A worker process that runs every so often and updates live values of the context. It should be noted that there is a race condition for the update. :param arguments: The input arguments to the call ''' global g_Time global s_Time global g_increment if g_Time >= 60*20: g_Time = 0 log.debug("g_Time reset") print "g_Time reset" g_Time += 1 log.debug("updating the context at {0}".format(g_Time)) context = a[0] srv_id = a[1] register = 3 slave_id = 0x00 # gets current values if context[slave_id].zero_mode: START_ADDRESS = FIRST_REGISTER # if zero_mode=True else: START_ADDRESS = FIRST_REGISTER-1 # if zero_mode=False. inizia a leggere da 40000 e prendi gli N successivi,escluso il 40000 values = context[slave_id].getValues(register, START_ADDRESS, count=NUM_REGISTERS) # update P and Q with random values log.debug("pump context values: " + str(values)) decoder = BinaryPayloadDecoder.fromRegisters(values[502:503],endian=Endian.Little) bits_502 = decoder.decode_bits() bits_502 += decoder.decode_bits() decoder = BinaryPayloadDecoder.fromRegisters(values[552:553],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() decoder = BinaryPayloadDecoder.fromRegisters(values[506:507],endian=Endian.Little) bits_506 = decoder.decode_bits() bits_506 += decoder.decode_bits() if g_Time >= s_Time > 0: print "start iniettore dopo {0} secondi".format(s_Time) log.debug("start iniettore dopo {0} secondi".format(s_Time)) s_Time = 0 bits_502[7] = 1 # START INIETTORE bits_builder = BinaryPayloadBuilder(endian=Endian.Little) bits_builder.add_bits(bits_502) bits_reg=bits_builder.to_registers() values[502:503]=[bits_reg[0]] cicli_min = 0 p_new = 0 # if iniettore Started if bits_502[7]: s_Time = 0 #cicli_min = cicli_rand.rvs() cicli_min = int( out_val_q(g_Time,50.) ) p_new = int(out_val_p(g_Time,values[560])) + delta_rand.rvs() + 1 if p_new < 1: cicli_min = 70. else: cicli_min = 70./p_new if g_Time % 13 == 0: g_increment += 1 p_new = p_new + g_increment ########################################## ### Verifica limite massimo P ############################# if p_new >= values[560]: log.debug("PMax exceeded: %d (516) > %d (560)" % (p_new,values[560]) ) p_new = values[560] + delta_rand.rvs() + 1 ########################################## ### Verifica limite massimo Q ############################# if cicli_min >= values[562]: log.debug("QMax exceeded: %d (520) > %d (562)" % (cicli_min,values[562]) ) cicli_min = values[562] else: if values[560] == 0: print "560 è zero" values[560] = 1 if p_new/values[560] >= 0.5: cicli_min = max(1,int((values[560])/max(1,p_new))) else: cicli_min = 3*values[560]/max(1,p_new) else: cicli_min = 0 p_new = 0 log.debug("p_new=%d" % p_new) q_val = cicli_min*liters_cycle q_m_ch = 60.0*q_val/1000.0 log.debug("cicli=%d, q=%f, mc=%f" % (cicli_min, q_val,q_m_ch)) # conversione float - Endian.Little il primo è il meno significativo if p_new < 0: p_new = 0 if cicli_min < 0: cicli_min = 0 values[516] = p_new # %MW516 PRESSIONE ATTUALE values[520] = cicli_min builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_32bit_float(q_val) builder.add_32bit_float(q_m_ch) reg=builder.to_registers() log.debug("2 x 32bit_float = %s" % str(reg)) values[522:526]=reg log.debug("On Pump Server %02d new values (516-525): %s" % (srv_id, str(values[516:526]))) # assign new values to context values[599] = 699 context[slave_id].setValues(register, START_ADDRESS, values)
def convert(self, config, data): byte_order = config["byteOrder"] if config.get("byteOrder") else "LITTLE" if byte_order == "LITTLE": builder = BinaryPayloadBuilder(byteorder=Endian.Little) elif byte_order == "BIG": builder = BinaryPayloadBuilder(byteorder=Endian.Big) else: log.warning("byte order is not BIG or LITTLE") return reg_count = config.get("registerCount", 1) value = config["value"] if config.get("tag") is not None: tags = (findall('[A-Z][a-z]*', config["tag"])) if "Coil" in tags: builder.add_bits(value) elif "String" in tags: builder.add_string(value) elif "Double" in tags: if reg_count == 4: builder.add_64bit_float(value) else: log.warning("unsupported amount of registers with double type for device %s in Downlink converter", self.__config["deviceName"]) return elif "Float" in tags: if reg_count == 2: builder.add_32bit_float(value) else: log.warning("unsupported amount of registers with float type for device %s in Downlink converter", self.__config["deviceName"]) return elif "Integer" in tags or "DWord" in tags or "DWord/Integer" in tags or "Word" in tags: if reg_count == 1: builder.add_16bit_int(value) elif reg_count == 2: builder.add_32bit_int(value) elif reg_count == 4: builder.add_64bit_int(value) else: log.warning("unsupported amount of registers with integer/word/dword type for device %s in Downlink converter", self.__config["deviceName"]) return else: log.warning("unsupported hardware data type for device %s in Downlink converter", self.__config["deviceName"]) if config.get("bit") is not None: bits = [0 for _ in range(8)] bits[config["bit"]-1] = int(value) log.debug(bits) builder.add_bits(bits) return builder.to_string() if config["functionCode"] in [5, 15]: return builder.to_coils() elif config["functionCode"] in [6, 16]: return builder.to_registers() else: log.warning("Unsupported function code, for device %s in Downlink converter", self.__config["deviceName"]) return
def run_binary_payload_ex(): # ----------------------------------------------------------------------- # # We are going to use a simple client to send our requests # ----------------------------------------------------------------------- # client = ModbusClient('127.0.0.1', port=5440) client.connect() # ----------------------------------------------------------------------- # # If you need to build a complex message to send, you can use the payload # builder to simplify the packing logic. # # Here we demonstrate packing a random payload layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - another 16 bit unsigned int 0x5678 # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # - an 32 bit uint 0x12345678 # - an 32 bit signed int -0x1234 # - an 64 bit signed int 0x12345678 # The packing can also be applied to the word (wordorder) and bytes in each # word (byteorder) # The wordorder is applicable only for 32 and 64 bit values # Lets say we need to write a value 0x12345678 to a 32 bit register # The following combinations could be used to write the register # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # # Word Order - Big Byte Order - Big # word1 =0x1234 word2 = 0x5678 # Word Order - Big Byte Order - Little # word1 =0x3412 word2 = 0x7856 # Word Order - Little Byte Order - Big # word1 = 0x5678 word2 = 0x1234 # Word Order - Little Byte Order - Little # word1 =0x7856 word2 = 0x3412 # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # # ----------------------------------------------------------------------- # builder = BinaryPayloadBuilder(byteorder=Endian.Little, wordorder=Endian.Big) builder.add_string('abcdefgh') builder.add_32bit_float(22.34) builder.add_16bit_uint(0x1234) builder.add_16bit_uint(0x5678) builder.add_8bit_int(0x12) builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0]) builder.add_32bit_uint(0x12345678) builder.add_32bit_int(-0x1234) builder.add_64bit_int(0x1234567890ABCDEF) payload = builder.build() address = 0 client.write_registers(address, payload, skip_encode=True, unit=1) # ----------------------------------------------------------------------- # # If you need to decode a collection of registers in a weird layout, the # payload decoder can help you as well. # # Here we demonstrate decoding a random register layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - another 16 bit unsigned int which we will ignore # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # ----------------------------------------------------------------------- # address = 0x00 count = len(payload) result = client.read_holding_registers(address, count, unit=1) print("-" * 60) print("Registers") print("-" * 60) print(result.registers) print("\n") decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Little, wordorder=Endian.Big) decoded = { 'string': decoder.decode_string(8), 'float': decoder.decode_32bit_float(), '16uint': decoder.decode_16bit_uint(), 'ignored': decoder.skip_bytes(2), '8int': decoder.decode_8bit_int(), 'bits': decoder.decode_bits(), "32uints": decoder.decode_32bit_uint(), "32ints": decoder.decode_32bit_int(), "64ints": decoder.decode_64bit_int(), } print("-" * 60) print("Decoded Data") print("-" * 60) for name, value in iteritems(decoded): print("%s\t" % name, hex(value) if isinstance(value, int) else value) # ----------------------------------------------------------------------- # # close the client # ----------------------------------------------------------------------- # client.close()
def convert(self, config, data): byte_order_str = config.get("byteOrder", "LITTLE") byte_order = Endian.Big if byte_order_str.upper( ) == "BIG" else Endian.Little builder = BinaryPayloadBuilder(byteorder=byte_order) builder_functions = { "string": builder.add_string, "bits": builder.add_bits, "8int": builder.add_8bit_int, "16int": builder.add_16bit_int, "32int": builder.add_32bit_int, "64int": builder.add_64bit_int, "8uint": builder.add_8bit_uint, "16uint": builder.add_16bit_uint, "32uint": builder.add_32bit_uint, "64uint": builder.add_64bit_uint, "16float": builder.add_16bit_float, "32float": builder.add_32bit_float, "64float": builder.add_64bit_float } value = None if data.get("data") and data["data"].get("params") is not None: value = data["data"]["params"] else: value = config["value"] lower_type = config.get("type", config.get("tag", "error")).lower() if lower_type == "error": log.error('"type" and "tag" - not found in configuration.') variable_size = config.get("registerCount", 1) * 8 if lower_type in ["integer", "dword", "dword/integer", "word", "int"]: lower_type = str(variable_size) + "int" assert builder_functions.get(lower_type) is not None builder_functions[lower_type](value) elif lower_type in [ "uint", "unsigned", "unsigned integer", "unsigned int" ]: lower_type = str(variable_size) + "uint" assert builder_functions.get(lower_type) is not None builder_functions[lower_type](value) elif lower_type in ["float", "double"]: lower_type = str(variable_size) + "float" assert builder_functions.get(lower_type) is not None builder_functions[lower_type](value) elif lower_type in ["coil", "bits"]: assert builder_functions.get("bits") is not None builder_functions["bits"](value) elif lower_type in ["string"]: assert builder_functions.get("string") is not None builder_functions[lower_type](value) elif lower_type in ["bit"]: bits = [0 for _ in range(8)] bits[config["bit"] - 1] = int(value) log.debug(bits) builder.add_bits(bits) return builder.to_string() else: log.error("Unknown variable type") builder_converting_functions = { 5: builder.to_coils, 15: builder.to_coils, 6: builder.to_registers, 16: builder.to_registers } function_code = config["functionCode"] if function_code in builder_converting_functions: builder = builder_converting_functions[function_code]() if "Exception" in str(builder): log.exception(builder) builder = str(builder) return builder log.warning( "Unsupported function code, for the device %s in the Modbus Downlink converter", config["device"]) return None
def convert(self, config, data): byte_order_str = config.get("byteOrder", "LITTLE") byte_order = Endian.Big if byte_order_str.upper( ) == "BIG" else Endian.Little builder = BinaryPayloadBuilder(byteorder=byte_order) builder_functions = { "string": builder.add_string, "bits": builder.add_bits, "8int": builder.add_8bit_int, "16int": builder.add_16bit_int, "32int": builder.add_32bit_int, "64int": builder.add_64bit_int, "8uint": builder.add_8bit_uint, "16uint": builder.add_16bit_uint, "32uint": builder.add_32bit_uint, "64uint": builder.add_64bit_uint, "16float": builder.add_16bit_float, "32float": builder.add_32bit_float, "64float": builder.add_64bit_float } value = config["value"] lower_type = config["tag"].lower() variable_size = config.get("registerCount", 1) * 8 if lower_type in ["integer", "dword", "dword/integer", "word"]: lower_type = str(variable_size) + "int" assert builder_functions.get(lower_type) is not None builder_functions[lower_type](value) elif lower_type in [ "uint", "unsigned", "unsigned integer", "unsigned int" ]: lower_type = str(variable_size) + "uint" assert builder_functions.get(lower_type) is not None builder_functions[lower_type](value) elif lower_type in ["float", "double"]: lower_type = str(variable_size) + "float" assert builder_functions.get(lower_type) is not None builder_functions[lower_type](value) elif lower_type in ["coil", "bits"]: assert builder_functions.get("bits") is not None builder_functions["bits"](value) elif lower_type in ["string"]: assert builder_functions.get("string") is not None builder_functions[lower_type](value) elif lower_type in ["bit"]: bits = [0 for _ in range(8)] bits[config["bit"] - 1] = int(value) log.debug(bits) builder.add_bits(bits) return builder.to_string() builder_converting_functions = { 5: builder.to_coils, 15: builder.to_coils, 6: builder.to_registers, 16: builder.to_registers } function_code = config["functionCode"] if function_code in builder_converting_functions: return builder_converting_functions[function_code]() log.warning( "Unsupported function code, for the device %s in the Modbus Downlink converter", self.__config["deviceName"]) return None
# # Here we demonstrate packing a random payload layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # ---------------------------------------------------------------------------# builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_string("abcdefgh") builder.add_32bit_float(22.34) builder.add_16bit_uint(0x1234) builder.add_8bit_int(0x12) builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0]) payload = builder.build() address = 0x01 result = client.write_registers(address, payload, skip_encode=True) # ---------------------------------------------------------------------------# # If you need to decode a collection of registers in a weird layout, the # payload decoder can help you as well. # # Here we demonstrate decoding a random register layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - an 8 bit int 0x12
def __write_Registers(self, regPara, value): objectType = regPara['objectType'] address = regPara['regAddr'] slaveUnit = regPara['slaveUnit'] bo = regPara['byteOrder'] wo = regPara['wordOrder'] dataTypeStr = regPara['dataType'] dataType = ''.join( filter(str.isalpha, dataTypeStr )) # vom dataType die Ziffen entfernen z.B. uint16 = uint registerCount = 0 # Anzahl der zu schreibenden Register (Words) try: bits = int(''.join(filter( str.isdigit, dataTypeStr))) # bit-Zahl aus aus dataType z.B. uint16 = 16 except: bits = 16 if dataType.lower() == 'string': registerCount = int( bits / 2 ) # bei string: bits = bytes !! string16 -> 16Byte - 8 registerCount else: registerCount = int(bits / 16) if regPara['factor'] != 1: #self.logger.debug("value {0} divided by: {1}".format(value, regPara['factor'])) value = value * (1 / regPara['factor']) self.logger.debug( "write {0} to {1}.{2}.{3} (address.slaveUnit) dataType:{4}".format( value, objectType, address, slaveUnit, dataTypeStr)) builder = BinaryPayloadBuilder(byteorder=bo, wordorder=wo) if dataType.lower() == 'uint': if bits == 16: builder.add_16bit_uint(int(value)) elif bits == 32: builder.add_32bit_uint(int(value)) elif bits == 64: builder.add_64bit_uint(int(value)) else: self.logger.error( "Number of bits or datatype not supportet : {0}".format( typeStr)) elif dataType.lower() == 'int': if bits == 16: builder.add_16bit_int(int(value)) elif bits == 32: builder.add_32bit_int(int(value)) elif bits == 64: builder.add_64bit_int(int(value)) else: self.logger.error( "Number of bits or datatype not supportet : {0}".format( typeStr)) elif dataType.lower() == 'float': if bits == 32: builder.add_32bit_float(value) if bits == 64: builder.add_64bit_float(value) else: self.logger.error( "Number of bits or datatype not supportet : {0}".format( typeStr)) elif dataType.lower() == 'string': builder.add_string(value) elif dataType.lower() == 'bit': if objectType == 'Coil' or objectType == 'DiscreteInput': if not type(value) == type(True): # test is boolean self.logger.error( "Value is not boolean: {0}".format(value)) return else: if set(bitstr).issubset({ '0', '1' }) and bool(bitstr): # test is bit-string '00110101' builder.add_bits(value) else: self.logger.error( "Value is not a bitstring: {0}".format(value)) else: self.logger.error( "Number of bits or datatype not supportet : {0}".format( typeStr)) return None if objectType == 'Coil': result = self._Mclient.write_coil(address, value, unit=slaveUnit) elif objectType == 'HoldingRegister': registers = builder.to_registers() result = self._Mclient.write_registers(address, registers, unit=slaveUnit) elif objectType == 'DiscreteInput': self.logger.warning( "this object type cannot be written {0}:{1} slaveUnit:{2}". format(objectType, address, slaveUnit)) return elif objectType == 'InputRegister': self.logger.warning( "this object type cannot be written {0}:{1} slaveUnit:{2}". format(objectType, address, slaveUnit)) return else: return if result.isError(): self.logger.error( "write error: {0} {1}.{2}.{3} (address.slaveUnit)".format( result, objectType, address, slaveUnit)) return None if 'write_dt' in regPara: regPara['last_write_dt'] = regPara['write_dt'] regPara['write_dt'] = datetime.now() else: regPara.update({'write_dt': datetime.now()}) if 'write_value' in regPara: regPara['last_write_value'] = regPara['write_value'] regPara['write_value'] = value else: regPara.update({'write_value': value})