/// <summary> /// Sends the specified <see cref="WatchoutCommand" /> asynchronously while waiting for a response. /// </summary> /// <typeparam name="T">The <see cref="WatchoutFeedback" /> type.</typeparam> /// <param name="command">The command.</param> /// <returns> /// Returns the proper feedback. /// </returns> public async Task <T> SendCommand <T>(WatchoutCommand command) where T : WatchoutFeedback { Task <T> task = new Task <T>(() => { SendCommand(command); DateTime sentDate = DateTime.Now; while (!_availableFeedbacks.Exists(x => x.ID == command.ID) && DateTime.Now < sentDate.AddSeconds(CommandsTimeout)) { Thread.Sleep(30); } var feedback = _availableFeedbacks.SingleOrDefault(x => x.ID == command.ID) as T; if (feedback == null) { WatchoutFeedback falseInstnce = Activator.CreateInstance <T>(); falseInstnce.CommandName = command.Name; falseInstnce.ID = command.ID; falseInstnce.Error = new ErrorFeedback() { ErrorKind = ErrorKind.NETWORK_ERRORS, Explanation = "Could not contact the Watchout server." }; return(falseInstnce as T); } else { feedback.CommandName = command.Name; } _availableFeedbacks.Remove(feedback); if (feedback.GetType() == typeof(ErrorFeedback)) { WatchoutFeedback falseInstnce = Activator.CreateInstance <T>(); falseInstnce.ID = feedback.ID; falseInstnce.Error = feedback as ErrorFeedback; return(falseInstnce as T); } return(feedback); }); task.Start(); await task; return(task.Result); }
/// <summary> /// Deserializes the specified response string and returns the proper <see cref="WatchoutFeedback"/>. /// </summary> /// <param name="response">The response string.</param> /// <returns>Returns the proper <see cref="WatchoutFeedback"/>.</returns> public static WatchoutFeedback Deserialize(String response) { response = RemoveCarriageReturn(response); var feedbackTypes = Assembly.GetAssembly(typeof(CommandFormatter)).GetTypes().Where(t => t != typeof(WatchoutFeedback) && typeof(WatchoutFeedback).IsAssignableFrom(t)); List <String> parameters = Regex.Matches(response, @"[\""].+?[\""]|[^ ]+") .Cast <Match>() .Select(m => m.Value) .ToList(); String commandName = parameters.FirstOrDefault(); if (parameters.Count == 1 && commandName.Contains("[")) { return(new WatchoutFeedback() { ID = commandName.Replace("[", "").Replace("]", "") }); } parameters.RemoveAt(0); String commandId = null; if (commandName.Contains("[")) { commandName = commandName.Remove(0, 1); String[] commandAndID = commandName.Split(']'); commandId = commandAndID[0]; commandName = commandAndID[1]; } foreach (var type in feedbackTypes) { String fName = type.GetAttributeValue((FeedbackNameAttribute att) => att.Name); if (fName == commandName) { WatchoutFeedback feedback = Activator.CreateInstance(type) as WatchoutFeedback; feedback.ID = commandId; var props = type.GetProperties().Where(pi => !pi.GetCustomAttributes(typeof(WatchoutIgnoreAttribute), true).Any()).ToList(); for (int i = 0; i < parameters.Count; i++) { if (i > props.Count - 1) { break; } var prop = props[i]; if (prop.PropertyType == typeof(String)) { prop.SetValue(feedback, Convert.ChangeType(parameters[i].Replace("\"", ""), prop.PropertyType)); } else if (prop.PropertyType == typeof(TimeSpan)) { prop.SetValue(feedback, TimeSpan.FromMilliseconds(Convert.ToInt32(parameters[i]))); } else if (prop.PropertyType.IsEnum) { int number = -1; if (int.TryParse(parameters[i], out number)) { prop.SetValue(feedback, Convert.ChangeType(Enum.ToObject(prop.PropertyType, number), prop.PropertyType)); } } else { prop.SetValue(feedback, Convert.ChangeType(parameters[i], prop.PropertyType)); } } return(feedback); } } Debug.WriteLine("Unrecognized feedback received. " + response); return(null); //throw new UnrecognizedFeedbackException("Unrecognized feedback received. " + response); }