Files
Desktop_BLVStudio_EN/BLV_Studio/ModelGrid/RowNodeCompile.vb

3129 lines
124 KiB
VB.net
Raw Normal View History

2025-12-11 14:22:51 +08:00
Imports System.Net
Imports BLV_Studio.GridModel
Imports BLV_Studio.GridModel.DeviceEventModel
Public Class RowNodeCompile
''' <summary>输出信息打印</summary>
Public Event OutputPrint(sender As Object, e As OutputPrintEventArgs)
Public _rootNode As RowNode
Public _configInfo As ConfigInfoStuct
''' <summary>
''' 场景编号,从1开始
''' </summary>
Public _sceneIndex As UShort
''' <summary>
''' 动作编号,从1开始
''' </summary>
Public _actionIndex As UShort
''' <summary>
''' 便于索引的动作编号
''' </summary>
Private _tempActionIndex As UShort
''' <summary>
''' 事件键值对,用于保存事件编号和对应的节点
''' </summary>
Public _eventRowNode As Dictionary(Of UShort, RowNode)
''' <summary>
''' 节点集合,表明该设备在哪些地方产生了调用
''' </summary>
Public _objectWhereUsed As Dictionary(Of String, List(Of RowNode))
''' <summary>
''' 节点集合,表明该动作组被哪些地方调用
''' </summary>
Public _actionGroupWhereUsed As Dictionary(Of String, List(Of RowNode))
''' <summary>
''' 节点集合,表明该场景被哪些地方调用
''' </summary>
Public _contexualGroupsWhereUsed As Dictionary(Of String, List(Of RowNode))
''' <summary>
''' 所有已配置词条的小宝的集合
''' </summary>
Public _xiaobaoUsed As List(Of RowNode)
''' <summary>
''' 动作组集合,键为动作组别名,键位动作组节点
''' </summary>
Public _actionGroups As Dictionary(Of String, RowNode)
''' <summary>
''' 模型集合,键为设备对象别名,键为模型节点
''' </summary>
Public _modelGroups As Dictionary(Of String, RowNode)
''' <summary>
''' 模型集合,键为设备对象行号,键为模型节点
''' </summary>
Public _modelGroups2 As Dictionary(Of Integer, RowNode)
''' <summary>
''' 设备对象集合,键为设备对象别名,键为设备对象节点
''' </summary>
Public _objectGroups As Dictionary(Of String, RowNode)
''' <summary>
''' 场景模式集合,键为设备对象别名,键为设备对象节点
''' </summary>
Public _contextualGroups As Dictionary(Of String, RowNode)
''' <summary>
''' 所有设备对象的集合
''' </summary>
Public _objectLst As List(Of RowNode)
''' <summary>
''' 所有非设备事件的自定义场景集合
''' </summary>
Public _contexualLst As List(Of RowNode)
''' <summary>
''' 所有设备存在的集合
''' </summary>
Public _deviceExists As List(Of RowNode)
''' <summary>
''' 所有小宝的集合
''' </summary>
Public _xiaobao As List(Of RowNode)
''' <summary>
''' RCU模型节点
''' </summary>
Public _modelNode As RowNode
''' <summary>
''' 别名转换所使用的编码格式,默认方式GBK
''' </summary>
Public Property AliasEncoding As Text.Encoding
''' <summary>
''' 单条数据帧,最大动作数量,默认80
''' </summary>
Public Property MaxActionCount As Integer
''' <summary>
''' 键为场景别名,值为场景编号
''' </summary>g
Private _dicScese As Dictionary(Of String, UShort)
''' <summary>
''' 键为场景编号,值为场景别名与设备动作编号
''' </summary>
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 "输出打印"
''' <summary>
''' 输出对应类型信息
''' </summary>
''' <param name="type"></param>
''' <param name="txt"></param>
Private Sub Print(type As OutputPrintEventArgs.Types, txt As String)
RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(type, txt))
End Sub
''' <summary>
''' 输出执行信息
''' </summary>
''' <param name="txt"></param>
Private Sub PrintInfo(txt As String)
RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(OutputPrintEventArgs.Types.Info, txt))
End Sub
''' <summary>
''' 输出警告信息
''' </summary>
''' <param name="txt"></param>
Private Sub PrintWarning(txt As String)
RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(OutputPrintEventArgs.Types.Warn, txt))
End Sub
''' <summary>
''' 输出错误信息
''' </summary>
''' <param name="txt"></param>
Private Sub PrintError(txt As String)
RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(OutputPrintEventArgs.Types.Error, txt))
End Sub
#End Region
''' <summary>
''' 填充编译所需要的必要索引信息
''' </summary>
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
''' <summary>
''' 编译
''' </summary>
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
''' <summary>
''' 下载
''' </summary>
Public Sub Download()
End Sub
''' <summary>
''' 规则检测
''' </summary>
Public Sub RuleCheck()
End Sub
''' <summary>
''' 填充数据帧
''' </summary>
''' <param name="data">包含帧类型和帧参数</param>
''' <returns></returns>
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
''' <summary>
''' CRC16校验
''' </summary>
''' <param name="dataBuff"></param>
''' <param name="length"></param>
''' <returns></returns>
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
''' <summary>
''' 在模型节点下查询指定名称的设备组节点
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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
''' <summary>
''' 在模型节点下查询属性集节点
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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
''' <summary>
''' 在属性集节点下查询指定名称的属性组节点
''' </summary>
''' <param name="pNode">属性集合节点</param>
''' <param name="name">属性组名称</param>
''' <returns></returns>
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
''' <summary>
''' 在属性组节点下查询属性节点
''' </summary>
''' <param name="pNode"></param>
''' <param name="name"></param>
''' <returns></returns>
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
''' <summary>
''' 获取节点选择项对应的数值
''' </summary>
''' <param name="node"></param>
''' <returns></returns>
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
''' <summary>
''' 在模型节点下查询指定组名下的指定名称属性节点
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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
''' <summary>
''' 在模型节点下查询指定组名下的指定名称的属性节点值
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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
''' <summary>
''' 在模型节点下查询指定组名下的指定名称的属性节点值
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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
''' <summary>
''' 在属性组节点下查询指定属性名的属性节点值
''' </summary>
''' <param name="pNode">属性组节点</param>
''' <param name="attributeName">属性值</param>
''' <returns></returns>
Private Function FindAttributeValueUnderGroup(pNode As RowNode, attributeName As String) As String
Dim node As RowNode = FindAttributeUnderAttributeGroup(pNode, attributeName)
Return GetNodeSelectStringValue(node)
End Function
''' <summary>
''' 在模型节点下查询指定名称的设备组节点
''' </summary>
''' <param name="pNode">模型节点</param>
''' <param name="name">设备组名</param>
''' <returns></returns>
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
''' <summary>
''' 填充小宝数据
''' </summary>
''' <returns></returns>
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
''' <summary>
''' 获取小宝词条组的数据
''' </summary>
''' <param name="pNode">小宝词条组节点</param>
''' <returns></returns>
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
''' <summary>
''' 填充配置信息
''' 修改记录:
''' 2022-05-16 曹聪
''' 1、下发的软件版本类型不对 - 已修改
''' 2、下发的中文编码不对 - 已修改
''' </summary>
''' <returns></returns>
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
''' <summary>
''' 填充设备存在
''' </summary>
''' <returns></returns>
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 新增 自检功率 命令数据
''' <summary>
''' 根据RCU模型的设备存在属性组配置设备存在数据
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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
''' <summary>
''' 根据RCU模型的设备存在属性组配置设备存在数据
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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
''' <summary>
''' 获取输入类型设备对象的回路设置
''' </summary>
''' <param name="pNode"></param>
''' <returns></returns>
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
''' <summary>
''' 根据连接在485设备下的模型节点信息配置设备存在数据
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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
''' <summary>
''' 配置RCU模型设备存在数据
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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
''' <summary>
''' 根据连接在485设备下的模型节点信息配置设备存在数据
''' </summary>
''' <param name="pNode">模型节点</param>
''' <returns></returns>
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 = DevTypeDataProtocolVer
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以前整个设备共用DevTypeDataV3.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以前整个设备共用ProtocolVerV3.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
''' <summary>
''' 获取事件条件节点下的条件执行方式节点
''' </summary>
''' <param name="pNode">设备对象节点</param>
''' <returns></returns>
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
''' <summary>
''' 在动作执行方式组节点下查询指定名称的动作执行方式节点
''' </summary>
''' <param name="pNode">模型节点</param>
''' <param name="name">设备组名</param>
''' <returns></returns>
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
''' <summary>
''' 获取事件条件下的编译数据
''' </summary>
''' <param name="pNode">条件组节点</param>
''' <returns></returns>
Private Function GetDataUnderEventCondition(pNode As RowNode) As List(Of Byte())
Dim lst As New List(Of Byte())
Return lst
End Function
''' <summary>
''' 获取设备对象的回路地址
''' </summary>
''' <param name="node"></param>
''' <returns></returns>
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
''' <summary>
''' 获取执行方式组节点下的执行方式编译数据
''' </summary>
''' <param name="pNode"></param>
''' <returns></returns>
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
''' <summary>
''' 获取条件组节点下的条件编译数据
''' </summary>
''' <param name="pNode">条件组节点</param>
''' <returns></returns>
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
''' <summary>
''' 获取设备对象下的所有动作编译数据(所有的设备对象动作数据)
''' </summary>
''' <returns></returns>
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
''' <summary>
''' 获取场景模式集下的所有编译数据(多个节点的场景数据)
''' </summary>
''' <returns></returns>
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
''' <summary>
''' 获取设备节点下的所有编译数据(多个节点的事件数据)
''' </summary>
''' <param name="pNode">设备对象节点</param>
''' <returns></returns>
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
''' <summary>
''' 获取事件节点下的编译数据(多个事件的编译数据)
''' </summary>
''' <param name="pNode">事件组节点</param>
''' <returns></returns>
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
''' <summary>
''' 获取场景模式节点下的编译数据(多个条件的编译数据)
''' </summary>
''' <param name="pNode">事件节点</param>
''' <returns></returns>
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
''' <summary>
''' 获取事件节点下的编译数据(多个条件的编译数据)
''' </summary>
''' <param name="pNode">事件节点</param>
''' <returns></returns>
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
''' <summary>
''' 获取事件条件节点下的编译数据(单个条件的编译数据)
''' </summary>
''' <param name="pNode"></param>
''' <returns></returns>
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
''' <summary>
''' 通过设备对象别名,查找设备对象回路信息
''' </summary>
''' <param name="name"></param>
''' <returns></returns>
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
''' <summary>
''' 获取场景节点的设备类型
''' </summary>
''' <returns></returns>
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
''' <summary>
''' 获取场景节点的设备地址
''' </summary>
''' <returns></returns>
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
''' <summary>
''' 获取指定名称设备对象的设备类型
''' </summary>
''' <param name="index">设备节点所在行</param>
''' <returns></returns>
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
''' <summary>
''' 获取指定名称设备对象的设备类型
''' </summary>
''' <param name="name">设备对象别名</param>
''' <returns></returns>
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
''' <summary>
''' 获取执行名称设备对象的设备地址
''' </summary>
''' <param name="index">设备节点所在行</param>
''' <returns></returns>
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
''' <summary>
''' 获取执行名称设备对象的设备地址
''' </summary>
''' <param name="name">设备对象别名</param>
''' <returns></returns>
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
''' <summary>
''' 获取节点组下所有动作的编译数据
''' </summary>
''' <param name="pNode"></param>
''' <returns></returns>
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)
''' <summary>
''' 从动作行节点获取动作数据
''' </summary>
''' <param name="node"></param>
''' <returns></returns>
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
''' <summary>
''' 根据动作节点内容获取执行方式与执行内容
''' </summary>
''' <param name="devType">设备类型</param>
''' <param name="node">动作节点</param>
''' <returns></returns>
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
''' <summary>
''' Integer 类型转 3 字节 byte数组高字节在前
''' </summary>
''' <param name="i"></param>
''' <returns></returns>
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
''' <summary>
''' Integer 类型转 4 字节 byte数组高字节在前
''' </summary>
''' <param name="i"></param>
''' <returns></returns>
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
''' <summary>
''' 获取延时时间
''' </summary>
''' <param name="str"></param>
''' <returns></returns>
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
''' <summary>
''' 获取动作组节点下动作总数
''' </summary>
''' <param name="pNode"></param>
''' <returns></returns>
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
''' <summary>
''' 执行条件转换为编译数据类
''' 2022-05-10 曹聪
''' 1、将变量类型从Integer改为Uint64 变量左移溢出导致条件参数不正确
''' 2、条件参数中背光状态没有调用
''' </summary>
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
''' <summary>动作输出使能</summary>
动作输出使能 = 0
''' <summary>房态</summary>
房态 = 1
''' <summary>控制取电服务</summary>
控制取电服务 = 4
''' <summary>取电状态</summary>
取电状态 = 5
''' <summary>勿扰状态</summary>
勿扰状态 = 8
''' <summary>清理状态</summary>
清理状态 = 11
''' <summary>呼叫状态</summary>
呼叫状态 = 14
''' <summary>洗衣状态</summary>
洗衣状态 = 17
''' <summary>退房状态</summary>
退房状态 = 20
''' <summary>稍后状态</summary>
稍后状态 = 23
''' <summary>SOS状态</summary>
SOS状态 = 26
''' <summary>预约待租状态</summary>
预约待租状态 = 29
''' <summary>开锁状态</summary>
开锁状态 = 32
''' <summary>行李状态</summary>
行李状态 = 35
''' <summary>保险箱状态</summary>
保险箱状态 = 38
''' <summary>门磁状态</summary>
门磁状态 = 41
''' <summary>提示音状态</summary>
提示音状态 = 44
''' <summary>背光状态</summary>
背光状态 = 47
''' <summary>季节状态</summary>
季节状态 = 50
''' <summary>时间状态</summary>
时间状态 = 53
''' <summary>起夜状态</summary>
起夜状态 = 56
''' <summary>锁定状态</summary>
锁定状态 = 59
''' <summary>保留字段</summary>
保留字段 = 62
End Enum
End Class
''' <summary>配置信息协议位</summary>
Enum ConfigParam
''' <summary>配置发布作者</summary>
ConfigReleaseAuthor
''' <summary>配置软件版本号</summary>
ConfigSoftwareVer
''' <summary>配置发布日期</summary>
ReleaseDate
''' <summary>用户名</summary>
UserName
''' <summary>项目编号</summary>
ProjectIndex
''' <summary>房型ID</summary>
RoomTypeID
''' <summary>房型别名</summary>
RommTypeAlias
''' <summary>配置数据版本</summary>
ConfigDataVer
End Enum
''' <summary>
''' 设备存在协议位
''' </summary>
Enum DeviceExsistParam
''' <summary>设备类型</summary>
DeviceType
''' <summary>设备地址</summary>
DeviceAddr
''' <summary>485端口</summary>
Port_485
''' <summary>波特率</summary>
BaudRate
''' <summary>设备协议版本</summary>
ProtocolVer = BaudRate + 4
''' <summary>通讯重发次数</summary>
RetryCount
''' <summary>通讯等待时间</summary>
WaitTime
''' <summary>保留</summary>
KeepParams = WaitTime + 2
''' <summary>输入回路数</summary>
InputLoopCount = KeepParams + 32
''' <summary>输出回路数</summary>
OutputLoopCount = InputLoopCount + 2
''' <summary>回路别名</summary>
LoopAlias = OutputLoopCount + 2
End Enum
''' <summary>设备动作协议位</summary>
Enum ActionParam
''' <summary>设备类型</summary>
DeviceType
''' <summary>设备地址</summary>
DeviceAddr
''' <summary>设备动作编号</summary>
DeviceActionNum
''' <summary>设备输入回路</summary>
DeviceInputLoop = DeviceActionNum + 2
''' <summary>设备输入类型</summary>
DeviceInputType = DeviceInputLoop + 2
''' <summary>动作执行条件</summary>
ActionCondition = DeviceInputType + 2
''' <summary>动作执行方式</summary>
ActionMode = ActionCondition + 8
''' <summary>设备动作别名</summary>
ActionAlias
''' <summary>保留参数</summary>
KeepParam = ActionAlias + 16
''' <summary>输出设备动作数</summary>
ActionCount = KeepParam + 32
''' <summary>设备动作</summary>
ActionParams
End Enum
''' <summary>设备动作参数协议位</summary>
Enum ActionDataParam
''' <summary>设备类型,外接设备设备类型(主机特殊处理)</summary>
DeviceType
''' <summary>设备地址,选择对象的设备拨码地址(主机特殊处理)</summary>
DeviceAddr
''' <summary>设备回路选择对象的回路地址2位</summary>
DeviceLoop
''' <summary>执行方式,不同设备类型有不同方式</summary>
ExecMode = DeviceLoop + 2
''' <summary>执行内容,不同设备类型有不同内容</summary>
ExecInfo
''' <summary>延时时间,动作执行延时</summary>
DelayTime
''' <summary>延时单位,做东执行延时单位</summary>
DelayUnit
End Enum
End Class