Ability to add multiple modbus hubs

Works for me.
Thank you for sharing your easy workaround.

1 Like

@cgrueter @monkey-house

Just testing 1 slave 1 register per connection but so far so good. No real CPU or mem increase.

Let me know how things go for you guys…

I am really counting on multiple connections. I will try to look into full integration.

1 Like

Will hopefully have a look tonight!
@PtP: have you made a pull request on the Home Assistant GitHub. For guys who’ve got experience writing components for Home Assistant, it’s probably easy to come up with a solution that alter the .py file based on the presence of a modus1 entity in the configuration.yaml. Maybe this can become an integral part of Home Assistant by v .73 or .74?

I have not yet but I plan on it!

That’d be great.
Could you also please publish the fully revised code for the modbus1.py custom_component + custom_component/sensor here for ease of upgrading?
It’s a pain to access files for docker containers even locally, let alone remotely… Sure it would make it easier for many users: just copy the modbus1.py files to their respective folders, upgrade configuration.yaml and you’re good to go!

OK, just got to test this as well. It works great. I can finally delete my second instance of Hass and run all in a single container. Thanks @PtP.

Here is the corrected custom_component modbus1.py:

"""
Support for Modbus.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/modbus/
"""
import logging
import threading

import voluptuous as vol

import homeassistant.helpers.config_validation as cv
from homeassistant.const import (
    EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
    CONF_HOST, CONF_METHOD, CONF_PORT, CONF_TYPE, CONF_TIMEOUT, ATTR_STATE)

DOMAIN = 'modbus1'

REQUIREMENTS = ['pymodbus==1.3.1']

# Type of network
CONF_BAUDRATE = 'baudrate'
CONF_BYTESIZE = 'bytesize'
CONF_STOPBITS = 'stopbits'
CONF_PARITY = 'parity'

SERIAL_SCHEMA = {
    vol.Required(CONF_BAUDRATE): cv.positive_int,
    vol.Required(CONF_BYTESIZE): vol.Any(5, 6, 7, 8),
    vol.Required(CONF_METHOD): vol.Any('rtu', 'ascii'),
    vol.Required(CONF_PORT): cv.string,
    vol.Required(CONF_PARITY): vol.Any('E', 'O', 'N'),
    vol.Required(CONF_STOPBITS): vol.Any(1, 2),
    vol.Required(CONF_TYPE): 'serial',
    vol.Optional(CONF_TIMEOUT, default=3): cv.socket_timeout,
}

ETHERNET_SCHEMA = {
    vol.Required(CONF_HOST): cv.string,
    vol.Required(CONF_PORT): cv.positive_int,
    vol.Required(CONF_TYPE): vol.Any('tcp', 'udp', 'rtuovertcp'),
    vol.Optional(CONF_TIMEOUT, default=3): cv.socket_timeout,
}


CONFIG_SCHEMA = vol.Schema({
    DOMAIN: vol.Any(SERIAL_SCHEMA, ETHERNET_SCHEMA)
}, extra=vol.ALLOW_EXTRA)


_LOGGER = logging.getLogger(__name__)

SERVICE_WRITE_REGISTER = 'write_register'
SERVICE_WRITE_COIL = 'write_coil'

ATTR_ADDRESS = 'address'
ATTR_UNIT = 'unit'
ATTR_VALUE = 'value'

SERVICE_WRITE_REGISTER_SCHEMA = vol.Schema({
    vol.Required(ATTR_UNIT): cv.positive_int,
    vol.Required(ATTR_ADDRESS): cv.positive_int,
    vol.Required(ATTR_VALUE): vol.All(cv.ensure_list, [cv.positive_int])
})

SERVICE_WRITE_COIL_SCHEMA = vol.Schema({
    vol.Required(ATTR_UNIT): cv.positive_int,
    vol.Required(ATTR_ADDRESS): cv.positive_int,
    vol.Required(ATTR_STATE): cv.boolean
})

HUB = None


def setup(hass, config):
    """Set up Modbus component."""
    # Modbus connection type
    client_type = config[DOMAIN][CONF_TYPE]

    # Connect to Modbus network
    # pylint: disable=import-error

    if client_type == 'serial':
        from pymodbus.client.sync import ModbusSerialClient as ModbusClient
        client = ModbusClient(method=config[DOMAIN][CONF_METHOD],
                              port=config[DOMAIN][CONF_PORT],
                              baudrate=config[DOMAIN][CONF_BAUDRATE],
                              stopbits=config[DOMAIN][CONF_STOPBITS],
                              bytesize=config[DOMAIN][CONF_BYTESIZE],
                              parity=config[DOMAIN][CONF_PARITY],
                              timeout=config[DOMAIN][CONF_TIMEOUT])
    elif client_type == 'rtuovertcp':
        from pymodbus.client.sync import ModbusTcpClient as ModbusClient
        from pymodbus.transaction import ModbusRtuFramer as ModbusFramer
        client = ModbusClient(host=config[DOMAIN][CONF_HOST],
                              port=config[DOMAIN][CONF_PORT],
                              framer=ModbusFramer,
                              timeout=config[DOMAIN][CONF_TIMEOUT])
    elif client_type == 'tcp':
        from pymodbus.client.sync import ModbusTcpClient as ModbusClient
        client = ModbusClient(host=config[DOMAIN][CONF_HOST],
                              port=config[DOMAIN][CONF_PORT],
                              timeout=config[DOMAIN][CONF_TIMEOUT])
    elif client_type == 'udp':
        from pymodbus.client.sync import ModbusUdpClient as ModbusClient
        client = ModbusClient(host=config[DOMAIN][CONF_HOST],
                              port=config[DOMAIN][CONF_PORT],
                              timeout=config[DOMAIN][CONF_TIMEOUT])
    else:
        return False

    global HUB
    HUB = ModbusHub(client)

    def stop_modbus(event):
        """Stop Modbus service."""
        HUB.close()

    def start_modbus(event):
        """Start Modbus service."""
        HUB.connect()
        hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_modbus)

        # Register services for modbus
        hass.services.register(
            DOMAIN, SERVICE_WRITE_REGISTER, write_register,
            schema=SERVICE_WRITE_REGISTER_SCHEMA)
        hass.services.register(
            DOMAIN, SERVICE_WRITE_COIL, write_coil,
            schema=SERVICE_WRITE_COIL_SCHEMA)

    def write_register(service):
        """Write modbus registers."""
        unit = int(float(service.data.get(ATTR_UNIT)))
        address = int(float(service.data.get(ATTR_ADDRESS)))
        value = service.data.get(ATTR_VALUE)
        if isinstance(value, list):
            HUB.write_registers(
                unit,
                address,
                [int(float(i)) for i in value])
        else:
            HUB.write_register(
                unit,
                address,
                int(float(value)))

    def write_coil(service):
        """Write modbus coil."""
        unit = service.data.get(ATTR_UNIT)
        address = service.data.get(ATTR_ADDRESS)
        state = service.data.get(ATTR_STATE)
        HUB.write_coil(unit, address, state)

    hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_modbus)

    return True


class ModbusHub(object):
    """Thread safe wrapper class for pymodbus."""

    def __init__(self, modbus_client):
        """Initialize the modbus hub."""
        self._client = modbus_client
        self._lock = threading.Lock()

    def close(self):
        """Disconnect client."""
        with self._lock:
            self._client.close()

    def connect(self):
        """Connect client."""
        with self._lock:
            self._client.connect()

    def read_coils(self, unit, address, count):
        """Read coils."""
        with self._lock:
            kwargs = {'unit': unit} if unit else {}
            return self._client.read_coils(
                address,
                count,
                **kwargs)

    def read_input_registers(self, unit, address, count):
        """Read input registers."""
        with self._lock:
            kwargs = {'unit': unit} if unit else {}
            return self._client.read_input_registers(
                address,
                count,
                **kwargs)

    def read_holding_registers(self, unit, address, count):
        """Read holding registers."""
        with self._lock:
            kwargs = {'unit': unit} if unit else {}
            return self._client.read_holding_registers(
                address,
                count,
                **kwargs)

    def write_coil(self, unit, address, value):
        """Write coil."""
        with self._lock:
            kwargs = {'unit': unit} if unit else {}
            self._client.write_coil(
                address,
                value,
                **kwargs)

    def write_register(self, unit, address, value):
        """Write register."""
        with self._lock:
            kwargs = {'unit': unit} if unit else {}
            self._client.write_register(
                address,
                value,
                **kwargs)

    def write_registers(self, unit, address, values):
        """Write registers."""
        with self._lock:
            kwargs = {'unit': unit} if unit else {}
            self._client.write_registers(
                address,
                values,
                **kwargs)

And the custom_component/sensor modbus1.py:

"""
Support for Modbus Register sensors.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.modbus/
"""
import logging
import struct

import voluptuous as vol

import custom_components.modbus1 as modbus
from homeassistant.const import (
    CONF_NAME, CONF_OFFSET, CONF_UNIT_OF_MEASUREMENT, CONF_SLAVE,
    CONF_STRUCTURE)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers import config_validation as cv
from homeassistant.components.sensor import PLATFORM_SCHEMA

_LOGGER = logging.getLogger(__name__)

DEPENDENCIES = ['modbus1']

CONF_COUNT = 'count'
CONF_REVERSE_ORDER = 'reverse_order'
CONF_PRECISION = 'precision'
CONF_REGISTER = 'register'
CONF_REGISTERS = 'registers'
CONF_SCALE = 'scale'
CONF_DATA_TYPE = 'data_type'
CONF_REGISTER_TYPE = 'register_type'

REGISTER_TYPE_HOLDING = 'holding'
REGISTER_TYPE_INPUT = 'input'

DATA_TYPE_INT = 'int'
DATA_TYPE_UINT = 'uint'
DATA_TYPE_FLOAT = 'float'
DATA_TYPE_CUSTOM = 'custom'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_REGISTERS): [{
        vol.Required(CONF_NAME): cv.string,
        vol.Required(CONF_REGISTER): cv.positive_int,
        vol.Optional(CONF_REGISTER_TYPE, default=REGISTER_TYPE_HOLDING):
            vol.In([REGISTER_TYPE_HOLDING, REGISTER_TYPE_INPUT]),
        vol.Optional(CONF_COUNT, default=1): cv.positive_int,
        vol.Optional(CONF_REVERSE_ORDER, default=False): cv.boolean,
        vol.Optional(CONF_OFFSET, default=0): vol.Coerce(float),
        vol.Optional(CONF_PRECISION, default=0): cv.positive_int,
        vol.Optional(CONF_SCALE, default=1): vol.Coerce(float),
        vol.Optional(CONF_SLAVE): cv.positive_int,
        vol.Optional(CONF_DATA_TYPE, default=DATA_TYPE_INT):
            vol.In([DATA_TYPE_INT, DATA_TYPE_UINT, DATA_TYPE_FLOAT,
                    DATA_TYPE_CUSTOM]),
        vol.Optional(CONF_STRUCTURE): cv.string,
        vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string
    }]
})


def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the Modbus sensors."""
    sensors = []
    data_types = {DATA_TYPE_INT: {1: 'h', 2: 'i', 4: 'q'}}
    data_types[DATA_TYPE_UINT] = {1: 'H', 2: 'I', 4: 'Q'}
    data_types[DATA_TYPE_FLOAT] = {1: 'e', 2: 'f', 4: 'd'}

    for register in config.get(CONF_REGISTERS):
        structure = '>i'
        if register.get(CONF_DATA_TYPE) != DATA_TYPE_CUSTOM:
            try:
                structure = '>{}'.format(data_types[
                    register.get(CONF_DATA_TYPE)][register.get(CONF_COUNT)])
            except KeyError:
                _LOGGER.error("Unable to detect data type for %s sensor, "
                              "try a custom type.", register.get(CONF_NAME))
                continue
        else:
            structure = register.get(CONF_STRUCTURE)

        try:
            size = struct.calcsize(structure)
        except struct.error as err:
            _LOGGER.error(
                "Error in sensor %s structure: %s",
                register.get(CONF_NAME), err)
            continue

        if register.get(CONF_COUNT) * 2 != size:
            _LOGGER.error(
                "Structure size (%d bytes) mismatch registers count "
                "(%d words)", size, register.get(CONF_COUNT))
            continue

        sensors.append(ModbusRegisterSensor(
            register.get(CONF_NAME),
            register.get(CONF_SLAVE),
            register.get(CONF_REGISTER),
            register.get(CONF_REGISTER_TYPE),
            register.get(CONF_UNIT_OF_MEASUREMENT),
            register.get(CONF_COUNT),
            register.get(CONF_REVERSE_ORDER),
            register.get(CONF_SCALE),
            register.get(CONF_OFFSET),
            structure,
            register.get(CONF_PRECISION)))

    if not sensors:
        return False
    add_devices(sensors)


class ModbusRegisterSensor(Entity):
    """Modbus register sensor."""

    def __init__(self, name, slave, register, register_type,
                 unit_of_measurement, count, reverse_order, scale, offset,
                 structure, precision):
        """Initialize the modbus register sensor."""
        self._name = name
        self._slave = int(slave) if slave else None
        self._register = int(register)
        self._register_type = register_type
        self._unit_of_measurement = unit_of_measurement
        self._count = int(count)
        self._reverse_order = reverse_order
        self._scale = scale
        self._offset = offset
        self._precision = precision
        self._structure = structure
        self._value = None

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._value

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._name

    @property
    def unit_of_measurement(self):
        """Return the unit of measurement."""
        return self._unit_of_measurement

    def update(self):
        """Update the state of the sensor."""
        if self._register_type == REGISTER_TYPE_INPUT:
            result = modbus.HUB.read_input_registers(
                self._slave,
                self._register,
                self._count)
        else:
            result = modbus.HUB.read_holding_registers(
                self._slave,
                self._register,
                self._count)
        val = 0

        try:
            registers = result.registers
            if self._reverse_order:
                registers.reverse()
        except AttributeError:
            _LOGGER.error("No response from modbus slave %s, register %s",
                          self._slave, self._register)
            return
        byte_string = b''.join(
            [x.to_bytes(2, byteorder='big') for x in registers]
        )
        val = struct.unpack(self._structure, byte_string)[0]
        self._value = format(
            self._scale * val + self._offset, '.{}f'.format(self._precision))

Let us know when you post on GitHub so we can support the fixed implementation of multiple modbus or to update the Home Assistant documentation, if we can only add a modbus1.py!

Hi, I just stumbled on this thread when I was trying to implement my second modbus hub. I have already configured modbus tcp but now I was planning to add another one, for modbus rtu. I am running hassio so don’t think I have access to those modbus.py files that you refer to… Does anyone know if it is possible to add both modbus tcp and rtu on hassio…? Thanks in advance.

There is no reason why you could not do this on hass.io. You just need to find out the paths to the custom_components folder (should be in your config folder)…

1 Like

Yes, you are right, it works perfectly now. There was no “custom_components” folder but I just created one inside of the config folder. And then created a “sensor” folder inside that.
Then just copy the 2 modbus1.py files inside those two folders and now it works fine. Thanks everyone for this.

1 Like

Yup, looks like this can be applied to any component. I’m looking at implementing this for Octoprint…

I have 3 Modbus Clients now. Working good! I made a few more code changes. Seems like it helped reduce memory use.

Hi

I’ve been looking for this for ages.

Tried it out and it works. Yay.

Amazing work.

Thank you. Thank you. Thank you.

Celebrated too quickly.

Getting errors from both devices now. Reverting to original config.
At least I was getting some readings on the second device.

Hi

Tried again today but still not getting any readings at all.

This is my configuration.yaml entry:

# Modbus sensors in sensors.yaml
modbus:
  type: serial
  method: rtu
  port: /dev/ttyUSB0
  baudrate: 9600
  stopbits: 1
  bytesize: 8
  parity: N
  scan_interval: 30

modbus1:
  type: serial
  method: rtu
  port: /dev/ttyUSB0
  baudrate: 9600
  stopbits: 1
  bytesize: 8
  parity: N
  scan_interval: 30

This is the sensor entry:

#Modbus SDM230 ##########
- platform: modbus
  registers:
  - name: 'Grid Voltage'
    unit_of_measurement: Volts
    slave: 1
    register: 0
    register_type: input
    count: 2
    data_type: float
  - name: 'Grid Current'                                                    
    unit_of_measurement: Amps
    slave: 1                                                                
    register: 6
    register_type: input                                                        
    count: 2                                                                 
    data_type: float 
  - name: 'Grid Power'                                                    
    unit_of_measurement: Watts
    slave: 1                                                                
    register: 12
    register_type: input                                                        
    count: 2                                                                 
    data_type: float 
  - name: 'Grid Import Energy Raw'                                                    
    unit_of_measurement: kWh
    slave: 1                                                                
    register: 72
    register_type: input                                                        
    count: 2    
    data_type: float 
    precision: 2 
    offset: 36481.26
  - name: 'Grid Export Energy Raw'                                                    
    unit_of_measurement: kWh
    slave: 1                                                                
    register: 74
    register_type: input                                                        
    count: 2                                                                 
    data_type: float 
    precision: 2
    offset: 10274.41
  - name: 'Total Hours'
    unit_of_measurement: h
    slave: 1
    register: 63792
    register_type: holding
    count: 2
    data_type: float
    precision: 2

#Modbus SDM120 ##########
- platform: modbus1
  registers:
  - name: 'Solar Voltage'
    unit_of_measurement: Volts
    slave: 2
    register: 0
    register_type: input
    count: 2
    data_type: float
  - name: 'Solar Current'                                                    
    unit_of_measurement: Amps
    slave: 2                                                                
    register: 6
    register_type: input                                                        
    count: 2                                                                 
    data_type: float 
  - name: 'Solar Power'                                                    
    unit_of_measurement: Watts
    slave: 2                                                                
    register: 12
    register_type: input                                                        
    count: 2                                                                 
    data_type: float 
  - name: 'Solar Import Energy Raw'
    unit_of_measurement: kWh
    slave: 2                                                                
    register: 72
    register_type: input                                                        
    count: 2                                                                 
    data_type: float 
    precision: 2                                                             
    offset: 21326.51

Both modbus1.py files have been copied from monkey-house’s post into their correct locations.

The only thing that I haven’t done is change ownership as suggested. I’m on Hassio and the files belong to ‘root’. Not sure if I need to change that.

I’m getting this in the Log

2018-10-17 14:47:39 ERROR (SyncWorker_15) [homeassistant.components.sensor.modbus] No response from modbus slave 1, register 72
2018-10-17 14:47:42 ERROR (SyncWorker_7) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:47:45 ERROR (SyncWorker_7) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:47:48 ERROR (SyncWorker_7) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:47:48 ERROR (SyncWorker_7) [homeassistant.components.sensor.modbus] No response from modbus slave 1, register 74
2018-10-17 14:47:48 ERROR (SyncWorker_10) [custom_components.sensor.modbus1] No response from modbus slave 2, register 0
2018-10-17 14:47:51 ERROR (SyncWorker_8) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:47:54 ERROR (SyncWorker_8) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:47:57 ERROR (SyncWorker_8) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:47:57 ERROR (SyncWorker_11) [custom_components.sensor.modbus1] No response from modbus slave 2, register 6
2018-10-17 14:47:57 ERROR (SyncWorker_8) [homeassistant.components.sensor.modbus] No response from modbus slave 1, register 0
2018-10-17 14:48:00 ERROR (SyncWorker_3) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:48:03 ERROR (SyncWorker_3) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:48:04 WARNING (MainThread) [homeassistant.components.sensor] Updating modbus1 sensor took longer than the scheduled update interval 0:00:30
2018-10-17 14:48:04 WARNING (MainThread) [homeassistant.components.sensor] Updating modbus sensor took longer than the scheduled update interval 0:00:30
2018-10-17 14:48:06 ERROR (SyncWorker_2) [custom_components.sensor.modbus1] No response from modbus slave 2, register 72
2018-10-17 14:48:06 ERROR (SyncWorker_3) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:48:06 ERROR (SyncWorker_3) [homeassistant.components.sensor.modbus] No response from modbus slave 1, register 12
2018-10-17 14:48:06 ERROR (SyncWorker_9) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:48:06 ERROR (SyncWorker_9) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:48:06 ERROR (SyncWorker_9) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:48:06 ERROR (SyncWorker_9) [homeassistant.components.sensor.modbus] No response from modbus slave 1, register 6
2018-10-17 14:48:06 ERROR (SyncWorker_17) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:48:06 ERROR (SyncWorker_17) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:48:06 ERROR (SyncWorker_17) [pymodbus.factory] Unable to decode response Modbus Error: Unknown response 68
2018-10-17 14:48:06 ERROR (SyncWorker_17) [homeassistant.components.sensor.modbus] No response from modbus slave 1, register 63792

What am I doing wrong?

Thank you for any suggestions.

Hi

Been trying to get this to work on my 2 modus devices without success.

They’re connected via serial rtu.

Would you post your corrected modbus1 files. as I’m on Hassio.

Thank you.

Hi,
I don’t think you need to do all of this to be able to talk to your two modbus slaves if they are both connected using serial interface and using the same communication parameters… I had to add modbus1 because I am using devices that are connected both on serial and tcp… In your case it should be enough to have modbus serial interface and then simply address slave 1 and slave 2 from that… (?) are you sure that they are communicating with 9600 bps, 1 stopbit and no parity?
I can post the files when I get back to my computer.

Hi Mgdfp

Thank you for your reply.

That is certainly some useful information.

The connection settting should be fine but I’ll check again.

The thing is that slave 2 is being read ok just not all the time. As a consequence I get continuous errors from slave 2 and a graph that looks like this:
06

Should you have any ideas it would be most appreciated.

Thank you.

Yeah, I see what you mean and I have something of a similar problem. SDM120s or SDM230s that are reporting “no resplonse” periodically.

https://community.home-assistant.io/t/no-response-from-modbus-slave-2-register-0/58943/7

I have a plan for how I want to get around this but so far I have not had time to do anything, I will post in that thread since it is more relevant.

Hello,

The solution I found is to add multiple “sensor networks”. Each network containing multiple slaves. This allows you for example to have a RTU network at 9600 baud, and RTU network at 115200, and a TCP network all in the same HA instance. The various sensor networks will require their own usb to serial or tcp/ip to serial adapter connected to the Pi or whatever hardware you are using.

I know very little about Hassio as it is not a robust enough solution for the many things I do with HA.

I also believe that the random no response or the failing to clear buffer is a pymodbus issue.

This could also be related to line biasing on the communication wire. These systems usually require proper communication cable and end of line termination (120 Ohms if proper cable is used).

If there are further questions let me know.

Thanks so much [monkey-house] and others for your invaluable help with this problem I was having. Initially I could not make this work as you have described here but after much time wasted I found I made a stupid typo in the target folder, your “custom_components” became “custom_component” in my home assistant config area. Stupid me!

Anyway so far I have 3 PLC’s connected with 2 more to go go and 350 odd tags to connect to.

Again many thanks!

PS: If you get errors in your logs I suggest to look at how your PLC is configured as the third one I connected caused errors. It was a silly ethernet reset I had configured in my plc which once ditched everything came good.

This is a wonderful community here…never forget that people!

1 Like