def test_send_message_with_timeout(): """ Test if TimoutError is raised when serial port doesn't receive enough data. """ s = serial_for_url('loop://', timeout=0) # As we are using a loop, the sent request will be read back as response. # To test timeout use a request that needs more bytes for the response. message = read_coils(slave_id=0, starting_address=1, quantity=40) with pytest.raises(ValueError): send_message(message, s)
def do_sendregs(devnum, parmlist): # parms = <regnum as int> <stringdata as string> try: regnum = int(parmlist[0]) except: print("<register> can only be a number") return dataString = parmlist[1] # Send the command message = rtu.write_multiple_registers(slave_id=devnum, starting_address=regnum, values=string2list(parmlist)) try: response = rtu.send_message(message, serial_port) except Timeout: print("Timeout error, ignoring", file=sys.stderr) if ignore_timeouts: return sys.exit(1) except: e = sys.exc_info()[0] print("Some other exception: %" % repr(e)) sys.exit(3) # print("Got a response back!"); # import pdb; pdb.set_trace() return
def read_discrete_inputs(self, start_discrete_address, number_of_inputs): """ Modbus command : Read discrete input(s) (function code = 02) @Argument : start_discrete_address (int16) : Start discrete input address where to read a input data number_of_inputs (int) : number of discrete input(s) to read @Return : response : Discrete input(s) data """ response = None # Generate modbus RTU message try: message = modbus_rtu.read_discrete_inputs( slave_id=self.device_id, starting_address=start_discrete_address, quantity=number_of_inputs) except Exception as e: print("Error during generate modbus message.") # Send message via serial port try: if self.serialport.is_open: response = modbus_rtu.send_message(message, self.serialport) print("response={}".format(response)) else: print("Error : Cannot send data. Serial port is closed.") except Exception as e: print("Error during send modbus message.") print(e) return response
def read_coils(self, start_coil_address, number_of_coils): """ Modbus command : Read coil data(s) (function code = 01) @Argument : start_coil_address (int16) : Start coil address where to read a coil data number_of_coil (int) : number of coil(s) to read @Return : response : Coil data (Byte) The coils in the response message are packed as one coil per bit of the data field. Status is indicated as 1= ON and 0= OFF. """ response = None # Generate modbus RTU message try: message = modbus_rtu.read_coils( slave_id=self.device_id, starting_address=start_coil_address, quantity=number_of_coils) except Exception as e: print("Error during generate modbus message.") # Send message via serial port try: if self.serialport.is_open: response = modbus_rtu.send_message(message, self.serialport) print("response={}".format(response)) else: print("Error : Cannot send data. Serial port is closed.") except Exception as e: print("Error during send modbus message.") print(e) return response
def write_coils(self, coil_start_address, write_values): """ Modbus command : write multiple coils data (function code = 15) @Argument : coil_start_address (int16) : Coil start address where to write a set of coils data write_values (int) : write value(s) """ # Generate modbus RTU message try: message = modbus_rtu.write_multiple_coils( slave_id=self.device_id, starting_address=coil_start_address, values=write_values) except Exception as e: print("Error during generate modbus message.") # Send message via serial port try: if self.serialport.is_open: response = modbus_rtu.send_message(message, self.serialport) print("response={}".format(response)) else: print("Error : Cannot send data. Serial port is closed.") except Exception as e: print("Error during send modbus message.") print(e)
def main(): # import pdb; pdb.set_trace() # import pdb; pdb.set_trace() # tempval = string2list("ABCDEFGHIJ"); # Even Number tempval = string2list("ABCDEFGHI") # Odd Number serial_port = get_serial_port() # Returns a message or Application Data Unit (ADU) specific for doing # Modbus RTU. # message = rtu.write_multiple_coils(slave_id=1, starting_address=1, values=[1, 0, 1, 1]) message = rtu.write_multiple_registers(slave_id=1, starting_address=1, values=string2list("ABCDEFG")) # Response depends on Modbus function code. In this case, it's the number # of registers written. try: response = rtu.send_message(message, serial_port) except Timeout: print("Timeout error") sys.exit(1) except: e = sys.exc_info()[0] print("Some other exception: %" % repr(e)) sys.exit(3) serial_port.close()
def read_input_registers(self, slave_id, address, quantity): """ Get raw data from input registers. Parameters ---------- slave_id Slave identifier number (targeted device) address Register starting address quantity Quantity of registers to read Returns ------- bytes Raw data from targeted registers """ message = rtu.read_input_registers(slave_id=slave_id, starting_address=address, quantity=quantity) logger.debug("-> Transmit ADU : 0x%s", str(bytes(message).hex())) try: response = rtu.send_message(message, self.serial_port) except (ValueError, KeyError) as e: logger.error( "--> Please match your configurations and the values set with the dip-switches on the device: ", e) except ModbusError as e: logger.error("--> Modbus error : ", e) else: hex_response = ' '.join(hex(x) for x in response) logger.debug("<- Receive data : %s", str(hex_response)) return response
def write_coil_register(self, slave_id, address, port, value): self.serial_port = self.get_serial_port(port) add = int(address) - 1 message = rtu.write_single_coil(slave_id=int(slave_id), address=add, value=int(value)) response = rtu.send_message(message, self.serial_port) print(response) self.serial_port.close()
def get_thermi( self, th=0): # to get the thermistor value, returns the thermistor value self.thermi = th try: serial_port = self.get_serial_port() if self.thermi == 0: # get the value of all the thermistors message = rtu.read_input_registers(SLAVE_ID, THERMI1_REG, 4) elif self.thermi == 1: # get the thermistor 1 value message = rtu.read_input_registers(SLAVE_ID, THERMI1_REG, 1) elif self.thermi == 2: # get the thermistor 2 value message = rtu.read_input_registers(SLAVE_ID, THERMI2_REG, 1) elif self.thermi == 3: # get the thermistor 3 value message = rtu.read_input_registers(SLAVE_ID, THERMI3_REG, 1) elif self.thermi == 4: # get the thermistor 4 value message = rtu.read_input_registers(SLAVE_ID, THERMI4_REG, 1) else: print("ERROR: no thermistor was found at this value") response = rtu.send_message(message, serial_port) self.close_serial_port() except: traceback.print_exc() return response
def get_tariff(): message = rtu.read_holding_registers(slave_id=1, starting_address=0x6048, quantity=1) response = rtu.send_message(message, serial_port) tariff = [-1, 1, 0] print(response) return {"tariff_val": tariff[response[0]]}
def read_input_registers(self, slave_id, address, quantity, port): self.serial_port = self.get_serial_port(port) add = int(address) - 1 message = rtu.read_input_registers(slave_id=int(slave_id), starting_address=add, quantity=int(quantity)) hexadecimal_string = message.hex() print(hexadecimal_string) response = rtu.send_message(message, self.serial_port) print("response", response) result = [] # return response count = 0 for offset in range(int(address), int(address) + int(quantity)): print("offset", offset) # for i in response: if offset == 100: res = response[count] / 10 print("Factory value", res) elif offset == 101: res = response[count] / 10 print("Factory value", res) elif offset == 102: res = response[count] / 10 print("Factory value", res) # print("count",count) elif offset == 103: res = response[count] / 10 print("Factory value", res) # print("count",count) elif offset == 10: res = response[count] / 10 print("Factory value", res) # print("count",count) elif offset == 124: res = response[count] / 10 print("Factory value", res) elif offset == 131: res = response[count] / 10 print("Factory value", res) elif offset == 183: res = response[count] / 10 print("Factory value", res) else: res = response[count] print(res) count = count + 1 result.append(res) return result, hexadecimal_string self.serial_port.close()
def read_input(self, reg): # read a single input register at reg address try: serial_port = self.get_serial_port() message = rtu.read_input_registers(SLAVE_ID, reg, 1) response = rtu.send_message(message, serial_port) self.release_serial_port() return response[0] except: traceback.print_exc() self.close_serial_port() return None
def get_battery_percentage(self): """ Return the current charge percentage of the batteries.""" ret_status = True message = rtu.read_holding_registers(slave_id=self.slave_id, starting_address=self.BATTPCT, quantity=1) try: response = rtu.send_message(message, self.serial_port) except: ret_status = False response = [-1] return ret_status, response[0]
def set_auto(self): """ Switch inverter to AUTO.""" ret_status = True message = write_passive_register(slave_id=self.slave_id, address=self.AUTO, value=0) try: response = rtu.send_message(message, self.serial_port) except: ret_status = False response = 0 return ret_status, response
def set_standby(self): """ Switch inverter to STANDBY.""" ret_status = True message = write_passive_register(slave_id=self.slave_id, address=self.STANDBY, value=self.STANDBY_VAL) try: response = rtu.send_message(message, self.serial_port) except: ret_status = False response = 0 return ret_status, response
def read_holding(self): """ Read all the holding registers from inverter.""" ret_status = True message = rtu.read_holding_registers(slave_id=self.slave_id, starting_address=self.ME_HOLDING, quantity=self.NUM_HOLDING) try: response = rtu.send_message(message, self.serial_port) except: ret_status = False response = 0 return ret_status, response
def write_holding(self, reg, val): # write val in the holding register at reg address try: serial_port = self.get_serial_port() message = rtu.write_single_register(SLAVE_ID, reg, val) response = rtu.send_message(message, serial_port) self.release_serial_port() return response except: traceback.print_exc() self.close_serial_port() return None
def get_inverter_state(self): """ Return the inverter state.""" ret_status = True message = rtu.read_holding_registers(slave_id=self.slave_id, starting_address=self.ME_STATE, quantity=1) try: response = rtu.send_message(message, self.serial_port) except: ret_status = False response = [-1] return ret_status, response[0], self.INV_STATES[response[0]]
def set_discharge(self, discharge=3000): """ Set discharge value.""" ret_status = True message = write_passive_register(slave_id=self.slave_id, address=self.DISCHARGE, value=discharge) try: response = rtu.send_message(message, self.serial_port) except: ret_status = False response = 0 return ret_status, response
def read_input(self): """ Read the inverter's input registers.""" ret_status = True message = rtu.read_input_registers(slave_id=self.slave_id, starting_address=self.ME_INPUT, quantity=self.NUM_INPUT) try: response = rtu.send_message(message, self.serial_port) except: ret_status = False response = 0 return ret_status, response
def read_deye_register(self, start_address, number_addresses): """ read specific register from inverter.""" ret_status = True message = rtu.read_holding_registers(slave_id=self.slave_id, starting_address=start_address, quantity=number_addresses) try: response = rtu.send_message(message, self.serial_port) except: ret_status = False response = 0 return ret_status, response
def get_pump_servo( self): # to get the pump speed returned by the servo of the pump response = None try: serial_port = self.get_serial_port() message = rtu.read_input_registers(SLAVE_ID, PUMP_SERVO_PERIODMAX_REG, 3) response = rtu.send_message(message, serial_port) message = rtu.read_holding_registers(SLAVE_ID, PUMP_SERVO_PULSES_REG, 1) response2 = rtu.send_message(message, serial_port) response.append(response2[0]) # Auto re-init every second... #message = rtu.write_single_register(SLAVE_ID, PUMP_SERVO_PULSES_REG , 0) #response3 = rtu.send_message(message, serial_port) self.close_serial_port() except: traceback.print_exc() return response
def write_holding_register(self, slave_id, address, port, value): self.serial_port = self.get_serial_port(port) add = int(address) - 1 if int(value) < 0: value1 = int(value) + 2 ** 16 else: value1 = int(value) print(value1) message = rtu.write_single_register(slave_id=int(slave_id), address=add, value=int(value1)) print(message) hexadecimal_string = message.hex() print(hexadecimal_string) response = rtu.send_message(message, self.serial_port) print(response) print(type(response)) self.serial_port.close()
def get_data(start=0x4000, length=0x02): message = rtu.read_holding_registers(slave_id=1, starting_address=start, quantity=length) response = rtu.send_message(message, serial_port) count = 0 data = {} while count < len(response): h = format(response[count + 0], '04X') l = format(response[count + 1], '04X') d = h + l val = struct.unpack('!f', bytes.fromhex(d))[0] key = str(format(start + count, '04X')) data[key] = val count += 2 return data
def do_sendreg(devnum, parmlist): # parms = <regnum> <single_word> in dec or hex (if "0x" prepended) baseConv = 10 # print("-- do_sendreg: DEV({}), WORD({})".format(devnum, repr(parmlist))) try: regnum = int(parmlist[0]) except: print("<register> can only be a number") return singleWord_s = parmlist[1] if singleWord_s.startswith("0x"): baseConv = 16 singleWord_s = singleWord_s[2:] try: singleWord = int(singleWord_s, baseConv) except ValueError: print("<singleWord> can only be a dec or hex (0x) number") return # Send the command # def write_single_register(slave_id, address, value): message = rtu.write_single_register(slave_id=devnum, address=regnum, value=singleWord) try: response = rtu.send_message(message, serial_port) except TimeoutError: print("Timeout error, ignoring", file=sys.stderr) if ignore_timeouts: return sys.exit(1) except: e = sys.exc_info()[0] print("Some other exception: %" % repr(e)) sys.exit(3) print("Got a response back!") import pdb pdb.set_trace()
def read_input_registers(self, start_register_address, number_of_registers): """ Modbus command : Read data to input registers (function code = 04) @Argument : start_register_address (int16) : Start address where to read a data number_of_registers (int) : number of register(s) in register-line where to read a data @Return : response : Read data(s). Return as list of read data (sequently) if number_of_register > 1 """ response = None # Enable byte system of modbus to be signed-value type if self.signed_type == True: conf.SIGNED_VALUES = True else: conf.SIGNED_VALUES = False # Generate modbus RTU message try: message = modbus_rtu.read_input_registers( slave_id=self.device_id, starting_address=start_register_address, quantity=number_of_registers) except Exception as e: print("Error during generate modbus message.") # Send message via serial port try: if self.serialport.is_open: response = modbus_rtu.send_message(message, self.serialport) print("response={}".format(response)) else: print("Error : Cannot send data. Serial port is closed.") except Exception as e: print("Error during send modbus message.") print(e) return response
def send(self, message: bytes, timeout: float, retries: int = 1) -> Optional[List[int]]: with self.lock: for i in range(retries): self.__wait() try: self.set_timeout(timeout) response = modbus.send_message(adu=message, serial_port=self._serial) return response except (KeyError, ValueError) as e: return None finally: self.__last = datetime.now()
def write_registers(self, start_register_address, write_values): """ Modbus command : Write data to multiple registers (function code = 16) Argument : start_register_address (int16) : Start address where to write a data write_values (int16) : Write data(s) """ # Enable byte system to be signed-value type if self.signed_type == True: conf.SIGNED_VALUES = True else: conf.SIGNED_VALUES = False # Generate modbus RTU message try: message = modbus_rtu.write_multiple_registers( slave_id=self.device_id, starting_address=start_register_address, values=write_values) except Exception as e: print("Error during generate modbus message.") print( "\tMaybe, write value is less than 0 as signed integer and .signed_type is set to 'False'." ) # Send message via serial port try: if self.serialport.is_open: response = modbus_rtu.send_message(message, self.serialport) print("response={}".format(response)) else: print("Error : Cannot send data. Serial port is closed.") except Exception as e: print("Error during send modbus message.") print(e)
import struct from serial import Serial, PARITY_NONE from umodbus.client.serial import rtu def get_serial_port(): """ Return serial.Serial instance, ready to use for RS485.""" port = Serial(port='/dev/ttyS1', baudrate=9600, parity=PARITY_NONE, stopbits=1, bytesize=8, timeout=1) fh = port.fileno() # A struct with configuration for serial port. serial_rs485 = struct.pack('hhhhhhhh', 1, 0, 0, 0, 0, 0, 0, 0) fcntl.ioctl(fh, 0x542F, serial_rs485) return port serial_port = get_serial_port() # Returns a message or Application Data Unit (ADU) specific for doing # Modbus RTU. message = rtu.write_multiple_coils(slave_id=1, address=1, values=[1, 0, 1, 1]) # Response depends on Modbus function code. This particular returns the # amount of coils written, in this case it is. response = rtu.send_message(message, serial_port) serial_port.close()
def get_frequency(self): message = rtu.read_holding_registers(DEVICE_ADDRESS, REG_OUTPUT_FREQ, 1) (response, ) = rtu.send_message(message, self.serial) return response * 0.01 # Hz
def stop(self): message = rtu.write_single_register(DEVICE_ADDRESS, REG_STATUS_CONTROL, 0b1) response = rtu.send_message(message, self.serial) return response