protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); byte[] command = ReceivedAchData.Command; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (command != null && command.Length > 1 && isSuportedScheme) { if (command[1] == COMMAND_CLASS_BASIC.BASIC_GET.ID) { ApiOperation sendData = null; var data = new COMMAND_CLASS_BASIC.BASIC_REPORT() { value = Value }; sendData = new SendDataExOperation(ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, data, TxOptions, TxSecOptions, scheme, TxOptions2); ou.SetNextActionItems(sendData); } else if (command[1] == COMMAND_CLASS_BASIC.BASIC_SET.ID) { var basicSetCommand = (COMMAND_CLASS_BASIC.BASIC_SET)command; Value = basicSetCommand.value; } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); byte nodeId = ReceivedAchData.SrcNodeId; byte[] command = ReceivedAchData.Command; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (command != null && command.Length > 1 && isSuportedScheme) { if (command[1] == COMMAND_CLASS_POWERLEVEL.POWERLEVEL_GET.ID) { _powerLevelGet.NewToken(); _sendPowerLevelReport.NewToken(); _sendPowerLevelReport.NodeId = nodeId; _sendPowerLevelReport.SecurityScheme = scheme; ou.SetNextActionItems(_powerLevelGet); } if (command[1] == COMMAND_CLASS_POWERLEVEL.POWERLEVEL_SET.ID) { COMMAND_CLASS_POWERLEVEL.POWERLEVEL_SET cmd = command; _powerLevelSet.NewToken(); _powerLevelSet.PowerLevel = cmd.powerLevel; ou.SetNextActionItems(_powerLevelSet); } else if (command[1] == COMMAND_CLASS_POWERLEVEL.POWERLEVEL_TEST_NODE_SET.ID) { COMMAND_CLASS_POWERLEVEL.POWERLEVEL_TEST_NODE_SET cmd = command; _sendTest.NewToken(); _sendTest.NodeId = cmd.testNodeid; _sendTest.PowerLevel = cmd.powerLevel; _testFromNodeId = nodeId; _testFrameCount = Tools.GetInt32(cmd.testFrameCount); _testIteration = 0; _failIterations = 0; ou.SetNextActionItems(_sendTest); } else if (command[1] == COMMAND_CLASS_POWERLEVEL.POWERLEVEL_TEST_NODE_GET.ID) { COMMAND_CLASS_POWERLEVEL.POWERLEVEL_TEST_NODE_GET cmd = command; _sendPowerLevelTestNodeReport.NewToken(); _sendPowerLevelTestNodeReport.NodeId = nodeId; _sendPowerLevelTestNodeReport.SecurityScheme = scheme; _sendPowerLevelTestNodeReport.Data = new COMMAND_CLASS_POWERLEVEL.POWERLEVEL_TEST_NODE_REPORT() { statusOfOperation = _failIterations == 0 ? (byte)0x01 : (byte)0x00, testFrameCount = new byte[] { (byte)(_testIteration << 8), (byte)_testIteration }, testNodeid = _sendTest.NodeId }; ou.SetNextActionItems(_sendPowerLevelTestNodeReport); } } }
private void OnReceived(DataReceivedUnit unit) { var payload = ((ApiHandler)unit.ActionHandler).DataFrame.Payload; _homeId = new byte[] { payload[3], payload[4], payload[5], payload[6] }; var dsk = _dskNeededCallback(_homeId); if (!_isRunning && dsk != null && dsk.Item2 != null && dsk.Item2.Length >= 16) { SetRunning(); byte[] dskPart = new byte[8]; Array.Copy(dsk.Item2, 8, dskPart, 0, 8); IAddRemoveNode addNode = null; if (dsk.Item1 > 0) { //addNode = new ReplaceFailedNodeOperation(dsk.First, _setNodeStatusSignal, _timeoutMs, dskPart) { SequenceNumber = SequenceNumber, DskValue = dsk.Item2 }; addNode = new AddNodeOperation((Modes.NodeOptionNetworkWide | Modes.NodeHomeId), _setNodeStatusSignal, _timeoutMs, dskPart) { SequenceNumber = SequenceNumber, DskValue = dsk.Item2, GrantSchemesValue = dsk.Item3 }; } else { addNode = new AddNodeOperation((Modes.NodeOptionNetworkWide | Modes.NodeHomeId), _setNodeStatusSignal, _timeoutMs, dskPart) { SequenceNumber = SequenceNumber, DskValue = dsk.Item2, GrantSchemesValue = dsk.Item3 }; } var action = new InclusionTask(_network, addNode, true); action.CompletedCallback = (x) => { var act = x as ActionBase; if (act != null) { ReleaseRunning(); _busyCallback(false, dsk.Item2, act.Result); } }; unit.SetNextActionItems(new ActionSerialGroup(action, new SetSmartStartAction(true))); _busyCallback(true, null, null); } else { unit.SetNextActionItems(new SetSmartStartAction(true)); } }
protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); byte nodeId = ReceivedAchData.SrcNodeId; byte[] command = ReceivedAchData.Command; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (isSuportedScheme && command != null && command.Length > 1) { if (command[1] == COMMAND_CLASS_WAKE_UP_V2.WAKE_UP_INTERVAL_CAPABILITIES_GET.ID) { var cmd = (COMMAND_CLASS_WAKE_UP_V2.WAKE_UP_INTERVAL_CAPABILITIES_GET)command; var rpt = new COMMAND_CLASS_WAKE_UP_V2.WAKE_UP_INTERVAL_CAPABILITIES_REPORT() { minimumWakeUpIntervalSeconds = new byte[] { 0x00, 0x00, 0x3C }, maximumWakeUpIntervalSeconds = new byte[] { 0x01, 0x51, 0x80 }, defaultWakeUpIntervalSeconds = new byte[] { 0x00, 0x01, 0x2C }, wakeUpIntervalStepSeconds = new byte[] { 0x00, 0x00, 0x3C } }; var sendData = new SendDataExOperation(nodeId, rpt, TxOptions, scheme); ou.SetNextActionItems(sendData); } else if (command[1] == COMMAND_CLASS_WAKE_UP_V2.WAKE_UP_INTERVAL_GET.ID) { var cmd = (COMMAND_CLASS_WAKE_UP_V2.WAKE_UP_INTERVAL_GET)command; var rpt = new COMMAND_CLASS_WAKE_UP_V2.WAKE_UP_INTERVAL_REPORT() { seconds = _wakeupDelay }; var sendData = new SendDataExOperation(nodeId, rpt, TxOptions, scheme); ou.SetNextActionItems(sendData); } else if (command[1] == COMMAND_CLASS_WAKE_UP_V2.WAKE_UP_INTERVAL_SET.ID) { var cmd = (COMMAND_CLASS_WAKE_UP_V2.WAKE_UP_INTERVAL_SET)command; _wakeupDelay = cmd.seconds; } else if (command[1] == COMMAND_CLASS_WAKE_UP_V2.WAKE_UP_NO_MORE_INFORMATION.ID) { _disableRFReceiveOperation.NewToken(); ou.SetNextActionItems(_disableRFReceiveOperation); } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); byte nodeId = ReceivedAchData.SrcNodeId; byte[] command = ReceivedAchData.Command; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (command != null && command.Length > 1 && isSuportedScheme) { switch (command[1]) { case (COMMAND_CLASS_FIRMWARE_UPDATE_MD_V5.FIRMWARE_MD_GET.ID): { ou.SetNextActionItems(SendFwuMdReport(nodeId, scheme)); } break; case (COMMAND_CLASS_FIRMWARE_UPDATE_MD_V5.FIRMWARE_UPDATE_MD_REQUEST_GET.ID): { ou.SetNextActionItems(HandleCmdClassFirmwareUpdateMdReqGet(nodeId, command, scheme)); if (_pStatus == 0xFF) { _firmwareOffset = 0; ou.AddNextActionItems(SendFwuMdGet(nodeId, START_REPORT_NUMBER, scheme)); _firmwareUpdateNvmInit.NewToken(); ou.AddNextActionItems(_firmwareUpdateNvmInit); _firmwareUpdateNvmSetNewImageFalse.NewToken(); ou.AddNextActionItems(_firmwareUpdateNvmSetNewImageFalse); } } break; case (COMMAND_CLASS_FIRMWARE_UPDATE_MD_V5.FIRMWARE_UPDATE_MD_REPORT.ID): { HandleCmdClassFirmwareUpdateMdReport(ou, nodeId, command, scheme); } break; default: break; } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); byte nodeId = ReceivedAchData.SrcNodeId; byte[] command = ReceivedAchData.Command; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (command != null && command.Length > 1 && isSuportedScheme) { if (command[1] == COMMAND_CLASS_VERSION.VERSION_GET.ID) { ApiOperation sendData = null; var data = new COMMAND_CLASS_VERSION.VERSION_REPORT(); sendData = new SendDataExOperation(nodeId, data, TxOptions, TxSecOptions, scheme, TxOptions2); ou.SetNextActionItems(sendData); } } }
/// <summary>handleCmdClassFirmwareUpdateMdReport</summary> private void HandleCmdClassFirmwareUpdateMdReport(DataReceivedUnit ou, byte nodeId, byte[] command, SecuritySchemes scheme) { var fwuMdReport = (COMMAND_CLASS_FIRMWARE_UPDATE_MD_V5.FIRMWARE_UPDATE_MD_REPORT)command; var lastReportNumber = Tools.GetBytes(_lastUsedReportNumber); if (fwuMdReport.properties1.reportNumber1 == lastReportNumber[0] && fwuMdReport.reportNumber2 == lastReportNumber[1]) { var crc16Res = Tools.CalculateCrc16Array(command.Take(command.Length - 2)); if (crc16Res.SequenceEqual(fwuMdReport.checksum)) { var data = fwuMdReport.data; ushort dataLen = (ushort)data.Count; var _firmwareUpdateNvmWrite = new FirmwareUpdateNvmWriteOperation(_firmwareOffset, dataLen, data.ToArray()); ou.SetNextActionItems(_firmwareUpdateNvmWrite); _firmwareOffset += dataLen; if (fwuMdReport.properties1.last == 0x00) { ushort nextReportNumber = (ushort)(_lastUsedReportNumber + 1); ou.AddNextActionItems(SendFwuMdGet(nodeId, nextReportNumber, scheme)); } else { _firmwareUpdateNvmSetNewImageTrue.NewToken(); ou.AddNextActionItems(_firmwareUpdateNvmSetNewImageTrue); ou.AddNextActionItems(SendFwuMdStatusReport(nodeId, 0xFF, scheme)); } } else //FW_EV_UPDATE_STATUS_UNABLE_TO_RECEIVE { "invalid MD report"._DLOG(); //retransmit request on the previous frame ou.SetNextActionItems(SendFwuMdGet(nodeId, _lastUsedReportNumber, scheme)); } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { var destNodeId = ReceivedAchData.DestNodeId > 0 ? ReceivedAchData.DestNodeId : _securityManagerInfo.Network.NodeId; SecuritySchemes scheme = SecuritySchemes.NONE; InvariantPeerNodeId peerNodeId = new InvariantPeerNodeId(destNodeId, ReceivedAchData.SrcNodeId); ou.SetNextActionItems(); if (!ou.DataFrame.IsSkippedSecurity) { if (_securityManagerInfo.Network.HasSecurityScheme(SecuritySchemeSet.ALLS2) && _securityManagerInfo.IsActive) { byte[] command = ReceivedAchData.Command; bool isNonceReport = false; bool isSupportedReport = false; // Only for test frame Extensions extensions = null; SubstituteSettings substituteSettings = null; if (command != null && command.Length > 1) { bool isSubstituteDenied = false; byte[] dataToSend = null; bool isMulticastFrame = (ou.DataFrame.Data[2] & MULTICAST_MASK) == MULTICAST_MASK; bool isBroadcastFrame = (ou.DataFrame.Data[2] & BROADCAST_MASK) == BROADCAST_MASK; if (command[1] == COMMAND_CLASS_SECURITY_2.SECURITY_2_NONCE_GET.ID && (SecuritySchemes)ReceivedAchData.SecurityScheme == SecuritySchemes.NONE) { byte rxSequenceNumber = command[2]; if (!isMulticastFrame && !isBroadcastFrame) { if (handlingNonceGetFromNode != ReceivedAchData.SrcNodeId) { handlingNonceGetFromNode = ReceivedAchData.SrcNodeId; var currentTxSequenceNumber = _spanTable.GetTxSequenceNumber(peerNodeId); _spanTable.SetNonceFree(peerNodeId); //reset MPAN for owner Id foreach (byte groupId in _mpanTable.SelectGroupIds(ReceivedAchData.SrcNodeId)) { _mpanTable.RemoveRecord(new NodeGroupId(ReceivedAchData.SrcNodeId, groupId)); } dataToSend = _securityS2CryptoProvider.GenerateNonceReport(_spanTable, peerNodeId, ++currentTxSequenceNumber, rxSequenceNumber, true, false); isNonceReport = true; isSubstituteDenied = true; } } } else if (command[1] == COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.ID) { byte rxSequenceNumber = command[2]; if (!isMulticastFrame && !isBroadcastFrame && ValidateS2MessageExtensions(command)) { var currentTxSequenceNumber = _spanTable.GetTxSequenceNumber(peerNodeId); _spanTable.SetNonceFree(peerNodeId); var isMos = _securityS2CryptoProvider.CheckMpanMosForOwnerNode(_mpanTable, ReceivedAchData.SrcNodeId); dataToSend = _securityS2CryptoProvider.GenerateNonceReport(_spanTable, peerNodeId, ++currentTxSequenceNumber, rxSequenceNumber, true, isMos); isNonceReport = true; isSubstituteDenied = true; } } else if (command[1] == COMMAND_CLASS_SECURITY_2.SECURITY_2_NONCE_REPORT.ID && (SecuritySchemes)ReceivedAchData.SecurityScheme == SecuritySchemes.NONE) { if (!isMulticastFrame && !isBroadcastFrame) { COMMAND_CLASS_SECURITY_2.SECURITY_2_NONCE_REPORT nonceReportCmd = command; if (_securityManagerInfo.InitializingNodeId != ReceivedAchData.SrcNodeId) // Node must be already initialized. { if (nonceReportCmd.properties1.sos > 0 && // Singlecast out of sync. nonceReportCmd.receiversEntropyInput != null && nonceReportCmd.receiversEntropyInput.Count == 16 ) { var rTable = _securityManagerInfo.RetransmissionTableS2; if (rTable.ContainsKey(peerNodeId)) { if (rTable[peerNodeId].Counter > 0) { _spanTable.AddOrReplace(peerNodeId, nonceReportCmd.receiversEntropyInput.ToArray(), _spanTable.GetTxSequenceNumber(peerNodeId), nonceReportCmd.sequenceNumber); dataToSend = rTable[peerNodeId].Data; scheme = rTable[peerNodeId].SecurityScheme; substituteSettings = rTable[peerNodeId].SubstituteSettings; rTable[peerNodeId].Counter--; } else { rTable.Remove(peerNodeId); _spanTable.SetNonceFree(peerNodeId); } } else { _spanTable.SetNonceFree(peerNodeId); } } if (nonceReportCmd.properties1.mos > 0) // Mutlicast out of sync. { var groupId = _securityS2CryptoProvider.LastSentMulticastGroupId; extensions = new Extensions(); var nodeGroupId = new NodeGroupId(destNodeId, groupId); if (!_mpanTable.CheckMpanExists(nodeGroupId)) { _mpanTable.AddOrReplace(nodeGroupId, 0x55, null, _securityS2CryptoProvider.GetRandomData()); } extensions.AddMpanExtension(_mpanTable.GetContainer(nodeGroupId).MpanState, groupId); } } } } else if (command[1] == COMMAND_CLASS_SECURITY_2.SECURITY_2_COMMANDS_SUPPORTED_GET.ID) { if (!isMulticastFrame && !isBroadcastFrame) { scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; if (scheme != SecuritySchemes.NONE && scheme != SecuritySchemes.S0 && _securityManagerInfo.Network.HasSecurityScheme(scheme)) { if (!_securityManagerInfo.Network.HasSecurityScheme(ReceivedAchData.SrcNodeId, SecuritySchemeSet.ALLS2) && !_securityManagerInfo.Network.IsSecuritySchemesSpecified(ReceivedAchData.SrcNodeId)) { _securityManagerInfo.Network.SetSecuritySchemes(ReceivedAchData.SrcNodeId, SecuritySchemeSet.ALL); } isSupportedReport = true; var ccReport = new COMMAND_CLASS_SECURITY_2.SECURITY_2_COMMANDS_SUPPORTED_REPORT(); if (ReceivedAchData.CommandType == CommandTypes.CmdApplicationCommandHandler_Bridge && ReceivedAchData.DestNodeId != _securityManagerInfo.Network.NodeId) { ccReport.commandClass = new List <byte>(_securityManagerInfo.Network.GetVirtualSecureCommandClasses()); } else { var secureCommandClasses = _securityManagerInfo.Network.GetSecureCommandClasses(); if (secureCommandClasses != null) { switch (scheme) { case SecuritySchemes.S2_UNAUTHENTICATED: if (!_securityManagerInfo.Network.HasSecurityScheme(SecuritySchemes.S2_ACCESS) && !_securityManagerInfo.Network.HasSecurityScheme(SecuritySchemes.S2_AUTHENTICATED)) { ccReport.commandClass = new List <byte>(_securityManagerInfo.Network.GetSecureCommandClasses()); } break; case SecuritySchemes.S2_AUTHENTICATED: if (!_securityManagerInfo.Network.HasSecurityScheme(SecuritySchemes.S2_ACCESS)) { ccReport.commandClass = new List <byte>(_securityManagerInfo.Network.GetSecureCommandClasses()); } break; case SecuritySchemes.S2_ACCESS: ccReport.commandClass = new List <byte>(secureCommandClasses); break; default: break; } } } dataToSend = ccReport; } } } if (dataToSend != null || extensions != null) { ApiOperation sendData = null; if (SecuritySchemeSet.ALLS2.Contains(scheme)) { sendData = new SendDataExOperation(ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, dataToSend, _securityManagerInfo.TxOptions, scheme); } else { if (ReceivedAchData.DestNodeId > 0) { sendData = new SendDataBridgeOperation(ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, dataToSend, _securityManagerInfo.TxOptions); if (extensions != null) { ((SendDataBridgeOperation)sendData).Extensions = extensions; } } else { sendData = new SendDataOperation(ReceivedAchData.SrcNodeId, dataToSend, _securityManagerInfo.TxOptions); if (extensions != null) { ((SendDataOperation)sendData).Extensions = extensions; } } } if (substituteSettings != null) { sendData.SubstituteSettings = substituteSettings; } if (isSubstituteDenied) { sendData.SubstituteSettings.SetFlag(SubstituteFlags.DenySecurity); } sendData.CompletedCallback = (x) => { var action = x as ActionBase; if (action != null) { handlingNonceGetFromNode = 0; SpecificResult.TotalCount++; if (action.Result.State != ActionStates.Completed) { SpecificResult.FailCount++; } } }; #region TestFrames if (isNonceReport) { _securityTestSettingsService.ActivateTestPropertiesForFrame(SecurityS2TestFrames.NonceReport, sendData); } else if (isSupportedReport) { _securityTestSettingsService.ActivateTestPropertiesForFrame(SecurityS2TestFrames.CommandsSupportedReport, sendData); } #endregion ou.SetNextActionItems(sendData); } else { ou.SetNextActionItems(); } } } else { "REJECT, {0}, {1} (IsNodeSecureS2={2}, IsActive={3}"._DLOG( _securityManagerInfo.IsInclusion, _securityManagerInfo.Network.HasSecurityScheme(ReceivedAchData.SrcNodeId, SecuritySchemeSet.ALLS2), _securityManagerInfo.Network.HasSecurityScheme(SecuritySchemeSet.ALLS2), _securityManagerInfo.IsActive); } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { byte nodeId = ReceivedAchData.SrcNodeId; byte[] command = ReceivedAchData.Command; if (command != null && command.Length > 1) { if (command[1] == COMMAND_CLASS_INCLUSION_CONTROLLER.INITIATE.ID && nodeIdToInclude == 0) { var initiateCommand = (COMMAND_CLASS_INCLUSION_CONTROLLER.INITIATE)command; if (initiateCommand.stepId == PROXY_INCLUSION || initiateCommand.stepId == PROXY_INCLUSION_REPLACE) { /*TO# 07220 - Delay before request Node Info*/ Thread.Sleep(2000); //if we're not SIS then ignore if (_securityManagerInfo.Network.SucNodeId == _securityManagerInfo.Network.NodeId) { //Start add node for example nodeIdToInclude = initiateCommand.nodeId; var isVirtualNodeOperation = new IsVirtualNodeOperation(nodeIdToInclude); if (ReceivedAchData.CommandType != CommandTypes.CmdApplicationCommandHandler_Bridge) { isVirtualNodeOperation.Token.SetCancelled(); } var stepId = initiateCommand.stepId; var sendDataComplete = new InclusionController.Complete(nodeId, TxOptions); sendDataComplete.SetCommandParameters(STEP_OK, stepId); var requestDataStep2 = new InclusionController.Initiate(0, nodeId, TxOptions, 20000); requestDataStep2.SetCommandParameters(nodeIdToInclude, S0_INCLUSION); var sendDataRejectComplete = new InclusionController.Complete(nodeId, TxOptions); sendDataRejectComplete.SetCommandParameters(STEP_USER_REJECTED, stepId); var addNodeOperation = new AddNodeS2Operation(_securityManagerInfo); addNodeOperation.SetInclusionControllerInitiateParameters(nodeIdToInclude); var setupNodeLifelineTask = new SetupNodeLifelineTask(_securityManagerInfo.Network); setupNodeLifelineTask.NodeId = _securityManagerInfo.Network.NodeId; setupNodeLifelineTask.SucNodeId = _securityManagerInfo.Network.NodeId; setupNodeLifelineTask.TargetNodeId = nodeIdToInclude; setupNodeLifelineTask.CompletedCallback = OnNodeInfoCompleted; var serialGroup = new ActionSerialGroup(OnInitiateFlowActionCompleted, isVirtualNodeOperation, new RequestNodeInfoOperation(nodeIdToInclude) { SubstituteSettings = new SubstituteSettings(SubstituteFlags.DenySecurity, 0) }, addNodeOperation, requestDataStep2, setupNodeLifelineTask, sendDataComplete); serialGroup.ActionUnitStop = new ActionUnit(sendDataRejectComplete); //hack serialGroup.Token.Result = new AddRemoveNodeResult(); serialGroup.CompletedCallback = OnS2SerialGroupCompleted; if (_inclusionControllerStatusUpdateCallback != null) { _inclusionControllerStatusUpdateCallback(serialGroup.Token, false); } ou.SetNextActionItems(serialGroup); } } else if (initiateCommand.stepId == S0_INCLUSION) { //only if asked from SIS if (_securityManagerInfo.Network.SucNodeId == nodeId) { InclusionController.Complete sendDataComplete = null; //Start S0 nodeIdToInclude = initiateCommand.nodeId; if (_securityManagerInfo.Network.HasSecurityScheme(SecuritySchemes.S0)) { sendDataComplete = new InclusionController.Complete(nodeId, TxOptions); sendDataComplete.SetCommandParameters(STEP_OK, S0_INCLUSION); var addNodeOperation = new AddNodeS0Operation(_securityManagerInfo); addNodeOperation.SetInclusionControllerInitiateParameters(nodeIdToInclude); var nodeInfoOperation = new RequestNodeInfoOperation(nodeIdToInclude); nodeInfoOperation.CompletedCallback = OnNodeInfoCompleted; var serialGroup = new ActionSerialGroup(new RequestNodeInfoOperation(nodeIdToInclude) { SubstituteSettings = new SubstituteSettings(SubstituteFlags.DenySecurity, 0) }, addNodeOperation, nodeInfoOperation, sendDataComplete); //hack serialGroup.Token.Result = new AddRemoveNodeResult(); ou.SetNextActionItems(serialGroup); } else { sendDataComplete = new InclusionController.Complete(nodeId, TxOptions); sendDataComplete.SetCommandParameters(STEP_NOT_SUPPORTED, S0_INCLUSION); ou.SetNextActionItems(sendDataComplete); } } } } else if (command[1] == COMMAND_CLASS_INCLUSION_CONTROLLER.COMPLETE.ID) { } } }
//TODO: //MULTI_CHANNEL_END_POINT_FIND //MULTI_INSTANCE_CMD_ENCAP //MULTI_INSTANCE_GET protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); byte nodeId = ReceivedAchData.SrcNodeId; byte[] command = ReceivedAchData.Command; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (command != null && command.Length > 1 && isSuportedScheme) { if (command[1] == COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_END_POINT_GET.ID) { var cmd = (COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_END_POINT_GET)command; var rpt = new COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_END_POINT_REPORT() { properties1 = new COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_END_POINT_REPORT.Tproperties1() { res1 = 0x00, identical = 0x01, dynamic = 0x00, }, properties2 = new COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_END_POINT_REPORT.Tproperties2() { individualEndPoints = END_POINTS_COUNT, res2 = 0x00 }, properties3 = new COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_END_POINT_REPORT.Tproperties3() { } }; var sendData = new SendDataExOperation(nodeId, rpt, TxOptions, scheme); ou.SetNextActionItems(sendData); } else if (command[1] == COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_CAPABILITY_GET.ID) { var cmd = (COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_CAPABILITY_GET)command; if (cmd.properties1.endPoint > 0 && cmd.properties1.endPoint <= END_POINTS_COUNT) { var rpt = new COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_CAPABILITY_REPORT() { genericDeviceClass = GENERIC_DEVICE_CLASS, specificDeviceClass = SPECIFIC_DEVICE_CLASS, properties1 = { dynamic = 0, endPoint = cmd.properties1.endPoint }, commandClass = GetCapability(cmd.properties1.endPoint) }; var sendData = new SendDataExOperation(nodeId, rpt, TxOptions, scheme); ou.SetNextActionItems(sendData); } } else if (command[1] == COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_AGGREGATED_MEMBERS_GET.ID) { var cmd = (COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_AGGREGATED_MEMBERS_GET)command; if (cmd.properties1.aggregatedEndPoint > 0 && cmd.properties1.aggregatedEndPoint <= END_POINTS_COUNT) { var rpt = new COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_AGGREGATED_MEMBERS_REPORT() { properties1 = { aggregatedEndPoint = cmd.properties1.aggregatedEndPoint, res = 0 }, numberOfBitMasks = 0x01 }; rpt.aggregatedMembersBitMask.Add(0x03); var sendData = new SendDataExOperation(nodeId, rpt, TxOptions, scheme); ou.SetNextActionItems(sendData); } } else if (command[1] == COMMAND_CLASS_MULTI_CHANNEL_V4.MULTI_CHANNEL_CMD_ENCAP.ID) { var data = UnboxAndGetResponce(command); if (data != null && data.Length > 0) { var sendData = new SendDataExOperation(nodeId, data, TxOptions, scheme); ou.SetNextActionItems(sendData); } } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { byte nodeId = ReceivedAchData.SrcNodeId; byte[] cmd = ReceivedAchData.Command; if (handlingRequestFromNode != nodeId || !handlingRequest.SequenceEqual(cmd)) { handlingRequestFromNode = nodeId; handlingRequest = cmd; if (ReceiveCallback != null) { byte[] data = ReceiveCallback(ReceivedAchData.Options, ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, ReceivedAchData.Command); if (data != null && data.Length > 0) { Data = new List <byte[]>(); Data.Add(data); } else { Data = null; } } else if (ReceiveExCallback != null) { Data = ReceiveExCallback(ReceivedAchData.Options, ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, ReceivedAchData.Command); } ou.SetNextActionItems(); List <ActionBase> nextOperations = new List <ActionBase>(); if (Data != null) { var scheme = IsSecuritySchemeSpecified ? SecurityScheme : (SecuritySchemes)ReceivedAchData.SecurityScheme; foreach (var command in Data) { bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (command != null && command.Length > 1 && isSuportedScheme) { CallbackApiOperation operation = null; operation = new SendDataExOperation(ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, command, TxOptions, TxSecOptions, scheme, TxOptions2); operation.SubstituteSettings = new SubstituteSettings(SubstituteSettings.SubstituteFlags, SubstituteSettings.MaxBytesPerFrameSize); if (ReceivedAchData.SubstituteIncomingFlags.HasFlag(SubstituteIncomingFlags.Crc16Encap)) { operation.SubstituteSettings.SetFlag(SubstituteFlags.UseCrc16Encap); } nextOperations.Add(operation); } } } if (nextOperations.Count > 0) { var next = new ActionSerialGroup(nextOperations.ToArray()); next.CompletedCallback = (x) => { var action = x as ActionBase; if (action != null) { handlingRequestFromNode = 0; handlingRequest = emptyArray; SpecificResult.TotalCount++; if (action.Result.State != ActionStates.Completed) { SpecificResult.FailCount++; } } }; ou.SetNextActionItems(next); } else { handlingRequestFromNode = 0; handlingRequest = emptyArray; } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { byte nodeId = ReceivedAchData.SrcNodeId; byte[] cmd = ReceivedAchData.Command; if (handlingRequestFromNode != nodeId || !handlingRequest.SequenceEqual(cmd)) { handlingRequestFromNode = nodeId; handlingRequest = cmd; if (ReceiveCallback != null) { byte[] data = ReceiveCallback(ReceivedAchData.Options, ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, ReceivedAchData.Command); if (data != null && data.Length > 0) { Data = new List <byte[]>(); Data.Add(data); } } else if (ReceiveExCallback != null) { Data = ReceiveExCallback(ReceivedAchData.Options, ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, ReceivedAchData.Command); } else if (ReceiveAchDataCallback != null) { Data = ReceiveAchDataCallback(ReceivedAchData); } if (Data != null) { if (ReceivedAchData.DestNodeId == 0) { ApiOperation[] operations = new ApiOperation[Data.Count]; for (int i = 0; i < Data.Count; i++) { operations[i] = new SendDataOperation(ReceivedAchData.SrcNodeId, Data[i], TxOptions); operations[i].SubstituteSettings = SubstituteSettings; operations[i].CompletedCallback = (x) => { var action = x as ActionBase; if (action != null) { handlingRequestFromNode = 0; handlingRequest = emptyArray; SpecificResult.TotalCount++; if (action.Result.State != ActionStates.Completed) { SpecificResult.FailCount++; } } }; } ou.SetNextActionItems(operations); } else { ApiOperation[] operations = new ApiOperation[Data.Count]; for (int i = 0; i < Data.Count; i++) { operations[i] = new SendDataBridgeOperation(ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, Data[i], TxOptions); operations[i].SubstituteSettings = SubstituteSettings; operations[i].CompletedCallback = (x) => { var action = x as ActionBase; if (action != null) { handlingRequestFromNode = 0; handlingRequest = emptyArray; SpecificResult.TotalCount++; if (action.Result.State != ActionStates.Completed) { SpecificResult.FailCount++; } } }; } ou.SetNextActionItems(operations); } } else { handlingRequestFromNode = 0; handlingRequest = emptyArray; ou.SetNextActionItems(); } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); byte nodeId = ReceivedAchData.SrcNodeId; byte[] command = ReceivedAchData.Command; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (command != null && command.Length > 1 && isSuportedScheme) { if (command[1] == COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_GET.ID) { var associationGetCmd = (COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_GET)command; var requestedGroupId = associationGetCmd.groupingIdentifier; if (requestedGroupId == GroupId) { ApiOperation sendData = null; var data = new COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_REPORT() { groupingIdentifier = GroupId, nodeid = AssociatedNodeIds, maxNodesSupported = MaxNodesSupported }; sendData = new SendDataExOperation(nodeId, data, TxOptions, TxSecOptions, scheme, TxOptions2); ou.SetNextActionItems(sendData); } else if (requestedGroupId != 0x00) { ApiOperation sendData = null; var data = new COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_REPORT() { groupingIdentifier = requestedGroupId, nodeid = AssociatedNodeIds, maxNodesSupported = MaxNodesSupported }; sendData = new SendDataExOperation(nodeId, data, TxOptions, TxSecOptions, scheme, TxOptions2); ou.SetNextActionItems(sendData); } } else if (command[1] == COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_SET.ID) { var associationSetCmd = (COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_SET)command; var requestedGroupId = associationSetCmd.groupingIdentifier; if (requestedGroupId == GroupId) { foreach (var associateNodeId in associationSetCmd.nodeId) { if (!AssociatedNodeIds.Contains(associateNodeId)) { AssociatedNodeIds.Add(associateNodeId); } } } else if (requestedGroupId != 0x00) { foreach (var associateNodeId in associationSetCmd.nodeId) { if (!AssociatedNodeIds.Contains(associateNodeId)) { AssociatedNodeIds.Add(associateNodeId); } } } } else if (command[1] == COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_REMOVE.ID) { var associationRemoveCmd = (COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_REMOVE)command; var requestedGroupId = associationRemoveCmd.groupingIdentifier; if (requestedGroupId == GroupId) { foreach (var associateNodeId in associationRemoveCmd.nodeId) { if (AssociatedNodeIds.Contains(associateNodeId)) { AssociatedNodeIds.Remove(associateNodeId); } } } else if (requestedGroupId != 0x00) { foreach (var associateNodeId in associationRemoveCmd.nodeId) { if (AssociatedNodeIds.Contains(associateNodeId)) { AssociatedNodeIds.Remove(associateNodeId); } } } } else if (command[1] == COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_GROUPINGS_GET.ID) { ApiOperation sendData = null; var data = new COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_GROUPINGS_REPORT() { supportedGroupings = 0x01 }; sendData = new SendDataExOperation(nodeId, data, TxOptions, TxSecOptions, scheme, TxOptions2); ou.SetNextActionItems(sendData); } else if (command[1] == COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_SPECIFIC_GROUP_GET.ID) { ApiOperation sendData = null; var data = new COMMAND_CLASS_ASSOCIATION_V2.ASSOCIATION_SPECIFIC_GROUP_REPORT() { group = 0 }; sendData = new SendDataExOperation(nodeId, data, TxOptions, TxSecOptions, scheme, TxOptions2); ou.SetNextActionItems(sendData); } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); byte nodeId = ReceivedAchData.SrcNodeId; byte[] command = ReceivedAchData.Command; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (command != null && command.Length > 1 && isSuportedScheme) { if (command[1] == COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_GET.ID) { var cmd = (COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_GET)command; if (cmd.groupingIdentifier == _groupId) { var rpt = new COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_REPORT() { groupingIdentifier = _groupId, nodeId = _associatedNodeIds, maxNodesSupported = _maxNodesSupported }; var sendData = new SendDataExOperation(nodeId, rpt, TxOptions, scheme); ou.SetNextActionItems(sendData); } } else if (command[1] == COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_GROUPINGS_GET.ID) { var cmd = (COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_GROUPINGS_GET)command; { var rpt = new COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_GROUPINGS_REPORT() { supportedGroupings = 0x01 }; var sendData = new SendDataExOperation(nodeId, rpt, TxOptions, scheme); ou.SetNextActionItems(sendData); } } else if (command[1] == COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_REMOVE.ID) { var cmd = (COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_REMOVE)command; if (cmd.groupingIdentifier == _groupId) { foreach (var associateNodeId in cmd.nodeId) { if (!_associatedNodeIds.Contains(associateNodeId)) { _associatedNodeIds.Remove(associateNodeId); } } } } else if (command[1] == COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_SET.ID) { var cmd = (COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V3.MULTI_CHANNEL_ASSOCIATION_SET)command; if (cmd.groupingIdentifier == _groupId) { foreach (var associateNodeId in cmd.nodeId) { if (!_associatedNodeIds.Contains(associateNodeId)) { _associatedNodeIds.Add(associateNodeId); } } } } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); if (!ou.DataFrame.IsSkippedSecurity) { if (_securityManagerInfo.IsActive && _securityManagerInfo.Network.HasSecurityScheme(SecuritySchemes.S0)) { byte[] command = ReceivedAchData.Command; if (command != null && command.Length > 1) { byte[] dataToSend = null; bool isSubstituteDenied = false; if ((command[1] == COMMAND_CLASS_SECURITY.SECURITY_NONCE_GET.ID || command[1] == COMMAND_CLASS_SECURITY.SECURITY_MESSAGE_ENCAPSULATION_NONCE_GET.ID) && handlingNonceGetFromNode != ReceivedAchData.SrcNodeId) { handlingNonceGetFromNode = ReceivedAchData.SrcNodeId; var destNodeId = ReceivedAchData.DestNodeId > 0 ? ReceivedAchData.DestNodeId : _securityManagerInfo.Network.NodeId; if (_securityManagerInfo.IsSenderNonceS0Disabled) { handlingNonceGetFromNode = 0; } else { dataToSend = _securityS0CryptoProvider.GenerateNonceReport(new OrdinalPeerNodeId(ReceivedAchData.SrcNodeId, destNodeId)); } isSubstituteDenied = true; if (_securityManagerInfo.DelaysS0.ContainsKey(SecurityS0Delays.NonceReport)) { Thread.Sleep(_securityManagerInfo.DelaysS0[SecurityS0Delays.NonceReport]); } } else if (command[1] == COMMAND_CLASS_SECURITY.SECURITY_COMMANDS_SUPPORTED_GET.ID && handlingNonceGetFromNode != ReceivedAchData.SrcNodeId) { handlingNonceGetFromNode = ReceivedAchData.SrcNodeId; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; if (scheme == SecuritySchemes.S0) { if (!_securityManagerInfo.Network.IsSecuritySchemesSpecified(ReceivedAchData.SrcNodeId) || _securityManagerInfo.Network.HasSecurityScheme(ReceivedAchData.SrcNodeId, SecuritySchemes.S0)) { var ccReport = new COMMAND_CLASS_SECURITY.SECURITY_COMMANDS_SUPPORTED_REPORT(); if (!_securityManagerInfo.Network.HasSecurityScheme(SecuritySchemeSet.ALLS2)) { if (ReceivedAchData.DestNodeId > 0 && ReceivedAchData.DestNodeId != _securityManagerInfo.Network.NodeId) { ccReport.commandClassSupport = new List <byte>(_securityManagerInfo.Network.GetVirtualSecureCommandClasses()); } else { var secureCommandClasses = _securityManagerInfo.Network.GetSecureCommandClasses(); if (secureCommandClasses != null) { ccReport.commandClassSupport = new List <byte>(secureCommandClasses); } } dataToSend = ccReport; } else { dataToSend = new byte[] { 0x98, 0x03, 0x00 }; } } } } if (dataToSend != null) { ApiOperation sendData = null; if (ReceivedAchData.DestNodeId > 0) { sendData = new SendDataBridgeOperation(ReceivedAchData.DestNodeId, ReceivedAchData.SrcNodeId, dataToSend, _securityManagerInfo.TxOptions); } else { sendData = new SendDataOperation(ReceivedAchData.SrcNodeId, dataToSend, _securityManagerInfo.TxOptions); } if (isSubstituteDenied) { sendData.SubstituteSettings.SetFlag(SubstituteFlags.DenySecurity); } sendData.CompletedCallback = (x) => { var action = x as ActionBase; if (action != null) { handlingNonceGetFromNode = 0; SpecificResult.TotalCount++; if (action.Result.State != ActionStates.Completed) { SpecificResult.FailCount++; } } }; ou.SetNextActionItems(sendData); } else { ou.SetNextActionItems(); } } } else { "REJECT, {0}, {1} (IsNodeSecure[S0]={2}, IsActive={3}"._DLOG( _securityManagerInfo.IsInclusion, _securityManagerInfo.Network.HasSecurityScheme(ReceivedAchData.SrcNodeId, SecuritySchemes.S0), _securityManagerInfo.Network.HasSecurityScheme(SecuritySchemes.S0), _securityManagerInfo.IsActive); } } }
protected override void OnHandledInternal(DataReceivedUnit ou) { ou.SetNextActionItems(); byte nodeId = ReceivedAchData.SrcNodeId; byte[] command = ReceivedAchData.Command; var scheme = (SecuritySchemes)ReceivedAchData.SecurityScheme; bool isSuportedScheme = IsSupportedScheme(_network, command, scheme); if (command != null && command.Length > 1 && isSuportedScheme) { if (command[1] == COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_NAME_GET.ID) { var associationNameGetCmd = (COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_NAME_GET)command; var requestedGroupId = associationNameGetCmd.groupingIdentifier; if (requestedGroupId == GroupId) { ApiOperation sendData = null; var data = new COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_NAME_REPORT() { groupingIdentifier = GroupId, lengthOfName = (byte)Encoding.UTF8.GetByteCount(GroupName), name = Encoding.UTF8.GetBytes(GroupName) }; sendData = new SendDataExOperation(nodeId, data, TxOptions, TxSecOptions, scheme, TxOptions2); ou.SetNextActionItems(sendData); } } else if (command[1] == COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_INFO_GET.ID) { var associationInfoGetCmd = (COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_INFO_GET)command; var requestedGroupId = associationInfoGetCmd.groupingIdentifier; ApiOperation sendData = null; var data = new COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_INFO_REPORT() { properties1 = new COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_INFO_REPORT.Tproperties1() { listMode = associationInfoGetCmd.properties1.listMode, groupCount = 0x01 }, vg1 = new List <COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_INFO_REPORT.TVG1>() { new COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_INFO_REPORT.TVG1() { groupingIdentifier = GroupId, mode = 0, profile1 = 0, profile2 = 1 } } }; sendData = new SendDataExOperation(nodeId, data, TxOptions, TxSecOptions, scheme, TxOptions2); ou.SetNextActionItems(sendData); } else if (command[1] == COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_COMMAND_LIST_GET.ID) { var associationCommandListGetCmd = (COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_COMMAND_LIST_GET)command; var requestedGroupId = associationCommandListGetCmd.groupingIdentifier; ApiOperation sendData = null; var data = new COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3.ASSOCIATION_GROUP_COMMAND_LIST_REPORT() { groupingIdentifier = GroupId, listLength = 0x02, command = new List <byte>() { COMMAND_CLASS_BASIC.ID, COMMAND_CLASS_BASIC.BASIC_GET.ID, } }; sendData = new SendDataExOperation(nodeId, data, TxOptions, TxSecOptions, scheme, TxOptions2); ou.SetNextActionItems(sendData); } } }