def bytes_to_status(bytes_, status_type): """Convert bytes to trip and digital input statuses """ # The 4 bits for a state is contained i 4 bytes, gather them up into one list all_states = [] for byte_ in bytes_: pay = BinaryPayloadDecoder(byte_) bits_ = pay.decode_bits() # 8 booleans all_states.extend([bits_[:4], bits_[4:]]) # The 3 bit indicates whether status is used, sort out the rest all_states = [state for state in all_states if state[3]] states = {} for state_num, state_bits in enumerate(all_states, start=1): # Enumeration starts at 1 # The first 3 bits has 3 different meanings: on, inhibit and override # First make sure only one is set if sum(state_bits[:3]) > 1: raise ValueError('Bad state: {}'.format(state_bits)) # Then translate, if none is set, default to off for bit_num, bit_meaning in enumerate(['on', 'inhibit', 'override']): if state_bits[bit_num]: states[status_type + str(state_num)] = bit_meaning break else: states[status_type + str(state_num)] = 'off' return states
def testPayloadDecoderReset(self): """ Test the payload decoder reset functionality """ decoder = BinaryPayloadDecoder(b'\x12\x34') self.assertEqual(0x12, decoder.decode_8bit_uint()) self.assertEqual(0x34, decoder.decode_8bit_uint()) decoder.reset() self.assertEqual(0x3412, decoder.decode_16bit_uint())
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 __init__(self, payload, byteorder): """ Initialize a new instance of the SunspecDecoder .. note:: This is always set to big endian byte order as specified in the protocol. """ byteorder = Endian.Big BinaryPayloadDecoder.__init__(self, payload, byteorder)
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 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 testPayloadDecoderRegisterFactory(self): """ Test the payload decoder reset functionality """ payload = [1, 2, 3, 4] decoder = BinaryPayloadDecoder.fromRegisters(payload, endian=Endian.Little) encoded = "\x00\x01\x00\x02\x00\x03\x00\x04" self.assertEqual(encoded, decoder.decode_string(8)) decoder = BinaryPayloadDecoder.fromRegisters(payload, endian=Endian.Big) encoded = "\x00\x01\x00\x02\x00\x03\x00\x04" self.assertEqual(encoded, decoder.decode_string(8)) self.assertRaises(ParameterException, lambda: BinaryPayloadDecoder.fromRegisters("abcd"))
def testPayloadDecoderCoilFactory(self): """ Test the payload decoder reset functionality """ payload = [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1] decoder = BinaryPayloadDecoder.fromCoils(payload, endian=Endian.Little) encoded = "\x11\x88" self.assertEqual(encoded, decoder.decode_string(2)) decoder = BinaryPayloadDecoder.fromCoils(payload, endian=Endian.Big) encoded = "\x11\x88" self.assertEqual(encoded, decoder.decode_string(2)) self.assertRaises(ParameterException, lambda: BinaryPayloadDecoder.fromCoils("abcd"))
def read(self): count = COUNTS.get(self.data_type) if not count: raise ValueError('Unsupported data type {}'.format(self.data_type)) _logger.debug('read register: {}, count: {}, slave: {}, function: {}'.format(self.register_addr, count, self.slave_id, self.function_code)) if self.function_code == 3: result = self.client.read_holding_registers(self.register_addr, count, unit=self.slave_id) elif self.function_code == 4: result = self.client.read_input_registers(self.register_addr, count, unit=self.slave_id) else: raise ValueError('Unsupported function code {}'.format(self.function_code)) if result is None: raise IOError('No modbus reponse') if isinstance(result, ExceptionResponse): raise IOError(str(result)) d = BinaryPayloadDecoder.fromRegisters(result.registers, endian=self.endian) if self.data_type == '16bit_int': value = d.decode_16bit_int() elif self.data_type == '16bit_uint': value = d.decode_16bit_uint() elif self.data_type == '32bit_int': value = d.decode_32bit_int() elif self.data_type == '32bit_uint': value = d.decode_32bit_uint() elif self.data_type == '32bit_float': value = d.decode_32bit_float() elif self.data_type == '64bit_float': value = d.decode_64bit_float() else: raise ValueError('Unsupported data type {}'.format(self.data_type)) return value
def decode(self, formatters, byte_order='big', word_order='big'): """ Decode the register response to known formatters. :param formatters: int8/16/32/64, uint8/16/32/64, float32/64 :param byte_order: little/big :param word_order: little/big :return: Decoded Value """ # Read Holding Registers (3) # Read Input Registers (4) # Read Write Registers (23) if not isinstance(formatters, (list, tuple)): formatters = [formatters] if self.function_code not in [3, 4, 23]: print_formatted_text( HTML("<red>Decoder works only for registers!!</red>")) return byte_order = (Endian.Little if byte_order.strip().lower() == "little" else Endian.Big) word_order = (Endian.Little if word_order.strip().lower() == "little" else Endian.Big) decoder = BinaryPayloadDecoder.fromRegisters(self.data.get('registers'), byteorder=byte_order, wordorder=word_order) for formatter in formatters: formatter = FORMATTERS.get(formatter) if not formatter: print_formatted_text( HTML("<red>Invalid Formatter - {}" "!!</red>".format(formatter))) return decoded = getattr(decoder, formatter)() self.print_result(decoded)
def checkPump(self,client_p): self.p_count += 1 rq = client_p.write_register(550,self.p_count,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) self.setPumpFlowAndPressure()
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 requestLoop(self): meterreadings = {} try: if (self.client.connect() is False): print('not connected') self.client = self.client.connect() print('trying to connecto to ' + str(self.pfcIp)) #============================================================================== # Read current timestamp from PFC #============================================================================== timestampSys = round(time.time() * 1000) result2 = self.client.read_holding_registers(4, 4) decoder = BinaryPayloadDecoder.fromRegisters(result2.registers, endian=Endian.Little) timestampPFC = decoder.decode_64bit_int() #============================================================================== # Reads the values from modbus registers clamp by clamp # and buffers the results in meterreadings{} # It is not possible to read all registers in one request because of the limitation of the Modbus-Message size to 255kb # When the results of all clamps are buffered, they are published #============================================================================== result = self.client.read_coils(16, 4) meterreadings = {'shStarr': result.bits[0], 'sh4QS': result.bits[1], 'speicherSh': result.bits[2], 'speicher4QS': result.bits[3]} #============================================================================== # standardize both TimestampPFC and TimestampSYS precision to be millisecond #============================================================================== meterreadingsToCompare = {} meterreadingsToCompare = meterreadings self.oldState.pop('TimestampPFC', None) self.oldState.pop('TimestampSYS', None) self.elapsedTime = self.elapsedTime + 1 if (self.oldState != meterreadingsToCompare) or (self.elapsedTime >= 60): self.elapsedTime = 0 self.oldState = meterreadingsToCompare meterreadings['TimestampPFC'] = str(timestampPFC)[0:13] meterreadings['TimestampSYS'] = round(time.time() * 1000) self.publish(u'eshl.wago.v1.readout.misc.4qs', json.dumps(meterreadings, sort_keys=True)) self.publish(u'eshl.wago.v2.readout.misc.4qs', meterreadings) #============================================================================== # If there is no connection to the pfc-modbus slave or no connection to the pfc at all # the blankDataSet is published #============================================================================== #============================================================================== # except ConnectionException as connErr: # for x in range(0, len(self.clamps)): # meterreadings[self.clamps[x]] = json.dumps(self.blankDataSetGen(), sort_keys=True) # self.publish(u'org.eshl.wago.readout.meter.494', json.dumps(meterreadings,sort_keys=True)) # print(str(connErr)) #============================================================================== except Exception as err: print("error: {}".format(err), file=sys.stdout) traceback.print_exc(file=sys.stdout)
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 __decodeData(self, data): """Decode MODBUS data to float Function decodes a list of MODBUS 32bit float data passed to it into its respective list of floats. Arguments: :param data: Data to be decoded :type data: list """ 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 readChannels(): # voltage phase 1 to neutral print "New measurement readings: ", int(time.time()) listValues = list() for c in listChannels: handle = client.read_holding_registers(c['register'],c['words'],unit=c['unit']) # print c['description'], ":" if c['words'] > 1: decoder = BinaryPayloadDecoder.fromRegisters(handle.registers, endian=Endian.Big) value = decoder.decode_32bit_int()/float(c['factor']) else: value = handle.registers[0]/float(c['factor']) #print c['description'], ":", str(value) listValues.append(value) for i, channel in enumerate(listChannels): # print channel['description'],":", channel['uuid'], int(time.time()*1000), listValues[i] # Here fire values into VZ middleware addValue(channel['uuid'], int(time.time()*1000), listValues[i])
def read_register(client, register): logger.info("---- Read register " + str(register)) try: rr = client.read_holding_registers(register, count=2, unit=1) logger.info("Register value are " + str(rr.registers)) # build register reg=[0, 0] reg[0] = rr.registers[0] reg[1] = rr.registers[1] # decode register decoder = BinaryPayloadDecoder.fromRegisters(reg, endian=Endian.Big) decoded = decoder.decode_32bit_float() logger.info("Register decoded value are " + str(decoded)) return decoded except ConnectionException: raise ConnectionExceptionRest("")
def __get_mc602(self, address): try: log.debug("Attempting to read from MC602") registers = self.read_input_registers( \ address = address, count = 2, unit = 65) log.debug("Successfully read registers from MC602") log.debug("Attempting to convert registers") # registers are encoded in "big endian", however the attribute # to convert to a float value in pymodbus therefore is Little # (and not Big as expected)! Details in class Constants/Endian decoder = BinaryPayloadDecoder.fromRegisters(registers, \ endian = Endian.Little) float_value = decoder.decode_32bit_float() log.debug("Successfully converted registers to float_value") return float_value except: log.error("Failed to read from MC602")
def read(self): for x in self.queue[self.current]: try: t = util.now() self.res = self.client.read_holding_registers(3900, 100, unit=x.Id) if (self.res == None): continue for y in xrange(0, len(self.parameters[x.Model])): read_reg = self.reading_registers[x.Model][y] if (read_reg == 92 or read_reg == 98): decoder = BinaryPayloadDecoder.fromRegisters(self.res.registers[read_reg:read_reg + 2], endian=Endian.Big) value = decoder.decode_32bit_uint() else: value = convert((self.res.registers[read_reg + 1] << 16) + self.res.registers[read_reg]) self.add('/Meter' + str(x.Id) + '/' + self.parameters[x.Model][y], t, value) except SerialException: print "Serial Exception encountered. Looking for new tty port." self.client = self.CONNECT_TO_METER() pop_count = len(self.queue[self.current]) for x in xrange(0, pop_count): popped = self.queue[self.current].pop(0) next_index = (self.current + popped.Rate) % self.SLOWEST_POSSIBLE_RATE while (len(self.queue[next_index]) == 2): next_index += 1 if (next_index == self.SLOWEST_POSSIBLE_RATE): next_index = 0 self.queue[next_index].append(popped) self.current = (self.current + 1) % self.SLOWEST_POSSIBLE_RATE
def on_btnShow_clicked(self,button): # show dlgRegistries self.lstDialog = builder.get_object("dlgRegistries") self.liststore = builder.get_object("liststore1") if not self.ret_p: self.ret_p = self.client_p.connect() if self.ret_p: self.liststore.clear() rr = self.client_p.read_holding_registers(500,100,unit=1) for idx in [0,2,4,6,12,13,14,15,16,20,50,52,60,62]: if idx in (2,4,6,52): decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[idx:idx+1],endian=Endian.Little) bits = decoder.decode_bits() bits += decoder.decode_bits() for ib, b in enumerate(bits): if b: sCode = "%MW5{0:02d}:X{1}".format(idx,ib) self.liststore.append([sCode,reg_descr[sCode], str( b ) ]) else: sCode = "%MW5{0:02d}".format(idx) self.liststore.append([sCode, reg_descr[sCode], str( rr.registers[idx]) ]) response = self.lstDialog.run() self.lstDialog.hide()
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 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 ReadUInt64(self, addr): data = self.client.read_holding_registers(addr, 4, unit=71) UInt64register = BinaryPayloadDecoder.fromRegisters( data.registers, byteorder=Endian.Big, wordorder=Endian.Big) result = UInt64register.decode_64bit_uint() return (result)
idslave = 0x01 if len(sys.argv) == 2: try: idslave = int(sys.argv[1]) except: print "usage: %s [idslave]" % sys.argv[0] sys.exit(-1) # get running mode print "modbus cmd: 0x03 value: 0x0000 length: 0x01\n" result = client.read_holding_registers(address=0x0000, count=0x01, unit=idslave) decoder = BinaryPayloadDecoder.fromRegisters(result.registers, endian=Endian.Big) print decoder.decode_16bit_int(), " (running mode)\n", print # get loader version print "modbus cmd: 0x03 value: 0x0001 length: 0x02\n" result = client.read_holding_registers(address=0x0001, count=0x02, unit=idslave) decoder = BinaryPayloadDecoder.fromRegisters(result.registers, endian=Endian.Big) x = decoder.decode_32bit_int() print ''.join(chr((x >> 8 * (4 - byte - 1)) & 0xFF) for byte in range(4)), " (software version)\n",
def __read_s16(self, adr_dec): result = self.client.read_holding_registers(adr_dec, 1, unit=71) s16_value = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big, wordorder=Endian.Little) return s16_value.decode_16bit_uint()
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()
def get_current_status(self): """ Gets the current status of the motor, including running data, operating data, and error data. :return: A dictionary containing the current data of the motor. Please use the converter class to convert each value into the appropriate unit. """ motor_running_data = self.modbus_client.read_holding_registers( MOTOR_POS, 4, unit=self.address) motor_voltage_data = self.modbus_client.read_holding_registers( MOTOR_VOLTAGE, 1, unit=self.address) motor_current_data = self.modbus_client.read_holding_registers( TORQUE_CURRENT, 1, unit=self.address) motor_operating_data = self.modbus_client.read_holding_registers( TEMP_ELECTRONICS, 2, unit=self.address) motor_error_data = self.modbus_client.read_holding_registers( ERROR, 1, unit=self.address) if motor_running_data.isError() or motor_error_data.isError( ) or motor_voltage_data.isError() or motor_current_data.isError( ) or motor_operating_data.isError(): raise Exception('Unable to get motor data. {}'.format( motor_running_data, motor_operating_data, motor_current_data, motor_voltage_data, motor_error_data)) decoder = BinaryPayloadDecoder.fromRegisters( motor_running_data.registers[0:2], byteorder=Endian.Big, wordorder=Endian.Big) decoder2 = BinaryPayloadDecoder.fromRegisters( motor_voltage_data.registers, byteorder=Endian.Big, wordorder=Endian.Big) decoder3 = BinaryPayloadDecoder.fromRegisters( motor_current_data.registers, byteorder=Endian.Big, wordorder=Endian.Big) decoder4 = BinaryPayloadDecoder.fromRegisters( motor_running_data.registers[3:4], byteorder=Endian.Big, wordorder=Endian.Big) error = motor_error_data.registers[0] if error == 0: error = "No error" if error == 1: error = "General internal error" if error == 2: error = "Internal software timing error" if error == 3: error = "Error in application: code not terminating" if error == 4097: error = "General communication error" if error == 4098: error = "Invalid register error" if error == 4353: error = "Modbus parity error" if error == 4354: error = "Modbus framing error" if error == 4355: error = "Modbus overrun error" if error == 4356: error = "Modbus checksum error" if error == 4357: error = "Modbus illegal function code error" if error == 4358: error = "Modbus illegal diagnostics function code error" if error == 8193: error = "Hardware overcurrent protection triggered" if error == 12289: error = "Supply voltage too low" if error == 12290: error = "Supply voltage too high" if error == 16385: error = "Temperature of electronics is too high" if error == 16386: error = "Temperature of motor winding is too high" if error == 20481: error = "Torque limiting is active" if error == 24577: error = "Locked shaft condition detected" if error == 28673: error = "Regulator error is large" # TIP: You can get true current drawn by the motor, by multiplying the torque value, and it's corresponding # speed. return { "position": decoder.decode_32bit_int(), "speed": motor_running_data.registers[2], "torque": decoder4.decode_16bit_int(), "voltage": decoder2.decode_16bit_int(), "current": decoder3.decode_16bit_int(), "electronics_temp": motor_operating_data.registers[0], "motor_temp": motor_operating_data.registers[1], "error": error }
def readmodbus(modbusid, register, fieldtype, readtype, serialport, current_baud): instrument = ModbusSerialClient(method='rtu', port=serialport, baudrate=current_baud, parity='E') instrument.connect() #print("Reading ModbusID %d register %d"%(modbusid,register)), x = None read = False validread = True while read == False: lock = True if lock: read = True # instrument.serial.reset_input_buffer() signed = False try: if fieldtype in ['int', 'sint']: readlen = 1 if fieldtype in ['long', 'slong', 'float']: readlen = 2 if fieldtype == 'string': readlen = 10 #print(".") if readtype == 3: x = instrument.read_holding_registers(register, readlen, unit=modbusid, timeout=.5) if readtype == 4: x = instrument.read_input_registers(register, readlen, unit=modbusid, timeout=.5) #print("..") instrument.close() #print(x) decoder = BinaryPayloadDecoder.fromRegisters( x.registers, byteorder=Endian.Big) if fieldtype == 'slong': x = decoder.decode_32bit_int() if fieldtype == 'long': x = decoder.decode_32bit_uint() if fieldtype == 'sint': x = decoder.decode_16bit_int() if fieldtype == 'int': x = decoder.decode_16bit_uint() if fieldtype == 'float': x = decoder.decode_32bit_float() if fieldtype == 'string': x = decoder.decode_string(10) except Exception as e: print(e) x = 0 validread = False #print(x,validread) #if fieldtype in ['sint','slong','int','long']: # print("%X"%x) #time.sleep(.1) return x
def adquisicion(): #try: global PStotal, PLtotal, PTred, PBtotal, sw, VpanelT, IpanelT k = 1 while True: #tic = tm.default_timer() #Inicializacion de variables antes de entrar al loop y obtener los promedios IpanelT = 0 VpanelT = 0 IcargaT = 0 VcargaT = 0 IbatT = 0 VbatT = 0 for j in range(501): ##potencia del panel solar Ipanel = mcp.read_adc(7) ## Corriente del panel solar Ipanel = ((Ipanel) * (5.15 / 1023)) + 0.03 #Ipanel=(-25.3+10*Ipanel)-0.2 Ipanel = (-2.6 + Ipanel) * (1 / 0.09693) IpanelT = IpanelT + Ipanel ## Suma de corriente del panel solar sin promediar Vpanel = mcp.read_adc(4) Vpanel = Vpanel * (5.15 / 1023) #*(37.5/7.5) ## voltaje del panel solar Vpanel = 4.093 * Vpanel + 3.4444 VpanelT = VpanelT + Vpanel # Suma de voltaje del panel solar sin promediar ## potencia de la carga Vcarga = mcp.read_adc(6) Vcarga = ((Vcarga) * (5.15 / 1023)) * (37000.0 / 7500.0) VcargaT = VcargaT + Vcarga Icarga = mcp.read_adc(0) ## Icarga = round(((Icarga) * (5.15 / 1023)), 2) ## voltaje desde el MCP #S_5=(-25.3+10*S_5m)-0.2 Icarga = (-2.54 + Icarga) * (1 / 0.095 ) ## calculo de corriente de la carga IcargaT = IcargaT + Icarga ## potencia de la bateria Ibat = mcp.read_adc(1) Ibat = ((Ibat) * (5.15 / 1023)) #Vsensor=Vsensor+Ibat #Ibat=(-2.54+Ibat)*(1/0.1852) IbatT = IbatT + Ibat Vbat = mcp.read_adc(5) Vbat = ((Vbat) * (5.15 / 1023)) * (37000.0 / 7500.0) VbatT = VbatT + Vbat #j=j+1 #toc = tm.default_timer() ## potencia del panel solar PStotal = round((IpanelT * VpanelT) / (j * j), 2) ## potencia del panel solar promedio ## potencia de la carga IcargaT = (IcargaT / j) - 0.2 PLtotal = (VcargaT / j) * IcargaT PLtotal = round( (-6.96327 + 0.742732 * PLtotal + 0.00062677 * PLtotal * PLtotal) + 2, 2) ## potencia de la bateria IbatT = IbatT / j if IbatT < 2.4: IbatT = 6 * IbatT - 14.28 elif IbatT > 2.46: IbatT = 5 * IbatT - 11.86 else: Ibat = 0 PBtotal = (round((IbatT * VbatT) / (j), 2)) - 13 if PLtotal < 2: PLtotal = 0 elif PStotal < 2: PStotal = 0 result = client.read_holding_registers(11729, 2, unit=1) #Current A 1100 decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big) PTred = decoder.decode_32bit_float() #if Pred<6: # Pred=8.1 sw = 1 k = k + 1 VpanelT = (VpanelT / j) IpanelT = IpanelT / j #hoja.write(k, 0, str(state)) #hoja.write(k, 1, str(VpanelT)) #hoja.write(k, 2, str(IpanelT)) #hoja.write(k, 3, str(PTred)) #hoja.write(k, 4, str(PLtotal)) #hoja.write(k, 5, str(PBtotal)) #hoja.write(k, 6, time.strftime("%X")) # print("Voltaje del panel solar = "+str(VpanelT)) # print("Corriente del panel solar ="+str(IpanelT)) # print("Potencia de la red = "+str(PTred)) # print("Potencia del panel = "+str(PStotal)) # print("Potencia de la bat = "+str(PBtotal)) # print("Corriente de la bat = "+str(IbatT)) # print("Voltaje de la bat = "+str(VbatT/j)) # print("Potencia de la carga = "+str(PLtotal)) # print(state) to5 = False Estados(state, to5) time.sleep(2) Potencias = [PTred, PStotal, PBtotal, PLtotal] return Potencias
def read(self): """ Read registers from client""" time.sleep(float(self._settings["interval"])) f = [] c = Cargo.new_cargo(rawdata="") if not self._modcon: self._con.close() self._log.info("Not connected, retrying connect" + str(self.init_settings)) self._con = self._open_modTCP(self.init_settings["modbus_IP"], self.init_settings["modbus_port"]) if self._modcon: #self._log.info(" names " + str(self._settings["rName"])) rNameList = self._settings["rName"] #self._log.info("rNames type: " + str(type(rNameList))) registerList = self._settings["register"] nRegList = self._settings["nReg"] rTypeList = self._settings["rType"] for idx, rName in enumerate(rNameList): register = int(registerList[idx]) qty = int(nRegList[idx]) rType = rTypeList[idx] self._log.debug("register # : " + str(register)) try: self.rVal = self._con.read_holding_registers(register - 1, qty, unit=1) assert (self.rVal.function_code < 0x80) except Exception as e: self._log.error("Connection failed on read of register: " + str(register) + " : " + str(e)) self._modcon = False else: #self._log.debug("register value:" + str(self.rVal.registers)+" type= " + str(type(self.rVal.registers))) #f = f + self.rVal.registers decoder = BinaryPayloadDecoder.fromRegisters( self.rVal.registers, endian=Endian.Big) self._log.debug("register type: " + str(rType)) if rType == "uint16": rValD = decoder.decode_16bit_uint() t = emonhub_coder.encode('H', rValD) f = f + list(t) elif rType == "uint32": rValD = decoder.decode_32bit_uint() t = emonhub_coder.encode('I', rValD) f = f + list(t) elif rType == "uint64": rValD = decoder.decode_64bit_uint() t = emonhub_coder.encode('Q', rValD) f = f + list(t) elif rType == "int16": rValD = decoder.decode_16bit_int() t = emonhub_coder.encode('h', rValD) f = f + list(t) elif rType == "string": rValD = decoder.decode_string(qty * 2) elif rType == "float32": rValD = decoder.decode_32bit_float() * 10 t = emonhub_coder.encode('f', rValD) f = f + list(t) else: self._log.error("Register type not found: " + str(rType) + " Register:" + str(register)) self._log.debug("Encoded value: " + str(t)) self._log.debug("reporting data: " + str(f)) if int(self._settings['nodeId']): c.nodeid = int(self._settings['nodeId']) c.realdata = f else: c.nodeid = int(12) c.realdata = f self._log.debug("Return from read data: " + str(c.realdata)) return c
reg2_324 = client2.read_holding_registers(324, 2, unit=71) # Plenticore Register 326: Monthly_yield [Wh] # ist PV Monatsertrag reg2_326 = client2.read_holding_registers(326, 2, unit=71) except: # Lesefehler bei den Registern, also Abbruch und mit 0 initialisierte Variablen in die Ramdisk write_log_entry( 'Fehler beim Lesen der Modbus-Register WR2 (falsche IP oder WR offline?)' ) write_to_ramdisk() exit() # ausgelesene Register WR 1 dekodieren #FRegister_100 = BinaryPayloadDecoder.fromRegisters(reg_100.registers, byteorder=Endian.Big, wordorder=Endian.Little) FRegister_150 = BinaryPayloadDecoder.fromRegisters(reg_150.registers, byteorder=Endian.Big, wordorder=Endian.Little) FRegister_220 = BinaryPayloadDecoder.fromRegisters(reg_220.registers, byteorder=Endian.Big, wordorder=Endian.Little) FRegister_222 = BinaryPayloadDecoder.fromRegisters(reg_222.registers, byteorder=Endian.Big, wordorder=Endian.Little) FRegister_224 = BinaryPayloadDecoder.fromRegisters(reg_224.registers, byteorder=Endian.Big, wordorder=Endian.Little) FRegister_230 = BinaryPayloadDecoder.fromRegisters(reg_230.registers, byteorder=Endian.Big, wordorder=Endian.Little) FRegister_232 = BinaryPayloadDecoder.fromRegisters(reg_232.registers, byteorder=Endian.Big,
def decode(value): value_d = decode.fromRegisters(value.registers, endian=Endian.Little) value_d ={'float':A_d.decode_32bit_float(),} for i, value in value_d.iteritems(): value=value return value
def onHeartbeat(self): #Domoticz.Log("onHeartbeat called") # Wich serial port settings to use? if (Parameters["Mode3"] == "S1B7PN"): StopBits, ByteSize, Parity = 1, 7, "N" if (Parameters["Mode3"] == "S1B7PE"): StopBits, ByteSize, Parity = 1, 7, "E" if (Parameters["Mode3"] == "S1B7PO"): StopBits, ByteSize, Parity = 1, 7, "O" if (Parameters["Mode3"] == "S1B8PN"): StopBits, ByteSize, Parity = 1, 8, "N" if (Parameters["Mode3"] == "S1B8PE"): StopBits, ByteSize, Parity = 1, 8, "E" if (Parameters["Mode3"] == "S1B8PO"): StopBits, ByteSize, Parity = 1, 8, "O" if (Parameters["Mode3"] == "S2B7PN"): StopBits, ByteSize, Parity = 2, 7, "N" if (Parameters["Mode3"] == "S2B7PE"): StopBits, ByteSize, Parity = 2, 7, "E" if (Parameters["Mode3"] == "S2B7PO"): StopBits, ByteSize, Parity = 2, 7, "O" if (Parameters["Mode3"] == "S2B8PN"): StopBits, ByteSize, Parity = 2, 8, "N" if (Parameters["Mode3"] == "S2B8PE"): StopBits, ByteSize, Parity = 2, 8, "E" if (Parameters["Mode3"] == "S2B8PO"): StopBits, ByteSize, Parity = 2, 8, "O" # How many registers to read (depending on data type)? # Added additional options for byte/word swapping registercount = 1 # Default if (Parameters["Mode6"] == "noco"): registercount = 1 if (Parameters["Mode6"] == "int8LSB"): registercount = 1 if (Parameters["Mode6"] == "int8MSB"): registercount = 1 if (Parameters["Mode6"] == "int16"): registercount = 1 if (Parameters["Mode6"] == "int16s"): registercount = 1 if (Parameters["Mode6"] == "int32"): registercount = 2 if (Parameters["Mode6"] == "int32s"): registercount = 2 if (Parameters["Mode6"] == "int64"): registercount = 4 if (Parameters["Mode6"] == "int64s"): registercount = 4 if (Parameters["Mode6"] == "uint8LSB"): registercount = 1 if (Parameters["Mode6"] == "uint8MSB"): registercount = 1 if (Parameters["Mode6"] == "uint16"): registercount = 1 if (Parameters["Mode6"] == "uint16s"): registercount = 1 if (Parameters["Mode6"] == "uint32"): registercount = 2 if (Parameters["Mode6"] == "uint32s"): registercount = 2 if (Parameters["Mode6"] == "uint64"): registercount = 4 if (Parameters["Mode6"] == "uint64s"): registercount = 4 if (Parameters["Mode6"] == "float32"): registercount = 2 if (Parameters["Mode6"] == "float32s"): registercount = 2 if (Parameters["Mode6"] == "float64"): registercount = 4 if (Parameters["Mode6"] == "float64s"): registercount = 4 if (Parameters["Mode6"] == "string2"): registercount = 2 if (Parameters["Mode6"] == "string4"): registercount = 4 if (Parameters["Mode6"] == "string6"): registercount = 6 if (Parameters["Mode6"] == "string8"): registercount = 8 # Split address to support TCP/IP device ID AddressData = Parameters["Address"].split("/") # Split on "/" UnitAddress = AddressData[0] # Is there a unit ID given after the IP? (e.g. 192.168.2.100/56) UnitIdForIp = 1 # Default if len(AddressData) > 1: UnitIdForIp = AddressData[1] ################################### # pymodbus: RTU / ASCII ################################### if (Parameters["Mode1"] == "rtu" or Parameters["Mode1"] == "ascii"): Domoticz.Debug("MODBUS DEBUG USB SERIAL HW - Port="+Parameters["SerialPort"]+", BaudRate="+Parameters["Mode2"]+", StopBits="+str(StopBits)+", ByteSize="+str(ByteSize)+" Parity="+Parity) Domoticz.Debug("MODBUS DEBUG USB SERIAL CMD - Method="+Parameters["Mode1"]+", Address="+UnitAddress+", Register="+Parameters["Password"]+", Function="+Parameters["Username"]+", Data type="+Parameters["Mode6"]) try: client = ModbusSerialClient(method=Parameters["Mode1"], port=Parameters["SerialPort"], stopbits=StopBits, bytesize=ByteSize, parity=Parity, baudrate=int(Parameters["Mode2"]), timeout=1, retries=2) except: Domoticz.Log("Error opening Serial interface on "+Parameters["SerialPort"]) Devices[1].Update(0, "0") # Update device in Domoticz ################################### # pymodbus: RTU over TCP ################################### if (Parameters["Mode1"] == "rtutcp"): Domoticz.Debug("MODBUS DEBUG TCP CMD - Method="+Parameters["Mode1"]+", Address="+UnitAddress+", Port="+Parameters["Port"]+", Register="+Parameters["Password"]+", Data type="+Parameters["Mode6"]) try: client = ModbusTcpClient(host=UnitAddress, port=int(Parameters["Port"]), framer=ModbusRtuFramer, auto_open=True, auto_close=True, timeout=5) except: Domoticz.Log("Error opening TCP interface on address: "+UnitAddress) Devices[1].Update(0, "0") # Update device in Domoticz ################################### # pymodbusTCP: TCP/IP ################################### if (Parameters["Mode1"] == "tcpip"): Domoticz.Debug("MODBUS DEBUG TCP CMD - Method="+Parameters["Mode1"]+", Address="+UnitAddress+", Port="+Parameters["Port"]+", Unit ID="+UnitIdForIp+", Register="+Parameters["Password"]+", Data type="+Parameters["Mode6"]) try: client = ModbusClient(host=UnitAddress, port=int(Parameters["Port"]), unit_id=UnitIdForIp, auto_open=True, auto_close=True, timeout=5) except: Domoticz.Log("Error opening TCP/IP interface on address: "+UnitAddress) Devices[1].Update(0, "0") # Update device in Domoticz ################################### # pymodbus section ################################### if (Parameters["Mode1"] == "rtu" or Parameters["Mode1"] == "ascii" or Parameters["Mode1"] == "rtutcp"): try: # Which function to execute? RTU/ASCII/RTU over TCP if (Parameters["Username"] == "1"): data = client.read_coils(int(Parameters["Password"]), registercount, unit=int(UnitIdForIp)) if (Parameters["Username"] == "2"): data = client.read_discrete_inputs(int(Parameters["Password"]), registercount, unit=int(UnitIdForIp)) if (Parameters["Username"] == "3"): data = client.read_holding_registers(int(Parameters["Password"]), registercount, unit=int(UnitIdForIp)) if (Parameters["Username"] == "4"): data = client.read_input_registers(int(Parameters["Password"]), registercount, unit=int(UnitIdForIp)) Domoticz.Debug("MODBUS DEBUG RESPONSE: " + str(data)) except: Domoticz.Log("Modbus error communicating! (RTU/ASCII/RTU over TCP), check your settings!") Devices[1].Update(0, "0") # Update device to OFF in Domoticz try: # How to decode the input? # Added option to swap bytes (little endian) if (Parameters["Mode6"] == "int16s" or Parameters["Mode6"] == "uint16s"): decoder = BinaryPayloadDecoder.fromRegisters(data, byteorder=Endian.Little, wordorder=Endian.Big) # Added option to swap words (little endian) elif (Parameters["Mode6"] == "int32s" or Parameters["Mode6"] == "uint32s" or Parameters["Mode6"] == "int64s" or Parameters["Mode6"] == "uint64s" or Parameters["Mode6"] == "float32s" or Parameters["Mode6"] == "float64s"): decoder = BinaryPayloadDecoder.fromRegisters(data, byteorder=Endian.Big, wordorder=Endian.Little) # Otherwise always big endian else: decoder = BinaryPayloadDecoder.fromRegisters(data, byteorder=Endian.Big, wordorder=Endian.Big) if (Parameters["Mode6"] == "noco"): value = data if (Parameters["Mode6"] == "int8LSB"): ignored = decoder.skip_bytes(1) value = decoder.decode_8bit_int() if (Parameters["Mode6"] == "int8MSB"): value = decoder.decode_8bit_int() if (Parameters["Mode6"] == "int16"): value = decoder.decode_16bit_int() if (Parameters["Mode6"] == "int16s"): value = decoder.decode_16bit_int() if (Parameters["Mode6"] == "int32"): value = decoder.decode_32bit_int() if (Parameters["Mode6"] == "int32s"): value = decoder.decode_32bit_int() if (Parameters["Mode6"] == "int64"): value = decoder.decode_64bit_int() if (Parameters["Mode6"] == "int64s"): value = decoder.decode_64bit_int() if (Parameters["Mode6"] == "uint8LSB"): ignored = decoder.skip_bytes(1) value = decoder.decode_8bit_uint() if (Parameters["Mode6"] == "uint8MSB"): value = decoder.decode_8bit_uint() if (Parameters["Mode6"] == "uint16"): value = decoder.decode_16bit_uint() if (Parameters["Mode6"] == "uint16s"): value = decoder.decode_16bit_uint() if (Parameters["Mode6"] == "uint32"): value = decoder.decode_32bit_uint() if (Parameters["Mode6"] == "uint32s"): value = decoder.decode_32bit_uint() if (Parameters["Mode6"] == "uint64"): value = decoder.decode_64bit_uint() if (Parameters["Mode6"] == "uint64s"): value = decoder.decode_64bit_uint() if (Parameters["Mode6"] == "float32"): value = decoder.decode_32bit_float() if (Parameters["Mode6"] == "float32s"): value = decoder.decode_32bit_float() if (Parameters["Mode6"] == "float64"): value = decoder.decode_64bit_float() if (Parameters["Mode6"] == "float64s"): value = decoder.decode_64bit_float() if (Parameters["Mode6"] == "string2"): value = decoder.decode_string(2) if (Parameters["Mode6"] == "string4"): value = decoder.decode_string(4) if (Parameters["Mode6"] == "string6"): value = decoder.decode_string(6) if (Parameters["Mode6"] == "string8"): value = decoder.decode_string(8) Domoticz.Debug("MODBUS DEBUG VALUE: " + str(value)) # Divide the value (decimal)? if (Parameters["Mode5"] == "div0"): value = str(value) if (Parameters["Mode5"] == "div10"): value = str(round(value / 10, 1)) if (Parameters["Mode5"] == "div100"): value = str(round(value / 100, 2)) if (Parameters["Mode5"] == "div1000"): value = str(round(value / 1000, 3)) if (Parameters["Mode5"] == "div10000"): value = str(round(value / 10000, 4)) Devices[1].Update(0, value) # Update value in Domoticz except: Domoticz.Log("Modbus error decoding or received no data (RTU/ASCII/RTU over TCP)!, check your settings!") Devices[1].Update(0, "0") # Update value in Domoticz ################################### # pymodbusTCP section ################################### if (Parameters["Mode1"] == "tcpip"): try: # Which function to execute? TCP/IP if (Parameters["Username"] == "1"): data = client.read_coils(int(Parameters["Password"]), registercount) if (Parameters["Username"] == "2"): data = client.read_discrete_inputs(int(Parameters["Password"]), registercount) if (Parameters["Username"] == "3"): data = client.read_holding_registers(int(Parameters["Password"]), registercount) if (Parameters["Username"] == "4"): data = client.read_input_registers(int(Parameters["Password"]), registercount) Domoticz.Debug("MODBUS DEBUG RESPONSE: " + str(data)) except: Domoticz.Log("Modbus error communicating! (TCP/IP), check your settings!") Devices[1].Update(0, "0") # Update device to OFF in Domoticz try: # How to decode the input? # Added option to swap bytes (little endian) if (Parameters["Mode6"] == "int16s" or Parameters["Mode6"] == "uint16s"): decoder = BinaryPayloadDecoder.fromRegisters(data, byteorder=Endian.Little, wordorder=Endian.Big) # Added option to swap words (little endian) elif (Parameters["Mode6"] == "int32s" or Parameters["Mode6"] == "uint32s" or Parameters["Mode6"] == "int64s" or Parameters["Mode6"] == "uint64s" or Parameters["Mode6"] == "float32s" or Parameters["Mode6"] == "float64s"): decoder = BinaryPayloadDecoder.fromRegisters(data, byteorder=Endian.Big, wordorder=Endian.Little) # Otherwise always big endian else: decoder = BinaryPayloadDecoder.fromRegisters(data, byteorder=Endian.Big, wordorder=Endian.Big) if (Parameters["Mode6"] == "noco"): value = data if (Parameters["Mode6"] == "int8LSB"): ignored = decoder.skip_bytes(1) value = decoder.decode_8bit_int() if (Parameters["Mode6"] == "int8MSB"): value = decoder.decode_8bit_int() if (Parameters["Mode6"] == "int16"): value = decoder.decode_16bit_int() if (Parameters["Mode6"] == "int16s"): value = decoder.decode_16bit_int() if (Parameters["Mode6"] == "int32"): value = decoder.decode_32bit_int() if (Parameters["Mode6"] == "int32s"): value = decoder.decode_32bit_int() if (Parameters["Mode6"] == "int64"): value = decoder.decode_64bit_int() if (Parameters["Mode6"] == "int64s"): value = decoder.decode_64bit_int() if (Parameters["Mode6"] == "uint8LSB"): ignored = decoder.skip_bytes(1) value = decoder.decode_8bit_uint() if (Parameters["Mode6"] == "uint8MSB"): value = decoder.decode_8bit_uint() if (Parameters["Mode6"] == "uint16"): value = decoder.decode_16bit_uint() if (Parameters["Mode6"] == "uint16s"): value = decoder.decode_16bit_uint() if (Parameters["Mode6"] == "uint32"): value = decoder.decode_32bit_uint() if (Parameters["Mode6"] == "uint32s"): value = decoder.decode_32bit_uint() if (Parameters["Mode6"] == "uint64"): value = decoder.decode_64bit_uint() if (Parameters["Mode6"] == "uint64s"): value = decoder.decode_64bit_uint() if (Parameters["Mode6"] == "float32"): value = decoder.decode_32bit_float() if (Parameters["Mode6"] == "float32s"): value = decoder.decode_32bit_float() if (Parameters["Mode6"] == "float64"): value = decoder.decode_64bit_float() if (Parameters["Mode6"] == "float64s"): value = decoder.decode_64bit_float() if (Parameters["Mode6"] == "string2"): value = decoder.decode_string(2) if (Parameters["Mode6"] == "string4"): value = decoder.decode_string(4) if (Parameters["Mode6"] == "string6"): value = decoder.decode_string(6) if (Parameters["Mode6"] == "string8"): value = decoder.decode_string(8) Domoticz.Debug("MODBUS DEBUG VALUE: " + str(value)) # Divide the value (decimal)? if (Parameters["Mode5"] == "div0"): value = str(value) if (Parameters["Mode5"] == "div10"): value = str(round(value / 10, 1)) if (Parameters["Mode5"] == "div100"): value = str(round(value / 100, 2)) if (Parameters["Mode5"] == "div1000"): value = str(round(value / 1000, 3)) if (Parameters["Mode5"] == "div10000"): value = str(round(value / 10000, 4)) if (value != "0"): Devices[1].Update(1, value) # Update value in Domoticz except: Domoticz.Log("Modbus error decoding or received no data (TCP/IP)!, check your settings!") Devices[1].Update(0, "0") # Update value in Domoticz
def __read_float(self, adr_dec): result = self.client.read_holding_registers(adr_dec, 2, unit=71) float_value = BinaryPayloadDecoder.fromRegisters( result.registers, byteorder=Endian.Big, wordorder=Endian.Little) return round(float_value.decode_32bit_float(), 2)
f1.write(str(status)) f1.close() if os.path.isfile(file_string): f = open( file_string , 'a') else: f = open( file_string , 'w') ipaddress=str(sys.argv[1]) newcurr=int(sys.argv[2]) client = ModbusTcpClient(ipaddress, port=502) # maxcurr state 1100 resp= client.read_holding_registers(1100,2,unit=255) decoder = BinaryPayloadDecoder.fromRegisters(resp.registers,byteorder=Endian.Big,wordorder=Endian.Big) final = float( decoder.decode_32bit_uint()) / 1000 oldcurr = int("%.f" % final) # cabel state 1004 resp= client.read_holding_registers(1004,2,unit=255) decoder = BinaryPayloadDecoder.fromRegisters(resp.registers,byteorder=Endian.Big,wordorder=Endian.Big) final2 = float( decoder.decode_32bit_uint()) plugs = "%.f" % final2 # max supported curr 1110 resp= client.read_holding_registers(1110,2,unit=255) decoder = BinaryPayloadDecoder.fromRegisters(resp.registers,byteorder=Endian.Big,wordorder=Endian.Big) final2 = float( decoder.decode_32bit_uint()) / 1000 supcur = int("%.f" % final2) if plugs == "7":
def onHeartbeat(self): Domoticz.Log("onHeartbeat called") ######################################## # SET HARDWARE - pymodbus: RTU / ASCII ######################################## if (self.Domoticz_Setting_Communication_Mode == "rtu" or self.Domoticz_Setting_Communication_Mode == "ascii"): Domoticz.Debug("MODBUS DEBUG - INTERFACE: Port=" + self.Domoticz_Setting_Serial_Port + ", BaudRate=" + self.Domoticz_Setting_Baudrate + ", StopBits=" + str(self.StopBits) + ", ByteSize=" + str(self.ByteSize) + " Parity=" + self.Parity) Domoticz.Debug("MODBUS DEBUG - SETTINGS: Method=" + self.Domoticz_Setting_Communication_Mode + ", Device ID=" + self.Domoticz_Setting_Device_ID + ", Register=" + self.Domoticz_Setting_Register_Number + ", Function=" + self.Domoticz_Setting_Modbus_Function + ", Data type=" + self.Domoticz_Setting_Data_Type + ", Pollrate=" + self.Domoticz_Setting_Device_Pollrate) try: client = ModbusSerialClient( method=self.Domoticz_Setting_Communication_Mode, port=self.Domoticz_Setting_Serial_Port, stopbits=self.StopBits, bytesize=self.ByteSize, parity=self.Parity, baudrate=int(self.Domoticz_Setting_Baudrate), timeout=2, retries=2) except: Domoticz.Error("Error opening Serial interface on " + self.Domoticz_Setting_Serial_Port) Devices[1].Update(1, "0") # Set value to 0 (error) ######################################## # SET HARDWARE - pymodbus: RTU over TCP ######################################## if (self.Domoticz_Setting_Communication_Mode == "rtutcp"): Domoticz.Debug("MODBUS DEBUG - INTERFACE: IP=" + self.Domoticz_Setting_TCP_IP + ", Port=" + self.Domoticz_Setting_TCP_PORT) Domoticz.Debug("MODBUS DEBUG - SETTINGS: Method=" + self.Domoticz_Setting_Communication_Mode + ", Device ID=" + self.Domoticz_Setting_Device_ID + ", Register=" + self.Domoticz_Setting_Register_Number + ", Function=" + self.Domoticz_Setting_Modbus_Function + ", Data type=" + self.Domoticz_Setting_Data_Type + ", Pollrate=" + self.Domoticz_Setting_Device_Pollrate) try: client = ModbusTcpClient(host=self.Domoticz_Setting_TCP_IP, port=int( self.Domoticz_Setting_TCP_PORT), framer=ModbusRtuFramer, auto_open=True, auto_close=True, timeout=2) except: Domoticz.Error( "Error opening RTU over TCP interface on address: " + self.Domoticz_Setting_TCP_IPPORT) Devices[1].Update(1, "0") # Set value to 0 (error) ######################################## # SET HARDWARE - pymodbusTCP: TCP/IP ######################################## if (self.Domoticz_Setting_Communication_Mode == "tcpip"): Domoticz.Debug("MODBUS DEBUG - INTERFACE: IP=" + self.Domoticz_Setting_TCP_IP + ", Port=" + self.Domoticz_Setting_TCP_PORT) Domoticz.Debug("MODBUS DEBUG - SETTINGS: Method=" + self.Domoticz_Setting_Communication_Mode + ", Device ID=" + self.Domoticz_Setting_Device_ID + ", Register=" + self.Domoticz_Setting_Register_Number + ", Function=" + self.Domoticz_Setting_Modbus_Function + ", Data type=" + self.Domoticz_Setting_Data_Type + ", Pollrate=" + self.Domoticz_Setting_Device_Pollrate) try: client = ModbusClient(host=self.Domoticz_Setting_TCP_IP, port=int(self.Domoticz_Setting_TCP_PORT), unit_id=int( self.Domoticz_Setting_Device_ID), auto_open=True, auto_close=True, timeout=2) except: Domoticz.Error("Error opening TCP/IP interface on address: " + self.Domoticz_Setting_TCP_IPPORT) Devices[1].Update(1, "0") # Set value to 0 (error) ######################################## # GET DATA - pymodbus: RTU / ASCII / RTU over TCP ######################################## if (self.Domoticz_Setting_Communication_Mode == "rtu" or self.Domoticz_Setting_Communication_Mode == "ascii" or self.Domoticz_Setting_Communication_Mode == "rtutcp"): try: # Function to execute if (self.Domoticz_Setting_Modbus_Function == "1"): data = client.read_coils( int(self.Domoticz_Setting_Register_Number), self.Register_Count, unit=int(self.Domoticz_Setting_Device_ID)) if (self.Domoticz_Setting_Modbus_Function == "2"): data = client.read_discrete_inputs( int(self.Domoticz_Setting_Register_Number), self.Register_Count, unit=int(self.Domoticz_Setting_Device_ID)) if (self.Domoticz_Setting_Modbus_Function == "3"): data = client.read_holding_registers( int(self.Domoticz_Setting_Register_Number), self.Register_Count, unit=int(self.Domoticz_Setting_Device_ID)) if (self.Domoticz_Setting_Modbus_Function == "4"): data = client.read_input_registers( int(self.Domoticz_Setting_Register_Number), self.Register_Count, unit=int(self.Domoticz_Setting_Device_ID)) if (self.Read_Scale_Factor == 1): decoder = BinaryPayloadDecoder.fromRegisters( data, byteorder=Endian.Big, wordorder=Endian.Big) decoder.skip_bytes((self.Register_Count - 1) * 2) sf_value = decoder.decode_16bit_int() data = data[0:self.Register_Count - 1] else: sf_value = 0 Domoticz.Debug("MODBUS DEBUG - RESPONSE: " + str(data)) except: Domoticz.Error( "Modbus error communicating! (RTU/ASCII/RTU over TCP), check your settings!" ) Devices[1].Update(1, "0") # Set value to 0 (error) ######################################## # GET DATA - pymodbusTCP: TCP/IP ######################################## if (self.Domoticz_Setting_Communication_Mode == "tcpip"): try: # Function to execute if (self.Domoticz_Setting_Modbus_Function == "1"): data = client.read_coils( int(self.Domoticz_Setting_Register_Number), self.Register_Count) if (self.Domoticz_Setting_Modbus_Function == "2"): data = client.read_discrete_inputs( int(self.Domoticz_Setting_Register_Number), self.Register_Count) if (self.Domoticz_Setting_Modbus_Function == "3"): data = client.read_holding_registers( int(self.Domoticz_Setting_Register_Number), self.Register_Count) if (self.Domoticz_Setting_Modbus_Function == "4"): data = client.read_input_registers( int(self.Domoticz_Setting_Register_Number), self.Register_Count) if (self.Read_Scale_Factor == 1): decoder = BinaryPayloadDecoder.fromRegisters( data, byteorder=Endian.Big, wordorder=Endian.Big) decoder.skip_bytes((self.Register_Count - 1) * 2) sf_value = decoder.decode_16bit_int() data = data[0:self.Register_Count - 1] else: sf_value = 0 Domoticz.Debug("MODBUS DEBUG RESPONSE: " + str(data)) except: Domoticz.Error( "Modbus error communicating! (TCP/IP), check your settings!" ) Devices[1].Update(1, "0") # Set value to 0 (error) ######################################## # DECODE DATA TYPE ######################################## # pymodbus (RTU/ASCII/RTU over TCP) will reponse in ARRAY, no matter what values read e.g. MODBUS DEBUG RESPONSE: [2] = data.registers # pymodbusTCP (TCP/IP) will give the value back e.g. MODBUS DEBUG RESPONSE: [61, 44] = data if (self.Domoticz_Setting_Communication_Mode == "rtu" or self.Domoticz_Setting_Communication_Mode == "ascii" or self.Domoticz_Setting_Communication_Mode == "rtutcp"): try: Domoticz.Debug("MODBUS DEBUG - VALUE before conversion: " + str(data.registers[0])) # Added option to swap bytes (little endian) if (self.Domoticz_Setting_Data_Type == "int16s" or self.Domoticz_Setting_Data_Type == "uint16s"): decoder = BinaryPayloadDecoder.fromRegisters( data.registers, byteorder=Endian.Little, wordorder=Endian.Big) # Added option to swap words (little endian) elif (self.Domoticz_Setting_Data_Type == "int32s" or self.Domoticz_Setting_Data_Type == "uint32s" or self.Domoticz_Setting_Data_Type == "int64s" or self.Domoticz_Setting_Data_Type == "uint64s" or self.Domoticz_Setting_Data_Type == "float32s" or self.Domoticz_Setting_Data_Type == "float64s"): decoder = BinaryPayloadDecoder.fromRegisters( data.registers, byteorder=Endian.Big, wordorder=Endian.Little) # Otherwise always big endian else: decoder = BinaryPayloadDecoder.fromRegisters( data.registers, byteorder=Endian.Big, wordorder=Endian.Big) except: Domoticz.Error( "Modbus error decoding or received no data (RTU/ASCII/RTU over TCP)!, check your settings!" ) Devices[1].Update(1, "0") # Set value to 0 (error) if (self.Domoticz_Setting_Communication_Mode == "tcpip"): try: Domoticz.Debug("MODBUS DEBUG - VALUE before conversion: " + str(data)) #value = data[0] # Added option to swap bytes (little endian) if (self.Domoticz_Setting_Data_Type == "int16s" or self.Domoticz_Setting_Data_Type == "uint16s"): decoder = BinaryPayloadDecoder.fromRegisters( data, byteorder=Endian.Little, wordorder=Endian.Big) # Added option to swap words (little endian) elif (self.Domoticz_Setting_Data_Type == "int32s" or self.Domoticz_Setting_Data_Type == "uint32s" or self.Domoticz_Setting_Data_Type == "int64s" or self.Domoticz_Setting_Data_Type == "uint64s" or self.Domoticz_Setting_Data_Type == "float32s" or self.Domoticz_Setting_Data_Type == "float64s"): decoder = BinaryPayloadDecoder.fromRegisters( data, byteorder=Endian.Big, wordorder=Endian.Little) # Otherwise always big endian else: decoder = BinaryPayloadDecoder.fromRegisters( data, byteorder=Endian.Big, wordorder=Endian.Big) except: Domoticz.Error( "Modbus error decoding or received no data (TCP/IP)!, check your settings!" ) Devices[1].Update(1, "0") # Set value to 0 (error) ######################################## # DECODE DATA VALUE ######################################## try: if (self.Domoticz_Setting_Data_Type == "noco"): value = data.registers[0] if (self.Domoticz_Setting_Data_Type == "bool"): value = bool(data.registers[0]) if (self.Domoticz_Setting_Data_Type == "int8LSB"): ignored = decoder.skip_bytes(1) value = decoder.decode_8bit_int() if (self.Domoticz_Setting_Data_Type == "int8MSB"): value = decoder.decode_8bit_int() if (self.Domoticz_Setting_Data_Type == "int16"): value = decoder.decode_16bit_int() if (self.Domoticz_Setting_Data_Type == "int16s"): value = decoder.decode_16bit_int() if (self.Domoticz_Setting_Data_Type == "int32"): value = decoder.decode_32bit_int() if (self.Domoticz_Setting_Data_Type == "int32s"): value = decoder.decode_32bit_int() if (self.Domoticz_Setting_Data_Type == "int64"): value = decoder.decode_64bit_int() if (self.Domoticz_Setting_Data_Type == "int64s"): value = decoder.decode_64bit_int() if (self.Domoticz_Setting_Data_Type == "uint8LSB"): ignored = decoder.skip_bytes(1) value = decoder.decode_8bit_uint() if (self.Domoticz_Setting_Data_Type == "uint8MSB"): value = decoder.decode_8bit_uint() if (self.Domoticz_Setting_Data_Type == "uint16"): value = decoder.decode_16bit_uint() if (self.Domoticz_Setting_Data_Type == "uint16s"): value = decoder.decode_16bit_uint() if (self.Domoticz_Setting_Data_Type == "uint32"): value = decoder.decode_32bit_uint() if (self.Domoticz_Setting_Data_Type == "uint32s"): value = decoder.decode_32bit_uint() if (self.Domoticz_Setting_Data_Type == "uint64"): value = decoder.decode_64bit_uint() if (self.Domoticz_Setting_Data_Type == "uint64s"): value = decoder.decode_64bit_uint() if (self.Domoticz_Setting_Data_Type == "float32"): value = decoder.decode_32bit_float() if (self.Domoticz_Setting_Data_Type == "float32s"): value = decoder.decode_32bit_float() if (self.Domoticz_Setting_Data_Type == "float64"): value = decoder.decode_64bit_float() if (self.Domoticz_Setting_Data_Type == "float64s"): value = decoder.decode_64bit_float() if (self.Domoticz_Setting_Data_Type == "string2"): value = decoder.decode_string(2) if (self.Domoticz_Setting_Data_Type == "string4"): value = decoder.decode_string(4) if (self.Domoticz_Setting_Data_Type == "string6"): value = decoder.decode_string(6) if (self.Domoticz_Setting_Data_Type == "string8"): value = decoder.decode_string(8) # Apply a scale factor (decimal) if (self.Domoticz_Setting_Scale_Factor == "div0"): value = str(value) if (self.Domoticz_Setting_Scale_Factor == "div10"): value = str(round(value / 10, 1)) if (self.Domoticz_Setting_Scale_Factor == "div100"): value = str(round(value / 100, 2)) if (self.Domoticz_Setting_Scale_Factor == "div1000"): value = str(round(value / 1000, 3)) if (self.Domoticz_Setting_Scale_Factor == "div10000"): value = str(round(value / 10000, 4)) if (self.Domoticz_Setting_Scale_Factor == "mul10"): value = str(value * 10) if (self.Domoticz_Setting_Scale_Factor == "mul100"): value = str(value * 100, 2) if (self.Domoticz_Setting_Scale_Factor == "mul1000"): value = str(value * 1000, 3) if (self.Domoticz_Setting_Scale_Factor == "mul10000"): value = str(value * 10000, 4) if (self.Domoticz_Setting_Scale_Factor == "sfnextreg"): if (sf_value == 0): value = str(value) if (sf_value == 1): value = str(round(value * 10, 1)) if (sf_value == 2): value = str(round(value * 100, 1)) if (sf_value == -1): value = str(round(value / 10, 1)) if (sf_value == -2): value = str(round(value / 100, 1)) Domoticz.Debug("MODBUS DEBUG - VALUE after conversion: " + str(value)) Devices[1].Update(1, value) # Update value except: Domoticz.Error( "Modbus error decoding or received no data!, check your settings!" ) Devices[1].Update(1, "0") # Set value to 0 (error)
async def write_to_influx(dbhost, dbport, period, dbname='solaredge'): global client def trunc_float(floatval): return float('%.2f' % floatval) try: solar_client = InfluxDBClient(host=dbhost, port=dbport, db=dbname) await solar_client.create_database(db=dbname) except ClientConnectionError as e: logger.error(f'Error during connection to InfluxDb {dbhost}: {e}') return logger.info('Database opened and initialized') while True: try: reg_block = client.read_holding_registers(40069, 38) if reg_block: # print(reg_block) data = BinaryPayloadDecoder.fromRegisters(reg_block, byteorder=Endian.Big, wordorder=Endian.Big) data.skip_bytes(12) scalefactor = 10**data.decode_16bit_int() data.skip_bytes(-10) # Register 40072-40075 datapoint['fields']['AC Total Current'] = trunc_float( data.decode_16bit_uint() * scalefactor) datapoint['fields']['AC Current phase A'] = trunc_float( data.decode_16bit_uint() * scalefactor) datapoint['fields']['AC Current phase B'] = trunc_float( data.decode_16bit_uint() * scalefactor) datapoint['fields']['AC Current phase C'] = trunc_float( data.decode_16bit_uint() * scalefactor) data.skip_bytes(14) scalefactor = 10**data.decode_16bit_int() data.skip_bytes(-8) # register 40080-40082 datapoint['fields']['AC Voltage phase A'] = trunc_float( data.decode_16bit_uint() * scalefactor) datapoint['fields']['AC Voltage phase B'] = trunc_float( data.decode_16bit_uint() * scalefactor) datapoint['fields']['AC Voltage phase C'] = trunc_float( data.decode_16bit_uint() * scalefactor) data.skip_bytes(4) scalefactor = 10**data.decode_16bit_int() data.skip_bytes(-4) # register 40084 datapoint['fields']['AC Power output'] = trunc_float( data.decode_16bit_int() * scalefactor) data.skip_bytes(24) scalefactor = 10**data.decode_16bit_int() data.skip_bytes(-6) # register 40094 datapoint['fields']['AC Lifetimeproduction'] = trunc_float( data.decode_32bit_uint() * scalefactor) data.skip_bytes(2) scalefactor = 10**data.decode_16bit_int() data.skip_bytes(-2) # register 40097 datapoint['fields']['DC Current'] = trunc_float( data.decode_16bit_uint() * scalefactor) data.skip_bytes(4) scalefactor = 10**data.decode_16bit_int() data.skip_bytes(-4) # register 40099 datapoint['fields']['DC Voltage'] = trunc_float( data.decode_16bit_uint() * scalefactor) data.skip_bytes(4) scalefactor = 10**data.decode_16bit_int() data.skip_bytes(-4) # datapoint 40101 datapoint['fields']['DC Power input'] = trunc_float( data.decode_16bit_int() * scalefactor) datapoint['time'] = str(datetime.datetime.utcnow().replace( tzinfo=datetime.timezone.utc).isoformat()) logger.debug(f'Writing to Influx: {str(datapoint)}') await solar_client.write(datapoint) else: # Error during data receive if client.last_error() == 2: logger.error( f'Failed to connect to SolarEdge inverter {client.host()}!' ) elif client.last_error() == 3 or client.last_error() == 4: logger.error('Send or receive error!') elif client.last_error() == 5: logger.error('Timeout during send or receive operation!') except InfluxDBWriteError as e: logger.error(f'Failed to write to InfluxDb: {e}') except IOError as e: logger.error(f'I/O exception during operation: {e}') except Exception as e: logger.error(f'Unhandled exception: {e}') await asyncio.sleep(period)
def onHeartbeat(self): self.client.connect() result = self.client.read_holding_registers(0, 11) if not result.isError(): on_off = int(result.registers[0]) eco = int(result.registers[2]) auto = int(result.registers[3]) mode = int(result.registers[4]) * 10 temp_control = int(result.registers[10]) * 10 + 10 UpdateDevice(self.UNITS['OnOff'], on_off, str(on_off), 0) UpdateDevice(self.UNITS['ECO'], eco, str(eco), 0) UpdateDevice(self.UNITS['Auto'], auto, str(auto), 0) UpdateDevice(self.UNITS['Mode'], mode, str(mode), 0) if mode == 50: # Kitchen UpdateDevice(self.UNITS['Kitchen'], 5, str(5), 0) elif mode == 60: # Fireplace UpdateDevice(self.UNITS['Fireplace'], 5, str(5), 0) else: UpdateDevice(self.UNITS['Kitchen'], 0, str(0), 0) UpdateDevice(self.UNITS['Fireplace'], 0, str(0), 0) UpdateDevice(self.UNITS['TempControlType'], temp_control, str(temp_control), 0) registersStartingOffset = 20 MonitoringDataResult = self.client.read_holding_registers(900, 47) if not MonitoringDataResult.isError(): SupplyTemp = ConvertToFloat(MonitoringDataResult, 1) ExtractTemp = ConvertToFloat(MonitoringDataResult, 2) OutdoorTemp = ConvertToFloat(MonitoringDataResult, 3) WaterTemp = ConvertToFloat(MonitoringDataResult, 4) UpdateDevice(self.UNITS['OutdoorTemp'], 0, str(OutdoorTemp), 0) UpdateDevice(self.UNITS['SupplyTemp'], 0, str(SupplyTemp), 0) UpdateDevice(self.UNITS['ExtractTemp'], 0, str(ExtractTemp), 0) UpdateDevice(self.UNITS['WaterTemp'], 0, str(WaterTemp), 0) SupplyFanIntens = ConvertToFloat(MonitoringDataResult, 9) ExtractFanIntens = ConvertToFloat(MonitoringDataResult, 10) HeatExchanger = ConvertToFloat(MonitoringDataResult, 11) ElectricHeater = ConvertToFloat(MonitoringDataResult, 12) WaterHeater = ConvertToFloat(MonitoringDataResult, 13) WaterCooling = ConvertToFloat(MonitoringDataResult, 14) DXUnit = ConvertToFloat(MonitoringDataResult, 15) FiltersImupurity = float(MonitoringDataResult.registers[16]) UpdateDevice(self.UNITS['SupplyFanIntensivity'], 0, str(SupplyFanIntens), 0) UpdateDevice(self.UNITS['ExtractFanIntensivity'], 0, str(ExtractFanIntens), 0) UpdateDevice(self.UNITS['HeatExchanger'], 0, str(HeatExchanger), 0) UpdateDevice(self.UNITS['ElectricHeater'], 0, str(ElectricHeater), 0) UpdateDevice(self.UNITS['WaterHeater'], 0, str(WaterHeater), 0) UpdateDevice(self.UNITS['WaterCooler'], 0, str(WaterCooling), 0) UpdateDevice(self.UNITS['DXUnit'], 0, str(DXUnit), 0) UpdateDevice(self.UNITS['FiltersImupurity'], 0, str(FiltersImupurity), 0) CurrentPowerConsumption = int( MonitoringDataResult.registers[0 + registersStartingOffset]) CurrentHeaterPower = int( MonitoringDataResult.registers[1 + registersStartingOffset]) CurrentHeatRecovery = int( MonitoringDataResult.registers[2 + registersStartingOffset]) CurrentExchangeEfficiency = int( MonitoringDataResult.registers[3 + registersStartingOffset]) CurrentEnergySaving = int( MonitoringDataResult.registers[4 + registersStartingOffset]) decoder = BinaryPayloadDecoder.fromRegisters( MonitoringDataResult.registers, byteorder=Endian.Big) decoder.skip_bytes(6 + 17 * 2 + 5 * 4) # 6 * char + 17 * short + 5 * int TotalEnergyConsumtion = decoder.decode_32bit_uint( ) # reg[11-12] from byte[21] UpdateDevice( self.UNITS['TotalEnergyConsumtion'], 0, str(CurrentPowerConsumption) + ';' + str(TotalEnergyConsumtion), 0) decoder.skip_bytes(8) TotalHeaterConsumtion = decoder.decode_32bit_uint( ) # reg[17-18] from byte[32] UpdateDevice( self.UNITS['TotalHeaterConsumtion'], 0, str(CurrentHeaterPower) + ';' + str(TotalHeaterConsumtion), 0) decoder.skip_bytes(8) TotalEnergyRecovered = decoder.decode_32bit_uint( ) # reg[23-24] from byte[44] UpdateDevice( self.UNITS['TotalEnergyRecovered'], 0, str(CurrentHeatRecovery) + ';' + str(TotalEnergyRecovered), 0) temperature = ConvertToFloat(MonitoringDataResult, 25 + registersStartingOffset) humidity = int( MonitoringDataResult.registers[26 + registersStartingOffset]) UpdateDevice(self.UNITS['CurrentExchangeEfficiency'], 0, str(CurrentExchangeEfficiency), 0) UpdateDevice(self.UNITS['CurrentEnergySaving'], 0, str(CurrentEnergySaving), 0) UpdateDevice(self.UNITS['Temp'], 0, str(temperature), 0) UpdateDevice(self.UNITS['Hum'], humidity, str(humidity), 0) if self.debug: Domoticz.Log("CurrentPowerConsumption: " + str(CurrentPowerConsumption)) Domoticz.Log("CurrentHeaterPower: " + str(CurrentHeaterPower)) Domoticz.Log("CurrentHeatRecovery: " + str(CurrentHeatRecovery)) Domoticz.Log("CurrentExchangeEfficiency: " + str(CurrentExchangeEfficiency)) Domoticz.Log("CurrentEnergySaving: " + str(CurrentEnergySaving)) Domoticz.Log("CurrentEnergySaving: " + str(CurrentEnergySaving)) Domoticz.Log("TotalEnergyConsumtion: " + str(TotalEnergyConsumtion)) Domoticz.Log("TotalHeaterConsumtion: " + str(TotalHeaterConsumtion)) Domoticz.Log("TotalEnergyRecovered: " + str(TotalEnergyRecovered)) Domoticz.Log("Temperature: " + str(temperature)) Domoticz.Log("Humidity: " + str(humidity)) self.client.close()
keyfile = private_key, cert_reqs = ssl.CERT_REQUIRED, tls_version = ssl.PROTOCOL_TLSv1_2, ciphers = None) client.on_connect = on_connect client.on_message = on_message client.connect(mqtt_url, port = 8883, keepalive=60) client.loop_start() # Publish to the same topic in a loop forever loopCount = 0 while True: Watthour = modclient.read_holding_registers(0x009E, 2, unit=1) decoder = BinaryPayloadDecoder.fromRegisters(Watthour.registers, Endian.Big, wordorder=Endian.Little) Wh_val = float(decoder.decode_32bit_float()) print("WattHour:",Wh_val) counter += 1 client.publish("Aws_regor", "Watthour = " + str(Wh_val) + " " + str(loopCount), 1) loopCount += 1 sleep(5)
def Read(Client, Tag_Number, Average=False, count=20, sleep_time=.010, Bool=False): ''' -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. __ Average: Tells us wether or not to average these data points __ Count: The number of points that we will average over if Average == True __ sleep_time: Time (ms) that we will rest before grabbing the next piece of data -Must have established client before attempting to read from the client -Outputs: The value of that Moodbus tag Method: Grab holding register value - Decode that value into a 32 bit float - Convert from 32 bit float to regular float -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 = Read(Client,22201) ''' Tag_Number = int(Tag_Number) - 1 if Bool == False: if Average == True: temp_list = [] for i in range(count): Payload = Client.read_holding_registers(Tag_Number, 2, unit=1) Tag_Value_Bit = BinaryPayloadDecoder.fromRegisters( Payload.registers, byteorder=Endian.Big, wordorder=Endian.Big) Tag_Value = Tag_Value_Bit.decode_32bit_float() temp_list.append(Tag_Value) time.sleep(sleep_time) return (sum(temp_list) / count) else: Payload = Client.read_holding_registers(Tag_Number, 2, unit=1) Tag_Value_Bit = BinaryPayloadDecoder.fromRegisters( Payload.registers, byteorder=Endian.Big, wordorder=Endian.Big) Tag_Value = Tag_Value_Bit.decode_32bit_float() return Tag_Value if Bool == True: Tag_Value = Client.read_coils(Tag_Number, unit=1).bits[0] return Tag_Value
def __get_mc602(self, address): registers = self.read_input_registers(address = address, count = 2, unit = 65) decoder = BinaryPayloadDecoder.fromRegisters(registers, endian = Endian.Little) float_value = decoder.decode_32bit_float() return float_value
def testLittleEndianPayloadDecoder(self): ''' Test basic bit message encoding/decoding ''' decoder = BinaryPayloadDecoder(self.little_endian_payload, endian=Endian.Little) self.assertEqual(1, decoder.decode_8bit_uint()) self.assertEqual(2, decoder.decode_16bit_uint()) self.assertEqual(3, decoder.decode_32bit_uint()) self.assertEqual(4, decoder.decode_64bit_uint()) self.assertEqual(-1, decoder.decode_8bit_int()) self.assertEqual(-2, decoder.decode_16bit_int()) self.assertEqual(-3, decoder.decode_32bit_int()) self.assertEqual(-4, decoder.decode_64bit_int()) self.assertEqual(1.25, decoder.decode_32bit_float()) self.assertEqual(6.25, decoder.decode_64bit_float()) self.assertEqual('test', decoder.decode_string(4).decode()) self.assertEqual(self.bitstring, decoder.decode_bits())
def convert(self, config, data): self.__result["telemetry"] = [] self.__result["attributes"] = [] for config_data in data: for tag in data[config_data]: try: configuration = data[config_data][tag]["data_sent"] response = data[config_data][tag]["input_data"] if configuration.get("byteOrder") is not None: byte_order = configuration["byteOrder"] else: byte_order = configuration.get("byteOrder", "LITTLE") endian_order = Endian.Little if byte_order.upper( ) == "LITTLE" else Endian.Big decoded_data = None if not isinstance(response, ModbusIOException): if configuration["functionCode"] in [1, 2]: result = response.bits result = result if byte_order.upper( ) == 'LITTLE' else result[::-1] log.debug(result) if configuration["type"].lower() == "bits": decoded_data = result[:configuration.get( "objectsCount", configuration. get("registersCount", configuration.get("registerCount", 1) ))] if len(decoded_data) == 1 and isinstance( decoded_data, list): decoded_data = decoded_data[0] else: decoded_data = result[0] elif configuration["functionCode"] in [3, 4]: decoder = None registers = response.registers log.debug("Tag: %s Config: %s registers: %s", tag, str(configuration), str(registers)) try: decoder = BinaryPayloadDecoder.fromRegisters( registers, byteorder=endian_order) except TypeError: # pylint: disable=E1123 decoder = BinaryPayloadDecoder.fromRegisters( registers, endian=endian_order) assert decoder is not None decoded_data = self.__decode_from_registers( decoder, configuration) if configuration.get("divider"): decoded_data = float(decoded_data) / float( configuration["divider"]) if configuration.get("multiplier"): decoded_data = decoded_data * configuration[ "multiplier"] else: log.exception(response) decoded_data = None if config_data == "rpc": return decoded_data log.debug("datatype: %s \t key: %s \t value: %s", self.__datatypes[config_data], tag, str(decoded_data)) self.__result[self.__datatypes[config_data]].append( {tag: decoded_data}) except Exception as e: log.exception(e) log.debug(self.__result) return self.__result
def ReadInt32(self, addr): data = self.client.read_holding_registers(addr, 2, unit=71) Int32register = BinaryPayloadDecoder.fromRegisters( data.registers, byteorder=Endian.Big, wordorder=Endian.Big) result = Int32register.decode_32bit_int() return (result)
def _get_modbus_message(client, adress, count, unit): data = client.read_holding_registers(adress, count, unit=unit) return BinaryPayloadDecoder.fromRegisters(data.registers, byteorder=Endian.Big)
import numpy as np import Master as M import Tag_Database as Tags from pymodbus.client.sync import ModbusTcpClient from pymodbus.payload import BinaryPayloadDecoder from pymodbus.payload import BinaryPayloadBuilder from pymodbus.constants import Endian Client = M.Make_Client('10.50.0.10') Tag_Number = int('00015') - 1 Payload = Client.read_holding_registers(Tag_Number, 2, unit=1) Tag_Value_Bit = BinaryPayloadDecoder.fromRegisters(Payload.registers, byteorder=Endian.Big, wordorder=Endian.Big) Tag_Value = Tag_Value_Bit.decode_32bit_float() print(True == int(Tag_Value))
def requestLoop(self): numberOfRegPerClamp = 74 # max number of holding registers is 125 as the total number of bytes incl. CRC is 256 according to the spec (via 03 command) meterreadings = {} meterreadingsV2 = {} print(time.time()) try: if (self.client.connect() is False): print('not connected') self.client = self.client.connect() print('trying to connecto to ' + str(self.pfcIp)) address = 0 #============================================================================== # Read current timestamp from PFC #============================================================================== timestampSys = round(time.time() * 1000) result2 = self.client.read_holding_registers(timestampPFCRegister, 4) decoder = BinaryPayloadDecoder.fromRegisters(result2.registers, endian=Endian.Little) timestampPFC = decoder.decode_64bit_int() #============================================================================== # Reads the values from modbus registers clamp by clamp # and buffers the results in meterreadings{} # It is not possible to read all registers in one request because of the limitation of the Modbus-Message size to 255kb # When the results of all clamps are buffered, they are published #============================================================================== for x in range(0, len(self.clamps)): result = self.client.read_holding_registers(address, numberOfRegPerClamp) decoder = BinaryPayloadDecoder.fromRegisters(result.registers, endian=Endian.Little) decoded = { 'I1': decoder.decode_32bit_float(), 'I2': decoder.decode_32bit_float(), 'I3': decoder.decode_32bit_float(), 'U1': decoder.decode_32bit_float(), 'U2': decoder.decode_32bit_float(), 'U3': decoder.decode_32bit_float(), 'P1': decoder.decode_32bit_float(), 'P2': decoder.decode_32bit_float(), 'P3': decoder.decode_32bit_float(), 'Q1': decoder.decode_32bit_float(), 'Q2': decoder.decode_32bit_float(), 'Q3': decoder.decode_32bit_float(), 'S1': decoder.decode_32bit_float(), 'S2': decoder.decode_32bit_float(), 'S3': decoder.decode_32bit_float(), 'CosPhi1': decoder.decode_32bit_float(), 'CosPhi2': decoder.decode_32bit_float(), 'CosPhi3': decoder.decode_32bit_float(), 'PF1': decoder.decode_32bit_float(), 'PF2': decoder.decode_32bit_float(), 'PF3': decoder.decode_32bit_float(), 'Qua1': decoder.decode_32bit_float(), 'Qua2': decoder.decode_32bit_float(), 'Qua3': decoder.decode_32bit_float(), 'AEI1': decoder.decode_32bit_float(), 'AED1': decoder.decode_32bit_float(), 'REI1': decoder.decode_32bit_float(), 'REC1': decoder.decode_32bit_float(), 'AEI2': decoder.decode_32bit_float(), 'AED2': decoder.decode_32bit_float(), 'REI2': decoder.decode_32bit_float(), 'REC2': decoder.decode_32bit_float(), 'AEI3': decoder.decode_32bit_float(), 'AED3': decoder.decode_32bit_float(), 'REI3': decoder.decode_32bit_float(), 'REC3': decoder.decode_32bit_float(), 'DataValid' : decoder.decode_32bit_float()} #============================================================================== # standardize both TimestampPFC and TimestampSYS precision to be millisecond #============================================================================== decoded['TimestampPFC'] = str(timestampPFC)[0:13] decoded['TimestampSYS'] = timestampSys #============================================================================== # PFC measures energy values in mWh --> convert to watt-seconds #============================================================================== decoded['AEI1'] = float(decoded['AEI1']) * 3.6 decoded['AED1'] = float(decoded['AED1']) * 3.6 decoded['REI1'] = float(decoded['REI1']) * 3.6 decoded['REC1'] = float(decoded['REC1']) * 3.6 decoded['AEI2'] = float(decoded['AEI2']) * 3.6 decoded['AED2'] = float(decoded['AED2']) * 3.6 decoded['REI2'] = float(decoded['REI2']) * 3.6 decoded['REC2'] = float(decoded['REC2']) * 3.6 decoded['AEI3'] = float(decoded['AEI3']) * 3.6 decoded['AED3'] = float(decoded['AED3']) * 3.6 decoded['REI3'] = float(decoded['REI3']) * 3.6 decoded['REC3'] = float(decoded['REC3']) * 3.6 meterreadingsV2[self.clampsV2[x]] = decoded meterreadings[self.clamps[x]] = decoded address += numberOfRegPerClamp self.publish(u'eshl.wago.v1.readout.wiz.494', json.dumps(meterreadings, sort_keys=True)) self.publish(u'eshl.wago.v2.readout.wiz.494', meterreadingsV2) #============================================================================== # If there is no connection to the pfc-modbus slave or no connection to the pfc at all # the blankDataSet is published #============================================================================== except ConnectionException as connErr: for x in range(0, len(self.clamps)): meterreadings[self.clamps[x]] = self.blankDataSetGen() self.publish(u'eshl.wago.v1.readout.wiz.494', json.dumps(meterreadings, sort_keys=True)) self.publish(u'eshl.wago.v2.readout.wiz.494', meterreadings) sys.__stdout__.write('ConnectionException in-wago-wiz-494' + '\n' + 'Timestamp: ' + str(timestampSys) + ', Errorcode --> ' + str(connErr)) sys.__stdout__.flush() except Exception as err: sys.__stdout__.write('Exception in-wago-wiz-494' + '\n' + 'Timestamp: ' + str(timestampSys) + ', Errorcode --> ' + str(err)) sys.__stdout__.flush()
def read(self, iO='in'): #print('DATEN VOM BUS LESEN') i = 0 if iO !='in': x = 'out' else: x = 'in' try: for byte in self._db[x]: rr = self._modbuspy.read_holding_registers(byte,2) pprint(rr) decodert2 = BinaryPayloadDecoder.fromRegisters(rr.registers, endian=Endian.Little) ##prüfen welcher dpt typ vorliegt und dann das registerabfrage ergebnis aufdröseln: #->decode_16bit_uint() -> 7 / 8 #->decode_8bit_uint() -> 5 | 5.001 #->decode_8bit_int() -> 6 #->decode_bits() -> 1 for bit in self._db[x][byte]: ##eintraege in dict durchgehen bitpos = bit[0] type = bit[1] name = bit[3] if type == '5' or type == '5.001' or type == '6': ##8bit uint / int length = 8 if type == '6': lb = decodert2.decode_8bit_int() hb = decodert2.decode_8bit_int() elif type == '5' or type == '5.001': lb = decodert2.decode_8bit_uint() hb = decodert2.decode_8bit_uint() if bitpos < 8:#lb value = hb #logger.debug('MODBUS: byte{0} startpos{1} wert (5) {2}'.format(bit, bitpos,value)) else:#hb value = lb #logger.debug('MODBUS: byte{0} startpos{1} wert (5) {2}'.format(bit, bitpos,value)) if type == '5.001': #print('lb/hb Daten gelesen', value) value = self.en5001(value) #logger.debug('MODBUS: byte{0} startpos{1} wert (5.001) {2}'.format(bit, bitpos, value)) elif type == '7' or type == '8': #16bit uint / int length = 16 if type == '7': #0...65535 value = decodert2.decode_16bit_uint() #logger.debug('MODBUS: 16bit uint{0}'.format(value)) else: #-32768...32767 value = decodert2.decode_16bit_int() #logger.debug('MODBUS: 16bit int{0}'.format(value)) elif type == '1': length = 1 hb = decodert2.decode_bits() lb = decodert2.decode_bits() bits = lb+hb value = bits[bitpos] #logger.debug('MODBUS: Bits{0}'.format(bits)) bit[2] = value #zurückspeichern decodert2.reset() ##Debug################################################################################# bit[3](value, caller='modbus') i = i+1 lb = decodert2.decode_bits() hb = decodert2.decode_bits() bits = hb+lb decodert2.reset() logger.debug('MODBUS: read from PLC {0}-{1} {2}'.format(byte, bits, bytes)) except Exception as e: logger.error('MODBUS: Could not read an InputWord, because {}'.format( e)) self._lock.release() return None i = 0 return None
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 get_pv_data(config): host = config.get('inv_host') port = config.get('inv_port', 502) modbusid = config.get('inv_modbus', 3) manufacturer = config.get('inv_modbus', 'Default') registers = eval(config.get('registers')) client = ModbusClient(host=host, port=port) try: client.connect() except: print('Modbus Connection Error', 'could not connect to target. Check your settings, please.') return None data = {} ## empty data store for current values for myreg in registers: ## if the connection is somehow not possible (e.g. target not responding) # show a error message instead of excepting and stopping try: received = client.read_input_registers(address=int(myreg[0]), count=modbusdatatype[myreg[1]], unit=modbusid) except: thisdate = str(datetime.datetime.now()).partition('.')[0] thiserrormessage = thisdate + ': Connection not possible. Check settings or connection.' print(thiserrormessage) return None ## prevent further execution of this function name = myreg[3] message = BinaryPayloadDecoder.fromRegisters(received.registers, byteorder=Endian.Big, wordorder=Endian.Big) ## provide the correct result depending on the defined datatype if myreg[1] == 'S32': interpreted = message.decode_32bit_int() elif myreg[1] == 'U32': interpreted = message.decode_32bit_uint() elif myreg[1] == 'U64': interpreted = message.decode_64bit_uint() elif myreg[1] == 'STR32': interpreted = message.decode_string(32) elif myreg[1] == 'S16': interpreted = message.decode_16bit_int() elif myreg[1] == 'U16': interpreted = message.decode_16bit_uint() else: ## if no data type is defined do raw interpretation of the delivered data interpreted = message.decode_16bit_uint() ## check for "None" data before doing anything else if ((interpreted == MIN_SIGNED) or (interpreted == MAX_UNSIGNED)): value = None else: ## put the data with correct formatting into the data table if myreg[2] == 'FIX3': value = float(interpreted) / 1000 elif myreg[2] == 'FIX2': value = float(interpreted) / 100 elif myreg[2] == 'FIX1': value = float(interpreted) / 10 elif myreg[2] == 'UTF8': value = str(interpreted,'UTF-8').rstrip("\x00") elif myreg[2] == 'ENUM': e=pvenums.get(name,{}) value = e.get(interpreted,str(interpreted)) else: value = interpreted data[name] = value client.close() return data
def _refresh(self): readCacheDictionary = {} for item in self._itemReadDictionary: pluggit_key = self._itemReadDictionary[item] pluggit_paramList = self._modbusRegisterDictionary[pluggit_key] # read values from pluggit via modbus client registers, if not in cache if pluggit_paramList[self.DICT_READ_ADDRESS] != -1: if pluggit_key in readCacheDictionary: registerValue = readCacheDictionary[pluggit_key] else: registerValue = self._Pluggit.read_holding_registers( pluggit_paramList[self.DICT_READ_ADDRESS], pluggit_paramList[self.DICT_ADDRESS_QUANTITY]) # TODO: auswerten, wenn Reigister nicht auslesbar readCacheDictionary[pluggit_key] = registerValue vdecoder = BinaryPayloadDecoder.fromRegisters( registerValue.registers, byteorder=Endian.Big, wordorder=Endian.Little) readItemValue = None if pluggit_paramList[self.DICT_VALUE_TYPE] == 'uint': if pluggit_paramList[ self. DICT_ADDRESS_QUANTITY] == 1 or pluggit_paramList[ self.DICT_ADDRESS_QUANTITY] == 2: readItemValue = vdecoder.decode_16bit_uint() if pluggit_paramList[self.DICT_ADDRESS_QUANTITY] == 4: readItemValue = vdecoder.decode_64bit_uint() if pluggit_paramList[self.DICT_VALUE_TYPE] == 'float': if pluggit_paramList[self.DICT_ADDRESS_QUANTITY] == 2: readItemValue = vdecoder.decode_32bit_float() if pluggit_paramList[self.DICT_ROUND_VALUE] != -1: readItemValue = round( readItemValue, pluggit_paramList[self.DICT_ROUND_VALUE]) if pluggit_paramList[self.DICT_VALUE_TYPE] == 'bool': if pluggit_paramList[self.DICT_ADDRESS_QUANTITY] == 1: readItemValue = bool(vdecoder.decode_16bit_uint()) if pluggit_paramList[self.DICT_VALUE_TYPE] == 'timestamp': if pluggit_paramList[self.DICT_ADDRESS_QUANTITY] == 2: readItemValue = vdecoder.decode_32bit_uint() if pluggit_paramList[self.DICT_VALUE_TYPE] == 'str': readItemValue = self.BinWordToString( registerValue.registers) if pluggit_paramList[self.DICT_VALUE_TYPE] == 'ip': readItemValue = '{}.{}.{}.{}'.format( registerValue.registers[1] >> 8, registerValue.registers[1] & 0xFF, registerValue.registers[0] >> 8, registerValue.registers[0] & 0xFF) if pluggit_paramList[self.DICT_VALUE_TYPE] == 'mac': readItemValue = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format( registerValue.registers[0] >> 8, registerValue.registers[0] & 0xFF, registerValue.registers[3] >> 8, registerValue.registers[3] & 0xFF, registerValue.registers[2] >> 8, registerValue.registers[2] & 0xFF) if pluggit_paramList[self.DICT_VALUE_TYPE] == 'version': vresult = vdecoder.decode_16bit_uint() readItemValue = '{}.{}'.format(vresult >> 8 & 0xFF, vresult & 0xFF) if pluggit_paramList[self.DICT_VALUE_TYPE] == 'version_bcd': vresult = vdecoder.decode_16bit_uint() readItemValue = '{}.{}{}'.format(vresult >> 12 & 0x0F, vresult >> 8 & 0x0F, vresult >> 4 & 0x0F, vresult & 0x0F) if pluggit_paramList[self.DICT_VALUE_TYPE] == 'weekprogram': # 6 Register, 1 h = 4 Bit, 2 h = 8 bit, 4 h = 16 bit = 1 Register #readItemValue = registerValue.registers #readItemValue = str(registerValue.registers[0] & 0x0F) #self.logger.info('{}'.format(readItemValue)) pass # check for conversion convItemValue = None if readItemValue is not None: if self.has_iattr(item.conf, 'pluggit_convert'): convType = self.get_iattr_value( item.conf, 'pluggit_convert') if convType in pluggit_paramList[ self.DICT_ALLOWED_CONV_LIST]: convItemValue = self.ConvertValueToItem( readItemValue, convType, pluggit_key) if convItemValue is not None: item(convItemValue, 'Pluggit') else: self.logger.warning( "Fehler bei der Umwandlung von Item {}.". format(item)) else: self.logger.warn( "Umwandlung von {} zu {} bei Item {} nicht zulässig." .format( pluggit_paramList[self.DICT_VALUE_TYPE], convType, item)) else: if readItemValue is not None: item(readItemValue, 'Pluggit') else: self.logger.warning( "Unbekannter Wert-Typ: {} bei Item {}.".format( pluggit_paramList[self.DICT_VALUE_TYPE]), item) time.sleep(0.1)
def decode_data_format(self, chl, res): value = None byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_UINT16: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_SINT16: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_UINT32: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_UINT32_RWORDS: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_SINT32: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_SINT32_RWORDS: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_SKIP2: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_FLOAT: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_FLOAT_SKIP2: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_FLOAT_RBYTES: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_FLOAT_RWORDS: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_FLOAT_RSKIP2: byteorder = Endian.Big wordorder = Endian.Little if chl.format == MODBUS_ABB_REAL32_U or chl.format == MODBUS_ABB_REAL32_S: byteorder = Endian.Big wordorder = Endian.Big decoder = BinaryPayloadDecoder.fromRegisters(res.response.registers, byteorder=byteorder, wordorder=wordorder) if chl.format == MODBUS_UINT16: value = decoder.decode_16bit_uint() if chl.format == MODBUS_SINT16: value = decoder.decode_16bit_int() if chl.format == MODBUS_SINT32: value = decoder.decode_32bit_int() if chl.format == MODBUS_UINT32: value = decoder.decode_32bit_uint() if chl.format == MODBUS_SINT32_RWORDS: value = decoder.decode_32bit_int() if chl.format == MODBUS_SKIP2: pass if chl.format == MODBUS_UINT32_RWORDS: pass if chl.format == MODBUS_FLOAT: value = decoder.decode_32bit_float() if chl.format == MODBUS_FLOAT_SKIP2: pass if chl.format == MODBUS_FLOAT_RBYTES: pass if chl.format == MODBUS_FLOAT_RWORDS: pass if chl.format == MODBUS_FLOAT_RSKIP2: pass if chl.format == MODBUS_ABB_REAL32_U: value = decoder.decode_16bit_uint() # print("Reg 1 : %d" % res.response.registers[0]) # print("Reg 2 : %d" % res.response.registers[1]) if chl.format == MODBUS_ABB_REAL32_S: value = int( format(res.response.registers[1], "b").zfill(16) + format(res.response.registers[0], "b").zfill(16), 2) # decoder.decode_bits() return value
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 from_registers(self, r): return BinaryPayloadDecoder.fromRegisters(r.registers, byteorder=self.byte_order, wordorder=self.word_order)
def testBigEndianPayloadDecoder(self): """ Test basic bit message encoding/decoding """ decoder = BinaryPayloadDecoder(self.big_endian_payload, byteorder=Endian.Big) self.assertEqual(1, decoder.decode_8bit_uint()) self.assertEqual(2, decoder.decode_16bit_uint()) self.assertEqual(3, decoder.decode_32bit_uint()) self.assertEqual(4, decoder.decode_64bit_uint()) self.assertEqual(-1, decoder.decode_8bit_int()) self.assertEqual(-2, decoder.decode_16bit_int()) self.assertEqual(-3, decoder.decode_32bit_int()) self.assertEqual(-4, decoder.decode_64bit_int()) self.assertEqual(1.25, decoder.decode_32bit_float()) self.assertEqual(6.25, decoder.decode_64bit_float()) self.assertEqual(None, decoder.skip_bytes(2)) self.assertEqual(b'test', decoder.decode_string(4)) self.assertEqual(self.bitstring, decoder.decode_bits())
def load_sma_register(registers): from pymodbus.payload import BinaryPayloadDecoder from pymodbus.constants import Endian import datetime ## request each register from datasets, omit first row which contains only column headers for thisrow in registers: name = thisrow[0] startPos = thisrow[1] type = thisrow[2] format = thisrow[3] ## if the connection is somehow not possible (e.g. target not responding) # show a error message instead of excepting and stopping try: received = client.read_input_registers(address=startPos, count=sma_moddatatype[type], unit=config.slave) except: thisdate = str(datetime.datetime.now()).partition('.')[0] thiserrormessage = thisdate + ': Connection not possible. Check settings or connection.' print( thiserrormessage) return ## prevent further execution of this function message = BinaryPayloadDecoder.fromRegisters(received.registers, endian=Endian.Big) ## provide the correct result depending on the defined datatype if type == 'S32': interpreted = message.decode_32bit_int() elif type == 'U32': interpreted = message.decode_32bit_uint() elif type == 'U64': interpreted = message.decode_64bit_uint() elif type == 'STR16': interpreted = message.decode_string(16) elif type == 'STR32': interpreted = message.decode_string(32) elif type == 'S16': interpreted = message.decode_16bit_int() elif type == 'U16': interpreted = message.decode_16bit_uint() else: ## if no data type is defined do raw interpretation of the delivered data interpreted = message.decode_16bit_uint() ## check for "None" data before doing anything else if ((interpreted == MIN_SIGNED) or (interpreted == MAX_UNSIGNED)): displaydata = None else: ## put the data with correct formatting into the data table if format == 'FIX3': displaydata = float(interpreted) / 1000 elif format == 'FIX2': displaydata = float(interpreted) / 100 elif format == 'FIX1': displaydata = float(interpreted) / 10 else: displaydata = interpreted #print '************** %s = %s' % (name, str(displaydata)) inverter[name] = displaydata # Add timestamp inverter["00000 - Timestamp"] = str(datetime.datetime.now()).partition('.')[0]
# implementations differentiate holding/input discrete/coils and as such # you will not be able to write to these, therefore the starting values # are not known to these tests. Furthermore, some use the same memory # blocks for the two sets, so a change to one is a change to the other. # Keep both of these cases in mind when testing as the following will # _only_ pass with the supplied async modbus server (script supplied). #---------------------------------------------------------------------------# #rr = client.read_holding_registers(1,1) # #rr = client.read_holding_registers(address=0xF900, count=1) #decoder = BcdPayloadDecoder.fromRegisters(rr.registers) #Time_Interval = decoder.decode_int(2) #Time_Interval = rs485.read_string(0xF900, functioncode=3, numberOfRegisters=2)[0] # rr = client.read_input_registers(address=0x0000, count=2) decoder = BinaryPayloadDecoder.fromRegisters(rr.registers, endian=Endian.Big) Volts = decoder.decode_32bit_float() # rr = client.read_input_registers(address=0x0006, count=2) decoder = BinaryPayloadDecoder.fromRegisters(rr.registers, endian=Endian.Big) Current = decoder.decode_32bit_float() # rr = client.read_input_registers(address=0x000C, count=2) decoder = BinaryPayloadDecoder.fromRegisters(rr.registers, endian=Endian.Big) Active_Power = decoder.decode_32bit_float() # rr = client.read_input_registers(address=0x0012, count=2) decoder = BinaryPayloadDecoder.fromRegisters(rr.registers, endian=Endian.Big) Apparent_Power = decoder.decode_32bit_float() # rr = client.read_input_registers(address=0x0018, count=2)
def read(self): """ Read registers from client""" if pymodbus_found: time.sleep(float(self._settings["interval"])) f = [] c = Cargo.new_cargo(rawdata="") # valid datacodes list and number of registers associated # in modbus protocol, one register is 16 bits or 2 bytes valid_datacodes = ({ 'h': 1, 'H': 1, 'i': 2, 'l': 2, 'I': 2, 'L': 2, 'f': 2, 'q': 4, 'Q': 4, 'd': 4 }) if not self._modcon: self._con.close() self._log.info("Not connected, retrying connect" + str(self.init_settings)) self._con = self._open_modTCP( self.init_settings["modbus_IP"], self.init_settings["modbus_port"]) if self._modcon: # fetch nodeid if 'nodeId' in self._settings: node = str(self._settings["nodeId"]) else: self._log.error("please provide a nodeId") return # stores registers if 'register' in self._settings: registers = self._settings["register"] else: self._log.error( "please provide a register number or a list of registers" ) return # fetch unitids if present UnitIds = self._settings.get("nUnit", None) # stores names # fetch datacode or datacodes if node in ehc.nodelist and 'rx' in ehc.nodelist[node]: rNames = ehc.nodelist[node]['rx']['names'] if 'datacode' in ehc.nodelist[node]['rx']: datacode = ehc.nodelist[node]['rx']['datacode'] datacodes = None elif 'datacodes' in ehc.nodelist[node]['rx']: datacodes = ehc.nodelist[node]['rx']['datacodes'] else: self._log.error( "please provide a datacode or a list of datacodes") return # check if number of registers and number of names are the same if len(rNames) != len(registers): self._log.error( "You have to define an equal number of registers and of names" ) return # check if number of names and number of datacodes are the same if datacodes is not None: if len(datacodes) != len(rNames): self._log.error( "You are using datacodes. You have to define an equal number of datacodes and of names" ) return # calculate expected size in bytes and search for invalid datacode(s) expectedSize = 0 if datacodes is not None: for code in datacodes: if code not in valid_datacodes: self._log.debug("-" * 46) self._log.debug("invalid datacode") self._log.debug("-" * 46) return else: expectedSize += valid_datacodes[code] * 2 else: if datacode not in valid_datacodes: self._log.debug("-" * 46) self._log.debug("invalid datacode") self._log.debug("-" * 46) return else: expectedSize = len( rNames) * valid_datacodes[datacode] * 2 self._log.debug("expected bytes number after encoding: " + str(expectedSize)) # at this stage, we don't have any invalid datacode(s) # so we can loop and read registers for idx, rName in enumerate(rNames): register = int(registers[idx]) if UnitIds is not None: unitId = int(UnitIds[idx]) else: unitId = 1 if datacodes is not None: datacode = datacodes[idx] self._log.debug("datacode " + datacode) qty = valid_datacodes[datacode] self._log.debug("reading register # :" + str(register) + ", qty #: " + str(qty) + ", unit #: " + str(unitId)) try: self.rVal = self._con.read_holding_registers( register - 1, qty, unit=unitId) assert self.rVal.function_code < 0x80 except Exception as e: self._log.error( "Connection failed on read of register: " + str(register) + " : " + str(e)) self._modcon = False #missing datas will lead to an incorrect encoding #we have to drop the payload return else: #self._log.debug("register value:" + str(self.rVal.registers) + " type= " + str(type(self.rVal.registers))) #f = f + self.rVal.registers decoder = BinaryPayloadDecoder.fromRegisters( self.rVal.registers, byteorder=Endian.Big, wordorder=Endian.Big) if datacode == 'h': rValD = decoder.decode_16bit_int() elif datacode == 'H': rValD = decoder.decode_16bit_uint() elif datacode == 'i': rValD = decoder.decode_32bit_int() elif datacode == 'l': rValD = decoder.decode_32bit_int() elif datacode == 'I': rValD = decoder.decode_32bit_uint() elif datacode == 'L': rValD = decoder.decode_32bit_uint() elif datacode == 'f': rValD = decoder.decode_32bit_float() * 10 elif datacode == 'q': rValD = decoder.decode_64bit_int() elif datacode == 'Q': rValD = decoder.decode_64bit_uint() elif datacode == 'd': rValD = decoder.decode_64bit_float() * 10 t = ehc.encode(datacode, rValD) f = f + list(t) self._log.debug("Encoded value: " + str(t)) self._log.debug("value: " + str(rValD)) #test if payload length is OK if len(f) == expectedSize: self._log.debug("payload size OK (" + str(len(f)) + ")") self._log.debug("reporting data: " + str(f)) c.nodeid = node c.realdata = f self._log.debug("Return from read data: " + str(c.realdata)) return c else: self._log.error("incorrect payload size :" + str(len(f)) + " expecting " + str(expectedSize))
# 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 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # ---------------------------------------------------------------------------# address = 0x01 count = 8 result = client.read_input_registers(address, count) decoder = BinaryPayloadDecoder.fromRegisters(result.registers, endian=Endian.Little) decoded = { "string": decoder.decode_string(8), "float": decoder.decode_32bit_float(), "16uint": decoder.decode_16bit_uint(), "8int": decoder.decode_8bit_int(), "bits": decoder.decode_bits(), } print "-" * 60 print "Decoded Data" print "-" * 60 for name, value in decoded.iteritems(): print ("%s\t" % name), value # ---------------------------------------------------------------------------#
IbatT = 5 * IbatT - 11.86 else: Ibat = 0 PBtotal = round((IbatT * VbatT) / (j), 2) - 13 #print(IbatT/j) if PLtotal < 2: PLtotal = 0 elif PStotal < 2: PStotal = 0 result = client.read_holding_registers(11729, 2, unit=1) #Current A 1100 decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big) PTred = decoder.decode_32bit_float() sw = 1 hoja.write(k, 0, str(A)) hoja.write(k, 1, str(VpanelT / j)) hoja.write(k, 2, str(IpanelT / j)) hoja.write(k, 3, str(PTred)) hoja.write(k, 4, str(PLtotal)) hoja.write(k, 5, str(PBtotal)) hoja.write(k, 6, time.strftime("%X"))