private void DispatchCommandTask(DeviceBase device, Command cCommand) { // invoke device DeviceCommandResult result; try { var command = new DeviceCommand(cCommand.Name.Trim(), cCommand.Parameters == null ? null : cCommand.Parameters.DeepClone(), cCommand.UserId); result = device.HandleCommand(command, _cancellationSource.Token); } catch (OperationCanceledException) { return; } catch (Exception ex) { // operation faulted - log the error and send failed result Logger.Error(string.Format("Exception while handling a command '{0}' by device {1} ({2})", cCommand.Name, device.ID, device.Name), ex); result = new DeviceCommandResult("Failed", "An error occurred while handling the command"); } // send command result cCommand.Status = result.Status; cCommand.Result = result.Result == null ? null : JToken.FromObject(result.Result, device.JsonSerializer); SendCommandResult(device, cCommand); }
/// <summary> /// Sends a notification on behalf of the specified device. /// </summary> /// <param name="sender">Sender <see cref="DeviceBase"/> object.</param> /// <param name="notification"><see cref="DeviceNotification"/> object to send.</param> public void SendNotification(DeviceBase sender, DeviceNotification notification) { if (sender == null) { throw new ArgumentNullException("sender"); } if (notification == null) { throw new ArgumentNullException("notification"); } Logger.InfoFormat("Sending notification '{0}' from device {1} ({2})", notification.Name, sender.ID, sender.Name); try { var cNotification = new Notification(notification.Name.Trim(), notification.Parameters == null ? null : notification.Parameters.DeepClone()); DeviceClient.SendNotification(sender.ID, sender.Key, cNotification); } catch (Exception ex) { // critical error - log and fault the service Logger.Error(string.Format("Exception while sending notification '{0}' from device {1} ({2})", notification.Name, sender.ID, sender.Name), ex); throw; } }
/// <summary> /// Sends a device status update. /// </summary> /// <param name="sender">Sender <see cref="DeviceBase"/> object.</param> /// <param name="status">New device status.</param> public void SendStatusUpdate(DeviceBase sender, string status) { if (sender == null) { throw new ArgumentNullException("sender"); } if (string.IsNullOrEmpty(status)) { throw new ArgumentException("Status is null or empty!", "status"); } Logger.InfoFormat("Updating device {1} ({2}) status to '{0}'", status, sender.ID, sender.Name); try { var cDevice = new Device(sender.ID, sender.Key) { Status = status }; DeviceClient.UpdateDevice(cDevice); } catch (Exception ex) { // critical error - log and fault the service Logger.Error(string.Format("Exception while updating device {1} ({2}) status to '{0}'", status, sender.ID, sender.Name), ex); throw; } }
/// <summary> /// Adds new device to the host. /// </summary> /// <param name="device"><see cref="DeviceBase"/> object to add.</param> public void AddDevice(DeviceBase device) { if (device == null) throw new ArgumentNullException("device"); device.Initialize(new DeviceServiceChannel(this, device)); _devices.Add(device); }
private void SendCommandResult(DeviceBase device, Command cCommand) { Logger.InfoFormat("Sending command '{0}' status '{1}' from device {2} ({3})", cCommand.Name, cCommand.Status, device.ID, device.Name); try { DeviceClient.UpdateCommand(device.ID, device.Key, cCommand); } catch (Exception ex) { // not critical - do nothing Logger.Error(string.Format("Exception while sending command '{0}' status '{1}' from device {2} ({3})", cCommand.Name, cCommand.Status, device.ID, device.Name), ex); } }
private void MainDeviceTask(DeviceBase device) { var token = _cancellationSource.Token; try { device.Main(token); } catch (OperationCanceledException) { return; } catch (Exception ex) { // operation faulted - log the error and stop the task Logger.Error(string.Format("Exception in main thread of device {0} ({1})", device.ID, device.Name), ex); throw; } }
private void RegisterDevice(DeviceBase device) { Logger.InfoFormat("Registering device {0} ({1})", device.ID, device.Name); try { var cDeviceClass = new DeviceClass(device.ClassName, device.ClassVersion, device.ClassOfflineTimeout, device.ClassData == null ? null : JToken.FromObject(device.ClassData, device.JsonSerializer)); var cDevice = new Device(device.ID, device.Key, device.Name, device.Status, device.Data == null ? null : JToken.FromObject(device.Data, device.JsonSerializer), Network, cDeviceClass); cDevice.Equipment = device.EquipmentInfo.Select(e => new Equipment( e.Name, e.Code, e.Type, e.Data == null ? null : JToken.FromObject(e.Data, device.JsonSerializer))).ToList(); DeviceClient.RegisterDevice(cDevice); } catch (Exception ex) { // critical error - log and fault the service Logger.Error(string.Format("Exception while registering device {0} ({1}), rethrowing exception", device.ID, device.Name), ex); throw; } }
private void SubscribeToCommands(DeviceBase device) { Logger.InfoFormat("Subscribe to device {0} ({1}) commands", device.ID, device.Name); if (device.ListenCommands) { while (true) { try { DeviceClient.SubscribeToCommands(device.ID, device.Key); break; } catch (DeviceServiceException e) { Logger.ErrorFormat("Error when subscribing to device {0} ({1}) commands: {2}", device.ID, device.Name, e); // retry with small wait Thread.Sleep(100); } } } }
/// <summary> /// Sends a device status update. /// </summary> /// <param name="sender">Sender <see cref="DeviceBase"/> object.</param> /// <param name="status">New device status.</param> public void SendStatusUpdate(DeviceBase sender, string status) { if (sender == null) throw new ArgumentNullException("sender"); if (string.IsNullOrEmpty(status)) throw new ArgumentException("Status is null or empty!", "status"); Logger.InfoFormat("Updating device {1} ({2}) status to '{0}'", status, sender.ID, sender.Name); try { var cDevice = new Device(sender.ID, sender.Key) { Status = status }; DeviceClient.UpdateDevice(cDevice); } catch (Exception ex) { // critical error - log and fault the service Logger.Error(string.Format("Exception while updating device {1} ({2}) status to '{0}'", status, sender.ID, sender.Name), ex); throw; } }
public DeviceServiceChannel(DeviceHost host, DeviceBase device) { _host = host; _device = device; }
/// <summary> /// Sends a notification on behalf of the specified device. /// </summary> /// <param name="sender">Sender <see cref="DeviceBase"/> object.</param> /// <param name="notification"><see cref="DeviceNotification"/> object to send.</param> public void SendNotification(DeviceBase sender, DeviceNotification notification) { if (sender == null) throw new ArgumentNullException("sender"); if (notification == null) throw new ArgumentNullException("notification"); Logger.InfoFormat("Sending notification '{0}' from device {1} ({2})", notification.Name, sender.ID, sender.Name); try { var cNotification = new Notification(notification.Name.Trim(), notification.Parameters == null ? null : notification.Parameters.DeepClone()); DeviceClient.SendNotification(sender.ID, sender.Key, cNotification); } catch (Exception ex) { // critical error - log and fault the service Logger.Error(string.Format("Exception while sending notification '{0}' from device {1} ({2})", notification.Name, sender.ID, sender.Name), ex); throw; } }
private void PollCommandsTask(DeviceBase device) { var timestamp = DateTime.UtcNow; var token = _cancellationSource.Token; while (true) { // poll commands List<Command> cCommands; try { cCommands = DeviceClient.PollCommands(device.ID, device.Key, timestamp, token); } catch (OperationCanceledException) { return; } catch (Exception ex) { // not critical - will retry Logger.Error(string.Format("Exception while polling commands for device {0} ({1})", device.ID, device.Name), ex); token.WaitHandle.WaitOne(1000); continue; } // dispatch comands to device timestamp = cCommands.Max(c => c.Timestamp.Value); foreach (var cCommand in cCommands) { Logger.InfoFormat("Dispatching command '{0}' to device {1} ({2})", cCommand.Name, device.ID, device.Name); var cCommandCopy = cCommand; _tasks.Add(Task.Factory.StartNew(() => DispatchCommandTask(device, cCommandCopy), token)); } } }