/// <summary> /// Обновить сигналы КП элементов групп, начиная с заданного узла дерева /// </summary> private void UpdateSignals(TreeNode startGrNode) { // проверка корректности заданного узла дерева if (!(startGrNode.Tag is ElemGroup)) { return; } // определение начального индекса тегов КП TreeNode prevGrNode = startGrNode.PrevNode; ElemGroup prevElemGroup = prevGrNode == null ? null : prevGrNode.Tag as ElemGroup; int tagInd = prevElemGroup == null ? 0 : prevElemGroup.StartKPTagInd + prevElemGroup.Elems.Count; // обновление групп и их элементов int grNodeCnt = grsNode.Nodes.Count; for (int i = startGrNode.Index; i < grNodeCnt; i++) { TreeNode grNode = grsNode.Nodes[i]; ElemGroup elemGroup = grNode.Tag as ElemGroup; int elemSig = tagInd + 1; elemGroup.StartKPTagInd = tagInd; tagInd += elemGroup.Elems.Count; foreach (TreeNode elemNode in grNode.Nodes) { ElemInfo elem = elemNode.Tag as ElemInfo; elem.Signal = elemSig++; } } }
/// <summary> /// Отобразить свойства группы элементов /// </summary> private void ShowElemGroupProps(ElemGroup elemGroup) { numGrAddress.Value = 1; numGrAddress.Minimum = AddrShift; numGrAddress.Maximum = ushort.MaxValue + AddrShift; numGrAddress.Hexadecimal = !DecAddr; ShowFuncCode(elemGroup); if (elemGroup == null) { chkGrActive.Checked = false; txtGrName.Text = ""; cbGrTableType.SelectedIndex = 0; numGrAddress.Value = AddrShift; lblGrAddressHint.Text = ""; numGrElemCnt.Value = 1; gbElemGroup.Enabled = false; } else { chkGrActive.Checked = elemGroup.Active; txtGrName.Text = elemGroup.Name; cbGrTableType.SelectedIndex = (int)elemGroup.TableType; numGrAddress.Value = elemGroup.Address + AddrShift; lblGrAddressHint.Text = string.Format(KpPhrases.AddressHint, AddrNotation, AddrShift); numGrElemCnt.Value = 1; numGrElemCnt.Maximum = elemGroup.MaxElemCnt; numGrElemCnt.Value = elemGroup.Elems.Count; gbElemGroup.Enabled = true; } }
/// <summary> /// Создать узел группы элементов /// </summary> private TreeNode NewElemGroupNode(ElemGroup elemGroup) { string name = elemGroup.Name == "" ? KpPhrases.DefGrName : elemGroup.Name; TreeNode grNode = new TreeNode(name + " (" + ModbusUtils.GetTableTypeName(elemGroup.TableType) + ")"); grNode.ImageKey = grNode.SelectedImageKey = elemGroup.Active ? "group.png" : "group_inactive.png"; grNode.Tag = elemGroup; ushort elemAddr = elemGroup.Address; int elemSig = elemGroup.StartKPTagInd + 1; foreach (Elem elem in elemGroup.Elems) { ElemInfo elemInfo = new ElemInfo() { Elem = elem, ElemGroup = elemGroup, Settings = template.Sett, Address = elemAddr, Signal = elemSig++ }; grNode.Nodes.Add(NewElemNode(elemInfo)); elemAddr += (ushort)elem.Quantity; } return(grNode); }
/// <summary> /// Обновить узлы элементов выбранной группы /// </summary> private void UpdateElemNodes(TreeNode grNode = null) { treeView.BeginUpdate(); if (grNode == null) { grNode = selNode; } if (grNode.Tag is ElemGroup) { ElemGroup elemGroup = (ElemGroup)grNode.Tag; ushort elemAddr = elemGroup.Address; int elemSig = elemGroup.StartKPTagInd + 1; foreach (TreeNode elemNode in grNode.Nodes) { ElemInfo elemInfo = elemNode.Tag as ElemInfo; elemInfo.Address = elemAddr; elemInfo.Signal = elemSig++; elemNode.Text = elemInfo.Caption; elemAddr += (ushort)elemInfo.Elem.Length; } } treeView.EndUpdate(); }
private void btnDelete_Click(object sender, EventArgs e) { if (selElemGroup != null) { // удаление группы элементов template.ElemGroups.Remove(selElemGroup); grsNode.Nodes.Remove(selNode); } else if (selElemInfo != null) { // удаление элемента ElemGroup elemGroup = selElemInfo.ElemGroup; elemGroup.Elems.Remove(selElemInfo.Elem); TreeNode grNode = selNode.Parent; grsNode.Nodes.Remove(selNode); UpdateElemNodes(grNode); UpdateSignals(grNode); ShowElemProps(selElemInfo); } else if (selCmd != null) { // удаление команды template.Cmds.Remove(selCmd); cmdsNode.Nodes.Remove(selNode); } // установка признака изменения Modified = true; }
/// <summary> /// Установить значения тегов КП в соответствии со значениями элементов группы /// </summary> private void SetTagsData(ElemGroup elemGroup) { for (int i = 0, j = elemGroup.StartKPTagInd + i, cnt = elemGroup.Elems.Count; i < cnt; i++, j++) { SetCurData(j, elemGroup.GetElemVal(i), BaseValues.CnlStatuses.Defined); } }
/// <summary> /// Sets the data of the element group tags. /// </summary> private void SetTagData(ElemGroup elemGroup) { for (int elemIdx = 0, tagIdx = elemGroup.StartTagIdx + elemIdx, cnt = elemGroup.Elems.Count; elemIdx < cnt; elemIdx++, tagIdx++) { DeviceData.Set(tagIdx, elemGroup.GetElemVal(elemIdx)); } }
/// <summary> /// Отобразить свойства группы элементов /// </summary> private void ShowElemGroupProps(ElemGroup elemGroup) { ctrlElemGroup.Visible = true; ctrlElemGroup.Settings = template.Sett; ctrlElemGroup.ElemGroup = elemGroup; ctrlElem.Visible = false; ctrlCmd.Visible = false; }
/// <summary> /// Установить значения тегов КП в соответствии со значениями элементов группы /// </summary> private void SetTagsData(ElemGroup elemGroup) { int len = elemGroup.ElemVals.Length; for (int i = 0, j = elemGroup.StartKPTagInd + i; i < len; i++, j++) { SetCurData(j, elemGroup.GetElemVal(i), BaseValues.CnlStatuses.Defined); } }
private void btnMoveDown_Click(object sender, EventArgs e) { // перемещение объекта вниз TreeNode nextNode = selNode.NextNode; int nextInd = nextNode.Index; if (selElemGroup != null) { // перемещение группы элементов вниз ElemGroup nextElemGroup = nextNode.Tag as ElemGroup; template.ElemGroups.RemoveAt(nextInd); template.ElemGroups.Insert(nextInd - 1, nextElemGroup); grsNode.Nodes.RemoveAt(nextInd); grsNode.Nodes.Insert(nextInd - 1, nextNode); UpdateSignals(nextNode); } else if (selElemInfo != null) { // перемещение элемента вниз ElemInfo nextElemInfo = nextNode.Tag as ElemInfo; selElemInfo.ElemGroup.Elems.RemoveAt(nextInd); selElemInfo.ElemGroup.Elems.Insert(nextInd - 1, nextElemInfo.Elem); TreeNode grNode = selNode.Parent; grNode.Nodes.RemoveAt(nextInd); grNode.Nodes.Insert(nextInd - 1, nextNode); UpdateElemNodes(grNode); ShowElemProps(selElemInfo); } else if (selCmd != null) { // перемещение команды вниз ModbusCmd nextCmd = nextNode.Tag as ModbusCmd; template.Cmds.RemoveAt(nextInd); template.Cmds.Insert(nextInd - 1, nextCmd); cmdsNode.Nodes.RemoveAt(nextInd); cmdsNode.Nodes.Insert(nextInd - 1, nextNode); } // установка доступности кнопок btnMoveUp.Enabled = selNode.PrevNode != null; btnMoveDown.Enabled = selNode.NextNode != null; // установка признака изменения Modified = true; }
private TreeNode cmdsNode; // узел дерева "Команды" /// <summary> /// Конструктор, ограничивающий создание формы без параметров /// </summary> private FrmDevTemplate() { InitializeComponent(); appDirs = null; initialFileName = ""; fileName = ""; saveOnly = false; template = null; modified = false; selElemGroup = null; selElemInfo = null; selCmd = null; selNode = null; grsNode = treeView.Nodes["grsNode"]; cmdsNode = treeView.Nodes["cmdsNode"]; }
private void treeView_AfterSelect(object sender, TreeViewEventArgs e) { // отображение выбранного объекта и его свойств selNode = e.Node; object tag = selNode.Tag; selElemGroup = tag as ElemGroup; selElemInfo = tag as ElemInfo; selCmd = tag as ModbusCmd; if (selElemGroup != null) { ShowElemGroupProps(selElemGroup); } else if (selElemInfo != null) { ShowElemProps(selElemInfo); } else if (selCmd != null) { ShowCmdProps(selCmd); } else if (selNode == grsNode) { ShowElemGroupProps(null); } else if (selNode == cmdsNode) { ShowCmdProps(null); } else // не выполняется { DisableProps(); } // установка доступности кнопок btnAddElem.Enabled = selElemGroup != null || selElemInfo != null; bool nodeIsOk = selElemGroup != null || selCmd != null || selElemInfo != null && selElemInfo.ElemGroup.Elems.Count > 1 /*последний не удалять*/; btnMoveUp.Enabled = nodeIsOk && selNode.PrevNode != null; btnMoveDown.Enabled = nodeIsOk && selNode.NextNode != null; btnDelete.Enabled = nodeIsOk; }
private void btnAddElemGroup_Click(object sender, EventArgs e) { // создание группы элементов и добавление в шаблон устройства ElemGroup elemGroup = template.CreateElemGroup(TableType.DiscreteInputs); elemGroup.Elems.Add(elemGroup.CreateElem()); int ind = selNode != null && selNode.Tag is ElemGroup ? selNode.Index + 1 : template.ElemGroups.Count; template.ElemGroups.Insert(ind, elemGroup); // создание узла дерева группы элементов TreeNode grNode = NewElemGroupNode(elemGroup); grsNode.Nodes.Insert(ind, grNode); UpdateSignals(grNode); grNode.Expand(); treeView.SelectedNode = grNode; ctrlElemGroup.SetFocus(); // установка признака изменения Modified = true; }
private void btnAddElem_Click(object sender, EventArgs e) { // создание элемента и добавление в шаблон устройства ElemGroup elemGroup = selElemGroup == null ? selElemInfo.ElemGroup : selElemGroup; int maxElemCnt = DataUnit.GetMaxElemCnt(elemGroup.TableType); if (elemGroup.Elems.Count >= maxElemCnt) { MessageBox.Show(string.Format(KpPhrases.ElemCntExceeded, maxElemCnt), CommonPhrases.WarningCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } ElemInfo elemInfo = new ElemInfo(); elemInfo.Elem = new Elem() { ElemType = elemGroup.DefElemType }; elemInfo.ElemGroup = elemGroup; elemInfo.Settings = template.Sett; int ind = selNode.Tag is ElemInfo ? selNode.Index + 1 : elemGroup.Elems.Count; elemGroup.Elems.Insert(ind, elemInfo.Elem); // создание узла дерева элемента TreeNode elemNode = NewElemNode(elemInfo); TreeNode grNode = selNode.Tag is ElemInfo ? selNode.Parent : selNode; grNode.Nodes.Insert(ind, elemNode); UpdateElemNodes(grNode); UpdateSignals(grNode); treeView.SelectedNode = elemNode; ctrlElem.SetFocus(); // установка признака изменения Modified = true; }
/// <summary> /// Заполнить дерево в соответствии с шаблоном устройства /// </summary> private void FillTree() { // обнуление выбранных объектов и снятие признака изменения selElemGroup = null; selElemInfo = null; selCmd = null; selNode = null; ShowElemGroupProps(null); Modified = false; // приостановка отрисовки дерева treeView.BeginUpdate(); // очистка дерева grsNode.Nodes.Clear(); cmdsNode.Nodes.Clear(); treeView.SelectedNode = grsNode; // заполнение узла групп элементов foreach (ElemGroup elemGroup in template.ElemGroups) { grsNode.Nodes.Add(NewElemGroupNode(elemGroup)); } // заполнение узла команд foreach (ModbusCmd modbusCmd in template.Cmds) { cmdsNode.Nodes.Add(NewCmdNode(modbusCmd)); } // раскрытие основных узлов дерева grsNode.Expand(); cmdsNode.Expand(); // возобновление отрисовки дерева treeView.EndUpdate(); }
/// <summary> /// Отобразить код функции группы элементов /// </summary> private void ShowFuncCode(ElemGroup elemGroup) { txtGrFuncCode.Text = elemGroup == null ? "" : string.Format("{0} ({1}H)", elemGroup.FuncCode, elemGroup.FuncCode.ToString("X2")); }
/// <summary> /// Выполнить сеанс опроса КП /// </summary> public override void Session() { base.Session(); if (deviceTemplate == null) { WriteToLog(Localization.UseRussian ? "Нормальное взаимодействие с КП невозможно, т.к. шаблон устройства не загружен" : "Normal device communication is impossible because device template has not been loaded"); Thread.Sleep(ReqParams.Delay); lastCommSucc = false; } else if (elemGroupCnt > 0) { // выполнение запросов по группам элементов int elemGroupInd = 0; while (elemGroupInd < elemGroupCnt && lastCommSucc) { ElemGroup elemGroup = elemGroups[elemGroupInd]; lastCommSucc = false; int tryNum = 0; while (RequestNeeded(ref tryNum)) { // выполнение запроса if (request(elemGroup)) { lastCommSucc = true; SetTagsData(elemGroup); // установка значений тегов КП } // завершение запроса FinishRequest(); tryNum++; } if (lastCommSucc) { // переход к следующей группе элементов elemGroupInd++; } else if (tryNum > 0) { // установка неопределённого статуса тегов КП текущей и следующих групп, если запрос неудачный while (elemGroupInd < elemGroupCnt) { elemGroup = elemGroups[elemGroupInd]; InvalidateCurData(elemGroup.StartKPTagInd, elemGroup.ElemVals.Length); elemGroupInd++; } } } } else { WriteToLog(Localization.UseRussian ? "Отсутствуют элементы для запроса" : "No elements for request"); Thread.Sleep(ReqParams.Delay); } // расчёт статистики CalcSessStats(); }
/// <summary> /// Конструктор /// </summary> public CtrlElemGroup() { InitializeComponent(); elemGroup = null; Settings = null; }
/// <summary> /// Initializes the device tags. /// </summary> public override void InitDeviceTags() { DeviceTemplate deviceTemplate = GetDeviceTemplate(); if (deviceTemplate == null) { return; } // create device model deviceModel = CreateDeviceModel(); deviceModel.Addr = (byte)NumAddress; // add model elements and device tags foreach (ElemGroupConfig elemGroupConfig in deviceTemplate.ElemGroups) { bool groupActive = elemGroupConfig.Active; bool groupCommands = groupActive && elemGroupConfig.ReadOnlyEnabled; ElemGroup elemGroup = null; TagGroup tagGroup = new TagGroup(elemGroupConfig.Name) { Hidden = !groupActive }; int elemIndex = 0; if (groupActive) { elemGroup = deviceModel.CreateElemGroup(elemGroupConfig.DataBlock); elemGroup.Name = elemGroupConfig.Name; elemGroup.Address = (ushort)elemGroupConfig.Address; elemGroup.StartTagIdx = DeviceTags.Count; } foreach (ElemConfig elemConfig in elemGroupConfig.Elems) { // add model element if (groupActive) { Elem elem = elemGroup.CreateElem(); elem.Name = elemConfig.Name; elem.ElemType = elemConfig.ElemType; elem.ByteOrder = ModbusUtils.ParseByteOrder(elemConfig.ByteOrder) ?? deviceTemplate.Options.GetDefaultByteOrder(ModbusUtils.GetDataLength(elemConfig.ElemType)); elemGroup.Elems.Add(elem); } // add model command if (groupCommands && !elemConfig.ReadOnly && !string.IsNullOrEmpty(elemConfig.TagCode)) { deviceModel.Cmds.Add( CreateModbusCmd(deviceTemplate.Options, elemGroupConfig, elemConfig, elemIndex)); } // add device tag tagGroup.AddTag(elemConfig.TagCode, elemConfig.Name).SetFormat(GetTagFormat(elemConfig)); elemIndex++; } if (groupActive) { elemGroup.InitReqPDU(); elemGroup.InitReqADU(deviceModel.Addr, transMode); deviceModel.ElemGroups.Add(elemGroup); } DeviceTags.AddGroup(tagGroup); } // add model commands foreach (CmdConfig cmdConfig in deviceTemplate.Cmds) { deviceModel.Cmds.Add(CreateModbusCmd(deviceTemplate.Options, cmdConfig)); } deviceModel.InitCmdMap(); CanSendCommands = deviceModel.Cmds.Count > 0; InitModbusPoll(); }
/// <summary> /// Performs a communication session. /// </summary> public override void Session() { base.Session(); if (deviceModel == null) { Log.WriteLine(Locale.IsRussian ? "Невозможно опросить устройство, потому что модель устройства не определена" : "Unable to poll the device because device model is undefined"); SleepPollingDelay(); LastRequestOK = false; } else if (deviceModel.ElemGroups.Count > 0) { // request element groups int elemGroupCnt = deviceModel.ElemGroups.Count; int elemGroupIdx = 0; while (elemGroupIdx < elemGroupCnt && LastRequestOK) { ElemGroup elemGroup = deviceModel.ElemGroups[elemGroupIdx]; LastRequestOK = false; int tryNum = 0; while (RequestNeeded(ref tryNum)) { // perform request if (modbusPoll.DoRequest(elemGroup)) { LastRequestOK = true; SetTagData(elemGroup); } FinishRequest(); tryNum++; } if (LastRequestOK) { // next element group elemGroupIdx++; } else if (tryNum > 0) { // set tag data as undefined for the current and the next element groups while (elemGroupIdx < elemGroupCnt) { elemGroup = deviceModel.ElemGroups[elemGroupIdx]; DeviceData.Invalidate(elemGroup.StartTagIdx, elemGroup.Elems.Count); elemGroupIdx++; } } } } else { Log.WriteLine(Locale.IsRussian ? "Отсутствуют элементы для запроса" : "No elements to request"); SleepPollingDelay(); } FinishSession(); }
/// <summary> /// Копировать модель устройства из заданной /// </summary> public void CopyFrom(DeviceModel srcDeviceModel) { if (srcDeviceModel == null) throw new ArgumentNullException("srcDeviceModel"); // очистка списков групп элементов и команд ElemGroups.Clear(); Cmds.Clear(); // копирование групп элементов foreach (ElemGroup srcGroup in srcDeviceModel.ElemGroups) { ElemGroup elemGroup = new ElemGroup(srcGroup.TableType) { Address = srcGroup.Address, Name = srcGroup.Name, StartKPTagInd = srcGroup.StartKPTagInd, StartSignal = srcGroup.StartSignal, }; foreach (Elem srcElem in srcGroup.Elems) { elemGroup.Elems.Add(new Elem() { Name = srcElem.Name, ElemType = srcElem.ElemType }); } ElemGroups.Add(elemGroup); } // копирование команд foreach (Cmd srcCmd in srcDeviceModel.Cmds) { Cmds.Add(new Cmd(srcCmd.TableType) { Multiple = srcCmd.Multiple, ElemCnt = srcCmd.ElemCnt, Address = srcCmd.Address, Name = srcCmd.Name, CmdNum = srcCmd.CmdNum }); } }
/// <summary> /// Загрузить шаблон устройства /// </summary> public bool LoadTemplate(string fileName, out string errMsg) { try { // очистка списков групп элементов и команд ElemGroups.Clear(); Cmds.Clear(); // загрузка шаблона устройства XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(fileName); // загрузка групп элементов XmlNode elemGroupsNode = xmlDoc.DocumentElement.SelectSingleNode("ElemGroups"); if (elemGroupsNode != null) { int kpTagInd = 0; foreach (XmlElement elemGroupElem in elemGroupsNode.ChildNodes) { TableTypes tableType = (TableTypes)(Enum.Parse(typeof(TableTypes), elemGroupElem.GetAttribute("tableType"), true)); ElemGroup elemGroup = new ElemGroup(tableType); elemGroup.Address = ushort.Parse(elemGroupElem.GetAttribute("address")); elemGroup.Name = elemGroupElem.GetAttribute("name"); elemGroup.StartKPTagInd = kpTagInd; elemGroup.StartSignal = kpTagInd + 1; XmlNodeList elemNodes = elemGroupElem.SelectNodes("Elem"); foreach (XmlElement elemElem in elemNodes) { Elem elem = new Elem(); elem.Name = elemElem.GetAttribute("name"); string elemTypeStr = elemElem.GetAttribute("type"); elem.ElemType = elemTypeStr == "" ? elemGroup.DefElemType : (ElemTypes)(Enum.Parse(typeof(ElemTypes), elemTypeStr, true)); elem.InitByteOrder(elemElem.GetAttribute("byteOrder")); elemGroup.Elems.Add(elem); } if (0 < elemGroup.Elems.Count && elemGroup.Elems.Count <= ElemGroup.GetMaxElemCnt(tableType)) { ElemGroups.Add(elemGroup); kpTagInd += elemGroup.Elems.Count; } } } // загрузка команд XmlNode cmdsNode = xmlDoc.DocumentElement.SelectSingleNode("Cmds"); if (cmdsNode != null) { foreach (XmlElement cmdElem in cmdsNode.ChildNodes) { TableTypes tableType = (TableTypes)(Enum.Parse(typeof(TableTypes), cmdElem.GetAttribute("tableType"), true)); string multiple = cmdElem.GetAttribute("multiple"); string elemCnt = cmdElem.GetAttribute("elemCnt"); Cmd cmd = multiple == "" || elemCnt == "" ? new Cmd(tableType) : new Cmd(tableType, bool.Parse(multiple), int.Parse(elemCnt)); cmd.Address = ushort.Parse(cmdElem.GetAttribute("address")); cmd.Name = cmdElem.GetAttribute("name"); cmd.CmdNum = int.Parse(cmdElem.GetAttribute("cmdNum")); if (0 < cmd.CmdNum && cmd.CmdNum <= ushort.MaxValue) Cmds.Add(cmd); } } errMsg = ""; return true; } catch (Exception ex) { errMsg = Phrases.LoadTemplateError + ":" + Environment.NewLine + ex.Message; return false; } }