class RegisterWriter(): def __init__(self, host, port): self.mb_client = ModbusClient(host, port=port) self.mb_client.connect() def write(self, displayName, address, value, dtype=None, bits=None): if dtype: builder = BinaryPayloadBuilder(wordorder=Endian.Big) # This code trick generates and calls methods of PayloadBuilder, # like `builder.add_16bit_int(r['value']) # where 16 = r[bits], int = r['typename'] if dtype == 'string': method_name = "add_string" else: method_name = "add_{0}bit_{1}".format(bits, dtype) getattr(builder, method_name)(value) payload = builder.build() logging.debug("Packed value '{0}' with method {1} into {2}".format( value, method_name, payload)) registers = builder.to_registers() self.mb_client.write_registers(address, registers, unit=1) # self.mb_client.write_registers(address, payload, skip_encode=True, unit=UNIT) else: logging.debug("Wrote value '{0}' to 16bit register as {1}".format(value, int(value))) self.mb_client.write_register(address, int(value), unit=UNIT)
def setDeviceStatus(self, postmsg): setDeviceStatusResult = True try: client = ModbusTcpClient(self.get_variable('address'),port=502) client.connect() if (self.get_variable('model')=='VC1000'): if 'heat_setpoint' in postmsg.keys(): client.write_register(6,int(self.far2cel(float(postmsg.get('heat_setpoint')))*100.0),unit=self.get_variable('slave_id')) if 'cool_setpoint' in postmsg.keys(): client.write_register(6,int(self.far2cel(float(postmsg.get('cool_setpoint')))*100.0),unit=self.get_variable('slave_id')) if 'flap_override' in postmsg.keys(): if postmsg.get('flap_override') == 'ON' or postmsg.get('flap_override') == True: client.write_register(159,1,unit=self.get_variable('slave_id')) elif postmsg.get('flap_override') == 'OFF' or postmsg.get('flap_override') == False: client.write_register(159,0,unit=self.get_variable('slave_id')) if 'flap_position' in postmsg.keys(): client.write_register(160,int(postmsg.get('flap_position')),unit=self.get_variable('slave_id')) elif (self.get_variable('model')=='M1000'): if 'heat_setpoint' in postmsg.keys(): client.write_register(187,int(self.far2cel(float(postmsg.get('heat_setpoint')))*100.0),unit=self.get_variable('slave_id')) if 'cool_setpoint' in postmsg.keys(): client.write_register(188,int(self.far2cel(float(postmsg.get('cool_setpoint')))*100.0),unit=self.get_variable('slave_id')) if 'outside_damper_position' in postmsg.keys(): client.write_register(274,int(postmsg.get('outside_damper_position')),unit=self.get_variable('slave_id')) if 'bypass_damper_position' in postmsg.keys(): client.write_register(275,int(postmsg.get('bypass_damper_position')),unit=self.get_variable('slave_id')) if 'fan_status' in postmsg.keys(): if postmsg.get('fan_status') == 'ON' or postmsg.get('fan_status') == True: client.write_register(130,2,unit=self.get_variable('slave_id')) elif postmsg.get('fan_status') == 'OFF' or postmsg.get('fan_status') == False: client.write_register(130,1,unit=self.get_variable('slave_id')) if 'cooling_status' in postmsg.keys(): if postmsg.get('cooling_status') == 'ON': client.write_registers(124,[1,2,2,2],unit=self.get_variable('slave_id')) elif postmsg.get('cooling_status') == 'OFF': client.write_registers(124,[0,1,1,1],unit=self.get_variable('slave_id')) if 'cooling_mode' in postmsg.keys(): if postmsg.get('cooling_mode') == 'None': client.write_register(10,0,unit=self.get_variable('slave_id')) elif postmsg.get('cooling_mode') == 'STG1': client.write_register(10,1,unit=self.get_variable('slave_id')) elif postmsg.get('cooling_mode') == 'STG2': client.write_register(10,2,unit=self.get_variable('slave_id')) elif postmsg.get('cooling_mode') == 'STG3': client.write_register(10,3,unit=self.get_variable('slave_id')) elif postmsg.get('cooling_mode') == 'STG4': client.write_register(10,4,unit=self.get_variable('slave_id')) if 'heating' in postmsg.keys(): client.write_register(129,int(postmsg.get('heating')),unit=self.get_variable('slave_id')) client.close() except: try: client.close() except: print('Modbus TCP client was not built successfully at the beginning') setDeviceStatusResult=False return setDeviceStatusResult
def loop_process(): # Main Process (template = flip-flop) err_count = 0 registre_count = 10 while True: sleep(1) try: client = ModbusTcpClient(modbus_server_ip, modbus_server_port) coils = client.read_coils(0, count=registre_count, unit=UNIT) coils = coils.bits[:registre_count] # flipping booleans from list coils coils = [not i for i in coils] client.write_coils(0, coils) registers = client.read_holding_registers(0, count=registre_count, unit=UNIT) registers = registers.registers[:registre_count] registers = [i + 1 for i in registers] client.write_registers(0, registers, unit=UNIT) updateGPIO(coils, registers) except Exception as err: print('[error] %s' % err) err_count += 1 if err_count == 5: print('[error] 5 errors happened in the process ! exiting...') sys.exit(1)
def post(self): query = self.reqparse.parse_args() client = ModbusClient(query['ip'], query['port']) client.connect() data = query['data'] start_address = query['start_address'] builder.reset() for vol in data: print(vol) builder.add_32bit_int(vol) parsed = builder.build() parsed = parsed[1::2] print(parsed) if query['type_prefix'] == ModbusTypePrefix.COIL.value: client.write_coils(start_address, parsed, skip_encode=True, unit=1) elif query['type_prefix'] == ModbusTypePrefix.HOLDING_REGISTER.value: client.write_registers(start_address, parsed, skip_encode=True, unit=1) client.close() return {'result': True}
def upmu(upmu, sw_value): IP = '131.243.41.14' PORT = 503 id = 2 if upmu == '123p': register = int(2) if upmu == '4': register = int(3) client = ModbusClient(IP, port=PORT) try: client.write_registers(register, int(sw_value), unit=id) print(f'uPMU{upmu} to {sw_value} ~~ time:', client.read_input_registers(1, count=1, unit=id).registers[0]) print('epoch:', time.time()) print(dt.datetime.fromtimestamp(time.time())) print('All Done.', client.read_input_registers(1, count=1, unit=id).registers[0]) except Exception as e: print(e) finally: client.close() print('client closed [uPMU]') return
def initdb(): try: client = ModbusTcpClient(modbus_server_ip, modbus_server_port) # Coils table # 0 : eolienne status (manual) # 1 : eolienne status (wind speed control, should be between 15km/h and 90km/h) # (corresponding to 4m/s and 25m/s) # 25 : eolienne broken status # # Holding registers table # 0 : wind speed (m/s) # 1 : power production (kW) # 2-9 : not used # 10 : wind min speed (4m/s) # 11 : wind max (25 m/s) client.write_coils(0, [True, True], unit=UNIT) client.write_coils(25, [False], unit=UNIT) client.write_registers(0, [speed, 0], unit=UNIT) client.write_registers(10, [4, 25], unit=UNIT) except Exception as err: print '[error] Can\'t init the Modbus coils' print '[error] %s' % err print '[error] exiting...' sys.exit(1)
class TestMbTcpClass0(unittest.TestCase): read_values = range(0xAA50, 0xAA60) write_values = range(0xBB50, 0xBB60) def setUp(self): self.client = ModbusTcpClient(SERVER_HOST) self.client.connect() def tearDown(self): self.client.close() def test_read_holding_registers(self): rv = self.client.read_holding_registers(0, 16) self.assertEqual(rv.function_code, 0x03) self.assertEqual(rv.registers, self.read_values) def test_read_holding_registers_exception(self): rv = self.client.read_holding_registers(16, 1) self.assertEqual(rv.function_code, 0x83) self.assertEqual(rv.exception_code, 0x02) def test_write_holding_registers(self): rq = self.client.write_registers(0, self.write_values) self.assertEqual(rq.function_code, 0x10) rr = self.client.read_holding_registers(0, 16) self.assertEqual(rr.registers, self.write_values) rq = self.client.write_registers(0, self.read_values) self.assertEqual(rq.function_code, 0x10) def test_write_holding_registers_exception(self): rq = self.client.write_registers(16, [0x00]) self.assertEqual(rq.function_code, 0x90) self.assertEqual(rq.exception_code, 0x02)
class ModbusDevice: def __init__(self, ip: str, port: int = 502): self.client = ModbusTcpClient(ip, port=502) def read(self, reg: Enum, count=2) -> List[int]: return self.client.read_input_registers(reg.value, count, unit=3).registers def write(self, reg: Enum, value: int) -> None: self.client.write_registers(reg.value, (value // 65536, value % 65536), unit=3) @staticmethod def decode_s32(value: List[int]) -> int: if value[0] == 32768 and value[1] == 0: return 0 # To enforce signed decoding, there seems to be no better way. return struct.unpack( '>i', bytes.fromhex(format(value[0], '04x') + format(value[1], '04x')))[0] @staticmethod def decode_u32(value: List[int]) -> int: if value[0] == 32768 and value[1] == 0: return 0 return int(format(value[0], '04x') + format(value[1], '04x'), 16)
class Modbus_client(Thread): def __init__(self, host, port): super(Modbus_client, self).__init__() self.host = host self.port = port self.client = ModbusClient(self.host, port=self.port) def run(self): print("starting Modbus client on {}:{}".format(self.host, self.port)) self.client.connect() def write_to_registers(self, startingaddress, values): converted_values = [] for value in values: if type(value) != float: try: f_value = float(value) except ValueError: print("Unknown value: {}".format(value)) else: f_value = value converted_values.append(int(f_value * 100)) self.client.write_registers(startingaddress, converted_values) def close(self): self.client.close()
def open(response: Response): try: client = ModbusTcpClient(host='192.168.1.15', port='5020') client.connect() client.write_registers(200, 1) except: response.status_code = status.HTTP_404_NOT_FOUND return {"status": "Door closed"} return {"status": "Door opened"}
class ModbusClient(object): """Establishes a secure connection with the Modbus slave. Will be able to read and write to all of the available I/O.""" def __init__(self, ip='192.168.2.17'): self.ip = ip self.client = ModbusTcpClient(self.ip) self.connection = self.client.connect() def isConnected(self): """Returns the connection status. Return: True if connected, False if not.""" return self.connection def sendInt(self, value, address): """Send a 32 bit value to the first modbus unit. Parameters: value and address where the value will be stored in. Return: Result if it was successful or not.""" builder = BinaryPayloadBuilder(byteorder=Endian.Big) builder.add_32bit_int(value) payload = builder.build() result = self.client.write_registers(address, payload, skip_encode=True, unit=1) return result def sendFloat(self, value, address): """Send a 32 bit value to the first modbus unit. Parameters: value and address where the value will be stored in. Return: Result if it was successful or not.""" builder = BinaryPayloadBuilder(byteorder=Endian.Big) builder.add_32bit_float(value) payload = builder.build() result = self.client.write_registers(address, payload, skip_encode=True, unit=1) return result def read(self, address): """Reads from a given address from the first modbus unit. Parameters: address where the value will be read from. Return: The read value in string format.""" result = self.client.read_holding_registers(address, 2, unit=1) decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big) return str(decoder.decode_32bit_float()) def close(self): """Closes the connection with the port. Return: True when the connection is closed.""" self.client.close() return True
class Client: def __init__(self): self.client = None self.handle = None self.ip = '127.0.0.1' self.port = 502 def setup(self, config): self.handle = config self.ip = config['ipv4']['value'] self.port = config['port']['value'] self.client = ModbusTcpClient(self.ip, self.port) def execute(self, fc, addr, length=1, values=None): result = None if fc == 1: temp = self.client.read_coils(addr, length) result = [] for i in range(temp.byte_count): t2 = temp.bits[i * 16:(i + 1) * 16] result.append(''.join([str(int(x)) for x in t2])) elif fc == 2: temp = self.client.read_discrete_inputs(addr, length) result = [] for i in range(temp.byte_count): t2 = temp.bits[i * 16:(i + 1) * 16] result.append(''.join([str(int(x)) for x in t2])) elif fc == 3: temp = self.client.read_holding_registers(addr, length).registers result = ['{0:016b}'.format(x) for x in temp] elif fc == 4: temp = self.client.read_input_registers(addr, length).registers result = ['{0:016b}'.format(x) for x in temp] elif fc == 5: if values: self.client.write_coil(addr, values[0]) elif fc == 6: if values: self.client.write_register(addr, values[0]) elif fc == 15: if values: self.client.write_coils(addr, values) elif fc == 16: if values: self.client.write_registers(addr, values) return result def update_config(self, conf): self.ip = conf['ipv4']['value'] self.port = conf['port']['value'] self.client = ModbusTcpClient(self.ip, self.port) self.handle = conf def connect(self): return self.client.connect()
class communication: def __init__(self): self.client = None def connectToDevice(self, address): """Connection to the client - the method takes the IP address (as a string, e.g. '192.168.1.11') as an argument.""" self.client = ModbusTcpClient(address) 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, int(len(data) / 2)): message.append((data[2 * i] << 8) + data[2 * i + 1]) #To do!: Implement try/except self.client.write_registers(0, message) 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!: Improve try/except to be more robust #Get status from the device response = self.client.read_input_registers(0, numRegs) connection_exception = False while isinstance(response, ModbusIOException) or connection_exception: try: response = self.client.read_input_registers(0, numRegs) connection_exception = False except ConnectionException: connection_exception = True print('WARNING: comModbusTCP.py ConnectionException, retrying') time.sleep(0.1) #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 store_file(Filename, starting): MAX_FILE_SIZE = 3204700 wordlist = [] if (os.path.isfile(Filename) & (get_IP() != "")): filesize = os.path.getsize(Filename) client = ModbusClient(get_IP(), DPORT) client.connect() if (filesize > MAX_FILE_SIZE - starting): print("Error: File is too big. Max size must be " + MAX_FILE_SIZE + "bytes") else: write_screen("Writing file to PLC...") pos = 0 #kk=[] with open(Filename, "rb") as f: while True: byteread = f.read(1) if not byteread: if (pos % 2 == 1): wordlist.append(a) break if ((pos > 0) & (pos % 128 == 0)): dot() rq = client.write_registers(starting, wordlist, unit=0x01) starting += 64 wordlist = [] # kk=[] # kk.append(ord(bl)) #LITTLE-ENDIAN if (pos % 2 == 0): a = ord(byteread) pos += 1 else: a = 256 * a + ord(byteread) wordlist.append(a) pos += 1 a = 0 rq = client.write_registers(starting, wordlist, unit=0x01) client.close() write_screen("\nFile " + Filename + "(" + str(filesize) + " bytes) stored in " + str(get_IP())) else: print("\nError: File or IP do NOT exist. Exiting") print("\nFile: " + Filename) print("\nIP: " + get_IP())
class Gripper: def __init__(self, address): self.client = ModbusTcpClient(address) self.lock = threading.Lock() def disconnect(self): self.client.close() def activate(self): self.send_cmd(self.gripper_cmd(1, 0, 0, 0, 0, 0)) sleep(5) def open(self): self.send_cmd(self.gripper_cmd(1, 1, 0, 0xFF, 0xFF, 0xFF)) def close(self): self.send_cmd(self.gripper_cmd(1, 1, 0, 0x00, 0xFF, 0xFF)) @staticmethod def gripper_cmd(ract, rgto, ratr, rpr, rsp, rfr): cmd = [0, 0, 0, 0, 0, 0] cmd[0] = (ract & 0x1) | ((rgto << 0x3) & 0x8) | ((ratr << 0x4) & 0x10) cmd[3] = rpr cmd[4] = rsp cmd[5] = rfr # for i in cmd: print(hex(i)) return cmd def send_cmd(self, data): if len(data) % 2 == 1: data.append(0) message = [] for i in range(0, int(len(data) / 2)): message.append((data[2 * i] << 8) + data[2 * i + 1]) with self.lock: self.client.write_registers(0, message) def get_status(self, nbytes): nregs = int(ceil(nbytes / 2.0)) with self.lock: response = self.client.read_input_registers(0, nregs) output = [] for i in range(0, nregs): output.append((response.getRegister(i) & 0xFF00) >> 8) output.append(response.getRegister(i) & 0x00FF) return output
def spam_modbus_register_values(modbus_ip, seconds, register, register_values): client = ModbusTcpClient(modbus_ip) if not client.connect(): print("Der Modbus Server läuft nicht.") sys.exit(1) print("Setze die Werte {} \t auf Register {} für {} Sekunden".format( register_values, register + 1, seconds)) time_end = time.time() + seconds while time.time() < time_end: client.write_registers(register, register_values) client.close()
class ComModbusTcp: def __init__(self): self.client = None self.lock = threading.Lock() def connectToDevice(self, address): """ Connection to the client - the method takes the IP address (as a string, e.g. '192.168.1.11') as an argument. """ self.client = ModbusTcpClient(address) 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 """ # 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]) # TODO: Implement try/except with self.lock: self.client.write_registers(0, message) 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)) # TODO: Implement try/except # Get status from the device with self.lock: response = self.client.read_input_registers(0, numRegs) # 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 communication: def __init__(self): self.client = None self.lock = threading.Lock() def connectToDevice(self, address): """Connection to the client - the method takes the IP address (as a string, e.g. '192.168.1.11') as an argument.""" self.client = ModbusTcpClient(address) 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 with self.lock: self.client.write_registers(0, message) 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 with self.lock: response = self.client.read_input_registers(0, numRegs) # 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 changeCurrent(self, current): def limitChargeStationCurrent(num, minimum=self.minimumCurrent, maximum=self.maximumCurrent): return max(min(num, maximum), minimum) chargeStationModbus = ModbusClient(self.ip, port=502, unit_id=1, auto_open=True, auto_close=True) time.sleep(0.1) builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big) builder.add_32bit_float(limitChargeStationCurrent(current)) registers = builder.to_registers() chargeStationModbus.write_registers(1210, registers, unit=1) chargeStationModbus.close()
def sim_start_pause_stop(sim_length_min): IP = '131.243.41.14' PORT = 503 id = 2 # Connect to client client = ModbusClient(IP, port=PORT) try: # Read simulaiton time sim_start = client.read_input_registers(1, count=1, unit=id).registers[0] print('simulation start time:',sim_start) # start recording data (sim flag on) client.write_registers(int(1), int(1), unit=id) client.write_registers(int(1), int(3), unit=id) #sets simulation flag to 1 (ON) w = 1 while w > 0: sim_cur = client.read_input_registers(1, count=1, unit=id).registers[0] if sim_cur - sim_start >= sim_length_min*60: break print('simulation end time',sim_cur) client.write_registers(int(1), int(0), unit=id) print('All Done.',client.read_input_registers(1, count=1, unit=id).registers[0]) except Exception as e: print(e) finally: client.close() print('client closed') return
def sim_stop(): IP = '131.243.41.14' PORT = 503 id = 2 client = ModbusClient(IP, port=PORT) try: client.write_registers(int(1), int(0), unit=id) print('simulation stop time:',client.read_input_registers(1, count=1, unit=id).registers[0]) print('epoch:',time.time()) print(dt.datetime.fromtimestamp(time.time())) print('All Done.',client.read_input_registers(1, count=1, unit=id).registers[0]) except Exception as e: print(e) finally: client.close() print('client closed [stop]') return
def config_thermocouple(client: ModbusTcpClient, name, AIN='AIN0'): # cfg = { # AIN + "_EF_INDEX": 24, # AIN + "_EF_CONFIG_A": 2, # AIN + "_EF_CONFIG_B": 60052, # AIN + "_EF_CONFIG_D": 1.0, # AIN + "_EF_CONFIG_E": 0.0 # } cfg = { 8198: 24, 9298: 2, 9598: 60052, 10198: 1.0, 10498: 0.0 } for addr, val in cfg.items(): ba = bytearray(struct.pack(">f", val)) print(name, ba) client.write_registers(addr, [int.from_bytes(ba[:2], 'big'), int.from_bytes(ba[2:], 'big')]) print(name, _convert_to_32_float(int.from_bytes(ba[:2], 'big'), int.from_bytes(ba[2:], 'big')))
def set_switches(dfsw_in, dfsw_out, test_ID): IP = '131.243.41.14' PORT = 503 id = 2 # Connect to client client = ModbusClient(IP, port=PORT) # Get indeces & assign values sw_idx = [] scales = {} for i in range(dfsw_in.shape[0]): if dfsw_in.Description.values[i][:3] == 'sw_': sw_idx.append(i) if 'scale_flexgrid' in dfsw_in.Description.values[i]: scales['flexgrid'] = { 'register': dfsw_in['Register'][i], 'value': dfsw_in[test_ID][i] } if 'scale_loadrack' in dfsw_in.Description.values[i]: scales['loadrack'] = { 'register': dfsw_in['Register'][i], 'value': dfsw_in[test_ID][i] } mtx = [] mtx_register = [] for i in sw_idx: mtx.append(dfsw_in[test_ID][i]) mtx_register.append(dfsw_in['Register'][i]) try: # Write the scaling client.write_registers(scales['flexgrid']['register'], int(scales['flexgrid']['value']), unit=id) client.write_registers(scales['loadrack']['register'], int(scales['loadrack']['value']), unit=id) print('scales set') # write switch positions for config for i in range(len(mtx)): client.write_registers(mtx_register[i], int(mtx[i]), unit=id) print('switches set') except Exception as e: print(e) finally: client.close() print('client closed') return
def write_multiple_registers(self, command): parser = argument_parser() command = 'write_multiple_registers ' + command spec = parser.parse_args(command.split()) builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big) for func, value in spec.values: getattr(builder, func)(value) payload = builder.build() response = _ModbusClient.write_registers( self, spec.address, payload, skip_encode=True, unit=spec.unit_id) return response
def activate(self): rospy.init_node('niryo_node', anonymous=False) while not rospy.is_shutdown(): if (self.activate_plc == "Activated"): rospy.loginfo( "Niryo will do other action, PLC will be deactivated") self.pub.publish("plc_deactivate") else: rospy.loginfo( "PLC hasn't been activated, Niryo will activate PLC") self.pub.publish("Activate_plc") client = ModbusClient("192.168.1.7", port=502) client.connect() UNIT = 0x1 print("Escritura de salidas") rq = client.write_coil(0, [True] * 8, unit=UNIT) rr = client.read_coils(0, 8, unit=UNIT) print("Las salidas Q0.0-Q0.7 ", rr.bits) print("Leer entradas") rr = client.read_discrete_inputs(0, 8, unit=UNIT) print("Las entradas I0.0-I0.7 son ", rr.bits) print("Escritura de un HR") rq = client.write_register(0, 15, unit=UNIT) rr = client.read_holding_registers(0, 1, unit=UNIT) print("HR0 = ", rr.registers) print("Escritura de varios HR") rq = client.write_registers(1, [35] * 10, unit=UNIT) rr = client.read_holding_registers(1, 10, unit=UNIT) print("HR0 = ", rr.registers) print("Escritura de varios HR") rq = client.write_registers(11, [43] * 5, unit=UNIT) rr = client.read_holding_registers(0, 15, unit=UNIT) print("HR0 = ", rr.registers) client.close() rospy.sleep(1)
def mb_restore(target): client = ModbusTcpClient(target) try: attack = client.write_registers(0x109c, 256) status = str(attack) except ConnectionException: status = "Error: No connection to target" pass except (ModbusIOException, ParameterException, ModbusException, InvalidMessageReceivedException, MessageRegisterException, NoSuchSlaveException, NotImplementedException): status = "Error:" + str(sys.exc_info()[0]) pass client.close() return status
class ModbusUtility(): def __init__(self, ip): self.modcli = ModbusTcpClient(ip) @staticmethod def getReg(reg, index=0): # Registers are stored without decimal points. Their values represent # the number multiplied by 100 so we undo that to get the real value # We assume desired register is first element, pass in optional index to change return (float(reg[index]) / 100) @staticmethod def setReg(data): # Since register data is stored without decimals and multiplied by 100 that is # what we supply return (int(data * 100)) def PrintAllRegisters(self): print("Printing registers...") for key in REG_DICT.keys(): data = self.ReadRegister(key) print("Register [{}]: {}".format(key, data)) def ReadRegister(self, name): t = REG_DICT[name]["type"] # Current register type o = REG_DICT[name]["offset"] # Current register offset s = REG_DICT[name]["size"] # Current register size in bytes. # If the size is greater the 2 bytes unpack it like it is a float. # Really we should also check that this is a float but it doesn't matter since # our system only has 3 registers that are 4 bytes long and they are all floats if (s > 2): data = self.modcli.read_holding_registers(o, s, unit=1).registers reg = struct.unpack( ">f", data[0].to_bytes(2, "big") + data[2].to_bytes(2, "big")) return (reg[0]) data = self.modcli.read_holding_registers(o, 1, unit=1) return (self.getReg(data.registers)) def WriteRegister(self, name, num): o = REG_DICT[name]["offset"] # Current register offset s = REG_DICT[name]["size"] / 2 # Current register size if (s > 1): data = struct.unpack("HH", struct.pack("=f", num)) # Sending these backwards is a concious decision. Unpack always returns # them in 'backwards' order. self.modcli.write_registers(o, data[1]) self.modcli.write_registers(o + 1, data[0]) else: data = num self.modcli.write_registers(o, self.setReg(data))
def scan(): parser = argparse.ArgumentParser(description = "Write all holding registries on a TCP MODBUS Slave") parser.add_argument("ip", help="IP address of the slave") parser.add_argument("-p", "--port", dest="port", help="Modbus Port. Defaults to 502", type=int, metavar="PORT", default=502) parser.add_argument("-u", "--uid", dest="uid", help="Modbus Unit ID. Defaults to 1", type=int, metavar="UID", default=1) parser.add_argument("-sa", "--start-address", dest="start_address", help="Starting Address for the writer. Defaults to 1", type=int, metavar="START", default=1) parser.add_argument("-ea", "--end-address", dest="end_address", help="Ending Address for the writer. Defaults to 65535", type=int, metavar="END", default=65535) parser.add_argument("-v", "--value", dest="value", help="Value that will be written. Defaults to 7777", type=int, metavar="VALUE", default=7777) args = parser.parse_args() try: ip = args.ip except IndexError: print "ERROR: No target given\n\n" parser.print_help() exit() # ip address format verification if not validate_ipv4(ip): print "ERROR: IP address is invalid\n\n" parser.print_help() exit() print 'Connecting to %s...' % ip, # connect to modbus slave client = ModbusTcpClient(ip, args.port) client.connect() if client.socket == None: print "ERROR: Could not connect to %s." %ip exit() print ' Connected.' # TODO add ETA mechanism results = [] addr = 1 for addr in range(args.start_address, args.end_address): hr = client.write_registers(addr, args.value, unit=args.uid) # unit value is device id of the slave (UID) if hr.function_code == 16: # if we succeeded writing stuff. code = 0x10 results.append(addr) # if it fails, hr.function = 144 (0x90), cf modbus doc client.close() print 'Register writing is finished (%d addresses were tried)' % (args.end_address-args.start_address+1) print 'Writing was successful on these %d addresses:' % len(results) print results
def writeMBholdingregisters(clientIP, register, valuelist): from pymodbus.client.sync import ModbusTcpClient, ConnectionException client = ModbusTcpClient(clientIP) try: rawresult = client.write_registers(register, valuelist) except ConnectionException: statuscode = 7 else: if 'exception_code' in rawresult.__dict__: statuscode = rawresult.exception_code values = [] else: statuscode = 0 values = valuelist # result = client.read_holding_registers(register, len(valuelist)) client.close() result = {'message': messagefrommbstatuscode(statuscode), 'statuscode': statuscode, 'values': values} return result
class DaikinModbusClient: def __init__(self, host, port, slave_id): self._host = host self._port = port self._slave_id = slave_id self.__init_modbus_client() def __init_modbus_client(self): self.__modbus_client = ModbusTcpClient(self._host, port=self._port) self.__modbus_client.connect() def _read_input_cells(self, address, count): result = self.__modbus_client.read_input_registers(address- 1, count, unit=self._slave_id) return result.registers def _read_holding_cells(self, address, count): result = self.__modbus_client.read_holding_registers(address- 1, count, unit=self._slave_id) return result.registers def read_cells(self, register_type, address, count): cells = None if(register_type==REGISTER_TYPE_INPUT): cells = self._read_input_cells(address, count) elif(register_type==REGISTER_TYPE_HOLDING): cells = self._read_holding_cells(address, count) else: raise("Invalid register_type") logging.debug(register_type, address, count,cells) return cells def write_cell(self, address, cell): logging.debug('write_cell: ', address, cell) result = self.__modbus_client.write_register(address - 1, cell, unit=self._slave_id) return result def write_cells(self, address, cells): logging.debug('write_cells: ', address, cells) result = self.__modbus_client.write_registers(address - 1, cells, unit=self._slave_id) return result
def writeMBholdingregisters(clientIP, register, valuelist): from pymodbus.client.sync import ModbusTcpClient, ConnectionException client = ModbusTcpClient(clientIP) try: rawresult = client.write_registers(register, valuelist) except ConnectionException: statuscode = 7 else: if 'exception_code' in rawresult.__dict__: statuscode = rawresult.exception_code values = [] else: statuscode = 0 values = valuelist # result = client.read_holding_registers(register, len(valuelist)) client.close() result = { 'message': messagefrommbstatuscode(statuscode), 'statuscode': statuscode, 'values': values } return result
class Connection(): def __init__(self, indicator_list, coil_on_list, coil_off_list, command_list, coil_list, port, method="rtu", timeout=0.1, unit=0x01): self.unit = unit self.indicator_list = indicator_list self.coil_on_list = coil_on_list self.coil_off_list = coil_off_list self.coil_list = coil_list self.command_list = command_list self.lock = threading.Lock() if method == "rtu": self.client = ModbusSerialClient(method=method, port=port, baudrate=19200, stopbits=1, bytesize=8, timeout=timeout) elif method == "tcp": self.client = ModbusTcpClient(host=port) def translate(self, command): self.lock.acquire() self.client.connect() print self.client.connect() # input registers if command.split("_")[0] == "IReg": rr = self.client.read_input_registers(self.indicator_list[command.split()[0]], 1, unit=self.unit) self.client.close() self.lock.release() return rr.getRegister(0) # coils elif command.split("_")[0] == "Coil": if command.split()[0] in self.coil_on_list: wr = self.client.write_coil(self.coil_on_list[command.split()[0]], 1, unit=self.unit) rr = self.client.read_coils(self.coil_on_list[command.split()[0]], 1, unit=self.unit) elif command.split()[0] in self.coil_off_list: wr = self.client.write_coil(self.coil_off_list[command.split()[0]], 0, unit=self.unit) rr = self.client.read_coils(self.coil_off_list[command.split()[0]], 1, unit=self.unit) elif command.split()[0] in self.coil_list and len(command.split()) > 1 and \ command.split()[1].isdigit(): wr = self.client.write_coil(self.coil_list[command.split()[0]], int(command.split()[1]), unit=self.unit) rr = self.client.read_coils(self.coil_list[command.split()[0]], 1, unit=self.unit) self.client.close() self.lock.release() return rr.getBit(0) # holding registers elif command.split("_")[0] == "HReg": if len(command.split()) > 1 and command.split()[1].isdigit(): wr = self.client.write_registers(self.command_list[command.split()[0]], [int(command.split()[1])], unit=self.unit) rr = self.client.read_holding_registers(self.command_list[command.split()[0]], 1, unit=self.unit) self.client.close() self.lock.release() return rr.getRegister(0) else: print "Not correct command" self.lock.release() return "Not correct command"
class Handler(object): def __init__(self,a,a2,canvas, samples_no=1): self.btnLog = builder.get_object("btnLog") self.txtCommentBuffer = builder.get_object("txtCommentBuffer") self.dlgComments = builder.get_object("dlgComments") self.samples_no = samples_no self.loop_no = 0 self.volume = 0 self.elapsed = 0 self.lastTick = None self.thisTick = None self.loop = None self.listP1 = [] self.reg104_1 = None self.low1, self.high1 = a_low, a_high # danzi.tn@20160728 current as nanoampere nA - analogic values self.low2, self.high2 = a_low, a_high # danzi.tn@20160728 current as nanoampere nA - analogic values self.low_p1, self.high_p1 = p_low, p_high # danzi.tn@20160728 pressure range (P in bar/10) self.low_q1, self.high_q1 = q_low, q_high # danzi.tn@20160728 flow-rate range (Q in lit/min/10) self.low_p2, self.high_p2 = p_low, p_high # danzi.tn@20160728 pressure range (P in bar/10) self.low_q2, self.high_q2 = q_low, q_high # danzi.tn@20160728 flow-rate range (Q in lit/min/10) self.p1_fit = np.polyfit([self.low1, self.high1],[self.low_p1, self.high_p1],1) self.p1_func = np.poly1d(self.p1_fit) # Conversion from current (mA) to flow-rate (lit/min) self.q1_fit = np.polyfit([self.low1, self.high1],[self.low_q1, self.high_q1],1) self.q1_func = np.poly1d(self.q1_fit) self.p2_fit = np.polyfit([self.low2, self.high2],[self.low_p2, self.high_p2],1) self.p2_func = np.poly1d(self.p2_fit) # Conversion from current (mA) to flow-rate (lit/min) self.q2_fit = np.polyfit([self.low2, self.high2],[self.low_q2, self.high_q2],1) self.q2_func = np.poly1d(self.q2_fit) self.ret_m1 = False self.ret_m2 = False self.ret_p = False self.afigure = a self.afigure2 = a2 self.afigure3 = a3 self.canvas = canvas self._bufsize = x_size self.databuffer_p1 = collections.deque([0.0]*self._bufsize, self._bufsize) self.databuffer_p2 = collections.deque([0.0]*self._bufsize, self._bufsize) self.databuffer_q1 = collections.deque([0.0]*self._bufsize, self._bufsize) self.databuffer_q2 = collections.deque([0.0]*self._bufsize, self._bufsize) self.databuffer_q_max = collections.deque([0.0]*self._bufsize, self._bufsize) self.databuffer_q_out = collections.deque([0.0]*self._bufsize, self._bufsize) self.x = range(x_size) self.line_p1, = self.afigure3.plot(self.x, self.databuffer_p1,"b-", label='P1(An./Eng.)') self.line_p2, = self.afigure.plot(self.x, self.databuffer_p2,"m-", label='Pmax') self.line_q2, = self.afigure.plot(self.x, self.databuffer_q2,"g-", label='Pout') self.line_q1, = self.afigure3.plot(self.x, self.databuffer_q1,"r-", label='Q1(An./Eng.)') self.line_qmax, = self.afigure2.plot(self.x, self.databuffer_q1,"y-", label='Qmax') self.line_qout, = self.afigure2.plot(self.x, self.databuffer_q1,"k-", label='Qout') h1, l1 = a.get_legend_handles_labels() h2, l2 = a2.get_legend_handles_labels() h3, l3 = a3.get_legend_handles_labels() self.afigure.legend(h1+h2+h3, l1+l2+l3, loc=2, ncol=3, fontsize=10) self.pmax = 0 self.qmax = 0 self.blogFile = False self.oneLogged = False self.pipeLength = 0.0 self.pipeDiam = 0.0 self.pipeType = "ND" self.mixType = "ND" self.mixDensity = 0.0 self.staticHead = 0.0 self.treeview2 = builder.get_object("treeview2") self.p_count = 0 renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("Name", renderer, text=0) self.treeview2.append_column(column) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("Description", renderer, text=1) self.treeview2.append_column(column) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("Value", renderer, text=2) self.treeview2.append_column(column) self.adjustPMax = builder.get_object("adjustment1") self.adjustQMax = builder.get_object("adjustment2") self.txtMongoConnection = builder.get_object("txtMongoConnection") self.lstPumps = builder.get_object("lstPumps") self.lstMan1 = builder.get_object("lstMan1") self.lstMan2 = builder.get_object("lstMan2") self.lblDbMesg = builder.get_object("lblDbMesg") self.btnFolder = builder.get_object("btnFolder") self.txtOutFolder = builder.get_object("txtOutFolder") self.chkAnalogic = builder.get_object("chkAnalogic") self.btnFolder.connect("clicked", self.on_btnFolder_clicked) self.time = datetime.datetime.utcnow() self.sMongoDbConnection = "" self.mongo_CLI = None self.mongodb = None self.outputFolder = None self.export_csv_path = None self.lblAnalyzed = builder.get_object("lblAnalyzed") self.parentWindow = builder.get_object("windowMain") if smtConfig.has_option('Mongodb','Connectionstring'): self.txtMongoConnection.set_text(smtConfig.get('Mongodb', 'Connectionstring')) def on_btnFolder_clicked(self, widget): dialog = Gtk.FileChooserDialog("Please choose an output folder", self.parentWindow, buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,"Select", Gtk.ResponseType.OK)) dialog.set_action(Gtk.FileChooserAction.SELECT_FOLDER) dialog.set_default_size(600, 400) response = dialog.run() if response == Gtk.ResponseType.OK: print("Select clicked") print("Folder selected: " + dialog.get_filename()) self.outputFolder = dialog.get_filename() self.export_csv_path = os.path.join(self.outputFolder,"test_{0}.csv".format(datetime.datetime.utcnow().strftime("%Y%m%d%H%M%S"))) self.txtOutFolder.set_text( dialog.get_filename()) if not smtConfig.has_section('Output'): smtConfig.add_section('Output') smtConfig.set('Output', 'Folder', self.outputFolder) with open(sCFGName, 'wb') as configfile: smtConfig.write(configfile) elif response == Gtk.ResponseType.CANCEL: print("Cancel clicked") dialog.destroy() def on_txtMongoConnection_changed(self,txtEdit): pass def on_btnDatabase_clicked(self,btn): self.sMongoDbConnection = self.txtMongoConnection.get_text() splitted = self.sMongoDbConnection.split("@") mongo_database = splitted[0] splitted = splitted[1].split(":") mongo_host = splitted[0] mongo_port = splitted[1] self.mongo_CLI = MongoClient(mongo_host, int(mongo_port)) self.mongodb = self.mongo_CLI[mongo_database] self.lstPumps.clear() self.lstMan2.clear() self.lstMan1.clear() projs =[] self.lblDbMesg.set_label("") try: projs = list(self.mongodb.projects.find({})) except pyErrors.ServerSelectionTimeoutError as timeouterr: self.lblDbMesg.set_label(str(timeouterr)) logApp.debug("Database error = {0}".format(str(timeouterr))) if len(projs) > 0: if not smtConfig.has_section('Mongodb'): smtConfig.add_section('Mongodb') smtConfig.set('Mongodb', 'Connectionstring', self.sMongoDbConnection) with open(sCFGName, 'wb') as configfile: smtConfig.write(configfile) gePumps = self.mongodb.groutingequipments.find({"type":"P"}) geManifolds = self.mongodb.groutingequipments.find({"type":"M"}) for p in gePumps: self.lstPumps.append([p["ipAddress"], int(p["TCPPort"]),"{0}.{1}({2}:{3})".format(p["type"],p["code"],p["ipAddress"],p["TCPPort"])]) for p in geManifolds: self.lstMan2.append([p["ipAddress"], int(p["TCPPort"]),"{0}.{1}({2}:{3})".format(p["type"],p["code"],p["ipAddress"],p["TCPPort"])]) self.lstMan1.append([p["ipAddress"], int(p["TCPPort"]),"{0}.{1}({2}:{3})".format(p["type"],p["code"],p["ipAddress"],p["TCPPort"])]) btn.set_label("DB Connected") logApp.debug("Database Connected") else: btn.set_label("DB Connect") self.lblDbMesg.set_label("Database {0} is empty".format(mongo_database)) logApp.debug("Database {0} is empty".format(mongo_database)) def on_cmbPumps_changed(self,cmb): tree_iter = cmb.get_active_iter() if tree_iter != None: model = cmb.get_model() ip = model[tree_iter][0] port = model[tree_iter][1] builder.get_object("txtIPPump").set_text(ip) builder.get_object("txtPortPump").set_text(str(port)) def on_cmbMan1_changed(self,cmb): tree_iter = cmb.get_active_iter() if tree_iter != None: model = cmb.get_model() ip = model[tree_iter][0] port = model[tree_iter][1] builder.get_object("txtIP1").set_text(ip) builder.get_object("txtPort1").set_text(str(port)) def on_cmbMan2_changed(self,cmb): tree_iter = cmb.get_active_iter() if tree_iter != None: model = cmb.get_model() ip = model[tree_iter][0] port = model[tree_iter][1] builder.get_object("txtIP2").set_text(ip) builder.get_object("txtPort2").set_text(str(port)) def logging_data(self, a): self.loop_no += 1 builder.get_object("levelbar1").set_value(len(self.listP1)%60+1) # print "1.1 {0}".format(t1) txtPout = a[11] txtQout = a[12] aIN1 = a[2] aIN2 = a[3] aIN1ENG = a[4] aIN2ENG = a[5] pDeltaPump = a[8] qDeltaPump = a[9] # print "1.2 {0}".format(t1) # QUI CAPITA Unhandled error in Deferred quando si perde la connessione- provare un try except e saltare il campione try: okC1 = self.client_1.connect() if okC1: rr1 = self.client_1.read_holding_registers(0,48) else: logApp.error("logging_data connection to manifold 1 failed") aIN1.set_text("CONNECTION ERROR") aIN2.set_text("CONNECTION ERROR") aIN1ENG.set_text("CONNECTION ERROR") aIN2ENG.set_text("CONNECTION ERROR") return False except: logApp.error("Unhandled error in Deferred - logging_data connection to manifold 1 failed") print "1.3 {0}".format(t1) aIN1.set_text("Unhandled ERROR") aIN2.set_text("Unhandled ERROR") aIN1ENG.set_text("Unhandled ERROR") aIN2ENG.set_text("Unhandled ERROR") return False # logApp.debug("logging_data 3 read_holding_registers 2 ok") # print "3 {0}".format(t1) self.client_1.close() if rr1.registers[test_reg_no] == test_value_1 or rr1.registers[test_reg_no] == test_value_2: # Manifold 1 p_mA1 = rr1.registers[4-1] q_mA1 = rr1.registers[6-1] q_Sign = 0 if rr1.registers[test_reg_no] == test_value_2: q_Sign = rr1.registers[12-1] # save value into databuffer for iprog in range(12): logApp.info("Manifold registers[{0}] = {1}".format(iprog+1, rr1.registers[iprog])) t1=datetime.datetime.utcnow() # logApp.debug("logging_data 1") dt_seconds = (t1-self.time).seconds # convert ANALOGIC to Digital p_Eng1 = self.p1_func(p_mA1) q_Eng1 = self.q1_func(q_mA1) if q_Sign: q_Eng1 = -1.*q_Eng1 pEng1Display = p_Eng1/10. qEng1Display = q_Eng1/10. self.thisTick = datetime.datetime.utcnow() dV = 0.0 if self.lastTick: dT = self.thisTick - self.lastTick self.elapsed = dT.total_seconds() dV = qEng1Display / 60 * self.elapsed self.volume += dV #print "total_seconds = " , dT.total_seconds() #print "qEng1Display = " , qEng1Display #print "dV = " , dV #print "volume = ", self.volume builder.get_object("txtVolume").set_text("{0:.2f} lit".format(self.volume)) self.lastTick = self.thisTick # display del valore analogico se chkAnalogic è selezionato if self.chkAnalogic.get_active(): self.databuffer_p1.append( p_mA1 ) self.afigure3.set_ylim(a_low, a_high) self.afigure3.set_ylabel('Voltage (mV)') else: self.databuffer_p1.append( pEng1Display ) self.afigure3.set_ylim(-10, 80) self.afigure3.set_ylabel('Eng Values') self.line_p1.set_ydata(self.databuffer_p1) # display del valore analogico se chkAnalogic è selezionato if self.chkAnalogic.get_active(): self.databuffer_q1.append( q_mA1 ) else: self.databuffer_q1.append( qEng1Display ) self.line_q1.set_ydata(self.databuffer_q1) self.listP1.append(p_Eng1/10.) aIN1.set_text(str(p_mA1)) aIN2.set_text(str(q_mA1)) aIN1ENG.set_text("{0} bar".format(pEng1Display )) aIN2ENG.set_text("{0} lit/min".format(qEng1Display)) # INIETTORE #print "4 {0}".format(t1) if self.client_p: rr_p = self.client_p.read_holding_registers(500,100,unit=1) # print "5 {0}".format(t1) txtPout.set_text("{0} bar".format(rr_p.registers[16])) txtQout.set_text("{0} s/min {1:.2f} l/min".format(rr_p.registers[20], litCiclo*rr_p.registers[20] )) self.pmax = rr_p.registers[60] self.qmax = rr_p.registers[62] self.adjustPMax.set_value(float(self.pmax) ) self.adjustQMax.set_value(float(self.qmax)) builder.get_object("txtPmax").set_text("{0} bar".format(rr_p.registers[60])) builder.get_object("txtQmax").set_text("{0} s/min {1:.2f} l/min".format(rr_p.registers[62], litCiclo*rr_p.registers[62])) self.pDeltaP = self.pmax - rr_p.registers[16] self.qDeltaP = self.qmax - rr_p.registers[20] self.databuffer_q_max.append(self.qmax*litCiclo) self.databuffer_q_out.append(rr_p.registers[20]*litCiclo) self.databuffer_q2.append(rr_p.registers[16] ) self.databuffer_p2.append( self.pmax ) self.line_p2.set_ydata(self.databuffer_p2) self.line_q2.set_ydata(self.databuffer_q2) self.line_qout.set_ydata(self.databuffer_q_out) self.line_qmax.set_ydata(self.databuffer_q_max) pDeltaPump.set_text("{0} bar".format(self.pDeltaP )) qDeltaPump.set_text("{0} s/min {1:.2f} l/min".format(self.qDeltaP, self.qDeltaP*litCiclo )) self.p_count += 1 rr_p.registers[50] = self.p_count self.client_p.write_registers(500,rr_p.registers,unit=1) self.afigure.relim() self.afigure.autoscale_view(False, False, True) self.afigure2.relim() self.afigure2.autoscale_view(False, False, True) self.afigure3.relim() self.afigure3.autoscale_view(False, False, True) self.canvas.draw() if self.blogFile: self.oneLogged = True # TODO btnLog set label # time now - before self.btnLog.set_label("{0}".format(datetime.timedelta(seconds =dt_seconds))) log.info("%d;%f;%d;%f;%f;%f" % (p_mA1, p_Eng1, q_mA1, q_Sign, q_Eng1,self.elapsed,self.volume)) # print "6 {0}".format(t1) logApp.debug("logging_data terminated successfully") else: logApp.error( "error on test data {0}-{1} vs {2}".format(test_value_1,test_value_2,rr1.registers[test_reg_no])) return False return True def onDeleteWindow(self, *args): Gtk.main_quit(*args) def testConnection1(self, button): lblTest1 = builder.get_object("lblTest1") manifold_host_1 = builder.get_object("txtIP1").get_text() manifold_port_1 = int(builder.get_object("txtPort1").get_text()) self.client_1 = ModbusClient(manifold_host_1, port=manifold_port_1) self.ret_m1=self.client_1.connect() lblTest1.set_text(str(self.ret_m1)) if not smtConfig.has_section('Manifold_1'): smtConfig.add_section('Manifold_1') if self.ret_m1: logApp.debug("connection to manifold #1 ({0}:{1}) succedeed".format(manifold_host_1,manifold_port_1)) rr1_103 = self.client_1.read_holding_registers(103,10) self.reg104_1 = tuple(rr1_103.registers ) builder.get_object("switchMain").set_sensitive(True) smtConfig.set('Manifold_1', 'host', manifold_host_1) smtConfig.set('Manifold_1', 'port', manifold_port_1) with open(sCFGName, 'wb') as configfile: smtConfig.write(configfile) else: logApp.debug("connection to manifold #1 ({0}:{1}) failed".format(manifold_host_1,manifold_port_1)) self.client_1.close() def on_btnConnectPump_clicked(self, button): lblTestPump = builder.get_object("lblTestPump") pump_host = builder.get_object("txtIPPump").get_text() pump_port = int(builder.get_object("txtPortPump").get_text()) self.client_p = ModbusClient(pump_host, port=pump_port) self.ret_p=self.client_p.connect() lblTestPump.set_text(str(self.ret_p)) if not smtConfig.has_section('Pump'): smtConfig.add_section('Pump') if self.ret_p: builder.get_object("btnShow").set_sensitive(True) logApp.debug("connection to Pump ({0}:{1}) succedeed".format(pump_host,pump_port)) self.checkPump(self.client_p) smtConfig.set('Pump', 'host', pump_host) smtConfig.set('Pump', 'port', pump_port) with open(sCFGName, 'wb') as configfile: smtConfig.write(configfile) else: builder.get_object("btnShow").set_sensitive(False) logApp.debug("connection to Pump ({0}:{1}) failed".format(pump_host,pump_port)) self.client_p.close() def checkPump(self,client_p): self.p_count += 1 rq = client_p.write_register(550,self.p_count,unit=1) if rq.function_code < 0x80: rr_p = client_p.read_holding_registers(500,100,unit=1) if len(rr_p.registers)==100 and rr_p.registers[0]==self.p_count: decoder = BinaryPayloadDecoder.fromRegisters(rr_p.registers[2:7],endian=Endian.Little) # 502 bits_502 = decoder.decode_bits() bits_502 += decoder.decode_bits() # 503 bits_503 = decoder.decode_bits() bits_503 += decoder.decode_bits() # 504 bits_504 = decoder.decode_bits() bits_504 += decoder.decode_bits() # 505 bits_505 = decoder.decode_bits() bits_505 += decoder.decode_bits() # 506 bits_506 = decoder.decode_bits() bits_506 += decoder.decode_bits() if bits_502[7]: builder.get_object("switchPumpStatus").set_active(True) else: builder.get_object("switchPumpStatus").set_active(False) if bits_502[4] == False and bits_502[10] == True: builder.get_object("switchPumpStatus").set_sensitive(True) else: builder.get_object("switchPumpStatus").set_sensitive(False) self.setPumpFlowAndPressure() def on_btnOpenFile_clicked(self,button): #os.system() subprocess.call(["libreoffice",self.export_csv_path]) def setPumpFlowAndPressure(self): if self.ret_p: rr_p = self.client_p.read_holding_registers(500,100,unit=1) self.p_count += 1 rr_p.registers[50] = self.p_count rr_p.registers[60] = int(self.pmax) rr_p.registers[62] = int(self.qmax) rr_p = self.client_p.write_registers(500,rr_p.registers,unit=1) def on_btnOff_clicked(self,button): print("Closing application") logApp.debug("HDLF GUI CLOSING") Gtk.main_quit() def storeHDLF(self): self.pipeLength = float(builder.get_object("txtPipeLenght").get_text()) self.pipeDiam = float(builder.get_object("txtPipeDiam").get_text()) self.pipeType = builder.get_object("txtPipeType").get_text() self.mixType = builder.get_object("txtMixType").get_text() self.mixDensity = float(builder.get_object("txtMixDensity").get_text()) self.staticHead = float(builder.get_object("txtStaticHead").get_text()) if not smtConfig.has_section('HeadLossFactor'): smtConfig.add_section('HeadLossFactor') smtConfig.set('HeadLossFactor', 'pipeLength', self.pipeLength) smtConfig.set('HeadLossFactor', 'pipeDiam', self.pipeDiam) smtConfig.set('HeadLossFactor', 'pipeType', self.pipeType) smtConfig.set('HeadLossFactor', 'mixType', self.mixType) smtConfig.set('HeadLossFactor', 'mixDensity', self.mixDensity) smtConfig.set('HeadLossFactor', 'staticHead', self.staticHead) with open(sCFGName, 'wb') as configfile: smtConfig.write(configfile) def on_btnLog_toggled(self,button): if button.get_active(): self.time = datetime.datetime.utcnow() self.blogFile = True self.volume = 0 self.elapsed = 0 else: self.blogFile = False builder.get_object("btnLog").set_label("Log Data") def on_switchPumpStatus_state_set(self, switch,gparam): self.ret_p=self.client_p.connect() rr = self.client_p.read_holding_registers(500,100,unit=1) # conversione in bit array da 552 decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[52:53],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[2:7],endian=Endian.Little) # 502 bits_502 = decoder.decode_bits() bits_502 += decoder.decode_bits() # 503 bits_503 = decoder.decode_bits() bits_503 += decoder.decode_bits() # 504 bits_504 = decoder.decode_bits() bits_504 += decoder.decode_bits() # 505 bits_505 = decoder.decode_bits() bits_505 += decoder.decode_bits() # 506 bits_506 = decoder.decode_bits() bits_506 += decoder.decode_bits() bSendCommand = False if switch.get_active(): # %MW552:X2 START INIET. DA REMOTO bSendCommand = not bits_502[7] bits_552[2] = True bits_552[3] = False bits_552[14] = True else: # %MW552:X2 STOP INIET. DA REMOTO bSendCommand = bits_502[7] bits_552[2] = False bits_552[3] = True bits_552[14] = False builder = BinaryPayloadBuilder(endian=Endian.Little) # builder.add_bits(bits_502) builder.add_bits(bits_552) reg_552 = builder.to_registers() rr.registers[52:53] = reg_552 self.p_count += 1 rr.registers[50] = self.p_count if bSendCommand: self.client_p.write_registers(500, rr.registers,unit=1) self.client_p.close() def on_btnShow_clicked(self,button): # show dlgRegistries self.lstDialog = builder.get_object("dlgRegistries") self.liststore = builder.get_object("liststore1") if not self.ret_p: self.ret_p = self.client_p.connect() if self.ret_p: self.liststore.clear() rr = self.client_p.read_holding_registers(500,100,unit=1) for idx in [0,2,4,6,12,13,14,15,16,20,50,52,60,62]: if idx in (2,4,6,52): decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[idx:idx+1],endian=Endian.Little) bits = decoder.decode_bits() bits += decoder.decode_bits() for ib, b in enumerate(bits): if b: sCode = "%MW5{0:02d}:X{1}".format(idx,ib) self.liststore.append([sCode,reg_descr[sCode], str( b ) ]) else: sCode = "%MW5{0:02d}".format(idx) self.liststore.append([sCode, reg_descr[sCode], str( rr.registers[idx]) ]) response = self.lstDialog.run() self.lstDialog.hide() def on_btnOk_clicked(self,button): self.lstDialog.close() def on_btnOKComments_clicked(self, button): self.dlgComments.close() def on_btnComments_clicked(self, button): # self.parentWindow response = self.dlgComments.run() self.dlgComments.hide() def on_btnVolume_clicked(self, button): self.volume = 0 self.elapsed = 0 def on_chkAnalogic_toggled(self,chk): if chk.get_active(): logApp.info( "on_chkAnalogic_toggled toggled Active" ) # else: logApp.info( "on_chkAnalogic_toggled toggled Inactive" ) def on_spinPMax_value_changed(self,spin): self.pmax = int(spin.get_value()) self.setPumpFlowAndPressure() def on_spinQMax_value_changed(self,spin): self.qmax = int(spin.get_value()) self.setPumpFlowAndPressure() def on_switchMain_activate(self, switch,gparam): self.lblAnalyzed.set_label("...") if switch.get_active(): self.listP1 = [] self.export_csv_path = os.path.join(self.outputFolder,"test_{0}.csv".format(datetime.datetime.utcnow().strftime("%Y%m%d%H%M%S"))) file_handler = logging.handlers.RotatingFileHandler(self.export_csv_path, maxBytes=5000000,backupCount=5) file_handler.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s;%(message)s') file_handler.setFormatter(formatter) if len(log.handlers) > 0: log.handlers[0] = file_handler else: log.addHandler(file_handler) log.info("p_mA1;p_Eng1;q_mA1;q_Sign;q_Eng1;elapsed;volume") self.client_1 = ModbusClient(manifold_host_1, port=manifold_port_1) self.client_p = None if self.ret_p: self.client_p = ModbusClient(pump_host, port=pump_port) #self.client_1.connect() self.ret_p = self.client_p.connect() time.sleep(1.5) print "start connection with Pump" time_delay = 1./float(self.samples_no) # 1 seconds delay self.loop = LoopingCall(f=self.logging_data, a=(self.client_1,None, builder.get_object("txtAIN1"),builder.get_object("txtAIN2"),builder.get_object("txtAIN1ENG"),builder.get_object("txtAIN2ENG"),None,None,builder.get_object("txtAIN1ENG2"),builder.get_object("txtAIN2ENG2"),self.client_p,builder.get_object("txtPout"),builder.get_object("txtQout"))) print "LoopingCall created" self.loop.start(time_delay, now=False) # initially delay by time print "loop started" builder.get_object("txtFilePath").set_text("") builder.get_object("btnOpenFile").set_sensitive(False) builder.get_object("btnOff").set_sensitive(False) # self.ani = animation.FuncAnimation(self.figure, self.update_plot, interval = 1000) else: self.loop.stop() time.sleep(1) #self.client_1.close() if self.ret_p: self.client_p.close() print "stop connection with Pump" time.sleep(1) builder.get_object("txtFilePath").set_text(self.export_csv_path) builder.get_object("btnOpenFile").set_sensitive(True) builder.get_object("btnOff").set_sensitive(True)
# # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] #---------------------------------------------------------------------------# builder = PayloadBuilder(endian=Endian.Little) builder.add_string('abcdefgh') builder.add_32bit_float(22.34) builder.add_16bit_uint(0x1234) builder.add_8bit_int(0x12) builder.add_bites([0,1,0,1,1,0,1,0]) payload = builder.tolist() address = 0x01 result = client.write_registers(address, payload) #---------------------------------------------------------------------------# # If you need to decode a collection of registers in a weird layout, the # payload decoder can help you as well. # # Here we demonstrate decoding a random register layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] #---------------------------------------------------------------------------# address = 0x01
import struct from pymodbus.client.sync import ModbusTcpClient parser = argparse.ArgumentParser(description='Send modbus TCP commands.') parser.add_argument('--dest', '-d', nargs=1, help='modbus server') parser.add_argument('--port', '-p', nargs='?', help='tcp port', default=502) parser.add_argument('--slave', '-s', type=int, nargs='?', help='slave address', default=1) parser.add_argument('--register', '-r', type=int, nargs=1, help='register') parser.add_argument('--count', '-c', type=int, nargs='?', help='count', default=1) parser.add_argument('--type', '-t', nargs='?', help='data type (python struct syntax)', default=None) parser.add_argument('--write', '-w', type=int, nargs='?', help='write single register', default=None) args = parser.parse_args() client = ModbusTcpClient(host=args.dest[0], port=args.port) if args.write == None: result = client.read_holding_registers(address=args.register[0], count=args.count, unit=args.slave) if result.function_code >= 0x80: print('Error in function_code: {} {}'.format(hex(result.function_code), hex(result.exception_code))) elif args.type == None: print(result.registers) else: bytes = b'' for r in result.registers: bytes += chr(r >> 8) bytes += chr(r & 255) print(struct.unpack(args.type, bytes)) else: result = client.write_registers(address=args.register[0], values=[args.write], unit=args.slave) if result.function_code >= 0x80: print('Error in function_code: {} {}'.format(hex(result.function_code), hex(result.exception_code)))
# TODO: check retries, and other options client = ModbusClient(args.ip, port=args.port) # retries=3, retry_on_empty=True) client.connect() # TODO: check if asserts are slowing down read/write if args.mode == 'w': # NOTE: write_register if args.type == 'HR': if args.count == 1: hr_write = client.write_register(args.offset, args.register[0]) assert (hr_write.function_code < 0x80) else: hrs_write = client.write_registers(args.offset, args.register) assert (hrs_write.function_code < 0x80) # NOTE: write_coil: map integers to bools elif args.type == 'CO': if args.count == 1: # NOTE: coil is a list with one bool if args.coil[0] == 1: co_write = client.write_coil(args.offset, True) else: co_write = client.write_coil(args.offset, False) assert (co_write.function_code < 0x80) else: coils = []
from pymodbus.constants import Endian from pymodbus.payload import BinaryPayloadDecoder from pymodbus.client.sync import ModbusTcpClient import time REAL_SERVER_IP = '' #centrifuge workstation IP client_real_server = ModbusTcpClient(REAL_SERVER_IP, port=502) # real server. connection = client_real_server.connect() if connection: print('disabling safety controls...') client_real_server.write_coils(1, [False], unit=1) time.sleep(2) print('increasing RPMs to 14000') client_real_server.write_registers(1, 14000, unit=1) time.sleep(2) current_RPM = client_real_server.read_holding_registers( address=0x01, count=1, unit=0x01).registers print('centrifuge RPMs are now set to: ' + str(current_RPM[0])) client_real_server.close() else: print('Connection lost, Try again')
rq = client.write_coils(1, [True]*8) rr = client.read_coils(1,8) assert(rq.function_code < 0x80) # test that we are not an error assert(rr.bits == [True]*8) # test the expected value rq = client.write_coils(1, [False]*8) rr = client.read_discrete_inputs(1,8) assert(rq.function_code < 0x80) # test that we are not an error assert(rr.bits == [True]*8) # test the expected value rq = client.write_register(1, 10) rr = client.read_holding_registers(1,1) assert(rq.function_code < 0x80) # test that we are not an error assert(rr.registers[0] == 10) # test the expected value rq = client.write_registers(1, [10]*8) rr = client.read_input_registers(1,8) assert(rq.function_code < 0x80) # test that we are not an error assert(rr.registers == [17]*8) # test the expected value arguments = { 'read_address': 1, 'read_count': 8, 'write_address': 1, 'write_registers': [20]*8, } rq = client.readwrite_registers(**arguments) rr = client.read_input_registers(1,8) assert(rq.function_code < 0x80) # test that we are not an error assert(rq.registers == [20]*8) # test the expected value assert(rr.registers == [17]*8) # test the expected value
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/ttyp0', timeout=1) 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=0x01) print(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 async 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(rq.function_code < 0x80) # 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(rq.function_code < 0x80) # test that we are not an error rr = client.read_coils(1, 21, unit=UNIT) assert(rr.function_code < 0x80) # 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(rq.function_code < 0x80) # 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(rq.function_code < 0x80) # 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(rq.function_code < 0x80) # 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(rq.function_code < 0x80) # 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(rq.function_code < 0x80) # 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(rq.function_code < 0x80) # 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()
print rr rr = client.read_input_registers(8009,1) print rr ''' ''' rr = client.read_input_registers(8000,1) print rr.registers rr = client.read_input_registers(8001,1) print rr.registers rr = client.read_holding_registers(8001, 1) print rr.registers ''' i=1 uptime = time.time() while True: rq = client.write_registers(8001, [i]*1) print i rr = client.read_input_registers(8000, 1) print rr.registers if i < 7: i = i * 2 print time.time() - uptime else: i=1 os.system("cls") time.sleep(1) #---------------------------------------------------------------------------# # close the client #---------------------------------------------------------------------------#
class Pluggit(): _myTempReadDict = {} _myTempWriteDict = {} #============================================================================# # define variables for most important modbus registers of KWL "Pluggit AP310" # # Important: In the PDU Registers are addressed starting at zero. # Therefore registers numbered 1-16 are addressed as 0-15. # that means e.g. holding register "40169" is "40168" and so on #============================================================================# # dictionary for modbus registers _modbusRegisterDic = { # 'prmDateTime': 108, # 40109: Current Date/time in Unix time (amount of seconds from 1.1.1970) 'prmRamIdxT1': 133, # 40133: T1, °C 'prmRamIdxT2': 135, # 40135: T2, °C 'prmRamIdxT3': 137, # 40137: T3, °C 'prmRamIdxT4': 139, # 40139: T4, °C # 'prmRamIdxT5': 140, # 40141: T5, °C 'prmRamIdxUnitMode': 168, # 40169: Active Unit mode> 0x0004 Manual Mode; 0x0008 WeekProgram 'prmRamIdxBypassActualState': 198, # 40199: Bypass state> Closed 0x0000; In process 0x0001; Closing 0x0020; Opening 0x0040; Opened 0x00FF 'prmRomIdxSpeedLevel': 324, # 40325: Speed level of Fans in Manual mode; shows a current speed level [4-0]; used for changing of the fan speed level # 'prmVOC': 430, # 40431: VOC sensor value (read from VOC); ppm. If VOC is not installed, then 0. # 'prmBypassTmin': 444, # 40445: Minimum temperature of Bypass openning (°C), if T1 < Tmin then bypass should be closed # 'prmBypassTmax': 446, # 40447: Maximum temperature of Bypass openning (°C), if T1 > Tmax or Tmax is 0 then bypass should be closed # 'prmWorkTime': 624 # 40625: Work time of system, in hour (UNIX) 'prmNumOfWeekProgram': 466, # 40467: Number of the Active Week Program (for Week Program mode) 'prmFilterRemainingTime': 554 # 40555: Remaining time of the Filter Lifetime (Days) } # Initialize connection def __init__(self, smarthome, host, port=502, cycle=300): self._host = host self._port = int(port) self._sh = smarthome self._cycle = int(cycle) self._lock = threading.Lock() self._is_connected = False self._items = {} self.connect() # pydevd.settrace("192.168.0.125") def connect(self): start_time = time.time() if self._is_connected: return True self._lock.acquire() try: logger.info("Pluggit: connecting to {0}:{1}".format(self._host, self._port)) self._Pluggit = ModbusTcpClient(self._host, self._port) except Exception as e: logger.error("Pluggit: could not connect to {0}:{1}: {2}".format(self._host, self._port, e)) return finally: self._lock.release() logger.info("Pluggit: connected to {0}:{1}".format(self._host, self._port)) self._is_connected = True end_time = time.time() logger.info("Pluggit: connection took {0} seconds".format(end_time - start_time)) def disconnect(self): start_time = time.time() if self._is_connected: try: self._Pluggit.close() except: pass self._is_connected = False end_time = time.time() logger.info("Pluggit: disconnect took {0} seconds".format(end_time - start_time)) def run(self): self.alive = True self._sh.scheduler.add('Pluggit', self._refresh, cycle=self._cycle) def stop(self): self.alive = False # parse items in pluggit.conf def parse_item(self, item): # check for smarthome.py attribute 'pluggit_listen' in pluggit.conf if 'pluggit_listen' in item.conf: # logger.debug("Pluggit: parse read item: {0}".format(item)) pluggit_key = item.conf['pluggit_listen'] if pluggit_key in self._modbusRegisterDic: self._myTempReadDict[pluggit_key] = item # logger.debug("Pluggit: Inhalt des dicts _myTempReadDict nach Zuweisung zu item: '{0}'".format(self._myTempReadDict)) else: logger.warn("Pluggit: invalid key {0} configured".format(pluggit_key)) elif 'pluggit_send' in item.conf: # logger.debug("Pluggit: parse send item: {0}".format(item)) pluggit_sendKey = item.conf['pluggit_send'] if pluggit_sendKey is None: return None else: self._myTempWriteDict[pluggit_sendKey] = item # logger.debug("Pluggit: Inhalt des dicts _myTempWriteDict nach Zuweisung zu send item: '{0}'".format(self._myTempWriteDict)) return self.update_item else: return None def parse_logic(self, logic): pass def update_item(self, item, caller=None, source=None, dest=None): if caller != 'Pluggit': if 'pluggit_send' in item.conf: command = item.conf['pluggit_send'] value = item() logger.info("Pluggit: {0} set {1} to {2} for {3}".format(caller, command, value, item.id())) if(command == 'activatePowerBoost') and (isinstance(value, bool)): if value: self._activatePowerBoost() else: self._activateWeekProgram() pass def _activatePowerBoost(self): active_unit_mode_value = 4, 0 fan_speed_level_value = 4, 0 # Change Unit Mode to manual # logger.debug("Pluggit: Start => Change Unit mode to manual: {0}".format(active_unit_mode_value)) self._Pluggit.write_registers(self._modbusRegisterDic['prmRamIdxUnitMode'], active_unit_mode_value) # logger.debug("Pluggit: Finished => Change Unit mode to manual: {0}".format(active_unit_mode_value)) # wait 100ms before changing fan speed # logger.debug("Pluggit: Wait 100ms before changing fan speed") time.sleep(0.1) # Change Fan Speed to highest speed # logger.debug("Pluggit: Start => Change Fan Speed to Level 4") self._Pluggit.write_registers(self._modbusRegisterDic['prmRomIdxSpeedLevel'], fan_speed_level_value) # logger.debug("Pluggit: Finished => Change Fan Speed to Level 4") # self._refresh() # check new active unit mode active_unit_mode = self._Pluggit.read_holding_registers(self._modbusRegisterDic['prmRamIdxUnitMode'], read_qty = 1).getRegister(0) if active_unit_mode == 8: logger.debug("Pluggit: Active Unit Mode: Week program") elif active_unit_mode == 4: logger.debug("Pluggit: Active Unit Mode: Manual") # check new fan speed fan_speed_level = self._Pluggit.read_holding_registers(self._modbusRegisterDic['prmRomIdxSpeedLevel'], read_qty = 1).getRegister(0) logger.debug("Pluggit: Fan Speed: {0}".format(fan_speed_level)) def _activateWeekProgram(self): active_unit_mode_value = 8, 0 # Change Unit Mode to "Week Program" # logger.debug("Pluggit: Start => Change Unit mode to 'Week Program': {0}".format(active_unit_mode_value)) self._Pluggit.write_registers(self._modbusRegisterDic['prmRamIdxUnitMode'], active_unit_mode_value) # logger.debug("Pluggit: Finished => Change Unit mode to 'Week Program': {0}".format(active_unit_mode_value)) # self._refresh() # check new active unit mode active_unit_mode = self._Pluggit.read_holding_registers(self._modbusRegisterDic['prmRamIdxUnitMode'], read_qty = 1).getRegister(0) if active_unit_mode == 8: logger.debug("Pluggit: Active Unit Mode: Week program") elif active_unit_mode == 4: logger.debug("Pluggit: Active Unit Mode: Manual") # wait 100ms before checking fan speed time.sleep(0.1) # check new fan speed fan_speed_level = self._Pluggit.read_holding_registers(self._modbusRegisterDic['prmRomIdxSpeedLevel'], read_qty = 1).getRegister(0) logger.debug("Pluggit: Fan Speed: {0}".format(fan_speed_level)) def _refresh(self): start_time = time.time() try: # myCounter = 1 for pluggit_key in self._myTempReadDict: # logger.debug("Pluggit: ---------------------------------> Wir sind in der Refresh Schleife") values = self._modbusRegisterDic[pluggit_key] # logger.debug("Pluggit: Refresh Schleife: Inhalt von values ist {0}".format(values)) # 2015-01-07 23:53:08,296 DEBUG Pluggit Pluggit: Refresh Schleife: Inhalt von values ist 168 -- __init__.py:_refresh:158 item = self._myTempReadDict[pluggit_key] # logger.debug("Pluggit: Refresh Schleife: Inhalt von item ist {0}".format(item)) # 2015-01-07 23:53:08,316 DEBUG Pluggit Pluggit: Refresh Schleife: Inhalt von item ist pluggit.unitMode -- __init__.py:_refresh:160 #=======================================================# # read values from pluggit via modbus client registers #=======================================================# # logger.debug("Pluggit: ------------------------------------------> Wir sind vor dem Auslesen der Werte") registerValue = None registerValue = self._Pluggit.read_holding_registers(values, read_qty = 1).getRegister(0) # logger.debug("Pluggit: Read parameter '{0}' with register '{1}': Value is '{2}'".format(pluggit_key, values, registerValue)) # week program: possible values 0-10 if values == self._modbusRegisterDic['prmNumOfWeekProgram']: registerValue += 1 item(registerValue, 'Pluggit') # 2015-01-07 23:53:08,435 DEBUG Pluggit Item pluggit.unitMode = 8 via Pluggit None None -- item.py:__update:363 # logger.debug("Pluggit: Week Program Number: {0}".format(registerValue)) # 2015-01-07 23:53:08,422 DEBUG Pluggit Pluggit: Active Unit Mode: Week program -- __init__.py:_refresh:177 # active unit mode if values == self._modbusRegisterDic['prmRamIdxUnitMode'] and registerValue == 8: # logger.debug("Pluggit: Active Unit Mode: Week program") item('Woche', 'Pluggit') if values == self._modbusRegisterDic['prmRamIdxUnitMode'] and registerValue == 4: # logger.debug("Pluggit: Active Unit Mode: Manual") item('Manuell', 'Pluggit') # fan speed if values == self._modbusRegisterDic['prmRomIdxSpeedLevel']: # logger.debug("Pluggit: Fan Speed: {0}".format(registerValue)) item(registerValue, 'Pluggit') # remaining filter lifetime if values == self._modbusRegisterDic['prmFilterRemainingTime']: # logger.debug("Pluggit: Remaining filter lifetime: {0}".format(registerValue)) item(registerValue, 'Pluggit') # bypass state if values == self._modbusRegisterDic['prmRamIdxBypassActualState'] and registerValue == 255: # logger.debug("Pluggit: Bypass state: opened") item('geöffnet', 'Pluggit') if values == self._modbusRegisterDic['prmRamIdxBypassActualState'] and registerValue == 0: # logger.debug("Pluggit: Bypass state: closed") item('geschlossen', 'Pluggit') # Temperatures # Frischluft außen if values == self._modbusRegisterDic['prmRamIdxT1']: t1 = self._Pluggit.read_holding_registers(values, 2, unit=22) decodert1 = BinaryPayloadDecoder.fromRegisters(t1.registers, endian=Endian.Big) t1 = decodert1.decode_32bit_float() t1 = round(t1, 2) # logger.debug("Pluggit: Frischluft außen: {0:4.1f}".format(t1)) # logger.debug("Pluggit: Frischluft außen: {0}".format(t1)) item(t1, 'Pluggit') # Zuluft innen if values == self._modbusRegisterDic['prmRamIdxT2']: t2 = self._Pluggit.read_holding_registers(values, 2, unit=22) decodert2 = BinaryPayloadDecoder.fromRegisters(t2.registers, endian=Endian.Big) t2 = decodert2.decode_32bit_float() t2 = round(t2, 2) # logger.debug("Pluggit: Zuluft innen: {0:4.1f}".format(t2)) # logger.debug("Pluggit: Zuluft innen: {0}".format(t2)) item(t2, 'Pluggit') # Abluft innen if values == self._modbusRegisterDic['prmRamIdxT3']: t3 = self._Pluggit.read_holding_registers(values, 2, unit=22) decodert3 = BinaryPayloadDecoder.fromRegisters(t3.registers, endian=Endian.Big) t3 = decodert3.decode_32bit_float() t3 = round(t3, 2) # logger.debug("Pluggit: Abluft innen: {0:4.1f}".format(t3)) # logger.debug("Pluggit: Abluft innen: {0}".format(t3)) item(t3, 'Pluggit') # Fortluft außen if values == self._modbusRegisterDic['prmRamIdxT4']: t4 = self._Pluggit.read_holding_registers(values, 2, unit=22) decodert4 = BinaryPayloadDecoder.fromRegisters(t4.registers, endian=Endian.Big) t4 = decodert4.decode_32bit_float() t4 = round(t4, 2) # logger.debug("Pluggit: Fortluft außen: {0:4.1f}".format(t4)) # logger.debug("Pluggit: Fortluft außen: {0}".format(t4)) item(t4, 'Pluggit') # logger.debug("Pluggit: ------------------------------------------> Ende der Schleife vor sleep, Durchlauf Nr. {0}".format(myCounter)) time.sleep(0.1) # myCounter += 1 except Exception as e: logger.error("Pluggit: something went wrong in the refresh function: {0}".format(e)) return end_time = time.time() cycletime = end_time - start_time logger.debug("Pluggit: cycle took {0} seconds".format(cycletime))
class Handler(object): def __init__(self,a,a2,canvas,loop=None): self.loop = loop self.ret_m1 = False self.afigure = a self.afigure2 = a2 self.canvas = canvas self._bufsize = x_size self.databuffer_p1 = collections.deque([0.0]*self._bufsize, self._bufsize) self.databuffer_p2 = collections.deque([0.0]*self._bufsize, self._bufsize) self.databuffer_r = collections.deque([0.0]*self._bufsize, self._bufsize) self.databuffer_q1 = collections.deque([0.0]*self._bufsize, self._bufsize) self.x = range(x_size) self.line_p1, = self.afigure.plot(self.x, self.databuffer_p1,"b-", label='Pg') self.line_p2, = self.afigure.plot(self.x, self.databuffer_p2,"-", color='#ffa100', label='Pe') self.line_r, = self.afigure.plot(self.x, self.databuffer_r,"r-", label='R') self.line_q1, = self.afigure2.plot(self.x, self.databuffer_q1,"m-", label='Q') h1, l1 = a.get_legend_handles_labels() h2, l2 = a2.get_legend_handles_labels() self.afigure.legend(h1+h2, l1+l2, loc=2, ncol=2, fontsize=10) self.pmax = 0 self.qmax = 0 self.qVmax = 0 self.pR = 0 self.blogFile = False self.oneLogged = False self.pipeLength = 0.0 self.pipeDiam = 0.0 self.pipeType = "ND" self.mixType = "ND" self.mixDensity = 0.0 self.staticHead = 0.0 self.treeview2 = builder.get_object("treeview2") self.p_count = 0 renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("Name", renderer, text=0) self.treeview2.append_column(column) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("Description", renderer, text=1) self.treeview2.append_column(column) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("Value", renderer, text=2) self.treeview2.append_column(column) self.adjustPMax = builder.get_object("adjustment1") self.adjustQMax = builder.get_object("adjustment2") self.chkPAna = builder.get_object("chkPAna") self.txtDHLF = builder.get_object("txtDHLF") self.btnAnalyze = builder.get_object("btnAnalyze") self.txtRefPressure = builder.get_object("txtR") self.btnAnalyze.set_sensitive(False) self.time = datetime.datetime.utcnow() self.lastPe = collections.deque(maxlen=designRTW*60) self.lastPg = collections.deque(maxlen=designRTW*60) self.lastQ = collections.deque(maxlen=designRTW*60) self.txtQ2 = builder.get_object("txtQ2") self.txtQ1 = builder.get_object("txtQ1") self.txtK = builder.get_object("txtK") self.txtPoutMax = builder.get_object("txtPoutMax") self.lblOK = builder.get_object("lblOK") self.hdlf_q2 = 0 self.hdlf_q1 = 0 self.hdlf_k = 0 self.designQmin = 0. def logging_data(self, a): self.send_parity() t1=datetime.datetime.utcnow() dt_seconds = (t1-self.time).seconds builder.get_object("levelbar1").set_value(len(listP1)%60+1) client_1 = a[0] client_p = a[8] txtPout = a[9] txtQout = a[10] aIN1 = a[1] aIN2 = a[2] aIN1ENG = a[3] aIN2ENG = a[4] aIN12 = a[5] aIN22 = a[6] aIN1ENG2 = a[7] strR = self.txtRefPressure.get_text() if strR.isdigit(): self.pR = int(strR) else: self.pR = 10 self.txtRefPressure.set_text("10") strR = builder.get_object("txtPipeLenght").get_text() if strR.isdigit(): self.pipeLength = int(strR) else: builder.get_object("txtPipeLenght").set_text(str(self.pipeLength)) self.hdlf_q2 = float(builder.get_object("txtQ2").get_text()) self.hdlf_q1 = float(builder.get_object("txtQ1").get_text()) self.hdlf_k = float(builder.get_object("txtK").get_text()) strR = builder.get_object("txtStaticHead").get_text() try: self.staticHead = float(strR) except ValueError: builder.get_object("txtStaticHead").set_text(str(self.staticHead)) rr1 = client_1.read_holding_registers(0,48) if rr1.registers[test_reg_no] == test_value: p_mA1 = rr1.registers[4-1]# AIN1 pressione in mA in posizione 4 p_Eng1 = int(pEngFunc(p_mA1)) # AIN2 portata in mA in posizione 6 q_mA1 = rr1.registers[6-1] q_Eng1 = int(qEngFunc(q_mA1)) rr1_103 = client_1.read_holding_registers(103,10) reg104_1 = tuple(rr1_103.registers ) p_mA2 = 0 # rr2.registers[4-1]# AIN1 pressione in mA in posizione 4 p_Eng2 = 0 # rr2.registers[5-1] # AIN2 portata in mA in posizione 6 q_mA2 = 0 # rr2.registers[6-1] if p_mA1 <= 4000: p_mA1 = 0 p_Eng1 = 0 if q_mA1 <= 4000: q_mA1 = 0 q_Eng1 = 0 hdlf = (self.hdlf_q2, self.hdlf_q1,self.hdlf_k) self.pDHL = phdlf( q_Eng1/10. ,self.pipeLength, hdlf ) p_Eng2 = p_Eng1 - 10.*self.pDHL + 10.*self.staticHead self.lastQ.append(q_Eng1/10.) self.lastPe.append(p_Eng2/10.) self.lastPg.append(p_Eng1/10.) if len(self.lastPe) == self.lastPe.maxlen: p_mA2 = np.mean(self.lastPe) q_mA2 = np.mean(self.lastQ) pRate = p_mA2/self.pR if q_mA2 <= self.designQmin and p_mA2 >= self.pR: self.lblOK.set_label("OK") else: self.lblOK.set_label("P<R ({0:.2f})".format(pRate)) self.txtDHLF.set_text("{0:.2f}".format(-self.pDHL)) self.databuffer_p1.append( p_Eng1/10. ) self.line_p1.set_ydata(self.databuffer_p1) self.databuffer_p2.append( p_Eng2/10. ) self.line_p2.set_ydata(self.databuffer_p2) self.databuffer_r.append( self.pR ) self.line_r.set_ydata(self.databuffer_r) self.databuffer_q1.append( q_Eng1/10. ) self.line_q1.set_ydata(self.databuffer_q1) self.afigure.relim() self.afigure.autoscale_view(False, False, True) self.afigure2.relim() self.afigure2.autoscale_view(False, False, True) self.canvas.draw() listP1.append(p_Eng1/10.) listP2.append(p_Eng2/10.) aIN1.set_text(str(p_mA1)) aIN2.set_text(str(q_mA1)) aIN1ENG.set_text("{0} bar".format(p_Eng1/10.)) aIN2ENG.set_text("{0} lit/min".format(q_Eng1/10.)) aIN12.set_text("{0:.2f} bar".format(p_mA2)) aIN22.set_text("{0:.2f} lit/min".format(q_mA2)) aIN1ENG2.set_text("{0} bar".format(p_Eng2/10.)) # INIETTORE rr_p = client_p.read_holding_registers(500,100,unit=1) txtPout.set_text("{0} bar".format(rr_p.registers[16])) fPoutMax = self.pR + rr_p.registers[16] - p_Eng2/10. self.txtPoutMax.set_text("{0}".format(int(fPoutMax))) txtQout.set_text("{0} c/min {1:.2f} l/min".format(rr_p.registers[20], litCiclo*rr_p.registers[20] )) self.pmax = rr_p.registers[60] if self.chkPAna.get_active(): self.qmax = rr_p.registers[64] builder.get_object("txtQmax").set_text("{0} V".format(self.qmax)) else: self.qmax = rr_p.registers[62] builder.get_object("txtQmax").set_text("{0} c/min {1:.2f} l/min".format(self.qmax, litCiclo*self.qmax)) # self.qVmax = rr_p.registers[64] builder.get_object("txtPmax").set_text("{0} bar".format(rr_p.registers[60])) # print "P: {0}->{1} \tdP = {4} \t\tQ: {2}->{3} \tn={5} \tavg P1 {6:.2f}({7:.2f}) P2 {8:.2f}({9:.2f})".format(p_Eng1/10.,p_Eng2/10.,q_Eng1/10.,q_Eng2/10.,(p_Eng1-p_Eng2)/10., len(listP1), np.mean(listP1),np.std(listP1),np.mean(listP2),np.std(listP2) ) if self.blogFile: self.oneLogged = True # TODO btnLog set label # time now - before builder.get_object("btnLog").set_label("{0}".format(datetime.timedelta(seconds =dt_seconds))) log.info("%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%f;%f;%s;%s;%f;%f;%f;%d;%d;%d;%d;%f;%f;%f;%f;%f;%f" % (self.pR, p_mA1, p_Eng1, q_mA1, q_Eng1,reg104_1[0] ,reg104_1[1] ,reg104_1[2] , reg104_1[3],reg104_1[6] ,reg104_1[7] ,reg104_1[8] , reg104_1[9],p_mA2, p_Eng2, q_mA2, self.pipeLength, self.pipeDiam,self.pipeType,self.mixType,self.mixDensity,self.staticHead,self.pDHL, rr_p.registers[16],rr_p.registers[20],self.pmax,self.qmax, self.pmax-rr_p.registers[16], rr_p.registers[16]- p_Eng1/10. , hdlf[0], hdlf[1], hdlf[2],fPoutMax)) else: print "error on test data {0} vs {1} or {0} vs {2}".format(test_value,rr1.registers[test_reg_no],rr2.registers[test_reg_no]) def onDeleteWindow(self, *args): Gtk.main_quit(*args) def testConnection1(self, button): lblTest1 = builder.get_object("lblTest1") manifold_host_1 = builder.get_object("txtIP1").get_text() manifold_port_1 = int(builder.get_object("txtPort1").get_text()) client_1 = ModbusClient(manifold_host_1, port=manifold_port_1) self.ret_m1=client_1.connect() lblTest1.set_text(str(self.ret_m1)) if not smtConfig.has_section('Manifold_1'): smtConfig.add_section('Manifold_1') if self.ret_m1: builder.get_object("switchMain").set_sensitive(True) smtConfig.set('Manifold_1', 'host', manifold_host_1) smtConfig.set('Manifold_1', 'port', manifold_port_1) with open(sCFGName, 'wb') as configfile: smtConfig.write(configfile) client_1.close() def on_btnConnectPump_clicked(self, button): lblTestPump = builder.get_object("lblTestPump") pump_host = builder.get_object("txtIPPump").get_text() pump_port = int(builder.get_object("txtPortPump").get_text()) self.client_p = ModbusClient(pump_host, port=pump_port) self.ret_p=self.client_p.connect() lblTestPump.set_text(str(self.ret_p)) if not smtConfig.has_section('Pump'): smtConfig.add_section('Pump') if self.ret_p: self.checkPump(self.client_p) smtConfig.set('Pump', 'host', pump_host) smtConfig.set('Pump', 'port', pump_port) with open(sCFGName, 'wb') as configfile: smtConfig.write(configfile) self.client_p.close() def checkPump(self,client_p): rr = client_p.read_holding_registers(500,100,unit=1) # conversione in bit array da 552 decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[52:53],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() bits_552[10] = True b_builder = BinaryPayloadBuilder(endian=Endian.Little) b_builder.add_bits(bits_552) reg_552 = b_builder.to_registers() rr.registers[52:53] = reg_552 for it in range(10): self.p_count += 1 rr.registers[50] = self.p_count rq = client_p.write_registers(500, rr.registers,unit=1) if rq.function_code < 0x80: rr_p = client_p.read_holding_registers(500,100,unit=1) if len(rr_p.registers)==100 and rr_p.registers[0]==self.p_count: decoder = BinaryPayloadDecoder.fromRegisters(rr_p.registers[2:7],endian=Endian.Little) # 502 bits_502 = decoder.decode_bits() bits_502 += decoder.decode_bits() # 503 bits_503 = decoder.decode_bits() bits_503 += decoder.decode_bits() # 504 bits_504 = decoder.decode_bits() bits_504 += decoder.decode_bits() # 505 bits_505 = decoder.decode_bits() bits_505 += decoder.decode_bits() # 506 bits_506 = decoder.decode_bits() bits_506 += decoder.decode_bits() if bits_502[7]: builder.get_object("switchPumpStatus").set_active(True) else: builder.get_object("switchPumpStatus").set_active(False) if bits_502[4] == False and bits_502[10] == True: builder.get_object("switchPumpStatus").set_sensitive(True) else: builder.get_object("switchPumpStatus").set_sensitive(False) else: print "errore checkPump %d" % self.p_count bits_552[10] = False print str(bits_552) b_builder = BinaryPayloadBuilder(endian=Endian.Little) b_builder.add_bits(bits_552) reg_552_2 = b_builder.to_registers() rr.registers[52:53] = reg_552_2 rq = client_p.write_registers(500, rr.registers,unit=1) if rq.function_code < 0x80: pass else: print "checkPump terminato con scrittura KO" def on_btnOpenFile_clicked(self,button): #os.system() subprocess.call(["libreoffice",export_csv_path]) def on_btnGetPump_clicked(self,button): self.adjustPMax.set_value(float(self.pmax) ) self.adjustQMax.set_value(float(self.qmax)) def send_parity(self): self.p_count += 1 rr_p = self.client_p.write_registers(550,self.p_count,unit=1) def on_btnSetPump_clicked(self,button): rr_p = self.client_p.read_holding_registers(500,100,unit=1) decoder = BinaryPayloadDecoder.fromRegisters(rr_p.registers[52:53],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() self.pmax = self.adjustPMax.get_value() _qmax = self.adjustQMax.get_value() self.p_count += 1 rr_p.registers[50] = self.p_count rr_p.registers[60] = int(self.pmax) if self.chkPAna.get_active(): self.qmax = getFlowRateAsVolts(_qmax) v = getVoltsFromFlowRate(self.qmax) print "_qmax => {0} self.qmax => {1} c => {2}".format(_qmax, self.qmax, v) rr_p.registers[64] = self.qmax rr_p.registers[62] = int(_qmax/litCiclo) bits_552[12] = True else: self.qmax = _qmax rr_p.registers[62] = int(self.qmax) rr_p.registers[64] = cicli_volt[int(self.qmax)] bits_552[12] = False b_builder = BinaryPayloadBuilder(endian=Endian.Little) # builder.add_bits(bits_502) b_builder.add_bits(bits_552) reg_552 = b_builder.to_registers() rr_p.registers[52:53] = reg_552 rr_p = self.client_p.write_registers(500,rr_p.registers,unit=1) def on_btnOff_clicked(self,button): print("Closing application") Gtk.main_quit() def on_btnLog_toggled(self,button): if button.get_active(): self.time = datetime.datetime.utcnow() self.blogFile = True else: self.blogFile = False builder.get_object("btnLog").set_label("Log Data") def readDataSetupConfig(self): self.pipeLength = float(builder.get_object("txtPipeLenght").get_text()) self.pipeDiam = float(builder.get_object("txtPipeDiam").get_text()) self.pipeType = builder.get_object("txtPipeType").get_text() self.mixType = builder.get_object("txtMixType").get_text() self.mixDensity = float(builder.get_object("txtMixDensity").get_text()) self.staticHead = float(builder.get_object("txtStaticHead").get_text()) self.hdlf_q2 = float(builder.get_object("txtQ2").get_text()) self.hdlf_q1 = float(builder.get_object("txtQ1").get_text()) self.hdlf_k = float(builder.get_object("txtK").get_text()) self.pR = int(builder.get_object("txtR").get_text()) self.designQmin = int(builder.get_object("txtQmin").get_text()) designRTW = int(builder.get_object("txtRefTime").get_text()) if designRTW*60 != self.lastPe.maxlen: print "resize RTW from {0} to {1}".format(self.lastPe.maxlen, designRTW*60) self.lastPe = collections.deque(self.lastPe, maxlen=designRTW*60) self.lastPg = collections.deque(self.lastPg, maxlen=designRTW*60) self.lastQ = collections.deque(self.lastQ, maxlen=designRTW*60) if not smtConfig.has_section('HeadLossFactor'): smtConfig.add_section('HeadLossFactor') smtConfig.set('HeadLossFactor', 'pipeLength', self.pipeLength) smtConfig.set('HeadLossFactor', 'pipeDiam', self.pipeDiam) smtConfig.set('HeadLossFactor', 'pipeType', self.pipeType) smtConfig.set('HeadLossFactor', 'mixType', self.mixType) smtConfig.set('HeadLossFactor', 'mixDensity', self.mixDensity) smtConfig.set('HeadLossFactor', 'staticHead', self.staticHead) smtConfig.set('HeadLossFactor', 'Q2', self.hdlf_q2) smtConfig.set('HeadLossFactor', 'Q1', self.hdlf_q1) smtConfig.set('HeadLossFactor', 'K', self.hdlf_k) if not smtConfig.has_section('Design'): smtConfig.add_section('Design') smtConfig.set('Design', 'R', self.pR) smtConfig.set('Design', 'Qmin', self.designQmin) smtConfig.set('Design', 'RTW', designRTW) with open(sCFGName, 'wb') as configfile: smtConfig.write(configfile) def on_switchPumpStatus_state_set(self, switch,gparam): self.ret_p=self.client_p.connect() rr = self.client_p.read_holding_registers(500,100,unit=1) # conversione in bit array da 552 decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[52:53],endian=Endian.Little) bits_552 = decoder.decode_bits() bits_552 += decoder.decode_bits() decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[2:7],endian=Endian.Little) # 502 bits_502 = decoder.decode_bits() bits_502 += decoder.decode_bits() # 503 bits_503 = decoder.decode_bits() bits_503 += decoder.decode_bits() # 504 bits_504 = decoder.decode_bits() bits_504 += decoder.decode_bits() # 505 bits_505 = decoder.decode_bits() bits_505 += decoder.decode_bits() # 506 bits_506 = decoder.decode_bits() bits_506 += decoder.decode_bits() bSendCommand = False if switch.get_active(): # %MW552:X2 START INIET. DA REMOTO bSendCommand = not bits_502[7] bits_552[2] = True bits_552[3] = False bits_552[14] = True else: # %MW552:X2 STOP INIET. DA REMOTO bSendCommand = bits_502[7] bits_552[2] = False bits_552[3] = True bits_552[14] = False builder = BinaryPayloadBuilder(endian=Endian.Little) # builder.add_bits(bits_502) builder.add_bits(bits_552) reg_552 = builder.to_registers() rr.registers[52:53] = reg_552 self.p_count += 1 rr.registers[50] = self.p_count if bSendCommand: self.client_p.write_registers(500, rr.registers,unit=1) if bits_552[2]: bits_552[2] = False builder = BinaryPayloadBuilder(endian=Endian.Little) # builder.add_bits(bits_502) builder.add_bits(bits_552) reg_552 = builder.to_registers() self.client_p.write_register(552, reg_552[0]) print "pulsante rilasciato" self.client_p.close() def on_btnShow_clicked(self,button): # show dlgRegistries self.lstDialog = builder.get_object("dlgRegistries") self.liststore = builder.get_object("liststore1") if self.ret_p: self.liststore.clear() rr = self.client_p.read_holding_registers(500,100,unit=1) for idx in [0,2,4,6,12,13,14,15,16,20,50,52,60,62,64]: if idx in (2,4,6,52): decoder = BinaryPayloadDecoder.fromRegisters(rr.registers[idx:idx+1],endian=Endian.Little) bits = decoder.decode_bits() bits += decoder.decode_bits() for ib, b in enumerate(bits): if b: sCode = "%MW5{0:02d}:X{1}".format(idx,ib) self.liststore.append([sCode,reg_descr[sCode], str( b ) ]) else: sCode = "%MW5{0:02d}".format(idx) self.liststore.append([sCode, reg_descr[sCode], str( rr.registers[idx]) ]) response = self.lstDialog.run() self.lstDialog.hide() def on_btnOk_clicked(self,button): self.lstDialog.close() def on_btnAnalyze_clicked(self,button): with open(export_csv_path, 'rb') as csvfile: template_vars = {} csv_reader = csv.DictReader(csvfile, delimiter=';') csv_list = list(csv_reader) data = [ np.asarray([row["q_Eng1"],row["dPManifold"],row["q_out"],row["dPPump"] , row["p_Eng1"],row["p_Eng2"]], dtype=np.float64) for row in csv_list] x1 = [d[0]/10. for d in data] y1 = [d[1]/10. for d in data] x2 = [d[2]*litCiclo for d in data] y2 = [d[3] for d in data] p1 = [d[4]/10. for d in data] p2 = [d[5]/10. for d in data] dP = [d[4]/10. - d[5]/10. for d in data] # The solution minimizes the squared error fit1_1, res1_1, _, _, _ = np.polyfit(x1, y1,1,full=True) fit1_2, res1_2, _, _, _ = np.polyfit(x1, y1,2,full=True) fit2_1, res2_1, _, _, _ = np.polyfit(x2, y2,1,full=True) fit2_2, res2_2, _, _, _ = np.polyfit(x2, y2,2,full=True) p_func_fit1_1 = np.poly1d(fit1_1) p_func_fit1_2 = np.poly1d(fit1_2) p_func_fit2_1 = np.poly1d(fit2_1) p_func_fit2_2 = np.poly1d(fit2_2) xp = np.linspace(np.min(x1), np.max(x1), 100) fig = plt.figure(figsize=(16, 9), dpi=100) plt.plot(x1, y1, 'b.', label='Samples') plt.plot(xp, p_func_fit1_1(xp), 'r--', label="Linear (e={0:.3f})".format(res1_1[0])) plt.plot(xp, p_func_fit1_2(xp), 'g-', label="Curved (e={0:.3f})".format(res1_2[0])) plt.xlabel('Flow Rate (lit/min)') plt.ylabel('Pressure (bar)') #plt.legend() plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=3, mode="expand", borderaxespad=0.) plt.grid(True) tex1 = r'$%.3fx^{2}%+.3fx%+.3f$' % tuple(fit1_2) plt.text(int(np.min(x1)),np.max(y1)*0.9, tex1, fontsize=16, va='bottom', color="g") template_vars["fit1_1"] = tuple(fit1_1) template_vars["fit1_2"] = tuple(fit1_2) template_vars["res1_1"] = res1_1 template_vars["res1_2"] = res1_2 imagefname = "hflf_1_{0}.png".format(sDate) imagefpath = os.path.join(sCurrentWorkingdir,"out",imagefname) template_vars["hflf_1"] = imagefpath plt.savefig(imagefpath,format="png", bbox_inches='tight', pad_inches=0) plt.close(fig) xp = np.linspace(np.min(x2), np.max(x2), 100) fig = plt.figure(figsize=(16, 9), dpi=100) plt.plot(x2, y2, 'b.', label='Samples') plt.plot(xp, p_func_fit2_1(xp), 'r--', label='Linear model (e={0:.3f})'.format(res2_1[0])) plt.plot(xp, p_func_fit2_2(xp), 'g-', label='Curved model (e={0:.3f})'.format(res2_2[0])) plt.xlabel('Flow Rate (lit/min)') plt.ylabel('Pressure (bar)') plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=3, mode="expand", borderaxespad=0.) plt.grid(True) tex1 = r'$%.3fx^{2}%+.3fx%+.3f$' % tuple(fit2_2) plt.text(int(np.min(x2)),np.max(y2)*0.9, tex1, fontsize=16, va='bottom', color="g") imagefname = "hflf_2_{0}.png".format(sDate) imagefpath = os.path.join(sCurrentWorkingdir,"out",imagefname) template_vars["hflf_2"] = imagefpath plt.savefig(imagefpath,format="png", bbox_inches='tight', pad_inches=0) plt.close(fig) # andamento pressione portata nel tempo fig = plt.figure(figsize=(16, 9), dpi=100) t = np.arange(len(p1)) a = fig.add_subplot(212) a.grid(True) for tick in a.xaxis.get_major_ticks(): tick.label.set_fontsize(10) for tick in a.yaxis.get_major_ticks(): tick.label.set_fontsize(10) a.set_xlabel('Time (seconds)') #a.set_ylim(np.min(dP)-2, np.max(dP)+2) a.set_ylim(np.min(p1)-2, np.max(p1)+2) a.set_xlim(0, len(t)+1) a.plot(t, p1, 'bo-', label='P1') a.plot(t, p2, 'ro-', label='P2') a.set_ylabel('Pressure (P bar)', fontsize=10) a.legend(loc=2, ncol=2, fontsize=10) a2 = fig.add_subplot(211) a2.grid(True) for tick in a2.xaxis.get_major_ticks(): tick.label.set_fontsize(10) for tick in a2.yaxis.get_major_ticks(): tick.label.set_fontsize(10) a2.set_xlabel('Time (seconds)') a2.set_ylabel('Flow rate (Q lit/min)', fontsize=10) a2.set_ylim(np.min(x1)-2, np.max(x1)+2) a2.set_xlim(0, len(t)+1) #a.plot(t, dP, 'r-', label='dP') a2.plot(t, x1, 'go-', label='Q') a2.legend(loc=2, ncol=2, fontsize=10) template_vars["t_items"] = list(t) template_vars["q_items"] = list(x1) template_vars["p1_items"] = list(p1) template_vars["p2_items"] = list(p2) template_vars["dp_items"] = list(dP) template_vars["pipeLength"] = self.pipeLength template_vars["pipeDiam"] = self.pipeDiam template_vars["pipeType"] = self.pipeType template_vars["mixType"] = self.mixType template_vars["mixDensity"] = self.mixDensity imagefname = "time_{0}.png".format(sDate) imagefpath = os.path.join(sCurrentWorkingdir,"out",imagefname) template_vars["time"] = imagefpath plt.savefig(imagefpath,format="png", bbox_inches='tight', pad_inches=0) plt.close(fig) template_vars["issue_date"] = datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S") env = Environment(loader=FileSystemLoader('.')) templateFile = "hdlf_template.html" templateFilePath = os.path.join(sCurrentWorkingdir,"out",templateFile) template = env.get_template(templateFile) html_out = template.render(template_vars) pdffname = "hdlf_{0}.pdf".format(sDate) pdfpath = os.path.join(sCurrentWorkingdir,"out",pdffname) HTML(string=html_out).write_pdf(pdfpath, stylesheets=["typography.css","grid.css"]) def on_switchMain_activate(self, switch,gparam): if switch.get_active(): self.client_1 = ModbusClient(manifold_host_1, port=manifold_port_1) self.client_p = ModbusClient(pump_host, port=pump_port) self.client_1.connect() self.client_p.connect() self.readDataSetupConfig() time.sleep(2) print "start connection" time_delay = 1 # 1 seconds delay self.loop = LoopingCall(f=self.logging_data, a=(self.client_1, builder.get_object("txtAIN1"),builder.get_object("txtAIN2"),builder.get_object("txtAIN1ENG"),builder.get_object("txtAIN2ENG"),builder.get_object("txtAIN12"),builder.get_object("txtAIN22"),builder.get_object("txtAIN1ENG2"),self.client_p,builder.get_object("txtPout"),builder.get_object("txtQout"))) self.loop.start(time_delay, now=False) # initially delay by time builder.get_object("btnOpenFile").set_sensitive(False) builder.get_object("btnOff").set_sensitive(False) self.btnAnalyze.set_sensitive(False) # self.ani = animation.FuncAnimation(self.figure, self.update_plot, interval = 1000) else: self.loop.stop() time.sleep(1) self.client_1.close() self.client_p.close() print "stop connection" time.sleep(2) builder.get_object("txtFilePath").set_text(export_csv_path) builder.get_object("btnOpenFile").set_sensitive(True) builder.get_object("btnOff").set_sensitive(True) if self.oneLogged: self.btnAnalyze.set_sensitive(True)
class ModbusIO(Component.generic): Name = "ModbusIO" xmlname="" sinkList = ['In'] sourceList = ['Out'] defaultConfig={} defaultState={} configuration={} modbus_ip="" modbus_period=0.1 modbus_read_adres=0 modbus_read_size=0 modbus_read_type=[] modbus_read_analog_threshold=[] modbus_write_adres=0 modbus_write_size=0 modbus_write_dict={} modbus_write_image=[] modbus_write_event=[] def __init__(self,componentId,xmlname): Component.generic.__init__(self,componentId) self.configuration=XmlDict.loadXml(xmlname) self.xmlname=xmlname #self.configuration=XmlDict.loadXml("global.xml") # Load Configuration for reading (input) self.modbus_ip=self.configuration["ip"]; self.modbus_period=1/float(self.configuration["update_frequency"]) self.modbus_read_adres=int(self.configuration["input"]["modbus_adres"]) self.modbus_read_size=int(self.configuration["input"]["modbus_register_count"]) self.modbus_read_type=[''] * self.modbus_read_size self.modbus_read_analog_threshold=[''] * self.modbus_read_size self.modbus_read_analog_scale=[''] * self.modbus_read_size self.modbus_read_event=[] # Load Configuration for writing (output) self.modbus_write_adres=int(self.configuration["output"]["modbus_adres"]) self.modbus_write_size=int(self.configuration["output"]["modbus_register_count"]) self.modbus_write_dict={} self.modbus_write_image=[0] * self.modbus_write_size self.modbus_write_event=[] self.prepareInputs() self.prepareOutputs() self.state_read_old = [0] * self.modbus_read_size self.state_read_new = [0] * self.modbus_read_size self.state_write = [0] * self.modbus_write_size self.state_write_changed=True #self.state_write[2]=1 #self.state_write[1]=16000 def prepareInputs(self): # Check inputs, if something is defined if (int(self.configuration["input"]["modbus_register_count"])>0): adres_definition=self.configuration["input"]["adres_definition"]["adres"] # Check that de definition fits with the reality if(self.modbus_read_size==len(adres_definition)): for adres in range(self.modbus_read_size): if(adres_definition[adres]["type"].lower()=="digital"): self.modbus_read_type[adres]="D" for bit in range(16): # add event to the list event_name=None if(adres_definition[adres].has_key("event_" + str(bit))): event_name = adres_definition[adres]["event_" + str(bit)] if(event_name==None): event_name="DI" + str(adres) + "b" + str( bit ) self.modbus_read_event.append(event_name) adres_definition[adres]["event_" + str(bit)] = event_name # end for bit elif(adres_definition[adres]["type"].lower()=="analog"): self.modbus_read_type[adres]="A" threshold=float(adres_definition[adres]["threshold"])*float(adres_definition[adres]["scale"]) self.modbus_read_analog_threshold[adres]=int(threshold) self.modbus_read_analog_scale[adres]=float(adres_definition[adres]["scale"]) # Add event to the list event_name = adres_definition[adres]["event"] if(event_name==None): event_name="AI" + str(adres) adres_definition[adres]["event"] = event_name self.modbus_read_event.append(event_name) # end for adres # end if self.sourceList = self.modbus_read_event def prepareOutputs(self): # Check outputs, if something is defined if (int(self.configuration["output"]["modbus_register_count"])>0): adres_definition=self.configuration["output"]["adres_definition"]["adres"] # Check that de definition fits with the reality if(self.modbus_write_size==len(adres_definition)): for adres in range(self.modbus_write_size): if(adres_definition[adres]["type"].lower()=="digital"): for bit in range(16): # add event to the list event_name=None if(adres_definition[adres].has_key("event_" + str(bit))): event_name = adres_definition[adres]["event_" + str(bit)] if(event_name==None): event_name="DO" + str(adres) + "b" + str( bit ) self.modbus_write_event.append(event_name) self.modbus_write_dict[event_name]={"adres":adres,"bit":bit,"type":"D"} adres_definition[adres]["event_" + str(bit)] = event_name # end for bit elif(adres_definition[adres]["type"].lower()=="analog"): # Add event to the list event_name = adres_definition[adres]["event"] if(event_name==None): event_name="AO" + str(adres) adres_definition[adres]["event"] = event_name self.modbus_write_dict[event_name]={"adres":adres,"type":"A"} self.modbus_write_event.append(event_name) # end for adres # end if self.sinkList = self.modbus_write_event def catchEvent(self,event,value): logger=logging.getLogger("service") if (self.modbus_write_dict.has_key(event)): if(self.modbus_write_dict[event]["type"]=="D"): current=self.state_write[self.modbus_write_dict[event]["adres"]] bitposition=self.modbus_write_dict[event]["bit"] if(bool(value["value"])): target = (current | ( 1 << bitposition)) else: target =(current & (~(1<<bitposition))) self.state_write[self.modbus_write_dict[event]["adres"]]=int(target) elif(modbus_write_dict[event]["type"]=="A"): self.state_write[self.modbus_write_dict[event]["adres"]]=int(value["value"]) self.state_write_changed=True else: logger.error("Event not found(modbus): " + eventName) def start(self): # Connect the client self.client = ModbusTcpClient(self.modbus_ip) logger=logging.getLogger("service") logger.info("Starting Service: " + self.componentId + " (ModbusIO: " + self.xmlname + ").") while (GlobalObjects.running): if(self.client.connect()): # Check if the output variables changed, if needed send the new state if (self.state_write_changed): self.state_write_changed = False try: self.client.write_registers(self.modbus_write_adres,self.state_write) except (AttributeError, ConnectionException): state_read_new=self.state_read_old pass # sleep a while time.sleep(self.modbus_period) # try to read new state of the inputs, if connection fails, continue try: state_read_new = self.client.read_holding_registers(self.modbus_read_adres, self.modbus_read_size).registers except (AttributeError, ConnectionException): state_read_new=self.state_read_old pass # Read check every register for changes for i in range( len(state_read_new)): if (state_read_new[i]!=self.state_read_old[i]): # When the change is in a DI if (self.modbus_read_type[i]=='D'): # Mark changed positions changed=state_read_new[i]^self.state_read_old[i] for j in range(16): if((changed >> j) & 1): # Generate event eventName=self.configuration["input"]["adres_definition"]["adres"][i]["event_" + str(j)] self.generateEvent(eventName,{'value':((state_read_new[i]>>j) & 1)}) #print str(time.time()) + " " + str(i) + "." + str(j) + ": " + str((state_read_new[i]>>j) & 1) ## Save the new state self.state_read_old[i]=state_read_new[i] # When the change is in a AI elif (self.modbus_read_type[i]=='A'): diff = (state_read_new[i]-self.state_read_old[i]) if ((diff>self.modbus_read_analog_threshold[i]) or (diff < -self.modbus_read_analog_threshold[i])): # Generate event eventName=self.configuration["input"]["adres_definition"]["adres"][i]["event"] value = float(state_read_new[i]) / self.modbus_read_analog_scale[i] self.generateEvent(eventName,{'value':value}) #print str(i) + ": " + str(value) ## Save new state self.state_read_old[i]=state_read_new[i] else: logger.warning("Lost connection to modbus module.") self.state_write_changed=True time.sleep(1)
assert(rq.function_code < 0x80) # 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=1) assert(rq.function_code < 0x80) # test that we are not an error log.debug("Write to a holding register and read back") rq = client.write_register(1, 10, unit=1) rr = client.read_holding_registers(1, 1, unit=1) assert(rq.function_code < 0x80) # 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=1) rr = client.read_holding_registers(1, 8, unit=1) assert(rq.function_code < 0x80) # 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=1) assert(rq.function_code < 0x80) # 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")
class DevBase(object): def __init__(self, name, url='0.0.0.0', unit=1, regs_r_address=10000, reg_r_num=0, regs_w_address=0, reg_w_num=0): # device info self.summary = str(name) + ' ' self.regsR = [] self.regsRLast = [] self.regsW = [] # devices registers info self.regsRInter = 1 self.regsWInter = 1 self.unit = unit self.regsRAddress = regs_r_address self.regsRNum = reg_r_num self.regsWAddress = regs_w_address self.regsWNum = reg_w_num # data sharing info # self.filePath = inspect.getfile(inspect.currentframe()) + str(name) + '.dat' self.filePath = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + '/' + str( name) + '.dat' self.file = '' self.normalizeLen = 32 self.create_data_file() self.mmapData = mmap.mmap(self.file.fileno(), 0) # devices address info self.url = url self.modbusClient = ModbusTcpClient(self.url) self.readingTimer = Timer(self.regsRInter, self.__read_regs__) self.writingTimer = Timer(self.regsWInter, self.__send_regs__) # for internal using self.regs_r_pos = 0 self.regs_w_pos = self.regs_r_pos + self.regsRNum * self.normalizeLen + 1 # skip the first line and symbol of newline def create_data_file(self): open(self.filePath, "w+").close() # create an empty file self.file = open(self.filePath, 'r+') for i in range(0, self.regsRNum): self.file.write(self.normalizeLen * '0') self.file.write('\n') # the second line for writing self.file.write('0') # 1 means ready to send regs_w to devices for i in range(0, self.regsWNum): self.file.write(self.normalizeLen * '0') self.file.seek(0) def __normalize_num__(self, src): # numbers to strings target = [] for i, d1 in enumerate(src): d1 = str(d1) if len(d1) < self.normalizeLen: target.append(' ' * (self.normalizeLen - len(d1)) + str(d1)) elif len(d1) == self.normalizeLen: target.append(str(d1)) else: print('item: \"', d1, '\" index: \"', i, '\" too long...') target.append(d1[:self.normalizeLen]) return target def compare_regs_r_last(self): for i, j in zip(self.regsR, self.regsRLast): if i != j: return False return True def __write_regs_to_mmap__(self): data = self.__normalize_num__(self.regsR) print(data) for i in range(0, self.regsRNum - 1): self.mmapData[i * self.normalizeLen:(i + 1) * self.normalizeLen] = bytes(data[i], 'utf8') def __read_regs__(self): # print 'reading...' try: res = self.modbusClient.read_holding_registers(address=self.regsRAddress, count=self.regsRNum, unit=self.unit) self.regsR = res.registers print('read registers: \t', self.regsR) if self.compare_regs_r_last(): # write to mmap only the data is different with last time pass else: self.regsRLast = self.regsR self.__write_regs_to_mmap__() regs_r_changed() except pymodbus.exceptions.ConnectionException: print('Communication failed ...') finally: self.readingTimer.run() if len(self.regsR) == self.regsRNum: print('Reading success...') def __send_regs__(self): self.regsW = [] print(self.mmapData.readline()) for i in range(0, self.regsWNum): d1_begin = self.regs_w_pos + i * self.normalizeLen d1_end = self.regs_w_pos + (i + 1) * self.normalizeLen d1 = str(self.mmapData[d1_begin:d1_end]) d1 = d1.strip() self.regsW.append(int(d1)) print(self.regsW) try: res = self.modbusClient.write_registers(address=self.regsWAddress, values=self.regsW, unit=self.unit) print('write registers: \t', self.regsW, 'result: ', res) self.__write_regs_to_mmap__() except pymodbus.exceptions.ConnectionException: print('Communication failed ... ') except pymodbus.exceptions.IndexError: print('Writing failed ... ', sys.exc_info()) finally: self.writingTimer.run() def __check_net_OK__(self): import subprocess res = subprocess.call("ping -c 1 %s" % self.url, shell=True, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT) if res == 0: return True else: return False def start_data_server(self): print('starting update data ... \n', time.ctime()) if self.__check_net_OK__(): self.readingTimer.start() self.writingTimer.start() else: print('Can not access', self.url) def stop_data_server(self): print('stopping update data ... \n', time.ctime()) self.readingTimer.cancel() self.writingTimer.cancel()
class TestModbusTcp(unittest.TestCase): def __init__(self, methodName='runTest'): unittest.TestCase.__init__(self, methodName) def setUp(self): self.client = ModbusTcpClient(client_ip) def tearDown(self): self.client.close() def _checked_read(self, address, length, unit=1): result = self.client.read_holding_registers(address, length, unit=unit) self.assertLess(result.function_code, 0x80) self.assertEqual(len(result.registers), length) return result.registers def _checked_write(self, address, value, unit=1): result = self.client.write_register(address, value, unit=unit) self.assertLess(result.function_code, 0x80) def test_1(self): # Test reading ve.bus address 33 until 36 self._checked_read(3,34, unit=246) def test_2to5(self): # Write multi /Mode and reset again r = self._checked_read(33, 1, unit=246) self._checked_write(33, 2, unit=246) r2 = self._checked_read(33, 1, unit=246) self._checked_write(33, r[0], unit=246) r3 = self._checked_read(33,1, unit=246) self.assertEqual(r2[0], 2) self.assertEqual(r[0], r3[0]) def test_6(self): # Test function code 4, read_input_registers address 256 until 267 self._checked_read(259, 2, unit=245) def test_7to9(self): # Test function code 16 r = self._checked_read(33, 1, unit=246) result = self.client.write_registers(33, [2], unit=246) self.assertTrue(result.function_code < 0x80) r2 = self._checked_read(33, 1, unit=246) result = self.client.write_registers(33, [r[0]], unit=246) self.assertTrue(result.function_code < 0x80) r3 = self._checked_read(33,1, unit=246) self.assertEqual(r2[0], 2) self.assertEqual(r[0], r3[0]) def test_10(self): # Test function code 16, write_registers address 256 until 267" result = self.client.write_registers(22, [100], unit=246) self.assertLess(result.function_code, 0x80) def test_11(self): # Test writing to ve.bus /State. result = self.client.write_register(31, 2, unit=246) self.assertGreaterEqual(result.function_code, 0x80) def test_12(self): # Test reading service without /DeviceInstance result = self._checked_read(2701, 1, unit=0) self.assertGreaterEqual(result[0], 0) self.assertLessEqual(result[0], 100) def test_13(self): # Test writing to service without /DeviceInstance prev = self._checked_read(2702, 1, unit=0) self._checked_write(2702, 35, unit=0) current = self._checked_read(2702, 1, unit=0) self.assertEqual(current[0], 35) self._checked_write(2702, prev[0], unit=0) current = self._checked_read(2702, 1, unit=0) self.assertEqual(current[0], prev[0]) def test_14(self): # Test reading a string # Register 800 return the MAC address of the CCGX as string. result = self._checked_read(800, 6, unit=0) bytes = b'' for r in result: bytes += chr(r >> 8) bytes += chr(r & 255) mac_address = int(struct.unpack('12s', bytes)[0], 16)
class modbus(): #################################################################################################### # # # # # #################################################################################################### def __init__(self, smarthome, device='', timeout=None, port=502, cycle=5, pe_adress = 0, pe_length= 0, pa_adress= 0, pa_length= 0): ##Initialdaten aus Plugin.conf self._sh = smarthome self._items = {} self.timeout = float(timeout) self.device = str(device) self.port = int(port) self.cycle = int(cycle) #Inputs self.pe_adress = int(pe_adress) self.pe_lenght = int(pe_length) #Outputs self.pa_adress = int(pa_adress) self.pa_lenght = int(pa_length) ###################################### self._db = {}##ausgangsbytes self._db['in'] = {} self._db['out'] = {} #1: bool 0...1 #5: 8-bit signed value 0...255 #5.001: 8-bit unsigned value 0...100 #6: 8-bit signed value -128...127 #7: 16-bit unsigned value 0...65535 #8: 16-bit signed value -32768...32767 #9: floating point -671088,64 - 670760,96 self._db['dpt'] = {1:1, 5:8, 5.001:8, 6:8, 7:16, 8:16}##dpt und länge in bits self.init_read = 0 self._lock = threading.Lock() self.connected = False logger.info('Initialising Modbus TCP PLUGIN###############################################') smarthome.connections.monitor(self) def run(self):##plugin starten self.alive = True self._sh.scheduler.add('Modbus', self.refresh, cycle=self.cycle) logger.info('MODBUS: Started!') def stop(self):##plugin stoppen self.alive = False self._socket.close() logger.info('MODBUS: Stopped!') def parse_logic(self, logic):##nicht benoetigt pass def connect(self): #Verbinden/socket oeffnen self._lock.acquire() target = None try: if self.device is not None: self._modbuspy = ModbusTcpClient(self.device, self.port) self._modbuspy.connect() except Exception as e: logger.error('MODBUS: Could not connect to {}: {}'.format(self.device, e)) self._lock.release() return else: logger.info('MODBUS: Connected to {}'.format(self.device)) self.connected = True self._lock.release() def disconnect(self): #Verbindung trennen/socket schließen if self.connected: try: if self_socket is not None: client.close() except: pass logger.info('MODBUS: Disconnected!') self.connected = False self._target = None #################################################################################################### #HAUPTFUNKTION(main) #Funktion wird zyklisch von Smarthome aufgerufen: # # # #################################################################################################### def refresh(self): logger.debug('MODBUS cycle started########################################################') if self.connected: if self.init_read == 0: #1 start Ausgangsregister lesen self.read('out') self.init_read = 1 pprint(self._db) start = time.time() werte = self.read() self.write() cycletime = time.time() - start logger.debug("Modbus cycle takes {0} seconds".format(cycletime)) else: self.connect()#neu pass #################################################################################################### #Items beim start überprüfen, auf modbus_on = 1 #Items Namen (gads) und Bytes werden peb und pab zugeordnet #Bits werden in Bytes einsortiert # # #################################################################################################### def parse_item(self, item): if 'modbus_on' in item.conf: byte = int(item.conf['modbus_byte']) if 'modbus_bit' in item.conf: bit = int(item.conf['modbus_bit']) else: bit = None ##Daten zusammenstellen daten = [] daten.append(bit) #0 if 'modbus_dpt' in item.conf: daten.append(item.conf['modbus_dpt']) #1 daten.append(item()) #2 else: #oder daten.append(1) #1 daten.append(bool(item())) #2 daten.append(item) #3 #pprint(daten) #datensatz pro item ##Unterscheidung in in/outputs if self.pe_adress <= byte <= (self.pe_adress+self.pe_lenght): ##INPUTS if not byte in self._db['in'].keys(): self._db['in'][byte] = [] self._db['in'][byte].append(daten) elif self.pa_adress <= byte <= (self.pa_adress+self.pa_lenght): ##OUTPUTS if byte not in self._db['out'].keys(): self._db['out'][byte] = [] self._db['out'][byte].append(daten) return None #################################################################################################### ##Item hat sich verändert, wird von Smarthome aufgerufen, bei item(name, caller...) ##self._DB updaten! # # # #################################################################################################### def update_item(self, item, caller=None, source=None, dest=None): if caller == 'modbus': pass #################################################################################################### #AusgangsWORTe an Steuerung schreiben # # # # #################################################################################################### def write(self): try: lb = 00000000 hb = 00000000 #### byte besteht immer aus 16 bits for byte in self._db['out']: for bit in sorted(self._db['out'][byte]): if bit in self._db['out'][byte]: bitpos = bit[0] #startbit/bitposition des binärwertes type = bit[1] value = bit[2] name = bit[3] bit[2] = bit[3]() ##aktueller wert des items abrufen und value updaten! builder = BinaryPayloadBuilder(endian=Endian.Little) ##unterscheidung dateityp if type == '5' or type == '5.001' or type == '6' : ##8bit uint / int length = 8 if bitpos < 8: #lb lb = value else: #hb hb = value if type == '5': builder.add_8bit_uint(lb) builder.add_8bit_uint(hb) #logger.debug('MODBUS: 8bit uint {0} ; {1}'.format(lb,hb)) elif type == '5.001': ##0-100 in 0-255 umwandeln! #print(dpts.en5001(lb)) #print(dpts.en5001(hb)) lb = self.de5001(lb) hb = self.de5001(hb) #print("lb geschrieben", lb ) #print("hb geschrieben", hb ) builder.add_8bit_uint(lb) builder.add_8bit_uint(hb) #logger.debug('MODBUS: 8bit uint {0} ; {1}'.format(lb,hb)) elif type == '6': if lb > 127: lb = 127 elif lb < -128: lb = -128 if hb > 127: hb = 127 elif hb < -128: hb = -128 builder.add_8bit_int(lb) builder.add_8bit_int(hb) #logger.debug('MODBUS: 8bit int {0} ; {1}'.format(lb.hb)) elif type == '7' or type == '8': #16bit uint / int length = 16 if type == '7': #0...65535 builder.add_16bit_uint(value) #logger.debug('MODBUS: 16bit uint {0} '.format(value)) else: #-32768...32767 builder.add_16bit_int(value) #logger.debug('MODBUS: 16bit int {0}'.format(value)) elif type == '1': length = 1 #nur pro byte einmal die bits wandeln if bitpos < 8: #lb lb = lb | int(value) << bitpos #logger.debug('MODBUS: 8bit int{0}'.format(lb)) else: #hb hb = hb | int(value) << bitpos #logger.debug('MODBUS: 8bit int{0}'.format(hb)) builder.add_8bit_uint(lb) builder.add_8bit_uint(hb) payload = builder.build() logger.debug('MODBUS: write to PLC: WORD {0} set to {1} '.format(byte,payload)) self._modbuspy.write_registers(byte, payload, skip_encode=True) builder.reset() except Exception as e: logger.error('MODBUS: Could not write an OutWord, because {}'.format(e)) self._lock.release() return None #################################################################################################### #Liest komplett angegebenen Speicherbereich aus Steuerung aus und gibt sie in dict zurück! #read = anfangswert, end= länge #Eingangsbereich von Steuerung lesen # # #################################################################################################### def read(self, iO='in'): #print('DATEN VOM BUS LESEN') i = 0 if iO !='in': x = 'out' else: x = 'in' try: for byte in self._db[x]: rr = self._modbuspy.read_holding_registers(byte,2) pprint(rr) decodert2 = BinaryPayloadDecoder.fromRegisters(rr.registers, endian=Endian.Little) ##prüfen welcher dpt typ vorliegt und dann das registerabfrage ergebnis aufdröseln: #->decode_16bit_uint() -> 7 / 8 #->decode_8bit_uint() -> 5 | 5.001 #->decode_8bit_int() -> 6 #->decode_bits() -> 1 for bit in self._db[x][byte]: ##eintraege in dict durchgehen bitpos = bit[0] type = bit[1] name = bit[3] if type == '5' or type == '5.001' or type == '6': ##8bit uint / int length = 8 if type == '6': lb = decodert2.decode_8bit_int() hb = decodert2.decode_8bit_int() elif type == '5' or type == '5.001': lb = decodert2.decode_8bit_uint() hb = decodert2.decode_8bit_uint() if bitpos < 8:#lb value = hb #logger.debug('MODBUS: byte{0} startpos{1} wert (5) {2}'.format(bit, bitpos,value)) else:#hb value = lb #logger.debug('MODBUS: byte{0} startpos{1} wert (5) {2}'.format(bit, bitpos,value)) if type == '5.001': #print('lb/hb Daten gelesen', value) value = self.en5001(value) #logger.debug('MODBUS: byte{0} startpos{1} wert (5.001) {2}'.format(bit, bitpos, value)) elif type == '7' or type == '8': #16bit uint / int length = 16 if type == '7': #0...65535 value = decodert2.decode_16bit_uint() #logger.debug('MODBUS: 16bit uint{0}'.format(value)) else: #-32768...32767 value = decodert2.decode_16bit_int() #logger.debug('MODBUS: 16bit int{0}'.format(value)) elif type == '1': length = 1 hb = decodert2.decode_bits() lb = decodert2.decode_bits() bits = lb+hb value = bits[bitpos] #logger.debug('MODBUS: Bits{0}'.format(bits)) bit[2] = value #zurückspeichern decodert2.reset() ##Debug################################################################################# bit[3](value, caller='modbus') i = i+1 lb = decodert2.decode_bits() hb = decodert2.decode_bits() bits = hb+lb decodert2.reset() logger.debug('MODBUS: read from PLC {0}-{1} {2}'.format(byte, bits, bytes)) except Exception as e: logger.error('MODBUS: Could not read an InputWord, because {}'.format( e)) self._lock.release() return None i = 0 return None #################################################################################################### #wandelt str in binary ohne führendes 0b #und invertiert auf wunsch das Ergebnis! # # # #################################################################################################### def toBinary2(self, n, invert = 1):## byte = '{:08b}'.format(n) i = int(16)-len(byte) ausgabe = "" for x in range(0,i): ausgabe = "0"+ausgabe ausgabe = ausgabe+byte if invert == 1:#invertieren ausgabe = ausgabe[::-1] return ausgabe def toBinary(self, n, invert = 0):## byte = '{:08b}'.format(n) if invert == 1:#invertieren byte = byte[::-1] ausgabe = [] if byte == '00000000': ausgabe.append('00000000') ausgabe.append('00000000') elif byte < '256' : ausgabe.append(byte[0:8]) ausgabe.append('00000000') else: ausgabe.append(byte[0:8]) ausgabe.append(byte[8:17]) return ausgabe def de5001(self, value): #8bit 0-100 auf 0-255 normieren if value > 255: value = 255 elif value < 0: value = 0 return int(round(value*2.55)) def en5001(self, value): #8bit auf 0-100 normieren if value > 255: value = 255 elif value < 0: value = 0 return (round((value/2.55), 2))
print 'epx ' , gpsd.fix.epx print 'epv ' , gpsd.fix.epv print 'ept ' , gpsd.fix.ept print 'speed (m/s) ' , gpsd.fix.speed print 'climb ' , gpsd.fix.climb print 'track ' , gpsd.fix.track print 'mode ' , gpsd.fix.mode print print 'sats ' , gpsd.satellites builder.add_32bit_float(gpsd.fix.latitude) builder.add_32bit_float(gpsd.fix.longitude) payload = builder.build() #print payload client.write_registers(0, payload, skip_encode=True) time.sleep(1) #set to whatever payload = builder.reset() #except ConnectionException as e: #when you press ctrl+c # print "\nKilling Thread...Modbus server not running" # print e # gpsp.running=False # client.close() except (KeyboardInterrupt, SystemExit): print "\nKilling Thread..." gpsp.running = False client.close() gpsp.join() # wait for the thread to finish what it's doing
#Its is the motor cos? and 0.5<motor_power_factor<0.97. ramp_mode=2# parm 30 Standard Std (2) without dynamic braking resistor, If with this resistor, should set to 0 or # Fast dynamicVtoF='OFF'# parm 32 - It should not be used when the drive is being used as a soft start to full speed. keep off voltage_mode_select=2 #parm 41 fixed boost mode(2) low_freq_voltage_boost=1 #% 0.5< low_freq_voltage_boost<1 __config__={ip:'127.0.0.1',min_speed:0.1,max_speed:60.0,acc_rate:33.0,dec_rate:33.0,motor_rated_speed:0, motor_rated_voltage:230,motor_power_factor:0.85,ramp_mode:2,dynamicVtoF:'OFF', voltage_mode_select:2, low_freq_voltage_boost:1} #open connection with sk commander # default port: 502 # change the ip below to the commander ip of your network #starting connection sk=ModbusTcpClient(ip) if sk.connect(): builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_32bit_float(321.57) payload = builder.build() result = sk.write_registers(4005, payload, skip_encode=True) sk.close() exit()
def run_binary_payload_ex(): # ----------------------------------------------------------------------- # # We are going to use a simple client to send our requests # ----------------------------------------------------------------------- # client = ModbusClient('127.0.0.1', port=5440) client.connect() # ----------------------------------------------------------------------- # # If you need to build a complex message to send, you can use the payload # builder to simplify the packing logic. # # Here we demonstrate packing a random payload layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - another 16 bit unsigned int 0x5678 # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # - an 32 bit uint 0x12345678 # - an 32 bit signed int -0x1234 # - an 64 bit signed int 0x12345678 # The packing can also be applied to the word (wordorder) and bytes in each # word (byteorder) # The wordorder is applicable only for 32 and 64 bit values # Lets say we need to write a value 0x12345678 to a 32 bit register # The following combinations could be used to write the register # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # # Word Order - Big Byte Order - Big # word1 =0x1234 word2 = 0x5678 # Word Order - Big Byte Order - Little # word1 =0x3412 word2 = 0x7856 # Word Order - Little Byte Order - Big # word1 = 0x5678 word2 = 0x1234 # Word Order - Little Byte Order - Little # word1 =0x7856 word2 = 0x3412 # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # # ----------------------------------------------------------------------- # builder = BinaryPayloadBuilder(byteorder=Endian.Little, wordorder=Endian.Big) builder.add_string('abcdefgh') builder.add_32bit_float(22.34) builder.add_16bit_uint(0x1234) builder.add_16bit_uint(0x5678) builder.add_8bit_int(0x12) builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0]) builder.add_32bit_uint(0x12345678) builder.add_32bit_int(-0x1234) builder.add_64bit_int(0x1234567890ABCDEF) payload = builder.build() address = 0 client.write_registers(address, payload, skip_encode=True, unit=1) # ----------------------------------------------------------------------- # # If you need to decode a collection of registers in a weird layout, the # payload decoder can help you as well. # # Here we demonstrate decoding a random register layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - another 16 bit unsigned int which we will ignore # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # ----------------------------------------------------------------------- # address = 0x00 count = len(payload) result = client.read_holding_registers(address, count, unit=1) print("-" * 60) print("Registers") print("-" * 60) print(result.registers) print("\n") decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Little, wordorder=Endian.Big) decoded = { 'string': decoder.decode_string(8), 'float': decoder.decode_32bit_float(), '16uint': decoder.decode_16bit_uint(), 'ignored': decoder.skip_bytes(2), '8int': decoder.decode_8bit_int(), 'bits': decoder.decode_bits(), "32uints": decoder.decode_32bit_uint(), "32ints": decoder.decode_32bit_int(), "64ints": decoder.decode_64bit_int(), } print("-" * 60) print("Decoded Data") print("-" * 60) for name, value in iteritems(decoded): print("%s\t" % name, hex(value) if isinstance(value, int) else value) # ----------------------------------------------------------------------- # # close the client # ----------------------------------------------------------------------- # client.close()
class clientthreads(threading.Thread): def __init__(self, vnic, ipaddr, port): threading.Thread.__init__(self) self.ipaddr = ipaddr # ip address self.port = port # port address self.vnic = vnic # virtual nic self.mode = "" # server or client self.state = "" # up or down self.dest = "" # destination address for client self.clientstop = threading.Event() self.server = "" self.client = "" self.framer = "" self.vnicm = "" self.runtime= 0 self.delayr = random.uniform(0,5) self.delayw = random.uniform(0,60) self.firstdelay = 0 self.pstart= "" def run(self): self.client = ModbusTcpClient(self.dest, self.port, source_address=(self.ipaddr, 0), retries=1, retry_on_empty=True) if(self.mode=="read"): self.clientintr() elif(self.mode=="write"): self.clientintw() else: print "wrong mode specified" def clientintr(self): # instantiate server stuff while(not self.clientstop.is_set()): if(time.time() - self.pstart > self.runtime): print "stopping" break if(self.firstdelay < 1): print "Start RDelay is: " + str(self.delayr) time.sleep(self.delayr) self.firstdelay = 1 print "Starting Reads" self.clientreads() print "\n\r-----read-----\n\r" print self.dest print time.time() - self.pstart print "------------------\n\r" def clientintw(self): # instantiate server stuff while(not self.clientstop.is_set()): if(time.time() - self.pstart > self.runtime): print "stopping" break if(self.firstdelay < 1): print "Start WDelay is: " + str(self.delayw) time.sleep(self.delayw) self.firstdelay = 1 print "Starting Writes" self.clientwrites() print "\n\r-----write----\n\r" print self.dest print time.time() - self.pstart print "------------------\n\r" def clientreads(self): self.client.read_coils(1, 10) self.client.read_discrete_inputs(1, 10) self.client.read_holding_registers(1, 10) self.client.read_input_registers(1, 10) time.sleep(5) def clientwrites(self): self.client.write_coil(1, True) self.client.write_register(1, 3) self.client.write_coils(1, [True]*10) self.client.write_registers(1, [3]*10) time.sleep(60) def alloc(self): # Allocate ip address if (validateIP(self.ipaddr, self.vnicm)): cmdargs = [self.vnic, self.ipaddr] subprocess.call(["ifconfig"] + cmdargs) else: return 0 def dealloc(self): # De-allocate ip address cmdargs = [self.vnic] subprocess.call(["ifconfig"] + cmdargs + ["down"]) def stop(self): self.clientstop.set() return
# # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # ---------------------------------------------------------------------------# builder = BinaryPayloadBuilder(endian=Endian.Little) builder.add_string("abcdefgh") builder.add_32bit_float(22.34) builder.add_16bit_uint(0x1234) builder.add_8bit_int(0x12) builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0]) payload = builder.build() address = 0x01 result = client.write_registers(address, payload, skip_encode=True) # ---------------------------------------------------------------------------# # If you need to decode a collection of registers in a weird layout, the # payload decoder can help you as well. # # Here we demonstrate decoding a random register layout, unpacked it looks # like the following: # # - a 8 byte string 'abcdefgh' # - a 32 bit float 22.34 # - a 16 bit unsigned int 0x1234 # - an 8 bit int 0x12 # - an 8 bit bitstring [0,1,0,1,1,0,1,0] # ---------------------------------------------------------------------------# address = 0x01
# TODO: check retries, and other options client = ModbusClient(args.ip, port=args.port) # retries=3, retry_on_empty=True) client.connect() # TODO: check if asserts are slowing down read/write if args.mode == 'w': # NOTE: write_register if args.type == 'HR': if args.count == 1: hr_write = client.write_register(args.offset, args.register[0]) assert(hr_write.function_code < 0x80) else: hrs_write = client.write_registers(args.offset, args.register) assert(hrs_write.function_code < 0x80) # NOTE: write_coil: map integers to bools elif args.type == 'CO': if args.count == 1: # NOTE: coil is a list with one bool if args.coil[0] == 1: co_write = client.write_coil(args.offset, True) else: co_write = client.write_coil(args.offset, False) assert(co_write.function_code < 0x80) else: coils = []