def testBasicSyncSerialClient(self, mock_serial): ''' Test the basic methods for the serial sync client''' # receive/send mock_serial.in_waiting = 0 mock_serial.write = lambda x: len(x) mock_serial.read = lambda size: b'\x00' * size client = ModbusSerialClient() client.socket = mock_serial client.state = 0 self.assertEqual(0, client._send(None)) client.state = 0 self.assertEqual(1, client._send(b'\x00')) self.assertEqual(b'\x00', client._recv(1)) # connect/disconnect self.assertTrue(client.connect()) client.close() # already closed socket client.socket = False client.close() self.assertEqual('ModbusSerialClient(ascii baud[19200])', str(client))
def get_data(): # choose the serial client client = ModbusClient(method='rtu', port=args.tty, baudrate=9600, timeout=args.timeout) client.connect() log.debug(client) # read the registers # for information about modbus registers see doc TSMPPT.APP.Modbus.EN.10.2.pdf rr = client.read_holding_registers(0,count=60,unit=1) if rr == None: client.close() log.error("couldn't connect") exit(1) # scaling v_scale = rr.registers[0] + rr.registers[1]/(2**16) i_scale = rr.registers[2] + rr.registers[3]/(2**16) # the stuff we want (the numbers are decimal but the registers are listed in hex) data={} data["batt-voltage" ] = ( rr.registers[24] * float(v_scale )) / (2**15) # 0x18 data["array-voltage" ] = ( rr.registers[27] * float(v_scale )) / (2**15) # 0x1b data["batt-current" ] = ( rr.registers[28] * float(i_scale )) / (2**15) # 0x1c data["array-current" ] = ( rr.registers[29] * float(i_scale )) / (2**15) # 0x1d data["batt-temp" ] = rr.registers[37] # 0x25 data["power-out" ] = ( rr.registers[58] * float(v_scale)*float(i_scale)) / (2**17) # 0x3a data["power-in" ] = ( rr.registers[59] * float(v_scale)*float(i_scale)) / (2**17) # 0x3b # close the client client.close() # debug log.info("got data from mppt via modbus") log.debug(datetime.datetime.now()) for key in keys: log.debug("%-15s : %.2f" % (key, data[key])) return data
def main(host, port, mqtt_username, mqtt_password, instance, name, serial_port): modbus = ModbusClient(method='rtu', port=serial_port, baudrate=9600, timeout=1) if not modbus.connect(): logger.error("Cannot connect to modbus") return client = mqtt.Client() client.loop_start() client.connect(host, port, 60) if mqtt_username is not None: client.username_pw_set(mqtt_username, mqtt_password) try: while True: now = int(time()) r = modbus.read_holding_registers(0, 16, unit=1) bat_volt = r.registers[8] * 96.667 * 2**(-15) bat_curr = r.registers[11] * 316.67 * 2**(-15) bat_temp = r.registers[15] client.publish('{}/{}/power'.format(instance, name), "{} {:0.2f}".format(now, bat_volt * bat_curr), 0) client.publish('{}/{}/voltage'.format(instance, name), "{} {:0.2f}".format(now, bat_volt), 0) client.publish('{}/{}/current'.format(instance, name), "{} {:0.2f}".format(now, bat_curr), 0) client.publish('{}/{}/temperature'.format(instance, name), "{} {}".format(now, bat_temp), 0) sleep(5) except KeyboardInterrupt: pass client.disconnect() client.loop_stop() modbus.close()
def request(reg, num, modbus_id): distance = None logger.debug("Measuring distance...") try: modbus_client = ModbusClient(method="rtu", port=PORT, stopbits=1, bytesize=8, parity="N", baudrate=9600, timeout=0.1) if modbus_client.connect(): height_query = modbus_client.read_holding_registers(reg, count=num, unit=modbus_id) distance = BinaryPayloadDecoder.fromRegisters( height_query.registers, byteorder=Endian.Big, wordorder=Endian.Big) distance = distance.decode_32bit_float() modbus_client.close() else: logger.error(f'Could not connecto to {PORT} port') except Exception as ex: logger.error('Error trying to read rs485 sensor') return height_query.registers, distance
def readDcPZEM(chanPort, chanAddr): voltage = 0 amperage = 0 power = 0 energy = 0 highVoltAlarmStatus = 0 lowVoltAlarmStatus = 0 #Connect to the serial modbus server client = ModbusClient(method="rtu", port=chanPort, stopbits=1, bytesize=8, parity='N', baudrate=9600) if client.connect(): try: result = client.read_input_registers(0x0000, 8, unit=chanAddr) voltage = scaleFactor(result.registers[0:1], 100) amperage = scaleFactor(result.registers[1:2], 100) power = scaleFactor(result.registers[2:4], 10) energy = scaleFactor(result.registers[4:6], 1) highVoltAlarmStatus = int(result.registers[6]) lowVoltAlarmStatus = int(result.registers[7]) except Exception as e: print('Exception reading DC PZEM: ' + str(e)) finally: client.close() return voltage, amperage, power, energy, highVoltAlarmStatus, lowVoltAlarmStatus
def readAcPZEM(chanPort, chanAddr): voltage = 0 amperage = 0 power = 0 energy = 0 frequency = 0 powerFactor = 0 alarmStatus = 0 client = ModbusClient(method="rtu", port=chanPort, stopbits=1, bytesize=8, parity='N', baudrate=9600) if client.connect(): try: result = client.read_input_registers(0x0000, 10, unit=chanAddr) voltage = scaleFactor(result.registers[0:1], 10) amperage = scaleFactor(result.registers[1:3], 1000) power = scaleFactor(result.registers[3:5], 10) energy = scaleFactor(result.registers[5:7], 1) frequency = scaleFactor(result.registers[7:8], 10) powerFactor = scaleFactor(result.registers[8:9], 100) alarmStatus = int(result.registers[9]) except Exception as e: print('Exception reading AC PZEM: ' + str(e)) finally: client.close() return voltage, amperage, power, energy, frequency, powerFactor, alarmStatus
def main(): parser = argparse.ArgumentParser( description='Talk to a voegtlin red-y flow controller') parser.add_argument( 'port', help='The serial interface your Modbus device is connected to.') parser.add_argument('--unit', default=247, type=int, help='The slave address of the Modbus device') args = parser.parse_args() logging.basicConfig() log = logging.getLogger() #log.setLevel(logging.DEBUG) client = ModbusClient(method='rtu', port=args.port, stopbits=2, baudrate=9600) try: client.connect() redy = RedY(unit=args.unit, modbus_client=client) redy.read_all() finally: client.close()
def main(): client = ModbusClient(method='rtu', port='/dev/ttyAMA0', baudrate=38400, parity='N', bytesize=8, stopbits=2, timeout=1) # request modbus register values from device client.connect() start = timer() reg_values = {} for addr, size in SDM630_BLOCKS.items(): resp = client.read_input_registers(addr, size * 2, unit=1) block = resp.registers reg_values.update({ (addr + i): block[i] for i in range(0, len(block)) }) request_time = timer() - start client.close() # close the client # convert modbus register values to float start = timer() mod_values = {} for name, r in SDM630_REGISTER.items(): w0 = reg_values[r.address + 0] w1 = reg_values[r.address + 1] mod_values[name] = struct.unpack('>f', struct.pack('>HH', w0, w1))[0] conversion_time = timer() - start # print all values in order of their modbus address for (name, _) in sorted(SDM630_REGISTER.items(), key = lambda x: x[1].address): v = mod_values[name] u = SDM630_REGISTER[name].unit print("{:40}: {:10.2f} {}".format(name, v, "" if u is None else str(u))) print("request took %.3f seconds" % request_time)
def main(args): global PUMP_TIME global SENSOR_TIME try: PUMP_TIME = int(args[1]) SENSOR_TIME = int(args[2]) print('using custom args. pump time: %d sensor time: %d' % (PUMP_TIME, SENSOR_TIME)) except: PUMP_TIME = 3 SENSOR_TIME = 5 print('using default args. pump time: %d sensor time: %d' % (PUMP_TIME, SENSOR_TIME)) startMeasurement() # Connect to sensor and record data try: client = ModbusClient(method = "rtu", port="/dev/ttyS0",stopbits = 1, bytesize = 8, parity = 'N', baudrate= 9600) # Connect to the serial modbus server connection = client.connect() if connection: recordData(client) # Closes the underlying socket connection client.close() except Exception as error: print('CO2 measurement failed: ' + repr(error)) finally: endMeasurement()
def getLoadCurrent(): client = ModbusClient(method='rtu', port=PORT, baudrate=BAUDRATE) client.connect() result = client.read_input_registers(0x3100, 15, unit=1) data = float(result.registers[13] / 100.0) client.close() return data
def main(args): global PUMP_TIME global SENSOR_TIME try: PUMP_TIME = int(args[1]) SENSOR_TIME = int(args[2]) print('using custom args. pump time: %d sensor time: %d' % (PUMP_TIME, SENSOR_TIME)) except: PUMP_TIME = 3 SENSOR_TIME = 5 print('using default args. pump time: %d sensor time: %d' % (PUMP_TIME, SENSOR_TIME)) startMeasurement() # Connect to sensor and record data try: client = ModbusClient(method="rtu", port="/dev/ttyS0", stopbits=1, bytesize=8, parity='N', baudrate=9600) # Connect to the serial modbus server connection = client.connect() if connection: recordData(client) # Closes the underlying socket connection client.close() except Exception as error: print('CO2 measurement failed: ' + repr(error)) finally: endMeasurement()
def main(): if len(sys.argv) != 4: print( """Usage: ./orno_modbus.py serial_port device_address target_device_address Example: ./orno_modbus.py /dev/ttyUSB0 1 11 If you have only one device you can set the device_address to 0 to change its address. """) sys.exit(0) port = sys.argv[1] address = int(sys.argv[2]) target_address = int(sys.argv[3]) client = ModbusClient(method="rtu", port=port, baudrate=9600) client.connect() request = SendOrnoPassword('00000000', unit=address) client.execute(request) response = client.write_registers(15, [target_address], unit=address) if response: if address: print "Success. Changed address from %d to %d." % (address, target_address) else: print "Success. Changed address to %d." % (target_address) else: print "Address change failed" client.close()
def run_sync_client(): clearScreen() print("Enter 1 to take reading, 0 to quit") running = True while running == True: client = ModbusClient(method='rtu', port='/dev/ttyUSB0', timeout=1, baudrate=9600) client.connect() hr = client.read_holding_registers(7, 3, unit=SLAVE) value = input(":") if value == 0: running = False else: temperature = hr.registers[0] / 10.0 humidity = hr.registers[1] / 10.0 dewpoint = hr.registers[2] / 10.0 print("Temperature : " + str(temperature)) print("Humidity : " + str(humidity)) print("Dew Point : " + str(dewpoint)) # ----------------------------------------------------------------------- # # close the client # ----------------------------------------------------------------------- # client.close()
def run_sync_client(): iteration_counter = 0 success_counter = 0 fail_counter = 0 client = ModbusClient(method='rtu', port='/dev/ttyUSB0', timeout=1, baudrate=115200) client.connect() while (iteration_counter < 10000): time.sleep(2) try: log.debug("Write to a holding register and read back") rq = client.write_register(1, 10, unit=UNIT) rr = client.read_holding_registers(1, 1, unit=UNIT) assert (not rq.isError()) # test that we are not an error # assert(rr.registers[0] == 10) # test the expected value log.debug("Write to multiple holding registers and read back") rq = client.write_registers(1, [10] * 8, unit=UNIT) time.sleep(0.5) # 이것을 넣지 않으면 에러가 뿜뿜. --> 마찬가지... rr = client.read_holding_registers(1, 8, unit=UNIT) assert (not rq.isError()) # test that we are not an error # assert(rr.registers == [10]*8) # test the expected value # arguments = { # 'read_address': 1, # 'read_count': 8, # 'write_address': 1, # 'write_registers': [20]*8, # } # log.debug("Read write registeres simulataneously") # rq = client.readwrite_registers(unit=UNIT, **arguments) # rr = client.read_holding_registers(1, 8, unit=UNIT) # assert(not rq.isError()) # test that we are not an error # assert(rq.registers == [20]*8) # test the expected value # assert(rr.registers == [20]*8) # test the expected value except AssertionError: print('ASSERT ERROR') fail_counter += 1 except pymodbus.exceptions.ModbusIOException: print('REGISTER ERROR') fail_counter += 1 else: success_counter += 1 iteration_counter += 1 print('iteration # : ', iteration_counter, ' success : ', success_counter, ' fail : ', fail_counter, ' rate : ', float(success_counter / iteration_counter) * 100, '%') # ----------------------------------------------------------------------- # # close the client # ----------------------------------------------------------------------- # client.close()
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" ################################### # 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"]) 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"]) 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="+self.UnitIdForIp+", Register="+Parameters["Password"]+", Data type="+Parameters["Mode6"]) try: client = ModbusClient(host=UnitAddress, port=int(Parameters["Port"]), unit_id=self.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 try: #Domoticz.Log("Before update. Number of devices:"+str(len(Devices))) for i in reg: i.update(client,Domoticz) #Domoticz.Log("After update") except Exception as e: Domoticz.Log("Error calling update "+repr(e)) client.close()
def main(args): global PUMP_TIME global SENSOR_TIME co2Runtotal = [] tempRuntotal = [] rhRuntotal = [] try: PUMP_TIME = int(args[1]) SENSOR_TIME = int(args[2]) print('using custom args. pump time: %d sensor time: %d' % (PUMP_TIME, SENSOR_TIME)) except: PUMP_TIME = 600 SENSOR_TIME = 300 print('using default args. pump time: %d sensor time: %d' % (PUMP_TIME, SENSOR_TIME)) if not os.path.isfile(DATAFILE_PATH): file = open(DATAFILE, "w") file.write('"TIMESTAMP","CO2","TEMPERATURE","HUMIDITY"\n"UTC","PPM","DEG_C","RH"\n') file.close() startMeasurement() # Connect to sensor and record data try: client = ModbusClient(method = "rtu", port="/dev/ttyS0",stopbits = 1, bytesize = 8, parity = 'N', baudrate= 9600) # Connect to the serial modbus server connection = client.connect() if connection: for x in range(0, PUMP_TIME, 30): #take a measurement every 30 secs until the pump and sensor time is over outputList = (recordData(client)) #return the co2, temp and rh data after every call and append it to list variables co2Runtotal.append(outputList[0]) tempRuntotal.append(outputList[1]) rhRuntotal.append(outputList[2]) time.sleep(30) writeMean(co2Runtotal, tempRuntotal, rhRuntotal) endPump() co2Runtotal = [] tempRuntotal = [] rhRuntotal = [] for x in range(0, SENSOR_TIME, 30): outputList = (recordData(client)) co2Runtotal.append(outputList[0]) tempRuntotal.append(outputList[1]) rhRuntotal.append(outputList[2]) time.sleep(30) writeMean(co2Runtotal, tempRuntotal, rhRuntotal) # Closes the underlying socket connection client.close() except Exception as error: print('CO2 measurement failed: ' + repr(error)) finally: endMeasurement()
class communication: def __init__(self): self.client = None def connectToDevice(self, device): """Connection to the client - the method takes the IP address (as a string, e.g. '192.168.1.11') as an argument.""" self.client = ModbusSerialClient(method='rtu', port=device, stopbits=1, bytesize=8, baudrate=115200, timeout=0.2) if not self.client.connect(): print "Unable to connect to %s" % device return False #print "It connected" return True def disconnectFromDevice(self): """Close connection""" self.client.close() def sendCommand(self, data): """Send a command to the Gripper - the method takes a list of uint8 as an argument. The meaning of each variable depends on the Gripper model (see support.robotiq.com for more details)""" #make sure data has an even number of elements if (len(data) % 2 == 1): data.append(0) #Initiate message as an empty list message = [] #Fill message by combining two bytes in one register for i in range(0, len(data) / 2): message.append((data[2 * i] << 8) + data[2 * i + 1]) #To do!: Implement try/except self.client.write_registers(0x03E8, message, unit=0x0009) def getStatus(self, numBytes): """Sends a request to read, wait for the response and returns the Gripper status. The method gets the number of bytes to read as an argument""" numRegs = int(ceil(numBytes / 2.0)) #To do!: Implement try/except #Get status from the device response = self.client.read_holding_registers(0x07D0, numRegs, unit=0x0009) #Instantiate output as an empty list output = [] #Fill the output with the bytes in the appropriate order for i in range(0, numRegs): output.append((response.getRegister(i) & 0xFF00) >> 8) output.append(response.getRegister(i) & 0x00FF) #Output the result return output
def run_sync_client(): # ------------------------------------------------------------------------# # choose the client you want # ------------------------------------------------------------------------# # make sure to start an implementation to hit against. For this # you can use an existing device, the reference implementation in the tools # directory, or start a pymodbus server. # # If you use the UDP or TCP clients, you can override the framer being used # to use a custom implementation (say RTU over TCP). By default they use # the socket framer:: # # client = ModbusClient('localhost', port=5020, framer=ModbusRtuFramer) # # It should be noted that you can supply an ipv4 or an ipv6 host address # for both the UDP and TCP clients. # # There are also other options that can be set on the client that controls # how transactions are performed. The current ones are: # # * retries - Specify how many retries to allow per transaction (default=3) # * retry_on_empty - Is an empty response a retry (default = False) # * source_address - Specifies the TCP source address to bind to # * strict - Applicable only for Modbus RTU clients. # Adheres to modbus protocol for timing restrictions # (default = True). # Setting this to False would disable the inter char timeout # restriction (t1.5) for Modbus RTU # # # Here is an example of using these options:: # # client = ModbusClient('localhost', retries=3, retry_on_empty=True) # ------------------------------------------------------------------------# # client = ModbusClient('localhost', port=5020) # from pymodbus.transaction import ModbusRtuFramer # client = ModbusClient('localhost', port=5020, framer=ModbusRtuFramer) # client = ModbusClient(method='binary', port='/dev/ptyp0', timeout=1) # client = ModbusClient(method='ascii', port='/dev/ptyp0', timeout=1) client = ModbusClient(method='rtu', port='/dev/cu.wchusbserial14310', timeout=1, baudrate=9600) client.connect() # ------------------------------------------------------------------------# # specify slave to query # ------------------------------------------------------------------------# # The slave to query is specified in an optional parameter for each # individual request. This can be done by specifying the `unit` parameter # which defaults to `0x00` # ----------------------------------------------------------------------- # log.debug("Write to a holding register and read back") rr = client.read_holding_registers(0, 8, unit=UNIT) print(rr.registers) # test the expected value client.close()
def write_modbus_rtu(id=1, addr=10, value=1, unit=0x01): client = ModbusClient(method="rtu", port="/dev/tty.usbserial-AK066TL5", stopbits = 1, bytesize = 8, parity='N', baudrate = 9600) connection = client.connect() if(connection is not True): print('ModbusClient connection error') rq=client.write_register(1, 10, unit=UNIT) assert(not rq.isError()) client.close()
def connect(ad1, comport): client = ModbusSerialClient(method='rtu', port=comport, baudrate=9600, timeout=3, parity='N', stopbits=1, bytesize=8) if client.connect(): #ad1=int(input("address1: ")) # Address input normal register = int(ad1) try: result1 = client.read_input_registers(address=register - 1, count=1, unit=1) #Uint32/1 result2 = client.read_input_registers(address=register, count=1, unit=1) #Uint32/2 r = result2.registers + result1.registers #[Uint32/2, Uint32/1] except AttributeError: connect(ad1, comport) try: try: b = struct.pack('HH', r[0], r[1]) ans = struct.unpack('f', b)[0] ans = '%.2f' % ans allans = ans print('Ans: ', allans) client.close() return allans except UnboundLocalError: print( "!!!!!!!!!!!!!!!!!!!!!!!!!!!UnboundLocalError!!!!!!!!!!!!!!!!!!!!!!!!!!" ) connect(ad1, comport) except: messagebox.askretrycancel( "Message", "Cannot connect to the Modbus Server/Slave") print( "!!!!!!!!!!!!!!!!!!!!!!!!!!!Cannot connect to the Modbus Server/Slave!!!!!!!!!!!!!!!!!!!!!!!!!!" ) connect(ad1, comport) raise else: print('Cannot connect to the Modbus Server/Slave') tryy = messagebox.askretrycancel("Message", "Please Check USB Cable or USB port") if (tryy): connect(ad1, comport)
def read_modbus_rtu(): client = ModbusClient(method="rtu", port="/dev/tty.usbserial-AK066TL5", stopbits = 1, bytesize = 8, parity='N', baudrate = 9600) connection = client.connect() if(connection is not True): print('ModbusClient connection error') rr = client.read_holding_registers(address=1, count=1, unit=UNIT) # assert(not rr.isError()) print(rr) client.close()
def write_data_rs485(configuration, device): client= ModbusClient(method = "rtu", port="/dev/ttyUSB0",stopbits = 1, bytesize = 8, parity = 'E',baudrate= 9600) #Connect to the serial modbus server connection = client.connect() print(connection) #Starting add, num of reg to read, slave unit. #result= client.read_holding_registers(0x00,2,unit= 0xff) #print(result) client.write_register(0x00,"1") #Closes the underlying socket connection client.close()
def run_sync_client(): #enabling modbus communication client = ModbusClient(method='rtu', port=MODBUS_DEVICE, timeout=MODBUS_TIMEOUT, baudrate=MODBUS_BAUDRATE) client.connect() MyBoiler.registers = [] id_stop = -1 for mbrange in cfg['modbus']['register_ranges']: id_start = mbrange[0] MyBoiler.registers.extend([None] * (id_start - id_stop - 1)) id_stop = mbrange[1] for i in range(MODBUS_RETRIES): log.debug("Attempt {} to read registers from {} to {}".format( i, id_start, id_stop)) rr = client.read_holding_registers(count=(id_stop - id_start + 1), address=id_start, unit=MODBUS_UNIT) if rr.isError(): log.error(rr.message) MyBoiler.registers.extend([None] * (id_stop - id_start + 1)) else: MyBoiler.registers.extend(rr.registers) break client.close() #parsing registers to push data in Object attributes MyBoiler.browse_registers() log.info("Dumping values\n" + MyBoiler.dump()) #pushing data to influxdb if args.backend and args.backend == 'influxdb': timestamp = int(time.time() * 1000) #milliseconds influx_json_body = [{ "measurement": "diematic", "tags": { "host": "raspberrypi", }, "timestamp": timestamp, "fields": MyBoiler.fetch_data() }] influx_client = InfluxDBClient(cfg['influxdb']['host'], cfg['influxdb']['port'], cfg['influxdb']['user'], cfg['influxdb']['password'], cfg['influxdb']['database']) log.debug("Write points: {0}".format(influx_json_body)) influx_client.write_points(influx_json_body, time_precision='ms')
def write_via_rtu_modbus(state): client = ModbusSerialClient(method='rtu', port=PORT, timeout=1, baudrate=460800) log.debug("Writing Coils") rq = client.write_coil(1, state, unit=UNIT) log.debug(rq) log.debug("Reading Coils") rr = client.read_coils(1, 1, unit=UNIT) log.debug(rr) client.close()
class communication: def __init__(self): self.client = None def connectToDevice(self, device): """Connection to the client - the method takes the IP address (as a string, e.g. '192.168.1.11') as an argument.""" self.client = ModbusSerialClient(method='rtu',port=device,stopbits=1, bytesize=8, baudrate=115200, timeout=0.2) if not self.client.connect(): print "Unable to connect to %s" % device return False return True def disconnectFromDevice(self): """Close connection""" self.client.close() def sendCommand(self, data): """Send a command to the Gripper - the method takes a list of uint8 as an argument. The meaning of each variable depends on the Gripper model (see support.robotiq.com for more details)""" #make sure data has an even number of elements if(len(data) % 2 == 1): data.append(0) #Initiate message as an empty list message = [] #Fill message by combining two bytes in one register for i in range(0, len(data)/2): message.append((data[2*i] << 8) + data[2*i+1]) #To do!: Implement try/except self.client.write_registers(0x03E8, message, unit=0x0009) def getStatus(self, numBytes): """Sends a request to read, wait for the response and returns the Gripper status. The method gets the number of bytes to read as an argument""" numRegs = int(ceil(numBytes/2.0)) #To do!: Implement try/except #Get status from the device response = self.client.read_holding_registers(0x07D0, numRegs, unit=0x0009) #Instantiate output as an empty list output = [] #Fill the output with the bytes in the appropriate order for i in range(0, numRegs): output.append((response.getRegister(i) & 0xFF00) >> 8) output.append( response.getRegister(i) & 0x00FF) #Output the result return output
def change_station_id(modbusid, serialport, id_setting, current_baudrate): instrument = ModbusSerialClient(method='rtu', port=serialport, baudrate=current_baudrate) builder = BinaryPayloadBuilder(byteorder=Endian.Big) builder.add_16bit_int(id_setting) payload = builder.build() pld = payload[0][1] | (payload[0][0] << 8) instrument.connect() instrument.write_register(1000, pld, unit=modbusid, timeout=.1) instrument.close()
class EPsolarTracerClient: ''' EPsolar Tracer client ''' def __init__(self, unit = 1, serialclient = None, **kwargs): ''' Initialize a serial client instance ''' self.unit = unit if serialclient == None: port = kwargs.get('port', '/dev/ttyXRUSB0') baudrate = kwargs.get('baudrate', 115200) self.client = ModbusClient(method = 'rtu', port = port, baudrate = baudrate, kwargs = kwargs) else: self.client = serialclient def connect(self): ''' Connect to the serial :returns: True if connection succeeded, False otherwise ''' return self.client.connect() def close(self): ''' Closes the underlying connection ''' return self.client.close() def read_device_info(self): request = ReadDeviceInformationRequest (unit = self.unit) response = self.client.execute(request) return response def read_input(self, name): register = registerByName(name) if register.is_coil(): response = self.client.read_coils(register.address, register.size, unit = self.unit) elif register.is_discrete_input(): response = self.client.read_discrete_inputs(register.address, register.size, unit = self.unit) elif register.is_input_register(): response = self.client.read_input_registers(register.address, register.size, unit = self.unit) else: response = self.client.read_holding_registers(register.address, register.size, unit = self.unit) return register.decode(response) def write_output(self, name, value): register = registerByName(name) values = register.encode(value) response = False if register.is_coil(): self.client.write_coil(register.address, values, unit = self.unit) response = True elif register.is_discrete_input(): _logger.error("Cannot write discrete input " + repr(name)) pass elif register.is_input_register(): _logger.error("Cannot write input register " + repr(name)) pass else: self.client.write_registers(register.address, values, unit = self.unit) response = True return response
class Torqueforce(crappy.inout.InOut): def __init__(self,port='/dev/ttyUSB0',baudrate=115200): self.port = port self.baudrate = baudrate self.m = ModbusSerialClient('rtu',port=self.port,baudrate=self.baudrate, parity='E') def open(self): self.m.connect() def get_data(self): l = self.m.read_holding_registers(32,4,unit=1).registers return [time(),tofloat(l[:2]),tofloat(l[2:])] def close(self): self.m.close()
def looo_read_modbus_rtu_message(): client = ModbusClient(method="rtu", port="/dev/tty.usbserial-AK066TL5", stopbits = 1, bytesize = 8, parity='N', baudrate = 9600) connection = client.connect() if(connection is not True): print('ModbusClient connection error') while True: try: rr = client.read_input_registers(address=1, count=1, unit=1) break except ValueError: print('{} has some error'.format(rr)) else: print('Error: ', type(rr)) client.close()
def write_register(reg_add, val, mod_adress): try: client = ModbusClient(method='rtu', port=com, baudrate=2400, stopbits=1, parity='N', bytesize=8, timeout=3) client.connect() time.sleep(0.3) client.write_register(reg_add, val, unit=mod_adress) client.close() except AttributeError: print('Połaczenie z adresem {} nie udane'.format(mod_adress)) return print('Nowa wartosc zapisana')
def main(): try: modbus = ModbusClient(method='rtu', port='/dev/ttyUSB0', baudrate=9600, timeout=1, parity='E', bytesize=8) modbus.connect() voltage = validator(modbus.read_holding_registers(3910, 2, unit=1)) current = validator(modbus.read_holding_registers(3928, 2, unit=1)) factor = validator(modbus.read_holding_registers(3922, 2, unit=1)) freq = validator(modbus.read_holding_registers(3914, 2, unit=1)) print("Voltage: {} V".format(round(voltage, 2))) print("Current: {} A".format(current)) print("Factor: {}".format(factor)) print("Frequency: {} Hz".format(freq)) modbus.close() return voltage, current, factor, freq except AttributeError as e: print(e) return None
def modbus_session(): modbus = ModbusSerialClient( method=cfg.modbus.method, baudrate=cfg.modbus.baudr, parity=cfg.modbus.parity, port=cfg.modbus.portname, timeout=cfg.modbus.timeout ) try: modbus.connect() except (OSError, ModbusException, serial.SerialException) as e: logger.error("Unable connect to the boiler via modbus: {}".format(e)) raise else: yield modbus finally: modbus.close()
def read_data_rs485_holding(): client = ModbusClient(method="rtu", port="/dev/ttyUSB0", stopbits=1, bytesize=8, parity='N', baudrate=9600) #Connect to the serial modbus server connection = client.connect() print(connection) #Starting add, num of reg to read, slave unit. result = client.read_holding_registers(0x17, 2, unit=1) print(result) #Closes the underlying socket connection client.close() print(result.registers[0] * 0.001) return result.registers[0]
class SynchronousRtuClient(Runner, unittest.TestCase): """ These are the integration tests for the synchronous serial rtu client. """ def setUp(self): """ Initializes the test environment """ super(Runner, self).setUp() self.initialize(["../tools/reference/diagslave", "-m", "rtu", "/dev/pts/14"]) self.client = ModbusClient(method='rtu', timeout=0.2, port='/dev/pts/13') self.client.connect() def tearDown(self): """ Cleans up the test environment """ self.client.close() super(Runner, self).tearDown()
def read_holding(self,reg_start, reg_lenght, mod_adress): try: client = ModbusClient(method='rtu', port=com, baudrate=2400, stopbits=1, parity='N', bytesize=8, timeout=3) connection = client.connect() time.sleep(0.3) massure = client.read_holding_registers(reg_start - 1, reg_lenght, unit=mod_adress) print('Rejestry :', massure.registers[0:]) # print(connection) client.close() return connection, massure.registers except AttributeError: print('Połaczenie z adresem {} nie udane'.format(mod_adress))
class Worker(QtCore.QObject): """opc-сервер""" finished = QtCore.pyqtSignal() def __init__(self, port: str = '', baud: int = 9600, timeout: float = 0.05, parent=None): super().__init__(parent) self.running = False self.name = port try: self.port = Client(method='rtu', port=port, timeout=timeout, baudrate=baud, retry_on_empty=True, retries=5, strict=False) print( f'Порт {self.name} baud = {baud} таймаут {timeout*1000:.0f} мс' ) except Exception as exc: print(exc) self.dev = [] def run(self): if self.port.connect(): print(f'Открыт порт {self.name}') self.running = True else: print(f'Порт {self.name} не удалось открыть') while self.running: for dev in self.dev: # if self.thread() == dev.thread(): print(self.thread(), dev.thread(), dev) dev.update() self.thread().msleep(2) if not self.running: break self.port.close() print('Остановлен сервер {}'.format(self.name)) self.finished.emit()
class SynchronousAsciiClient(Runner, unittest.TestCase): ''' These are the integration tests for the synchronous serial ascii client. ''' def setUp(self): ''' Initializes the test environment ''' super(Runner, self).setUp() # "../tools/nullmodem/linux/run", self.initialize(["../tools/reference/diagslave", "-m", "ascii", "/dev/pts/14"]) self.client = ModbusClient(method='ascii', timeout=0.2, port='/dev/pts/13') self.client.connect() def tearDown(self): ''' Cleans up the test environment ''' self.client.close() super(Runner, self).tearDown()
def testBasicSyncSerialClient(self): ''' Test the basic methods for the serial sync client''' # receive/send client = ModbusSerialClient() client.socket = mockSocket() self.assertEqual(0, client._send(None)) self.assertEqual(1, client._send('\x00')) self.assertEqual('\x00', client._recv(1)) # connect/disconnect self.assertTrue(client.connect()) client.close() # already closed socket client.socket = False client.close() self.assertEqual('ascii baud[19200]', str(client))
def run_motor_gui_standalone(): client = ModbusClient(method="rtu", port="/dev/ttyUSB0", stopbits=1, \ bytesize=8, parity='E', baudrate=9600, timeout=0.1) # connect to the serial modbus server connection = client.connect() print("Connection = " + str(connection)) # Create and set up the GUI object root = Tk() root.title("WIFIS Motor Controller") root.geometry("275x375") #root.protocol("WM_DELETE_WINDOW", on_closing) app = MainApplication(root,client) root.mainloop() # closes the underlying socket connection client.close()
class TristarPWM(object): """ tristar pwm ts45 or ts60 for data logging, it can read the holding/input register and save to csv file """ def __init__(self, method, port, baudrate, stopbits, parity, timeout, DT=10, COUNT=6, debug_flag=True, log_flag=True, thingspeak_flag=True): self.method = method self.port = port self.baudrate = baudrate self.stopbits = stopbits self.parity = parity self.timeout = timeout self.DT = DT self.COUNT = COUNT self.debug_flag = debug_flag self.log_flag = log_flag self.thingspeak_flag = thingspeak_flag self.register_dict={} def connect(self): """ connect to modbus client """ try: self.client = ModbusClient(method=self.method, port=self.port, baudrate=self.baudrate, stopbits=self.stopbits, parity=self.parity, timeout=self.timeout) self.client.connect() print "connected" except KeyboardInterrupt: self.client.close() def close(self): """ disconnect client """ self.client.close() def read_registers(self): """ read holding registers """ # read the registers from logical address 0 to 0x1e. response = self.client.read_holding_registers(0x00, 0x1e, unit=1) # the stuff we want batt_V = (response.registers[adc_vb_f] * v_scale) / (2**15) batt_sens_V = (response.registers[adc_vs_f] * v_scale) / (2**15) array_V = (response.registers[adc_vx_f] * array_scale) / (2**15) charge_I = (response.registers[adc_ipv_f] * i_scale) / (2**15) load_I = (response.registers[adc_iload_f] * iload_scale) / (2**15) batt_V_slow = (response.registers[vb_f] * v_scale) / (2**15) heatsink_T = response.registers[t_hs] batt_T = response.registers[t_batt] reference_V = (response.registers[v_ref] * v_scale) / (2**15) ah_reset = (response.registers[ah_r_hi]<<8 + \ response.registers[ah_r_lo] ) * ah_scale ah_total = (response.registers[ah_t_hi]<<8 + \ response.registers[ah_t_lo] ) * ah_scale hourmeter = response.registers[hourmeter_hi]<<8 + \ response.registers[hourmeter_lo] alarm_bits = response.registers[alarm_hi]<<8 + \ response.registers[alarm_lo] fault_bits = response.registers[fault] dip_num = response.registers[dip_switch] mode_num = response.registers[control_mode] state_num = response.registers[control_state] pwm_duty = response.registers[d_filt] /230.0 if pwm_duty > 1: pwm_duty = 100.0 # p. 13 0: 0%, >=230: 100% else: pwm_duty *= 100.0 # convert to percentage powerIn = batt_V * charge_I mode = control_mode_turple[mode_num] if mode_num == 0 or mode_num ==2: # charge of diversion state = charge_div_state_turple[state_num] else: # load and lighting mode state = load_light_state_turple[state_num] return {"batt_V":batt_V,"batt_sens_V":batt_sens_V, "array_V":array_V,"charge_I":charge_I,"load_I":load_I, "batt_V_slow":batt_V_slow,"heatsink_T":heatsink_T, "batt_T":batt_T,"reference_V":reference_V, "ah_reset":ah_reset,"ah_total":ah_total, "hourmeter":hourmeter,"alarm_bits":alarm_bits, "fault_bits":fault_bits,"dip_num":dip_num, "mode_num":mode_num,"state_num":state_num, "pwm_duty":pwm_duty,"powerIn":powerIn, "mode":mode,"state":state} def read_modbus(self): """read output from modbus, save them into a list""" assert(self.client is not None), "client not connected" counter = 1 # initialize list batt_V_list = [] batt_sens_V_list = [] array_V_list = [] charge_I_list = [] load_I_list = [] batt_V_slow_list = [] heatsink_T_list = [] batt_T_list = [] pwm_duty_list = [] powerIn_list = [] while counter <= self.COUNT: try: self.register_dict = self.read_registers() except KeyboardInterrupt: print "interrupted" break except: print "port not available" continue # debug if self.debug_flag: print self.register_dict.items() # for key in register_dict: # print key # print register_dict[key] # calculate average batt_V_list.append(self.register_dict["batt_V"]) batt_sens_V_list.append(self.register_dict["batt_sens_V"]) array_V_list.append(self.register_dict["array_V"]) charge_I_list.append(self.register_dict["charge_I"]) load_I_list.append(self.register_dict["load_I"]) batt_V_slow_list.append(self.register_dict["batt_V_slow"]) heatsink_T_list.append(self.register_dict["heatsink_T"]) batt_T_list.append(self.register_dict["batt_T"]) pwm_duty_list.append(self.register_dict["pwm_duty"]) powerIn_list.append(self.register_dict["powerIn"]) # return value counter += 1 time.sleep(self.DT) else: # add time point tid = time.strftime("%Y/%m/%d %H:%M:%S") self.register_dict["tid"] = str(tid) # calculate average self.register_dict["batt_V"] = mean(batt_V_list) self.register_dict["array_V"] = mean(array_V_list) self.register_dict["charge_I"] = mean(charge_I_list) self.register_dict["pwm_duty"] = mean(pwm_duty_list) self.register_dict["heatsinke_T"] = mean(heatsink_T_list) self.register_dict["powerIn"] = mean(powerIn_list) def write_thingspeak(self, field_id, field_var_name): """ write certain fields to thingspeak, while loop """ if self.thingspeak_flag: channel = thingspeak.channel() try: while True: # register_dict = self.read_modbus() self.read_modbus() field_var = [self.register_dict[i] for i in field_var_name] channel.update(field_id, field_var) except KeyboardInterrupt: self.close() else: pass def write_thingspeak_oneshot(self, field_id, field_var_name): """ write certain fields to thingspeak, no loop """ if self.thingspeak_flag: channel = thingspeak.channel() self.read_modbus() field_var = [self.register_dict[i] for i in field_var_name] channel.update(field_id, field_var) else: pass def log_data(self, field_var_name, filename, tid=None): """ log data into a file Changelog 20160308: insert external tid for data to have same tid """ if self.log_flag: filename_new = filename + time.strftime("%Y%m%d") + '.csv' if not os.path.isfile(filename_new): # write new file with header # create new file os.mknod(filename_new) # chmod os.chmod(filename_new, 0o755) fil = open(filename_new, 'w+') # write header # select items to write header = ",".join(field_var_name) fil.write(header+"\n") else: # append if not os.access(filename_new, os.W_OK): # chmod os.chmod(filename_new, 0o755) else: fil = open(filename_new, 'a+') # pass register_dict to file write # check if have external tid if tid is not None: self.register_dict['tid'] = str(tid) field_var = [str(self.register_dict[i]) for i in field_var_name] output_text = ",".join(field_var) # print output_text fil.write(output_text+"\n") fil.close() else: # no log pass
def run_sync_client(): # ------------------------------------------------------------------------# # choose the client you want # ------------------------------------------------------------------------# # make sure to start an implementation to hit against. For this # you can use an existing device, the reference implementation in the tools # directory, or start a pymodbus server. # # If you use the UDP or TCP clients, you can override the framer being used # to use a custom implementation (say RTU over TCP). By default they use # the socket framer:: # # client = ModbusClient('localhost', port=5020, framer=ModbusRtuFramer) # # It should be noted that you can supply an ipv4 or an ipv6 host address # for both the UDP and TCP clients. # # There are also other options that can be set on the client that controls # how transactions are performed. The current ones are: # # * retries - Specify how many retries to allow per transaction (default=3) # * retry_on_empty - Is an empty response a retry (default = False) # * source_address - Specifies the TCP source address to bind to # # Here is an example of using these options:: # # client = ModbusClient('localhost', retries=3, retry_on_empty=True) # ------------------------------------------------------------------------# # client = ModbusClient('localhost', port=5020) # client = ModbusClient(method='ascii', port='/dev/pts/2', timeout=1) client = ModbusClient(method='rtu', port='/dev/ttyS3', baudrate=9600, timeout=1) client.connect() # ----------------------------------------------------------------------- # # example requests # ----------------------------------------------------------------------- # # simply call the methods that you would like to use. An example session # is displayed below along with some assert checks. Note that some modbus # 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(40001, 1, unit=UNIT) print(rr.registers[0]) # 读两路输入(寄存器地址200,共2个) log.debug("Read discrete inputs") rr = client.read_discrete_inputs(200, 2, unit=UNIT) print(rr.bits) # bit0表示DI1的状态,bit1表示DI2 # 写单个输出DO1(寄存器地址100) log.debug("Write to a Coil and read back") rq = client.write_coil(100, True, unit=UNIT) rr = client.read_coils(100, 1, unit=UNIT) assert(rq.function_code < 0x80) # test that we are not an error assert(rr.bits[0] == True) # test the expected value # ----------------------------------------------------------------------- # # close the client # ----------------------------------------------------------------------- # client.close()
class SunSaverMPPT(object): """ sunsaver mppt 15 for data logging, it can read the holding/input register and save to csv file """ def __init__(self, method, port, baudrate, stopbits, parity, timeout, DT=10, COUNT=6, debug_flag=True, log_flag=True, thingspeak_flag=True): self.method = method self.port = port self.baudrate = baudrate self.stopbits = stopbits self.parity = parity self.timeout = timeout self.DT = DT self.COUNT = COUNT self.debug_flag = debug_flag self.log_flag = log_flag self.thingspeak_flag = thingspeak_flag def connect(self): """ connect to modbus client """ try: self.client = ModbusClient(method=self.method, port=self.port, baudrate=self.baudrate, stopbits=self.stopbits, parity=self.parity, timeout=self.timeout) self.client.connect() except KeyboardInterrupt: self.client.close() def close(self): """ disconnect client """ self.client.close() def read_registers(self): """ read holding registers """ # read the registers from logical address 0 to 0x1e. response = self.client.read_holding_registers(0x00, 0x3e, unit=1) # the stuff we want batt_V = (response.registers[Adc_vb_f] * v_scale) / (2**15) array_V = (response.registers[Adc_va_f] * v_scale) / (2**15) load_V = (response.registers[Adc_vl_f] * v_scale) / (2**15) charge_I = (response.registers[Adc_ic_f] * i_scale) / (2**15) load_I = (response.registers[Adc_il_f] * i_scale) / (2**15) batt_V_slow = (response.registers[Vb_f] * v_scale) / (2**15) heatsink_T = response.registers[t_hs] ah_reset = (response.registers[Ahc_r_HI]<<8 + \ response.registers[Ahc_r_LO] ) * ah_scale ah_total = (response.registers[Ahc_t_HI]<<8 + \ response.registers[Ahc_t_LO] ) * ah_scale hourmeter = response.registers[hourmeter_HI]<<8 + \ response.registers[hourmeter_LO] alarm_bits = response.registers[alarm_HI]<<8 + \ response.registers[alarm_LO] dip_num = response.registers[dip_switch] led_num = response.registers[led_state] power_out = (response.registers[Power_out] * p_scale) / (2**15) mode = control_mode_turple[mode_num] if mode_num == 0 or mode_num ==2: # charge of diversion state = charge_div_state_turple[state_num] else: # load and lighting mode state = load_light_state_turple[state_num] return {"batt_V":batt_V,"batt_sens_V":batt_sens_V, "array_V":array_V,"charge_I":charge_I,"load_I":load_I, "batt_V_slow":batt_V_slow,"heatsink_T":heatsink_T, "batt_T":batt_T,"reference_V":reference_V, "ah_reset":ah_reset,"ah_total":ah_total, "hourmeter":hourmeter,"alarm_bits":alarm_bits, "fault_bits":fault_bits,"dip_num":dip_num, "mode_num":mode_num,"state_num":state_num, "pwm_duty":pwm_duty,"powerIn":powerIn, "mode":mode,"state":state} def read_modbus(self): """read output from modbus, save them into a list""" assert(self.client is not None), "client not connected" counter = 1 # initialize list batt_V_list = [] batt_sens_V_list = [] array_V_list = [] charge_I_list = [] load_I_list = [] batt_V_slow_list = [] heatsink_T_list = [] batt_T_list = [] pwm_duty_list = [] powerIn_list = [] while counter <= self.COUNT: register_dict = self.read_registers() # debug if self.debug_flag: print register_dict.items() # for key in register_dict: # print key # print register_dict[key] # calculate average batt_V_list.append(register_dict["batt_V"]) batt_sens_V_list.append(register_dict["batt_sens_V"]) array_V_list.append(register_dict["array_V"]) charge_I_list.append(register_dict["charge_I"]) load_I_list.append(register_dict["load_I"]) batt_V_slow_list.append(register_dict["batt_V_slow"]) heatsink_T_list.append(register_dict["heatsink_T"]) batt_T_list.append(register_dict["batt_T"]) pwm_duty_list.append(register_dict["pwm_duty"]) powerIn_list.append(register_dict["powerIn"]) # return value counter += 1 time.sleep(self.DT) else: # add time point tid = time.strftime("%Y/%m/%d %H:%M:%S") register_dict["tid"] = str(tid) # calculate average register_dict["batt_V"] = mean(batt_V_list) register_dict["array_V"] = mean(array_V_list) register_dict["charge_I"] = mean(charge_I_list) register_dict["pwm_duty"] = mean(pwm_duty_list) register_dict["heatsinke_T"] = mean(heatsink_T_list) register_dict["powerIn"] = mean(powerIn_list) # return result return register_dict def write_thingspeak(self, field_id, field_var_name): """ write certain fields to thingspeak, while loop """ if self.thingspeak_flag: channel = thingspeak.channel() try: while True: register_dict = self.read_modbus() field_var = [register_dict[i] for i in field_var_name] channel.update(field_id, field_var) except KeyboardInterrupt: self.close() else: pass def write_thingspeak_oneshot(self, field_id, field_var_name): """ write certain fields to thingspeak, no loop """ if self.thingspeak_flag: channel = thingspeak.channel() register_dict = self.read_modbus() field_var = [register_dict[i] for i in field_var_name] channel.update(field_id, field_var) else: pass def log_data(self, field_var_name, filename): """ log data into a file """ if self.log_flag: filename_new = filename + time.strftime("%Y%m%d") + '.csv' if not os.path.isfile(filename_new): # write new file with header fil = open(filename_new, 'w') # write header # select items to write header = ",".join(field_var_name) fil.write(header+"\n") else: # append fil = open(filename_new, 'a') # read modbus register_dict = self.read_modbus() field_var = [str(register_dict[i]) for i in field_var_name] output_text = ",".join(field_var) print output_text fil.write(output_text+"\n") fil.close() else: # no log pass
class SenseAirDevice(object): def __init__(self): #---------------------------------------------------------------------------# # This will simply send everything logged to console #---------------------------------------------------------------------------# logging.basicConfig() log = logging.getLogger() log.setLevel(logging.DEBUG) self.client = None def connect(self, deviceName): self.client = ModbusSerialClient(method='rtu',port=deviceName,stopbits=1, bytesize=8, baudrate=9600, timeout=0.2) if not self.client.connect(): rospy.logerr("Unable to connect to %s", device) return False return True def close(self): self.client.close() # Not working right now def getDeviceIdentification(self, objectId): rq = ReadDeviceInformationRequest(read_code=4, object_id=objectId, unit=0xFE) #rospy.loginfo("encoded: %h", encoded[0]) rr = self.client.execute(rq) print rr return "" if rr is None: rospy.logerr("No response from device") return None if rr.function_code < 0x80: # test that we are not an error return rr.information[0] #vendor_name = rr.information[0] #product_code = rr.information[1] #code_revision = rr.information[2] #rospy.loginfo("vendor: %s", vendor_name) #rospy.loginfo("product code: %s", product_code) #rospy.loginfo("revision: %s", code_revision) else: rospy.logwarn("error reading device identification: %h", rr.function_code) def getVendor(self): vendor = self.getDeviceIdentification(0) print vendor def readCO2(self): response = self.client.read_input_registers(address=3, count=1, unit=0xFE ) return response.getRegister(0) def readTemperature(self): response = self.client.read_input_registers(address=4, count=1, unit=0xFE ) return response.getRegister(0)*100.0 def sendCommand(self, data): #make sure data has an even number of elements if(len(data) % 2 == 1): data.append(0) #Initiate message as an empty list message = [] #Fill message by combining two bytes in one register for i in range(0, len(data)/2): message.append((data[2*i] << 8) + data[2*i+1]) #To do!: Implement try/except self.client.write_registers(0x03E8, message, unit=0x0009) def getStatus(self, numBytes): """Sends a request to read, wait for the response and returns the Gripper status. The method gets the number of bytes to read as an argument""" numRegs = int(ceil(numBytes/2.0)) #To do!: Implement try/except #Get status from the device response = self.client.read_holding_registers(0x07D0, numRegs, unit=0x0009) #Instantiate output as an empty list output = [] #Fill the output with the bytes in the appropriate order for i in range(0, numRegs): output.append((response.getRegister(i) & 0xFF00) >> 8) output.append( response.getRegister(i) & 0x00FF) #Output the result return output
class Device: """ Modbus device (Master) class """ def __init__(self, device): self.device = device self._address = device.modbusdevice.ip_address self._unit_id = device.modbusdevice.unit_id self._port = device.modbusdevice.port self._protocol = device.modbusdevice.protocol self._framer = device.modbusdevice.framer self._stopbits = device.modbusdevice.stopbits self._bytesize = device.modbusdevice.bytesize self._parity = device.modbusdevice.parity self._baudrate = device.modbusdevice.baudrate self._timeout = device.modbusdevice.timeout self._device_not_accessible = 0 # stopbits if self._stopbits == 0: self._stopbits = Defaults.Stopbits # bytesize if self._bytesize == 0: self._bytesize = Defaults.Bytesize # parity parity_list = {0: Defaults.Parity, 1: 'N', 2: 'E', 3: 'O'} self._parity = parity_list[self._parity] # baudrate if self._baudrate == 0: self._baudrate = Defaults.Baudrate # timeout if self._timeout == 0: self._timeout = Defaults.Timeout self.trans_input_registers = [] self.trans_coils = [] self.trans_holding_registers = [] self.trans_discrete_inputs = [] self.variables = {} self._variable_config = self._prepare_variable_config(device) self.data = [] def _prepare_variable_config(self, device): for var in device.variable_set.filter(active=1): if not hasattr(var, 'modbusvariable'): continue f_c = var.modbusvariable.function_code_read if f_c == 0: continue # add some attr to the var model var.add_attr(accessible=1) # add the var to the list of self.variables[var.pk] = var if f_c == 1: # coils self.trans_coils.append([var.modbusvariable.address, var.pk, f_c]) elif f_c == 2: # discrete inputs self.trans_discrete_inputs.append([var.modbusvariable.address, var.pk, f_c]) elif f_c == 3: # holding registers self.trans_holding_registers.append( [var.modbusvariable.address, var.decode_value, var.get_bits_by_class(), var.pk, f_c]) elif f_c == 4: # input registers self.trans_input_registers.append( [var.modbusvariable.address, var.decode_value, var.get_bits_by_class(), var.pk, f_c]) else: continue self.trans_discrete_inputs.sort(key=lambda x: x[0]) self.trans_holding_registers.sort(key=lambda x: x[0]) self.trans_coils.sort(key=lambda x: x[0]) self.trans_input_registers.sort(key=lambda x: x[0]) out = [] # input registers old = -2 regcount = 0 for entry in self.trans_input_registers: if (entry[0] != old) or regcount > 122: regcount = 0 out.append(InputRegisterBlock()) # start new register block out[-1].insert_item(entry[3], entry[0], entry[1], entry[2]) # add item to block old = entry[0] + entry[2] / 16 regcount += entry[2] / 16 # holding registers old = -2 regcount = 0 for entry in self.trans_holding_registers: if (entry[0] != old) or regcount > 122: regcount = 0 out.append(HoldingRegisterBlock()) # start new register block out[-1].insert_item(entry[3], entry[0], entry[1], entry[2]) # add item to block old = entry[0] + entry[2] / 16 regcount += entry[2] / 16 # coils old = -2 for entry in self.trans_coils: if entry[0] != old + 1: out.append(CoilBlock()) # start new coil block out[-1].insert_item(entry[1], entry[0]) old = entry[0] # discrete inputs old = -2 for entry in self.trans_discrete_inputs: if entry[0] != old + 1: out.append(DiscreteInputBlock()) # start new coil block out[-1].insert_item(entry[1], entry[0]) old = entry[0] return out def _connect(self): """ connect to the modbus slave (server) """ framer = None if self._framer == 0: # Socket Framer framer = ModbusSocketFramer elif self._framer == 1: # RTU Framer framer = ModbusRtuFramer elif self._framer == 2: # ASCII Framer framer = ModbusAsciiFramer elif self._framer == 3: # Binary Framer framer = ModbusBinaryFramer if self._protocol == 0: # TCP if self._framer is None: # No Framer self.slave = ModbusTcpClient(self._address, int(self._port)) else: self.slave = ModbusTcpClient(self._address, int(self._port), framer=framer) elif self._protocol == 1: # UDP if self._framer is None: # No Framer self.slave = ModbusUdpClient(self._address, int(self._port)) else: self.slave = ModbusUdpClient(self._address, int(self._port), framer=framer) elif self._protocol in (2, 3, 4): # serial method_list = {2: 'ascii', 3: 'rtu', 4: 'binary'} self.slave = ModbusSerialClient( method=method_list[self._protocol], port=self._port, stopbits=self._stopbits, bytesize=self._bytesize, parity=self._parity, baudrate=self._baudrate, timeout=self._timeout) else: raise NotImplementedError("Protocol not supported") status = self.slave.connect() return status def _disconnect(self): """ close the connection to the modbus slave (server) """ self.slave.close() def request_data(self): """ """ if not driver_ok: return None if not self._connect(): if self._device_not_accessible == -1: # logger.error("device with id: %d is not accessible" % self.device.pk) self._device_not_accessible -= 1 return [] output = [] for register_block in self._variable_config: result = register_block.request_data(self.slave, self._unit_id) if result is None: self._disconnect() self._connect() result = register_block.request_data(self.slave, self._unit_id) if result is not None: for variable_id in register_block.variables: if self.variables[variable_id].update_value(result[variable_id], time()): recorded_data_element = self.variables[variable_id].create_recorded_data_element() if recorded_data_element is not None: output.append(recorded_data_element) if self.variables[variable_id].accessible < 1: logger.info("variable with id: %d is now accessible" % variable_id) self.variables[variable_id].accessible = 1 else: for variable_id in register_block.variables: if self.variables[variable_id].accessible == -1: logger.error("variable with id: %d is not accessible" % variable_id) self.variables[variable_id].update_value(None, time()) self.variables[variable_id].accessible -= 1 # reset device not accessible status if self._device_not_accessible <= -1: logger.info("device with id: %d is now accessible" % self.device.pk) if self._device_not_accessible < 1: self._device_not_accessible = 1 self._disconnect() return output def write_data(self, variable_id, value, task): """ write value to single modbus register or coil """ if variable_id not in self.variables: return False if not self.variables[variable_id].writeable: return False if self.variables[variable_id].modbusvariable.function_code_read == 3: # write register if 0 <= self.variables[variable_id].modbusvariable.address <= 65535: if self._connect(): if self.variables[variable_id].get_bits_by_class() / 16 == 1: # just write the value to one register self.slave.write_register(self.variables[variable_id].modbusvariable.address, int(value), unit=self._unit_id) else: # encode it first self.slave.write_registers(self.variables[variable_id].modbusvariable.address, list(self.variables[variable_id].encode_value(value)), unit=self._unit_id) self._disconnect() return True else: logger.info("device with id: %d is now accessible" % self.device.pk) return False else: logger.error('Modbus Address %d out of range' % self.variables[variable_id].modbusvariable.address) return False elif self.variables[variable_id].modbusvariable.function_code_read == 1: # write coil if 0 <= self.variables[variable_id].modbusvariable.address <= 65535: if self._connect(): self.slave.write_coil(self.variables[variable_id].modbusvariable.address, bool(value), unit=self._unit_id) self._disconnect() return True else: logger.info("device with id: %d is now accessible" % self.device.pk) return False else: logger.error('Modbus Address %d out of range' % self.variables[variable_id].modbusvariable.address) else: logger.error('wrong type of function code %d' % self.variables[variable_id].modbusvariable.function_code_read) return False
""" import time # For sleep functionality import logging # For detailed error output from pymodbus.client.sync import ModbusSerialClient \ as ModbusClient # Import MODBUS support class comSettings = { "method" : 'rtu', "port" : 'COM3', "stopbits" : 1, "bytesize" : 8, "parity" : 'N', "baudrate" : 9600, "timeout" : 1 } logging.basicConfig() # Setup error logging log = logging.getLogger() # Start logging client = ModbusClient(**comSettings) # Setup connection object client.connect() # Open the MODBUS connection while(True): client.write_register(3,1000,unit=0x01) # Write valve to 100% time.sleep(4) # Sleep 4 seconds client.write_register(3,0,unit=0x01) # Write valve to 0% time.sleep(4) # Sleep 4 seconds client.close() # Close the connection
class modbusClient: """Class to carry out MODBUS read/write requests Usage: Ensure all params are setup in the 'modbusSettings' file Call 'openConnection' to connect to the assigned server Use 'dataHandler' to read or write data to the server Call 'closeConnection' to safely close the connection """ def __init__(self): """Load settings and connect to the designated slave""" self.modbusCfg = yamlImport.importYAML("./cfg/modbusSettings.yaml") if self.modbusCfg['logging'] == "enable": self.log = self.__logging() if self.__setupClient() == 0: return 0 if self.openConnection() == 0: return 0 def __logging(self): """Setup and enable logging on the client :return: enabled log instance """ import logging logging.basicConfig() log = logging.getLogger() log.setLevel(logging.INFO) return log def __setupClient(self): """Setup MODBUS client object""" if self.modbusCfg['method'] == "tcp": try: self.client = ModbusTcpClient(self.modbusCfg['ip'],\ self.modbusCfg['tcpPort']) except: raise return 0 elif self.modbusCfg['method'] == "rtu": try: self.client = ModbusSerialClient(self.modbusCfg['method'],\ self.modbusCfg['rtuPort'],\ self.modbusCfg['stopbits'],\ self.modbusCfg['bytesize'],\ self.modbusCfg['parity'],\ self.modbusCfg['baudrate'],\ self.modbusCfg['timeout']) except: raise return 0 else: raise NameError("Unsupported method") return 0 def openConnection(self): """Attempt connection with the MODBUS server""" for i in range(3): if self.client.connect() == True: return 1 else: print "Attempt " + str(i) + " failed" if i == 2: raise IOError("Failed to connect to specified server") return 0 time.sleep(0.5) def closeConnection(self): """Close connection with the MODBUS server""" try: self.client.close() except: print("Error - See log for details") return 0 return 1 def dataHandler(self, op, reg, addr, length=None, data=None, encoding=1): """Handle the MODBUS read/write requests and pass to the appropriate function Arguments: :param op: Operation to perform (R/W) :param reg: Modbus register to access (1-4) :param addr: Address to start operation at :type op: string :type reg: int :type addr: int Keyword Arguments: :param length: Length of registers to read (default None) :param data: Data to write to the slave :type length: int :type data: list :return: List containing the requested data or confimation of send. """ if op == 'r': for i in range(3): r = self.__readData(reg, addr, length, encoding) if (r == ConnectionException) or (r == ModbusIOException): print("Read attempt " + str(i) + " failed") if i == 2: #TODO: remove sys exit and handle properly raise SystemExit('Modbus Error: Failed 3 Attemps') elif r == ValueError: #TODO: remove sys exit and handle properly raise SystemExit('Invalid Register - Use 15 or 16') else: return r if op == 'w': for i in range(3): w = self.__writeData(reg, addr, data, encoding) if (w == ConnectionException) or (w == ModbusIOException): print("Write attempt " + str(i) + " failed") if i == 2: #TODO: remove sys exit and handle properly raise SystemExit('Modbus Error: Failed 3 Attemps') elif w == ValueError: #TODO: remove sys exit and handle properly raise SystemExit('Invalid Register - Use 15 or 16') else: return w return ValueError('Invalid Operation') def __readData(self, reg, addr, length, encoding): """Read data from the MODBUS Slave Called by 'dataHandler' in modbusClient.py Arguments: :param reg: Modbus register to access (1-4) :param addr: Address to start reading from :param length: Quantity of registers to read :param encoding: States whether data should be decoded :type reg: int :type addr: int :type length: int :type encoding: int :return: List containing the requested data or failure exception. """ data = [] if 1 <= reg <= 2: try: if reg == 1: co = self.client.read_coils(addr,length,unit=0x01) else: co = self.client.read_discrete_inputs(addr,length,unit=0x01) except ConnectionException: return ConnectionException if co.function_code != reg: return ModbusIOException for i in range(length): data.append(co.getBit(i)) return data elif 3 <= reg <= 4: try: if reg == 3: hr = self.client.read_holding_registers(addr,length,unit=0x01) else: hr = self.client.read_input_registers(addr,length,unit=0x01) except ConnectionException: return ConnectionException if hr.function_code != reg: return ModbusIOException for i in range(length): data.append(hr.getRegister(i)) if encoding == 1: return self.__decodeData(data) return data else: return ValueError def __writeData(self, reg, addr, data, encoding): """Write data to the MODBUS slave Called by 'dataHandler' in modbusClient.py Arguments: :param reg: Modbus register to access (15 or 16) :param addr: Address to start writing to :param data: List of data to write to the device :param encoding: States whether data should be encoded first :type reg: int :type addr: int :type length: int :type encoding: int :return: success or failure exception """ if reg == 15: try: co = self.client.write_coils(addr,data,unit=0x01) except ConnectionException: return ConnectionException if co.function_code != reg: return ModbusIOException elif reg == 16: if encoding == 1: data = self.__encodeData(data) try: hr = self.client.write_registers(addr,data,unit=0x01) except ConnectionException: return ConnectionException if hr.function_code != reg: return ModbusIOException else: return ValueError def __encodeData(self, data): """Encode data to 32bit float Function encodes a list of data passed to it into a 32 bit float packet that can be written directly to the MODBUS server table. Arguments: :param data: Float to be encoded :type data: list """ builder = BinaryPayloadBuilder(endian=Endian.Little) try: for i in range(0,len(data)): builder.add_32bit_float(data[i]) except TypeError: builder.add_32bit_float(data) return builder.to_registers() def __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 execute_extended_requests(): # ------------------------------------------------------------------------# # choose the client you want # ------------------------------------------------------------------------# # make sure to start an implementation to hit against. For this # you can use an existing device, the reference implementation in the tools # directory, or start a pymodbus server. # # It should be noted that you can supply an ipv4 or an ipv6 host address # for both the UDP and TCP clients. # ------------------------------------------------------------------------# client = ModbusClient(method='rtu', port="/dev/ttyp0") # client = ModbusClient('127.0.0.1', port=5020) client.connect() # ----------------------------------------------------------------------- # # extra requests # ----------------------------------------------------------------------- # # If you are performing a request that is not available in the client # mixin, you have to perform the request like this instead:: # # from pymodbus.diag_message import ClearCountersRequest # from pymodbus.diag_message import ClearCountersResponse # # request = ClearCountersRequest() # response = client.execute(request) # if isinstance(response, ClearCountersResponse): # ... do something with the response # # # What follows is a listing of all the supported methods. Feel free to # comment, uncomment, or modify each result set to match with your ref. # ----------------------------------------------------------------------- # # ----------------------------------------------------------------------- # # information requests # ----------------------------------------------------------------------- # log.debug("Running ReadDeviceInformationRequest") rq = ReadDeviceInformationRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference # assert (rr.function_code < 0x80) # test that we are not an error # assert (rr.information[0] == b'Pymodbus') # test the vendor name # assert (rr.information[1] == b'PM') # test the product code # assert (rr.information[2] == b'1.0') # test the code revision log.debug("Running ReportSlaveIdRequest") rq = ReportSlaveIdRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference # assert(rr.function_code < 0x80) # test that we are not an error # assert(rr.identifier == 0x00) # test the slave identifier # assert(rr.status == 0x00) # test that the status is ok log.debug("Running ReadExceptionStatusRequest") rq = ReadExceptionStatusRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference # assert(rr.function_code < 0x80) # test that we are not an error # assert(rr.status == 0x55) # test the status code log.debug("Running GetCommEventCounterRequest") rq = GetCommEventCounterRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference # assert(rr.function_code < 0x80) # test that we are not an error # assert(rr.status == True) # test the status code # assert(rr.count == 0x00) # test the status code log.debug("Running GetCommEventLogRequest") rq = GetCommEventLogRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference # assert(rr.function_code < 0x80) # test that we are not an error # assert(rr.status == True) # test the status code # assert(rr.event_count == 0x00) # test the number of events # assert(rr.message_count == 0x00) # test the number of messages # assert(len(rr.events) == 0x00) # test the number of events # ------------------------------------------------------------------------# # diagnostic requests # ------------------------------------------------------------------------# log.debug("Running ReturnQueryDataRequest") rq = ReturnQueryDataRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference # assert(rr.message[0] == 0x0000) # test the resulting message log.debug("Running RestartCommunicationsOptionRequest") rq = RestartCommunicationsOptionRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference # assert(rr.message == 0x0000) # test the resulting message log.debug("Running ReturnDiagnosticRegisterRequest") rq = ReturnDiagnosticRegisterRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ChangeAsciiInputDelimiterRequest") rq = ChangeAsciiInputDelimiterRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ForceListenOnlyModeRequest") rq = ForceListenOnlyModeRequest(unit=UNIT) rr = client.execute(rq) # does not send a response print(rr) log.debug("Running ClearCountersRequest") rq = ClearCountersRequest() rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ReturnBusCommunicationErrorCountRequest") rq = ReturnBusCommunicationErrorCountRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ReturnBusExceptionErrorCountRequest") rq = ReturnBusExceptionErrorCountRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ReturnSlaveMessageCountRequest") rq = ReturnSlaveMessageCountRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ReturnSlaveNoResponseCountRequest") rq = ReturnSlaveNoResponseCountRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ReturnSlaveNAKCountRequest") rq = ReturnSlaveNAKCountRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ReturnSlaveBusyCountRequest") rq = ReturnSlaveBusyCountRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ReturnSlaveBusCharacterOverrunCountRequest") rq = ReturnSlaveBusCharacterOverrunCountRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ReturnIopOverrunCountRequest") rq = ReturnIopOverrunCountRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running ClearOverrunCountRequest") rq = ClearOverrunCountRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference log.debug("Running GetClearModbusPlusRequest") rq = GetClearModbusPlusRequest(unit=UNIT) rr = client.execute(rq) print(rr) # assert(rr == None) # not supported by reference # ------------------------------------------------------------------------# # close the client # ------------------------------------------------------------------------# client.close()
def run_sync_client(): # ------------------------------------------------------------------------# # choose the client you want # ------------------------------------------------------------------------# # make sure to start an implementation to hit against. For this # you can use an existing device, the reference implementation in the tools # directory, or start a pymodbus server. # # If you use the UDP or TCP clients, you can override the framer being used # to use a custom implementation (say RTU over TCP). By default they use # the socket framer:: # # client = ModbusClient('localhost', port=5020, framer=ModbusRtuFramer) # # It should be noted that you can supply an ipv4 or an ipv6 host address # for both the UDP and TCP clients. # # There are also other options that can be set on the client that controls # how transactions are performed. The current ones are: # # * retries - Specify how many retries to allow per transaction (default=3) # * retry_on_empty - Is an empty response a retry (default = False) # * source_address - Specifies the TCP source address to bind to # * strict - Applicable only for Modbus RTU clients. # Adheres to modbus protocol for timing restrictions # (default = True). # Setting this to False would disable the inter char timeout # restriction (t1.5) for Modbus RTU # # # Here is an example of using these options:: # # client = ModbusClient('localhost', retries=3, retry_on_empty=True) # ------------------------------------------------------------------------# client = ModbusClient('localhost', port=5020) # from pymodbus.transaction import ModbusRtuFramer # client = ModbusClient('localhost', port=5020, framer=ModbusRtuFramer) # client = ModbusClient(method='binary', port='/dev/ptyp0', timeout=1) # client = ModbusClient(method='ascii', port='/dev/ptyp0', timeout=1) # client = ModbusClient(method='rtu', port='/dev/ptyp0', timeout=1, # baudrate=9600) client.connect() # ------------------------------------------------------------------------# # specify slave to query # ------------------------------------------------------------------------# # The slave to query is specified in an optional parameter for each # individual request. This can be done by specifying the `unit` parameter # which defaults to `0x00` # ----------------------------------------------------------------------- # log.debug("Reading Coils") rr = client.read_coils(1, 1, unit=UNIT) log.debug(rr) # ----------------------------------------------------------------------- # # example requests # ----------------------------------------------------------------------- # # simply call the methods that you would like to use. An example session # is displayed below along with some assert checks. Note that some modbus # 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 asynchronous modbus server (script supplied). # ----------------------------------------------------------------------- # log.debug("Write to a Coil and read back") rq = client.write_coil(0, True, unit=UNIT) rr = client.read_coils(0, 1, unit=UNIT) assert(not rq.isError()) # test that we are not an error assert(rr.bits[0] == True) # test the expected value log.debug("Write to multiple coils and read back- test 1") rq = client.write_coils(1, [True]*8, unit=UNIT) assert(not rq.isError()) # test that we are not an error rr = client.read_coils(1, 21, unit=UNIT) assert(not rr.isError()) # test that we are not an error resp = [True]*21 # If the returned output quantity is not a multiple of eight, # the remaining bits in the final data byte will be padded with zeros # (toward the high order end of the byte). resp.extend([False]*3) assert(rr.bits == resp) # test the expected value log.debug("Write to multiple coils and read back - test 2") rq = client.write_coils(1, [False]*8, unit=UNIT) rr = client.read_coils(1, 8, unit=UNIT) assert(not rq.isError()) # test that we are not an error assert(rr.bits == [False]*8) # test the expected value log.debug("Read discrete inputs") rr = client.read_discrete_inputs(0, 8, unit=UNIT) assert(not rq.isError()) # test that we are not an error log.debug("Write to a holding register and read back") rq = client.write_register(1, 10, unit=UNIT) rr = client.read_holding_registers(1, 1, unit=UNIT) assert(not rq.isError()) # test that we are not an error assert(rr.registers[0] == 10) # test the expected value log.debug("Write to multiple holding registers and read back") rq = client.write_registers(1, [10]*8, unit=UNIT) rr = client.read_holding_registers(1, 8, unit=UNIT) assert(not rq.isError()) # test that we are not an error assert(rr.registers == [10]*8) # test the expected value log.debug("Read input registers") rr = client.read_input_registers(1, 8, unit=UNIT) assert(not rq.isError()) # test that we are not an error arguments = { 'read_address': 1, 'read_count': 8, 'write_address': 1, 'write_registers': [20]*8, } log.debug("Read write registeres simulataneously") rq = client.readwrite_registers(unit=UNIT, **arguments) rr = client.read_holding_registers(1, 8, unit=UNIT) assert(not rq.isError()) # test that we are not an error assert(rq.registers == [20]*8) # test the expected value assert(rr.registers == [20]*8) # test the expected value # ----------------------------------------------------------------------- # # close the client # ----------------------------------------------------------------------- # client.close()
def close(self): if self.socket: self.ioloop.remove_handler(self.socket.fileno()) return ModbusSerialClient.close(self)
class BmsLionModbus: #init def __init__(self, configuration): self.config = configuration self.client = 0 self.busy = 0 self.device = '' self.datalayer = 0 self.thread = 0 self.connection = 0 self.connected = 0 self.terminate_flag = 0 self.running_flag = 0 self.commands = ['v','t','b','c','e','s'] self.logfile = '' self.logfileH = '' self.filemode = False self.clearFileFlag = False #join def terminate(self): self.terminate_flag = 1 self.thread.join() #module can receive GET messages def http_get(self, key, name, value): # we receive only string at the moment and pass it over serial (=value) # we only get further when key = pass if key != "pass": return if (name == "download"): return "not implemented yet!" # TODO: sd card readout # self.datalayer.allfile if name == "configload": self.readConfig() if name == "configsave": print("Will send following config regs to CPU module:") #struct to 16bit register conversion (big endian) regs = [ int(value[i:i+4],16) for i in range(0, len(value), 4)] #struct to 16bit register conversion (little endian) #regs = [ int(value[i:i+2],16)+int(value[i+2:i+4],16)*256 for i in range(0, len(value), 4)] print(regs) try: rq = self.client.write_registers(4000,regs,unit=1) print ("Config registers written!") except Exception as e: print ("Could not write CONFIG registers!") return '' def status(self): return "OK, PEC: "+str(self.datalayer.cpuPEC)+"%" # menu items offered by module # each menu item is connected with a view def menu(self): return { 'view_modulesm' :'overview', 'view_settingsm':'settings', } #items visible on each page def sticky(self): return {} #fork def start(self): self.datalayer = Datalayer() self.datalayer.sqllog = 0 if 0 == self.running_flag: self.thread = threading.Thread(target=self.run) self.terminate_flag = 0 self.thread.start() self.datalayer.message = "started new reading process" else: self.datalayer.message = "one process already running" def run(self): self.running_flag = 1 currentMod = 0 while not self.terminate_flag: if not self.connected: for self.device in self.config['ports']: try: self.datalayer.status = 'opening '+self.device self.client = ModbusSerialClient(method = "rtu", port=self.device, baudrate=self.config['modbus_speed'], stopbits=1, bytesize=8, timeout=self.config['modbus_timeout']) time.sleep(0.1) if not self.client.connect(): self.connected = 0 self.datalayer.status = 'retry in 2s, no connection '+self.device time.sleep(1) continue self.connected = 1 self.datalayer.receivecounter = 0 self.datalayer.status = 'connected to '+self.device except Exception as e: print(str(e)) self.connected = 0 time.sleep(1) continue if not self.readConfig(): continue # must exit "connection trying loop" because when it gets here --> successfully made connection break # this is needed when for loop per device finishes # we cannot continue without proper connection if not self.connected: print ("No success with connection. Will test configured devices again...") time.sleep(1) continue # here is the "worker code" error = 0 try: if self.busy: time.sleep(self.config['sleeptime_comm']) continue self.busy = 1; rq = self.client.read_holding_registers(1000+currentMod*100,30,unit=1) #if hasattr(rq, 'registers'): self.datalayer.modulesRegsParse(currentMod, rq.registers) self.datalayer.receivecounter += 1 currentMod += 1 if currentMod == self.datalayer.numModules: currentMod = 0 self.busy = 0; # configurable delay time.sleep(self.config['sleeptime_comm']) self.datalayer.status = "connected: "+self.device except AttributeError: self.datalayer.status = 'Read holding registers exception (attr error): '+self.device print(self.datalayer.status) self.busy = 0; except ModbusException as e: self.busy = 0; self.datalayer.status = 'Read holding registers exception: '+self.device print(self.datalayer.status) self.connected = 0 self.client.close() time.sleep(1) #cleanup only if connection was established... if self.connected: self.client.close() self.connected = 0 self.datalayer.message = "closing connection, thread exit" self.running_flag = 0 def readConfig(self): # read config print ("MODBUS connected - will read config 58 regs") timeout = 10 while (self.busy == 1) and (timeout > 0): print ("Waiting for connection 100ms") timeout -= 1 time.sleep(0.1) if timeout == 0: print("Timeout - no configuration read") return False try: self.busy = 1; rq = self.client.read_holding_registers(4000,58,unit=1) self.datalayer.configRegsParse(rq.registers) self.busy = 0; except Exception as e: print ("Could not read BMS config! Maybe some other program blocks the connection?") self.connected = 0 self.busy = 0; return False print ("Config successfully loaded!") return True
words_per_channel += 1 rval = response.registers for i in range(len(files)): files[i][1].write(str(bin(rval[i]))[2:]) finally: finalize_runinfo(rtime) for s, f in files: f.close() if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-p', '--port', default='/dev/ttyACM1', help="Serial Port",) parser.add_argument('-b', '--baudrate', default=256000, type=int, help="Baud Rate. Not applicable to USB CDC links") parser.add_argument('source', choices=['entropy', 'all', 'lfsr16', 'lfsr32', 'lfsr64', 'sg16', 'sg32', 'sg64', 'asg16', 'asg32', 'asg64', 'entropium', 'rand'], default='entropy', help='Data stream to use') args = parser.parse_args() mclient = ModbusClient(method='rtu', port=args.port, timeout=0.1, baudrate=args.baudrate) mclient.connect() try: acquire(args.source) finally: mclient.close()
class comClient: def __init__(self): self.__parseConfig() # Configure logging on the client logging.basicConfig() self.log = logging.getLogger() # Change to DEBUG for full information during runtime self.log.setLevel(logging.INFO) # Setup and Open the connection self.client = ModbusClient(**self.comSettings) def __parseConfig(self): try: with open("../../cfg/connection.yaml", "r") as f: # safely opens the file and gets the text config = yaml.load(f) # parses the data into python self.comSettings = config # saves config to member variable except IOError: print ("Failed to set config from file. Falling back to default values:") self.comSettings = { "method": "rtu", "port": "COM3", # FALL BACK VALUES ONLY "stopbits": 1, "bytesize": 8, "parity": "N", "baudrate": 9600, "timeout": 1, } def dataHandler(self, operation, *data): if operation == "r": for i in range(3): r = self.__readData() # Attempt to read MODBUS data if r != IOError: # If success, carry on break elif i == 2: # Retry 3 times on failure raise SystemExit("Modbus Error: Failed 3 Attemps") time.sleep(5) return r elif operation == "w": try: self.__writeData(data[0]) # Attempt to write MODBUS data except IndexError: raise SystemExit("No data passed to write!") return else: raise ValueError("Invalid Operation") def __readData(self): # Function to write data to controller try: self.client.connect() # REMEMBER: Controller is unit 0x01 r = self.client.read_holding_registers(0, 4, unit=0x01) self.client.close() return r except: print "Modbus Error: Read Connection Failed" return IOError def __writeData(self, op): # Set to write data to the controller output (MODBUS HR 3) self.client.connect() w = self.client.write_register(3, op, unit=0x01) self.client.close() return w
# Andrew Elwell <*****@*****.**> 2013-09-01 from pymodbus.client.sync import ModbusSerialClient as ModbusClient import time result = {} result['timestamp'] = time.time() client = ModbusClient(method='rtu', port='/dev/ttyUSB0', baudrate=9600, stopbits=1, parity='N', bytesize=8, timeout=1) client.connect() # can'r read the whole lot in one pass, so grab each chunk # addr / descriptions lifted from http://code.google.com/p/pvbeancounter/source/browse/trunk_v2/PVSettings/Device_Growatt.xml rr = [] rr = client.read_input_registers(2,3) result['PV_W'], result['PV_V'], result['PV_A'] = rr.registers rr = [] rr = client.read_input_registers(12,3) result['Out_W'], result['AC_Hz'], result['AC_V'] = rr.registers #rr = client.read_input_registers(17, 1) #result['wtf2'] = rr.registers[0] #rr = client.read_input_registers(29,3) #print rr.registers client.close() print result,
t_date = format(strftime('%Y%m%d')) t_time = format(strftime('%H:%M')) pv_volts=0.0 pv_power=0.0 Wh_today=0 current_temp=0.0 cmo_str='None' for i in range(NoInvert): # Read data from inverter inverter = ModbusClient(method='rtu', port='/dev/ttyUSB'+str(i), baudrate=9600, stopbits=1, parity='N', bytesize=8, timeout=1) inverter.connect() rr = inverter.read_input_registers(1,27) inverter.close() value=rr.registers[2] pv_volts=pv_volts+(float(value)/10) value=rr.registers[11] pv_power=pv_power+(float(value)/10) value=rr.registers[26] Wh_today=Wh_today+(float(value)*100) if OWMKey<>'': owm = OWM(OWMKey) if owm.API_online: obs = owm.weather_at_coords(OWMLat, OWMLon) w = obs.get_weather() w_stat = w.get_detailed_status() temp = w.get_temperature(unit='celsius') current_temp = temp['temp']