예제 #1
0
        protected override async Task ServiceTaskAsync(CancellationToken cancellationToken)
        {
            ArcController?.NewLogMessage(LogCode.ModbusStarting);

            Logger.Info("begin");

            var tcpListener = new TcpListener(IPAddress.Any, TcpPort);
            var rtuListener = new TcpListener(IPAddress.Any, RtuOverTcpPort);

            Logger.Info("starting listener");

            tcpListener.Start();
            rtuListener.Start();

            Logger.Info("generating slave net");

            var factory = new ModbusFactory();

            var tcpNetwork = factory.CreateSlaveNetwork(tcpListener);
            var rtuNetwork = factory.CreateRtuOverTcpSlaveNetwork(rtuListener);

            var slaveTcp = factory.CreateSlave(1);
            var slaveRtu = factory.CreateSlave(1, slaveTcp.DataStore);

            tcpNetwork.AddSlave(slaveTcp);
            rtuNetwork.AddSlave(slaveRtu);

            iRegisters = slaveTcp.DataStore.InputRegisters;
            hRegisters = slaveTcp.DataStore.HoldingRegisters;

            WfqydbServer.PropertyChanged += Wf_PropertyChanged;

            var timeOfStart = DateTime.Now.ToUnixTimestamp();

            ushort[] timeOfStartBuffer =
            {
                (ushort)(timeOfStart >> 16),
                (ushort)(timeOfStart),
            };

            var ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

            ushort[] verBuffer =
            {
                (ushort)ver.Major,
                (ushort)ver.Minor,
                (ushort)ver.Build,
            };

            byte[] myAddress = { 0x01, 0x00, 0x00, 0x00, };

            iRegisters.WritePoints(0, verBuffer);
            iRegisters.WritePoints(3, timeOfStartBuffer);

            Logger.Info("starting slave net. step1");

            var tcpListenerTask = tcpNetwork.ListenAsync(cancellationToken);
            var rtuListenerTask = rtuNetwork.ListenAsync(cancellationToken);

            Logger.Info($"starting slave net. step2 {WfqydbServer.ToString()}");

            ArcController?.NewLogMessage(LogCode.ModbusStarted);
            ArcController?.NewLogMessage(LogCode.WFQYDBConnecting);

            //await WfqydbServer.PullBroadcastQuery().ConfigureAwait(false);
            //WfqydbServer.PullBroadcastQuery();
            ArcController?.NewLogMessage(LogCode.WFQYDBConnected);

            const int waitTime        = 100;    //ms
            const int faultRestTime   = 10_000; //ms
            const int responseTime    = 500;    //ms
            var       lastRequestTime = DateTime.Now;
            var       lastResetTime   = DateTime.Now;
            var       resetInterval   = TimeSpan.FromSeconds(30);

            var faultRestTimer = 0;

            Logger.Info("entering inf loop");
            // Главный цикл до отмены этой задачи.
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    // состояние связи
                    iRegisters.WritePoints(5, new ushort[] { (ushort)WfqydbServer.ConnectionState });
                    // Habdle

                    var buff     = hRegisters.ReadPoints(10, 5);
                    var cmd      = buff[0];
                    var cmdState = buff[1];

                    if ((buff[2] + buff[3]) == 0)
                    {
                        // Чтобы не было пустого места на элкамрм
                        hRegisters.WritePoints(12, new ushort[] { currentData[3], currentData[4], currentData[6] });
                    }

                    // обработка команд по модбас
                    if ((cmd > 0) && (cmdState == (ushort)CmdState.Rdy))
                    {
                        var upFreq    = (byte)buff[2];
                        var dnFreq    = (byte)buff[3];
                        var stokeRate = (byte)buff[4];

                        hRegisters.WritePoints(10, new ushort[] { cmd, (ushort)CmdState.Working });

                        try
                        {
                            switch ((Cmd)cmd)
                            {
                            case Cmd.Reset:
                                cmd      = 0;
                                cmdState = 0;
                                hRegisters.WritePoints(10, new ushort[] { (ushort)Cmd.NoOp, (ushort)CmdState.Rdy });
                                break;

                            case Cmd.BroadcastQuery:
                                lastRequestTime = DateTime.Now;
                                //await WfqydbServer.PullBroadcastQuery().ConfigureAwait(false);
                                WfqydbServer.PullBroadcastQuery();
                                hRegisters.WritePoints(10, new ushort[] { (ushort)Cmd.NoOp, (ushort)CmdState.Rdy });

                                ArcController?.NewLogMessage(LogCode.WFQYDBCmdRead);
                                break;

                            case Cmd.AutoRun:
                                lastRequestTime = DateTime.Now;
                                //await WfqydbServer.PullAutoRun(upFreq, dnFreq, stokeRate).ConfigureAwait(false);
                                WfqydbServer.PullAutoRun(upFreq, dnFreq, stokeRate);
                                hRegisters.WritePoints(10, new ushort[] { (ushort)Cmd.NoOp, (ushort)CmdState.Rdy });

                                ArcController?.NewLogMessage(LogCode.WFQYDBCmdCtart, $"u:{upFreq}, d:{dnFreq}, sr:{stokeRate}");
                                break;

                            case Cmd.Shutdown:
                                lastRequestTime = DateTime.Now;
                                //await WfqydbServer.PullShutdown().ConfigureAwait(false);
                                WfqydbServer.PullShutdown();
                                hRegisters.WritePoints(10, new ushort[] { (ushort)Cmd.NoOp, (ushort)CmdState.Rdy });

                                ArcController?.NewLogMessage(LogCode.WFQYDBCmdCtop);
                                break;

                            case Cmd.ThrowException:
                                throw new Exception("Test exception");

                            default:
                                hRegisters.WritePoints(10, new ushort[] { cmd, (ushort)CmdState.NotImplementedCmd });
                                faultRestTimer = faultRestTime;
                                break;
                            }
                        }
                        catch (Exception ex)
                        {
                            hRegisters.WritePoints(10, new ushort[] { cmd, (ushort)CmdState.CommonError });
                            faultRestTimer = faultRestTime;
                            FireOnError(ex);

                            Logger.Alarm(ex.Message);
                            ArcController?.NewLogMessage(LogCode.ModbusFailed);
                        }
                    }

                    if (cmdState != (ushort)CmdState.Rdy)
                    {
                        if ((faultRestTimer -= waitTime) <= 0)
                        {
                            hRegisters.WritePoints(10, new ushort[] { (ushort)Cmd.NoOp, (ushort)CmdState.Rdy });
                        }
                    }

                    await Task.Delay(waitTime, cancellationToken).ConfigureAwait(false);

                    // передернем сеть rtu. Так как она периодически подвисает.
                    //var lastResetTime = DateTime.Now;
                    //var resetInterval = TimeSpan.FromSeconds(30);
                    if ((lastResetTime + resetInterval) < DateTime.Now)
                    {
                        lastResetTime = DateTime.Now;
                        Logger.Info("restarting rtu");
                        //var rtuListener = new TcpListener(IPAddress.Any, RtuOverTcpPort);
                        rtuListener.Stop();
                        rtuListener.Start();
                        // var rtuNetwork = factory.CreateRtuOverTcpSlaveNetwork(rtuListener);
                        // var slaveRtu = factory.CreateSlave(1, slaveTcp.DataStore);
                        // rtuNetwork.AddSlave(slaveRtu);
                        // var rtuListenerTask = rtuNetwork.ListenAsync(cancellationToken);
                    }
                }
                catch (Exception ex)
                {
                    FireOnError(ex);

                    Logger.Alarm(ex.Message);

                    ArcController?.NewLogMessage(LogCode.ModbusFailed);

                    await Task.Delay(waitTime, cancellationToken).ConfigureAwait(false);
                }
            }// while

            tcpListener.Stop();
            rtuListener.Stop();

            tcpNetwork.Dispose();
            rtuNetwork.Dispose();

            await tcpListenerTask.ConfigureAwait(true);

            await rtuListenerTask.ConfigureAwait(true);
        }