def write_modbus(solve_coo): if solve_coo is None: return False ra = solve_coo.ra.deg if ra > 180: ra -= 360 ra = ra * np.pi/180. dec = solve_coo.dec.deg * np.pi/180. val_dict = { 24592: ra, 24590: dec, 24594: time.time() - 1544000000. } for address, value in val_dict.items(): builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big) print(address, value) builder.add_32bit_float(value) payload = builder.build() registers = builder.to_registers() rr = modbus_client.write_registers(address, registers, unit=modbus_UNIT) time.sleep(0.1) if rr.isError(): return False return True
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 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 write_registers(self, key): point = self.point_dict.get(key[2:]) if point: value = conpot_core.get_databus().get_value(key) if not point.encoding == 'none': endian = Endian.Auto if point.endian == 'Little': endian = Endian.Little elif point.endian == 'Big': endian = Endian.Big builder = BinaryPayloadBuilder(endian=endian) builder_map = {'bits': builder.add_bits, '8unit': builder.add_8bit_uint, '16unit': builder.add_16bit_uint, '32unit': builder.add_32bit_uint, '64unit': builder.add_64bit_uint, '8int': builder.add_8bit_int, '16int': builder.add_16bit_int, '32int': builder.add_32bit_int, '64int': builder.add_64bit_int, '32float': builder.add_32bit_float, '64float': builder.add_64bit_float, 'string': builder.add_string} builder_map[point.encoding](value) payload = [unpack(endian + 'H', x)[0] for x in builder.build()] with lock: return self.modbus_client.write_registers(point.address, payload, unit=point.slave_id) else: with lock: return self.modbus_client.write_registers(point.address, [value], unit=point.slave_id)
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 testPayloadBuilderWithRawPayload(self): """ Test basic bit message encoding/decoding """ _coils1 = [False, False, True, True, False, True, False, False, False, False, False, True, False, False, True, False, False, True, True, True, True, False, False, False, False, True, False, True, False, True, True, False] _coils2 = [False, False, False, True, False, False, True, False, False, False, True, True, False, True, False, False, False, True, False, True, False, True, True, False, False, True, True, True, True, False, False, False] builder = BinaryPayloadBuilder([b'\x12', b'\x34', b'\x56', b'\x78'], repack=True) self.assertEqual(b'\x12\x34\x56\x78', builder.to_string()) self.assertEqual([13330, 30806], builder.to_registers()) c = builder.to_coils() self.assertEqual(_coils1, c) builder = BinaryPayloadBuilder([b'\x12', b'\x34', b'\x56', b'\x78'], byteorder=Endian.Big) self.assertEqual(b'\x12\x34\x56\x78', builder.to_string()) self.assertEqual([4660, 22136], builder.to_registers()) self.assertEqual('\x12\x34\x56\x78', str(builder)) c = builder.to_coils() self.assertEqual(_coils2, c)
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())
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 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) 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 setUp(self): ''' Initializes the test environment and builds request/result encoding pairs ''' self.value = 0xabcd self.values = [0xa, 0xb, 0xc] builder = BinaryPayloadBuilder(endian=Endian.Big) builder.add_16bit_uint(0x1234) self.payload = builder.build() self.write = { WriteSingleRegisterRequest(1, self.value) : b'\x00\x01\xab\xcd', WriteSingleRegisterResponse(1, self.value) : b'\x00\x01\xab\xcd', WriteMultipleRegistersRequest(1, self.values) : b'\x00\x01\x00\x03\x06\x00\n\x00\x0b\x00\x0c', WriteMultipleRegistersResponse(1, 5) : b'\x00\x01\x00\x05', WriteSingleRegisterRequest(1, self.payload[0], skip_encode=True): b'\x00\x01\x12\x34', WriteMultipleRegistersRequest(1, self.payload, skip_encode=True): b'\x00\x01\x00\x01\x02\x12\x34', }
def run_payload_server(): # ----------------------------------------------------------------------- # # build your payload # ----------------------------------------------------------------------- # builder = BinaryPayloadBuilder(byteorder=Endian.Little) # builder.add_string('abcdefgh') # builder.add_32bit_float(22.34) # builder.add_16bit_uint(4660) # builder.add_8bit_int(18) 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. # ----------------------------------------------------------------------- # 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.0' # ----------------------------------------------------------------------- # # run the server you want # ----------------------------------------------------------------------- # StartTcpServer(context, identity=identity, address=("localhost", 5020))
def setUp(self): ''' Initializes the test environment and builds request/result encoding pairs ''' self.value = 0xabcd self.values = [0xa, 0xb, 0xc] builder = BinaryPayloadBuilder(endian=Endian.Big) builder.add_16bit_uint(0x1234) self.payload = builder.build() self.write = { WriteSingleRegisterRequest(1, self.value): b'\x00\x01\xab\xcd', WriteSingleRegisterResponse(1, self.value): b'\x00\x01\xab\xcd', WriteMultipleRegistersRequest(1, self.values): b'\x00\x01\x00\x03\x06\x00\n\x00\x0b\x00\x0c', WriteMultipleRegistersResponse(1, 5): b'\x00\x01\x00\x05', WriteSingleRegisterRequest(1, self.payload[0], skip_encode=True): b'\x00\x01\x12\x34', WriteMultipleRegistersRequest(1, self.payload, skip_encode=True): b'\x00\x01\x00\x01\x02\x12\x34', }
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)
def send(self, hex_list): builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) for hex_val in hex_list: builder.add_8bit_uint(hex_val) Modules.Utils.append_crc(builder) print('sending: ', builder.to_string()) payload = builder.build() for char in payload: self.client.send(char)
def Write_Multiple(Client, Start_Tag_Number, New_Value_List): ''' Inputs: __ Client: See client __ Start_Tag_Number: This is the starting tag value, this will increment by two for each of the items in the New_Values_List __ New_Values_List: This is a list of new values that you want to write, this is typically the same number repeated once for each time that you want to write to each magnet. This is done this way so that you can write different values to each magnet if you want to. (Typically by a scaled amount if you are doing that.) - Must have an established Client before running this function. - Outputs: __ Writes to a number of user defined magnets, may, in the future, allow one value to be written to a specified number of magnets. - Method: - Set up the Client - Define the start tag value, 22201 for dipole 1 for example - For each dipole you want to step, you define the new value you want written to it. - Example (Writing to 8 Dipoles starting with DP1) List = [0.100,0.100,0.100,0.100,0.100,0.100,0.100,0.100] DP1_Tag = 22201 Client = M.Make_Client('192.168.1.2') M.Write_Multiple(Client, DP1_Tag, List) - Result: All of the Dipoles (Assuming there are 8 will be written to 0.100) ''' Tag_Number = int(Start_Tag_Number) - 1 Builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big) for value in New_Value_List: Builder.add_32bit_float(value) Payload = Builder.to_registers() Payload = Builder.build() Client.write_registers(Tag_Number, Payload, skip_encode=True, unit=1) return
def push_buffer(self, buff): builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) [builder.add_8bit_uint(i) for i in buff] builder.add_16bit_uint(self.calc_crc(buff)) payload = builder.build() rq = self.client.write_registers(self.MB_STREAM_REG, payload, skip_encode=True, unit=self.id) #logging.info(f"Push {binascii.hexlify(buff)}") # logging.info(rq.isError()) if not rq.isError(): return True else: logging.warning(f"Can't write stream data") return False
def connect(port, baudrate): global server global myobj global client global my_python_obj my_python_obj = MyObj(server, myobj) client = ModbusClient(method='rtu', port=port, timeout=0.5, baudrate=baudrate) client.connect() rs485_mode = serial.rs485.RS485Settings(delay_before_tx=0, delay_before_rx=0, rts_level_for_tx=True, rts_level_for_rx=False, loopback=False) # client.socket.rs485_mode = rs485_mode builder = BinaryPayloadBuilder(endian=Endian.Big) print('connected')
def write_small_buff(self, buff): if len(buff) == self.mb_transfer_size: self.reset_state() # reset error state builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) [builder.add_16bit_uint(i) for i in buff] builder.add_16bit_uint(self.calc_crc(buff)) payload = builder.build() #print(payload) self.client.write_registers(self.MB_START_STREAM, payload, skip_encode=True, unit=self.id) if self.update_state() == 0: #check errors self.client.write_register(self.MB_ACTION_REG, self.MB_ACTION_WRITE, unit=self.id) if self.update_state() == 0: return True return False
def __encodeData(self, data): """Encode data to 32bit float Function encodes a list of data passed to it into a 32 bit float packet that can be written directly to the MODBUS server table. Arguments: :param data: Float to be encoded :type data: list """ builder = BinaryPayloadBuilder(endian=Endian.Little) try: for i in range(0,len(data)): builder.add_32bit_float(data[i]) except TypeError: builder.add_32bit_float(data) return builder.to_registers()
def sendModbus(address, value, type): global modbusClient if (modbusClient.connect() == False): print("Modbus connection lost, trying to reconnect...") ModbusClient(modbusInverterIP, port=502, unit_id=3, auto_open=True, auto_close=True) print("Modbus Connected: {}".format(modbusClient.connect())) else: # SMA expects everything in Big Endian format builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big) # Only unsigned int32 and signed int32 are built in. It is enough to control the flow of power of the battery. if (type == "uint32"): builder.add_32bit_uint(value) if (type == "int32"): builder.add_32bit_int(value) registers = builder.to_registers() modbusClient.write_registers(address, registers, unit=3)
def Write(Client, Tag_Number, New_Value, Bool=False): ''' -Future: input a safety method to make sure we aren't drastically changing values Inputs: Client, see "Client" Above __ Tag_Number: which modbus to read, convention is this: input the modbus start tag number. Must have a modbus tag. __ New_Value: New value which you want the modbus to output to -Must have established client before attempting to write to the client -Outputs: The value of that Moodbus tag Method: - Build a payload to send to register - Add float value to that payload - Build payload path (path to register) - Build the payload - Write the new value -Required imports from pymodbus.client.sync import ModbusTcpClient from pymodbus.payload import BinaryPayloadDecoder from pymodbus.constants import Endian -example: Client = Make_Client('192.168.1.2') Dipole_1_Current = Write(Client,22201,0.450) ''' Tag_Number = int(Tag_Number) - 1 if Bool == False: Builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big) Builder.add_32bit_float(New_Value) Payload = Builder.to_registers() Payload = Builder.build() Client.write_registers(Tag_Number, Payload, skip_encode=True, unit=1) if Bool == True: Client.write_coils(Tag_Number, [New_Value], skip_encode=False, unit=1) return
def convert_string_to_register(value): # currently not used because no need to write string in register """ Convert a string value to a list of registers :param value: A string :type value: str :return: registers value :rtype: list[int] """ if isinstance(value, str): if pymodbus.__version__ == '1.3.2': # by default, on Version 1.3.2, endian is Endian.Little, # so registers were written in the reverse order. # For now, we use this version on the raspberry pi # and v 2.4.0 in simulation builder = BinaryPayloadBuilder(endian=Endian.Big) else: builder = BinaryPayloadBuilder() builder.add_string(value) payload = builder.to_registers() return payload else: return None
client.connect() endian=client.read_holding_registers(49991,4,unit=1) #endian.registers[0] = byteswap(endian.registers[0]) #endian.registers[1] = byteswap(endian.registers[1]) #endian.registers[2] = byteswap(endian.registers[2]) #endian.registers[3] = byteswap(endian.registers[3]) decoder=BinaryPayloadDecoder.fromRegisters(endian.registers,endian=Endian.Big) decoded={ 'val':hex(decoder.decode_32bit_uint()), 'v100':decoder.decode_32bit_float() } print decoded encoder = BinaryPayloadBuilder(endian=Endian.Big) encoder.add_16bit_uint(0x1234) buf = encoder.build() #buf[0] = charswap(buf[0]) client.write_registers(51234, buf, unit=1, skip_encode=True) encoder = BinaryPayloadBuilder(endian=Endian.Big) encoder.add_32bit_float(1.0114) encoder.add_32bit_float(-6) buf = encoder.build() #buf[0] = charswap(buf[0]) #buf[1] = charswap(buf[1]) #buf[2] = charswap(buf[2]) #buf[3] = charswap(buf[3]) client.write_registers(50000 + 8 * 5, buf, unit=1, skip_encode=True)
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 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 = '2.2.0' # ----------------------------------------------------------------------- # # run the server you want # ----------------------------------------------------------------------- # StartTcpServer(context, identity=identity, address=("localhost", 5020))
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(b'test') builder.add_bits(self.bitstring) self.assertEqual(self.little_endian_payload, builder.to_string())
def t_update(ctx, stop, module, device, refresh): this_t = threading.currentThread() logger = logging.getLogger() while not stop.is_set(): try: values = module.values(device) if not values: logger.debug(f"{this_t.name}: no new values") continue block_1001 = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) block_1001.add_32bit_float(values.get("energy_active", 0)) # total active energy block_1001.add_32bit_float(values.get("import_energy_active", 0)) # imported active energy block_1001.add_32bit_float(values.get( "energy_active", 0)) # total active energy non-reset block_1001.add_32bit_float(values.get( "import_energy_active", 0)) # imported active energy non-reset block_1001.add_32bit_float(values.get("power_active", 0)) # total power block_1001.add_32bit_float(values.get("p1_power_active", 0)) # power l1 block_1001.add_32bit_float(values.get("p2_power_active", 0)) # power l2 block_1001.add_32bit_float(values.get("p3_power_active", 0)) # power l3 block_1001.add_32bit_float(values.get("voltage_ln", 0)) # l-n voltage block_1001.add_32bit_float(values.get("p1n_voltage", 0)) # l1-n voltage block_1001.add_32bit_float(values.get("p2n_voltage", 0)) # l2-n voltage block_1001.add_32bit_float(values.get("p3n_voltage", 0)) # l3-n voltage block_1001.add_32bit_float(values.get("voltage_ll", 0)) # l-l voltage block_1001.add_32bit_float(values.get("p12_voltage", 0)) # l1-l2 voltage block_1001.add_32bit_float(values.get("p23_voltage", 0)) # l2-l3 voltage block_1001.add_32bit_float(values.get("p31_voltage", 0)) # l3-l1 voltage block_1001.add_32bit_float(values.get("frequency", 0)) # line frequency ctx.setValues(3, 1000, block_1001.to_registers()) block_1101 = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) block_1101.add_32bit_float(values.get("p1_energy_active", 0)) # total active energy l1 block_1101.add_32bit_float(values.get("p2_energy_active", 0)) # total active energy l2 block_1101.add_32bit_float(values.get("p3_energy_active", 0)) # total active energy l3 block_1101.add_32bit_float(values.get( "p1_import_energy_active", 0)) # imported active energy l1 block_1101.add_32bit_float(values.get( "p2_import_energy_active", 0)) # imported active energy l2 block_1101.add_32bit_float(values.get( "p3_import_energy_active", 0)) # imported active energy l3 block_1101.add_32bit_float(values.get( "export_energy_active", 0)) # total exported active energy block_1101.add_32bit_float( values.get("export_energy_active", 0)) # total exported active energy non-reset block_1101.add_32bit_float(values.get("p1_export_energy_active", 0)) # exported energy l1 block_1101.add_32bit_float(values.get("p2_export_energy_active", 0)) # exported energy l2 block_1101.add_32bit_float(values.get("p3_export_energy_active", 0)) # exported energy l3 block_1101.add_32bit_float(values.get("energy_reactive", 0)) # total reactive energy block_1101.add_32bit_float(values.get("p1_energy_reactive", 0)) # reactive energy l1 block_1101.add_32bit_float(values.get("p2_energy_reactive", 0)) # reactive energy l2 block_1101.add_32bit_float(values.get("p3_energy_reactive", 0)) # reactive energy l3 block_1101.add_32bit_float(values.get("energy_apparent", 0)) # total apparent energy block_1101.add_32bit_float(values.get("p1_energy_apparent", 0)) # apparent energy l1 block_1101.add_32bit_float(values.get("p2_energy_apparent", 0)) # apparent energy l2 block_1101.add_32bit_float(values.get("p3_energy_apparent", 0)) # apparent energy l3 block_1101.add_32bit_float(values.get("power_factor", 0)) # power factor block_1101.add_32bit_float(values.get("p1_power_factor", 0)) # power factor l1 block_1101.add_32bit_float(values.get("p2_power_factor", 0)) # power factor l2 block_1101.add_32bit_float(values.get("p3_power_factor", 0)) # power factor l3 block_1101.add_32bit_float(values.get("power_reactive", 0)) # total reactive power block_1101.add_32bit_float(values.get("p1_power_reactive", 0)) # reactive power l1 block_1101.add_32bit_float(values.get("p2_power_reactive", 0)) # reactive power l2 block_1101.add_32bit_float(values.get("p3_power_reactive", 0)) # reactive power l3 block_1101.add_32bit_float(values.get("power_apparent", 0)) # total apparent power block_1101.add_32bit_float(values.get("p1_power_apparent", 0)) # apparent power l1 block_1101.add_32bit_float(values.get("p2_power_apparent", 0)) # apparent power l2 block_1101.add_32bit_float(values.get("p3_power_apparent", 0)) # apparent power l3 block_1101.add_32bit_float(values.get("p1_current", 0)) # current l1 block_1101.add_32bit_float(values.get("p2_current", 0)) # current l2 block_1101.add_32bit_float(values.get("p3_current", 0)) # current l3 block_1101.add_32bit_float(values.get("demand_power_active", 0)) # demand power block_1101.add_32bit_float( values.get("minimum_demand_power_active", 0)) # minimum demand power block_1101.add_32bit_float( values.get("maximum_demand_power_active", 0)) # maximum demand power block_1101.add_32bit_float(values.get("demand_power_apparent", 0)) # apparent demand power block_1101.add_32bit_float(values.get("p1_demand_power_active", 0)) # demand power l1 block_1101.add_32bit_float(values.get("p2_demand_power_active", 0)) # demand power l2 block_1101.add_32bit_float(values.get("p3_demand_power_active", 0)) # demand power l3 ctx.setValues(3, 1100, block_1101.to_registers()) except Exception as e: logger.critical(f"{this_t.name}: {e}") finally: time.sleep(refresh)
#Its is the motor cos? and 0.5<motor_power_factor<0.97. ramp_mode=2# parm 30 Standard Std (2) without dynamic braking resistor, If with this resistor, should set to 0 or # Fast dynamicVtoF='OFF'# parm 32 - It should not be used when the drive is being used as a soft start to full speed. keep off voltage_mode_select=2 #parm 41 fixed boost mode(2) low_freq_voltage_boost=1 #% 0.5< low_freq_voltage_boost<1 __config__={ip:'127.0.0.1',min_speed:0.1,max_speed:60.0,acc_rate:33.0,dec_rate:33.0,motor_rated_speed:0, motor_rated_voltage:230,motor_power_factor:0.85,ramp_mode:2,dynamicVtoF:'OFF', voltage_mode_select:2, low_freq_voltage_boost:1} #open connection with sk commander # default port: 502 # change the ip below to the commander ip of your network #starting connection sk=ModbusTcpClient(ip) if sk.connect(): builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_32bit_float(321.57) payload = builder.build() result = sk.write_registers(4005, payload, skip_encode=True) sk.close() exit()
from pymodbus.constants import Endian from pymodbus.payload import BinaryPayloadDecoder from pymodbus.payload import BinaryPayloadBuilder #---------------------------------------------------------------------------# # 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)
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 _write_request(self, action_byte, position_byte=0x00, speed_byte=0x00, force_byte=0x00): builder = BinaryPayloadBuilder(byteorder=Endian.Little, wordorder=Endian.Little) builder.add_8bit_uint(action_byte) builder.add_8bit_uint(0x00) builder.add_8bit_uint(0x00) builder.add_8bit_uint(position_byte) builder.add_8bit_uint(force_byte) builder.add_8bit_uint(speed_byte) registers = builder.to_registers() return self._client.write_registers(WRITING_REGISTER, registers, unit=DEFAULT_UNIT)
def convert(self, config, data): byte_order_str = config.get("byteOrder", "LITTLE") word_order_str = config.get("wordOrder", "LITTLE") byte_order = Endian.Big if byte_order_str.upper( ) == "BIG" else Endian.Little word_order = Endian.Big if word_order_str.upper( ) == "BIG" else Endian.Little repack = config.get("repack", False) builder = BinaryPayloadBuilder(byteorder=byte_order, wordorder=word_order, repack=repack) 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.get("value", 0) 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( "objectsCount", config.get("registersCount", config.get("registerCount", 1))) * 16 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](int(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](int(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](float(value)) elif lower_type in ["coil", "bits", "coils", "bit"]: assert builder_functions.get("bits") is not None if variable_size / 8 > 1.0: builder_functions["bits"](bytes(value, encoding='UTF-8')) if isinstance(value, str) else \ builder_functions["bits"](bytes(value)) else: return bytes(int(value)) elif lower_type in ["string"]: assert builder_functions.get("string") is not None builder_functions[lower_type](value) elif lower_type in builder_functions and 'int' in lower_type: builder_functions[lower_type](int(value)) elif lower_type in builder_functions and 'float' in lower_type: builder_functions[lower_type](float(value)) elif lower_type in builder_functions: builder_functions[lower_type](value) 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]() log.debug(builder) if "Exception" in str(builder): log.exception(builder) builder = str(builder) if variable_size <= 16: if isinstance(builder, list) and len(builder) not in (8, 16, 32, 64): builder = builder[0] else: if isinstance(builder, list) and len(builder) not in (2, 4): log.warning( "There is a problem with the value builder. Only the first register is written." ) builder = builder[0] return builder log.warning( "Unsupported function code, for the device %s in the Modbus Downlink converter", config["device"]) return None
# License: GPL 2.0 import os import math from gps import * from time import * import time import threading from pymodbus.client.sync import ModbusTcpClient from pymodbus.constants import Endian from pymodbus.payload import BinaryPayloadDecoder from pymodbus.payload import BinaryPayloadBuilder gpsd = None #seting the global variable client = ModbusTcpClient('192.168.0.100') builder = BinaryPayloadBuilder(endian=Endian.Big) gplat_dec = 0 gplat_int = 0 gplong_dec = 0 gplong_int = 0 os.system('clear') #clear the terminal (optional) class GpsPoller(threading.Thread): def __init__(self): threading.Thread.__init__(self) global gpsd #bring it in scope gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info self.current_value = None
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 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()
"meters", fallback=default_config["server"] ["meters"]).split(',') ] for meter in meters: address = confparser[meter].getint( "dst_address", fallback=default_config["meters"]["dst_address"]) meter_type = confparser[meter].get( "type", fallback=default_config["meters"]["type"]) meter_module = importlib.import_module(f"devices.{meter_type}") meter_device = meter_module.device(confparser[meter]) slave_ctx = ModbusSlaveContext() block_1601 = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) block_1601.add_32bit_int(1234) # config passcode block_1601.add_16bit_int(confparser[meter].getint( "ct_current", fallback=default_config["meters"] ["ct_current"])) # ct rated current block_1601.add_16bit_int(confparser[meter].getint( "ct_current", fallback=default_config["meters"] ["ct_current"])) # ct rated current l1 block_1601.add_16bit_int(confparser[meter].getint( "ct_current", fallback=default_config["meters"] ["ct_current"])) # ct rated current l2 block_1601.add_16bit_int(confparser[meter].getint( "ct_current",
def change(): #Current address 01 is changed to 09 #01 10 00 00 00 01 02 00 09 66 56 builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) #builder.add_8bit_uint(0x00) #builder.add_8bit_uint(0x10) #builder.add_8bit_uint(0x00) #builder.add_8bit_uint(0x00) #builder.add_8bit_uint(0x00) #builder.add_8bit_uint(0x01) #builder.add_8bit_uint(0x02) #builder.add_8bit_uint(0x00) #builder.add_8bit_uint(0x09) #builder.add_8bit_uint(0x01) # Unit ID #builder.add_8bit_uint(0x10) # function ID #builder.add_8bit_uint(0x00) #builder.add_8bit_uint(0x00) # coil ID #builder.add_8bit_uint(0x00) # data, here: on #builder.add_8bit_uint(0x01) #builder.add_8bit_uint(0x02) #builder.add_8bit_uint(0x00) #builder.add_8bit_uint(0x09) builder.add_8bit_uint(0x01) # Unit ID builder.add_8bit_uint(0x10) # function ID builder.add_8bit_uint(0x00) builder.add_8bit_uint(0x00) # coil ID builder.add_8bit_uint(0x00) # data builder.add_8bit_uint(0x01) builder.add_8bit_uint(0x02) builder.add_8bit_uint(0x00) builder.add_8bit_uint(0x09) builder.build() utils.appendCrc(builder) print('TMP:', builder) #print(computeCRC(str(builder).encode())) #crc = computeCRC(ut.make_byte_string(builder.to_string())) #print(crc) #hexStr = '%04x' % crc #hex1 = int(hexStr[0] + hexStr[1], 16) #hex2 = int(hexStr[2] + hexStr[3], 16) ##print(hex(hex2)) ##builder.add_8bit_uint(0x66) ##builder.add_8bit_uint(0x56) #builder.add_8bit_uint(hex1) #builder.add_8bit_uint(hex2) return builder.build()
def testBigEndianPayloadBuilder(self): """ Test basic bit message encoding/decoding """ builder = BinaryPayloadBuilder(byteorder=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_16bit_uint(1) # placeholder builder.add_string('test') builder.add_bits(self.bitstring) self.assertEqual(self.big_endian_payload, builder.to_string())
async def _write_register_value( self, key: str, value: Union[str, float, int]) -> WriteMultipleRegistersResponse: """Write a single value to the holding registers. Currently registers are written one at a time to avoid issues with discontinuous modbus addresses. """ start_address = self.tags[key]['address']['start'] - 400001 builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) data_type = self.tags[key]['type'] if data_type == 'float': builder.add_32bit_float(value) elif data_type == 'str': chars = self.tags[key]['length'] if len(value) > chars: raise ValueError(f'{value} is too long for {key}. ' f'Max: {chars} chars') builder.add_string(value.ljust(chars)) elif data_type == 'int16': builder.add_16bit_int(value) elif data_type == 'int32': builder.add_32bit_int(value) else: raise ValueError("Missing data type.") resp = await self.write_registers(start_address, builder.build(), skip_encode=True) return resp[0]
def updating_pump_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 ''' context = a[0] srv_id = a[1] handler = a[2] register = 3 slave_id = 0x00 values = context[slave_id].getValues(register, 0, count=600) # update P and Q with random values logInfo.debug("PUMP context values: " + str(values)) logInfo.debug("PUMP p_out=%d; q_out=%d" % (handler.p_out,handler.q_out)) 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() cicli_min = 0 p_new = 0 q_val = 0 # if iniettore Started if handler.pumpStarted and not bits_502[7]: handler.pumpStarted = False if bits_502[7]: #cicli_min = cicli_rand.rvs() q_val = handler.q_out if q_val < 0: q_val = 0 cicli_min = int(q_val / liters_cycle ) p_new = handler.p_out logInfo.debug("PUMP p_new=%d" % p_new) q_m_ch = 60.0*q_val/1000.0 handler.cicli_min = cicli_min handler.q_m_ch = q_m_ch logInfo.debug("PUMP cicli=%d, q=%f, mc=%f" % (cicli_min, q_val,q_m_ch)) # conversione float - Endian.Little il primo è il meno significativo handler.p_pump_out = p_new handler.q_pump_out = cicli_min values[516] = p_new # %MW516 PRESSIONE ATTUALE values[520] = cicli_min handler.qmax = values[562] handler.pmax = values[560] builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_32bit_float(q_val) builder.add_32bit_float(q_m_ch) reg=builder.to_registers() logInfo.debug("PUMP 2 x 32bit_float = %s" % str(reg)) values[522:526]=reg logInfo.debug("PUMP 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, 0, values)
from pymodbus.constants import Endian from pymodbus.payload import BinaryPayloadDecoder from pymodbus.payload import BinaryPayloadBuilder #---------------------------------------------------------------------------# # 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)
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()
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
#!/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)
log = logging.getLogger() log.setLevel(logging.DEBUG) client = ModbusClient(method="rtu", port="/dev/ttyUSB0", stopbits=1, 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)
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 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]: log.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() log.debug("ModbusMySequentialDataBlock.setValues updating 552({0}) {1}".format(values[552-start], bits_552)) if bits_552[2]: print "start iniettore da remoto" log.debug("start iniettore da remoto") g_Time = 0 bits_502[7] = 1 # START INIETTORE 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 "stop iniettore da remoto" log.debug("stop iniettore da remoto") bits_502[7] = 0 # STOP INIETTORE bits_506[2] = 0 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 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)
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_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
#---------------------------------------------------------------------------# # 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] #---------------------------------------------------------------------------# builder = BinaryPayloadBuilder(endian=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]) payload = builder.build() address = 0 result = 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
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 # - 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:
def update_register(context, param): values = [] fn_code = HOLDING_REGISTER_FN_CODE if (param == "temperature"): address = TEMPERATURE_REGISTER newvalue = random.randint(TEMP_LO, TEMP_HI) log.debug("new temperatue value: " + str(newvalue)) elif (param == "humidity"): address = HUMIDITY_REGISTER newvalue = random.randint(HUMID_LO, HUMID_HI) log.debug("new humidity value: " + str(newvalue)) elif (param == "pressure"): address = PRESSURE_REGISTER newvalue = random.randint(PRESSURE_LO, PRESSURE_HI) log.debug("new pressure value: " + str(newvalue)) elif (param == "geolati"): address = GEO_LATI_REGISTER newvalue = random.uniform(LATI_LO, LATI_HI) log.debug("new latitude value = " + str(newvalue)) builder = BinaryPayloadBuilder(endian=Endian.Big) builder.add_32bit_float(newvalue) payload = builder.to_registers() context.setValues(fn_code, address, payload) return elif (param == "geolongi"): address = GEO_LONGI_REGISTER newvalue = random.uniform(LONGI_LO, LONGI_HI) log.debug("new longitude value = " + str(newvalue)) builder = BinaryPayloadBuilder(endian=Endian.Big) builder.add_32bit_float(newvalue) payload = builder.to_registers() context.setValues(fn_code, address, payload) return elif (param == "keyop"): address = KEY_OP_REGISTER context.setValues(fn_code, address, [0] * 8) newvalue = random.choice(operations) newvalue = newvalue log.debug("new key operation = " + newvalue) builder = BinaryPayloadBuilder(endian=Endian.Big) builder.add_string(newvalue) payload = builder.to_registers() context.setValues(fn_code, address, payload) return else: return values.append(newvalue) context.setValues(fn_code, address, values)