private void EstablishConnection()
        {
            if (_oldConnected)
            {
                ConnectionChanged?.Invoke(_connectionContext, false);
                _oldConnected = false;
            }

            if (_pollDevice == null)
            {
                Thread.Sleep(FailureRetryInterval);
                _pollDevice = _master.ConnectDevice(_address, _port, _id);
                return;
            }

            if (_pollDevice.IsConnected)
            {
                _retryCount   = 0;
                _failureCount = 0;
                GoState(Connected);
                return;
            }

            Thread.Sleep(FailureRetryInterval);
            _failureCount++;
            if (_failureCount > 2)
            {
                GoState(Disconnected);
            }
        }
        /// <summary>
        /// Start polling the specified slave.
        /// Establish connection.
        /// </summary>
        /// <param name="master"></param>
        /// <param name="address"></param>
        /// <param name="port"></param>
        /// <param name="id"></param>
        /// <param name="register"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public ModbusDevicePollService(ModbusMaster master, string address, ushort port, byte id, Register register, int offset, int count)
        {
            _master       = master;
            _address      = address;
            _port         = port;
            _id           = id;
            _pollDevice   = null;
            _oldConnected = true;

            _registerToPoll = register;
            _pollOffset     = offset;
            _pollCount      = count;
            _traceId        = $"ModbusDevicePollService({address}:{port}#{id})";

            PollRetryInterval    = TimeSpan.FromSeconds(0.1);
            FailureRetryInterval = TimeSpan.FromSeconds(1);
            PollRetries          = 1;
        }
        public void Stop()
        {
            if (_pollingTask == null)
            {
                return;
            }

            var p = _pollingTask;

            _pollingTask = null;
            p?.Wait(TimeSpan.FromSeconds(10));

            if (_pollDevice != null)
            {
                _pollDevice.Disconnect();
                _pollDevice.Dispose();
                _pollDevice = null;
            }
        }
        public ConnectedSlave ConnectDevice(string address, ushort port, byte id)
        {
            var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);

            try
            {
                sock.Connect(address, port);
                if (!sock.Connected)
                {
                    LastError = "Connect failed";
                    sock.Dispose();
                    return(null);
                }
            }
            catch (Exception ex)
            {
                LastError = ex.Message;
                Trace.TraceError("ModbusMaster: Could not connect to {0}:{1} id={2}" + Environment.NewLine + ex.Message,
                                 address, port, id);
                sock.Dispose();
                return(null);
            }

            LastError = null;
            var dev = new ConnectedSlave(this, sock, id);

            dev.Disconnected += () =>
            {
                lock (ConnectedSlaveDevices)
                {
                    ConnectedSlaveDevices.Remove(dev);
                }
            };

            lock (ConnectedSlaveDevices)
            {
                ConnectedSlaveDevices.Add(dev);
            }

            Trace.TraceInformation("ModbusMaster: Connected to device {0}:{1} id={2}", address, port, id);
            return(dev);
        }
 /// <summary>
 /// Start polling already connected slave.
 /// </summary>
 /// <param name="slave"></param>
 /// <param name="register"></param>
 /// <param name="offset"></param>
 /// <param name="count"></param>
 public ModbusDevicePollService(ConnectedSlave slave, Register register, int offset, int count)
     : this(slave.Master, slave.Address.ToString(), slave.Port, slave.Id, register, offset, count)
 {
     _pollDevice   = slave;
     _oldConnected = !_pollDevice.IsConnected;
 }