Example #1
0
        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();
        }
Example #2
0
        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 в маске Веса импульсов
                        }
                    }
                }
            }
        }