示例#1
0
 /// <summary>
 /// Primary constructor
 /// </summary>
 /// <param name="opType">Enumeration that controls the behavior of the command</param>
 /// <param name="tcc">Enumeration that controls the behavior of the command</param>
 /// <param name="clear">Boolean that controls the behavior of the command</param>
 /// <param name="count">How many times to repeat the operation</param>
 /// <param name="onTime">How long to set the output active></param>
 /// <param name="offTime">How long to set the output inactive></param>
 public ControlRelayOutputBlock(OperationType opType, TripCloseCode tcc, bool clear, byte count, System.UInt32 onTime, System.UInt32 offTime)
 {
     this.opType  = opType;
     this.tcc     = tcc;
     this.clear   = clear;
     this.count   = count;
     this.onTime  = onTime;
     this.offTime = offTime;
 }
示例#2
0
        // This process watches (via change stream) for commands inserted to a commands collection
        // When the command is considered valid it is forwarded to the RTU
        static async void ProcessMongoCmd(JSONSCADAConfig jsConfig)
        {
            do
            {
                try
                {
                    var Client     = ConnectMongoClient(jsConfig);
                    var DB         = Client.GetDatabase(jsConfig.mongoDatabaseName);
                    var collection =
                        DB
                        .GetCollection
                        <rtCommand>(CommandsQueueCollectionName);

                    bool isMongoLive =
                        DB
                        .RunCommandAsync((Command <BsonDocument>) "{ping:1}")
                        .Wait(1000);
                    if (!isMongoLive)
                    {
                        throw new Exception("Error on connection " + jsConfig.mongoConnectionString);
                    }

                    Log("MongoDB CMD CS - Start listening for commands via changestream...");
                    var filter = "{ operationType: 'insert' }";

                    var pipeline =
                        new EmptyPipelineDefinition <ChangeStreamDocument <rtCommand
                                                                           >
                                                     >().Match(filter);
                    using (var cursor = await collection.WatchAsync(pipeline))
                    {
                        await cursor
                        .ForEachAsync(async change =>
                        {
                            if (!Active)
                            {
                                return;
                            }

                            // process change event, only process inserts
                            if (
                                change.OperationType ==
                                ChangeStreamOperationType.Insert
                                )
                            {
                                // consider only commands for this driver
                                {
                                    Log("MongoDB CMD CS - Looking for connection " +
                                        change
                                        .FullDocument
                                        .protocolSourceConnectionNumber +
                                        "...");
                                    var found = false;
                                    foreach (DNP3_connection
                                             srv
                                             in
                                             DNP3conns
                                             )
                                    {
                                        if (
                                            srv.protocolConnectionNumber ==
                                            change
                                            .FullDocument
                                            .protocolSourceConnectionNumber
                                            )
                                        {
                                            found  = true;
                                            var cs = srv.channel.GetChannelStatistics();
                                            if (
                                                srv.isConnected &&
                                                srv.commandsEnabled
                                                )
                                            {
                                                var group     = change.FullDocument.protocolSourceCommonAddress;
                                                var variation = change.FullDocument.protocolSourceASDU;
                                                if (group == 41 || group == 12)
                                                {
                                                    if (         // check for command expired
                                                        DateTime
                                                        .Now
                                                        .ToLocalTime()
                                                        .Subtract(change
                                                                  .FullDocument
                                                                  .timeTag
                                                                  .ToLocalTime(
                                                                      ))
                                                        .Seconds <
                                                        10
                                                        )
                                                    {         // can execute
                                                        System.Threading.Tasks.Task <CommandTaskResult> cmdTask = null;

                                                        if (group == 12)
                                                        {
                                                            OperationType ot = OperationType.NUL;

                                                            TripCloseCode tc = TripCloseCode.NUL;
                                                            switch (System.Convert.ToUInt16(change.FullDocument.protocolSourceCommandDuration))
                                                            {
                                                            default:
                                                            case 0:
                                                                ot = OperationType.NUL;
                                                                break;

                                                            case 1:
                                                                if (change.FullDocument.value != 0)
                                                                {
                                                                    ot = OperationType.PULSE_ON;
                                                                }
                                                                else
                                                                {
                                                                    ot = OperationType.PULSE_OFF;
                                                                }
                                                                break;

                                                            case 2:
                                                                if (change.FullDocument.value != 0)
                                                                {
                                                                    ot = OperationType.PULSE_OFF;
                                                                }
                                                                else
                                                                {
                                                                    ot = OperationType.PULSE_ON;
                                                                }
                                                                break;

                                                            case 3:
                                                                if (change.FullDocument.value != 0)
                                                                {
                                                                    ot = OperationType.LATCH_ON;
                                                                }
                                                                else
                                                                {
                                                                    ot = OperationType.LATCH_OFF;
                                                                }
                                                                break;

                                                            case 4:
                                                                if (change.FullDocument.value != 0)
                                                                {
                                                                    ot = OperationType.LATCH_OFF;
                                                                }
                                                                else
                                                                {
                                                                    ot = OperationType.LATCH_ON;
                                                                }
                                                                break;

                                                            case 11:
                                                                if (change.FullDocument.value != 0)
                                                                {
                                                                    ot = OperationType.PULSE_ON;
                                                                    tc = TripCloseCode.CLOSE;
                                                                }
                                                                else
                                                                {
                                                                    ot = OperationType.PULSE_OFF;
                                                                    tc = TripCloseCode.TRIP;
                                                                }
                                                                break;

                                                            case 13:
                                                                if (change.FullDocument.value != 0)
                                                                {
                                                                    ot = OperationType.LATCH_ON;
                                                                    tc = TripCloseCode.CLOSE;
                                                                }
                                                                else
                                                                {
                                                                    ot = OperationType.LATCH_OFF;
                                                                    tc = TripCloseCode.TRIP;
                                                                }
                                                                break;

                                                            case 21:
                                                                if (change.FullDocument.value != 0)
                                                                {
                                                                    ot = OperationType.PULSE_ON;
                                                                    tc = TripCloseCode.TRIP;
                                                                }
                                                                else
                                                                {
                                                                    ot = OperationType.PULSE_OFF;
                                                                    tc = TripCloseCode.CLOSE;
                                                                }
                                                                break;

                                                            case 23:
                                                                if (change.FullDocument.value != 0)
                                                                {
                                                                    ot = OperationType.LATCH_ON;
                                                                    tc = TripCloseCode.TRIP;
                                                                }
                                                                else
                                                                {
                                                                    ot = OperationType.LATCH_OFF;
                                                                    tc = TripCloseCode.CLOSE;
                                                                }
                                                                break;
                                                            }
                                                            ControlRelayOutputBlock crob = new ControlRelayOutputBlock(ot, tc, false, 1, 0, 0);
                                                            if (System.Convert.ToBoolean(change.FullDocument.protocolSourceCommandUseSBO))
                                                            {
                                                                cmdTask = srv.master.SelectAndOperate(
                                                                    crob,
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                            else
                                                            {
                                                                cmdTask = srv.master.DirectOperate(
                                                                    crob,
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                        }
                                                        else if (group == 41 && variation == 1)
                                                        {
                                                            if (System.Convert.ToBoolean(change.FullDocument.protocolSourceCommandUseSBO))
                                                            {
                                                                cmdTask = srv.master.SelectAndOperate(
                                                                    new AnalogOutputInt32(System.Convert.ToInt32(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                            else
                                                            {
                                                                cmdTask = srv.master.DirectOperate(
                                                                    new AnalogOutputInt32(System.Convert.ToInt32(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                        }
                                                        else if (group == 41 && variation == 2)
                                                        {
                                                            if (System.Convert.ToBoolean(change.FullDocument.protocolSourceCommandUseSBO))
                                                            {
                                                                cmdTask = srv.master.SelectAndOperate(
                                                                    new AnalogOutputInt16(System.Convert.ToInt16(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                            else
                                                            {
                                                                cmdTask = srv.master.DirectOperate(
                                                                    new AnalogOutputInt16(System.Convert.ToInt16(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                        }
                                                        else if (group == 41 && variation == 3)
                                                        {
                                                            if (System.Convert.ToBoolean(change.FullDocument.protocolSourceCommandUseSBO))
                                                            {
                                                                cmdTask = srv.master.SelectAndOperate(
                                                                    new AnalogOutputFloat32(System.Convert.ToSingle(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                            else
                                                            {
                                                                cmdTask = srv.master.DirectOperate(
                                                                    new AnalogOutputFloat32(System.Convert.ToSingle(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                        }
                                                        else if (group == 41 && variation == 4)
                                                        {
                                                            if (System.Convert.ToBoolean(change.FullDocument.protocolSourceCommandUseSBO))
                                                            {
                                                                cmdTask = srv.master.SelectAndOperate(
                                                                    new AnalogOutputDouble64(System.Convert.ToDouble(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                            else
                                                            {
                                                                cmdTask = srv.master.DirectOperate(
                                                                    new AnalogOutputDouble64(System.Convert.ToDouble(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                        }
                                                        else if (group == 41)     // group 41, other variations defaults to float32
                                                        {
                                                            if (System.Convert.ToBoolean(change.FullDocument.protocolSourceCommandUseSBO))
                                                            {
                                                                cmdTask = srv.master.SelectAndOperate(
                                                                    new AnalogOutputFloat32(System.Convert.ToSingle(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                            else
                                                            {
                                                                cmdTask = srv.master.DirectOperate(
                                                                    new AnalogOutputFloat32(System.Convert.ToSingle(change.FullDocument.value)),
                                                                    System.Convert.ToUInt16(change.FullDocument.protocolSourceObjectAddress),
                                                                    TaskConfig.Default);
                                                            }
                                                        }

                                                        if (cmdTask != null)
                                                        {
                                                            _ = cmdTask.ContinueWith((result) =>
                                                            {
                                                                Console.WriteLine("Result: " + result.Result);
                                                                Log("MongoDB CMD CS - " +
                                                                    srv.name +
                                                                    " - Command " +
                                                                    " TAG:" + change.FullDocument.tag +
                                                                    " GRP:" + change.FullDocument.protocolSourceCommonAddress +
                                                                    " VAR:" + change.FullDocument.protocolSourceASDU +
                                                                    " OBJ:" + change.FullDocument.protocolSourceObjectAddress +
                                                                    " Value:" + change.FullDocument.value +
                                                                    " Delivered");

                                                                // update as delivered
                                                                var filter =
                                                                    new BsonDocument(new BsonDocument("_id",
                                                                                                      change.FullDocument.id));
                                                                var update =
                                                                    new BsonDocument("$set", new BsonDocument {
                                                                    { "delivered", true },
                                                                    { "ack",
                                                                      result.Result.Results.FirstOrDefault().PointState == CommandPointState.SUCCESS &&
                                                                      result.Result.Results.FirstOrDefault().Status == CommandStatus.SUCCESS },
                                                                    { "ackTimeTag", BsonValue.Create(DateTime.Now) },
                                                                    { "resultDescription", result.Result.ToString() }
                                                                });
                                                                var res =
                                                                    collection
                                                                    .UpdateOneAsync(filter,
                                                                                    update);
                                                            });
                                                        }
                                                        else
                                                        {
                                                            Console.WriteLine("Command Error");
                                                        }
                                                    }
                                                    else
                                                    {
                                                        // update as expired
                                                        Log("MongoDB CMD CS - " +
                                                            srv.name +
                                                            " - Command " +
                                                            " TAG:" + change.FullDocument.tag +
                                                            " GRP:" + change.FullDocument.protocolSourceCommonAddress +
                                                            " VAR:" + change.FullDocument.protocolSourceASDU +
                                                            " OBJ:" + change.FullDocument.protocolSourceObjectAddress +
                                                            " Value:" + change.FullDocument.value +
                                                            " Expired");
                                                        var filter =
                                                            new BsonDocument(new BsonDocument("_id",
                                                                                              change
                                                                                              .FullDocument
                                                                                              .id));
                                                        var update =
                                                            new BsonDocument("$set",
                                                                             new BsonDocument("cancelReason",
                                                                                              "expired"));
                                                        var result =
                                                            await collection
                                                            .UpdateOneAsync(filter,
                                                                            update);
                                                    }
                                                }
                                                else
                                                {
                                                    // update as canceled (asdu not implemented)
                                                    Log("MongoDB CMD CS - " +
                                                        srv.name +
                                                        " - Command " +
                                                        " TAG:" + change.FullDocument.tag +
                                                        " GRP:" + change.FullDocument.protocolSourceCommonAddress +
                                                        " VAR:" + change.FullDocument.protocolSourceASDU +
                                                        " OBJ:" + change.FullDocument.protocolSourceObjectAddress +
                                                        " Value:" + change.FullDocument.value +
                                                        " ASDU Not Implemented");
                                                    var filter =
                                                        new BsonDocument(new BsonDocument("_id",
                                                                                          change
                                                                                          .FullDocument
                                                                                          .id));
                                                    var update =
                                                        new BsonDocument("$set",
                                                                         new BsonDocument("cancelReason",
                                                                                          "asdu not implemented"));
                                                    var result =
                                                        await collection
                                                        .UpdateOneAsync(filter,
                                                                        update);
                                                }
                                            }
                                            else
                                            {
                                                // update as canceled (not connected)
                                                Log("MongoDB CMD CS - " +
                                                    srv.name +
                                                    " - Command " +
                                                    " TAG:" + change.FullDocument.tag +
                                                    " GRP:" + change.FullDocument.protocolSourceCommonAddress +
                                                    " VAR:" + change.FullDocument.protocolSourceASDU +
                                                    " OBJ:" + change.FullDocument.protocolSourceObjectAddress +
                                                    " Value:" + change.FullDocument.value +
                                                    change.FullDocument.value +
                                                    (
                                                        srv.commandsEnabled
                                                            ? " Not Connected"
                                                            : " Commands Disabled"
                                                    ));
                                                var filter =
                                                    new BsonDocument(new BsonDocument("_id",
                                                                                      change
                                                                                      .FullDocument
                                                                                      .id));
                                                var update =
                                                    new BsonDocument("$set",
                                                                     new BsonDocument("cancelReason",
                                                                                      (
                                                                                          srv
                                                                                          .commandsEnabled
                                                                        ? "not connected"
                                                                        : "commands disabled"
                                                                                      )));
                                                var result =
                                                    await collection
                                                    .UpdateOneAsync(filter,
                                                                    update);
                                            }
                                            break;
                                        }
                                    }
                                    if (!found)
                                    {
                                        // update as canceled command (not found)
                                        Log("MongoDB CMD CS - " +
                                            change
                                            .FullDocument
                                            .protocolSourceConnectionNumber
                                            .ToString() +
                                            " - Command " +
                                            " TAG:" + change.FullDocument.tag +
                                            " GRP:" + change.FullDocument.protocolSourceCommonAddress +
                                            " VAR:" + change.FullDocument.protocolSourceASDU +
                                            " OBJ:" + change.FullDocument.protocolSourceObjectAddress +
                                            " Value:" + change.FullDocument.value +
                                            " Not Found");
                                        var filter =
                                            new BsonDocument(new BsonDocument("_id",
                                                                              change
                                                                              .FullDocument
                                                                              .id));
                                        var update =
                                            new BsonDocument("$set",
                                                             new BsonDocument("cancelReason",
                                                                              "connection not found"));
                                        var result =
                                            await collection
                                            .UpdateOneAsync(filter,
                                                            update);
                                    }
                                }
                            }
                        });
                    }
                }
                catch (Exception e)
                {
                    Log("Exception MongoCmd");
                    Log(e);
                    Log(e
                        .ToString()
                        .Substring(0,
                                   e.ToString().IndexOf(Environment.NewLine)));
                    System.Threading.Thread.Sleep(3000);
                }
            }while (true);
        }