Imports System.Net Imports BLV_Studio.GridModel Imports BLV_Studio.GridModel.DeviceEventModel Public Class RowNodeCompile ''' 输出信息打印 Public Event OutputPrint(sender As Object, e As OutputPrintEventArgs) Public _rootNode As RowNode Public _configInfo As ConfigInfoStuct ''' ''' 场景编号,从1开始 ''' Public _sceneIndex As UShort ''' ''' 动作编号,从1开始 ''' Public _actionIndex As UShort ''' ''' 便于索引的动作编号 ''' Private _tempActionIndex As UShort ''' ''' 事件键值对,用于保存事件编号和对应的节点 ''' Public _eventRowNode As Dictionary(Of UShort, RowNode) ''' ''' 节点集合,表明该设备在哪些地方产生了调用 ''' Public _objectWhereUsed As Dictionary(Of String, List(Of RowNode)) ''' ''' 节点集合,表明该动作组被哪些地方调用 ''' Public _actionGroupWhereUsed As Dictionary(Of String, List(Of RowNode)) ''' ''' 节点集合,表明该场景被哪些地方调用 ''' Public _contexualGroupsWhereUsed As Dictionary(Of String, List(Of RowNode)) ''' ''' 所有已配置词条的小宝的集合 ''' Public _xiaobaoUsed As List(Of RowNode) ''' ''' 动作组集合,键为动作组别名,键位动作组节点 ''' Public _actionGroups As Dictionary(Of String, RowNode) ''' ''' 模型集合,键为设备对象别名,键为模型节点 ''' Public _modelGroups As Dictionary(Of String, RowNode) ''' ''' 模型集合,键为设备对象行号,键为模型节点 ''' Public _modelGroups2 As Dictionary(Of Integer, RowNode) ''' ''' 设备对象集合,键为设备对象别名,键为设备对象节点 ''' Public _objectGroups As Dictionary(Of String, RowNode) ''' ''' 场景模式集合,键为设备对象别名,键为设备对象节点 ''' Public _contextualGroups As Dictionary(Of String, RowNode) ''' ''' 所有设备对象的集合 ''' Public _objectLst As List(Of RowNode) ''' ''' 所有非设备事件的自定义场景集合 ''' Public _contexualLst As List(Of RowNode) ''' ''' 所有设备存在的集合 ''' Public _deviceExists As List(Of RowNode) ''' ''' 所有小宝的集合 ''' Public _xiaobao As List(Of RowNode) ''' ''' RCU模型节点 ''' Public _modelNode As RowNode ''' ''' 别名转换所使用的编码格式,默认方式GBK ''' Public Property AliasEncoding As Text.Encoding ''' ''' 单条数据帧,最大动作数量,默认80 ''' Public Property MaxActionCount As Integer ''' ''' 键为场景别名,值为场景编号 ''' g Private _dicScese As Dictionary(Of String, UShort) ''' ''' 键为场景编号,值为场景别名与设备动作编号 ''' Private _lstScese As Dictionary(Of UShort, tmpClass) Public Class tmpClass Public rowNode As RowNode Public AliasName As String Public Actions As New List(Of UShort) Sub New(name As String, node As RowNode) AliasName = name rowNode = node End Sub Public Function GetActionNums() As Byte() Dim lst As New List(Of Byte) For Each num As UShort In Actions lst.AddRange(BitConverter.GetBytes(num)) Next Return lst.ToArray End Function End Class Sub New(root As RowNode) _rootNode = root '根节点 _sceneIndex = 1 _actionIndex = 1 _tempActionIndex = 1 _actionGroups = New Dictionary(Of String, RowNode) _modelGroups = New Dictionary(Of String, RowNode) _modelGroups2 = New Dictionary(Of Integer, RowNode) _objectGroups = New Dictionary(Of String, RowNode) _contextualGroups = New Dictionary(Of String, RowNode) _objectWhereUsed = New Dictionary(Of String, List(Of RowNode)) _actionGroupWhereUsed = New Dictionary(Of String, List(Of RowNode)) _contexualGroupsWhereUsed = New Dictionary(Of String, List(Of RowNode)) _eventRowNode = New Dictionary(Of UShort, RowNode) _objectLst = New List(Of RowNode) _deviceExists = New List(Of RowNode) _xiaobao = New List(Of RowNode) _xiaobaoUsed = New List(Of RowNode) _contexualLst = New List(Of RowNode) AliasEncoding = Text.Encoding.GetEncoding("GBK") MaxActionCount = 80 _dicScese = New Dictionary(Of String, UShort) _lstScese = New Dictionary(Of UShort, tmpClass) End Sub #Region "输出打印" ''' ''' 输出对应类型信息 ''' ''' ''' Private Sub Print(type As OutputPrintEventArgs.Types, txt As String) RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(type, txt)) End Sub ''' ''' 输出执行信息 ''' ''' Private Sub PrintInfo(txt As String) RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(OutputPrintEventArgs.Types.Info, txt)) End Sub ''' ''' 输出警告信息 ''' ''' Private Sub PrintWarning(txt As String) RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(OutputPrintEventArgs.Types.Warn, txt)) End Sub ''' ''' 输出错误信息 ''' ''' Private Sub PrintError(txt As String) RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(OutputPrintEventArgs.Types.Error, txt)) End Sub #End Region ''' ''' 填充编译所需要的必要索引信息 ''' Public Sub FillActionGroups() _objectLst.Clear() _actionGroups.Clear() _modelGroups.Clear() _modelGroups2.Clear() _objectGroups.Clear() _contextualGroups.Clear() _deviceExists.Clear() _xiaobao.Clear() _objectWhereUsed.Clear() _actionGroupWhereUsed.Clear() _contexualGroupsWhereUsed.Clear() _xiaobaoUsed.Clear() _contexualLst.Clear() _eventRowNode.Clear() Dim tmpStr As String = 0 Try For Each node As RowNode In _rootNode.RowList tmpStr = " 行号: " & node.RowListIndex & vbCrLf & " 节点: " & node.Text & vbCrLf & " 别名: " & node.DeviceAlias & vbCrLf '填充编译所需节点内容 Select Case node.RowType Case RowNode.RowTypeEnum.Model _modelNode = node _deviceExists.Add(node) Case RowNode.RowTypeEnum.DeviceObject _objectLst.Add(node) _modelGroups2.Add(node.RowListIndex, node.ParentNode.ParentNode) Case RowNode.RowTypeEnum.ExternalModel _deviceExists.Add(node) Case RowNode.RowTypeEnum.ModelAttributes_DeviceExists _deviceExists.Add(node) Case RowNode.RowTypeEnum.ModelAttributes_XiaoBaoCMD _xiaobao.Add(node) Case RowNode.RowTypeEnum.ModelAttribute_XiaoBaoCMD If String.IsNullOrEmpty(node.DeviceType) OrElse String.IsNullOrEmpty(node.DeviceName) Then Else _xiaobaoUsed.Add(node) End If Case RowNode.RowTypeEnum.ContextualModel '场景模式 _contexualLst.Add(node) End Select '根据别名索引 If String.IsNullOrEmpty(node.DeviceAlias) Then Continue For Select Case node.RowType Case RowNode.RowTypeEnum.DeviceObject '设备对象 _objectGroups.Add(node.DeviceAlias, node) _modelGroups.Add(node.DeviceAlias, node.ParentNode.ParentNode) Case RowNode.RowTypeEnum.DeviceEventActions '设备动作组 _actionGroups.Add(node.DeviceAlias, node) Case RowNode.RowTypeEnum.DeviceEvent '设备事件 _contextualGroups.Add(node.DeviceAlias, node) _modelGroups.Add(node.DeviceAlias, _modelNode) Case RowNode.RowTypeEnum.ContextualModel '场景模式 _contextualGroups.Add(node.DeviceAlias, node) _modelGroups.Add(node.DeviceAlias, _modelNode) End Select Next ''增加动作组调用列表 If _actionGroups.Count > 0 Then For Each tmpStrKey As String In _actionGroups.Keys Dim keyObject As RowNode = _actionGroups(tmpStrKey) '键对应的rownode Dim tmpNodeList As New List(Of RowNode) '新建一个list对象用于保存调用列表’ tmpNodeList.Clear() For Each node As RowNode In _rootNode.RowList '如果 DeviceType 和 DeviceName都相同,就加入列表’ If node.DeviceType = keyObject.DeviceType AndAlso node.DeviceName = tmpStrKey Then tmpNodeList.Add(node) End If Next _actionGroupWhereUsed.Add(tmpStrKey, tmpNodeList) Next End If '增加场景调动列表 If _contextualGroups.Count > 0 Then For Each tmpStrKey As String In _contextualGroups.Keys Dim keyObject As RowNode = _contextualGroups(tmpStrKey) '键对应的rownode Dim tmpNodeList As New List(Of RowNode) '新建一个list对象用于保存调用列表’ tmpNodeList.Clear() For Each node As RowNode In _rootNode.RowList '如果 DeviceName 相同,就加入列表’ If node.DeviceName = tmpStrKey Then tmpNodeList.Add(node) End If Next _contexualGroupsWhereUsed.Add(tmpStrKey, tmpNodeList) Next End If '增加别名调用列表 If _objectGroups.Count > 0 Then For Each tmpStrKey As String In _objectGroups.Keys Dim keyObject As RowNode = _objectGroups(tmpStrKey) '键对应的rownode Dim tmpNodeList As New List(Of RowNode) '新建一个list对象用于保存调用列表’ tmpNodeList.Clear() For Each node As RowNode In _rootNode.RowList '如果 DeviceType 和 DeviceName都相同,就加入列表’ If node.DeviceType = keyObject.DeviceType AndAlso node.DeviceName = tmpStrKey Then tmpNodeList.Add(node) End If Next _objectWhereUsed.Add(tmpStrKey, tmpNodeList) Next End If Catch ex As Exception MsgBox(ex.Message & vbCrLf & vbCrLf & tmpStr) End Try End Sub ''' ''' 编译 ''' Public Function Complie(ByRef argEffMsg As String, ByVal configInfo As ConfigInfoStuct, ByRef tsp As ToolStripProgressBar, datPath As String, Optional ByVal dic As List(Of Dictionary(Of String, String)) = Nothing) As Boolean PrintInfo("开始编译") '传递配置信息,这些信息将会保存在0x01数据块 _configInfo = configInfo '编译错误消息 argEffMsg = "" '获取基础数据 FillActionGroups() If _modelNode Is Nothing Then Throw New Exception("请选择模型后重试") _sceneIndex = 1 _actionIndex = 1 _dicScese.Clear() _lstScese.Clear() _eventRowNode.Clear() Dim lst As New List(Of Byte()) '编译配置信息 Momo 2020-05-14 Dim configInfoLst As New List(Of Byte()) Dim tmpInfo() As Byte = FillConfigInfo().ToArray configInfoLst.Add(tmpInfo) lst.AddRange(configInfoLst.ToArray) PrintInfo("配置信息编译完成,长度:" & tmpInfo.Count & " Bytes") '编译全局属性 '编译设备存在 Dim deviceExistsDatas As List(Of Byte()) Dim OutDevlist As New List(Of Byte) deviceExistsDatas = FillDeviceExistsData(dic) lst.AddRange(deviceExistsDatas.ToArray) '获取编译的设备动作 Dim actionDatas As New List(Of Byte()) actionDatas.AddRange(FillDeviceObject(tsp)) '编译设备对象动作数据 actionDatas.AddRange(FillSceneModel) '编译场景动作数据 lst.AddRange(actionDatas.ToArray) '编译小宝数据 Dim xiaobaoDatas As List(Of Byte()) xiaobaoDatas = FillXiaobaoData() lst.AddRange(xiaobaoDatas.ToArray) '编译场景信息 Dim SceneDatas As List(Of Byte()) SceneDatas = FillSceneData() lst.AddRange(SceneDatas.ToArray) '填充数据帧 Dim frames As List(Of Byte()) = FillDataFrames(lst) '生成Bin文件 Dim path As String = datPath.Replace(".xml", ".dat") 'Dim devpath As String = datPath.Replace(".xml", "_dev.dat") If IO.File.Exists(path) Then IO.File.Delete(path) Using steam As New IO.FileStream(path, IO.FileMode.OpenOrCreate) For Each frame As Byte() In frames steam.Write(frame, 0, frame.Length) Console.WriteLine($"Length:{frame.Length:D4} Data:{BitConverter.ToString(frame).Replace("-", " ")}") Next steam.Flush() steam.Close() End Using Dim filebuff() As Byte = IO.File.ReadAllBytes(path) Dim ismod As Integer = filebuff.Length Mod 4 Dim buff As New List(Of Byte) buff.AddRange(filebuff) For isnum As Integer = 1 To (4 - ismod) buff.Add(0) Next IO.File.WriteAllBytes(path, buff.ToArray) 'IO.File.WriteAllBytes(devpath, OutDevlist.ToArray) 'PrintWarning("编译警告") 'PrintError("编译错误") PrintInfo("编译完成") PrintInfo("事件键值对:") For Each key As UShort In _eventRowNode.Keys Dim tmpRode As RowNode = _eventRowNode(key) Dim tmpString As String = " 事件编号:" & key & " ,行号:" & tmpRode.RowListIndex & " ,事件名称:" & tmpRode.Text & " ,事件别名:" & tmpRode.DeviceAlias PrintInfo(tmpString) Next PrintInfo("") PrintInfo("") PrintInfo("场景键值对:") For Each key As UShort In _lstScese.Keys Dim tmpRode As RowNode = _lstScese(key).rowNode Dim tmpString As String = " 场景编号:" & key & " ,行号:" & tmpRode.RowListIndex & " ,场景名称:" & tmpRode.Text & " ,场景别名:" & tmpRode.DeviceAlias PrintInfo(tmpString) Next Return True End Function ''' ''' 下载 ''' Public Sub Download() End Sub ''' ''' 规则检测 ''' Public Sub RuleCheck() End Sub ''' ''' 填充数据帧 ''' ''' 包含帧类型和帧参数 ''' Private Function FillDataFrames(data As List(Of Byte())) As List(Of Byte()) Dim result As New List(Of Byte()) Dim index As Short = 1 Dim count As Short = data.Count Dim frameBuf As List(Of Byte) Dim num As Integer = 0 For Each buf As Byte() In data num = num + buf.Length frameBuf = New List(Of Byte) '包头(2位) frameBuf.Add(&HCC) frameBuf.Add(&HC0) '长度(2位) Dim length As Short = buf.Length + 10 frameBuf.AddRange(BitConverter.GetBytes(length)) 'CRC校验(2位) frameBuf.AddRange(New Byte() {0, 0}) '帧号(2位) frameBuf.AddRange(BitConverter.GetBytes(index)) '帧总数(2位) frameBuf.AddRange(BitConverter.GetBytes(count)) ''帧类型(1位) 'frameBuf.Add(type) '帧参数(不定长) frameBuf.AddRange(buf) Dim crc() As Byte = GetCRC16CheckSum(frameBuf.ToArray, frameBuf.Count) frameBuf(4) = crc(0) frameBuf(5) = crc(1) index += 1 result.Add(frameBuf.ToArray) Next 'Dim themore As Integer = num Mod 4 'Console.WriteLine(num) 'For isnum As Integer = 1 To (4 - themore) ' result(result.Count -1).Add({0}) 'Next Return result End Function ''' ''' CRC16校验 ''' ''' ''' ''' Public Function GetCRC16CheckSum(dataBuff() As Byte, length As Integer) As Byte() Dim crc16 As UInteger Dim crcBytes() As Byte crc16 = &HFFFF For i = 0 To length - 1 crc16 = crc16 And &HFFFF crc16 = crc16 Xor dataBuff(i) For bit = 0 To 7 crc16 = IIf((crc16 And 1) = 0, crc16 >> 1, (crc16 >> 1) Xor &HA001) Next Next crc16 = crc16 And &HFFFF crcBytes = BitConverter.GetBytes(UShort.Parse(crc16)) Return crcBytes End Function Private Function FindModelDeviceGroupUnderModel_By_Interface(pNode As RowNode, strInterface As String) As RowNode Dim resultNode As RowNode = Nothing For Each node As RowNode In pNode.Nodes If node.RowType <> RowNode.RowTypeEnum.DeviceGroup Then Continue For If String.Compare(node.Interface, strInterface, True) <> 0 Then Continue For resultNode = node Exit For Next Return resultNode End Function ''' ''' 在模型节点下查询指定名称的设备组节点 ''' ''' 模型节点 ''' Private Function FindModelDeviceGroupUnderModel(pNode As RowNode, name As String) As RowNode Dim resultNode As RowNode = Nothing ''2022-05-14 2.0.2.0 版本以前:匹配节点名称与“DI”‘DO’字符串,来确定是否返回端点 ''外设有继电器时,继电器名称为“Relay”,Interface为“DO”,此方法会范围“0” For Each node As RowNode In pNode.Nodes If node.RowType <> RowNode.RowTypeEnum.DeviceGroup Then Continue For If String.Compare(node.Name, name, True) <> 0 Then Continue For resultNode = node Exit For Next Return resultNode End Function ''' ''' 在模型节点下查询属性集节点 ''' ''' 模型节点 ''' Private Function FindModelAttributesUnderModel(pNode As RowNode) As RowNode Dim resultNode As RowNode = Nothing For Each node As RowNode In pNode.Nodes If node.RowType <> RowNode.RowTypeEnum.ModelAttributes Then Continue For resultNode = node Exit For Next Return resultNode End Function ''' ''' 在属性集节点下查询指定名称的属性组节点 ''' ''' 属性集合节点 ''' 属性组名称 ''' Private Function FindAttributeGroupUnderAttributes(pNode As RowNode, name As String) As RowNode Dim resultNode As RowNode = Nothing For Each node As RowNode In pNode.Nodes If node.RowType <> RowNode.RowTypeEnum.ModelAttributeGroup AndAlso node.RowType <> RowNode.RowTypeEnum.ModelAttributes_DeviceExists Then Continue For If String.Compare(node.Name, name, True) <> 0 Then Continue For resultNode = node Exit For Next Return resultNode End Function ''' ''' 在属性组节点下查询属性节点 ''' ''' ''' ''' Private Function FindAttributeUnderAttributeGroup(pNode As RowNode, name As String) As RowNode Dim resultNode As RowNode = Nothing For Each node As RowNode In pNode.Nodes ' If node.RowType <> RowNode.RowTypeEnum.DeviceAttribute Then Continue For If String.Compare(node.Name, name, True) <> 0 Then Continue For resultNode = node Exit For Next Return resultNode End Function ''' ''' 获取节点选择项对应的数值 ''' ''' ''' Private Function GetNodeSelectStringValue(node As RowNode) As String Dim result As String Dim tag As AttributeRowNodeTag = node.Tag result = tag.ValueData If node.Text.Contains("判断锁定状态") Then Console.WriteLine($"{node.ParentNode.ParentNode.ParentNode.ParentNode.ParentNode.Text }") Console.WriteLine($"{node.ParentNode.ParentNode.ParentNode.Text }") Console.WriteLine($"判断锁定状态{result}") End If result = tag.ValueData Return result End Function ''' ''' 在模型节点下查询指定组名下的指定名称属性节点 ''' ''' 模型节点 ''' Private Function FindAttributeUnderModel(pNode As RowNode, groupName As String, attributeName As String) As RowNode Dim resultNode As RowNode = Nothing If pNode Is Nothing Then Return resultNode Dim n As RowNode = FindModelAttributesUnderModel(pNode) If n Is Nothing Then Return resultNode Dim n2 As RowNode = FindAttributeGroupUnderAttributes(n, groupName) If n2 Is Nothing Then Return resultNode resultNode = FindAttributeUnderAttributeGroup(n2, attributeName) Return resultNode End Function ''' ''' 在模型节点下查询指定组名下的指定名称的属性节点值 ''' ''' 模型节点 ''' Private Function FindAttributeValueUnderModel(pNode As RowNode, groupName As String, attributeName As String) As String Dim node As RowNode = FindAttributeUnderModel(pNode, groupName, attributeName) If node Is Nothing Then Throw New Exception($"{pNode.RowListIndex}:{pNode.Name} 未查询属性组[{groupName}]下属性[{attributeName}]节点") Dim result As String Try result = GetNodeSelectStringValue(node) Catch ex As Exception Throw New Exception($"{pNode.RowListIndex}:{pNode.Name} 查询属性值失败,{ex.Message}") End Try Return result End Function ''' ''' 在模型节点下查询指定组名下的指定名称的属性节点值 ''' ''' 模型节点 ''' Private Function TheFindAttributeValueUnderModel(pNode As RowNode, groupName As String, attributeName As String) As String Dim node As RowNode = FindAttributeUnderModel(pNode, groupName, attributeName) If node Is Nothing Then Return String.Empty Dim result As String Try result = GetNodeSelectStringValue(node) Catch ex As Exception Return String.Empty End Try Return result End Function ''' ''' 在属性组节点下查询指定属性名的属性节点值 ''' ''' 属性组节点 ''' 属性值 ''' Private Function FindAttributeValueUnderGroup(pNode As RowNode, attributeName As String) As String Dim node As RowNode = FindAttributeUnderAttributeGroup(pNode, attributeName) Return GetNodeSelectStringValue(node) End Function ''' ''' 在模型节点下查询指定名称的设备组节点 ''' ''' 模型节点 ''' 设备组名 ''' Private Function FindDeviceGroupUnderModel(pNode As RowNode, name As String) As RowNode Dim resultNode As RowNode = Nothing For Each node As RowNode In pNode.Nodes If node.RowType <> RowNode.RowTypeEnum.DeviceGroup Then Continue For If String.Compare(node.Name, name, True) <> 0 Then Continue For resultNode = node Exit For Next Return resultNode End Function Private Function FillSceneData() As List(Of Byte()) Dim tmpBufferCount As Integer = 0 Dim resultDatas As New List(Of Byte()) Dim cmd As Byte = &H6 Dim buf As List(Of Byte) For Each num As UShort In _lstScese.Keys buf = New List(Of Byte) buf.Add(cmd) buf.AddRange(BitConverter.GetBytes(num)) '2字节场景编号 Dim aliasData() As Byte = AliasEncoding.GetBytes(_lstScese(num).AliasName) ReDim Preserve aliasData(15) buf.AddRange(aliasData) '16字节场景别名 buf.AddRange(_lstScese(num).GetActionNums) '2n动作编号集 tmpBufferCount = tmpBufferCount + buf.Count resultDatas.Add(buf.ToArray) Next PrintInfo("场景编译完成,长度:" & tmpBufferCount & "Bytes") Return resultDatas End Function ''' ''' 填充小宝数据 ''' ''' Private Function FillXiaobaoData() As List(Of Byte()) Dim tmpBufferCount As Integer = 0 Dim resultDatas As New List(Of Byte()) Dim cmd As Byte = &H5 Dim buf As List(Of Byte) PrintInfo("开始编译小宝数据") For Each node As RowNode In _xiaobao PrintInfo(" - 行号:" & node.RowListIndex & " " & node.Text) 'Momo 20220617 增加场景编译输出信息 For Each data() As Byte In FillXiaoBaoGroupData(node) buf = New List(Of Byte) buf.Add(cmd) buf.AddRange(data) resultDatas.Add(buf.ToArray) tmpBufferCount = tmpBufferCount + buf.Count Next Next PrintInfo("小宝编译完成,长度:" & tmpBufferCount & "Bytes") Return resultDatas End Function ''' ''' 获取小宝词条组的数据 ''' ''' 小宝词条组节点 ''' Private Function FillXiaoBaoGroupData(pNode As RowNode) As List(Of Byte()) Dim lst As New List(Of Byte()) If pNode.RowType <> RowNode.RowTypeEnum.ModelAttributes_XiaoBaoCMD Then Throw New Exception($"未知的小宝类型:{pNode.RowListIndex}") Dim data As List(Of Byte) For Each node As RowNode In pNode.Nodes If String.IsNullOrEmpty(node.DeviceType) OrElse String.IsNullOrEmpty(node.DeviceName) Then Continue For data = New List(Of Byte) Dim tag As XiaoBaoRowNodeTag = node.Tag data.Add(CInt(tag.DevType)) '输入类型(1个字节) data.Add(CInt(tag.Address)) '输入地址(1个字节) If node.DeviceType = "场景" Then data.Add(GetContextualModelDeviceType()) '控制类型(1个字节) data.Add(GetContextualModelDeviceAddr()) '控制地址(1个字节) If _dicScese.ContainsKey(node.DeviceName) Then Dim tmpDicSceseIdx As UShort = _dicScese(node.DeviceName) data.AddRange(BitConverter.GetBytes(_dicScese(node.DeviceName))) '场景编号(2个字节) PrintInfo(" 行号:" & node.RowListIndex & " 小宝命令:" & node.Text & " ,场景别名:" & node.DeviceName & " ,场景编号:" & tmpDicSceseIdx) 'Momo 20220610 增加场景编译输出信息 Else Throw New Exception($"无效的场景名{node.DeviceName}") End If Else data.Add(GetActionDeviceType(node.DeviceName)) '控制类型(1个字节) data.Add(GetActionDeviceAddr(node.DeviceName)) '控制地址(1个字节) data.AddRange(GetActionDeviceLoop(node.DeviceName)) '控制回路(2个字节) End If lst.Add(data.ToArray) Next Return lst End Function ''' ''' 填充配置信息 ''' 修改记录: ''' 2022-05-16 曹聪 ''' 1、下发的软件版本类型不对 - 已修改 ''' 2、下发的中文编码不对 - 已修改 ''' ''' Private Function FillConfigInfo() As List(Of Byte) Dim resultDatas As New List(Of Byte()) Dim cmd As Byte = &H1 Dim buf As List(Of Byte) = New List(Of Byte) '填充配置信息 '_configInfo.Author = Account '配置发布作者 '_configInfo.ConfigToolVersion = Application.ProductVersion '配置软件版本号’ '_configInfo.ReleaseDate = date_now '发布日期 '_configInfo.HotelName = _project.HotelName '项目名称’ '_configInfo.HotelCode = _project.HotelCode '项目代号 '_configInfo.HotelGroupName = _project.VerdorName '项目分组 '_configInfo.RoomTypeName = _project.RoomType(g_CurrentTreeNodeRoomTypeItemIndex).structRoomType_Name '房型别名 '_configInfo.CfgFileVersion = _project.RoomType(g_CurrentTreeNodeRoomTypeItemIndex).structRoomType_ConfigVersion + 1 '配置版本号加一 Dim arrayCopyLenght As Integer = 0 '命令 buf.Add(cmd) '发布作者 P0~31 Dim bytesAuthor() As Byte = AliasEncoding.GetBytes(_configInfo.Author.Trim) Dim bytesAuthor_32bytes(31) As Byte If bytesAuthor.Length <= 32 Then arrayCopyLenght = bytesAuthor.Length Else arrayCopyLenght = 32 End If Array.Copy(bytesAuthor, bytesAuthor_32bytes, arrayCopyLenght) buf.AddRange(bytesAuthor_32bytes) '软件版本号 P32~35 'Dim strConfigToolsVersion As String = Replace(_configInfo.ConfigToolVersion, ".", "", 1, 4) 'Dim byetConfigToolsVersion() As Byte = System.Text.Encoding.UTF8.GetBytes(strConfigToolsVersion) Dim ByteConfigToolsVersion() As String = _configInfo.ConfigToolVersion.Split(".") Dim byetConfigToolsVersion(3) As Byte byetConfigToolsVersion(0) = Val(ByteConfigToolsVersion(0)) byetConfigToolsVersion(1) = Val(ByteConfigToolsVersion(1)) byetConfigToolsVersion(2) = Val(ByteConfigToolsVersion(2)) byetConfigToolsVersion(3) = Val(ByteConfigToolsVersion(3)) buf.AddRange(byetConfigToolsVersion) '配置发布日期 P36~42 'Dim strReleaseDate As String = Format(_configInfo.ReleaseDate, "yyyyMMddHHmmss") 'Dim byteReleaseDate() = System.Text.Encoding.UTF8.GetBytes(strReleaseDate) Dim byteReleaseDate(6) As Byte ' byteReleaseDate(0) = _configInfo.ReleaseDate.Year \ 256 'yy H byteReleaseDate(1) = _configInfo.ReleaseDate.Year Mod 256 'yy L byteReleaseDate(2) = _configInfo.ReleaseDate.Month 'Month byteReleaseDate(3) = _configInfo.ReleaseDate.Day 'd byteReleaseDate(4) = _configInfo.ReleaseDate.Hour 'h byteReleaseDate(5) = _configInfo.ReleaseDate.Minute 'm byteReleaseDate(6) = _configInfo.ReleaseDate.Second 's buf.AddRange(byteReleaseDate) '项目名称 P43~74 Dim byteHotelName() As Byte = AliasEncoding.GetBytes(_configInfo.HotelName.Trim) Dim byteHotelName_32Bytes(31) As Byte If byteHotelName.Length <= 32 Then arrayCopyLenght = byteHotelName.Length Else arrayCopyLenght = 32 End If Array.Copy(byteHotelName, byteHotelName_32Bytes, arrayCopyLenght) buf.AddRange(byteHotelName_32Bytes) '项目编号 P75~78 Dim byteHotelCode() As Byte = iByte4(_configInfo.HotelCode) buf.AddRange(byteHotelCode) '项目分组 P79~110 Dim byteHoteGroupName() As Byte = AliasEncoding.GetBytes(_configInfo.HotelGroupName.Trim) Dim byteHoteGroupName_32Bytes(31) As Byte If byteHoteGroupName.Length <= 32 Then arrayCopyLenght = byteHoteGroupName.Length Else arrayCopyLenght = 32 End If Array.Copy(byteHoteGroupName, byteHoteGroupName_32Bytes, arrayCopyLenght) buf.AddRange(byteHoteGroupName_32Bytes) '房型别名 P111~142 Dim byteRoomTypeName() As Byte = AliasEncoding.GetBytes(_configInfo.RoomTypeName.Trim) Dim byteRoomTypeName_32Bytes(31) As Byte If byteRoomTypeName.Length <= 32 Then arrayCopyLenght = byteRoomTypeName.Length Else arrayCopyLenght = 32 End If Array.Copy(byteRoomTypeName, byteRoomTypeName_32Bytes, arrayCopyLenght) buf.AddRange(byteRoomTypeName_32Bytes) '配置版本号 P143~146 'Dim byteConfigFileVersion() As Byte = iByte4(_configInfo.CfgFileVersion) 'buf.AddRange(byteConfigFileVersion) 'Momo 2022-09-06 配置版本号只有3位 P143~145 Dim byteConfigFileVersion() As Byte = iByte3(_configInfo.CfgFileVersion) buf.AddRange(byteConfigFileVersion) '配置机型 P146~P209 MCU机型名称 64 Dim tmpModelName As String = _modelNode.Name.Trim 'MsgBox(tmpModelName) Dim byteModelName() As Byte = AliasEncoding.GetBytes(tmpModelName) Dim byteModelName_64Bytes(63) As Byte If byteModelName.Length <= 64 Then arrayCopyLenght = byteModelName.Length Else arrayCopyLenght = 64 End If Array.Copy(byteModelName, byteModelName_64Bytes, arrayCopyLenght) buf.AddRange(byteModelName_64Bytes) '完成配置数据添加 Return buf 'resultDatas End Function ''' ''' 填充设备存在 ''' ''' Private Function FillDeviceExistsData(ByRef OutDevlist As List(Of Dictionary(Of String, String))) As List(Of Byte()) Dim resultDatas As New List(Of Byte()) Dim cmd As Byte = &H3 Dim buf As List(Of Byte) For Each node As RowNode In _deviceExists buf = New List(Of Byte) PrintInfo("[行号:" & node.RowListIndex & "]" & " - 开始编译节点:" & node.Text) If node.RowType = RowNode.RowTypeEnum.ExternalModel Then ''485外设 03 加到每个设备组数据块前面 Dim tmpBufferLst As List(Of Byte()) = FillExternalModelDeviceExsist(node, OutDevlist) Dim tmpOutData As Byte() For i = 0 To tmpBufferLst.Count - 1 tmpOutData = tmpBufferLst(i).ToArray Console.WriteLine("FillDeviceExistsData.outBuff( " & i & ": " & BitConverter.ToString(tmpOutData).Replace("-", " ")) resultDatas.Add(tmpOutData.ToArray) PrintInfo(" 编译完成,长度:" & tmpOutData.Count & " Bytes") Next tmpBufferLst = SelfCheckingPower(node) For i = 0 To tmpBufferLst.Count - 1 tmpOutData = tmpBufferLst(i).ToArray Console.WriteLine("FillDeviceExistsData.outBuff( " & i & ": " & BitConverter.ToString(tmpOutData).Replace("-", " ")) resultDatas.Add(tmpOutData.ToArray) PrintInfo(" 编译完成,长度:" & tmpOutData.Count & " Bytes") Next Continue For ElseIf node.RowType = RowNode.RowTypeEnum.ModelAttributes_DeviceExists Then buf.Add(cmd) Dim tmpBuffer() As Byte = FillModeDeviceExsist(node) buf.AddRange(tmpBuffer) PrintInfo(" 设备存在 编译完成,长度:" & tmpBuffer.Count & " Bytes") ElseIf node.RowType = RowNode.RowTypeEnum.Model Then buf.Add(cmd) Dim tmpBuffer() As Byte = FillRCUModelDeviceExsist(node) buf.AddRange(tmpBuffer) PrintInfo(" 主机模型 编译完成,长度:" & tmpBuffer.Count & " Bytes") Else PrintError("未知的设备存在类型:" & node.Text) Throw New Exception($"FillDeviceExistsData : 未处理的设备存在类型行:{node.RowListIndex}") End If resultDatas.Add(buf.ToArray) Next Return resultDatas End Function 'CZH 23 12 28 新增 自检功率 命令数据 Public Function SelfCheckingPower(pNode As RowNode) As List(Of Byte()) If pNode.RowType <> RowNode.RowTypeEnum.ExternalModel Then Throw New Exception($"行号:{pNode.RowListIndex} 不为外接设备类型") '返回参数 Dim outDataLst As New List(Of Byte()) '输出数据列表 '公共参数 Dim pTag As DeviceObjectRowNodeTag = pNode.ParentNode.Tag If Not pTag.Device.Interface.Equals("PB_BUS_LINE") Then Return outDataLst '2022-05-23 Momo V3.0 找到外设设备(RowType=26)后,再遍历设备组(RowType=8) 'To be code here ! 'OutDevlist.Add(System.Text.Encoding.Default.GetBytes(Str)) For Each objGroupNode As RowNode In pNode.Nodes If objGroupNode.RowType <> RowNode.RowTypeEnum.DeviceGroup Then Continue For '找到模型外设组 If objGroupNode.Compile = False Then Continue For '判断是否enable action’ If objGroupNode.DEV_TYPE_DATA.Equals("49") OrElse objGroupNode.DEV_TYPE_DATA.Equals("50") OrElse objGroupNode.DEV_TYPE_DATA.Equals("51") Then Dim cmd As Byte = &H7 Dim tmpAddr As Byte = CInt(FindAttributeValueUnderModel(pNode, "设备存在", "拨码地址")) '设备地址(1字节) Dim devtype As Byte = CByte(objGroupNode.DEV_TYPE_DATA) '遍历设备 For Each objNode As RowNode In objGroupNode.Nodes If objNode.RowType <> RowNode.RowTypeEnum.DeviceObject Then Continue For '设备 If objNode.Compile = False Then Continue For '判断是否enable action’ Dim bpTag As DeviceObjectRowNodeTag = objNode.Tag Select Case objNode.Interface Case "DI" Case "DO" Dim nli As New List(Of Byte) Dim upAddr As Integer = CInt(FindAttributeValueUnderModel(pNode, "设备存在", $"回路{bpTag.Device.LoopAddr}自检功率下限")) '设备地址(1字节) Dim domAddr As Integer = CInt(FindAttributeValueUnderModel(pNode, "设备存在", $"回路{bpTag.Device.LoopAddr}自检功率上限")) '设备地址(1字节) nli.Add(cmd) nli.Add(devtype) nli.Add(tmpAddr) nli.AddRange(BitConverter.GetBytes(CShort(bpTag.Device.LoopAddr))) nli.AddRange(BitConverter.GetBytes(CShort(upAddr))) nli.AddRange(BitConverter.GetBytes(CShort(domAddr))) outDataLst.Add(nli.ToArray) Case Else Continue For End Select Next End If Next Return outDataLst End Function 'CZH 23 12 28 新增 自检功率 命令数据 ''' ''' 根据RCU模型的设备存在属性组,配置设备存在数据 ''' ''' 模型节点 ''' Private Function FillModeDeviceExsist2(pNode As RowNode) As Byte() If pNode.RowType <> RowNode.RowTypeEnum.ModelAttributes_DeviceExists Then Return Nothing Dim modelNode As RowNode = pNode.ParentNode.ParentNode Dim tag As ModelRowNodeTag = modelNode.Tag Dim buf(62) As Byte buf(DeviceExsistParam.DeviceType) = FindAttributeValueUnderGroup(pNode, "DeviceType") '设备类型(1字节) buf(DeviceExsistParam.DeviceAddr) = FindAttributeValueUnderGroup(pNode, "DeviceAddr") '设备地址(1字节) buf(DeviceExsistParam.Port_485) = FindAttributeValueUnderGroup(pNode, "DevicePort") '485端口(1字节) Dim baudData() As Byte = BitConverter.GetBytes(CInt(FindAttributeValueUnderGroup(pNode, "DeviceBaud"))) Array.Copy(baudData, 0, buf, DeviceExsistParam.BaudRate, baudData.Length) '波特率(4字节) buf(DeviceExsistParam.ProtocolVer) = tag.Desc.ProtocolVer '协议版本(1字节) buf(DeviceExsistParam.RetryCount) = FindAttributeValueUnderGroup(pNode, "DeviceRetryNum") '重发次数(1字节) Dim retryTimeData() As Byte = BitConverter.GetBytes(CShort(FindAttributeValueUnderGroup(pNode, "DeviceRetryTime"))) Array.Copy(retryTimeData, 0, buf, DeviceExsistParam.WaitTime, retryTimeData.Length) '重发间隔(2字节) buf(DeviceExsistParam.KeepParams) = &H0 '保留字段(32字节) Dim index As Integer = pNode.Name.IndexOf("设备组信息") Dim type As String = pNode.Name.Substring(0, index) Dim inputCount, outputCount As Short Select Case type Case "DI" inputCount = FindModelDeviceGroupUnderModel(modelNode, "DI").Count outputCount = 0 Case "DO" inputCount = 0 outputCount = FindModelDeviceGroupUnderModel(modelNode, "DO").Count Case "RELAY" inputCount = FindModelDeviceGroupUnderModel(modelNode, "RELAY").Count outputCount = 0 Case "MUSIC" inputCount = FindModelDeviceGroupUnderModel(modelNode, "MUSIC").Count outputCount = 0 End Select Dim inputCountData() As Byte = BitConverter.GetBytes(inputCount) Array.Copy(inputCountData, 0, buf, DeviceExsistParam.InputLoopCount, inputCountData.Length) '输入回路数(2字节) Dim outputCountData() As Byte = BitConverter.GetBytes(outputCount) Array.Copy(outputCountData, 0, buf, DeviceExsistParam.OutputLoopCount, outputCountData.Length) '输出回路数(2字节) 'todo:获取所有输出节点的别名并填充 Dim aliasData() As Byte = AliasEncoding.GetBytes(pNode.DeviceAlias) If aliasData.Length > 16 Then Throw New Exception($"当前行:{pNode.RowListIndex},超过上限长度上限") Array.Copy(aliasData, 0, buf, DeviceExsistParam.LoopAlias, aliasData.Length) '属性组别名(16字节) Return buf End Function ''' ''' 根据RCU模型的设备存在属性组,配置设备存在数据 ''' ''' 模型节点 ''' Private Function FillModeDeviceExsist(pNode As RowNode) As Byte() If pNode.RowType <> RowNode.RowTypeEnum.ModelAttributes_DeviceExists Then Throw New Exception($"行号:{pNode.RowListIndex} 不为设备存在模型属性类型") Dim modelNode As RowNode = pNode.ParentNode.ParentNode Dim tag As ModelRowNodeTag = modelNode.Tag Dim buf As New List(Of Byte) buf.Add(FindAttributeValueUnderGroup(pNode, "DeviceType")) '设备类型(1字节) buf.Add(FindAttributeValueUnderGroup(pNode, "DeviceAddr")) '设备地址(1字节) buf.Add(FindAttributeValueUnderGroup(pNode, "DevicePort")) '485端口(1字节) Dim baudData() As Byte = BitConverter.GetBytes(CInt(FindAttributeValueUnderGroup(pNode, "DeviceBaud"))) buf.AddRange(baudData) '波特率(4字节) buf.Add(FindAttributeValueUnderGroup(pNode, "DeviceVer")) '协议版本(1字节) buf.Add(FindAttributeValueUnderGroup(pNode, "DeviceRetryNum")) '重发次数(1字节) Dim retryTimeData() As Byte = BitConverter.GetBytes(CShort(FindAttributeValueUnderGroup(pNode, "DeviceRetryTime"))) buf.AddRange(retryTimeData) '重发间隔(2字节) Dim keepParam(63) As Byte '保留字段(32字节) -> 2022-05-28 V3.1 32bytes->64Bytes buf.AddRange(keepParam) Dim index As Integer = pNode.Name.IndexOf("设备组信息") Dim type As String = pNode.Name.Substring(0, index) Dim inputCount, outputCount As UShort Dim inputSettings As New List(Of Byte) Dim outputAliases As New List(Of Byte) Dim inputGroupNode As RowNode = Nothing Dim outputGroupNode As RowNode = Nothing Select Case type Case "DI" inputGroupNode = FindModelDeviceGroupUnderModel(modelNode, "DI") Case Else outputGroupNode = FindModelDeviceGroupUnderModel(modelNode, type) End Select If inputGroupNode Is Nothing Then inputCount = 0 Else For Each node As RowNode In inputGroupNode.Nodes If node.RowType <> RowNode.RowTypeEnum.DeviceObject Then Continue For If node.Compile = False Then Continue For inputCount += 1 inputSettings.AddRange(GetDeviceObjectSetting(node)) Next End If If outputGroupNode Is Nothing Then outputCount = 0 Else For Each node As RowNode In outputGroupNode.Nodes If node.RowType <> RowNode.RowTypeEnum.DeviceObject Then Continue For If node.Compile = False Then Continue For outputCount += 1 Dim aliasData() As Byte 'Momo 2022-05-03 增加DeviceAlias非空判断,避免报错 If String.IsNullOrEmpty(node.DeviceAlias) = False Then aliasData = AliasEncoding.GetBytes(node.DeviceAlias) End If ReDim Preserve aliasData(31) 'caocong 2022-06-07 修改别名长度16Byte -> 32Byte outputAliases.AddRange(aliasData) Next End If buf.AddRange(BitConverter.GetBytes(inputCount)) '输入回路数(2字节) buf.AddRange(BitConverter.GetBytes(outputCount)) '输出回路数(2字节) buf.AddRange(inputSettings.ToArray) '所有输入回路设置(n*4字节) buf.AddRange(outputAliases.ToArray) '所有输出回路别名(n*16字节) ''输入回路设置(n*4) 'If inputCount > 0 Then ' For Each node As RowNode In inputGroupNode.Nodes ' '查询设备节点 ' If node.RowType <> RowNode.RowTypeEnum.DeviceObject Then Continue For ' buf.AddRange(GetDeviceObjectSetting(node)) ' Next 'End If ''所有输出回路别名(n*16字节) 'If outputCount > 0 Then ' For Each node As RowNode In outputGroupNode.Nodes ' Dim aliasData() As Byte = AliasEncoding.GetBytes(node.DeviceAlias) ' ReDim Preserve aliasData(15) ' buf.AddRange(aliasData) ' Next 'End If Return buf.ToArray End Function ''' ''' 获取输入类型设备对象的回路设置 ''' ''' ''' Private Function GetDeviceObjectSetting(pNode As RowNode) As Byte() Dim buf(3) As Byte For Each node As RowNode In pNode.Nodes '查询设备属性集合 If node.RowType <> RowNode.RowTypeEnum.DeviceAttributes Then Continue For '获取设备属性值 Dim index As Integer = 0 Dim tag As AttributeRowNodeTag For Each n As RowNode In node.Nodes tag = n.Tag buf(index) = tag.ValueData index += 1 If index >= 4 Then Exit For Next Next Return buf End Function ''' ''' 根据连接在485设备下的模型节点信息,配置设备存在数据 ''' ''' 模型节点 ''' Private Function FillExternalModelDeviceExsist2(pNode As RowNode) As Byte() If pNode.RowType <> RowNode.RowTypeEnum.ExternalModel Then Return Nothing Dim buf(62) As Byte Dim tag As ModelRowNodeTag = pNode.Tag buf(DeviceExsistParam.DeviceType) = tag.Desc.DevTypeData '设备类型(1字节) buf(DeviceExsistParam.DeviceAddr) = CInt(FindAttributeValueUnderModel(pNode, "设备存在", "拨码地址")) '设备地址(1字节) Dim pTag As DeviceObjectRowNodeTag = pNode.ParentNode.Tag buf(DeviceExsistParam.Port_485) = pTag.Device.LoopAddr '485端口(1字节) Dim baudData() As Byte = BitConverter.GetBytes(CInt(FindAttributeValueUnderModel(pNode, "设备存在", "波特率"))) Array.Copy(baudData, 0, buf, DeviceExsistParam.BaudRate, baudData.Length) '波特率(4字节) buf(DeviceExsistParam.ProtocolVer) = tag.Desc.ProtocolVer '协议版本(1字节) buf(DeviceExsistParam.RetryCount) = CInt(FindAttributeValueUnderModel(pNode, "设备存在", "重发次数")) '重发次数(1字节) Dim retryTimeData() As Byte = BitConverter.GetBytes(CShort(FindAttributeValueUnderModel(pNode, "设备存在", "重发时间"))) Array.Copy(retryTimeData, 0, buf, DeviceExsistParam.WaitTime, retryTimeData.Length) '重发间隔(2字节) buf(DeviceExsistParam.KeepParams) = &H0 '保留字段(32字节) Dim groupNode As RowNode = FindModelDeviceGroupUnderModel(pNode, "DI") If groupNode Is Nothing Then buf(DeviceExsistParam.InputLoopCount) = 0 '输入回路数(1字节) Else buf(DeviceExsistParam.InputLoopCount) = groupNode.Count '输入回路数(1字节) End If groupNode = FindModelDeviceGroupUnderModel(pNode, "DO") If groupNode Is Nothing Then buf(DeviceExsistParam.OutputLoopCount) = 0 '输出回路数(1字节) Else buf(DeviceExsistParam.OutputLoopCount) = groupNode.Count '输出回路数(1字节) End If For Each node As RowNode In groupNode.Nodes '输出回路的名称 Dim aliasData() As Byte = AliasEncoding.GetBytes(pNode.DeviceAlias) If aliasData.Length > 16 Then Throw New Exception($"当前行:{pNode.RowListIndex},超过上限长度上限") Array.Copy(aliasData, 0, buf, DeviceExsistParam.LoopAlias, aliasData.Length) '回路别名(16字节) Next Return buf End Function ''' ''' 配置RCU模型设备存在数据 ''' ''' 模型节点 ''' Private Function FillRCUModelDeviceExsist(pNode As RowNode) As Byte() If pNode.RowType <> RowNode.RowTypeEnum.Model Then Throw New Exception($"行号:{pNode.RowListIndex} 不为RCU模型类型") Dim buf As New List(Of Byte) Dim tag As ModelRowNodeTag = pNode.Tag buf.Add(tag.Desc.DevTypeData) '设备类型(1字节) buf.Add(&H0) '设备地址(1字节) buf.Add(&H0) '485端口(1字节) Dim baudrate As Integer = 0 buf.AddRange(BitConverter.GetBytes(baudrate)) '波特率(4字节) buf.Add(tag.Desc.ProtocolVer) '协议版本(1字节) buf.Add(&H0) '重发次数(1字节) Dim retryInterval As Short = 0 buf.AddRange(BitConverter.GetBytes(retryInterval)) '重发间隔(2字节) Dim keepParam(63) As Byte buf.AddRange(keepParam) '保留字段(32字节) -> 2022-05-28 V3.1 32bytes->64Bytes Dim inputCount As Short = 0 Dim outputCount As Short = 0 buf.AddRange(BitConverter.GetBytes(inputCount)) '输入回路数(2字节) buf.AddRange(BitConverter.GetBytes(outputCount)) '输出回路数(2字节) '所有输入回路设置(n*4字节) '所有输出回路别名(n*16字节) Return buf.ToArray End Function ''' ''' 根据连接在485设备下的模型节点信息,配置设备存在数据 ''' ''' 模型节点 ''' Private Function FillExternalModelDeviceExsist(pNode As RowNode, ByRef OutDevlist As List(Of Dictionary(Of String, String))) As List(Of Byte()) If pNode.RowType <> RowNode.RowTypeEnum.ExternalModel Then Throw New Exception($"行号:{pNode.RowListIndex} 不为外接设备类型") '返回参数 Dim outDataLst As New List(Of Byte()) '输出数据列表 '公共参数 Dim pTag As DeviceObjectRowNodeTag = pNode.ParentNode.Tag Dim baudData(3) As Byte '波特率(4字节) Dim retryTimeData(1) As Byte '重发次数(2字节) Dim keepParam(59) As Byte '保留字段(32字节) -> 2022-05-28 V3.1 32bytes->64Bytes Dim ipadd(3) As Byte '键值对,用于保存合并后设备数据 Dim ObjGroupNodesInOutDic As New Dictionary(Of String, List(Of Byte)) '键值对,用于保存合并后的数据,Val = 设备组编译后的byte数组 Dim strObjGroupNodesTypedataAndProtocol As String = "" '键值对的Key 即:key = DevTypeData,ProtocolVer Dim ObjGroupNodesInputCnt As New Dictionary(Of String, UInt16) '键值对,用于保存合并后的输入回路数,Val = 设备组编译后的byte数组 Dim ObjGroupNodesoutputCnt As New Dictionary(Of String, UInt16) '键值对,用于保存合并后的输出回路数,Val = 设备组编译后的byte数组 Dim ObjGroupNodesInpuSettings As New Dictionary(Of String, List(Of Byte)) '用于保存合并后输入设定数组 Dim ObjGroupNodesOutputAliases As New Dictionary(Of String, List(Of Byte)) '用于保存合并后输出别名数组 Dim strObjGroupNodesInterface As String = "" '2022-05-23 Momo V3.0 找到外设设备(RowType=26)后,再遍历设备组(RowType=8) 'To be code here ! 'OutDevlist.Add(System.Text.Encoding.Default.GetBytes(Str)) For Each objGroupNode As RowNode In pNode.Nodes If objGroupNode.RowType <> RowNode.RowTypeEnum.DeviceGroup Then Continue For '找到模型外设组 If objGroupNode.Compile = False Then Continue For '判断是否enable action’ strObjGroupNodesTypedataAndProtocol = objGroupNode.DEV_TYPE_DATA & "," & objGroupNode.PROTOCOL_VER strObjGroupNodesInterface = objGroupNode.Interface PrintInfo(" 开始遍历:" & objGroupNode.Text & " (" & strObjGroupNodesTypedataAndProtocol & "," & strObjGroupNodesInterface & ")") 'OutDevlist.AddRange(System.Text.Encoding.Default.GetBytes(pNode.Text)) 'OutDevlist.AddRange(System.Text.Encoding.Default.GetBytes(strObjGroupNodesTypedataAndProtocol & "," & strObjGroupNodesInterface)) 'Console.WriteLine($"{pNode.Text}:{}") '如果键值对不存在就增加键值对 If ObjGroupNodesInOutDic.ContainsKey(strObjGroupNodesTypedataAndProtocol) = False Then ObjGroupNodesInputCnt.Add(strObjGroupNodesTypedataAndProtocol, 0) '输入回路数 = 0 ObjGroupNodesoutputCnt.Add(strObjGroupNodesTypedataAndProtocol, 0) '输出回路数 = 0 ObjGroupNodesInpuSettings.Add(strObjGroupNodesTypedataAndProtocol, New List(Of Byte)) ObjGroupNodesOutputAliases.Add(strObjGroupNodesTypedataAndProtocol, New List(Of Byte)) '添加输出合并设备键值对’ ObjGroupNodesInOutDic.Add(strObjGroupNodesTypedataAndProtocol, New List(Of Byte)) '添加设备组公共信息 baudData = BitConverter.GetBytes(CInt(FindAttributeValueUnderModel(pNode, "设备存在", "波特率"))) retryTimeData = BitConverter.GetBytes(CShort(FindAttributeValueUnderModel(pNode, "设备存在", "重发时间"))) Dim tmpAddr As Byte = CInt(FindAttributeValueUnderModel(pNode, "设备存在", "拨码地址")) '设备地址(1字节) 'cah 20223_12_27 编译设备增加 父设备类型相关描述 Start Dim ParentDevType As Byte = 0 Dim ParentDevAddr As Byte = 0 Dim ParentDevPort As Byte = 0 Dim node As RowNode = FindAttributeUnderModel(pNode, "设备存在", "父设备类型") If Not IsNothing(node) Then ParentDevType = CInt(FindAttributeValueUnderModel(pNode, "设备存在", "父设备类型")) '父设备美型(1字节) End If node = FindAttributeUnderModel(pNode, "设备存在", "父设备地址") If Not IsNothing(node) Then ParentDevAddr = CInt(FindAttributeValueUnderModel(pNode, "设备存在", "父设备地址")) '父设备美型(1字节) End If node = FindAttributeUnderModel(pNode, "设备存在", "父设备端口") If Not IsNothing(node) Then ParentDevPort = CInt(FindAttributeValueUnderModel(pNode, "设备存在", "父设备端口")) '父设备美型(1字节) End If keepParam(0) = ParentDevType keepParam(1) = ParentDevAddr keepParam(2) = ParentDevPort 'cah 20223_12_27 编译设备增加 父设备类型相关描述 End For weindex As Integer = 0 To 4 node = FindAttributeUnderModel(pNode, "设备存在", $"弱电输入{weindex + 1}") If Not IsNothing(node) Then keepParam(3 + weindex) = CInt(FindAttributeValueUnderModel(pNode, "设备存在", $"弱电输入{weindex + 1}")) '父设备美型(1字节) End If Next 'Dim ipAddr As IPAddress = IPAddress.Parse(FindAttributeValueUnderModel(pNode, "设备存在", "中控IP地址")) '设备地址(1字节) 'ipadd = ipAddr.GetAddressBytes() With ObjGroupNodesInOutDic(strObjGroupNodesTypedataAndProtocol) .Add(&H3) '设备存在,每个数据块前面都加上 &H03 .Add(CByte(objGroupNode.DEV_TYPE_DATA)) '设备类型(1字节) .Add(tmpAddr) PrintInfo(" *** 设备地址:" & tmpAddr.ToString) .Add(CByte(pTag.Device.LoopAddr)) '485端口(1字节) .AddRange(baudData) '波特率(4字节) .Add(CByte(objGroupNode.PROTOCOL_VER)) '协议版本(1字节) .Add(CInt(FindAttributeValueUnderModel(pNode, "设备存在", "重发次数"))) '重发次数(1字节) .AddRange(retryTimeData) '重发间隔(2字节) If objGroupNode.DEV_TYPE_DATA.Equals("42") Then Dim ipAddr As IPAddress = IPAddress.Parse(FindAttributeValueUnderModel(pNode, "设备存在", "中控IP地址")) '设备地址(1字节) ipadd = ipAddr.GetAddressBytes() PrintInfo(" 中控IP地址 IPadd :" & ipAddr.ToString) ElseIf objGroupNode.DEV_TYPE_DATA.Equals("43") Then Dim ipAddr As IPAddress = IPAddress.Parse(FindAttributeValueUnderModel(pNode, "设备存在", "域控IP地址")) '设备地址(1字节) ipadd = ipAddr.GetAddressBytes() PrintInfo(" 域控IP地址 IPadd :" & ipAddr.ToString) End If .AddRange(ipadd) .AddRange(keepParam) End With 'OutDevlist.AddRange(ObjGroupNodesInOutDic(strObjGroupNodesTypedataAndProtocol)) 'Momo 2022-10-31 把编译后的485公共参数打印出来 'Dim tmpData As Byte() = ObjGroupNodesInOutDic(strObjGroupNodesTypedataAndProtocol).ToArray 'Dim tmpStr As String = BitConverter.ToString(tmpData).Replace("-", " ") 'PrintInfo(" *** 编译数据:" & tmpStr) 'Dim tmpData As Byte() = ObjGroupNodesInOutDic(strObjGroupNodesTypedataAndProtocol).ToArray 'Console.WriteLine(BitConverter.ToString(tmpData).Replace("-", " ")) End If '遍历设备 For Each objNode As RowNode In objGroupNode.Nodes If objNode.RowType <> RowNode.RowTypeEnum.DeviceObject Then Continue For '设备 If objNode.Compile = False Then Continue For '判断是否enable action’ Select Case objNode.Interface Case "DI" ObjGroupNodesInputCnt(strObjGroupNodesTypedataAndProtocol) += 1 '输入回路数+1 ObjGroupNodesInpuSettings(strObjGroupNodesTypedataAndProtocol).AddRange(GetDeviceObjectSetting(objNode))'输入回路设定’ Case "DO" Dim tmpDevAlias As String = objNode.DeviceAlias If String.IsNullOrEmpty(tmpDevAlias) Then tmpDevAlias = String.Empty '未命名别名的输出设备不参与编译 Dim aliasData() As Byte = AliasEncoding.GetBytes(tmpDevAlias) ReDim Preserve aliasData(31) 'caocong 2022-06-07 修改别名长度16Byte -> 32Byte ObjGroupNodesoutputCnt(strObjGroupNodesTypedataAndProtocol) += 1 '输出回路数+1’ ObjGroupNodesOutputAliases(strObjGroupNodesTypedataAndProtocol).AddRange(aliasData) '输出回路别名’ Case Else Continue For End Select Next Next PrintInfo(" 设备组遍历结束,合并后设备组数据如下:") '遍历合并后的设备组(保存于键值对中) For Each strKey As String In ObjGroupNodesInOutDic.Keys Dim inputCnt As UInt16 = ObjGroupNodesInputCnt(strKey) Dim outputCnt As UInt16 = ObjGroupNodesoutputCnt(strKey) Dim arryInputSetting As Byte() = ObjGroupNodesInpuSettings(strKey).ToArray Dim arryOutputSetting As Byte() = ObjGroupNodesOutputAliases(strKey).ToArray ObjGroupNodesInOutDic(strKey).AddRange(BitConverter.GetBytes(inputCnt)) ObjGroupNodesInOutDic(strKey).AddRange(BitConverter.GetBytes(outputCnt)) ObjGroupNodesInOutDic(strKey).AddRange(arryInputSetting) '所有输入回路设置(n*4字节) ObjGroupNodesInOutDic(strKey).AddRange(arryOutputSetting) '所有输出回路别名(n*16字节) PrintInfo(" DevType and Protocol:" & strKey) PrintInfo(" Input :" & inputCnt & ", Len=" & arryInputSetting.Length) PrintInfo(" Output:" & outputCnt & ", Len=" & arryOutputSetting.Length) 'Dim tmpData As Byte() = ObjGroupNodesInOutDic(strKey).ToArray 'Console.WriteLine("strKey=" & strKey & " : " & BitConverter.ToString(tmpData).Replace("-", " ")) 'OutDevlist.AddRange(ObjGroupNodesInOutDic(strKey).ToArray) 'OutDevlist.AddRange({&HD, &HA}) outDataLst.Add(ObjGroupNodesInOutDic(strKey).ToArray) Next '' OLD CODE -------------------------------------- 'Dim oobjectGroupsBuf As New List(Of Byte) ' 设备组buff,所有设备组buff 组成一个外设的buff 'Dim tag As ModelRowNodeTag = pNode.Tag ''V3.0以前:整个设备共用DevTypeData,V3.0以后:以设备组的DEV_TYPE_DATA为准 'oobjectGroupsBuf.Add(tag.Desc.DevTypeData) '设备类型(1字节) 'oobjectGroupsBuf.Add(CInt(FindAttributeValueUnderModel(pNode, "设备存在", "拨码地址"))) '设备地址(1字节) 'Dim pTag As DeviceObjectRowNodeTag = pNode.ParentNode.Tag 'oobjectGroupsBuf.Add(pTag.Device.LoopAddr) '485端口(1字节) 'Dim baudData() As Byte = BitConverter.GetBytes(CInt(FindAttributeValueUnderModel(pNode, "设备存在", "波特率"))) 'oobjectGroupsBuf.AddRange(baudData) '波特率(4字节) ''V3.0以前:整个设备共用ProtocolVer,V3.0以后:以设备组的ProtocolVer为准 'oobjectGroupsBuf.Add(tag.Desc.ProtocolVer) '协议版本(1字节) 'oobjectGroupsBuf.Add(CInt(FindAttributeValueUnderModel(pNode, "设备存在", "重发次数"))) '重发次数(1字节) 'Dim retryTimeData() As Byte = BitConverter.GetBytes(CShort(FindAttributeValueUnderModel(pNode, "设备存在", "重发时间"))) 'oobjectGroupsBuf.AddRange(retryTimeData) '重发间隔(2字节) 'Dim keepParam(31) As Byte '保留字段(32字节) 'oobjectGroupsBuf.AddRange(keepParam) 'Dim inputCount, outputCount As UShort 'Dim inputSettings As New List(Of Byte) 'Dim outputAliases As New List(Of Byte) ''Dim inputGroupNode As RowNode = FindModelDeviceGroupUnderModel(pNode, "DI") ''Dim outputGroupNode As RowNode = FindModelDeviceGroupUnderModel(pNode, "DO") 'Dim inputGroupNode As RowNode = FindModelDeviceGroupUnderModel_By_Interface(pNode, "DI") 'Dim outputGroupNode As RowNode = FindModelDeviceGroupUnderModel_By_Interface(pNode, "DO") 'If inputGroupNode Is Nothing Then ' inputCount = 0 'Else ' For Each node As RowNode In inputGroupNode.Nodes ' If node.RowType <> RowNode.RowTypeEnum.DeviceObject Then Continue For ' If node.Compile = False Then Continue For ' inputCount += 1 ' inputSettings.AddRange(GetDeviceObjectSetting(node)) ' Next 'End If 'If outputGroupNode Is Nothing Then ' outputCount = 0 'Else ' For Each node As RowNode In outputGroupNode.Nodes ' If node.RowType <> RowNode.RowTypeEnum.DeviceObject Then Continue For ' If node.Compile = False Then Continue For ' outputCount += 1 ' Dim aliasData() As Byte = AliasEncoding.GetBytes(node.DeviceAlias) ' ReDim Preserve aliasData(15) ' outputAliases.AddRange(aliasData) ' Next 'End If 'buf.AddRange(BitConverter.GetBytes(inputCount)) '输入回路数(2字节) 'buf.AddRange(BitConverter.GetBytes(outputCount)) '输出回路数(2字节) 'buf.AddRange(inputSettings.ToArray) '所有输入回路设置(n*4字节) 'buf.AddRange(outputAliases.ToArray) '所有输出回路别名(n*16字节) 'PrintInfo(" InputCount = " & inputCount) 'PrintInfo(" OutputCount = " & outputCount) Return outDataLst End Function Public Sub GetXMLdevList(ByRef OutDevlist As List(Of Dictionary(Of String, String))) #Region "CZh2023-3-30" FillActionGroups() For Each node As RowNode In _deviceExists If node.RowType = RowNode.RowTypeEnum.ExternalModel Then If node.RowType <> RowNode.RowTypeEnum.ExternalModel Then Return Dim ObjGroupNodesInOutDic As New Dictionary(Of String, List(Of Byte)) Dim strObjGroupNodesTypedataAndProtocol As String = "" For Each objGroupNode As RowNode In node.Nodes If objGroupNode.RowType <> RowNode.RowTypeEnum.DeviceGroup Then Continue For '找到模型外设组 If objGroupNode.Compile = False Then Continue For '判断是否enable action’ strObjGroupNodesTypedataAndProtocol = objGroupNode.DEV_TYPE_DATA & "," & objGroupNode.PROTOCOL_VER If ObjGroupNodesInOutDic.ContainsKey(strObjGroupNodesTypedataAndProtocol) = False Then ObjGroupNodesInOutDic.Add(strObjGroupNodesTypedataAndProtocol, New List(Of Byte)) Dim tmpAddr As Byte = CInt(FindAttributeValueUnderModel(node, "设备存在", "拨码地址")) '设备地址(1字节) Dim devtype As String = TheFindAttributeValueUnderModel(node, "设备存在", "是否为BLE设备") Dim devdic As New Dictionary(Of String, String) If devtype.Contains("1") AndAlso Not IsNothing(OutDevlist) Then devdic.Add("BleName", node.DeviceAlias) devdic.Add("DeviceAdd", tmpAddr) devtype = FindAttributeValueUnderModel(node, "设备存在", "BLE设备类型") devdic.Add("BleType", devtype) OutDevlist.Add(devdic) End If End If Next End If Next #End Region End Sub ''' ''' 获取事件条件节点下的条件执行方式节点 ''' ''' 设备对象节点 ''' Private Function GetActionModeUnderEventCondition(pNode As RowNode) As RowNode Dim resultNode As RowNode = Nothing For Each node As RowNode In pNode.Nodes If node.RowType <> RowNode.RowTypeEnum.DeviceEventActionModeGroup Then Continue For resultNode = node Exit For Next Return resultNode End Function ''' ''' 在动作执行方式组节点下查询指定名称的动作执行方式节点 ''' ''' 模型节点 ''' 设备组名 ''' Private Function GetActionModeUnderActionModeGroup(pNode As RowNode, name As String) As RowNode Dim resultNode As RowNode = Nothing For Each node As RowNode In pNode.Nodes If node.RowType <> RowNode.RowTypeEnum.DeviceEventActionMode Then Continue For If String.Compare(node.Name, name, True) <> 0 Then Continue For resultNode = node Exit For Next Return resultNode End Function ''' ''' 获取事件条件下的编译数据 ''' ''' 条件组节点 ''' Private Function GetDataUnderEventCondition(pNode As RowNode) As List(Of Byte()) Dim lst As New List(Of Byte()) Return lst End Function ''' ''' 获取设备对象的回路地址 ''' ''' ''' Private Function GetDeviceObjectData(node As RowNode) As Byte() If node.RowType <> RowNode.RowTypeEnum.DeviceObject Then Throw New Exception($"行号:{node.RowListIndex},文本:{node.Text}不为设备对象节点") Dim tag As DeviceObjectRowNodeTag = node.Tag Return BitConverter.GetBytes(CShort(tag.Device.LoopAddr)) End Function ''' ''' 获取执行方式组节点下的执行方式编译数据 ''' ''' ''' Private Function GetExecModeDataUnderCondtion(pNode As RowNode) As Byte If pNode.RowType <> RowNode.RowTypeEnum.DeviceEventActionModeGroup Then Throw New Exception("转换执行方式时无效的类型") If pNode.Count <> 1 Then Throw New Exception("执行方式数量异常") Return CInt(GetNodeSelectStringValue(pNode.Nodes(0))) End Function ''' ''' 获取条件组节点下的条件编译数据 ''' ''' 条件组节点 ''' Private Function GetConditionDataUnderConditionGroup(pNode As RowNode) As Byte() If pNode.RowType <> RowNode.RowTypeEnum.DeviceEventAllConditions Then Throw New Exception("转换条件时无效的类型") Dim a As New ConditionConverter For Each node As RowNode In pNode.Nodes Select Case node.Name Case " 1 动作输出使能" a.动作输出使能 = CInt(GetNodeSelectStringValue(node)) Case " 2 判断房态" a.房态 = CInt(GetNodeSelectStringValue(node)) Case " 3 控制取电服务" a.控制取电服务 = CInt(GetNodeSelectStringValue(node)) Case " 4 判断取电状态" a.取电状态 = CInt(GetNodeSelectStringValue(node)) Case " 5 判断勿扰状态" a.勿扰状态 = CInt(GetNodeSelectStringValue(node)) Case " 6 判断清理状态" a.清理状态 = CInt(GetNodeSelectStringValue(node)) Case " 7 判断呼叫状态" a.呼叫状态 = CInt(GetNodeSelectStringValue(node)) Case " 8 判断洗衣状态" a.洗衣状态 = CInt(GetNodeSelectStringValue(node)) Case " 9 判断退房状态" a.退房状态 = CInt(GetNodeSelectStringValue(node)) Case "10 判断稍后状态" a.稍后状态 = CInt(GetNodeSelectStringValue(node)) Case "11 判断SOS状态" a.SOS状态 = CInt(GetNodeSelectStringValue(node)) ' Case "12 判断预约待租状态" Case "12 判断送餐状态" a.预约待租状态 = CInt(GetNodeSelectStringValue(node)) Case "13 判断开锁状态" a.开锁状态 = CInt(GetNodeSelectStringValue(node)) Case "14 判断行李状态" a.行李状态 = CInt(GetNodeSelectStringValue(node)) Case "15 判断保险箱状态" a.保险箱状态 = CInt(GetNodeSelectStringValue(node)) Case "16 判断门磁状态" a.门磁状态 = CInt(GetNodeSelectStringValue(node)) Case "17 判断提示音状态" a.提示音状态 = CInt(GetNodeSelectStringValue(node)) Case "18 判断背光状态" a.背光状态 = CInt(GetNodeSelectStringValue(node)) Case "19 判断季节状态" a.季节状态 = CInt(GetNodeSelectStringValue(node)) Case "20 判断时间状态" a.时间状态 = CInt(GetNodeSelectStringValue(node)) Case "21 判断起夜状态" a.起夜状态 = CInt(GetNodeSelectStringValue(node)) Case "22 判断锁定状态" a.锁定状态 = CInt(GetNodeSelectStringValue(node)) Case Else Throw New Exception($"未知条件属性名:{node.Name}") End Select Next Return a.GetConditionData() End Function ''' ''' 获取设备对象下的所有动作编译数据(所有的设备对象动作数据) ''' ''' Private Function FillDeviceObject(ByRef tsp As ToolStripProgressBar) As List(Of Byte()) Dim lst As New List(Of Byte()) Dim tmpDataCount As Integer = 0 PrintInfo("开始编译设备对象") For Each node As RowNode In _objectLst tsp.Value = tsp.Value + 1 If node.Compile = False Then Continue For '过滤不编译的设备对象 If String.IsNullOrEmpty(node.DeviceType) Then Continue For For Each data() As Byte In GetComplieDataUnderDeviceObject(node, tsp) lst.Add(data) tmpDataCount = tmpDataCount + data.Length Next Next PrintInfo("设备对象编译完成,长度:" & tmpDataCount & "Bytes") Return lst End Function ''' ''' 获取场景模式集下的所有编译数据(多个节点的场景数据) ''' ''' Private Function FillSceneModel() As List(Of Byte()) Dim lst As New List(Of Byte()) Dim tmpBufferCount As Integer = 0 If _modelNode Is Nothing Then Return lst '命令参数 Dim cmd As Byte = &H4 '场景存在组的设备类型 Dim devType As Byte = FindAttributeValueUnderModel(_modelNode, "场景设备组信息", "DeviceType") '场景存在组的拨码地址 Dim devAddr As Byte = FindAttributeValueUnderModel(_modelNode, "场景设备组信息", "DeviceAddr") Dim buf As List(Of Byte) Dim devLoop As UShort = 1 '进度计数 PrintInfo("开始编译场景") For Each node As RowNode In _contexualLst If node.RowType <> RowNode.RowTypeEnum.ContextualModel Then Continue For If node.Compile = False Then Continue For Dim eventNodeLst As New List(Of RowNode) Dim i As Integer = 0 For Each data() As Byte In GetComplieDataUnderSceneModel(node, eventNodeLst) If data.Length = 0 Then Continue For buf = New List(Of Byte) buf.Add(cmd) '命令参数 buf.Add(devType) '设备类型 buf.Add(devAddr) '设备地址 buf.AddRange(BitConverter.GetBytes(_actionIndex)) '动作编号 buf.AddRange(BitConverter.GetBytes(devLoop)) '设备回路 buf.AddRange(data) '事件条件数据 tmpBufferCount = tmpBufferCount + buf.Count lst.Add(buf.ToArray) '单包动作数据 If _lstScese.ContainsKey(_sceneIndex) = False Then _lstScese.Add(_sceneIndex, New tmpClass(node.DeviceAlias, node)) End If _lstScese(_sceneIndex).Actions.Add(_actionIndex) If eventNodeLst.Count > i Then Dim tmpNode As RowNode = eventNodeLst.Item(i) PrintInfo(" --- 行号:" & tmpNode.RowListIndex & " ,事件编号:" & _actionIndex & " ,事件名称:" & tmpNode.Text & " ,事件别名:" & tmpNode.DeviceAlias) 'Momo 20220617 '添加事件键值对 If _eventRowNode.ContainsKey(_actionIndex) Then _eventRowNode(_actionIndex) = tmpNode Else _eventRowNode.Add(_actionIndex, tmpNode) End If End If _actionIndex += 1 i = i + 1 Next devLoop += 1 '更新设备回路 If String.IsNullOrEmpty(node.DeviceAlias) = False Then _dicScese.Add(node.DeviceAlias, _sceneIndex) End If PrintInfo(" 行号:" & node.RowListIndex & " 场景编号:" & _sceneIndex & " ,场景名称:" & node.DeviceAlias) 'Momo 20220610 增加场景编译输出信息 _sceneIndex += 1 '更新场景编号 Next PrintInfo("场景动作编译完成,长度:" & tmpBufferCount & "Bytes") Return lst End Function ''' ''' 获取设备节点下的所有编译数据(多个节点的事件数据) ''' ''' 设备对象节点 ''' Private Function GetComplieDataUnderDeviceObject(pNode As RowNode, ByRef tsp As ToolStripProgressBar) As List(Of Byte()) If pNode.RowType <> RowNode.RowTypeEnum.DeviceObject Then Throw New Exception($"行号:{pNode.RowListIndex},文本:{pNode.Text}不为设备对象节点") If pNode.Compile = False Then Return New List(Of Byte()) '过滤不编译的设备对象 Dim lst As New List(Of Byte()) '命令参数 Dim cmd As Byte = &H4 '模型的设备类型 Dim devType As Byte = GetActionDeviceType(pNode.RowListIndex) '模型的拨码地址 Dim devAddr As Byte = GetActionDeviceAddr(pNode.RowListIndex) '当前设备的回路 Dim devLoop() As Byte = GetDeviceObjectData(pNode) Dim buf As List(Of Byte) Dim eventNodeLst As New List(Of RowNode) Dim i As Integer = 0 For Each node As RowNode In pNode.Nodes tsp.Value = tsp.Value + 1 Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEvents For Each data() As Byte In GetCompliDataUnderEvents(node, eventNodeLst) buf = New List(Of Byte) buf.Add(cmd) '命令参数 buf.Add(devType) '设备类型 buf.Add(devAddr) '设备地址 buf.AddRange(BitConverter.GetBytes(_actionIndex)) '动作编号 buf.AddRange(devLoop) '设备回路 buf.AddRange(data) '事件条件数据 lst.Add(buf.ToArray) '单包动作数据 Dim num As Integer = BitConverter.ToUInt16(data, 75) '2022-06-08 caocong _lstScese(num).Actions.Add(_actionIndex) If eventNodeLst.Count > i Then Dim tmpNode As RowNode = eventNodeLst.Item(i) PrintInfo(" --- 行号:" & tmpNode.RowListIndex & " ,事件编号:" & _actionIndex & " ,事件名称:" & tmpNode.Text & " ,事件别名:" & tmpNode.DeviceAlias) 'Momo 20220617 '添加事件键值对 If _eventRowNode.ContainsKey(_actionIndex) Then _eventRowNode(_actionIndex) = tmpNode Else _eventRowNode.Add(_actionIndex, tmpNode) End If End If _actionIndex += 1 '更新动作编号 i += 1 Next Case RowNode.RowTypeEnum.DeviceAttributes '属性 End Select Next Return lst End Function Public Function ByteToString(databuff() As Byte) Dim strData As String = String.Empty For i = 0 To databuff.Length - 1 strData &= $" {Hex(databuff(i)).PadLeft(2, "0"c)}" Next Return strData End Function ''' ''' 获取事件节点下的编译数据(多个事件的编译数据) ''' ''' 事件组节点 ''' Private Function GetCompliDataUnderEvents(pNode As RowNode, ByRef allCondictionsEventNodeLst As List(Of RowNode)) As List(Of Byte()) If pNode.RowType <> RowNode.RowTypeEnum.DeviceEvents Then Throw New Exception($"行号:{pNode.RowListIndex},文本:{pNode.Text}不为事件组节点") Dim lst As New List(Of Byte()) allCondictionsEventNodeLst.Clear() For Each node As RowNode In pNode.Nodes If node.Compile = False Then Continue For '过滤不编译事件 Dim eventNodeLst As New List(Of RowNode) Dim eventBuf As List(Of Byte()) = GetComplieDataUnderEvent(node, eventNodeLst) If eventBuf.Count = 0 Then Continue For allCondictionsEventNodeLst.AddRange(eventNodeLst) lst.AddRange(eventBuf) If String.IsNullOrEmpty(node.DeviceAlias) = False Then _dicScese.Add(node.DeviceAlias, _sceneIndex) End If If _lstScese.ContainsKey(_sceneIndex) = False Then _lstScese.Add(_sceneIndex, New tmpClass(node.DeviceAlias, node)) End If PrintInfo(" *行号:" & node.RowListIndex & " 场景编号:" & _sceneIndex & " ,场景名称:" & node.DeviceAlias) 'Momo 20220610 增加场景编译输出信息 _sceneIndex += 1 '更新场景编号 Next Return lst End Function ''' ''' 获取场景模式节点下的编译数据(多个条件的编译数据) ''' ''' 事件节点 ''' Private Function GetComplieDataUnderSceneModel(pNode As RowNode, ByRef eventNodeLst As List(Of RowNode)) As List(Of Byte()) If pNode.RowType <> RowNode.RowTypeEnum.ContextualModel Then Throw New Exception($"行号:{pNode.RowListIndex},文本:{pNode.Text}不为场景节点") If pNode.Compile = False Then Return New List(Of Byte()) Dim lst As New List(Of Byte()) ' Dim eventNum As UShort = 0 Dim eventNum() As Byte = BitConverter.GetBytes(CUShort(0)) Dim sceneNum() As Byte = BitConverter.GetBytes(_sceneIndex) Dim buf As List(Of Byte) eventNodeLst.Clear() '获取不同条件的填包数据 For Each node As RowNode In pNode.Nodes buf = New List(Of Byte) Dim keepParam(31) As Byte '保留字段(32字节) -> 2022-05-28 V3.1 32bytes '添加事件编号 buf.AddRange(eventNum) '事件条件相关数据 Dim conditionBuf As List(Of Byte()) = GetCompileDataUnderEventCondition(node) If conditionBuf.Count = 0 Then Continue For eventNodeLst.Add(node) buf.AddRange(conditionBuf(3)) '获取执行条件编译数据 buf.AddRange(keepParam) '条件保留32Byte buf.AddRange(conditionBuf(2)) '获取执行模式 buf.AddRange(conditionBuf(0)) '32字节,事件条件别名 2022-06-07 caocong buf.AddRange(sceneNum) '2字节,场景编号 buf.AddRange(conditionBuf(1)) '30位保留字段 buf.AddRange(conditionBuf(4)) '获取执行动作数量 buf.AddRange(conditionBuf(5)) '获取动作数据 lst.Add(buf.ToArray) Next Return lst End Function ''' ''' 获取事件节点下的编译数据(多个条件的编译数据) ''' ''' 事件节点 ''' Private Function GetComplieDataUnderEvent(pNode As RowNode, ByRef eventNodeLst As List(Of RowNode)) As List(Of Byte()) If pNode.RowType <> RowNode.RowTypeEnum.DeviceEvent Then Throw New Exception($"行号:{pNode.RowListIndex},文本:{pNode.Text}不为事件节点") If pNode.Compile = False Then Return New List(Of Byte()) '过滤不编译事件 eventNodeLst.Clear() Dim lst As New List(Of Byte()) Dim tag As DeviceEventRowNodeTag = pNode.Tag Dim strEventNum As UShort = CUShort(tag.DataValue) Dim eventNum() As Byte = BitConverter.GetBytes(strEventNum) Dim sceneNum() As Byte = BitConverter.GetBytes(_sceneIndex) Dim buf As List(Of Byte) '获取不同条件的填包数据 For Each node As RowNode In pNode.Nodes buf = New List(Of Byte) Dim keepParam(31) As Byte '保留字段(32字节) -> 2022-05-28 V3.1 32bytes '添加事件编号 buf.AddRange(eventNum) eventNodeLst.Add(node) '事件条件相关数据 Dim conditionBuf As List(Of Byte()) = GetCompileDataUnderEventCondition(node) If conditionBuf.Count = 0 Then Continue For buf.AddRange(conditionBuf(3)) '获取执行条件编译数据 buf.AddRange(keepParam) '条件保留32Byte buf.AddRange(conditionBuf(2)) '获取执行模式 buf.AddRange(conditionBuf(0)) '32字节,事件条件别名 2022-06-07 caocong buf.AddRange(sceneNum) '2字节,场景编号 buf.AddRange(conditionBuf(1)) '30位保留字段 buf.AddRange(conditionBuf(4)) '获取执行动作数量 buf.AddRange(conditionBuf(5)) '获取动作数据 lst.Add(buf.ToArray) Next Return lst End Function ''' ''' 获取事件条件节点下的编译数据(单个条件的编译数据) ''' ''' ''' Private Function GetCompileDataUnderEventCondition(pNode As RowNode) As List(Of Byte()) 'If pNode.RowType <> RowNode.RowTypeEnum.DeviceEventConditionItem Then Throw New Exception($"行号:{pNode.RowListIndex},文本:{pNode.Text}不为事件节点") 'If pNode.Compile = False Then Return New List(Of Byte()) '过滤不编译事件 Dim lst As New List(Of Byte()) Dim aliasbuf(31) As Byte 'caocong 2022-06-07 修改别名长度16Byte -> 32Byte If String.IsNullOrEmpty(pNode.DeviceAlias) = False Then Dim buf() As Byte = AliasEncoding.GetBytes(pNode.DeviceAlias) If buf.Length > aliasbuf.Length Then Array.Copy(buf, 0, aliasbuf, 0, aliasbuf.Length) Else Array.Copy(buf, 0, aliasbuf, 0, buf.Length) End If End If lst.Add(aliasbuf) '32字节,事件条件别名 '30位保留字段 Dim keepBuf(31) As Byte lst.Add(keepBuf) For Each node As RowNode In pNode.Nodes If node.Text.Contains("睡眠场景") OrElse node.Text.Contains("睡眠模式") Then Console.WriteLine(node.Text) End If If node.RowListIndex > 575 Then Console.WriteLine("") End If Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventAllConditions lst.Add(GetConditionDataUnderConditionGroup(node))'获取执行条件编译数据 Case RowNode.RowTypeEnum.DeviceEventActionModeGroup lst.Add(New Byte() {GetExecModeDataUnderCondtion(node)})'获取执行模式 Case RowNode.RowTypeEnum.DeviceEventActions If node.Compile Then Dim actionCount As Integer = GetActionCount(node, New List(Of String)) If actionCount = 0 Then Return New List(Of Byte()) '没有动作节点则退出 If actionCount > MaxActionCount Then Throw New Exception($"当前动作总数({actionCount})超过上限({MaxActionCount})") lst.Add(New Byte() {actionCount}) '获取执行动作数量 Dim actionBuf() As Byte = GetActionDataByActionGroup(node) If actionBuf.Length = 0 Then Return New List(Of Byte()) '没有动作数据则退出 End If lst.Add(actionBuf) '获取动作数据 Else Return New List(Of Byte()) '没有动作组不参与编译则退出 End If Case Else Throw New Exception($"[{node.RowListIndex}]:[{node.Text}]无效的事件条件节点") End Select Next Return lst End Function ''' ''' 通过设备对象别名,查找设备对象回路信息 ''' ''' ''' Private Function GetActionDeviceLoop(name As String) As Byte() Dim node As RowNode = _objectGroups(name) Dim tag As DeviceObjectRowNodeTag = node.Tag Return BitConverter.GetBytes(CShort(tag.Device.LoopAddr)) End Function ''' ''' 获取场景节点的设备类型 ''' ''' Private Function GetContextualModelDeviceType() As Byte 'If node.RowType <> RowNode.RowTypeEnum.ContextualModel AndAlso ' node.RowType <> RowNode.RowTypeEnum.DeviceEvent Then Throw New Exception($"行号:{node.RowListIndex} 不为场景模式节点或事件节点") Return CInt(FindAttributeValueUnderModel(_modelNode, $"场景设备组信息", "DeviceType")) End Function ''' ''' 获取场景节点的设备地址 ''' ''' Private Function GetContextualModelDeviceAddr() As Byte ' If node.RowType <> RowNode.RowTypeEnum.ContextualModel AndAlso 'node.RowType <> RowNode.RowTypeEnum.DeviceEvent Then Throw New Exception($"行号:{node.RowListIndex} 不为场景模式节点或事件节点") Return CInt(FindAttributeValueUnderModel(_modelNode, $"场景设备组信息", "DeviceAddr")) End Function ''' ''' 获取指定名称设备对象的设备类型 ''' ''' 设备节点所在行 ''' Private Function GetActionDeviceType(index As Integer) As Byte Dim modelNode As RowNode = _modelGroups2(index) Select Case modelNode.RowType Case RowNode.RowTypeEnum.Model 'RCU模型 Dim devGroup As String = _rootNode.RowList(index).ParentNode.Name Return CInt(FindAttributeValueUnderModel(modelNode, $"{devGroup}设备组信息", "DeviceType")) Case RowNode.RowTypeEnum.ExternalModel '外接模型 'Dim tag As ModelRowNodeTag = modelNode.Tag 'Return tag.Desc.DevTypeData '2022-05-25 CaoCong 修改,设备类型在XML中位置有变动 Dim objGroupNode As RowNode = _rootNode.RowList(index).ParentNode If objGroupNode.RowType <> RowNode.RowTypeEnum.DeviceGroup Then Throw New Exception("获取设备类型意料之外的情况 - 未找到模型外设组") End If If objGroupNode.Compile = False Then Throw New Exception("获取设备类型意料之外的结果 - 动作未使能") End If Return CByte(objGroupNode.DEV_TYPE_DATA) Case Else Throw New Exception("获取设备类型意料之外的结果") End Select End Function ''' ''' 获取指定名称设备对象的设备类型 ''' ''' 设备对象别名 ''' Private Function GetActionDeviceType(name As String) As Byte Dim modelNode As RowNode = _modelGroups(name) Select Case modelNode.RowType Case RowNode.RowTypeEnum.Model 'RCU模型 Dim devGroup As String = _objectGroups(name).ParentNode.Name Return CInt(FindAttributeValueUnderModel(modelNode, $"{devGroup}设备组信息", "DeviceType")) Case RowNode.RowTypeEnum.ExternalModel '外接模型 'Dim tag As ModelRowNodeTag = modelNode.Tag 'Return tag.Desc.DevTypeData '2022-05-25 CaoCong 修改,设备类型在XML中位置有变动 Dim objGroupNode As RowNode = _objectGroups(name).ParentNode If objGroupNode.RowType <> RowNode.RowTypeEnum.DeviceGroup Then Throw New Exception("获取设备类型意料之外的情况 - 未找到模型外设组") End If If objGroupNode.Compile = False Then Throw New Exception("获取设备类型意料之外的结果 - 动作未使能") End If Return CByte(objGroupNode.DEV_TYPE_DATA) Case Else Throw New Exception("获取设备类型意料之外的结果") End Select End Function ''' ''' 获取执行名称设备对象的设备地址 ''' ''' 设备节点所在行 ''' Private Function GetActionDeviceAddr(index As Integer) As Byte Dim modelNode As RowNode = _modelGroups2(index) Select Case modelNode.RowType Case RowNode.RowTypeEnum.Model 'RCU模型 Dim devGroup As String = _rootNode.RowList(index).ParentNode.Name Return CInt(FindAttributeValueUnderModel(modelNode, $"{devGroup}设备组信息", "DeviceAddr")) Case RowNode.RowTypeEnum.ExternalModel '外接模型 Return CInt(FindAttributeValueUnderModel(modelNode, "设备存在", "拨码地址")) Case Else Throw New Exception("获取设备地址意料之外的结果") End Select End Function ''' ''' 获取执行名称设备对象的设备地址 ''' ''' 设备对象别名 ''' Private Function GetActionDeviceAddr(name As String) As Byte Dim modelNode As RowNode = _modelGroups(name) Select Case modelNode.RowType Case RowNode.RowTypeEnum.Model 'RCU模型 Dim devGroup As String = _objectGroups(name).ParentNode.Name Return CInt(FindAttributeValueUnderModel(modelNode, $"{devGroup}设备组信息", "DeviceAddr")) Case RowNode.RowTypeEnum.ExternalModel '外接模型 Return CInt(FindAttributeValueUnderModel(modelNode, "设备存在", "拨码地址")) Case Else Throw New Exception("获取设备地址意料之外的结果") End Select End Function ''' ''' 获取节点组下所有动作的编译数据 ''' ''' ''' Private Function GetActionDataByActionGroup(pNode As RowNode) As Byte() If pNode.RowType <> RowNode.RowTypeEnum.DeviceEventActions Then Throw New Exception($"行号:{pNode.RowListIndex},文本:{pNode.Text}不为动作组节点") If pNode.Compile = False Then Return New Byte() {} Dim lst As New List(Of Byte) For Each node As RowNode In pNode.Nodes If node.Compile = False Then Continue For If String.IsNullOrEmpty(node.DeviceType) Then Continue For If String.IsNullOrEmpty(node.DeviceName) Then Continue For If node.DeviceType = "动作组" Then If _actionGroups.ContainsKey(node.DeviceName) Then lst.AddRange(GetActionDataByActionGroup(_actionGroups(node.DeviceName))) Else Throw New Exception($"行号:[{node.RowListIndex}] ,动作组中不包含:[{node.DeviceName}]") End If Else If String.IsNullOrEmpty(node.DeviceMothed) Then Continue For Try lst.AddRange(GetActionData(node)) Catch ex As Exception Throw New Exception($"行号:{node.RowListIndex} 动作编译异常:{ex.Message}") End Try End If Next Return lst.ToArray End Function Public Event updanodetext(node As RowNode) ''' ''' 从动作行节点获取动作数据 ''' ''' ''' Private Function GetActionData(node As RowNode) As Byte() If node.RowType <> RowNode.RowTypeEnum.DeviceEventAction Then Throw New Exception($"行号:{node.RowListIndex},文本:{node.Text}不为动作节点") Dim buf(7) As Byte '设备类型,外接设备设备类型(主机特殊处理) buf(ActionDataParam.DeviceType) = GetActionDeviceType(node.DeviceName) '设备地址,选择对象的设备拨码地址(主机特殊处理) buf(ActionDataParam.DeviceAddr) = GetActionDeviceAddr(node.DeviceName) '设备回路,选择对象的回路地址 Dim loopBuf() As Byte = GetActionDeviceLoop(node.DeviceName) Array.Copy(loopBuf, 0, buf, ActionDataParam.DeviceLoop, loopBuf.Length) Dim buf2() As Byte = GetExecMode(buf(ActionDataParam.DeviceType), node) '执行方式,不同设备类型有不同方式 buf(ActionDataParam.ExecMode) = buf2(0) '执行方式 '执行内容,不同设备类型有不同内容 buf(ActionDataParam.ExecInfo) = buf2(1) '执行内容 '延时时间,动作执行延时 buf(ActionDataParam.DelayTime) = GetDelayTime(node.DelayTime) '延时时间 '延时单位,做东执行延时单位 buf(ActionDataParam.DelayUnit) = GetDelayUnit(node.DelayUnit) '延时单位 '2022-10-31 Momo 打印动作数据 Dim tmpStr As String = BitConverter.ToString(buf).Replace("-", " ") PrintInfo(" [行号:" & node.RowListIndex & "] - " & "> 动作数据:" & tmpStr) Return buf End Function ''' ''' 根据动作节点内容获取执行方式与执行内容 ''' ''' 设备类型 ''' 动作节点 ''' Private Function GetExecMode(devType As Byte, node As RowNode) As Byte() '参考设备详细协议进行填充 Dim buf(1) As Byte Select Case devType Case DeviceTypes.指令场景 '涉及打开与关闭,参考强电继电器 buf(0) = node.Params(0).ValueData Case DeviceTypes.强电继电器 Dim sw As Integer '开关状态 sw = CInt(node.Params(0).ValueData) buf(0) = sw Case DeviceTypes.弱电输入 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") buf(0) = node.Params(0).ValueData buf(1) = node.Params(1).ValueData Case DeviceTypes.弱电输出 buf(0) = CInt(node.Params(0).ValueData) If node.Params.Count >= 2 Then buf(1) = CInt(node.Params(1).ValueData) End If Case DeviceTypes.服务信息 Dim sw As Integer '开关状态 sw = CInt(node.Params(0).ValueData) buf(0) = sw Case DeviceTypes.干接点窗帘 '基类为CURTAIN的类型 buf(0) = CInt(node.Params(0).ValueData) Case DeviceTypes.开关 '基类为Light的类型 buf(0) = CInt(node.Params(0).ValueData) Case DeviceTypes.空调 '基类为Temp的类型 Dim sw As Integer = CInt(node.Params(0).ValueData) '开关状态 Dim mode As Integer = CInt(node.Params(1).ValueData) '模式 Dim speed As Integer = CInt(node.Params(2).ValueData) '风速 Dim fm As Integer = CInt(node.Params(3).ValueData) '阀门 Dim temp As Integer = CInt(node.Params(4).ValueData) '温度 'start 2022-05-03 Temp 直接顺序调换 --------------------------b 'buf(0) = fm 'buf(0) = buf(0) Or (speed << 2) 'buf(0) = buf(0) Or (mode << 4) 'buf(0) = buf(0) Or (sw << 6) 'buf(1) = temp buf(1) = fm buf(1) = buf(1) Or (speed << 2) buf(1) = buf(1) Or (mode << 4) buf(1) = buf(1) Or (sw << 6) buf(0) = temp 'end 2022-05-03 Temp 直接顺序调换 ---------------------------- Case DeviceTypes.红外感应 '只有开关状态,参考强电继电器 Dim sw As Integer '开关状态 sw = CInt(node.Params(0).ValueData) buf(0) = sw Case DeviceTypes.空气质量检测设备 '特殊类型,暂无处理 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.插卡取电 '无控制方法 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.地暖 'Dim sw As Integer '开关状态 'Dim mode As Integer '模式 'Dim fm As Integer '阀门 'Dim temp As Integer '温度 'buf(0) = buf(0) Or (mode << 0) 'buf(0) = buf(0) Or (sw << 4) 'buf(1) = temp 'buf(1) = buf(1) Or (fm << 6) 'CZH注释 '''buf(0) = node.Params(0).ValueData '''If node.Params.Count > 1 Then ''' ' buf(1) = node.Params(1).ValueData ''' Dim temp As Integer = CInt(node.Params(1).ValueData) '温度 ''' buf(1) = temp '''End If buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData ' Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.RCU设备网络 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.窗帘 buf(0) = node.Params(0).ValueData Case DeviceTypes.继电器 Dim sw As Integer '开关状态 sw = CInt(node.Params(0).ValueData) buf(0) = sw Case DeviceTypes.红外发送 buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.直流调光 buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.可控硅调光 buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.灯带 buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.中控 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.微信锁 buf(0) = node.Params(0).ValueData Case DeviceTypes.背景音乐 ''Music类型 'Dim dirIndex As Integer = node.Params(0).ValueData '文件夹索引 'Dim modeStatus As Integer = node.Params(1).ValueData '播放时场景状态 'Dim fileIndex As Integer = node.Params(2).ValueData '文件索引 '2022-05-06 Caocong: 先将变量初始化为0.有可能没有三个参数 Dim dirIndex As Integer = 0 'node.Params(0).ValueData '文件夹索引 Dim modeStatus As Integer = 0 'node.Params(1).ValueData '播放时场景状态 Dim fileIndex As Integer = 0 'node.Params(2).ValueData '文件索引 Select Case node.Params.Count Case 1 dirIndex = node.Params(0).ValueData Case 2 dirIndex = node.Params(0).ValueData '文件夹索引 modeStatus = node.Params(1).ValueData '播放时场景状态 Case 3 dirIndex = node.Params(0).ValueData '文件夹索引 modeStatus = node.Params(1).ValueData '播放时场景状态 fileIndex = node.Params(2).ValueData '文件索引 Case Else End Select '2022-05-06 Caocong: 先将变量初始化为0.有可能没有三个参数 ---end buf(0) = buf(0) Or (dirIndex << 0) buf(0) = buf(0) Or (modeStatus << 4) buf(1) = fileIndex '2023-03-02 CZH: 新增 新风设备 类型 Case DeviceTypes.新风设备 buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.房态下发 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.主机本地调光 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.PWM调光 buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.总线调光 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.RCU电源 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.A9IO开关 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.A9IO扩展 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.A9IO电源 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.无线网关轮询 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.无线网关主动 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.无线门磁 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.空气参数显示设备 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.无线继电器红外 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.时间同步 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.监控控制 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.旋钮开关 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.BLV_CxIO类型 Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") Case DeviceTypes.中控管道 buf(0) = CInt(node.Params(0).ValueData) Case DeviceTypes.域控管道 buf(0) = CInt(node.Params(0).ValueData) Case DeviceTypes.PB_总线 buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.PB_BUS_LINE buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.PB_STRIP buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.PB_Relay buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case DeviceTypes.无卡断电 buf(0) = node.Params(0).ValueData If node.Params.Count > 1 Then buf(1) = node.Params(1).ValueData Case Else Throw New Exception($”行号:{node.RowListIndex},未处理的设备类型") End Select Return buf End Function Enum DeviceTypes 指令场景 强电继电器 弱电输入 弱电输出 服务信息 干接点窗帘 开关 空调 红外感应 空气质量检测设备 插卡取电 地暖 RCU设备网络 窗帘 继电器 红外发送 直流调光 可控硅调光 灯带 中控 微信锁 背景音乐 房态下发 主机本地调光 PWM调光 总线调光 RCU电源 A9IO开关 A9IO扩展 A9IO电源 无线网关轮询 无线网关主动 无线门磁 空气参数显示设备 无线继电器红外 时间同步 监控控制 旋钮开关 BLV_CxIO类型 '2023-03-02 CZH 插卡状态虚拟设备 新风设备 人脸机 '未做 中控管道 域控管道 无卡断电 PB_总线 = 48 PB_BUS_LINE PB_STRIP PB_Relay End Enum ''' ''' Integer 类型转 3 字节 byte数组,高字节在前 ''' ''' ''' Public Function iByte3(ByVal i As Integer) As Byte() Dim btemp() As Byte = {0, 0, 0} Dim b() As Byte = BitConverter.GetBytes(i) btemp(2) = b(2) btemp(1) = b(1) btemp(0) = b(0) Return btemp End Function ''' ''' Integer 类型转 4 字节 byte数组,高字节在前 ''' ''' ''' Public Function iByte4(ByVal i As Integer) As Byte() Dim btemp() As Byte = {0, 0, 0, 0} Dim b() As Byte = BitConverter.GetBytes(i) btemp(3) = b(3) btemp(2) = b(2) btemp(1) = b(1) btemp(0) = b(0) Return btemp End Function Private Function GetDelayUnit(str As String) As Byte Dim result As Integer Select Case str Case "ms" result = 1 Case "s" result = 2 Case "m" result = 3 Case "h" result = 4 Case "d" result = 5 Case Else result = 1 End Select Return result End Function ''' ''' 获取延时时间 ''' ''' ''' Private Function GetDelayTime(str As String) As Byte If String.IsNullOrEmpty(str) Then Return 0 Dim num As Integer If Integer.TryParse(str, num) Then If num > 255 Then num = 255 ElseIf num < 0 Then num = 0 End If Else num = 0 End If Return num End Function ''' ''' 获取动作组节点下动作总数 ''' ''' ''' Private Function GetActionCount(pNode As RowNode, groupStack As List(Of String)) As Byte If pNode.Compile = False Then Return 0 '检测是否动作组嵌套调用 If String.IsNullOrEmpty(pNode.DeviceAlias) = False Then If groupStack.Contains(pNode.DeviceAlias) Then Throw New Exception($"行号:[{pNode.RowListIndex}]:[{pNode.DeviceAlias}]动作组递归调用,递归调用过程:{String.Join("->", groupStack)}->{pNode.DeviceAlias}") groupStack.Add(pNode.DeviceAlias) End If Dim result As Byte For Each node As RowNode In pNode.Nodes If node.Compile = False Then Continue For If String.IsNullOrEmpty(node.DeviceType) Then Continue For If String.IsNullOrEmpty(node.DeviceName) Then Continue For If node.DeviceType = "动作组" Then If _actionGroups.ContainsKey(node.DeviceName) Then result += GetActionCount(_actionGroups(node.DeviceName), groupStack) Else Throw New Exception($"行号:{node.RowListIndex},文本:{node.Text}不为设备对象节点") End If Else If String.IsNullOrEmpty(node.DeviceMothed) Then Continue For result += 1 End If Next Return result End Function ''' ''' 执行条件转换为编译数据类 ''' 2022-05-10 曹聪 ''' 1、将变量类型从Integer改为Uint64 变量左移溢出导致条件参数不正确 ''' 2、条件参数中背光状态没有调用 ''' Public Class ConditionConverter Public Property 动作输出使能 As UInt64 Public Property 房态 As UInt64 Public Property 控制取电服务 As UInt64 Public Property 取电状态 As UInt64 Public Property 勿扰状态 As UInt64 Public Property 清理状态 As UInt64 Public Property 呼叫状态 As UInt64 Public Property 洗衣状态 As UInt64 Public Property 退房状态 As UInt64 Public Property 稍后状态 As UInt64 Public Property SOS状态 As UInt64 Public Property 预约待租状态 As UInt64 Public Property 开锁状态 As UInt64 Public Property 行李状态 As UInt64 Public Property 保险箱状态 As UInt64 Public Property 门磁状态 As UInt64 Public Property 提示音状态 As UInt64 Public Property 背光状态 As UInt64 Public Property 季节状态 As UInt64 Public Property 时间状态 As UInt64 Public Property 起夜状态 As UInt64 Public Property 锁定状态 As UInt64 Public Function GetConditionData() As Byte() Dim num As UInt64 = 0 num = num Or (动作输出使能 << ConditionBits.动作输出使能) num = num Or (房态 << ConditionBits.房态) num = num Or (控制取电服务 << ConditionBits.控制取电服务) num = num Or (取电状态 << ConditionBits.取电状态) num = num Or (勿扰状态 << ConditionBits.勿扰状态) num = num Or (清理状态 << ConditionBits.清理状态) num = num Or (呼叫状态 << ConditionBits.呼叫状态) num = num Or (洗衣状态 << ConditionBits.洗衣状态) num = num Or (退房状态 << ConditionBits.退房状态) num = num Or (稍后状态 << ConditionBits.稍后状态) num = num Or (SOS状态 << ConditionBits.SOS状态) num = num Or (预约待租状态 << ConditionBits.预约待租状态) num = num Or (开锁状态 << ConditionBits.开锁状态) num = num Or (行李状态 << ConditionBits.行李状态) num = num Or (保险箱状态 << ConditionBits.保险箱状态) num = num Or (门磁状态 << ConditionBits.门磁状态) num = num Or (提示音状态 << ConditionBits.提示音状态) num = num Or (背光状态 << ConditionBits.背光状态) num = num Or (季节状态 << ConditionBits.季节状态) num = num Or (时间状态 << ConditionBits.时间状态) num = num Or (起夜状态 << ConditionBits.起夜状态) num = num Or (锁定状态 << ConditionBits.锁定状态) Return BitConverter.GetBytes(num) End Function Enum ConditionBits ''' 动作输出使能 动作输出使能 = 0 ''' 房态 房态 = 1 ''' 控制取电服务 控制取电服务 = 4 ''' 取电状态 取电状态 = 5 ''' 勿扰状态 勿扰状态 = 8 ''' 清理状态 清理状态 = 11 ''' 呼叫状态 呼叫状态 = 14 ''' 洗衣状态 洗衣状态 = 17 ''' 退房状态 退房状态 = 20 ''' 稍后状态 稍后状态 = 23 ''' SOS状态 SOS状态 = 26 ''' 预约待租状态 预约待租状态 = 29 ''' 开锁状态 开锁状态 = 32 ''' 行李状态 行李状态 = 35 ''' 保险箱状态 保险箱状态 = 38 ''' 门磁状态 门磁状态 = 41 ''' 提示音状态 提示音状态 = 44 ''' 背光状态 背光状态 = 47 ''' 季节状态 季节状态 = 50 ''' 时间状态 时间状态 = 53 ''' 起夜状态 起夜状态 = 56 ''' 锁定状态 锁定状态 = 59 ''' 保留字段 保留字段 = 62 End Enum End Class ''' 配置信息协议位 Enum ConfigParam ''' 配置发布作者 ConfigReleaseAuthor ''' 配置软件版本号 ConfigSoftwareVer ''' 配置发布日期 ReleaseDate ''' 用户名 UserName ''' 项目编号 ProjectIndex ''' 房型ID RoomTypeID ''' 房型别名 RommTypeAlias ''' 配置数据版本 ConfigDataVer End Enum ''' ''' 设备存在协议位 ''' Enum DeviceExsistParam ''' 设备类型 DeviceType ''' 设备地址 DeviceAddr ''' 485端口 Port_485 ''' 波特率 BaudRate ''' 设备协议版本 ProtocolVer = BaudRate + 4 ''' 通讯重发次数 RetryCount ''' 通讯等待时间 WaitTime ''' 保留 KeepParams = WaitTime + 2 ''' 输入回路数 InputLoopCount = KeepParams + 32 ''' 输出回路数 OutputLoopCount = InputLoopCount + 2 ''' 回路别名 LoopAlias = OutputLoopCount + 2 End Enum ''' 设备动作协议位 Enum ActionParam ''' 设备类型 DeviceType ''' 设备地址 DeviceAddr ''' 设备动作编号 DeviceActionNum ''' 设备输入回路 DeviceInputLoop = DeviceActionNum + 2 ''' 设备输入类型 DeviceInputType = DeviceInputLoop + 2 ''' 动作执行条件 ActionCondition = DeviceInputType + 2 ''' 动作执行方式 ActionMode = ActionCondition + 8 ''' 设备动作别名 ActionAlias ''' 保留参数 KeepParam = ActionAlias + 16 ''' 输出设备动作数 ActionCount = KeepParam + 32 ''' 设备动作 ActionParams End Enum ''' 设备动作参数协议位 Enum ActionDataParam ''' 设备类型,外接设备设备类型(主机特殊处理) DeviceType ''' 设备地址,选择对象的设备拨码地址(主机特殊处理) DeviceAddr ''' 设备回路,选择对象的回路地址,2位 DeviceLoop ''' 执行方式,不同设备类型有不同方式 ExecMode = DeviceLoop + 2 ''' 执行内容,不同设备类型有不同内容 ExecInfo ''' 延时时间,动作执行延时 DelayTime ''' 延时单位,做东执行延时单位 DelayUnit End Enum End Class