/// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="parent">TagGroup对象所依赖的Device对象</param>
        /// <param name="node">TagGroup对象属性的Xml节点</param>
        /// <param name="eventTagRegister">西门子Tag注册委托</param>
        public SiemensTagGroup(
            CustomDevice parent,
            XmlNode node,
            TagRegisterHandler eventTagRegister) : base(parent, node)
        {
            if (!(parent is SiemensDevice))
            {
                throw new Exception("parent对象必须是SiemensDevice对象");
            }

            if (node.Name.ToUpper() != "TAGGROUP")
            {
                throw new Exception($"Xml节点[{node.Name}]不是\"TagGroup\"");
            }

            _tagRegisterInParentHandler = eventTagRegister;

            _log    = Logger.Get <SiemensTagGroup>();
            _tags   = new SiemensTagCollection(this, OnTagInGroupRegister);
            _groups = new SiemensSubTagGroupCollection(this);

            _log.Trace($"创建TagGroup[{Name}]");

            #region 创建Tag
            if (node.HasChildNodes)
            {
                SiemensTagCreator creator   = new SiemensTagCreator();
                XmlNode           childNode = node.FirstChild;
                while (childNode != null)
                {
                    string nodeName = childNode.Name.ToUpper();
                    switch (nodeName)
                    {
                    case "TAG":
                        CustomTag tag = creator.CreateProduct(this, childNode);
                        if (tag != null)
                        {
                            _tags.Add(tag);
                        }
                        break;

                    case "SUBTAGGROUP":
                        SiemensSubTagGroup subTagGroup =
                            new SiemensSubTagGroup(
                                this,
                                childNode,
                                OnTagInGroupRegister);
                        if (subTagGroup != null)
                        {
                            _groups.Add(subTagGroup);
                        }
                        break;
                    }

                    childNode = childNode.NextSibling;
                }
            }
            #endregion
        }
        /// <summary>
        /// 根据关键字处理指定TagGroup所对应的数据块数据
        /// </summary>
        private void DealPartBlockBuffer(string key, byte[] buffer)
        {
            PLCDBBlock block = ControlBlock[key];

            if (block != null && key != "COMM")
            {
                _log.Debug(
                    $"[{key}.Offset={block.Start_Offset}, " +
                    $"{key}.Length={block.BufferLength}]");
                _log.Debug($"[{key}]|[Data:{Tools.BytesToBCD(buffer)}]");
            }

            // 根据key解析出TagGroup和SubTagGroup
            string[] keys           = key.Split('.');
            string   keyTagGroup    = keys[0];
            string   keySubTagGroup = "";

            if (keys.Length >= 2)
            {
                keySubTagGroup = keys[1];
            }

            SiemensTagGroup group = _groups[keyTagGroup] as SiemensTagGroup;

            if (group == null)
            {
                _log.Error($"设备[{Name}]未找到[{keyTagGroup}]Tag组");
                return;
            }
            if (keySubTagGroup == "")
            {
                SetControlTagValueInGroup(group, buffer, block.Start_Offset);
            }
            else
            {
                SiemensSubTagGroup subGroup =
                    group.SubGroups[keySubTagGroup] as SiemensSubTagGroup;
                if (subGroup == null)
                {
                    _log.Error($"设备[{Name}]未找到[{keyTagGroup}.{keySubTagGroup}]Tag组");
                    return;
                }
                else
                {
                    SetControlTagValueInGroup(subGroup, buffer, block.Start_Offset);
                }
            }
        }
 /// <summary>
 /// 设置控制Tag值
 /// </summary>
 /// <param name="group">SubTagGroup对象</param>
 /// <param name="buffer">数据块内容</param>
 /// <param name="offset">当前数据块内容在整个数据块的起始偏移量</param>
 private void SetControlTagValueInGroup(
     SiemensSubTagGroup group,
     byte[] buffer,
     int offset)
 {
     foreach (CustomTag tag in group.Tags)
     {
         if (tag.Type == TagType.C)
         {
             if (SetTagValue(buffer, tag, offset))
             {
                 ControlTagValueChanged(tag);
             }
         }
     }
 }
        /// <summary>
        /// Tag对象注册事件
        /// </summary>
        /// <param name="group">TagGroup对象</param>
        /// <param name="tag">Tag对象</param>
        private void OnTagRegister(CustomGroup group, CustomTag tag)
        {
            _log.Trace($"Device[{Name}]:Tag[{tag.Name}],Offset[{tag.DB_Offset}]");

            if (!(tag is SiemensTag))
            {
                throw new Exception($"tag对象:{tag.Name}不是SiemensTag对象");
            }

            SiemensTag siemensTag = tag as SiemensTag;

            switch (CycleReadMode)
            {
            case SiemensCycleReadMode.FullBlock:
                FullBlock.Add(siemensTag.DB_Offset, siemensTag.Length);
                break;

            case SiemensCycleReadMode.ControlBlock:
                if (siemensTag.Type == TagType.C)
                {
                    string key = "";
                    if (group is SiemensTagGroup)
                    {
                        key = (group as SiemensTagGroup).Name;
                    }
                    else if (group is SiemensSubTagGroup)
                    {
                        SiemensSubTagGroup subGroup = group as SiemensSubTagGroup;
                        key = $"{subGroup.Parent.Name}.{subGroup.Prefix}";
                    }

                    PLCDBBlock block = ControlBlock[key];
                    if (block == null)
                    {
                        block = new PLCDBBlock();
                        ControlBlock.Add(key, block);
                    }
                    block.Add(siemensTag.DB_Offset, siemensTag.Length);
                }
                break;
            }
        }
        /// <summary>
        /// 增加SubTagGroup对象
        /// </summary>
        /// <param name="group">SubTagGroup对象</param>
        public override void Add(CustomSubTagGroup group)
        {
            if (!(group is SiemensSubTagGroup))
            {
                throw new Exception("group对象必须是SiemensSubTagGroup对象");
            }

            SiemensSubTagGroup sGroup = group as SiemensSubTagGroup;

            if (sGroup.Parent != _parent)
            {
                throw new Exception("group对象隶属的TagGroup和当前SubTagGroup集合不是同一个TagGroup");
            }

            if (_groups.Keys.Contains(sGroup.Prefix))
            {
                throw new Exception($"当前SubTagGroup集合中已经存在前缀[{sGroup.Prefix}]的SubTagGroup!");
            }

            _groups.Add(sGroup.Prefix, group);
        }