public async void TimeoutIsResetAfterRequest()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            var delay = TimeSpan.FromSeconds(1);

            await Task.Run(async() =>
            {
                var data = Enumerable.Range(0, 20).Select(i => (float)i).ToArray();

                // Act
                await Task.Delay(delay);
                var lastRequest1 = server.RequestHandlerSet.First().LastRequest.Elapsed;
                client.WriteMultipleRegisters(0, 0, data);
                var lastRequest2 = server.RequestHandlerSet.First().LastRequest.Elapsed;

                client.Disconnect();

                // Assert
                Assert.True(lastRequest1 >= delay);
                Assert.True(lastRequest2 < delay);
            });

            server.Stop();
        }
        public async void ServerHandlesRequestFire()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            // Act
            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            await Task.Run(() =>
            {
                var data       = Enumerable.Range(0, 20).Select(i => (float)i).ToArray();
                var sw         = Stopwatch.StartNew();
                var iterations = 10000;

                for (int i = 0; i < iterations; i++)
                {
                    client.WriteMultipleRegisters(0, 0, data);
                }

                var timePerRequest = sw.Elapsed.TotalMilliseconds / iterations;
                _logger.WriteLine($"Time per request: {timePerRequest * 1000:F0} us. Frequency: {1/timePerRequest * 1000:F0} requests per second.");

                client.Disconnect();
            });

            // Assert
        }
        public async void ServerWorksWithExternalTcpClient()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();
            var listener = new TcpListener(endpoint);

            using var server = new ModbusTcpServer();
            var client = new ModbusTcpClient();

            var expected = new double[] { 0.1, 0.2, 0.3, 0.4, 0.5 };

            double[] actual = null;

            // Act
            listener.Start();

            var clientTask = Task.Run(() =>
            {
                client.Connect(endpoint);

                actual = client
                         .ReadWriteMultipleRegisters <double, double>(0, 0, 5, 0, expected)
                         .ToArray();

                client.Disconnect();
            });

            var serverTask = Task.Run(() =>
            {
                var tcpClient = listener.AcceptTcpClient();
                server.Start(tcpClient);
            });

            await clientTask;

            // Assert
            Assert.True(actual.SequenceEqual(expected));
        }
Example #4
0
        static async Task Main(string[] args)
        {
            /* prepare dependency injection */
            var services = new ServiceCollection();

            ConfigureServices(services);
            /* create types */
            var provider      = services.BuildServiceProvider();
            var loggerFactory = provider.GetRequiredService <ILoggerFactory>();
            var serverLogger  = loggerFactory.CreateLogger("Server");
            var clientLogger  = loggerFactory.CreateLogger("Client");

            /* create Modbus TCP server and client */
            var server = new ModbusTcpServer(serverLogger);
            var client = new ModbusTcpClient();

            /* run Modbus TCP server (option 1) */
            var cts = new CancellationTokenSource();

            var task_server = Task.Run(async() =>
            {
                server.Start();

                while (!cts.IsCancellationRequested)
                {
                    // lock is required to synchronize buffer access between this application and one or more Modbus clients
                    lock (server.Lock)
                    {
                        DoServerWork(server);
                    }

                    // update server buffer content once per second
                    await Task.Delay(TimeSpan.FromSeconds(1));
                }

                server.Dispose();
            }, cts.Token);

            /* run Modbus TCP client */
            var task_client = Task.Run(() =>
            {
                client.Connect();

                try
                {
                    DoClientWork(client, clientLogger);
                }
                catch (Exception ex)
                {
                    clientLogger.LogError(ex.Message);
                }

                client.Disconnect();

                Console.WriteLine("Tests finished. Press any key to continue.");
                Console.ReadKey(true);
            });

            // wait for client task to finish
            await task_client;

            // stop server
            cts.Cancel();
            await task_server;

            server.Stop();
            serverLogger.LogInformation("Server stopped.");
        }
Example #5
0
        static async Task Main(string[] args)
        {
            /* create logger */
            var loggerFactory = LoggerFactory.Create(loggingBuilder =>
            {
                loggingBuilder.SetMinimumLevel(LogLevel.Debug);
                loggingBuilder.AddConsole();
            });

            var serverLogger = loggerFactory.CreateLogger("Server");
            var clientLogger = loggerFactory.CreateLogger("Client");

            /* create Modbus TCP server */
            using var server = new ModbusTcpServer(serverLogger)
                  {
                      // see 'RegistersChanged' event below
                      EnableRaisingEvents = true
                  };

            /* subscribe to the 'RegistersChanged' event (in case you need it) */
            server.RegistersChanged += (sender, registerAddresses) =>
            {
                // the variable 'registerAddresses' contains a list of modified register addresses
            };

            /* create Modbus TCP client */
            var client = new ModbusTcpClient();

            /* run Modbus TCP server */
            var cts = new CancellationTokenSource();

            var task_server = Task.Run(async() =>
            {
                server.Start();
                serverLogger.LogInformation("Server started.");

                while (!cts.IsCancellationRequested)
                {
                    // lock is required to synchronize buffer access between this application and one or more Modbus clients
                    lock (server.Lock)
                    {
                        DoServerWork(server);
                    }

                    // update server register content once per second
                    await Task.Delay(TimeSpan.FromSeconds(1));
                }
            }, cts.Token);

            /* run Modbus TCP client */
            var task_client = Task.Run(() =>
            {
                client.Connect();

                try
                {
                    DoClientWork(client, clientLogger);
                }
                catch (Exception ex)
                {
                    clientLogger.LogError(ex.Message);
                }

                client.Disconnect();

                Console.WriteLine("Tests finished. Press any key to continue.");
                Console.ReadKey(true);
            });

            // wait for client task to finish
            await task_client;

            // stop server
            cts.Cancel();
            await task_server;

            server.Stop();
            serverLogger.LogInformation("Server stopped.");
        }
        static async Task Main(string[] args)
        {
            string SENTRON_IP = Environment.GetEnvironmentVariable("SENTRON_IP");
            string SENTRON_ID = Environment.GetEnvironmentVariable("SENTRON_ID");
            string INFLUXDB_IP = Environment.GetEnvironmentVariable("INFLUXDB_IP");
            string INFLUXDB_PORT = Environment.GetEnvironmentVariable("INFLUXDB_PORT");
            string INFLUXDB_DATABASE = Environment.GetEnvironmentVariable("INFLUXDB_DATABASE");
            string INFLUXDB_USERNAME = Environment.GetEnvironmentVariable("INFLUXDB_USERNAME");
            string INFLUXDB_PASSWORD = Environment.GetEnvironmentVariable("INFLUXDB_PASSWORD");
            int    RETRY, READING;

            if (!Int32.TryParse(Environment.GetEnvironmentVariable("RETRY"), out RETRY))
            {
                Console.WriteLine("Invalid RETRY using 10");
                RETRY = 10 * 1000;
            }
            else
            {
                RETRY = RETRY * 1000;
            }
            if (!Int32.TryParse(Environment.GetEnvironmentVariable("READING"), out READING))
            {
                Console.WriteLine("Invalid READING using 5");
                READING = 5 * 1000;
            }
            else
            {
                READING = READING * 1000;
            }

            string statusURLString = "http://" + SENTRON_IP + "/";
            string influxDbURL     = "http://" + INFLUXDB_IP + ":" + INFLUXDB_PORT;

            Console.WriteLine("Running with below parameters");
            Console.WriteLine("\tSENTRON_IP {0}", SENTRON_IP);
            Console.WriteLine("\tSENTRON_ID {0}", SENTRON_ID);
            Console.WriteLine("\tINFLUXDB_IP {0}", INFLUXDB_IP);
            Console.WriteLine("\tINFLUXDB_PORT {0}", INFLUXDB_PORT);
            Console.WriteLine("\tINFLUXDB_DATABASE {0}", INFLUXDB_DATABASE);
            Console.WriteLine("\tINFLUXDB_USERNAME {0}", INFLUXDB_USERNAME);
            Console.WriteLine("\tINFLUXDB_PASSWORD {0}", INFLUXDB_PASSWORD);
            Console.WriteLine("\tRETRY {0}", RETRY / 1000);
            Console.WriteLine("\tREADING {0}", READING / 1000);
            Console.WriteLine("\n\nUsing Status URL   : {0}", statusURLString);
            Console.WriteLine("Using InfluxDB URL : {0}", influxDbURL);


            while (true)
            {
                InfluxDBClient influxClient = new InfluxDBClient(influxDbURL, INFLUXDB_USERNAME, INFLUXDB_PASSWORD);
                try
                {
                    while (true)
                    {
                        byte unitIdentifier = 0xFF;

                        client.Connect(IPAddress.Parse(SENTRON_IP));
                        var data = client.ReadHoldingRegisters(unitIdentifier, 200, 122).ToArray();

                        var valMixed = new InfluxDatapoint <InfluxValueField>();
                        valMixed.UtcTimestamp = DateTime.UtcNow;
                        valMixed.Tags.Add("id", SENTRON_ID);
                        valMixed.MeasurementName = "METER_DATA";
                        valMixed.Precision       = TimePrecision.Seconds;

                        var Va = ToFloatStart201(data, 201);
                        var Vb = ToFloatStart201(data, 203);
                        var Vc = ToFloatStart201(data, 205);
                        var VN = ToFloatStart201(data, 207);

                        valMixed.Fields.Add("Va", new InfluxValueField(Va));
                        valMixed.Fields.Add("Vb", new InfluxValueField(Vb));
                        valMixed.Fields.Add("Vc", new InfluxValueField(Vc));
                        valMixed.Fields.Add("VN", new InfluxValueField(VN));

                        var Ia = ToFloatStart201(data, 209);
                        var Ib = ToFloatStart201(data, 211);
                        var Ic = ToFloatStart201(data, 213);
                        var IN = ToFloatStart201(data, 215);

                        valMixed.Fields.Add("Ia", new InfluxValueField(Ia));
                        valMixed.Fields.Add("Ib", new InfluxValueField(Ib));
                        valMixed.Fields.Add("Ic", new InfluxValueField(Ic));
                        valMixed.Fields.Add("IN", new InfluxValueField(IN));

                        var Vab = ToFloatStart201(data, 217);
                        var Vbc = ToFloatStart201(data, 219);
                        var Vca = ToFloatStart201(data, 221);

                        valMixed.Fields.Add("Vab", new InfluxValueField(Vab));
                        valMixed.Fields.Add("Vbc", new InfluxValueField(Vbc));
                        valMixed.Fields.Add("Vca", new InfluxValueField(Vca));

                        var Vavg = ToFloatStart201(data, 223);
                        var Iavg = ToFloatStart201(data, 225);

                        valMixed.Fields.Add("Vavg", new InfluxValueField(Vavg));
                        valMixed.Fields.Add("Iavg", new InfluxValueField(Iavg));

                        var Pa = ToFloatStart201(data, 227);
                        var Pb = ToFloatStart201(data, 229);
                        var Pc = ToFloatStart201(data, 231);
                        var P  = ToFloatStart201(data, 233);

                        valMixed.Fields.Add("Pa", new InfluxValueField(Pa));
                        valMixed.Fields.Add("Pb", new InfluxValueField(Pb));
                        valMixed.Fields.Add("Pc", new InfluxValueField(Pc));
                        valMixed.Fields.Add("P", new InfluxValueField(P));

                        var Qa = ToFloatStart201(data, 235);
                        var Qb = ToFloatStart201(data, 237);
                        var Qc = ToFloatStart201(data, 239);
                        var Q  = ToFloatStart201(data, 241);

                        var Sa = ToFloatStart201(data, 243);
                        var Sb = ToFloatStart201(data, 245);
                        var Sc = ToFloatStart201(data, 247);
                        var S  = ToFloatStart201(data, 249);

                        var cos_phi_a = ToFloatStart201(data, 251);
                        var cos_phi_b = ToFloatStart201(data, 253);
                        var cos_phi_c = ToFloatStart201(data, 255);
                        var cos_phi   = ToFloatStart201(data, 257);

                        var PFa = ToFloatStart201(data, 259);
                        var PFb = ToFloatStart201(data, 261);
                        var PFc = ToFloatStart201(data, 263);
                        var PF  = ToFloatStart201(data, 265);

                        valMixed.Fields.Add("PFa", new InfluxValueField(PFa));
                        valMixed.Fields.Add("PFb", new InfluxValueField(PFb));
                        valMixed.Fields.Add("PFc", new InfluxValueField(PFc));
                        valMixed.Fields.Add("PF", new InfluxValueField(PF));

                        var phi_a = ToFloatStart201(data, 267);
                        var phi_b = ToFloatStart201(data, 269);
                        var phi_c = ToFloatStart201(data, 271);
                        var phi   = ToFloatStart201(data, 273);

                        var f  = ToFloatStart201(data, 275);
                        var U2 = ToFloatStart201(data, 277);

                        var THDS_Va_Vab = ToFloatStart201(data, 295);
                        var THDS_Vb_Vbc = ToFloatStart201(data, 297);
                        var THDS_Vc_Vca = ToFloatStart201(data, 299);

                        var THDS_Ia = ToFloatStart201(data, 301);
                        var THDS_Ib = ToFloatStart201(data, 303);
                        var THDS_Ic = ToFloatStart201(data, 305);

                        var V_phi_12 = ToFloatStart201(data, 307);
                        var V_phi_13 = ToFloatStart201(data, 309);
                        var I_phi_12 = ToFloatStart201(data, 311);
                        var I_phi_13 = ToFloatStart201(data, 313);

                        var Q1a = ToFloatStart201(data, 315);
                        var Q1b = ToFloatStart201(data, 317);
                        var Q1c = ToFloatStart201(data, 319);
                        var Q1  = ToFloatStart201(data, 321);

                        var r = await influxClient.PostPointAsync(INFLUXDB_DATABASE, valMixed);

                        Console.WriteLine(r);
                        Thread.Sleep(READING);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nException Caught!");
                    Console.WriteLine("Message :{0} ", e.Message);
                }
                client.Disconnect();
                influxClient.Dispose();
                Thread.Sleep(RETRY);
            }
        }