/// <summary> /// Sends ZigBeeCommand command and uses the ZigBeeTransactionMatcher to match the response. /// The task will be timed out if there is no response. /// /// @param command the ZigBeeCommand /// @param responseMatcher the ZigBeeTransactionMatcher /// </summary> public async Task <CommandResult> SendTransaction(ZigBeeCommand command, IZigBeeTransactionMatcher responseMatcher) { _command = command; _responseMatcher = responseMatcher; _timeout = DateTime.Now.AddMilliseconds(DEFAULT_TIMEOUT_MILLISECONDS); lock (_command) { _networkManager.AddCommandListener(this); int transactionId = _networkManager.SendCommand(command); if (command is ZclCommand cmd) { cmd.TransactionId = (byte)transactionId; } } return(await Task.Run(() => { while (true) { if (DateTime.Now < _timeout) { if (_result != null) { return _result; } } else { _logger.Debug("Transaction timeout: {Command}", _command); lock (_command) { _networkManager.RemoveCommandListener(this); return new CommandResult(); } } } })); }
/// <summary> /// Sends ZigBeeCommand command and uses the ZigBeeTransactionMatcher to match the response. /// The task will be timed out if there is no response. /// /// <param name="command">the ZigBeeCommand</param> /// <param name="responseMatcher">the ZigBeeTransactionMatcher</param> /// </summary> public async Task <CommandResult> SendTransaction(ZigBeeCommand command, IZigBeeTransactionMatcher responseMatcher) { CommandResult commandResult; lock (_objLock) { _command = command; _responseMatcher = responseMatcher; _networkManager.AddCommandListener(this); int transactionId = _networkManager.SendCommand(command); if (command is ZclCommand cmd) { cmd.TransactionId = (byte)transactionId; } //Without RunContinuationsAsynchronously, calling SetResult can block the calling thread, because the continuation is run synchronously //see https://stackoverflow.com/a/37492081 _sendTransactionTask = new TaskCompletionSource <CommandResult>(TaskCreationOptions.RunContinuationsAsynchronously); } var t = _sendTransactionTask.Task; var cancel = new CancellationTokenSource(); var timeoutTask = Task.Delay(Timeout, cancel.Token); if (t == await Task.WhenAny(t, timeoutTask).ConfigureAwait(false)) { cancel.Cancel(); //Cancel the timeout task commandResult = t.Result; } else { /* Timeout */ Log.Debug("Transaction timeout: {Command}", _command); commandResult = new CommandResult(); } _networkManager.RemoveCommandListener(this); return(commandResult); }
public async Task <CommandResult> SendTransaction(ZigBeeCommand command, IZigBeeTransactionMatcher responseMatcher) { return(await _network.SendTransaction(command, responseMatcher)); }
/// <summary> /// Sends <see cref="ZigBeeCommand"> command and uses the <see cref="ZigBeeTransactionMatcher"> to match the response. /// /// <param name="command">the <see cref="ZigBeeCommand"> to send</param> /// <param name="responseMatcher">the <see cref="ZigBeeTransactionMatcher"> used to match the response to the request</param> /// <returns>the <see cref="CommandResult"> future.</returns> /// </summary> public async Task <CommandResult> SendTransaction(ZigBeeCommand command, IZigBeeTransactionMatcher responseMatcher) { //command.DestinationAddress = GetEndpointAddress(); return(await Node.SendTransaction(command, responseMatcher)); }
/// <summary> /// Sends ZigBeeCommand command and uses the ZigBeeTransactionMatcher to match the response. /// The task will be timed out if there is no response. /// /// <param name="command">the ZigBeeCommand</param> /// <param name="responseMatcher">the ZigBeeTransactionMatcher</param> /// </summary> public async Task <CommandResult> SendTransaction(ZigBeeCommand command, IZigBeeTransactionMatcher responseMatcher) { _command = command; _responseMatcher = responseMatcher; _timeout = DateTime.Now.AddMilliseconds(DEFAULT_TIMEOUT_MILLISECONDS); _networkManager.AddCommandListener(this); int transactionId = _networkManager.SendCommand(command); if (command is ZclCommand cmd) { cmd.TransactionId = (byte)transactionId; } _sendTransactionTask = new TaskCompletionSource <CommandResult>(); var t = _sendTransactionTask.Task; var timeoutTask = Task.Delay(DEFAULT_TIMEOUT_MILLISECONDS); var cancel = new CancellationTokenSource(); if (t == await Task.WhenAny(t, timeoutTask).ConfigureAwait(false)) { cancel.Cancel(); //Cancel the timeout task _networkManager.RemoveCommandListener(this); return(t.Result); } else { /* Timeout */ Log.Debug("Transaction timeout: {Command}", _command); _networkManager.RemoveCommandListener(this); return(new CommandResult()); } /* !!! OLD CODE WITHOUT COMPLETION SOURCE - DO NOT DELET IT YET !!! * * return await Task.Run(() => * { * while (true) * { * if (DateTime.Now < _timeout) * { * if (_result != null) * { * return _result; * } * } * else * { * Log.Debug("Transaction timeout: {Command}", _command); * lock (_command) * { * _networkManager.RemoveCommandListener(this); * return new CommandResult(); * } * } * } * }); * */ }