Example #1
0
      public virtual void Reset()
      {
         this.receiveBootupHeartbeart = false;
         this.faultReason = null;
         this.actionQueue.Clear();
         this.commState = CommStates.idle;

         this.consumerHeartbeatActive = false;
         this.consumerHeartbeatSetting = 0;

         NetworkRequest networkRequest = new NetworkRequest(0x81, this.NodeId);
         this.ScheduleAction(networkRequest);
      }
Example #2
0
      public virtual void Update()
      {
         CommStates processedState;

         do 
         {
            processedState = this.commState;

            switch (this.commState)
            {
               case CommStates.idle:
               {
                  lock (this)
                  {
                     if (this.actionQueue.Count != 0)
                     {
                        this.action = (CommAction)this.actionQueue.Dequeue();
                     }
                  }

                  if (null != this.action)
                  {
                     this.commAttemptCount = 0;
                     this.commState = CommStates.tx;
                     //Tracer.WriteHigh(TraceGroup.CANBUS, "", "action start");
                  }

                  break;
               }
               case CommStates.tx:
               {
                  this.commAttemptCount++;

                  if (this.commAttemptCount <= this.action.RetryAttemptLimit)
                  {
                     int cobId = 0;
                     byte[] frameData = this.action.GetTransmitFrame(ref cobId, this.NodeId);

                     if (null != frameData)
                     {
                        bool txResult = this.Transmit(cobId, frameData);

                        if (false != txResult)
                        {
                           this.action.TransmitComplete();

                           bool responseNeeded = this.action.ResponseNeeded();

                           if (false != responseNeeded)
                           {
                              //Tracer.WriteHigh(TraceGroup.CANBUS, "", "tx pending");
                              this.commTimeLimit = DateTime.Now.AddMilliseconds(this.action.RetryTime);
                              this.commState = CommStates.rxWait;
                           }
                           else
                           {
                              this.EvaluateAction(this.action);
                              this.action = null;
                              this.commState = CommStates.idle;
                           }
                        }
                        else
                        {
                           Tracer.WriteHigh(TraceGroup.CANBUS, "", "tx fail");
                           this.commTimeLimit = DateTime.Now.AddMilliseconds(this.TransmitFailureHoldoffTime);
                           this.commState = CommStates.txWait;
                        }
                     }
                     else
                     {
                        this.action = null;
                        this.commState = CommStates.idle;
                     }
                  }
                  else
                  {
                     this.Fault("comm failure");
                     this.action = null;
                  }

                  break;
               }
               case CommStates.txWait:
               {
                  if (DateTime.Now > this.commTimeLimit)
                  {
                     this.commState = CommStates.tx;
                  }

                  break;
               }
               case CommStates.rxWait:
               {
                  if (false != this.action.Done)
                  {
                     this.EvaluateAction(this.action);

                     if (false != this.action.Aborted)
                     {
                        this.Fault("comm abort");
                     }

                     this.action = null;
                     this.commState = CommStates.idle;
                  }
                  else if (false != this.action.Transmit)
                  {
                     this.commAttemptCount = 0;
                     this.commState = CommStates.tx;
                  }
                  else if (DateTime.Now > this.commTimeLimit)
                  {
                     this.commState = CommStates.tx;
                     Tracer.WriteHigh(TraceGroup.CANBUS, "", "response timeout");
                  }

                  break;
               }
               case CommStates.error:
               {
                  break;
               }                
            }

         }
         while (processedState != this.commState);

         if (null == this.FaultReason)
         {
            if ((false != this.consumerHeartbeatActive) &&
                (DateTime.Now > this.consumerHeartbeatTimeLimit))
            {
               this.Fault("heartbeat missing");
            }
         }

         #region Download Process

         if (false != this.downloadActive)
         {
            string downloadResult = null;
            bool downloadComplete = false;
            
            if (null != this.FaultReason)
            {
               downloadComplete = true;
               downloadResult = "Device faulted: " + this.FaultReason;
            }
            else if (false != this.downloadCancel)
            {
               downloadComplete = true;
               downloadResult = "Cancelled";
            }
            else if (DownloadSteps.start == this.downloadStep)
            {
               if (File.Exists(this.downloadFile) != false)
               {
                  FileStream fs = File.Open(this.downloadFile, FileMode.Open);
                  BinaryReader br = new BinaryReader(fs);

                  this.downloadImagePosition = 0;
                  this.downloadImageSize = (UInt32)fs.Length;
                  this.downloadData = br.ReadBytes((int)this.downloadImageSize);

                  br.Close();
                  br.Dispose();

                  fs.Close();
                  fs.Dispose();

                  this.receiveBootupHeartbeart = false;
                  this.downloadAction = new NetworkRequest(0x80, this.NodeId);
                  bool result = this.ScheduleAction(this.downloadAction);

                  if (false != result)
                  {
                     this.downloadTimeLimit = DateTime.Now.AddMilliseconds(700);
                     this.downloadStep = DownloadSteps.waitReset;
                  }
                  else
                  {
                     downloadResult = "Unable to schedule reset.";
                     downloadComplete = true;
                  }
               }
               else
               {
                  downloadResult = "Unable to open file.";
                  downloadComplete = true;
               }
            }
            else if (DownloadSteps.waitReset == this.downloadStep)
            {
               if ((null == this.downloadAction) && (false != this.receiveBootupHeartbeart))
               {
                  this.downloadTimeLimit = DateTime.Now.AddMilliseconds(500);
                  this.downloadStep = DownloadSteps.waitBootStart;
               }
               else if (DateTime.Now > this.downloadTimeLimit)
               {
                  this.downloadTimeLimit = DateTime.Now.AddMilliseconds(500);
                  this.downloadStep = DownloadSteps.waitBootStart;
               }
            }
            else if (DownloadSteps.waitBootStart == this.downloadStep)
            {
               if (DateTime.Now > this.downloadTimeLimit)
               {
                  this.downloadAction = new SDODownload(0x1F50, 1, this.downloadData, 0, this.downloadData.Length);
                  bool result = this.ScheduleAction(this.downloadAction, 5000, 1);

                  if (false != result)
                  {
                     this.downloadStep = DownloadSteps.waitFirmwareDownload;
                  }
                  else
                  {
                     downloadResult = "Unable to schedule download.";
                     downloadComplete = true;
                  }
               }
            }
            else if (DownloadSteps.waitFirmwareDownload == this.downloadStep)
            {
               if (null != this.downloadAction)
               {
                  this.downloadImagePosition = ((SDODownload)this.downloadAction).SentCount;
               }
               else 
               {
                  this.downloadImagePosition = this.downloadImageSize;
                  this.downloadAction = new SDODownload(0x1F51, 1, 1, 1);
                  bool result = this.ScheduleAction(this.downloadAction);

                  if (false != result)
                  {
                     this.downloadTimeLimit = DateTime.Now.AddSeconds(2);
                     this.downloadStep = DownloadSteps.waitStartRequest;
                  }
                  else
                  {
                     downloadResult = "Unable to schedule start.";
                     downloadComplete = true;
                  }
               }
            }
            else if (DownloadSteps.waitStartRequest == this.downloadStep)
            {
               if (null == this.downloadAction)
               {
                  downloadResult = null;
                  downloadComplete = true;
               }
            }
            else
            {
               downloadResult = "Unknown step.";
               downloadComplete = true;
            }

            if (false != downloadComplete)
            {
               this.downloadData = null;
               this.downloadActive = false;
               this.downloadCompleteHandler(downloadResult);
            }
         }
         #endregion
      }
Example #3
0
      public virtual void Initialize()
      {
         this.faultReason = null;

         this.receiveBootupHeartbeart = false;
         this.consumerHeartbeatActive = false;
         this.consumerHeartbeatSetting = 0;

         this.actionQueue.Clear();
         this.commState = CommStates.idle;

         this.TransmitFailureHoldoffTime = 50;
      }
Example #4
0
        /// <summary>
        /// Отправить команду ТУ SCADA-Серверу
        /// </summary>
        protected bool SendCommand(int userID, int ctrlCnl, double cmdVal, byte[] cmdData, int kpNum, out bool result)
        {
            Monitor.Enter(tcpLock);
            bool complete = false;
            result = false;
            errMsg = "";

            try
            {
                if (RestoreConnection())
                {
                    WriteAction(Localization.UseRussian ? "Отправка команды ТУ SCADA-Серверу" :
                        "Send telecommand to SCADA-Server", Log.ActTypes.Action);

                    commState = CommStates.WaitResponse;
                    tcpClient.ReceiveTimeout = commSettings.ServerTimeout;

                    // отправка команды
                    int cmdLen = double.IsNaN(cmdVal) ? cmdData == null ? 12 : 10 + cmdData.Length : 18;
                    byte[] buf = new byte[cmdLen];
                    buf[0] = (byte)(cmdLen % 256);
                    buf[1] = (byte)(cmdLen / 256);
                    buf[2] = 0x06;
                    buf[3] = (byte)(userID % 256);
                    buf[4] = (byte)(userID / 256);
                    buf[6] = (byte)(ctrlCnl % 256);
                    buf[7] = (byte)(ctrlCnl / 256);

                    if (!double.IsNaN(cmdVal)) // стандартная команда
                    {
                        buf[5] = 0x00;
                        buf[8] = 0x08;
                        buf[9] = 0x00;
                        byte[] bytes = BitConverter.GetBytes(cmdVal);
                        Array.Copy(bytes, 0, buf, 10, 8);
                    }
                    else if (cmdData != null) // бинарная команда
                    {
                        buf[5] = 0x01;
                        int cmdDataLen = cmdData.Length;
                        buf[8] = (byte)(cmdDataLen % 256);
                        buf[9] = (byte)(cmdDataLen / 256);
                        Array.Copy(cmdData, 0, buf, 10, cmdDataLen);
                    }
                    else // опрос КП
                    {
                        buf[5] = 0x02;
                        buf[8] = 0x02;
                        buf[9] = 0x00;
                        buf[10] = (byte)(kpNum % 256);
                        buf[11] = (byte)(kpNum / 256);
                    }

                    netStream.Write(buf, 0, cmdLen);

                    // приём результата
                    buf = new byte[4];
                    int bytesRead = netStream.Read(buf, 0, 4);

                    // обработка полученных данных
                    if (bytesRead == buf.Length && CheckDataFormat(buf, 0x06))
                    {
                        result = buf[3] > 0;
                        commState = result ? CommStates.Authorized : CommStates.NotReady;
                        complete = true;
                    }
                    else
                    {
                        errMsg = Localization.UseRussian ? "Неверный формат ответа SCADA-Сервера на команду ТУ" :
                            "Incorrect SCADA-Server response to telecommand";
                        WriteAction(errMsg, Log.ActTypes.Error);
                        commState = CommStates.Error;
                    }
                }
            }
            catch (Exception ex)
            {
                errMsg = (Localization.UseRussian ? "Ошибка при отправке команды ТУ SCADA-Серверу: " :
                    "Error sending telecommand to SCADA-Server: ") + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
                Disconnect();
            }
            finally
            {
                RestoreReceiveTimeout();
                Monitor.Exit(tcpLock);
            }

            return complete;
        }
Example #5
0
        /// <summary>
        /// Запросить правильность имени и пароля пользователя от SCADA-Сервера, получить его роль.
        /// Возвращает успешность выполнения запроса
        /// </summary>
        public bool CheckUser(string login, string password, out int roleID)
        {
            Monitor.Enter(tcpLock);
            bool result = false;
            roleID = (int)Roles.Disabled;
            errMsg = "";

            try
            {
                if (RestoreConnection())
                {
                    commState = CommStates.WaitResponse;
                    tcpClient.ReceiveTimeout = commSettings.ServerTimeout;

                    // запрос правильности имени и пароля пользователя, его роли
                    byte userLen = login == null ? (byte)0 : (byte)login.Length;
                    byte pwdLen = password == null ? (byte)0 : (byte)password.Length;
                    byte[] buf = new byte[5 + userLen + pwdLen];

                    buf[0] = (byte)(buf.Length % 256);
                    buf[1] = (byte)(buf.Length / 256);
                    buf[2] = 0x01;
                    buf[3] = userLen;
                    if (userLen > 0)
                        Array.Copy(Encoding.Default.GetBytes(login), 0, buf, 4, userLen);
                    buf[4 + userLen] = pwdLen;
                    if (pwdLen > 0)
                        Array.Copy(Encoding.Default.GetBytes(password), 0, buf, 5 + userLen, pwdLen);

                    netStream.Write(buf, 0, buf.Length);

                    // приём результата
                    buf = new byte[4];
                    int bytesRead = netStream.Read(buf, 0, 4);

                    // обработка полученных данных
                    if (bytesRead == buf.Length && CheckDataFormat(buf, 0x01))
                    {
                        roleID = buf[3];
                        result = true;
                        commState = CommStates.Authorized;
                    }
                    else
                    {
                        errMsg = Localization.UseRussian ? 
                            "Неверный формат ответа SCADA-Сервера на запрос правильности имени и пароля" :
                            "Incorrect SCADA-Server response to check user name and password request";
                        WriteAction(errMsg, Log.ActTypes.Error);
                        commState = CommStates.Error;
                    }
                }
            }
            catch (Exception ex)
            {
                errMsg = (Localization.UseRussian ? 
                    "Ошибка при запросе правильности имени и пароля пользователя от SCADA-Сервера: " :
                    "Error requesting check user name and password to SCADA-Server: ") + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
                Disconnect();
            }
            finally
            {
                RestoreReceiveTimeout();
                Monitor.Exit(tcpLock);
            }

            return result;
        }
Example #6
0
        /// <summary>
        /// Принять дату и время изменения файла от SCADA-Сервера.
        /// В случае отсутствия файла возвращается минимальная дата
		/// </summary>
        public DateTime ReceiveFileAge(Dirs dir, string fileName)
        {
            Monitor.Enter(tcpLock);
            DateTime result = DateTime.MinValue;
            string filePath = DirToString(dir) + fileName;
            errMsg = "";

            try
            {
                if (RestoreConnection())
                {
#if DETAILED_LOG
                    WriteAction(string.Format(Localization.UseRussian ? 
                        "Приём даты и времени изменения файла {0} от SCADA-Сервера" :
                        "Receive date and time of file {0} modification from SCADA-Server", filePath), 
                        Log.ActTypes.Action);
#endif

                    commState = CommStates.WaitResponse;
                    tcpClient.ReceiveTimeout = commSettings.ServerTimeout;

                    // отправка запроса даты и времени изменения файла
                    int cmdLen = 6 + fileName.Length;
                    byte[] buf = new byte[cmdLen];
                    buf[0] = (byte)(cmdLen % 256);
                    buf[1] = (byte)(cmdLen / 256);
                    buf[2] = 0x0C;
                    buf[3] = 0x01;
                    buf[4] = (byte)dir;
                    buf[5] = (byte)fileName.Length;
                    Array.Copy(Encoding.Default.GetBytes(fileName), 0, buf, 6, fileName.Length);
                    netStream.Write(buf, 0, cmdLen);

                    // приём даты и времени изменения файла
                    buf = new byte[12];
                    netStream.Read(buf, 0, 12);

                    // обработка даты и времени изменения файла
                    if (CheckDataFormat(buf, 0x0C))
                    {
                        double dt = BitConverter.ToDouble(buf, 4);
                        result = dt == 0.0 ? DateTime.MinValue : Arithmetic.DecodeDateTime(dt);
                        commState = CommStates.Authorized;
                    }
                    else
                    {
                        errMsg = string.Format(Localization.UseRussian ? 
                            "Неверный формат ответа SCADA-Сервера на запрос даты и времени изменения файла {0}" :
                            "Incorrect SCADA-Server response to file modification date and time request", filePath);
                        WriteAction(errMsg, Log.ActTypes.Error);
                        commState = CommStates.Error;
                    }
                }
            }
            catch (Exception ex)
            {
                errMsg = string.Format(Localization.UseRussian ?
                        "Ошибка при приёме даты и времени изменения файла {0} от SCADA-Сервера: " :
                        "Error receiving date and time of file {0} modification from SCADA-Server: ", filePath) + 
                        ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
                Disconnect();
            }
            finally
            {
                RestoreReceiveTimeout();
                Monitor.Exit(tcpLock);
            }

            return result;
        }
Example #7
0
        /// <summary>
        /// Принять файл от SCADA-Сервера
        /// </summary>
        protected bool ReceiveFile(Dirs dir, string fileName, Stream inStream)
        {
            bool result = false;
            string filePath = DirToString(dir) + fileName;

            try
            {
#if DETAILED_LOG
                WriteAction(string.Format(Localization.UseRussian ? "Приём файла {0} от SCADA-Сервера" : 
                    "Receive file {0} from SCADA-Server", filePath), Log.ActTypes.Action);
#endif

                commState = CommStates.WaitResponse;
                tcpClient.ReceiveTimeout = commSettings.ServerTimeout;

                const int dataSize = 10240; // размер запрашиваемых данных 10 кБ
                const byte dataSizeL = dataSize % 256;
                const byte dataSizeH = dataSize / 256;

                byte[] buf = new byte[6 + dataSize]; // буфер отправляемых и получаемых данных
                bool open = true;  // выполняется открытие файла
                bool stop = false; // признак завершения приёма данных

                while (!stop)
                {
                    if (open)
                    {
                        // отправка команды открытия файла и чтения данных
                        byte fileNameLen = (byte)fileName.Length;
                        int cmdLen = 7 + fileNameLen;
                        buf[0] = (byte)(cmdLen % 256);
                        buf[1] = (byte)(cmdLen / 256);
                        buf[2] = 0x08;
                        buf[3] = (byte)dir;
                        buf[4] = fileNameLen;
                        Array.Copy(Encoding.Default.GetBytes(fileName), 0, buf, 5, fileNameLen);
                        buf[cmdLen - 2] = dataSizeL;
                        buf[cmdLen - 1] = dataSizeH;
                        netStream.Write(buf, 0, cmdLen);
                    }
                    else
                    {
                        // отправка команды чтения данных из файла
                        buf[0] = 0x05;
                        buf[1] = 0x00;
                        buf[2] = 0x0A;
                        buf[3] = dataSizeL;
                        buf[4] = dataSizeH;
                        netStream.Write(buf, 0, 5);
                    }

                    // приём результата открытия файла и считанных данных
                    byte cmdNum = buf[2];
                    int headerLen = open ? 6 : 5;
                    int bytesRead = netStream.Read(buf, 0, headerLen);
                    int dataSizeRead = 0; // размер считанных из файла данных                    

                    if (bytesRead == headerLen)
                    {
                        dataSizeRead = buf[headerLen - 2] + 256 * buf[headerLen - 1];
                        if (0 < dataSizeRead && dataSizeRead <= dataSize)
                            bytesRead += ReadNetStream(buf, headerLen, dataSizeRead);
                    }

                    if (CheckDataFormat(buf, cmdNum, bytesRead) && bytesRead == dataSizeRead + headerLen)
                    {
                        if (open)
                        {
                            open = false;

                            if (buf[3] > 0) // файл открыт
                            {
                                inStream.Write(buf, 6, dataSizeRead);
                                commState = CommStates.Authorized;
                                stop = dataSizeRead < dataSize;
                            }
                            else
                            {
                                errMsg = string.Format(Localization.UseRussian ? 
                                    "SCADA-Серверу не удалось открыть файл {0}" : 
                                    "SCADA-Server unable to open file {0}", filePath);
                                WriteAction(errMsg, Log.ActTypes.Action);
                                commState = CommStates.NotReady;
                                stop = true;
                            }
                        }
                        else
                        {
                            inStream.Write(buf, 5, dataSizeRead);
                            commState = CommStates.Authorized;
                            stop = dataSizeRead < dataSize;
                        }
                    }
                    else
                    {
                        errMsg = string.Format(Localization.UseRussian ? 
                            "Неверный формат ответа SCADA-Сервера на команду открытия или чтения из файла {0}" :
                            "Incorrect SCADA-Server response to open file or read from file {0} command ", filePath);
                        WriteAction(errMsg, Log.ActTypes.Error);
                        commState = CommStates.Error;
                        stop = true;
                    }
                }

                // определение результата
                if (commState == CommStates.Authorized)
                {
                    if (inStream.Length > 0)
                        inStream.Position = 0;
                    result = true;
                }
            }
            catch (Exception ex)
            {
                errMsg = string.Format(Localization.UseRussian ? "Ошибка при приёме файла {0} от SCADA-Сервера: " :
                    "Error receiving file {0} from SCADA-Server: ", filePath) + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
                Disconnect();
            }
            finally
            {
                RestoreReceiveTimeout();
            }

            return result;
        }
Example #8
0
        /// <summary>
        /// Установить соединение со SCADA-Сервером и произвести авторизацию
        /// </summary>
        protected bool Connect()
        {
            try
            {
                commState = CommStates.Disconnected;
                WriteAction(string.Format(Localization.UseRussian ? 
                    "Установка соединения со SCADA-Сервером \"{0}\"" : 
                    "Connect to SCADA-Server \"{0}\"", commSettings.ServerHost), Log.ActTypes.Action);

                // определение IP-адреса, если он указан в конфигурации программы
                IPAddress ipAddress = null;
                try { ipAddress = IPAddress.Parse(commSettings.ServerHost); }
                catch { }

                // создание, настройка и попытка установки соединения
                tcpClient = new TcpClient();
                tcpClient.NoDelay = true;            // sends data immediately upon calling NetworkStream.Write
                tcpClient.ReceiveBufferSize = 16384; // 16 кБ
                tcpClient.SendBufferSize = 8192;     // 8 кБ, размер по умолчанию
                tcpClient.SendTimeout = TcpSendTimeout;
                tcpClient.ReceiveTimeout = TcpReceiveTimeout;

                if (ipAddress == null)
                    tcpClient.Connect(commSettings.ServerHost, commSettings.ServerPort);
                else
                    tcpClient.Connect(ipAddress, commSettings.ServerPort);

                netStream = tcpClient.GetStream();

                // получение версии SCADA-Сервера
                byte[] buf = new byte[5];
                int bytesRead = netStream.Read(buf, 0, 5);

                // обработка считанных данных версии
                if (bytesRead == buf.Length && CheckDataFormat(buf, 0x00))
                {
                    commState = CommStates.Connected;
                    serverVersion = buf[4] + "." + buf[3]; 

                    // запрос правильности имени и пароля пользователя, его роли
                    byte userLen = (byte)commSettings.ServerUser.Length;
                    byte pwdLen = (byte)commSettings.ServerPwd.Length;
                    buf = new byte[5 + userLen + pwdLen];

                    buf[0] = (byte)(buf.Length % 256);
                    buf[1] = (byte)(buf.Length / 256);
                    buf[2] = 0x01;
                    buf[3] = userLen;
                    Array.Copy(Encoding.Default.GetBytes(commSettings.ServerUser), 0, buf, 4, userLen);
                    buf[4 + userLen] = pwdLen;
                    Array.Copy(Encoding.Default.GetBytes(commSettings.ServerPwd), 0, buf, 5 + userLen, pwdLen);

                    netStream.Write(buf, 0, buf.Length);

                    // приём результата
                    buf = new byte[4];
                    bytesRead = netStream.Read(buf, 0, 4);

                    // обработка считанных данных
                    if (bytesRead == buf.Length && CheckDataFormat(buf, 0x01))
                    {
                        Roles role = (Roles)buf[3];

                        if (role == Roles.App)
                        {
                            commState = CommStates.Authorized;
                        }
                        else if (role < Roles.Err)
                        {
                            errMsg = Localization.UseRussian ? "Недостаточно прав для соединения со SCADA-Сервером" :
                                "Insufficient rights to connect to SCADA-Server";
                            WriteAction(errMsg, Log.ActTypes.Error);
                            commState = CommStates.Error;
                        }
                        else // role == Roles.Err
                        {
                            errMsg = Localization.UseRussian ? "Неверное имя пользователя или пароль" :
                                "User name or password is incorrect";
                            WriteAction(errMsg, Log.ActTypes.Error);
                            commState = CommStates.Error;
                        }
                    }
                    else
                    {
                        errMsg = Localization.UseRussian ? 
                            "Неверный формат ответа SCADA-Сервера на запрос правильности имени и пароля" :
                            "Incorrect SCADA-Server response to check user name and password request";
                        WriteAction(errMsg, Log.ActTypes.Error);
                        commState = CommStates.Error;
                    }
                }
                else
                {
                    errMsg = Localization.UseRussian ? "Неверный формат ответа SCADA-Сервера на запрос версии" :
                        "Incorrect SCADA-Server response to version request";
                    WriteAction(errMsg, Log.ActTypes.Error);
                    commState = CommStates.Error;
                }
            }
            catch (Exception ex)
            {
                errMsg = (Localization.UseRussian ? "Ошибка при установке соединения со SCADA-Сервером: " : 
                    "Error connecting to SCADA-Server: ") + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
            }

            // возврат результата
            if (commState == CommStates.Authorized)
            {
                return true;
            }
            else
            {
                Disconnect();
                return false;
            }
        }
Example #9
0
        /// <summary>
        /// Разорвать соединение со SCADA-Сервером
        /// </summary>
        protected void Disconnect()
        {
            try
            {
                commState = CommStates.Disconnected;
                serverVersion = "";

                if (tcpClient != null)
                {
                    WriteAction(Localization.UseRussian ? "Разрыв соединения со SCADA-Сервером" : 
                        "Disconnect from SCADA-Server", Log.ActTypes.Action);

                    if (netStream != null)
                    {
                        // очистка (для корректного разъединения) и закрытие потока данных TCP-клиента
                        ClearNetStream();
                        netStream.Close();
                        netStream = null;
                    }

                    tcpClient.Close();
                    tcpClient = null;
                }
            }
            catch (Exception ex)
            {
                errMsg = (Localization.UseRussian ? "Ошибка при разрыве соединения со SCADA-Сервером: " : 
                    "Error disconnecting from SCADA-Server: ") + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
            }
        }
Example #10
0
        /// <summary>
        /// Отправить команду квитирования события SCADA-Серверу
        /// </summary>
        public bool CheckEvent(int userID, DateTime date, int evNum, out bool result)
        {
            Monitor.Enter(tcpLock);
            bool complete = false;
            result = false;
            errMsg = "";

            try
            {
                if (RestoreConnection())
                {
                    WriteAction(Localization.UseRussian ? "Отправка команды квитирования события SCADA-Серверу" :
                        "Send check event command to SCADA-Server", Log.ActTypes.Action);

                    commState = CommStates.WaitResponse;
                    tcpClient.ReceiveTimeout = commSettings.ServerTimeout;

                    // отправка команды
                    byte[] buf = new byte[10];
                    buf[0] = 0x0A;
                    buf[1] = 0x00;
                    buf[2] = 0x0E;
                    buf[3] = (byte)(userID % 256);
                    buf[4] = (byte)(userID / 256);
                    buf[5] = (byte)(date.Year % 100);
                    buf[6] = (byte)date.Month;
                    buf[7] = (byte)date.Day;
                    buf[8] = (byte)(evNum % 256);
                    buf[9] = (byte)(evNum / 256);
                    netStream.Write(buf, 0, 10);

                    // приём результата
                    buf = new byte[4];
                    int bytesRead = netStream.Read(buf, 0, 4);

                    // обработка полученных данных
                    if (bytesRead == buf.Length && CheckDataFormat(buf, 0x0E))
                    {
                        result = buf[3] > 0;
                        commState = result ? CommStates.Authorized : CommStates.NotReady;
                        complete = true;
                    }
                    else
                    {
                        errMsg = Localization.UseRussian ? 
                            "Неверный формат ответа SCADA-Сервера на команду квитирования события" :
                            "Incorrect SCADA-Server response to check event command";
                        WriteAction(errMsg, Log.ActTypes.Error);
                        commState = CommStates.Error;
                    }
                }
            }
            catch (Exception ex)
            {
                errMsg = (Localization.UseRussian ? 
                    "Ошибка при отправке команды квитирования события SCADA-Серверу: " :
                    "Error sending check event command to SCADA-Server: ") + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
                Disconnect();
            }
            finally
            {
                RestoreReceiveTimeout();
                Monitor.Exit(tcpLock);
            }

            return complete;
        }
Example #11
0
 /// <summary>
 /// Конструктор
 /// </summary>
 protected ServerComm()
 {
     tcpClient = null;
     netStream = null;
     tcpLock = new object();
     commState = CommStates.Disconnected;
     serverVersion = "";
     restConnSuccDT = DateTime.MinValue;
     restConnErrDT = DateTime.MinValue;
     errMsg = "";
 }
Example #12
0
        /// <summary>
        /// Отправить событие SCADA-Серверу
        /// </summary>
        public bool SendEvent(EventTableLight.Event aEvent, out bool result)
        {
            Monitor.Enter(tcpLock);
            bool complete = false;
            result = false;
            errMsg = "";

            try
            {
                if (RestoreConnection())
                {
                    commState = CommStates.WaitResponse;
                    tcpClient.ReceiveTimeout = commSettings.ServerTimeout;

                    // отправка команды записи события
                    byte descrLen = (byte)aEvent.Descr.Length;
                    byte dataLen = (byte)aEvent.Data.Length;
                    int cmdLen = 46 + descrLen + dataLen;
                    byte[] buf = new byte[cmdLen];
                    buf[0] = (byte)(cmdLen % 256);
                    buf[1] = (byte)(cmdLen / 256);
                    buf[2] = 0x05;

                    double evDT = Arithmetic.EncodeDateTime(aEvent.DateTime);
                    byte[] bytes = BitConverter.GetBytes(evDT);
                    Array.Copy(bytes, 0, buf, 3, 8);

                    buf[11] = (byte)(aEvent.ObjNum % 256);
                    buf[12] = (byte)(aEvent.ObjNum / 256);
                    buf[13] = (byte)(aEvent.KPNum % 256);
                    buf[14] = (byte)(aEvent.KPNum / 256);
                    buf[15] = (byte)(aEvent.ParamID % 256);
                    buf[16] = (byte)(aEvent.ParamID / 256);

                    bytes = BitConverter.GetBytes(aEvent.CnlNum);
                    Array.Copy(bytes, 0, buf, 17, 4);
                    bytes = BitConverter.GetBytes(aEvent.OldCnlVal);
                    Array.Copy(bytes, 0, buf, 21, 8);
                    bytes = BitConverter.GetBytes(aEvent.OldCnlStat);
                    Array.Copy(bytes, 0, buf, 29, 2);
                    bytes = BitConverter.GetBytes(aEvent.NewCnlVal);
                    Array.Copy(bytes, 0, buf, 31, 8);
                    bytes = BitConverter.GetBytes(aEvent.NewCnlStat);
                    Array.Copy(bytes, 0, buf, 39, 2);

                    buf[41] = aEvent.Checked ? (byte)0x01 : (byte)0x00;
                    buf[42] = (byte)(aEvent.UserID % 256);
                    buf[43] = (byte)(aEvent.UserID / 256);

                    buf[44] = descrLen;
                    Array.Copy(Encoding.Default.GetBytes(aEvent.Descr), 0, buf, 45, descrLen);
                    buf[45 + descrLen] = dataLen;
                    Array.Copy(Encoding.Default.GetBytes(aEvent.Data), 0, buf, 46 + descrLen, dataLen);

                    netStream.Write(buf, 0, cmdLen);

                    // приём результата
                    buf = new byte[4];
                    int bytesRead = netStream.Read(buf, 0, 4);

                    // обработка полученных данных
                    if (bytesRead == buf.Length && CheckDataFormat(buf, 0x05))
                    {
                        result = buf[3] > 0;
                        commState = result ? CommStates.Authorized : CommStates.NotReady;
                        complete = true;
                    }
                    else
                    {
                        errMsg = Localization.UseRussian ?
                            "Неверный формат ответа SCADA-Сервера на команду отправки события" :
                            "Incorrect SCADA-Server response to sending event command";
                        WriteAction(errMsg, Log.ActTypes.Error);
                        commState = CommStates.Error;
                    }
                }
            }
            catch (Exception ex)
            {
                errMsg = (Localization.UseRussian ? "Ошибка при отправке события SCADA-Серверу: " :
                    "Error sending event to SCADA-Server: ") + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
                Disconnect();
            }
            finally
            {
                RestoreReceiveTimeout();
                Monitor.Exit(tcpLock);
            }

            return complete;
        }
Example #13
0
        /// <summary>
        /// Отправить архивный срез SCADA-Серверу
        /// </summary>
        public bool SendArchive(SrezTableLight.Srez arcSrez, out bool result)
        {
            Monitor.Enter(tcpLock);
            bool complete = false;
            result = false;
            errMsg = "";

            try
            {
                if (RestoreConnection())
                {
                    commState = CommStates.WaitResponse;
                    tcpClient.ReceiveTimeout = commSettings.ServerTimeout;

                    // отправка команды записи архивного среза
                    int cnlCnt = arcSrez.CnlNums.Length;
                    int cmdLen = cnlCnt * 14 + 13;

                    byte[] buf = new byte[cmdLen];
                    buf[0] = (byte)(cmdLen % 256);
                    buf[1] = (byte)(cmdLen / 256);
                    buf[2] = 0x04;

                    double arcDT = Arithmetic.EncodeDateTime(arcSrez.DateTime);
                    byte[] bytes = BitConverter.GetBytes(arcDT);
                    Array.Copy(bytes, 0, buf, 3, 8);

                    buf[11] = (byte)(cnlCnt % 256);
                    buf[12] = (byte)(cnlCnt / 256);

                    for (int i = 0; i < cnlCnt; i++)
                    {
                        bytes = BitConverter.GetBytes((UInt32)arcSrez.CnlNums[i]);
                        Array.Copy(bytes, 0, buf, i * 14 + 13, 4);

                        SrezTableLight.CnlData data = arcSrez.CnlData[i];
                        bytes = BitConverter.GetBytes(data.Val);
                        Array.Copy(bytes, 0, buf, i * 14 + 17, 8);

                        bytes = BitConverter.GetBytes((UInt16)data.Stat);
                        Array.Copy(bytes, 0, buf, i * 14 + 25, 2);
                    }

                    netStream.Write(buf, 0, cmdLen);

                    // приём результата
                    buf = new byte[4];
                    int bytesRead = netStream.Read(buf, 0, 4);

                    // обработка полученных данных
                    if (bytesRead == buf.Length && CheckDataFormat(buf, 0x04))
                    {
                        result = buf[3] > 0;
                        commState = result ? CommStates.Authorized : CommStates.NotReady;
                        complete = true;
                    }
                    else
                    {
                        errMsg = Localization.UseRussian ?
                            "Неверный формат ответа SCADA-Сервера на команду отправки архивного среза" :
                            "Incorrect SCADA-Server response to sending archive data command";
                        WriteAction(errMsg, Log.ActTypes.Exception);
                        commState = CommStates.Error;
                    }
                }
            }
            catch (Exception ex)
            {
                errMsg = (Localization.UseRussian ? "Ошибка при отправке архивного среза SCADA-Серверу: " : 
                    "Error sending archive data to SCADA-Server: ") + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
                Disconnect();
            }
            finally
            {
                RestoreReceiveTimeout();
                Monitor.Exit(tcpLock);
            }

            return complete;
        }
Example #14
0
        /// <summary>
        /// Принять команду ТУ от SCADA-Сервера
        /// </summary>
        /// <remarks>
        /// Для стандартной команды возвращаемые данные команды равны null.
        /// Для бинарной команды возвращаемое значение команды равно double.NaN.
        /// Для команды опроса КП возвращаемое значение команды равно double.NaN и данные команды равны null.</remarks>
        public bool ReceiveCommand(out int kpNum, out int cmdNum, out double cmdVal, out byte[] cmdData)
        {
            Monitor.Enter(tcpLock);
            bool result = false;
            kpNum = 0;
            cmdNum = 0;
            cmdVal = double.NaN;
            cmdData = null;
            errMsg = "";

            try
            {
                if (RestoreConnection())
                {
                    commState = CommStates.WaitResponse;
                    tcpClient.ReceiveTimeout = commSettings.ServerTimeout;

                    // запрос команды
                    byte[] buf = new byte[3];
                    buf[0] = 0x03;
                    buf[1] = 0x00;
                    buf[2] = 0x07;
                    netStream.Write(buf, 0, 3);

                    // приём команды
                    buf = new byte[5];
                    int bytesRead = netStream.Read(buf, 0, 5);
                    int cmdDataLen = 0;

                    if (bytesRead == 5)
                    {
                        cmdDataLen = buf[3] + buf[4] * 256;

                        if (cmdDataLen > 0)
                        {
                            Array.Resize<byte>(ref buf, 10 + cmdDataLen);
                            bytesRead += netStream.Read(buf, 5, 5 + cmdDataLen);
                        }
                    }

                    // обработка полученных данных
                    if (CheckDataFormat(buf, 0x07) && bytesRead == buf.Length)
                    {
                        if (cmdDataLen > 0)
                        {
                            byte cmdType = buf[5];

                            if (cmdType == 0)
                            {
                                cmdVal = BitConverter.ToDouble(buf, 10);
                            }
                            else if (cmdType == 1)
                            {
                                cmdData = new byte[cmdDataLen];
                                Array.Copy(buf, 10, cmdData, 0, cmdDataLen);
                            }

                            kpNum = buf[6] + buf[7] * 256;
                            cmdNum = buf[8] + buf[9] * 256;

                            commState = CommStates.Authorized;
                            result = true;
                        }
                        else // команд в очереди нет
                        {
                            commState = CommStates.Authorized;
                        }
                    }
                    else
                    {
                        errMsg = Localization.UseRussian ?
                            "Неверный формат ответа SCADA-Сервера на запрос команды ТУ" :
                            "Incorrect SCADA-Server response to telecommand request";
                        WriteAction(errMsg, Log.ActTypes.Error);
                        commState = CommStates.Error;
                    }
                }
            }
            catch (Exception ex)
            {
                errMsg = (Localization.UseRussian ? "Ошибка при приёме команды ТУ от SCADA-Сервера: " : 
                    "Error requesting telecommand from SCADA-Server: ") + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
                Disconnect();
            }
            finally
            {
                RestoreReceiveTimeout();
                Monitor.Exit(tcpLock);
            }

            return result;
        }
Example #15
0
 public virtual void Fault(string faultReason)
 {
    this.faultReason = faultReason;
    this.commState = CommStates.error;
    this.actionQueue.Clear();
    this.SignalCommError();
    this.Stop();
 }
Example #16
0
        /// <summary>
        /// Восстановить соединение со SCADA-Сервером и произвести авторизацию при необходимости
        /// </summary>
        protected bool RestoreConnection()
        {
            bool connectNeeded = false; // требуется повторное соединение
            DateTime now = DateTime.Now;

            if (commState >= CommStates.Authorized)
            {
                if (now - restConnSuccDT > PingSpan)
                {
                    // проверка соединения
                    try
                    {
                        WriteAction(Localization.UseRussian ? "Запрос состояния SCADA-Сервера" : 
                            "Request SCADA-Server state", Log.ActTypes.Action);
                        commState = CommStates.WaitResponse;

                        // запрос состояния SCADA-Сервера (ping)
                        byte[] buf = new byte[3];
                        buf[0] = 0x03;
                        buf[1] = 0x00;
                        buf[2] = 0x02;
                        netStream.Write(buf, 0, 3);

                        // приём результата
                        buf = new byte[4];
                        netStream.Read(buf, 0, 4);

                        // обработка результата
                        if (CheckDataFormat(buf, 0x02))
                        {
                            commState = buf[3] > 0 ? CommStates.Authorized : CommStates.NotReady;
                        }
                        else
                        {
                            errMsg = Localization.UseRussian ? 
                                "Неверный формат ответа SCADA-Сервера на запрос состояния" : 
                                "Incorrect SCADA-Server response to state request";
                            WriteAction(errMsg, Log.ActTypes.Error);
                            commState = CommStates.Error;
                            connectNeeded = true;
                        }
                    }
                    catch
                    {
                        connectNeeded = true;
                    }
                }
            }
            else if (now - restConnErrDT > ConnectSpan)
            {
                connectNeeded = true;
            }

            // соединение при необходимости
            if (connectNeeded)
            {
                if (tcpClient != null) 
                    Disconnect();

                if (Connect())
                {
                    restConnSuccDT = now;
                    restConnErrDT = DateTime.MinValue;
                    return true;
                }
                else
                {
                    restConnSuccDT = DateTime.MinValue;
                    restConnErrDT = now;
                    return false;
                }
            }
            else
            {
                ClearNetStream(); // очистка потока данных TCP-клиента

                if (commState >= CommStates.Authorized)
                {
                    restConnSuccDT = now;
                    return true;
                }
                else
                {
                    errMsg = Localization.UseRussian ? "Невозможно соединиться со SCADA-Сервером. Повторите попытку." :
                        "Unable to connect to SCADA-Server. Try again.";
                    return false;
                }
            }
        }
Example #17
0
      public virtual void Update()
      {
         CommStates processedState;

         do 
         {
            processedState = this.commState;

            switch (this.commState)
            {
               case CommStates.idle:
               {
                  lock (this)
                  {
                     if (this.actionQueue.Count != 0)
                     {
                        this.action = (CommAction)this.actionQueue.Dequeue();
                     }
                  }

                  if (null != this.action)
                  {
                     this.commAttemptCount = 0;
                     this.commState = CommStates.tx;
                     //Tracer.WriteHigh(TraceGroup.CANBUS, "", "action start");
                  }

                  break;
               }
               case CommStates.tx:
               {
                  this.commAttemptCount++;

                  if (this.commAttemptCount <= this.action.RetryAttemptLimit)
                  {
                     int cobId = 0;
                     byte[] frameData = this.action.GetTransmitFrame(ref cobId, this.NodeId);

                     if (null != frameData)
                     {
                        bool txResult = this.Transmit(cobId, frameData);

                        if (false != txResult)
                        {
                           this.action.TransmitComplete();

                           bool responseNeeded = this.action.ResponseNeeded();

                           if (false != responseNeeded)
                           {
                              //Tracer.WriteHigh(TraceGroup.CANBUS, "", "tx pending");
                              this.commTimeLimit = DateTime.Now.AddMilliseconds(this.action.RetryTime);
                              this.commState = CommStates.rxWait;
                           }
                           else
                           {
                              this.EvaluateAction(this.action);
                              this.action = null;
                              this.commState = CommStates.idle;
                           }
                        }
                        else
                        {
                           Tracer.WriteHigh(TraceGroup.CANBUS, "", "tx fail");
                           this.commTimeLimit = DateTime.Now.AddMilliseconds(this.TransmitFailureHoldoffTime);
                           this.commState = CommStates.txWait;
                        }
                     }
                     else
                     {
                        this.action = null;
                        this.commState = CommStates.idle;
                     }
                  }
                  else
                  {
                     this.Fault("comm failure");
                     this.action = null;
                  }

                  break;
               }
               case CommStates.txWait:
               {
                  if (DateTime.Now > this.commTimeLimit)
                  {
                     this.commState = CommStates.tx;
                  }

                  break;
               }
               case CommStates.rxWait:
               {
                  if (false != this.action.Done)
                  {
                     this.EvaluateAction(this.action);

                     if (false != this.action.Aborted)
                     {
                        this.Fault("comm abort");
                     }

                     this.action = null;
                     this.commState = CommStates.idle;
                  }
                  else if (false != this.action.Transmit)
                  {
                     this.commAttemptCount = 0;
                     this.commState = CommStates.tx;
                  }
                  else if (DateTime.Now > this.commTimeLimit)
                  {
                     this.commState = CommStates.tx;
                     Tracer.WriteHigh(TraceGroup.CANBUS, "", "response timeout");
                  }

                  break;
               }
               case CommStates.error:
               {
                  break;
               }                
            }

         }
         while (processedState != this.commState);

         if (null == this.FaultReason)
         {
            if ((false != this.consumerHeartbeatActive) &&
                (DateTime.Now > this.consumerHeartbeatTimeLimit))
            {
               this.Fault("heartbeat missing");
            }
         }
      }
Example #18
0
        /// <summary>
        /// Принять тренд входного канала от SCADA-Сервера
        /// </summary>
        public bool ReceiveTrend(string tableName, DateTime date, Trend trend)
        {
            Monitor.Enter(tcpLock);
            bool result = false;
            errMsg = "";

            try
            {
                try
                {
                    if (RestoreConnection())
                    {
                        WriteAction(string.Format(Localization.UseRussian ? 
                            "Приём тренда входного канала {0} от SCADA-Сервера. Файл: {1}" : 
                            "Receive input channel {0} trend from SCADA-Server. File: {1}", 
                            trend.CnlNum, tableName), Log.ActTypes.Action);

                        commState = CommStates.WaitResponse;
                        tcpClient.ReceiveTimeout = commSettings.ServerTimeout;

                        byte tableType;        // тип таблицы: текущая, часовая или минутная
                        byte year, month, day; // дата запрашиваемых данных

                        if (tableName == "current.dat")
                        {
                            tableType = (byte)0x01;
                            year = month = day = 0;
                        }
                        else
                        {
                            tableType = tableName.Length > 0 && tableName[0] == 'h' ? (byte)0x02 : (byte)0x03;
                            year = (byte)(date.Year % 100);
                            month = (byte)date.Month;
                            day = (byte)date.Day;
                        }

                        // отправка запроса тренда входного канала
                        byte[] buf = new byte[13];
                        buf[0] = 0x0D;
                        buf[1] = 0x00;
                        buf[2] = 0x0D;
                        buf[3] = tableType;
                        buf[4] = year;
                        buf[5] = month;
                        buf[6] = day;
                        buf[7] = 0x01;
                        buf[8] = 0x00;
                        byte[] bytes = BitConverter.GetBytes(trend.CnlNum);
                        Array.Copy(bytes, 0, buf, 9, 4);
                        netStream.Write(buf, 0, 13);

                        // приём данных тренда входного канала
                        buf = new byte[7];
                        int bytesRead = netStream.Read(buf, 0, 7);
                        int pointCnt = 0;

                        if (bytesRead == 7)
                        {
                            pointCnt = buf[5] + buf[6] * 256;

                            if (pointCnt > 0)
                            {
                                Array.Resize<byte>(ref buf, 7 + pointCnt * 18);
                                bytesRead += ReadNetStream(buf, 7, buf.Length - 7);
                            }
                        }

                        // заполение тренда входного канала из полученных данных
                        if (bytesRead == buf.Length && buf[4] == 0x0D)
                        {
                            for (int i = 0; i < pointCnt; i++)
                            {
                                Trend.Point point;
                                int pos = i * 18 + 7;
                                point.DateTime = Arithmetic.DecodeDateTime(BitConverter.ToDouble(buf, pos));
                                point.Val = BitConverter.ToDouble(buf, pos + 8);
                                point.Stat = BitConverter.ToUInt16(buf, pos + 16);

                                trend.Points.Add(point);
                            }

                            trend.Sort();
                            result = true;
                            commState = CommStates.Authorized;
                        }
                        else
                        {
                            errMsg = Localization.UseRussian ? 
                                "Неверный формат ответа SCADA-Сервера на запрос тренда входного канала" :
                                "Incorrect SCADA-Server response to input channel trend request";
                            WriteAction(errMsg, Log.ActTypes.Error);
                            commState = CommStates.Error;
                        }
                    }
                }
                finally
                {
                    // очистка тренда, если не удалось получить новые данные
                    if (!result)
                    {
                        trend.Clear();
                        trend.TableName = tableName;
                    }
                }
            }
            catch (Exception ex)
            {
                errMsg = (Localization.UseRussian ? "Ошибка при приёме тренда входного канала от SCADA-Сервера: " :
                    "Error receiving input channel trend from SCADA-Server: ") + ex.Message;
                WriteAction(errMsg, Log.ActTypes.Exception);
                Disconnect();
            }
            finally
            {
                RestoreReceiveTimeout();
                Monitor.Exit(tcpLock);
            }

            return result;
        }