private void btnSend_Click(object sender, EventArgs e) { // send a command to Server int userID = decimal.ToInt32(numUserID.Value); int ctrlCnlNum = decimal.ToInt32(numCtrlCnlNum.Value); bool cmdSent = false; bool sendOK = false; if (rbStandard.Checked) { double cmdVal = ScadaUtils.StrToDouble(txtCmdVal.Text); if (double.IsNaN(cmdVal)) { ScadaUiUtils.ShowError(CommonPhrases.IncorrectCmdVal); } else { sendOK = serverComm.SendStandardCommand(userID, ctrlCnlNum, cmdVal, out bool result); cmdSent = true; } } else if (rbBinary.Checked) { if (rbString.Checked) { byte[] cmdData = Command.StrToCmdData(txtCmdData.Text); sendOK = serverComm.SendBinaryCommand(userID, ctrlCnlNum, cmdData, out bool result); cmdSent = true; } else if (ScadaUtils.HexToBytes(txtCmdData.Text, out byte[] cmdData, true))
/// <summary> /// Loads the options from the XML node. /// </summary> public void LoadFromXml(XmlNode xmlNode) { if (xmlNode == null) { throw new ArgumentNullException(nameof(xmlNode)); } Name = xmlNode.GetChildAsString("Name"); Host = xmlNode.GetChildAsString("Host"); Port = xmlNode.GetChildAsInt("Port", Port); User = xmlNode.GetChildAsString("User"); Password = ScadaUtils.Decrypt(xmlNode.GetChildAsString("Password")); Instance = xmlNode.GetChildAsString("Instance"); Timeout = xmlNode.GetChildAsInt("Timeout", Timeout); string secretKeyStr = xmlNode.GetChildAsString("SecretKey"); if (string.IsNullOrEmpty(secretKeyStr)) { SecretKey = null; } else { SecretKey = ScadaUtils.HexToBytes(secretKeyStr); if (SecretKey.Length != ScadaUtils.SecretKeySize) { throw new ScadaException(CommonPhrases.InvalidParamVal, "SecretKey"); } } }
private void btnCreateSession_Click(object sender, EventArgs e) { var client = new AgentSvcClient(); try { if (client.CreateSession(out sessionID)) { MessageBox.Show(@"Session created: " + sessionID); string encPwd = CryptoUtils.EncryptPassword("12345", sessionID, ScadaUtils.HexToBytes(SecretKey)); if (client.Login(sessionID, "admin", encPwd, "Default", out string errMsg)) { MessageBox.Show(@"Logged on."); } else { MessageBox.Show(errMsg); } } else { MessageBox.Show(@"Unable to create session."); } } finally { client.Close(); } }
/// <summary> /// Creates a telecontrol command. /// </summary> private bool CreateCommand(out TeleCommand cmd) { TeleCommand InitCmd() { return(new TeleCommand { DeviceNum = deviceConfig.DeviceNum, CmdNum = Convert.ToInt32(numCmdNum.Value), CmdCode = txtCmdCode.Text }); } if (rbNumVal.Checked) { if (ScadaUtils.TryParseDouble(txtCmdVal.Text, out double cmdVal)) { cmd = InitCmd(); cmd.CmdVal = cmdVal; return(true); } else { ScadaUiUtils.ShowError(CommonPhrases.RealRequired); } } else if (rbStrData.Checked) { cmd = InitCmd(); cmd.CmdData = TeleCommand.StringToCmdData(txtCmdData.Text); return(true); } else if (rbHexData.Checked) { if (ScadaUtils.HexToBytes(txtCmdData.Text, out byte[] cmdData, true))
/// <summary> /// Sets the settings according to the controls. /// </summary> private void ControlsToSettings() { if (Profile != null) { ConnectionSettings connSettings = Profile.ConnectionSettings; Profile.Name = txtProfileName.Text.Trim(); connSettings.Host = txtHost.Text.Trim(); connSettings.Port = (int)numPort.Value; connSettings.Username = txtUsername.Text.Trim(); connSettings.Password = txtPassword.Text; connSettings.SecretKey = ScadaUtils.HexToBytes(txtSecretKey.Text.Trim()); } }
/// <summary> /// Установить настройки в соответствии с элементами управления /// </summary> private void ControlsToSettings() { if (ConnectionSettings != null) { ConnectionSettings.Name = txtName.Text.Trim(); ConnectionSettings.Host = txtHost.Text.Trim(); ConnectionSettings.Port = (int)numPort.Value; ConnectionSettings.Username = txtUsername.Text.Trim(); ConnectionSettings.Password = txtPassword.Text; ConnectionSettings.ScadaInstance = txtScadaInstance.Text.Trim(); ConnectionSettings.SecretKey = ScadaUtils.HexToBytes(txtSecretKey.Text.Trim()); } }
/// <summary> /// Загрузить настройки из XML-узла /// </summary> public void LoadFromXml(XmlNode xmlNode) { if (xmlNode == null) { throw new ArgumentNullException("xmlNode"); } Name = xmlNode.GetChildAsString("Name"); Host = xmlNode.GetChildAsString("Host"); Port = xmlNode.GetChildAsInt("Port", 10002); Username = xmlNode.GetChildAsString("Username", "admin"); Password = xmlNode.GetChildAsString("Password"); ScadaInstance = xmlNode.GetChildAsString("ScadaInstance"); SecretKey = ScadaUtils.HexToBytes(xmlNode.GetChildAsString("SecretKey")); }
/// <summary> /// Validates the form fields. /// </summary> private bool ValidateFields() { StringBuilder sbError = new StringBuilder(); if (string.IsNullOrWhiteSpace(txtProfileName.Text)) { sbError.AppendError(lblProfileName, CommonPhrases.NonemptyRequired); } if (!string.IsNullOrWhiteSpace(txtWebUrl.Text) && !ScadaUtils.IsValidUrl(txtWebUrl.Text)) { sbError.AppendError(lblWebUrl, AppPhrases.ValidUrlRequired); } if (string.IsNullOrWhiteSpace(txtHost.Text)) { sbError.AppendError(lblHost, CommonPhrases.NonemptyRequired); } if (string.IsNullOrWhiteSpace(txtUsername.Text)) { sbError.AppendError(lblUsername, CommonPhrases.NonemptyRequired); } if (string.IsNullOrWhiteSpace(txtPassword.Text)) { sbError.AppendError(lblPassword, CommonPhrases.NonemptyRequired); } if (string.IsNullOrWhiteSpace(txtSecretKey.Text)) { sbError.AppendError(lblSecretKey, CommonPhrases.NonemptyRequired); } if (sbError.Length > 0) { sbError.Insert(0, AppPhrases.CorrectErrors + Environment.NewLine); ScadaUiUtils.ShowError(sbError.ToString()); return(false); } if (ExistingProfileNames != null && ExistingProfileNames.Contains(txtProfileName.Text.Trim())) { ScadaUiUtils.ShowError(AppPhrases.ProfileNameDuplicated); return(false); } if (!ScadaUtils.HexToBytes(txtSecretKey.Text.Trim(), out byte[] bytes))
/// <summary> /// Loads the options from the XML node. /// </summary> public void LoadFromXml(XmlNode xmlNode) { if (xmlNode == null) { throw new ArgumentNullException(nameof(xmlNode)); } Port = xmlNode.GetChildAsInt("Port", Port); Timeout = xmlNode.GetChildAsInt("Timeout", Timeout); SecretKey = ScadaUtils.HexToBytes(xmlNode.GetChildAsString("SecretKey")); if (SecretKey.Length != ScadaUtils.SecretKeySize) { throw new ScadaException(CommonPhrases.InvalidParamVal, "SecretKey"); } }
/// <summary> /// Load settings from file /// </summary> public bool Load(string fileName, out string errMsg) { // setting default values SetToDefault(); try { if (!File.Exists(fileName)) { throw new FileNotFoundException(string.Format(CommonPhrases.NamedFileNotFound, fileName)); } var xmlDoc = new XmlDocument(); xmlDoc.Load(fileName); var rootElem = xmlDoc.DocumentElement; // secret key loading if (ScadaUtils.HexToBytes(rootElem.GetChildAsString("SecretKey"), out byte[] secretKey) &&
/// <summary> /// Попытаться получить данные бинарной команды, введённые пользователем /// </summary> private bool TryParseCmdData(out byte[] cmdData) { if (txtCmdData.Text == "") { cmdData = null; return(false); } else if (rbStr.Checked) { cmdData = Command.StrToCmdData(txtCmdData.Text); return(true); } else { return(ScadaUtils.HexToBytes(txtCmdData.Text, out cmdData, true)); } }
/// <summary> /// Попытаться получить данные бинарной команды, введённые пользователем /// </summary> private bool TryParseCmdData(out byte[] cmdData) { if (txtCmdData.Text == "") { cmdData = null; return(false); } else if (rbStr.Checked) { cmdData = Encoding.Default.GetBytes(txtCmdData.Text); return(true); } else { return(ScadaUtils.HexToBytes(txtCmdData.Text, out cmdData, true)); } }
/// <summary> /// Sets the configuration according to the controls. /// </summary> private void ControlsToConfing() { // general options GeneralOptions generalOptions = serverConfig.GeneralOptions; generalOptions.UnrelIfInactive = decimal.ToInt32(numUnrelIfInactive.Value); generalOptions.GenerateAckCmd = chkGenerateAckCmd.Checked; generalOptions.MaxLogSize = decimal.ToInt32(numMaxLogSize.Value); generalOptions.DisableFormulas = chkDisableFormulas.Checked; generalOptions.EnableFormulasObjNums = ScadaUtils.ParseRange(txtEnableFormulasObjNums.Text, true, true); // listener options ListenerOptions listenerOptions = serverConfig.ListenerOptions; listenerOptions.Port = decimal.ToInt32(numPort.Value); listenerOptions.Timeout = decimal.ToInt32(numTimeout.Value); listenerOptions.SecretKey = ScadaUtils.HexToBytes(txtSecretKey.Text.Trim()); }
/// <summary> /// Загрузить настройки из файла /// </summary> public bool Load(string fileName, out string errMsg) { // установка значений по умолчанию SetToDefault(); try { if (!File.Exists(fileName)) { throw new FileNotFoundException(string.Format(CommonPhrases.NamedFileNotFound, fileName)); } XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(fileName); XmlElement rootElem = xmlDoc.DocumentElement; // загрузка секретного ключа if (ScadaUtils.HexToBytes(rootElem.GetChildAsString("SecretKey"), out byte[] secretKey) &&
/// <summary> /// Validates the values of the controls. /// </summary> private bool ValidateControls() { if (string.IsNullOrWhiteSpace(txtProfileName.Text) || string.IsNullOrWhiteSpace(txtHost.Text) || string.IsNullOrWhiteSpace(txtUsername.Text) || string.IsNullOrWhiteSpace(txtPassword.Text) || string.IsNullOrWhiteSpace(txtSecretKey.Text)) { ScadaUiUtils.ShowError(AppPhrases.EmptyFieldsNotAllowed); return(false); } if (ExistingProfileNames != null && ExistingProfileNames.Contains(txtProfileName.Text.Trim())) { ScadaUiUtils.ShowError(AppPhrases.ProfileNameDuplicated); return(false); } if (!ScadaUtils.HexToBytes(txtSecretKey.Text.Trim(), out byte[] bytes))
/// <summary> /// Handles a message received event. /// </summary> private void MqttClient_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e) { try { string topic = e.ApplicationMessage.Topic; string payload = e.ApplicationMessage.ConvertPayloadToString(); dsLog.WriteAction("{0} {1} = {2}", CommPhrases.ReceiveNotation, topic, payload.GetPreview(MqttUtils.MessagePreviewLength)); // parse and pass command if (topic == commandTopic) { ReceivedCommand command = JsonSerializer.Deserialize <ReceivedCommand>(payload); CommContext.SendCommand(new TeleCommand { CommandID = ScadaUtils.GenerateUniqueID(), CreationTime = DateTime.UtcNow, DeviceNum = command.DeviceNum, CmdCode = command.CmdCode, CmdVal = command.CmdVal, CmdData = ScadaUtils.HexToBytes(command.CmdData, false, true) }, DriverUtils.DriverCode); } } catch (JsonException) { dsLog.WriteError(Locale.IsRussian ? "Ошибка при получении команды из JSON." : "Error parsing command from JSON."); } catch (Exception ex) { dsLog.WriteError(ex, Locale.IsRussian ? "Ошибка при обработке полученного сообщения. Топик: {0}" : "Error handling the received message. Topic: {0}", e?.ApplicationMessage?.Topic); } }
private void btnSend_Click(object sender, EventArgs e) { // initialize a command Command cmd = new Command() { KPNum = kp.Number }; bool cmdOK = false; if (rbStandard.Checked) { cmd.CmdTypeID = BaseValues.CmdTypes.Standard; cmd.CmdNum = decimal.ToInt32(numCmdNum.Value); double cmdVal = ScadaUtils.StrToDouble(txtCmdVal.Text); if (double.IsNaN(cmdVal)) { ScadaUiUtils.ShowError(CommonPhrases.IncorrectCmdVal); } else { cmd.CmdVal = cmdVal; cmdOK = true; } } else if (rbBinary.Checked) { cmd.CmdTypeID = BaseValues.CmdTypes.Binary; cmd.CmdNum = decimal.ToInt32(numCmdNum.Value); if (rbString.Checked) { cmd.CmdData = Command.StrToCmdData(txtCmdData.Text); cmdOK = true; } else if (ScadaUtils.HexToBytes(txtCmdData.Text, out byte[] cmdData, true))
/// <summary> /// Validates the form controls. /// </summary> private bool ValidateControls() { StringBuilder sbError = new(); if (!ScadaUtils.ParseRange(txtEnableFormulasObjNums.Text, true, true, out _)) { sbError.AppendLine(ExtensionPhrases.InvalidObjectRange); } if (!ScadaUtils.HexToBytes(txtSecretKey.Text.Trim(), out _)) { sbError.AppendLine(CommonPhrases.InvalidSecretKey); } if (sbError.Length > 0) { ScadaUiUtils.ShowError(CommonPhrases.CorrectErrors + Environment.NewLine + sbError); return(false); } else { return(true); } }
// --------------------------------------------- Формирование буфера для команд чтения и команд записи private void Buf_Out(int Num, byte Fcode, byte[] bData, bool read) // формирование буфера отправки в порт Num = Номер индекса запроса или команды { // Fcode = параметр команды SndCode или CmdCode, read = true - чтение, выполняются запросы Snd или read = false, выполняются команды if (read) { // Тут собраны команды чтения if (Fcode == 0x01 || Fcode == 0x07) // Если код равен F=0x01 - Текущие параметры или F=0x07 - Вес омпульсов { Array.Resize(ref buf_out, 14); // Меняем размер буфера для запроса Текущих параметров и Веса импульсов if (Fcode == 0x01) { maskch = BitConverter.GetBytes(mask_ch); // запись битовой маски Текущих параметров в массив байт Array.Resize(ref buf_in, col * res_ch + 10); // длина ответа 4 * n каналов (или 8 * n каналов) + 10 байт } else if (Fcode == 0x07) { maskch = BitConverter.GetBytes(mask_chv); // запись битовой маски Веса импульсов в массив байт Array.Resize(ref buf_in, 4 * res_chv + 10); // длина ответа 4 * n каналов + 10 байт } Array.Copy(maskch, 0, buf_out, 6, maskch.Length); // Копирование маски в буфер запроса } else if (Fcode == 0x04) // Если код равен F=0x04 - Системное время { Array.Resize(ref buf_out, 10); // Меняем размер буфера для запроса Системного времмени Array.Resize(ref buf_in, 16); // длина ответа 16 байт } else if (Fcode == 0x0A) // Если код равен F=0x0A - Параметры прибора { Array.Resize(ref buf_out, 12); // Меняем размер буфера для запроса Параметров прибора byte[] snddata = ScadaUtils.HexToBytes(devTemplate.SndGroups[Num].SndData, true); // Чтение строки HEX из параметра SndData buf_out[6] = snddata[0]; // требуется 1 байт, код параметра buf_out[7] = 0x00; // второй байт будет со значением 0 Array.Resize(ref buf_in, 18); // длина ответа 18 байт } } else // Тут собраны команды записи { if (Fcode == 0x03 || Fcode == 0x08) // Если код равен F=0x03 – код функции записи текущих показаний { // Или F=0x08 - Вес импульса для Регистраторов импульса Array.Resize(ref buf_out, 0x0E + bData.Length); // Меняем размер буфера для запроса Текущих параметров maskch = Fcode == 0x03 ? BitConverter.GetBytes(mask_ch_wr) : BitConverter.GetBytes(mask_chv_wr); // запись битовой маски редактируемого канала в массив байт Array.Copy(maskch, 0, buf_out, 6, maskch.Length); // Копирование маски в буфер запроса Array.Copy(bData, 0, buf_out, 10, bData.Length); // Копируем значение cmdVal в буфер запроса Array.Resize(ref buf_in, 14); // длина ответа 14 байт } else if (Fcode == 0x05) // Запись времени в прибор { Array.Resize(ref buf_out, 10 + bData.Length); Array.Copy(bData, 0, buf_out, 6, bData.Length); Array.Resize(ref buf_in, 14); // длина ответа 14 байт } else if (Fcode == 0x0B) // Запись параметров в прибор { Array.Resize(ref buf_out, 12 + bData.Length); Array.Copy(bData, 0, buf_out, 8, bData.Length); byte[] cmddata = ScadaUtils.HexToBytes(devTemplate.CmdGroups[Num].CmdData, true); // Чтение строки HEX из параметра SndData buf_out[6] = cmddata[0]; // требуется 1 байт, код параметра buf_out[7] = 0x00; // второй байт будет со значением 0 Array.Resize(ref buf_in, 12); // длина ответа 12 байт } } buf_out[4] = Fcode; // Копируем в буфер код запроса F buf_out[5] = Convert.ToByte(buf_out.Length); // Запись длины массива запроса - параметр L idBCD = BitConverter.GetBytes(ConvFunc.DecToBCD(Address)); // Преобразование адреса в BCD формат ConvFunc.Reverse_array(idBCD, false); // Переворот буфера старшим байтом вперед Array.Copy(idBCD, 0, buf_out, 0, idBCD.Length); // Копирование адреса в буфер запроса byteID = BitConverter.GetBytes((ushort)rnd.Next(1, 65535)); // Сформировать случайный ID запроса buf_out[buf_out.Length - 4] = byteID[0]; buf_out[buf_out.Length - 3] = byteID[1]; crc = CrcFunc.CalcCRC16(buf_out, buf_out.Length - 2); // Рассчет контрольной суммы CRC16 buf_out[buf_out.Length - 2] = (byte)(crc % 256); // Запись младшего байта контрольной суммы в буфер buf_out[buf_out.Length - 1] = (byte)(crc / 256); // Запись старшего байта контрольной суммы в буфер }
public override void SendCmd(Command cmd) { base.SendCmd(cmd); lastCommSucc = false; bool WriteOk = false; // Идентификатор успешной записи mask_ch_wr = 0; // переменная для параметра MASK_CH записи данных каналов (Регистратор импульсов) mask_chv_wr = 0; // Переменная для параметра MASK_CH записи Веса импульсов (Регистратор импульсов) byte cmdCode = 0x00; // переменная для байта запроса CmdCode - параметр F протокола (номера для записи) byte[] byteData = new byte[1]; // Буфер для значения переменной double cmdVal = cmd.CmdVal; int cmdNum = cmd.CmdNum; int cmdCnl = ActiveCmd[cmdNum]; // Чтение индекса команды по ключу из Словаря if (cmd.CmdTypeID == BaseValues.CmdTypes.Standard) { byte[] cmdcode = ScadaUtils.HexToBytes(devTemplate.CmdGroups[cmdCnl].CmdCode, true); // Чтение строки HEX из параметра CmdCode cmdCode = cmdcode[0]; string cmdtype = devTemplate.CmdGroups[cmdCnl].CmdType; // Чтение строки Типа переменной команды // Определив диапазон проверяем к какому из них относятся Текущие параметры и Веса импульса для составления маски if ((cmdNum >= startCnl && cmdNum <= maxch) || (cmdNum >= startCnlv && cmdNum <= maxchv)) { if ((cmdNum >= startCnl && cmdNum <= maxch) && !(cmdNum >= startCnlv && cmdNum <= maxchv)) { mask_ch_wr = BitFunc.SetBit(mask_ch_wr, cmdNum - startCnl, true); // Если каналы относятся к Текущим данным, то формируем маску для записи маски текущих данных } else { mask_chv_wr = BitFunc.SetBit(mask_chv_wr, cmdNum - startCnlv, true); // Иначе для записи маски Весов импульсов } } if (cmdtype == "uint16") { Array.Resize(ref byteData, 2); byteData = BitConverter.GetBytes(Convert.ToUInt16(cmdVal)); } else if (cmdtype == "float") { Array.Resize(ref byteData, 4); byteData = BitConverter.GetBytes(Convert.ToSingle(cmdVal)); } else if (cmdtype == "double") { Array.Resize(ref byteData, 8); byteData = BitConverter.GetBytes(cmdVal); } else if (cmdtype == "DateTime") { Array.Resize(ref byteData, 6); DateTime dateTime = DateTime.FromOADate(cmdVal); byteData[0] = Convert.ToByte(dateTime.Year - 2000); byteData[1] = Convert.ToByte(dateTime.Month); byteData[2] = Convert.ToByte(dateTime.Day); byteData[3] = Convert.ToByte(dateTime.Hour); byteData[4] = Convert.ToByte(dateTime.Minute); byteData[5] = Convert.ToByte(dateTime.Second); } if (cmdCode == 0x0B) { Array.Resize(ref byteData, 8); // Увеличить размер буфера до 8 байт записываемого параметра F=0x0B PARAM_VAL_NEW } Buf_Out(cmdCnl, cmdCode, byteData, false); // отправить в функцию Номер индекса команды управления и Байт запроса Connection.Write(buf_out, 0, buf_out.Length, CommUtils.ProtocolLogFormats.Hex, out logText); //послать запрос в порт ExecWriteToLog(logText); // вывести запрос в Журнал линии связи readcnt = Connection.Read(buf_in, 0, buf_in.Length, ReqParams.Timeout, CommUtils.ProtocolLogFormats.Hex, out logText); //считать значение из порта ExecWriteToLog(logText); // вывести запрос в Журнал линии связи // Проверка выполнения команды прибором - определяется по ответу прибора на запись команды if (readcnt == buf_in.Length || readcnt == 11) { crc = CrcFunc.CalcCRC16(buf_in, readcnt); // Рассчет CRC16 полученного ответа, при совпадении должно вернуть 0 при расчете CRC16(Modbus) и полного буфера вместе с CRC byte fCode = buf_in[4]; // Чтение кода команды F Array.Copy(buf_in, readcnt - 4, byteIDres, 0, 2); if (!(crc == 0 & fCode != 0 & byteID.SequenceEqual(byteIDres))) // Проверка CRC, параметра F и ID запроса { if (crc != 0) { ExecWriteToLog(CommPhrases.ResponseCrcError); } else if (fCode == 0) { string err = Error_code(buf_in[6]); ExecWriteToLog(CommPhrases.IncorrectCmdData + " - " + err); // При некорректном запросе F будет равен 0x00 } else if (!byteID.SequenceEqual(byteIDres)) { ExecWriteToLog("ID ответа не совпадает с ID запроса"); // При несовпадении ID } FinishRequest(); } else { if (fCode == 0x03 || fCode == 0x08) { byte[] maskchRes = new byte[4]; Array.Copy(buf_in, 6, maskchRes, 0, 4); if (maskch.SequenceEqual(maskchRes)) { WriteOk = true; } } if (fCode == 0x05) { if (buf_in[6] != 0) { WriteOk = true; } } if (fCode == 0x0B) { UInt16 Result_WR = BitConverter.ToUInt16(buf_in, 6); if (Result_WR == 0) { WriteOk = true; } } if (WriteOk) { lastCommSucc = true; string nameCnl = ActiveCnl.Find(c => c.Cnl == cmdNum).Name; ExecWriteToLog($"Запись команды {nameCnl} - " + CommPhrases.ResponseOK); } else { ExecWriteToLog(CommPhrases.WriteDataError); } FinishRequest(); } } else { if (readcnt == 0) { ExecWriteToLog(CommPhrases.ResponseError); // Нет ответа по Timeout - Ошибка связи! } else { ExecWriteToLog(CommPhrases.IncorrectResponseLength); // Некорректная длина ответа } FinishRequest(); } } else { WriteToLog(CommPhrases.IllegalCommand); } CalcCmdStats(); }
/// <summary> /// Загрузить из файла команду и проверить её корретность /// </summary> private bool LoadCmdFromFile(string fileName, out string cmdType, out Dictionary <string, string> cmdParams, out Command cmd) { bool result = false; cmdType = ""; cmdParams = null; cmd = null; FileStream fileStream = null; StreamReader streamReader = null; try { // считывание команды из файла string target = ""; DateTime dateTime = DateTime.MinValue; int lifeTime = 0; bool endFound = false; fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); streamReader = new StreamReader(fileStream, Encoding.Default); while (!streamReader.EndOfStream) { string line = streamReader.ReadLine().Trim(); string lineL = line.ToLowerInvariant(); if (cmdParams == null) { if (lineL == "[command]") { cmdParams = new Dictionary <string, string>(); } } else { if (lineL.StartsWith("target=")) { target = lineL.Remove(0, 7); } else if (lineL.StartsWith("datetime=")) { dateTime = DateTime.Parse(lineL.Remove(0, 9), DateTimeFormatInfo.InvariantInfo); } else if (lineL.StartsWith("lifetime=")) { lifeTime = int.Parse(lineL.Remove(0, 9)); } else if (lineL.StartsWith("cmdtype=")) { cmdType = line.Remove(0, 8); int cmdTypeID = BaseValues.CmdTypes.ParseCmdTypeCode(cmdType); if (cmdTypeID >= 0) { cmd = new Command(cmdTypeID); } } else if (lineL.StartsWith("end=")) { endFound = true; } else { int ind = lineL.IndexOf("="); if (ind >= 0) { cmdParams[lineL.Substring(0, ind)] = lineL.Substring(ind + 1); } if (cmd != null) { if (lineL.StartsWith("kpnum=")) { cmd.KPNum = int.Parse(lineL.Remove(0, 6)); } else if (lineL.StartsWith("cmdnum=")) { if (cmd.CmdTypeID != BaseValues.CmdTypes.Request) { cmd.CmdNum = int.Parse(lineL.Remove(0, 7)); } } else if (lineL.StartsWith("cmdval=")) { if (cmd.CmdTypeID == BaseValues.CmdTypes.Standard) { cmd.CmdVal = ScadaUtils.ParseDouble(lineL.Remove(0, 7)); } } else if (lineL.StartsWith("cmddata=")) { if (cmd.CmdTypeID == BaseValues.CmdTypes.Binary) { byte[] cmdData; if (ScadaUtils.HexToBytes(lineL.Remove(0, 8), out cmdData)) { cmd.CmdData = cmdData; } } } } } } } if (cmdParams != null && target == "scadacommsvc" && endFound) { // проверка актуальности команды DateTime nowDT = DateTime.Now; if (nowDT.AddSeconds(-lifeTime) <= dateTime && dateTime <= nowDT.AddSeconds(lifeTime)) { log.WriteAction((Localization.UseRussian ? "Получена команда из файла: " : "The command is received from file: ") + GetCmdShortDescr(cmd)); result = true; } else { log.WriteAction((Localization.UseRussian ? "Получена неактуальная команда из файла: " : "The outdated command is received from file: ") + GetCmdShortDescr(cmd)); } cmdType = cmdType.ToLowerInvariant(); } } catch (ThreadAbortException) { } catch (Exception ex) { log.WriteException(ex, Localization.UseRussian ? "Ошибка при приёме команды из файла {0}" : "Error receiving command from file {0}", Path.GetFileName(fileName)); } finally { if (streamReader != null) { streamReader.Close(); } if (fileStream != null) { fileStream.Close(); } } if (result) { // удаление успешно обработанного файла команды try { File.Delete(fileName); } catch { } return(true); } else { // переименование файла команды, который не был обработан try { File.Move(fileName, fileName + ".err"); } catch { } return(false); } }
public override void OnAddedToCommLine() // Выполняем действия при добавлении Линии связи - Чтение шаблона, создание списка Тегов { base.OnAddedToCommLine(); devTemplate = null; fileName = ReqParams.CmdLine == null ? "" : ReqParams.CmdLine.Trim(); string filePath = AppDirs.ConfigDir + fileName; if (fileName == "") { WriteToLog(string.Format(Localization.UseRussian ? "{0} Ошибка: Не задан шаблон устройства для {1}" : "{0} Error: Template is undefined for the {1}", CommUtils.GetNowDT(), Caption)); } else { try { devTemplate = FileFunc.LoadXml(typeof(DevTemplate), filePath) as DevTemplate; fileyes = true; } catch (Exception err) { WriteToLog(string.Format(Localization.UseRussian ? "Ошибка: " + err.Message : "Error: " + err.Message, CommUtils.GetNowDT(), Caption)); } } // Проверка на наличие конфигурации XML if (devTemplate != null) { // Определить Номера активных запросов, посылку команд проводить согласно списку активных запросов. if (devTemplate.SndGroups.Count != 0) // Определить активные запросы и записать в массив номера запросов для создания тегов по номерам телеграмм // Можно упростить до определения индекса { for (int snd = 0; snd < devTemplate.SndGroups.Count; snd++) { if (devTemplate.SndGroups[snd].SndActive) // Если запрос активен, заносим его номер Cnt в Словарь { if (!ActiveSnd.ContainsKey(devTemplate.SndGroups[snd].SndCnt)) // Ключ = SndCnt - Значение = Индекс Активного запроса SndCnt { ActiveSnd.Add(devTemplate.SndGroups[snd].SndCnt, devTemplate.SndGroups.FindIndex(x => x.SndCnt == devTemplate.SndGroups[snd].SndCnt)); } byte[] sndcode = ScadaUtils.HexToBytes(devTemplate.SndGroups[snd].SndCode, true); // Чтение строки HEX из параметра SndCode sndcode_ = sndcode[0]; if (sndcode_ == 0x01) // Проверяем какой номер запроса у параметра SndCode - F=0x01 Текущие параметры { xValCnt01 = devTemplate.SndGroups[snd].SndCnt; // Сохраняем номер запроса (SndCnt) if (devTemplate.SndGroups[snd].SndData != "") { startCnl = Convert.ToInt32(ScadaUtils.StrToDouble(devTemplate.SndGroups[snd].SndData.Trim())); // Сохранить начальный номер сигнала Текущих параметров } } else if (sndcode_ == 0x07) // Или F=0x07 (Вес импульса для Регистратора импульсов) { xValCnt07 = devTemplate.SndGroups[snd].SndCnt; // Сохраняем номер запроса (SndCnt) if (devTemplate.SndGroups[snd].SndData != "") { startCnlv = Convert.ToInt32(ScadaUtils.StrToDouble(devTemplate.SndGroups[snd].SndData.Trim())); // Сохранить начальный номер сигнала Весов импульсов (Регистратор импульсов) } } activeuse = true; // Есть активные запросы } } } if (devTemplate.CmdGroups.Count != 0) // Определяем наличие активных команд и заносим в словарь Индексов команд { for (int cmd = 0; cmd < devTemplate.CmdGroups.Count; cmd++) { if (devTemplate.CmdGroups[cmd].CmdActive) { if (!ActiveCmd.ContainsKey(devTemplate.CmdGroups[cmd].CmdCnl)) // Ключ = номер команды CmdCnl - Значение = Индекс Активной команды CmdCnl { ActiveCmd.Add(devTemplate.CmdGroups[cmd].CmdCnl, devTemplate.CmdGroups.FindIndex(x => x.CmdCnl == devTemplate.CmdGroups[cmd].CmdCnl)); } } } } if (devTemplate.Values.Count != 0) // Проверка наличия записей переменных в конфигурации { if (activeuse) { // ------------------- Сформировать Список параметров по меню ------------------ for (int ac = 0; ac < ActiveSnd.Count; ac++) { var valCnt_ = devTemplate.Values.FindIndex(x => x.ValCnt == ActiveSnd.ElementAt(ac).Key); for (int val = 0; val < devTemplate.Values[valCnt_].Vals.Count; val++) // МЕНЯЕМ valCnt_ на уже проиндексированный Словарь { if (devTemplate.Values[valCnt_].Vals[val].SigActive) // Проверяем переменную на активность { sigN = devTemplate.Values[valCnt_].Vals[val].SigCnl; // читаем номер сигнала переменной ActiveCnl.Add(new ActiveCnlList() { Cnl = sigN, // Номер текущего активного сигнала Name = devTemplate.Values[valCnt_].Vals[val].SigName, // Имя текущего активного сигнала Format = devTemplate.Values[valCnt_].Vals[val].SigType, // Тип переменной активного сигнала IdxValue = valCnt_, // Индекс группы ответа (ValCnt), в которой находится сигнал MenuName = devTemplate.Values[valCnt_].ValMenu }); // Проверяем номер запроса с параметром SndCode = F=0x01 и создаем маску запросов if (devTemplate.Values[valCnt_].ValCnt == xValCnt01) { // Заносим в маску номер сигнала - startCnl (1 по умолчанию) бит по расположению. mask_ch = BitFunc.SetBit(mask_ch, devTemplate.Values[valCnt_].Vals[val].SigCnl - startCnl, devTemplate.Values[valCnt_].Vals[val].SigActive); //maxch = ActiveCnl.FindLast(s => s.IdxValue == ActiveCnl.Find(d => d.Cnl == sigN).IdxValue).Cnl; // Поиск Максимального номер канала для Текущих параметров } // SigCnl - startCnl (1 по умолчанию) определяет какой бит 32-х разрядного числа выставить в 1 (единицу) if (devTemplate.Values[valCnt_].ValCnt == xValCnt07) { // Заносим в маску номер сигнала - startCnlv (41 по умолчанию) бит по расположению. // Номера сигналов для запроса F=0x07, Вес импульса Регистратора импульсов должны начинаться с 41-ого если не задан в SndData mask_chv = BitFunc.SetBit(mask_chv, devTemplate.Values[valCnt_].Vals[val].SigCnl - startCnlv, devTemplate.Values[valCnt_].Vals[val].SigActive); } // SigCnl - startCnlv (41 по умолчанию) определяет какой бит 32-х разрядного числа выставить в 1 (единицу) } } } // ------------ Создание тегов на основе созданного Списка Активных переменных ------------ List <TagGroup> tagGroups = new List <TagGroup>(); TagGroup tagGroup; var categoryCounts = // Считаем количество Меню и количество переменных в Меню в шаблоне from p in ActiveCnl group p by p.MenuName into g select new { NameMenu = g.Key, counts = g.Count() }; int cnt = 0; foreach (var menu in categoryCounts) { tagGroup = new TagGroup(menu.NameMenu); // Создание меню Тегов var actcnl = ActiveCnl.FindAll(s => s.MenuName == menu.NameMenu).OrderBy(d => d.Cnl); // Сортировка активных каналов по каждому меню foreach (var tags in actcnl) { sigN = ActiveCnl.Find(f => f.Cnl == tags.Cnl).Cnl; tagGroup.KPTags.Add(new KPTag(sigN, ActiveCnl.Find(f => f.Cnl == tags.Cnl).Name)); // Заносим в тег Коммуникатора ActiveCnl.Find(s => s.Cnl == sigN).IdxTag = cnt; // Заносим номер тега Коммуникатора в Список cnt++; // Увеличиваем счетчик тегов } tagGroups.Add(tagGroup); // Добавляем группу тегов } InitKPTags(tagGroups); // Инициализация всех тегов // Определяем диапазон каналов в группах Текущие параметры и Вес импульса if (xValCnt01 != 0) // Если запрос с кодом 0x01 активен, переменная xValCnt01 содержит номер запроса { int idx = devTemplate.SndGroups.FindIndex(f => f.SndCnt == xValCnt01); maxch = ActiveCnl.FindLast(d => d.IdxValue == idx).Cnl; // Максимальный номер канала для Текущих параметров res_ch = BitFunc.CountBit32(mask_ch); // Определяем количество бит = 1 в маске текущих параметров string format = ActiveCnl.Find(d => d.IdxValue == idx).Format; if (format == "float" || format == "uint32") { col = 4; } if (format == "double") { col = 8; } } if (xValCnt07 != 0) // Если запрос с кодом 0x07 активен, переменная xValCnt07 содержит номер запроса { int idx = devTemplate.SndGroups.FindIndex(f => f.SndCnt == xValCnt07); maxchv = ActiveCnl.FindLast(d => d.IdxValue == idx).Cnl; // Максимальный номер канала для Веса импульсов res_chv = BitFunc.CountBit32(mask_chv); // Определяем количество бит = 1 в маске Веса импульсов } } } } }
private void txtSecretKey_Validating(object sender, CancelEventArgs e) { if (connectionOptions != null && secretKeyChanged) { if (ScadaUtils.HexToBytes(txtSecretKey.Text, out byte[] secretKey) &&
// -- incoming publish events -- void OnPublishReceived(PublishPacket packet) { //WriteToLog (Encoding.UTF8.GetString(packet.Message)); //WriteToLog (packet.Topic); string pv = Encoding.UTF8.GetString(packet.Message); Regex reg = new Regex(@"^[-]?\d+[,.]?\d+$"); Regex reg2 = new Regex(@"^[-\d]+$"); if (SubCmds.Count > 0) { bool IsResSendCmd; bool IsSendCmd; foreach (MQTTSubCmd mqttcmd in SubCmds) { if (mqttcmd.TopicName == packet.Topic) { if (mqttcmd.CmdType == "St") { if (reg.IsMatch(pv)) { pv = pv.Replace('.', ','); } mqttcmd.CmdVal = ScadaUtils.StrToDouble(pv); IsSendCmd = RSrv.SendStandardCommand(mqttcmd.IDUser, mqttcmd.NumCnlCtrl, mqttcmd.CmdVal, out IsResSendCmd); break; } if (mqttcmd.CmdType == "BinTxt") { IsSendCmd = RSrv.SendBinaryCommand(mqttcmd.IDUser, mqttcmd.NumCnlCtrl, packet.Message, out IsResSendCmd); break; } if (mqttcmd.CmdType == "BinHex") { byte[] cmdData; bool IsHexToByte = ScadaUtils.HexToBytes(pv.Trim(), out cmdData); if (IsHexToByte) { IsSendCmd = RSrv.SendBinaryCommand(mqttcmd.IDUser, mqttcmd.NumCnlCtrl, cmdData, out IsResSendCmd); } break; } if (mqttcmd.CmdType == "Req") { IsSendCmd = RSrv.SendRequestCommand(mqttcmd.IDUser, mqttcmd.NumCnlCtrl, mqttcmd.KPNum, out IsResSendCmd); break; } } } } if (KPTags.Length > 0) { int tagInd = 0; foreach (KPTag kpt in KPTags) { if (kpt.Name == packet.Topic) { if (reg.IsMatch(pv)) { pv = pv.Replace('.', ','); SetCurData(tagInd, ScadaUtils.StrToDouble(pv), 1); WriteToLog(pv); break; } if (reg2.IsMatch(pv)) { SetCurData(tagInd, ScadaUtils.StrToDouble(pv), 1); WriteToLog(pv); break; } } tagInd++; } } if (packet.QosLevel == MqttQos.ExactlyOnce) { OnQos2PublishReceived(packet); } else { if (packet.QosLevel == MqttQos.AtLeastOnce) { Send(new PubackPacket() { PacketId = packet.PacketId }); } } }
/// <summary> /// Loads the command from the specified file. /// </summary> public bool Load(string fileName, out string errMsg) { try { string[] lines = File.ReadAllLines(fileName, Encoding.UTF8); if (lines.Length >= 2 && lines[0] == "[TeleCommand]" && lines[lines.Length - 1] == "End=") { foreach (string line in lines) { int equalIdx = line.IndexOf('='); if (equalIdx > 0) { string name = line.Substring(0, equalIdx).Trim(); string value = line.Substring(equalIdx + 1).Trim(); switch (name) { case "CommandID": CommandID = long.Parse(value); break; case "CreationTime": CreationTime = DateTime.Parse(value, DateTimeFormatInfo.InvariantInfo); break; case "UserID": UserID = int.Parse(value); break; case "OutCnlNum": OutCnlNum = int.Parse(value); break; case "CmdTypeID": CmdTypeID = int.Parse(value); break; case "ObjNum": ObjNum = int.Parse(value); break; case "DeviceNum": DeviceNum = int.Parse(value); break; case "CmdNum": CmdNum = int.Parse(value); break; case "CmdCode": CmdCode = value; break; case "CmdVal": CmdVal = double.Parse(value, NumberFormatInfo.InvariantInfo); break; case "CmdData": CmdData = ScadaUtils.HexToBytes(value, false, true); break; case "RecursionLevel": RecursionLevel = int.Parse(value); break; } } } errMsg = ""; return(true); } else { errMsg = Locale.IsRussian ? "Ошибка при загрузке команды ТУ: неверный формат файла" : "Error loading telecontrol command: invalid file format"; return(false); } } catch (Exception ex) { errMsg = string.Format(Locale.IsRussian ? "Ошибка при загрузке команды ТУ: " : "Error loading telecontrol command: ") + ex.Message; return(false); } }
/// <summary> /// Loads the command from the specified stream. /// </summary> public void Load(Stream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } List <string> lines = stream.ReadAllLines(); if (lines.Count >= 2 && lines[0] == "[TeleCommand]" && lines[lines.Count - 1] == "End=") { foreach (string line in lines) { int equalIdx = line.IndexOf('='); if (equalIdx > 0) { string name = line.Substring(0, equalIdx).Trim(); string value = line.Substring(equalIdx + 1).Trim(); switch (name) { case "CommandID": CommandID = long.Parse(value); break; case "CreationTime": CreationTime = DateTime.Parse(value, DateTimeFormatInfo.InvariantInfo); break; case "ClientName": ClientName = value; break; case "UserID": UserID = int.Parse(value); break; case "CnlNum": CnlNum = int.Parse(value); break; case "ObjNum": ObjNum = int.Parse(value); break; case "DeviceNum": DeviceNum = int.Parse(value); break; case "CmdNum": CmdNum = int.Parse(value); break; case "CmdCode": CmdCode = value; break; case "CmdVal": CmdVal = double.Parse(value, NumberFormatInfo.InvariantInfo); break; case "CmdData": CmdData = ScadaUtils.HexToBytes(value, false, true); break; case "RecursionLevel": RecursionLevel = int.Parse(value); break; } } } } else { throw new ScadaException(Locale.IsRussian ? "Неверный формат файла." : "Invalid file format."); } }
protected void btnExecute_Click(object sender, EventArgs e) { // проверка пароля if (pnlPassword.Visible) { int roleID; string errMsg; AppData.MainData.CheckUser(UserData.GetUserData().UserLogin, txtPassword.Text, true, out roleID, out errMsg); if (errMsg != "") { lblMessage.Text = string.Format(WebPhrases.ErrorFormat, errMsg); } } // получение и проверка параметров команды int ctrlCnlNum = (int)ViewState["CtrlCnlNum"]; double cmdVal = 0.0; byte[] cmdData = null; View activeView = mvCommand.Visible ? mvCommand.GetActiveView() : null; if (lblMessage.Text == "") { if (activeView == viewStandCmd1) { if (!double.TryParse(rblCmdVal.SelectedValue, out cmdVal)) { lblMessage.Text = string.Format(WebPhrases.ErrorFormat, WebPhrases.CmdNotSelected); } } else if (activeView == viewStandCmd2) { cmdVal = ScadaUtils.StrToDouble(txtCmdVal.Text); if (double.IsNaN(cmdVal)) { lblMessage.Text = string.Format(WebPhrases.ErrorFormat, WebPhrases.IncorrectCmdVal); } } else if (activeView == viewBinCmd) { if (txtCmdData.Text.Length > 0) { if (rbStr.Checked) { cmdData = Encoding.Default.GetBytes(txtCmdData.Text); } else { if (!ScadaUtils.HexToBytes(txtCmdData.Text, out cmdData)) { lblMessage.Text = string.Format(WebPhrases.ErrorFormat, WebPhrases.IncorrectCmdData); } } } else { lblMessage.Text = string.Format(WebPhrases.ErrorFormat, WebPhrases.EmptyCmdData); } } } // отправка команды if (lblMessage.Text == "") { SendCmd(ctrlCnlNum, cmdVal, cmdData); } // отображение сообщения об ошибке if (lblMessage.Text != "") { lblMessage.Visible = true; } }
// Сессия опроса ------------------------------------------------------------------------------------------------------------------------------------ public override void Session() { base.Session(); // Опрос должен происходить согласно активности списка запросов по Словарю ActiveSnd if (!fileyes) // Если конфигурация не была загружена, выставляем все теги в невалидное состояние и выходим { InvalidateCurData(); return; } for (int i = 0; i < ActiveSnd.Count; i++) { int sndCnt_ = ActiveSnd.Values.ElementAt(i); // Выполняем запросы поочередно по индексам из словаря Активных запросов byte[] sndcode = ScadaUtils.HexToBytes(devTemplate.SndGroups[sndCnt_].SndCode, true); // Чтение строки HEX из параметра SndCode sndcode_ = sndcode[0]; // ------------------ Тут вызвать формирование буфера запроса -------------------------------------- Buf_Out(sndCnt_, sndcode_, null, true); // отправить в функцию Номер и Байт запроса if (lastCommSucc) { lastCommSucc = false; int tryNum = 0; // Счетчик для корректных ответов // Выполняем опрос если был загружен файл конфигурации while (RequestNeeded(ref tryNum)) { Connection.Write(buf_out, 0, buf_out.Length, CommUtils.ProtocolLogFormats.Hex, out logText); //послать запрос в порт ExecWriteToLog(logText); // вывести запрос в Журнал линии связи readcnt = Connection.Read(buf_in, 0, buf_in.Length, ReqParams.Timeout, CommUtils.ProtocolLogFormats.Hex, out logText); //считать значение из порта ExecWriteToLog(logText); // вывести запрос в Журнал линии связи // ------------------------------Тут проверка на корректность ответа - ID запроса и CRC ------------------------------------------------------------------- var valCnt_ = devTemplate.Values.FindIndex(x => x.ValCnt == ActiveSnd.ElementAt(i).Key); // Разбираем ответ поочередно по индексам из Списка Активных запросов if (readcnt == buf_in.Length || readcnt == 11) { crc = CrcFunc.CalcCRC16(buf_in, readcnt); // Рассчет CRC16 полученного ответа, при совпадении должно вернуть 0 при расчете CRC16(Modbus) и полного буфера вместе с CRC byte fCode = buf_in[4]; Array.Copy(buf_in, readcnt - 4, byteIDres, 0, 2); if (!(crc == 0 & fCode != 0 & byteID.SequenceEqual(byteIDres))) // Проверка CRC, параметра F и ID запроса { if (crc != 0) { ExecWriteToLog(CommPhrases.ResponseCrcError); } else if (fCode == 0) { string err = Error_code(buf_in[6]); ExecWriteToLog(CommPhrases.IncorrectCmdData + " - " + err); // При некорректном запросе F будет равен 0x00 } else if (!byteID.SequenceEqual(byteIDres)) { ExecWriteToLog("ID ответа не совпадает с ID запроса"); // При несовпадении ID } FinishRequest(); invalidData(valCnt_); // выставить сигналы в невалидное состояние } else { int index_bufin = 6; // Индекс первой переменной в ответе прибора for (int sig = 0; sig < devTemplate.Values[valCnt_].Vals.Count; sig++) // Разбор по количеству переменных Vals в ответе { if (devTemplate.Values[valCnt_].Vals[sig].SigActive) // Если переменная активна, читаем и разбираем ее { string sig_type = devTemplate.Values[valCnt_].Vals[sig].SigType; // читаем тип переменной double range = devTemplate.Values[valCnt_].Vals[sig].Range; // читаем множитель (мало ли, вдруг пригодится) :) int k = ActiveCnl.Find(s => s.Cnl == devTemplate.Values[valCnt_].Vals[sig].SigCnl).IdxTag; // Находим в списке Индекс переменной и Указываем индекс Тега if (sig_type == "float") { SetCurData(k, BitConverter.ToSingle(buf_in, index_bufin) * range, 1); // Конвертируем буфер байт в переменную float } else if (sig_type == "double") { SetCurData(k, BitConverter.ToDouble(buf_in, index_bufin) * range, 1); // Конвертируем буфер байт в переменную double } else if (sig_type == "uint16") { SetCurData(k, BitConverter.ToUInt16(buf_in, index_bufin) * range, 1); // Конвертируем буфер байт в переменную UInt16 } else if (sig_type == "uint32") { SetCurData(k, BitConverter.ToUInt32(buf_in, index_bufin) * range, 1); // Конвертируем буфер байт в переменную UInt32 } else if (sig_type == "DateTime") // Определяем системное время и конвертируем в double для Scada { if (!myTagId.ContainsKey(devTemplate.Values[valCnt_].Vals[sig].SigCnl)) // Указываем номер сигнала для преобразования в текстовую строку { // в окне Данных КП Коммуникатора myTagId.Add(devTemplate.Values[valCnt_].Vals[sig].SigCnl, "DateTime"); } int year = Convert.ToInt32(buf_in[index_bufin]) + 2000; // Читаем из ответа переменные года int month = Convert.ToInt32(buf_in[index_bufin + 1]); // месяца int day = Convert.ToInt32(buf_in[index_bufin + 2]); // дня int hour = Convert.ToInt32(buf_in[index_bufin + 3]); // часа int minute = Convert.ToInt32(buf_in[index_bufin + 4]); // минут int second = Convert.ToInt32(buf_in[index_bufin + 5]); // секунд DateTime dateTime = new DateTime(year, month, day, hour, minute, second); // формируем переменную времени в формате DateTime SetCurData(k, dateTime.ToOADate(), 1); } if (devTemplate.Values[valCnt_].ValCnt == xValCnt01 || devTemplate.Values[valCnt_].ValCnt == xValCnt07) { if (sig_type == "float" || sig_type == "uint32") // Найденная ошибка, не учитывалось увеличение индекса при наличии uint32 переменной { index_bufin = index_bufin + 4; // Увеличиваем индекс переменной для следующего текущего параметра для float } else if (sig_type == "double") { index_bufin = index_bufin + 8; // Увеличиваем индекс переменной для следующего текущего параметра для double } } } } ExecWriteToLog(CommPhrases.ResponseOK); lastCommSucc = true; FinishRequest(); } } else { if (readcnt == 0) { ExecWriteToLog(CommPhrases.ResponseError); // Нет ответа по Timeout - Ошибка связи! } else { ExecWriteToLog(CommPhrases.IncorrectResponseLength); // Некорректная длина ответа } FinishRequest(); invalidData(valCnt_); // выставить сигналы в невалидное состояние } // завершение запроса tryNum++; } } } CalcSessStats(); // расчёт статистики }
// -- incoming publish events -- void OnPublishReceived(PublishPacket packet) { //WriteToLog (Encoding.UTF8.GetString(packet.Message)); //WriteToLog (packet.Topic); string pv = Encoding.UTF8.GetString(packet.Message); Regex reg = new Regex(@"^[-]?\d+[,.]?\d+$"); Regex reg2 = new Regex(@"^[-\d]+$"); if (SubJSs.Count > 0) { Engine jsEng = new Engine(); foreach (MQTTSubJS mqttjs in SubJSs) { if (mqttjs.TopicName == packet.Topic) { SrezTableLight.Srez srez = new SrezTableLight.Srez(DateTime.Now, mqttjs.CnlCnt); List <JSVal> jsvals = new List <JSVal>(); for (int i = 0; i < srez.CnlNums.Length; i++) { JSVal jsval = new JSVal(); jsvals.Add(jsval); } jsEng.SetValue("mqttJS", mqttjs); jsEng.SetValue("InMsg", Encoding.UTF8.GetString(packet.Message)); jsEng.SetValue("jsvals", jsvals); jsEng.SetValue("mylog", new Action <string>(WriteToLog)); bool sndres; try { jsEng.Execute(mqttjs.JSHandler); int i = 0; foreach (JSVal jsvl in jsvals) { SrezTableLight.CnlData cnlData = new SrezTableLight.CnlData(); cnlData.Stat = jsvl.Stat; cnlData.Val = jsvl.Val; srez.CnlNums[i] = jsvl.CnlNum; srez.SetCnlData(jsvl.CnlNum, cnlData); i++; } bool snd = RSrv.SendSrez(srez, out sndres); } catch { WriteToLog(Localization.UseRussian ? "Ошибка обработки JS" : "Error execute JS"); } break; } } } if (SubCmds.Count > 0) { bool IsResSendCmd; bool IsSendCmd; foreach (MQTTSubCmd mqttcmd in SubCmds) { if (mqttcmd.TopicName == packet.Topic) { if (mqttcmd.CmdType == "St") { if (reg.IsMatch(pv)) { pv = pv.Replace('.', ','); } mqttcmd.CmdVal = ScadaUtils.StrToDouble(pv); IsSendCmd = RSrv.SendStandardCommand(mqttcmd.IDUser, mqttcmd.NumCnlCtrl, mqttcmd.CmdVal, out IsResSendCmd); break; } if (mqttcmd.CmdType == "BinTxt") { IsSendCmd = RSrv.SendBinaryCommand(mqttcmd.IDUser, mqttcmd.NumCnlCtrl, packet.Message, out IsResSendCmd); break; } if (mqttcmd.CmdType == "BinHex") { byte[] cmdData; bool IsHexToByte = ScadaUtils.HexToBytes(pv.Trim(), out cmdData); if (IsHexToByte) { IsSendCmd = RSrv.SendBinaryCommand(mqttcmd.IDUser, mqttcmd.NumCnlCtrl, cmdData, out IsResSendCmd); } break; } if (mqttcmd.CmdType == "Req") { IsSendCmd = RSrv.SendRequestCommand(mqttcmd.IDUser, mqttcmd.NumCnlCtrl, mqttcmd.KPNum, out IsResSendCmd); break; } } } } if (KPTags.Length > 0) { int tagInd = 0; foreach (KPTag kpt in KPTags) { if (kpt.Name == packet.Topic) { if (reg.IsMatch(pv)) { pv = pv.Replace('.', ','); SetCurData(tagInd, ScadaUtils.StrToDouble(pv), 1); WriteToLog(pv); break; } if (reg2.IsMatch(pv)) { SetCurData(tagInd, ScadaUtils.StrToDouble(pv), 1); WriteToLog(pv); break; } } tagInd++; } } if (packet.QosLevel == MqttQos.ExactlyOnce) { OnQos2PublishReceived(packet); } else { if (packet.QosLevel == MqttQos.AtLeastOnce) { Send(new PubackPacket() { PacketId = packet.PacketId }); } } }