Example #1
0
 def __init__(self, sh, *args, **kwargs):
     self.logger = logging.getLogger(__name__)
     self._helios_ip = self.get_parameter_value('helios_ip')
     self._client = ModbusTcpClient(self._helios_ip)
     self.alive = False
     self._is_connected = False
     self._update_cycle = self.get_parameter_value('update_cycle')
Example #2
0
    def test_tcp_client_send(self):
        """ Test the tcp client send method"""
        client = ModbusTcpClient()
        self.assertRaises(ConnectionException, lambda: client.send(None))

        client.socket = MockSocket()
        self.assertEqual(0, client.send(None))
        self.assertEqual(4, client.send('1234'))
Example #3
0
    def test_tcp_client_recv(self):
        """ Test the tcp client receive method"""
        client = ModbusTcpClient()
        self.assertRaises(ConnectionException, lambda: client.receive(1024))

        client.socket = MockSocket()
        self.assertEqual('', client.receive(0))
        self.assertEqual('\x00'*4, client.receive(4))
Example #4
0
 def __init__(self, ip_address, port):
     if ip_address is not None or port is not None:
         if MODBUS_BACKEND == PYMODBUS3:
             self._client = ModbusTcpClient(ip_address, port=port)
         if MODBUS_BACKEND == UMODBUS:
             self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
             self._sock.settimeout(2)  # seconds
             self._sock.connect((ip_address, port))
     super(COMx, self).__init__(com=self, registration_number=0)
Example #5
0
    def __init__(self, sh):
        from bin.smarthome import VERSION
        if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5':
            self.logger = logging.getLogger(__name__)

        self._helios_ip = self.get_parameter_value('helios_ip')
        self._client = ModbusTcpClient(self._helios_ip)
        self.alive = False
        self._is_connected = False
        self._update_cycle = self.get_parameter_value('update_cycle')
Example #6
0
    def connect(self):
        """Connect to target MODBUS server.

        """
        try:
            self.client = ModbusTcpClient(self.config['ip_add'])
            self.client.connect()
            self.connected = True
        except:
            print('MODBUS CLIENT:', self.process_name,
                  '-- unable to connect to target server.')
Example #7
0
    def test_tcp_client_connect(self):
        """ Test the tcp client connection method"""
        with patch.object(socket, 'create_connection') as mock_method:
            mock_method.return_value = object()
            client = ModbusTcpClient()
            self.assertTrue(client.connect())

        with patch.object(socket, 'create_connection') as mock_method:
            mock_method.side_effect = socket.error()
            client = ModbusTcpClient()
            self.assertFalse(client.connect())
Example #8
0
def runModBus(IOVariables):
    client = ModbusTcpClient('192.168.1.9')
    Digital_Out_1 = ModbusDigitalOutputIOCard(2048, client, IOVariables)          
    try:
        Digital_Out_1.WriteStatus()
    except ConnectionException:
        print('A connection error to the modbus occured at {}'.format(
            datetime.datetime.now()
            )
        )
        pass
    client.close()      
Example #9
0
def read_sensors(request):
    sensors = Sensor.objects.all()
    sensor_data = []
    dictionary = {}
    for sensor in sensors:
        client = ModbusTcpClient(sensor.address.server, port=502, timeout=1)
        try:
            client.connect()
            if sensor.sensor_type == Sensor.SensorType.DIGITAL:
                reply = client.read_discrete_inputs(sensor.channel, 1, unit=1)
                sensor_reading = reply.bits[0]
                sensor_response = {
                    'sensor_name': sensor.name,
                    'sensor_reading': sensor_reading
                }
                if sensor.digital_sensor_alert and sensor.email and str(
                        sensor_reading) != sensor.last_value:
                    if sensor.digital_alert_value and sensor_reading:
                        send_sensor_alert_email(sensor, str(sensor_reading))
                        #send_sensor_alert_email()
                    elif not sensor.digital_alert_value and not sensor_reading:
                        send_sensor_alert_email(sensor, str(sensor_reading))
                        #send_sensor_alert_email()
            else:
                reply = client.read_input_registers(sensor.channel, 1, unit=1)
                sensor_reading = round(
                    reply.registers[0] * sensor.conversion_factor, 2)
                if sensor.high_alert_value and sensor.email:
                    if sensor_reading > sensor.high_alert_value and float(
                            sensor.last_value) <= sensor.high_alert_value:
                        send_sensor_alert_email(sensor, str(sensor_reading))
                        #send_sensor_alert_email()
                if sensor.low_alert_value and sensor.email:
                    if sensor_reading < sensor.low_alert_value and float(
                            sensor.last_value) >= sensor.low_alert_value:
                        send_sensor_alert_email(sensor, str(sensor_reading))
                        #send_sensor_alert_email()
            sensor.last_value = str(sensor_reading)
            sensor.save()
            client.close()
        except:
            sensor_reading = "Could Not Connect"
        sensor_response = {
            'sensor_name': sensor.name,
            'sensor_reading': sensor_reading
        }
        sensor_data.append(sensor_response)
        client.close()
    dictionary['sensor_data'] = sensor_data
    return render(request, 'sensors/sensor_data.html', dictionary)
Example #10
0
    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
Example #11
0
    def __init__(self, address, port=502, logger=None):
        if not logger:
            self.logger = logging.getLogger(__name__)
            self.logger.setLevel(logging.ERROR)
        else:
            self.logger = logger

        self.address = address
        self.client = ModbusTcpClient(address, port)
Example #12
0
        def __init__(self):
            if (self.logger == None):
                self.createLogger('generalPLCgateway')
            if len(self.plc_host) > 1:
                plc_client = ModbusTcpClient(self.plc_host)
            try:
                if len(self.plc_host) > 1:
                    result = plc_client.read_holding_registers(0, 5, unit=0X01)
                    if len(result.registers) == 5:
                        print("Gateway connected succesfully to PLC : " +
                              str(result))
                #self.update_conected_plc(self.plc_host)

                else:
                    print("connection is terminated ")
                    self.logger.error("connection is terminated ")
            except Exception as e:
                print("error sending data to PLC " + str(e))
                self.logger.error("error sending data to PLC " + str(e))
Example #13
0
class Modbus:
    def __init__(self, uri='localhost', port=502):
        self.host = socket.gethostbyname(uri)
        self.client = ModbusClient(self.host, port=port)
        self.client.connect()
        # // TODO implement a fallback
        # if not self.client:
        #     raise RuntimeError('Error establishing connection with uri {}'.format(uri))

    def _read(self, response, typ='Float32'):
        if typ == 'Float32':
            raw = struct.pack('>HH', response.get_register(1), response.get_register(0))
            return struct.unpack('>f', raw)[0]

    def read(self, register, n, unit=1, typ='Float32'):
        response = self.client.read_holding_registers(register, n, unit=unit)
        return self._read(response, typ)

    def readN(self, registers, n, unit=1):
        # // TODO implement reading multiple registers
        pass
Example #14
0
    def test_tcp_client_send(self):
        """ Test the tcp client send method"""
        client = ModbusTcpClient()
        self.assertRaises(ConnectionException, lambda: client.send(None))

        client.socket = MockSocket()
        self.assertEqual(0, client.send(None))
        self.assertEqual(4, client.send('1234'))
Example #15
0
    def test_tcp_client_recv(self):
        """ Test the tcp client receive method"""
        client = ModbusTcpClient()
        self.assertRaises(ConnectionException, lambda: client.receive(1024))

        client.socket = MockSocket()
        self.assertEqual('', client.receive(0))
        self.assertEqual('\x00' * 4, client.receive(4))
Example #16
0
def runModBus(IOVariables):
    #---------------------------------------------------------------------------#
    # 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.
    #---------------------------------------------------------------------------#
    client = ModbusTcpClient('192.168.1.9')
    #rq = client.write_registers(2048, [0])
    #rr = client.read_input_registers(000, 1)
    #print (rr.registers)       
    #---------------------------------------------------------------------------#
    # configure io card
    #---------------------------------------------------------------------------#
    #Digital_In_1 = ModbusDigitalInputIOCard(0, client)   
    #print('IOVariables in modbus.py: {IOVariables} '.format(IOVariables=IOVariables))  
    Digital_Out_1 = ModbusDigitalOutputIOCard(2048, client, IOVariables)          
    #---------------------------------------------------------------------------#
    # Run io card
    #---------------------------------------------------------------------------#
    #Digital_In_1.ReadStatus()
    #---------------------------------------------------------------------------#
    # Run io card
    #---------------------------------------------------------------------------#
    try:
        Digital_Out_1.WriteStatus()
    except ConnectionException:
        print('A connection error to the modbus occured at {}'.format(
            datetime.datetime.now()
            )
        )
        pass

    #---------------------------------------------------------------------------#
    # close the client
    #---------------------------------------------------------------------------#
    client.close()      
Example #17
0
 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=())
Example #18
0
def runModBus(IOVariables):
    #---------------------------------------------------------------------------#
    # 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.
    #---------------------------------------------------------------------------#
    client = ModbusTcpClient('192.168.1.9')
    #rq = client.write_registers(2048, [0])
    #rr = client.read_input_registers(000, 1)
    #print (rr.registers)       
    #---------------------------------------------------------------------------#
    # configure io card
    #---------------------------------------------------------------------------#
    #Digital_In_1 = ModbusDigitalInputIOCard(0, client)   
    #print('IOVariables in modbus.py: {IOVariables} '.format(IOVariables=IOVariables))  
    Digital_Out_1 = ModbusDigitalOutputIOCard(2048, client, IOVariables)          
    #---------------------------------------------------------------------------#
    # Run io card
    #---------------------------------------------------------------------------#
    #Digital_In_1.ReadStatus()
    #---------------------------------------------------------------------------#
    # Run io card
    #---------------------------------------------------------------------------#
    try:
        Digital_Out_1.WriteStatus()
    except ConnectionException:
        print('A connection error to the modbus occured at {}'.format(
            datetime.datetime.now()
            )
        )
        pass
    #---------------------------------------------------------------------------#
    # close the client
    #---------------------------------------------------------------------------#
    client.close()      
Example #19
0
    def test_tcp_client_connect(self):
        """ Test the tcp client connection method"""
        with patch.object(socket, 'create_connection') as mock_method:
            mock_method.return_value = object()
            client = ModbusTcpClient()
            self.assertTrue(client.connect())

        with patch.object(socket, 'create_connection') as mock_method:
            mock_method.side_effect = socket.error()
            client = ModbusTcpClient()
            self.assertFalse(client.connect())
Example #20
0
def get_1wire_config(ip_address):
    try:
        client = ModbusTcpClient(ip_address)

        wire_config = []
        for i in range(MAX_1WIRE):
            holding_regs = client.read_holding_registers(
                HR_TI_001_ID_H + i * 4, 4)
            cur_uuid = format_uuid(holding_regs.registers)
            holding_regs = client.read_holding_registers(HR_TI_001 + i, 1)
            wire_config.append(
                [i, cur_uuid, i,
                 to_signed(holding_regs.registers[0]) / 10.0])

        client.close()
        return wire_config
    except ConnectionException:
        print("{0} - unavailable".format(cuip))
Example #21
0
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)")
Example #22
0
 def test_sync_tcp_client_instantiation(self):
     client = ModbusTcpClient()
     self.assertNotEqual(client, None)
Example #23
0
    def test_basic_sync_tcp_client(self):
        """ Test the basic methods for the tcp sync client"""

        # receive/send
        client = ModbusTcpClient()
        client.socket = MockSocket()
        self.assertEqual(0, client.send(None))
        self.assertEqual(1, client.send('\x00'))
        self.assertEqual('\x00', client.receive(1))

        # connect/disconnect
        self.assertTrue(client.connect())
        client.close()

        # already closed socket
        client.socket = False
        client.close()

        self.assertEqual("127.0.0.1:502", str(client))
Example #24
0
class HeliosTCP(SmartPlugin):

    PLUGIN_VERSION = "1.0.2"
    MODBUS_SLAVE = 180
    PORT = 502
    START_REGISTER = 1

    _items = {}

    def __init__(self, sh):
        from bin.smarthome import VERSION
        if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5':
            self.logger = logging.getLogger(__name__)

        self._helios_ip = self.get_parameter_value('helios_ip')
        self._client = ModbusTcpClient(self._helios_ip)
        self.alive = False
        self._is_connected = False
        self._update_cycle = self.get_parameter_value('update_cycle')

    def run(self):
        """
        Run method for the plugin
        """
        self.logger.debug("Run method called")
        self._is_connected = self._client.connect()
        if not self._is_connected:
            self.logger.error(
                "Helios TCP: Failed to connect to Modbus Server at {0}".format(
                    self._helios_ip))
        self.scheduler_add('Helios TCP',
                           self._update_values,
                           cycle=self._update_cycle)
        self.alive = True

    def stop(self):
        """
        Stop method for the plugin
        """
        self.logger.debug("Stop method called")
        self.scheduler_remove('Helios TCP')
        self._client.close()
        self.alive = False

    def parse_item(self, item):
        if 'helios_tcp' in item.conf:
            varname = item.conf['helios_tcp']
            if varname in VARLIST.keys():
                self._items[varname] = item
                return self.update_item
            else:
                self.logger.warning(
                    "Helios TCP: Ignoring unknown variable '{0}'".format(
                        varname))

    def _update_values(self):
        for item in self._items:
            self._read_value(self._items[item])

    @staticmethod
    def _string_to_registers(instr: str):
        l = bytearray(instr, 'ascii')
        return [k[0] * 256 + k[1] for k in zip(l[::2], l[1::2])] + [0]

    def _read_value(self, item):
        try:
            var = item.conf['helios_tcp']
        except ValueError:
            return

        try:
            varprop = VARLIST[var]
        except KeyError:
            self.logger.error(
                "Helios TCP: Failed to find variable '{0}'".format(var))
            return

        # At first we write the variable name to read into the input registers:
        payload = self._string_to_registers(varprop['var'])
        request = self._client.write_registers(self.START_REGISTER,
                                               payload,
                                               unit=self.MODBUS_SLAVE)
        if request is None:
            self.logger.warning(
                "Helios TCP: Failed to send read request for variable '{0}'".
                format(var))
            return

        # Now we may read the holding registers:
        response = self._client.read_holding_registers(self.START_REGISTER,
                                                       varprop['length'],
                                                       unit=self.MODBUS_SLAVE)
        if response is None:
            self.logger.warning(
                "Helios TCP: Failed to send read response for variable '{0}'".
                format(var))
            return

        # Now we may dedocde the result
        # Note that we immediatly strip the varname from the result.
        result = response.encode().decode('ascii')[8:]
        result = list(result)

        # Remove trailing zeros:
        while result[-1] == '\x00':
            result.pop()

        result = ''.join(result)

        # Finally we may cast the result and return the obtained value:
        try:
            item(varprop["type"](result), self.get_shortname())
        except ValueError:
            self.logger.warning(
                "Helios TCP: Could not assign {0} to item {1}".format(
                    varprop["type"](result), item.id()))
            return

    def update_item(self, item, caller=None, source=None, dest=None):
        """
        Item has been updated

        This method is called, if the value of an item has been updated by SmartHomeNG.
        It should write the changed value out to the device (hardware/interface) that
        is managed by this plugin.

        :param item: item to be updated towards the plugin
        :param caller: if given it represents the callers name
        :param source: if given it represents the source
        :param dest: if given it represents the dest
        """
        if self.alive and caller != self.get_shortname():
            try:
                var = item.conf['helios_tcp']
            except ValueError:
                return

            newval = item()

            try:
                varprop = VARLIST[var]
            except KeyError:
                self.logger.error(
                    "Helios TCP: Failed to find variable '{0}'".format(var))
                return

            if not varprop["write"]:
                return

            if type(newval) != varprop["type"]:
                self.logger.error(
                    "Helios TCP: Type mismatch for variable '{0}'".format(var))
                return

            if newval < varprop["min"] or newval > varprop["max"]:
                self.logger.error(
                    "Helios TCP: Variable '{0}' out of bounds. The allowed range is [{1}, {2}]"
                    .format(var, varprop["min"], varprop["max"]))
                return

            if varprop["type"] == bool:
                payload_string = "{0}={1}".format(varprop["var"], int(newval))
            elif varprop["type"] == int:
                payload_string = "{0}={1}".format(varprop["var"], int(newval))
            elif varprop["type"] == float:
                payload_string = "{0}={1:.1f}".format(varprop["var"], newval)
            else:
                self.logger.error(
                    "Helios TCP: Type {0} of varible '{1}' not known".format(
                        varprop["type"], var))
                return

            payload = self._string_to_registers(payload_string)
            request = self._client.write_registers(self.START_REGISTER,
                                                   payload,
                                                   unit=self.MODBUS_SLAVE)
            if request is None:
                self.logger.warning(
                    "Helios TCP: Failed to send write request for variable '{0}'"
                    .format(var))
                return
Example #25
0
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
Example #26
0
    def test_basic_sync_tcp_client(self):
        """ Test the basic methods for the tcp sync client"""

        # receive/send
        client = ModbusTcpClient()
        client.socket = MockSocket()
        self.assertEqual(0, client.send(None))
        self.assertEqual(1, client.send('\x00'))
        self.assertEqual('\x00', client.receive(1))

        # connect/disconnect
        self.assertTrue(client.connect())
        client.close()

        # already closed socket
        client.socket = False
        client.close()

        self.assertEqual("127.0.0.1:502", str(client))
Example #27
0
    },
    'module10': {
        'ch1': 713,
        'ch2': 715,
        'ch3': 717,
        'ch4': 719
    },
    'module11': {
        'ch1': 721,
        'ch2': 723,
        'ch3': 725,
        'ch4': 727
    }
}

client = ModbusTcpClient('192.168.100.12')

# configure I/O modules (input = 0x100, output = 0x180)
client.write_register(
    6146, 0x180, unit=10
)  #<--- this is supposed to config module 2, point 0 as an output but it doesn't work...
client.write_register(input_output_flags['module2']['ch1'], 0x180)
client.write_register(input_output_flags['module2']['ch2'], 0x180)
client.write_register(input_output_flags['module2']['ch3'], 0x180)
client.write_register(input_output_flags['module3']['ch1'], 0x180)
print("config set")

# save configuration to flash (doesn't work... see Opto doc 1465, page 104)
#client.write_register(0, 0x00000003, unit=30)
#print("saved to flash")
Example #28
0
    while threads_switch:
        global read_discrete_inputs_data
        global discrete_inputs_data
        if discrete_inputs_data != read_discrete_inputs_data:
            msg = str(read_discrete_inputs_data)
            rc, mid = mqtt_client.publish("one2one/fpq", payload=msg, qos=1)  # qos
            on_publish(msg, rc)
            print(read_discrete_inputs_data)
            discrete_inputs_data = read_discrete_inputs_data


logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.CRITICAL)

modbus_client = ModbusClient('192.168.1.133', port=503, retries=2, framer=ModbusFramer)
modbus_client.connect()

write_coils_data = []
read_discrete_inputs_data = []
discrete_inputs_data = []
threads_switch = 1

while True:
    time.sleep(1)
'''
threads = []
t1 = threading.Thread(target=modbus_rr)
threads.append(t1)
t2 = threading.Thread(target=modbus_print)
threads.append(t2)
import time  
from pymodbus3.client.sync import ModbusTcpClient



client = ModbusTcpClient('127.0.0.1')


while True:
	client.write_coil(0, True)
	time.sleep(1.0)
	client.write_coil(0, False)
	time.sleep(1.0)
Example #30
0
def display_remote_io(ip_address):
    '''
    display remote I/O information at the given IP address
    '''
    try:
        client = ModbusTcpClient(ip_address)
        client.write_coil(HW_CY_006, False)

        ip_holding_regs = client.read_holding_registers(HR_CI_006_CV, 6)

        client.write_registers(HW_CI_006_PV, ip_holding_regs.registers)
        cur_ip = format_modbus_ip_address(ip_holding_regs.registers[0],
                                          ip_holding_regs.registers[1])
        cur_gateway = format_modbus_ip_address(ip_holding_regs.registers[2],
                                               ip_holding_regs.registers[3])
        cur_subnet = format_modbus_ip_address(ip_holding_regs.registers[4],
                                              ip_holding_regs.registers[5])

        ip_holding_regs = client.read_holding_registers(HR_CI_009_CV, 4)
        cur_mac = format_mac(ip_holding_regs.registers)
        ip_holding_regs = client.read_holding_registers(HR_KI_003, 2)
        cur_version = format_version(ip_holding_regs.registers[0])

        print("{0} - {1}, version:{2}.{3}.{4} ".format(
            ip_address, device_type_name(ip_holding_regs.registers[1]),
            cur_version[1], cur_version[2], cur_version[3]),
              end='')
        print("gateway:{0}, subnet:{1} mac:{2}".format(cur_gateway, cur_subnet,
                                                       cur_mac))
        client.close()
    except ConnectionException:
        print("{0} - unavailable".format(ip_address))
Example #31
0
from time import sleep
import os
from datetime import datetime

#---------------------------------------------------------------------------# 
# configure the client logging
#---------------------------------------------------------------------------# 
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.INFO)

#---------------------------------------------------------------------------# 
# We are going to use a simple client to send our requests
#---------------------------------------------------------------------------# 
client = ModbusClient('192.168.33.1', port=10502)
client.connect()

FILENAME = 'rtu_5_log.csv'

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"
Example #32
0
#working ------- 1 seferde 124 tane cektik
from pymodbus3.client.sync import ModbusTcpClient
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

#defaults
ip="188.59.150.237"
start="0"
count="3"
unit_number="2"

#get necessary values


#modbus connection
client = ModbusTcpClient(ip)
connection = client.connect()

#read register
request = client.read_holding_registers(int(start),int(count),unit=int(unit_number))
result = request.registers
print (result) #result is the array of register values, can be accesses as result[i]



#ege
Example #33
0
#
# 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('192.168.1.4', port=502)
#client = ModbusClient(method='ascii', port='/dev/pts/2', timeout=1)
# client = ModbusClient(method='rtu', port='/dev/ttyp0', timeout=1)
client.connect()

#---------------------------------------------------------------------------#
# example requests
#---------------------------------------------------------------------------#
# simply call the methods that you would like to use. An example session
# is displayed below along with some assert checks. Note that some modbus
# implementations differentiate holding/input discrete/coils and as such
# you will not be able to write to these, therefore the starting values
# are not known to these tests. Furthermore, some use the same memory
# blocks for the two sets, so a change to one is a change to the other.
# Keep both of these cases in mind when testing as the following will
# _only_ pass with the supplied async modbus server (script supplied).
Example #34
0
STOPC = 29835  #This are complements of control keys, must be write together with the control key
AUTO = 35701
AUTOC = 29834
MANUAL = 35702
MANUALC = 29833
AUTOM = 35704
AUTOMC = 29831
START = 35705
STARTC = 29830
RESETAL = 35734

print("Waiting for the unit to start")
time.sleep(30)
host = sys.argv[1]
print("Connecting to DSE with IP ", host)
client = ModbusClient(host)
client.connect()
time.sleep(0.1)


def sync_client_read(registerNumber):
    try:
        result = client.read_holding_registers(registerNumber, 1)
        return result.registers
    except:
        print("Connection Error Handled")
        output = False
        return output


def read_register(PageNumber, RegisterOffset, Scale):
Example #35
0
 
from pymodbus3.client.sync import ModbusTcpClient  
 
        # instead of this

       # 192.168.1.22:502
        #PLC Mod Bus Regs 40001-40100
        
        
 #40096-40100     monnth day hour .....  
#Reg 2 Bytes --> not 4 bytes     
 


plc_client = ModbusTcpClient('192.168.1.22')
# result =client.read_holding_registers(0,5,unit=0X01) 
# print (str(result))
try:
    for x in range(5,6):
        result = plc_client.write_registers( 9,[int(x)  ],unit=0X01) 
        result = plc_client.write_registers(40007,[int(x) ],unit=0X01) 
        result = plc_client.write_registers(40010,[int(1)],unit=0X01) 
 
    print (str(result))
except Exception as e:
    print("error sending data to plc " + str(e))
 

plc_client.close()
Example #36
0
import time  
import RPi.GPIO as GPIO
from pymodbus3.client.sync import ModbusTcpClient

#set up GPIO using BCM numbering
GPIO.setmode(GPIO.BCM)

#setup GPIO using Board numbering
#GPIO.setmode(GPIO.BOARD)
GPIO.cleanup()  
GPIO.setup(22, GPIO.OUT)
GPIO.setup(5, GPIO.IN)
  
client = ModbusTcpClient('127.0.0.1')

while True:

    uzaklik=GPIO.input(5)
    print(uzaklik)

    if(uzaklik == 1.0):
	# Uncomment if connected to led
        # GPIO.output(22, True)
        client.write_register(1, 1)
    if(uzaklik == 0.0):
	# Uncomment if connected to led
        # GPIO.output(22, False)
        client.write_register(1, 1)

   time.sleep(1.0)
Example #37
0
    class __CalculatedParams:

        params = ConfParams()
        user = ThingBoardUser()
        dt2 = 1 / 6000
        TMS_DL = float(params.getParam("INITIAL_TMS_DL"))
        CFT = 0

        TCC_MODE = params.getParam("TCC_MODE")
        TCC = float(params.getParam("INITIAL_TCC"))
        alpha0 = int(params.getParam("IIR_Alfa"))
        dict_Tcycle_A_2_by_sensor_id = {}
        dict_Tcharge_by_sensor_id = {}
        timer = None
        plc_client = None
        if len(params.getParam("PLC_HOST")) > 1:
            plc_client = ModbusTcpClient(params.getParam("PLC_HOST"))

        # after 30 seconds, "hello, world" will be printed
        # a time counter will be more than “TMS” or the time counter will be more than 5 sec

        def init_timer(self):
            # print("init_timer:"+str(self.TMS))
            min_interval = min(5.0, float(self.TMS_DL))
            self.timer = threading.Timer(min_interval, self.timerFunction)
            self.timer.start()

        def timerFunction(self):
            self.submit_CFT_and_TCC()
            # print("sent by Timer, TMS:"+str(self.TMS))

        def set_param(self, sensor_id, param_name, value):
            if self.timer == None:
                self.init_timer()

            if (not param_name):
                return

            if (param_name == "Tcycle_A_2"):
                self.process_Tcycle_A_2(sensor_id, value)

            elif (param_name == "Tcharge"):
                self.process_Tcharge(sensor_id, value)

            elif (param_name == "TBagSpacing"):
                self.submit_parameter("TBS", 0.01 * value, 3)

            elif (param_name == "ChBHight"):
                self.submit_parameter("ABH", 0.1 * value, 4)

            elif (param_name == "Tbaglength"):
                self.submit_parameter("TBL", 0.01 * value, 5)

        def submit_parameter(self, out_param_name, value, plc_reg_address=None):
            ts = {"ts": int(round(time.time() * 1000))}

            # if start_new_data:
            data = []

            new_obj_to_send = {"ts": ts["ts"], "values": {}}

            # Lior process out_param_name ,value
            # Change - Start
            attr_to_send = calculate_info(out_param_name, value)
            #print(value_storage)
            #print(attr_to_send)
            self.user.send_attributes("PLC", attr_to_send)
            
            # new_obj_to_send["values"][out_param_name] = value
            new_obj_to_send["values"][out_param_name] = add_color_digit(value, out_param_name)
            # Change - End

            data.append(new_obj_to_send)
            value = int(value * pow(2, 9))
            try:
                try:
                    if not self.plc_client == None:
                        result = self.plc_client.write_registers(plc_reg_address, [value], unit=0X01)
                        print(out_param_name + " Sent to PLC : " + str(value))
                        self.sendIsAlive()
                except Exception as e:
                    print("error sending data to PLC :  " + str(e))

                self.user.send_telemetry("PLC", data, False, None, None)

            except Exception as e:
                print("error sending data to Things Board :  " + str(e))
                # self.generalLogger.error("error sending data serv " + str(e))

        def process_Tcycle_A_2(self, sensor_id, value):
            self.dict_Tcycle_A_2_by_sensor_id[sensor_id] = value
            if (len(self.dict_Tcycle_A_2_by_sensor_id) == 3 and len(self.dict_Tcharge_by_sensor_id) == 3):
                self.submit_CFT_and_TCC()

        def process_Tcharge(self, sensor_id, value):
            self.dict_Tcharge_by_sensor_id[sensor_id] = value
            if (len(self.dict_Tcycle_A_2_by_sensor_id) == 3 and len(self.dict_Tcharge_by_sensor_id) == 3):
                self.submit_CFT_and_TCC()

        def sendIsAlive(self):
            data = {"ts": int(round(time.time() * 1000)), "values": {"is_alive": True}}
            jsonData = json.dumps(data)
            re = self.user.post(self.user.telemetry_url.format(self.user.access_token("MODBUS")), jsonData)

        def submit_CFT_and_TCC(self):
            if not self.timer == None:
                self.timer.cancel()

            if (len(self.dict_Tcycle_A_2_by_sensor_id) == 0 and len(self.dict_Tcharge_by_sensor_id) == 0):
                # print("no values to be sent by timer, init_timer")
                self.init_timer()
                return

            Nsyc = 0
            ATsycle = 0
            self.CFT = 0

            for value in self.dict_Tcycle_A_2_by_sensor_id.values():

                if (value > 2800 and value < 18000):
                    ATsycle += value
                    Nsyc += 1

            if Nsyc:
                ATsycle = ATsycle / Nsyc
                self.TMS_DL = (float(((10000 - (float(self.alpha0))) * (float(self.TMS_DL)) + (float(self.alpha0)) * (
                    float(ATsycle))) / 10000))
                # self.TMS = self.dt2*float(self.TMS_DL)

            Nsyc = 0
            Tcharge_values_list = []
            if self.TCC_MODE == '0':
                for value in self.dict_Tcharge_by_sensor_id.values():

                    if (value > 0 and value < self.TMS_DL):
                        Tcharge_values_list.append(int(value))
                    else:
                        Tcharge_values_list.append(0)

                if len(Tcharge_values_list) > 0:
                    self.TCC = self.dt2 * max(Tcharge_values_list)


            elif self.TCC_MODE == '1':
                self.TCC = 0
                for value in self.dict_Tcharge_by_sensor_id.values():

                    if (value > 0 and value < self.TMS_DL):
                        self.TCC += value
                        Nsyc += 1

                if Nsyc:
                    self.TCC = self.dt2 * self.TCC / Nsyc

            #             Mode 2: (Median(TCharge(1), TCharge(2), TCharge(3)))
            # If  0<TCharge(n)<( TMS_DL), Add TCharge(n) to a buffer
            # TCC = dt2*(median of the buffer)

            if self.TCC_MODE == '2':
                for value in self.dict_Tcharge_by_sensor_id.values():

                    if (value > 0 and value < self.TMS_DL):
                        Tcharge_values_list.append(int(value))

                if len(Tcharge_values_list) > 0:
                    self.TCC = self.dt2 * median(Tcharge_values_list)
                else:
                    self.TCC = 0




            elif self.TCC_MODE == '3':
                for value in self.dict_Tcharge_by_sensor_id.values():

                    if (value > 0 and value < self.TMS_DL):
                        Tcharge_values_list.append(int(value))
                    else:
                        Tcharge_values_list.append(0)

                if len(Tcharge_values_list) > 0:
                    value1 = max(Tcharge_values_list)

                    Tcharge_values_list.remove(value1)
                    if len(Tcharge_values_list) > 0:
                        value2 = max(Tcharge_values_list)
                        self.TCC = self.dt2 * (value1 + value2) / 2

                    else:
                        self.TCC = self.dt2 * value1
            if ATsycle > 0:
                self.CFT = self.dt2 * ATsycle - self.TCC;

            ts = {"ts": int(round(time.time() * 1000))}

            # if start_new_data:
            data = []

            new_obj_to_send = {"ts": ts["ts"], "values": {}}

            # Change - Start
            attr_to_send = calculate_info("CFT", self.CFT)
            #print(value_storage)
            #print(attr_to_send)
            self.user.send_attributes("PLC", attr_to_send)
            
            attr_to_send = calculate_info("TCC", self.TCC)
            #print(attr_to_send)
            self.user.send_attributes("PLC", attr_to_send)
            

            # new_obj_to_send["values"]["CFT"] = self.CFT
            new_obj_to_send["values"]["CFT"] = add_color_digit(self.CFT, "CFT")
            # new_obj_to_send["values"]["TCC"] = self.TCC
            new_obj_to_send["values"]["TCC"] = add_color_digit(self.TCC, "TCC")
            # Change - End

            data.append(new_obj_to_send)

            cftToSend = int(self.CFT * pow(2, 9))
            tccToSend = int(self.TCC * pow(2, 9))
            try:
                try:
                    if not self.plc_client == None:
                        result = self.plc_client.write_registers(1, [tccToSend], unit=0X01)
                        print("  TCC data sent to PLC :  " + str(tccToSend))
                        result = self.plc_client.write_registers(6, [cftToSend], unit=0X01)
                        print("  CFT data sent to PLC :  " + str(cftToSend))
                        result = self.plc_client.write_registers(9, [1], unit=0X01)
                        self.sendIsAlive()


                except Exception as e:
                    print("error sending data to PLC :  " + str(e))

                self.user.send_telemetry("PLC", data, False, None, None)

            except Exception as e:
                print("error sending data to Things Board :  " + str(e))
                # self.generalLogger.error("error sending data serv " + str(e))

            self.dict_Tcycle_A_2_by_sensor_id = {}
            self.dict_Tcharge_by_sensor_id = {}
            # self.timer = threading.Timer(min(5,int(self.TMS)), self.timerFunction)
            self.init_timer()
Example #38
0
def write_network_config(cuip, aip, agw, asn, amac):
    try:
        client = ModbusTcpClient(cuip)
        client.write_register(HW_CI_006_PV, aip >> 16)
        client.write_register(HW_CI_006_PV + 1, aip & 0xffff)
        client.write_register(HW_CI_007_PV, agw >> 16)
        client.write_register(HW_CI_007_PV + 1, agw & 0xffff)
        client.write_register(HW_CI_008_PV, asn >> 16)
        client.write_register(HW_CI_008_PV + 1, asn & 0xffff)

        client.write_register(HW_CI_009_PV, 0)
        client.write_register(HW_CI_009_PV + 1, amac >> 32)

        client.write_register(HW_CI_009_PV + 2, (amac & 0xFFFFFFFF) >> 16)
        client.write_register(HW_CI_009_PV + 3, (amac & 0xFFFFFFFF) & 0xffff)
        client.write_coil(HW_CY_006, True)
        client.close()
    except ConnectionException:
        print("{0} - unavailable".format(cuip))
Example #39
0
DCCurrentRegisterOffset = 201
STOP = 35700 #This are control keys
STOPC = 29835 #This are complements of control keys, must be write together with the control key
AUTO = 35701
AUTOC = 29834
MANUAL = 35702
MANUALC = 29833
AUTOM = 35704
AUTOMC = 29831
START = 35705
STARTC = 29830
RESETAL = 35734

host = sys.argv[1]
print("Connecting to DSE with IP ", host)
client = ModbusClient(str(host), port = 502)
client.connect()
time.sleep(0.1)

def sync_client_read(registerNumber):
	try:
		result = client.read_holding_registers(registerNumber,1)
		return result.registers
	except:
		print("Connection Error Handled")
		output = False
		return output

def read_register(PageNumber, RegisterOffset, Scale):
	register = 256 * PageNumber + RegisterOffset
	read = sync_client_read(register)
Example #40
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)
Example #41
0
def main():            
	registersPerPage = 256
	RPMPageNumber = 4
	RPMRegisterOffset = 6
	DCCurrentPageNumber = 4
	DCCurrentStartOffset = 204
	DCCurrentEndOffset = 205
	STOP     =  35700;    # 10001011(H8B,D139) 01110100(H74,116)  # -29836 (35700)
	STOPC    =  29835;    # 01110100(H74,D116) 10001011(H8B,D139) #  29835
	AUTO     =  35701;    # 10001011(H8B,D139) 01110101(H75,D117) # -29835 (35701)
	AUTOC    =  29834;    # 01110100(H74,D116) 10001010(H8A,D138) #  29834
	MANUAL   =  35702;    # 10001011(H8B,D139) 01110110(H76,D118) # -29834 (35702)
	MANUALC  =  29833;    # 01110100(H74,D116) 10001001(H89,D137) #  29833
	AUTOM    =  35704;    # 10001011(H8B,D139) 01111000(H78,D120) # -29832 (35704)
	AUTOMC   =  29831;    # 01110100(H74,D116) 10000111(H87,D135) #  29831
	START    =  35705;    # 10001011(H8B,D139) 01111001(H79,D121) # -29831 (35705)
	STARTC   =  29830;    # 01110100(H74,D116) 10000110(H87,D134) #  29830
	RESETAL  =  35734;    # 10001011(H8B,D139) 10010110(H96,D150) # -35734 (35734)
	#RESETALC =  29801;    # 
	#RESETA2  =  35734;    # 10001011(H8B,D139) 10010110(H96,D150) #  (35734)
	#RESETA2C =  29828;
	#RESETAT  = -29801;    # 10001011(H8B,D139) 10010110(H96,D150) # -35734 (35734)
	#RESETATC =  29800;    
	MODE_STOP          = 0; #Stop mode
	MODE_AUTO          = 1; #Auto mode
	MODE_MANUAL        = 2; #Manual mode
	MODE_TEST          = 3; #Test on load mode
	MODE_AUTO_MRESTORE = 4; #Auto with manual restore mode/Prohibit Return
	MODE_USER_CONFIG   = 5; #User configuration mode
	MODE_TEST_OFF_LOAD = 6; #Test off load mode

	host = sys.argv[1]
	print(host)
	client = ModbusClient(str(host), port=502)
	client.connect()
	time.sleep(0.1)

	rm = client.write_registers(4104, [MANUAL,MANUALC])
	print("Change DSE to MANUAL mode, starting engine in 5 seconds...")

	x = 4
	while x>=1:
		time.sleep(1)
		print(str(x))
		x-=1

	rq = client.write_registers(4104, [START,STARTC])
	time.sleep(3)
	print("Starting engine, proceding to read RPM and DC current")
	time.sleep(1)

	x = 1
	while x==1:
		time.sleep(0.01)
		register = registersPerPage * RPMPageNumber + RPMRegisterOffset
		global RPMRegister
		RPMRegister  = sync_client_read(register)
		register = registersPerPage * DCCurrentPageNumber + DCCurrentEndOffset
		global DCRegister
		DCRegister = sync_client_read(register)
		DCRegister = float(DCRegister)
		x = 0
		os.system('sudo python3 readings.py')

	while 1==1:
		time.sleep(0.01)
		register = registersPerPage * RPMPageNumber + RPMRegisterOffset
		RPMRegister  = sync_client_read(register)
		register = registersPerPage * DCCurrentPageNumber + DCCurrentEndOffset
		DCregister  = sync_client_read(register)
		DCRegister  = float(DCRegister)
Example #42
0
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()