def setRelayState(interlock: Interlock_model, state: {0, 1}) -> Interlock_model.State: client = ModbusTcpClient(interlock.card.server) client.connect() client.write_coil(interlock.channel, state, unit=1) sleep(0.3) reply = client.read_coils(interlock.channel, 1, unit=1) state = reply.bits[0] client.close() if state == ModbusInterlock.MODBUS_OFF: return Interlock_model.State.LOCKED elif state == ModbusInterlock.MODBUS_ON: return Interlock_model.State.UNLOCKED
class MBPLC(PLC): """PLC con comunicación Modbus. Args: address (str): Dirección IP (o nombre) del controlador. port (int): Puerto de conexión. Típicamente el 502. unit (int): Número de esclavo. method (str): Método de conexión (RTU/ASCII) retries (int): Reintentos de lectura/escritura. client (ModbusClient): Cliente modbus. pollingtime (float): Segundos entre escaneos. Attributes: coil (Memory): Memoria de bobinas. input (Memory): Memoria de entradas digitales. holding (Memory): Memoria de registros de retención. register (Memory): Memoria de registros de entrada. client (ModbusClient): Cliente Modbus. thread (Thread): Hebra de escaneo. """ class COIL: """Tipo de memoria COIL.""" pass class INPUT: """Tipo de memoria INPUT.""" pass class HOLDING: """Tipo de memoria HOLDING.""" pass class REGISTER: """Tipo de memoria REGISTER.""" pass class Memory(PLC.Memory): ''' Representacióne un área de memoria. Args: plc (PLC): Controlador al que pertenece. memorytype (type): Tipo de memoria (COIL, INPUT, HOLDING, REGISTER). Attributes: minindex (int): Dirección más baja de la memoria leída. maxindex (int): Dirección más alta de la memoria leída. ''' class Tag(PLC.Memory.Tag): ''' Variable de controlador Modbus. Args: memory (Memory): Memoria a la que pertenece. key (str): Nombre. description (str): Descripción. address: Dirección (None si no esta asociada). Attributes: value: Valor. subscriptor (Subcriptor[]): Objetos suscritos a los cambios. ''' def __init__(self, memory:PLC.Memory, key:str, description:str="", address=None): if type(address)==str: address=int(address) super().__init__(memory,key,description,address) if memory.minindex is None or memory.minindex>address: memory.minindex=address if memory.maxindex is None or memory.maxindex<address: memory.maxindex=address def set(self, value): ''' Modifica el valor de una variable. Args: value: Nuevo valor de la variable. ''' plc=self.memory.plc if plc.connected: try: if self.memory.memorytype==MBPLC.COIL: if isinstance(value,str): if value.upper()=="TRUE" or value=="1": value=True elif value.upper()=="FALSE" or value=="0": value=False rw = plc.client.write_coil(self.address,value,unit=plc.unit) if self.memory.memorytype==MBPLC.HOLDING: if isinstance(value,str): value=int(value) rw = plc.client.write_register(self.address,value,unit=plc.unit) self.update(value) except Exception as e: self.memory.plc.connected=False printexception(e,"Error writing to PLC") def __init__(self, plc:PLC, memorytype:type): self.memorytype=memorytype self.minindex=None self.maxindex=None super().__init__(plc) def __init__(self, address:str, port:int=502, unit:int=1, method:str="rtu", retries:int=3, pollingtime:float=1.0): super().__init__() self.coil=self.create("coil",MBPLC.COIL) self.input=self.create("input",MBPLC.INPUT) self.holding=self.create("holding",MBPLC.HOLDING) self.register=self.create("register",MBPLC.REGISTER) self.address=address self.unit=unit self.port=port self.method=method self.retries=retries self.pollingtime=pollingtime self.client = ModbusClient(address, port, method=method, retries=retries) self.thread=Thread(target=self.__Polling, args=()) def create(self,memory_key, memorytype:type): ''' Crea una memoria en el controlador. Args: memory_key (str): Nombre o identificador de la memoria. memorytype (type): Tipo de memoria (COIL, INPUT, HOLDING, REGISTER). Returns (Memory): Memoria que se ha creado. ''' return self.set(memory_key, self.Memory(self, memorytype)) def connect(self): ''' Conexión con el controlador ''' self.thread.start() def disconnect(self): ''' Termina la conexión con el controlador. ''' self.connected=false self.client.close() def read(self): ''' Lectura de un área de memoria del controlador real. Si falla la lectura (tras el número de reintentos) se actualiza el estado de conexión a desconectado. ''' try: if not self.coil.minindex is None: rr = self.client.read_coils(self.coil.minindex, self.coil.maxindex-self.coil.minindex+1,unit=self.unit) for i in range(self.coil.minindex,self.coil.maxindex+1): if i in self.coil.tagbyaddress: self.coil.tagbyaddress[i].update(rr.bits[i-self.coil.minindex]) if not self.input.minindex is None: rr = self.client.read_discrete_inputs(self.input.minindex, self.input.maxindex-self.input.minindex+1,unit=self.unit) for i in range(self.input.minindex,self.input.maxindex+1): if i in self.input.tagbyaddress: self.input.tagbyaddress[i].update(rr.bits[i-self.input.minindex]) if not self.holding.minindex is None: rr = self.client.read_holding_registers(self.holding.minindex, self.holding.maxindex-self.holding.minindex+1,unit=self.unit) for i in range(self.holding.minindex,self.holding.maxindex+1): if i in self.holding.tagbyaddress: self.holding.tagbyaddress[i].update(rr.registers[i-self.holding.minindex]) if not self.register.minindex is None: rr = self.client.read_input_registers(self.register.minindex, self.register.maxindex-self.register.minindex+1,unit=self.unit) for i in range(self.register.minindex,self.register.maxindex+1): if i in self.register.tagbyaddress: self.register.tagbyaddress[i].update(rr.registers[i-self.register.minindex]) except Exception as e: self.coil.plc.disconnect() printexception(e,"Error reading from PLC") def __Polling(plc): ''' Lectura de todas las áreas de escaneo. Establece la conexión con los controladores, si no se ha hecho antes, o se ha perdido. ''' while True: if plc.connected: plc.read() time.sleep(plc.pollingtime) else: print("Connecting to MBPLC "+plc.address+":"+str(plc.port)+"("+str(plc.unit)+")") plc.connected=plc.client.connect()
from pymodbus3.client.sync import ModbusTcpClient inp = input( u"Press any key and enter to send a packet... (Just enter to quit)") client = ModbusTcpClient('100.100.100.2') while (inp): client.write_coil(1, True) result = client.read_coils(1, 1) print(result.bits[0]) client.close() inp = input( u"Press any key and enter to send a packet... (Just enter to quit)")
try: os.remove(FILENAME) except OSError: pass print("*"*30) print("SCADA server, reading the values of switch states, current and voltage readings") print("*"*30+"\n\n") fd = open(FILENAME, 'w+') csvrow = "timestamp;switch19;switch24;switch25;switch36;voltageb5;current19;current24;current25;current36\n" fd.write(csvrow) i=0 while i<10000: result = client.read_coils(0, 4, unit=1) ts = str(datetime.now()) print("*"*10+" SWITCHES "+"*"*10) switches = [result.bits[0], result.bits[1], result.bits[2], result.bits[3]] print("Switch branch 19: {}\nSwitch branch 24: {}\nSwitch branch 25: {}\nSwitch branch 36: {}".format(switches[0], switches[1], switches[2], switches[3])) # Voltage and current address = 12 count = 20 result = client.read_holding_registers(address, count, unit=1) decoder = BinaryPayloadDecoder.from_registers(result.registers, endian=Endian.Big) print("*"*10+" VOLTAGE "+"*"*10) voltage = decoder.decode_64bit_float() current = [decoder.decode_64bit_float(), decoder.decode_64bit_float(), decoder.decode_64bit_float(), decoder.decode_64bit_float()]
# save configuration to flash (also doesn't work... see Opto doc 1678, page 35) #client.write_register(61496, True) #print("saved to flash") # save configuration to flash (also doesn't work... see Opto doc 1678, page 35) #client.write_coil(257, True) #print("saved to flash") # set module2 ch1 output high client.write_coil(4, True) print("done") # scan module4 ch1 for input, send output to module3 ch1 while [True]: result = client.read_coils(12) print(result.bits[0]) if (result.bits[0] == 1): for r in range(5): client.write_coil(8, True) sleep(.2) client.write_coil(8, False) sleep(.2) else: client.write_coil(8, False) # scan module1 channels for input, send output to module2 channels for i in range(4): result = client.read_coils(i) print(result.bits[0])
from pymodbus3.client.sync import ModbusTcpClient #.client.sync import time as t from twisted.internet import reactor, protocol from pymodbus3.constants import Defaults import logging logging.basicConfig() a = 1 client = ModbusTcpClient('10.181.5.35', port=502) rq = client.write_coil(1, True) rr = client.read_coils(1, 1) assert (rq.function_code < 0x80) # test that we are not an error assert (rr.bits[0] == True) # test the expected value #result = client.read_coils(0,1) """arguments = { 'read_address': 1, 'read_count': 8, 'write_address': 1, 'write_registers': [20]*8,""" while a < 4: rq = client.write_registers(0, [0] * 15) rq2 = client.write_registers( 1000, [241] * 100) #Startadresse, skrevet verdi, antall registre log = logging.getLogger() log.setLevel(logging.DEBUG) client.write_coil(0, True) client.write_coil(1, True) client.write_coil(2, False) client.write_coil(3, True)
def plugin_poll(handle): """ Poll readings from the modbus device and returns it in a JSON document as a Python dict. Available for poll mode only. Args: handle: handle returned by the plugin initialisation call Returns: returns a reading in a JSON document, as a Python dict, if it is available None - If no reading is available Raises: """ try: global mbus_client if mbus_client is None: try: source_address = handle['address']['value'] source_port = int(handle['port']['value']) except Exception as ex: e_msg = 'Failed to parse Modbus TCP address and / or port configuration.' _LOGGER.error('%s %s', e_msg, str(ex)) raise ValueError(e_msg) try: mbus_client = ModbusTcpClient(host=source_address, port=source_port) mbus_client_connected = mbus_client.connect() if mbus_client_connected: _LOGGER.info('Modbus TCP Client is connected. %s:%d', source_address, source_port) else: raise RuntimeError("Modbus TCP Connection failed!") except: mbus_client = None _LOGGER.warn('Failed to connect! Modbus TCP host %s on port %d', source_address, source_port) return """ read_coils(self, address, count=1, **kwargs) read_discrete_inputs(self, address, count=1, **kwargs) read_holding_registers(self, address, count=1, **kwargs) read_input_registers(self, address, count=1, **kwargs) - address: The starting address to read from - count: The number of coils / discrete or registers to read - unit: The slave unit this request is targeting On TCP/IP, the MODBUS server is addressed using its IP address; therefore, the MODBUS Unit Identifier is useless. Remark : The value 0 is also accepted to communicate directly to a MODBUS TCP device. """ unit_id = UNIT modbus_map = json.loads(handle['map']['value']) readings = {} # Read coils coils_address_info = modbus_map['coils'] if len(coils_address_info) > 0: for k, address in coils_address_info.items(): coil_bit_values = mbus_client.read_coils(99 + int(address), 1, unit=unit_id) readings.update({k: coil_bit_values.bits[0]}) # Discrete input discrete_input_info = modbus_map['inputs'] if len(discrete_input_info) > 0: for k, address in discrete_input_info.items(): read_discrete_inputs = mbus_client.read_discrete_inputs(99 + int(address), 1, unit=unit_id) readings.update({k: read_discrete_inputs.bits[0]}) # Holding registers holding_registers_info = modbus_map['registers'] if len(holding_registers_info) > 0: for k, address in holding_registers_info.items(): register_values = mbus_client.read_holding_registers(99 + int(address), 1, unit=unit_id) readings.update({k: register_values.registers[0]}) # Read input registers input_registers_info = modbus_map['inputRegisters'] if len(input_registers_info) > 0: for k, address in input_registers_info.items(): read_input_reg = mbus_client.read_input_registers(99 + int(address), 1, unit=unit_id) readings.update({k: read_input_reg.registers[0] }) wrapper = { 'asset': handle['assetName']['value'], 'timestamp': utils.local_timestamp(), 'key': str(uuid.uuid4()), 'readings': readings } except Exception as ex: _LOGGER.error('Failed to read data from modbus device. Got error %s', str(ex)) raise ex else: return wrapper
if args.verbose: print(registerList) print(readList) #create modbus client client = ModbusTcpClient(args.ip_address, args.port) #read modbus data data = {} lastFilename = '' while True: for ri in readList: result = '-' if ri['type'] == 0: result = client.read_coils(ri['address'], ri['count'], unit=args.unit) if ri['type'] == 1: result = client.read_discrete_inputs(ri['address'], ri['count'], unit=args.unit) if ri['type'] == 3: result = client.read_input_registers(ri['address'], ri['count'], unit=args.unit) if ri['type'] == 4: result = client.read_holding_registers(ri['address'], ri['count'], unit=args.unit) if ri['type'] < 2 and result != '-':