public static OperationMessage GetAddressableOperation(this HomeDevice homeDevice, OperationMessage message) { if (homeDevice.InUse) message.DestinationAddress = (ushort)homeDevice.Connector.Node.Address; return message; }
public FragmentReadTransaction(ModuleBase callingModule, OperationMessage.OPCodes startOpcode, OperationMessage.OPCodes confirmationOpcode, Type statusCodeType, ushort destinationAddress) { this.callingModule = callingModule; this.operationResponseOPCode = (OperationMessage.OPCodes)((int)startOpcode + 1); this.StartOpCode = startOpcode; this.ConfirmationOpCode = confirmationOpcode; this.DestinationAddress = destinationAddress; this.inputBuffer = new List<OperationMessage>(); }
/// <summary> /// Contructor /// </summary> /// <param name="callingModule">Reference to the calling module</param> /// <param name="opcode">OPCode used for the outgoing messages</param> /// <param name="statusCodeType">Type of the enum for status code parsing on error</param> /// <param name="destinationAddress">Destination node address</param> /// <param name="content">Content to send in bytes</param> public FragmentWriteTransaction(ModuleBase callingModule, OperationMessage.OPCodes opcode, Type statusCodeType, ushort destinationAddress, byte[] content) { this.callingModule = callingModule; this.operationResponseOPCode = (OperationMessage.OPCodes)((int)opcode + 1); this.applicationStatusCodeType = statusCodeType; this.OpCode = opcode; this.DestinationAddress = destinationAddress; this.outputBuffer = new List<OperationMessage>(); this.totalFragments = (byte)(content.Length / MAX_CONTENT_SIZE); for (byte i = 0; i <= this.totalFragments; i++) { this.CurrentFrameSize = Math.Min(MAX_CONTENT_SIZE, content.Length - (i * MAX_CONTENT_SIZE)); OperationMessage currentOp = new OperationMessage() { SourceAddress = 0x00, DestinationAddress = destinationAddress, OpCode = OperationMessage.OPCodes.ConfigWrite, Args = new byte[this.CurrentFrameSize + 2] }; currentOp.Args[0] = (byte)((this.totalFragments << 4) | (i & 0xF)); currentOp.Args[1] = (byte)this.CurrentFrameSize; Buffer.BlockCopy(content, (i * MAX_CONTENT_SIZE), currentOp.Args, 2, this.CurrentFrameSize); this.outputBuffer.Add(currentOp); } }
/// <summary> /// Method that process a received response. This method will check the response and send the next fragment. /// </summary> /// <param name="response">The received operation response</param> /// <returns>True if the operation was successfully sent</returns> public async Task<bool> ProcessResponse(OperationMessage response) { if (response.OpCode != this.operationResponseOPCode) throw new InvalidOperationException("The received OperationMessage has an invalid OPCode"); if (response.SourceAddress != this.DestinationAddress) throw new InvalidOperationException("The received OperationMessage has an invalid SourceAddress"); if (this.IsCompleted) throw new InvalidOperationException("The transaction is completed"); if (response.Args[0] == this.outputBuffer[0].Args[0]) { if (response.Args[1] == (byte)WriteSessionStatusCodes.OK) { this.outputBuffer.RemoveAt(0); if (this.outputBuffer.Count > 0) { return await callingModule.SendMessage(this.outputBuffer[0]); } else { Debug.WriteLine(String.Format("TRANSACTION WRITE DONE TO 0x{0:X4}", response.SourceAddress)); return true; } } else { object errorCode = (object)response.Args[1]; if (Enum.IsDefined(typeof(WriteSessionStatusCodes), errorCode)) Debug.WriteLine(String.Format("TRANSACTION WRITE TO 0x{0:X4} ERROR CODE: {1}", this.DestinationAddress, Enum.GetName(typeof(WriteSessionStatusCodes), errorCode))); else if (Enum.IsDefined(typeof(ConfigWriteStatusCodes), errorCode)) Debug.WriteLine(String.Format("TRANSACTION WRITE TO 0x{0:X4} APP ERROR CODE: {1}", this.DestinationAddress, Enum.GetName(typeof(ConfigWriteStatusCodes), errorCode))); else Debug.WriteLine(String.Format("TRANSACTION WRITE TO 0x{0:X4} UNKNOWN ERROR CODE: {1}", this.DestinationAddress, errorCode)); this.IsAborted = true; return false; } } else { int rcvFragment = response.Args[0] & 0x0F; int rcvTotalFragment = (response.Args[0] & 0xF0) >> 4; int expFragment = this.outputBuffer[0].Args[0] & 0x0F; int expTotalFragment = (this.outputBuffer[0].Args[0] & 0xF0) >> 4; Debug.WriteLine(String.Format("TRANSACTION WRITE INVALID PROTOCOL: RECEIVED({0}/{1}) EXPECTED({2}/{3})", rcvFragment, rcvTotalFragment, expFragment, expTotalFragment)); this.IsAborted = true; return false; } }
/// <summary> /// Method that process a received response. This method will check the response and send the next fragment. /// </summary> /// <param name="response">The received operation response</param> /// <returns>True if the operation was successfully sent</returns> public async Task<bool> ProcessResponse(OperationMessage operation) { if (operation.OpCode != this.operationResponseOPCode) throw new InvalidOperationException("The received OperationMessage has an invalid OPCode"); if (operation.SourceAddress != this.DestinationAddress) throw new InvalidOperationException("The received OperationMessage has an invalid SourceAddress"); if (this.IsCompleted) throw new InvalidOperationException("The transaction is completed"); int fragment = operation.Args[0] & 0x0F; OperationMessage lastOp = null; if (this.inputBuffer.Count == 0) //First response { this.NumberOfFragments = (byte)((operation.Args[0] & 0xF0) >> 4); } else { lastOp = this.inputBuffer.Last(); } if (lastOp == null || (lastOp != null && operation.Args[0] == lastOp.Args[0] + 1)) { if (operation.Args[0] == 0 && operation.Args[1] == 0) //ERROR { Debug.WriteLine(String.Format("CONFIG READ RESPONSE FROM 0x{0:X4} -> BUSY SENDING CONFIG STATE", operation.SourceAddress)); return false; } else //OK { Debug.WriteLine(String.Format("CONFIG READ RESPONSE FROM 0x{0:X4} -> {1}/{2} OK", operation.SourceAddress, fragment, this.NumberOfFragments)); this.inputBuffer.Add(operation); return await this.callingModule.SendMessage( new OperationMessage() { SourceAddress = 0x00, DestinationAddress = this.DestinationAddress, OpCode = this.ConfirmationOpCode, Args = new byte[] { operation.Args[0], 0x00 } }); } } else { Debug.WriteLine(String.Format("CONFIG READ RESPONSE FROM 0x{0:X4} -> {1}/{2} ERROR", operation.SourceAddress, fragment, this.NumberOfFragments)); //Send error code back await this.callingModule.SendMessage( new OperationMessage() { SourceAddress = 0x00, DestinationAddress = this.DestinationAddress, OpCode = this.ConfirmationOpCode, Args = new byte[] { operation.Args[0], 0x01 } }); return false; } }