示例#1
0
        static void Main(string[] args)
        {
            Log("{json:scada} IEC60870-5-101 Server Driver - Copyright 2020 RLO");
            Log("Driver version " + DriverVersion);
            Log("Using lib60870.NET version " +
                LibraryCommon.GetLibraryVersionString());

            if (
                args.Length > 0 // first argument in number of the driver instance
                )
            {
                int  num;
                bool res = int.TryParse(args[0], out num);
                if (res)
                {
                    ProtocolDriverInstanceNumber = num;
                }
            }
            if (
                args.Length > 1 // second argument is logLevel
                )
            {
                int  num;
                bool res = int.TryParse(args[1], out num);
                if (res)
                {
                    LogLevel = num;
                }
            }

            string fname = JsonConfigFilePath;

            if (args.Length > 2) // third argument is config file name
            {
                if (File.Exists(args[2]))
                {
                    fname = args[2];
                }
            }
            if (!File.Exists(fname))
            {
                fname = JsonConfigFilePathAlt;
            }
            if (!File.Exists(fname))
            {
                Log("Missing config file " + JsonConfigFilePath);
                Environment.Exit(-1);
            }

            Log("Reading config file " + fname);
            string json = File.ReadAllText(fname);

            JSConfig = JsonSerializer.Deserialize <JSONSCADAConfig>(json);
            if (
                JSConfig.mongoConnectionString == "" ||
                JSConfig.mongoConnectionString == null
                )
            {
                Log("Missing MongoDB connection string in JSON config file " +
                    fname);
                Environment.Exit(-1);
            }
            // Log("MongoDB connection string: " + JSConfig.mongoConnectionString);
            if (
                JSConfig.mongoDatabaseName == "" ||
                JSConfig.mongoDatabaseName == null
                )
            {
                Log("Missing MongoDB database name in JSON config file " +
                    fname);
                Environment.Exit(-1);
            }
            Log("MongoDB database name: " + JSConfig.mongoDatabaseName);
            if (JSConfig.nodeName == "" || JSConfig.nodeName == null)
            {
                Log("Missing nodeName parameter in JSON config file " +
                    fname);
                Environment.Exit(-1);
            }
            Log("Node name: " + JSConfig.nodeName);

            // connect to MongoDB Database server
            Client = ConnectMongoClient(JSConfig);
            var DB = Client.GetDatabase(JSConfig.mongoDatabaseName);

            // read and process instances configuration
            var collinsts =
                DB
                .GetCollection
                <protocolDriverInstancesClass
                >(ProtocolDriverInstancesCollectionName);
            var instances =
                collinsts
                .Find(inst =>
                      inst.protocolDriver == ProtocolDriverName &&
                      inst.protocolDriverInstanceNumber ==
                      ProtocolDriverInstanceNumber &&
                      inst.enabled == true)
                .ToList();
            var foundInstance = false;

            foreach (protocolDriverInstancesClass inst in instances)
            {
                if (
                    ProtocolDriverName == inst.protocolDriver &&
                    ProtocolDriverInstanceNumber ==
                    inst.protocolDriverInstanceNumber
                    )
                {
                    foundInstance = true;
                    if (!inst.enabled)
                    {
                        Log("Driver instance [" +
                            ProtocolDriverInstanceNumber.ToString() +
                            "] disabled!");
                        Environment.Exit(-1);
                    }
                    Log("Instance: " +
                        inst.protocolDriverInstanceNumber.ToString());
                    var nodefound = false;
                    foreach (var name in inst.nodeNames)
                    {
                        if (JSConfig.nodeName == name)
                        {
                            nodefound = true;
                        }
                    }
                    if (!nodefound)
                    {
                        Log("Node '" +
                            JSConfig.nodeName +
                            "' not found in instances configuration!");
                        Environment.Exit(-1);
                    }
                    DriverInstance = inst;
                    break;
                }
                break; // process just first result
            }
            if (!foundInstance)
            {
                Log("Driver instance [" +
                    ProtocolDriverInstanceNumber +
                    "] not found in configuration!");
                Environment.Exit(-1);
            }

            // read and process connections configuration for this driver instance
            var collconns =
                DB
                .GetCollection
                <IEC10X_connection>(ProtocolConnectionsCollectionName);
            var conns =
                collconns
                .Find(conn =>
                      conn.protocolDriver == ProtocolDriverName &&
                      conn.protocolDriverInstanceNumber ==
                      ProtocolDriverInstanceNumber &&
                      conn.enabled == true)
                .ToList();

            foreach (IEC10X_connection isrv in conns)
            {
                IEC10Xconns.Add(isrv);
                Log(isrv.name.ToString());
            }
            if (IEC10Xconns.Count == 0)
            {
                Log("No connections found!");
                Environment.Exit(-1);
            }

            // start thread to dequeue iec data and send to connections
            Thread thrDeqIecInfo =
                new Thread(() =>
                           DequeueIecInfo());

            thrDeqIecInfo.Start();

            // start thread to watch for commands in the database using a change stream
            Thread thrMongoCS =
                new Thread(() =>
                           ProcessMongoCS(JSConfig));

            thrMongoCS.Start();

            Log("Setting up IEC Connections & ASDU handlers...");
            int cntIecSrv = 0;

            foreach (IEC10X_connection srv in IEC10Xconns)
            {
                TcpClientVirtualSerialPort virtualPort = null;
                SerialPort port = null;
                if (srv.portName.Contains(":"))
                {
                    var hostport = srv.portName.Split(":");
                    virtualPort = new TcpClientVirtualSerialPort(hostport[0], System.Convert.ToInt32(hostport[1]));
                    if (LogLevel >= LogLevelDebug)
                    {
                        virtualPort.DebugOutput = true;
                    }
                    virtualPort.Start();
                }
                else
                {
                    port          = new SerialPort();
                    port.PortName = srv.portName;
                    port.BaudRate = srv.baudRate;
                    switch (srv.parity.ToLower())
                    {
                    default:     // Even is the starndard parity for 101
                    case "even":
                        port.Parity = Parity.Even;
                        break;

                    case "none":
                        port.Parity = Parity.None;
                        break;

                    case "odd":
                        port.Parity = Parity.Odd;
                        break;

                    case "mark":
                        port.Parity = Parity.Mark;
                        break;

                    case "space":
                        port.Parity = Parity.Space;
                        break;
                    }
                    switch (srv.stopBits.ToLower())
                    {
                    default:
                    case "one":
                        port.StopBits = StopBits.One;
                        break;

                    case "one5":
                    case "onepointfive":
                        port.StopBits = StopBits.OnePointFive;
                        break;

                    case "two":
                        port.StopBits = StopBits.Two;
                        break;
                    }
                    switch (srv.handshake.ToLower())
                    {
                    default:
                    case "none":
                        port.Handshake = Handshake.None;
                        break;

                    case "xon":
                    case "xonxoff":
                        port.Handshake = Handshake.XOnXOff;
                        break;

                    case "rts":
                    case "requesttosend":
                        port.Handshake = Handshake.RequestToSend;
                        break;

                    case "rtsxon":
                    case "requesttosendxonxoff":
                        port.Handshake = Handshake.RequestToSendXOnXOff;
                        break;
                    }
                    port.Open();
                    port.DiscardInBuffer();
                }

                LinkLayerParameters llParameters = new LinkLayerParameters();
                llParameters.AddressLength    = srv.sizeOfLinkAddress;
                llParameters.TimeoutForACK    = srv.timeoutForACK;
                llParameters.TimeoutRepeat    = srv.timeoutRepeat;
                llParameters.UseSingleCharACK = srv.useSingleCharACK;

                CS101Slave slave;
                if (port != null)
                {
                    slave = new CS101Slave(port, llParameters);
                }
                else
                {
                    slave = new CS101Slave(virtualPort, llParameters);
                }
                slave.Parameters.SizeOfCOT = srv.sizeOfCOT;
                slave.Parameters.SizeOfCA  = srv.sizeOfCA;
                slave.Parameters.SizeOfIOA = srv.sizeOfIOA;
                slave.Parameters.OA        = srv.localLinkAddress;
                if (LogLevel >= LogLevelDebug)
                {
                    slave.DebugOutput = true;
                }
                slave.LinkLayerAddress = srv.localLinkAddress;
                slave.LinkLayerMode    = lib60870.linklayer.LinkLayerMode.UNBALANCED;
                slave.SetInterrogationHandler(InterrogationHandler, cntIecSrv);
                slave.SetUserDataQueueSizes(srv.maxQueueSize, srv.maxQueueSize);
                srv.server = slave;
                slave.SetASDUHandler(AsduReceivedHandler, cntIecSrv);
                // slave.Start();

                Log(srv.name + " - New server listening on " + srv.portName);
                cntIecSrv++;
            }
            Thread.Sleep(1000);
            bool running = true;

            Console.CancelKeyPress +=
                delegate(object sender, ConsoleCancelEventArgs e)
            {
                e.Cancel = true;
                running  = false;
            };
            Log("Press [CTRL]+[C] to terminate...");

            int cnt = 1;

            do
            {
                try
                {
                    foreach (IEC10X_connection srv in IEC10Xconns)
                    {
                        srv.server.Run();
                    }

                    if (Client == null)
                    {
                        // retry connection
                        IsMongoLive = false;
                        Client      = new MongoClient(JSConfig.mongoConnectionString);
                        DB          = Client.GetDatabase(JSConfig.mongoDatabaseName);
                        IsMongoLive = true;
                    }

                    if ((cnt % 20) == 0) // each 1 second test mongo connection
                    {
                        IsMongoLive =
                            DB
                            .RunCommandAsync((Command <BsonDocument>)
                                             "{ping:1}")
                            .Wait(1000);
                        if (!IsMongoLive)
                        {
                            throw new Exception("Error on MongoDB connection ");
                        }
                    }
                }
                catch (Exception e)
                { // Disconnects to retry after some time
                    IsMongoLive = false;
                    Client      = null;
                    Log("Exception");
                    Log(e);
                    Log(e
                        .ToString()
                        .Substring(0,
                                   e.ToString().IndexOf(Environment.NewLine)));
                    System.Threading.Thread.Sleep(100);
                }

                Thread.Sleep(50);
                cnt++;
            }while (running);
            Log("Exiting application!");
            Environment.Exit(0);
        }
示例#2
0
        public static void Main(string[] args)
        {
            bool running = true;

            // use Ctrl-C to stop the programm
            Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) {
                e.Cancel = true;
                running  = false;
            };

            string portName = "/dev/ttyUSB3";

            if (args.Length > 0)
            {
                portName = args [0];
            }

            SerialPort port = new SerialPort();

            port.PortName  = portName;
            port.BaudRate  = 9600;
            port.Parity    = Parity.Even;
            port.Handshake = Handshake.None;
            port.Open();

            LinkLayerParameters llParameters = new LinkLayerParameters();

            llParameters.AddressLength    = 1;
            llParameters.UseSingleCharACK = true;

            CS101Slave slave = new CS101Slave(port, llParameters);

            slave.DebugOutput      = true;
            slave.LinkLayerAddress = 1;

            // for using the slave in balanced mode simple change the mode here:
            slave.LinkLayerMode = lib60870.linklayer.LinkLayerMode.UNBALANCED;

            slave.SetInterrogationHandler(myInterrogationHandler, null);

            slave.SetUserDataQueueSizes(50, 20);

            ASDU asdu = new ASDU(slave.Parameters, CauseOfTransmission.SPONTANEOUS, false, false, 0, 1, false);

            asdu.AddInformationObject(new StepPositionInformation(301, 1, false, new QualityDescriptor()));
            slave.EnqueueUserDataClass1(asdu);

            long  lastTimestamp = SystemUtils.currentTimeMillis();
            Int16 measuredValue = 0;

            TransparentFile file = new TransparentFile(1, 30000, NameOfFile.TRANSPARENT_FILE);

            byte[] fileData = new byte[1025];

            for (int i = 0; i < 1025; i++)
            {
                fileData [i] = (byte)(i + 1);
            }

            file.AddSection(fileData);

            slave.GetAvailableFiles().AddFile(file);

            while (running)
            {
                slave.Run();                  // call the protocol stack

                if ((SystemUtils.currentTimeMillis() - lastTimestamp) >= 5000)
                {
                    lastTimestamp = SystemUtils.currentTimeMillis();

                    ASDU newAsdu = new ASDU(slave.Parameters, CauseOfTransmission.PERIODIC, false, false, 0, 1, false);
                    newAsdu.AddInformationObject(new MeasuredValueScaled(110, measuredValue, new QualityDescriptor()));
                    slave.EnqueueUserDataClass2(newAsdu);

                    measuredValue++;
                }

                if (Console.KeyAvailable)
                {
                    ConsoleKeyInfo keyInfo = Console.ReadKey();

                    if (keyInfo.KeyChar == 't')
                    {
                        slave.SendLinkLayerTestFunction();
                    }
                    else
                    {
                        Console.WriteLine("Send spontaneous message");

                        bool value = false;

                        if (keyInfo.KeyChar == 's')
                        {
                            value = true;
                        }

                        ASDU newAsdu = new ASDU(slave.Parameters, CauseOfTransmission.SPONTANEOUS, false, false, 0, 1, false);
                        newAsdu.AddInformationObject(new SinglePointInformation(100, value, new QualityDescriptor()));

                        slave.EnqueueUserDataClass1(newAsdu);
                    }
                }
            }
        }
示例#3
0
        public static void Main(string[] args)
        {
            bool running = true;

            // use Ctrl-C to stop the programm
            Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) {
                e.Cancel = true;
                running  = false;
            };

            LinkLayerParameters llParameters = new LinkLayerParameters();

            llParameters.AddressLength    = 1;
            llParameters.TimeoutForACK    = 500;
            llParameters.UseSingleCharACK = true;

            TcpServerVirtualSerialPort port = new TcpServerVirtualSerialPort();

            //TcpClientVirtualSerialPort port = new TcpClientVirtualSerialPort("192.168.2.9", 2404);

            port.DebugOutput = true;
            port.Start();

            CS101Slave slave = new CS101Slave(port, llParameters);

            slave.DebugOutput                  = true;
            slave.LinkLayerAddress             = 3;
            slave.LinkLayerAddressOtherStation = 1;

            slave.LinkLayerMode = lib60870.linklayer.LinkLayerMode.BALANCED;

            slave.SetInterrogationHandler(myInterrogationHandler, null);

            slave.SetUserDataQueueSizes(50, 20);

            ASDU asdu = new ASDU(slave.Parameters, CauseOfTransmission.SPONTANEOUS, false, false, 0, 1, false);

            asdu.AddInformationObject(new StepPositionInformation(301, 1, false, new QualityDescriptor()));
            slave.EnqueueUserDataClass1(asdu);

            long  lastTimestamp = SystemUtils.currentTimeMillis();
            Int16 measuredValue = 0;

            TransparentFile file = new TransparentFile(1, 30000, NameOfFile.TRANSPARENT_FILE);

            byte[] fileData = new byte[1025];

            for (int i = 0; i < 1025; i++)
            {
                fileData [i] = (byte)(i + 1);
            }

            file.AddSection(fileData);

            slave.GetAvailableFiles().AddFile(file);

            while (running)
            {
                slave.Run();                  // call the protocol stack

                if ((SystemUtils.currentTimeMillis() - lastTimestamp) >= 5000)
                {
                    lastTimestamp = SystemUtils.currentTimeMillis();

                    ASDU newAsdu = new ASDU(slave.Parameters, CauseOfTransmission.PERIODIC, false, false, 0, 1, false);
                    newAsdu.AddInformationObject(new MeasuredValueScaled(110, measuredValue, new QualityDescriptor()));
                    slave.EnqueueUserDataClass2(newAsdu);

                    measuredValue++;
                }

                if (Console.KeyAvailable)
                {
                    ConsoleKeyInfo keyInfo = Console.ReadKey();

                    if (keyInfo.KeyChar == 't')
                    {
                        slave.SendLinkLayerTestFunction();
                    }
                    else
                    {
                        Console.WriteLine("Send spontaneous message");

                        bool value = false;

                        if (keyInfo.KeyChar == 's')
                        {
                            value = true;
                        }

                        ASDU newAsdu = new ASDU(slave.Parameters, CauseOfTransmission.SPONTANEOUS, false, false, 0, 1, false);
                        newAsdu.AddInformationObject(new SinglePointInformation(100, value, new QualityDescriptor()));

                        slave.EnqueueUserDataClass1(newAsdu);
                    }
                }

                Thread.Sleep(1);
            }

            port.Stop();
        }