/// <summary> /// Remote call a function by its name with arguments and get the returned value /// </summary> /// <typeparam name="ReturnType">The .NET type expected. Should be the same as the Arduino function return type</typeparam> /// <param name="functionName">Name of the function to call</param> /// <param name="timeout">Maximum expected duration of the function execution on Arduino</param> /// <param name="arguments">Optional list of argument values.</param> /// <returns>Status of the function call with its returned value</returns> public SharerFunctionReturn <ReturnType> Call <ReturnType>(string functionName, TimeSpan timeout, params object[] arguments) { AssertConnected(); if (functionName == null) { throw new ArgumentNullException("functionName"); } Int16 functionId = -1; SharerFunction function = null; for (int i = 0; i < Functions.Count; i++) { if (Functions[i].Name == functionName) { function = Functions[i]; functionId = (Int16)i; break; } } if (function == null || functionId < 0) { throw new Exception(functionName + " not found in function list. Try to update the function List or check if this function has been shared."); } if (arguments == null || arguments.Length == 0) { if (function.Arguments.Count != 0) { throw new Exception("Attempt to call the function " + function.Name + " with no arguments, but the function has " + function.Arguments.Count + " arguments"); } } else if (function.Arguments.Count != arguments.Length) { throw new Exception("Attempt to call the function " + function.Name + " with " + arguments.Length + " argument(s), but the function has " + function.Arguments.Count + " argument(s)"); } byte[] buffer; using (MemoryStream memory = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(memory)) { writer.Write(functionId); if (arguments != null) { for (int i = 0; i < arguments.Length; i++) { if (arguments[i] == null) { throw new ArgumentNullException("arguments[" + i + "]"); } try { SharerTypeHelper.Encode(function.Arguments[i].Type, writer, arguments[i]); } catch (Exception ex) { throw new Exception("Error in argument " + function.Arguments[i].Name + " of function " + function.Name, ex); } } } buffer = memory.ToArray(); } } var cmd = new SharerCallFunctionCommand <ReturnType>(buffer, function.ReturnType); sendCommand(cmd); bool success = cmd.WaitAnswer(timeout); if (!success) { throw new Exception("Error while calling function " + functionName, cmd.Exception); } return(cmd.Return); }
internal override bool DecodeArgument(byte b) { switch (_receivedStep) { case Steps.FunctionCountHigh: // get number of functions Functions.Clear(); _nbFunctions = b; _receivedStep = Steps.FunctionCountLow; break; case Steps.FunctionCountLow: _nbFunctions = _nbFunctions + 256 * b; if (_nbFunctions == 0) { _receivedStep = Steps.End; // if no function, stop parsing } else { _receivedStep = Steps.ArgumentCount; } break; case Steps.ArgumentCount: // get number of functions _currentFunction = new SharerFunction(); _nbArguments = b; _receivedStep = Steps.FunctionReturnType; break; case Steps.FunctionReturnType: // get return type _currentFunction.ReturnType = (SharerType)b; _nameByte.Clear(); _receivedStep = Steps.FunctionName; break; case Steps.FunctionName: // get function name // if end of name if (b == 0) { _currentFunction.Name = System.Text.Encoding.UTF8.GetString(_nameByte.ToArray(), 0, _nameByte.Count); if (_nbArguments > 0) // if this function has arguments { _receivedStep = Steps.ArgumentType; } else { Functions.Add(_currentFunction); if (Functions.Count >= _nbFunctions) // if enought function { _receivedStep = Steps.End; } else // else, go to next function { _receivedStep = Steps.ArgumentCount; } } } else // else, store value { _nameByte.Add(b); } break; case Steps.ArgumentType: // Get argument type _currentArgument = new SharerFunctionArgument(); _currentArgument.Type = (SharerType)b; _nameByte.Clear(); _receivedStep = Steps.ArgumentName; break; case Steps.ArgumentName: // Get argument name // if end of name if (b == 0) { _currentArgument.Name = System.Text.Encoding.Default.GetString(_nameByte.ToArray(), 0, _nameByte.Count); _currentFunction.Arguments.Add(_currentArgument); if (_currentFunction.Arguments.Count >= _nbArguments) // if all arguments for this function has been read { Functions.Add(_currentFunction); if (Functions.Count >= _nbFunctions) // if enought functions { _receivedStep = Steps.End; } else // else, go to next function { _receivedStep = Steps.ArgumentCount; } } else // else, go to next argument { _receivedStep = Steps.ArgumentType; } } else // else, store value { _nameByte.Add(b); } break; default: break; } return(_receivedStep == Steps.End); }