/// <summary> /// Used by the event processor to update the initial data for the device /// without deleting the CommandHistory and the original created date /// This assumes the device controls and has full knowledge of its metadata except for: /// - CreatedTime /// - CommandHistory /// </summary> /// <param name="device">Device information to save to the backend Device Registry</param> /// <returns>Combined device that was saved to registry</returns> public async Task <dynamic> UpdateDeviceFromDeviceInfoPacketAsync(dynamic device) { if (device == null) { throw new ArgumentNullException("device"); } dynamic existingDevice = await GetDeviceAsync(DeviceSchemaHelper.GetDeviceID(device)); // Save the command history, original created date, and system properties (if any) of the existing device if (DeviceSchemaHelper.GetDeviceProperties(existingDevice) != null) { dynamic deviceProperties = DeviceSchemaHelper.GetDeviceProperties(device); deviceProperties.CreatedTime = DeviceSchemaHelper.GetCreatedTime(existingDevice); } device.CommandHistory = existingDevice.CommandHistory; // Copy the existing system properties, or initialize them if they do not exist if (existingDevice.SystemProperties != null) { device.SystemProperties = existingDevice.SystemProperties; } else { DeviceSchemaHelper.InitializeSystemProperties(device, null); } return(await _deviceRegistryCrudRepository.UpdateDeviceAsync(device)); }
/// <summary> /// Sends a command to the provided device and updates the command history of the device /// </summary> /// <param name="device">Device to send the command to</param> /// <param name="commandName">Name of the command to send</param> /// <param name="parameters">Parameters to send with the command</param> /// <returns></returns> private async Task <dynamic> SendCommandAsyncWithDevice(dynamic device, string commandName, dynamic parameters) { string deviceId; if (device == null) { throw new ArgumentNullException("device"); } bool canDevicePerformCommand = CommandSchemaHelper.CanDevicePerformCommand(device, commandName); deviceId = DeviceSchemaHelper.GetDeviceID(device); if (!canDevicePerformCommand) { throw new UnsupportedCommandException(deviceId, commandName); } dynamic command = CommandHistorySchemaHelper.BuildNewCommandHistoryItem(commandName); CommandHistorySchemaHelper.AddParameterCollectionToCommandHistoryItem(command, parameters); CommandHistorySchemaHelper.AddCommandToHistory(device, command); await _iotHubRepository.SendCommand(deviceId, command); await _deviceRegistryCrudRepository.UpdateDeviceAsync(device); return(command); }
public async Task <HttpResponseMessage> DeleteAllDevices() { return(await GetServiceResponseAsync(async() => { // note that you could also hardcode a query to delete a subset of devices var query = new DeviceListQuery() { Skip = 0, Take = 1000, SortColumn = "DeviceID", }; var devices = await _deviceLogic.GetDevices(query); foreach (var d in devices.Results) { if (d.DeviceProperties != null && d.DeviceProperties.DeviceID != null) { string deviceId = DeviceSchemaHelper.GetDeviceID(d); // do this in serial so as not to overload anything Debug.Write("DELETING DEVICE: " + deviceId + "..."); await _deviceLogic.RemoveDeviceAsync(deviceId); Debug.WriteLine(" (Deleted)"); } } return true; })); }
private async Task <List <string> > BootstrapDefaultDevices() { List <string> sampleIds = SampleDeviceFactory.GetDefaultDeviceNames(); foreach (string id in sampleIds) { dynamic device = DeviceSchemaHelper.BuildDeviceStructure(id, true); SecurityKeys securityKeys = _securityKeyGenerator.CreateRandomKeys(); try { await _iotHubRepository.AddDeviceAsync(device, securityKeys); await _virtualDeviceStorage.AddOrUpdateDeviceAsync(new InitialDeviceConfig() { DeviceId = DeviceSchemaHelper.GetDeviceID(device), HostName = _configProvider.GetConfigurationSettingValue("iotHub.HostName"), Key = securityKeys.PrimaryKey }); } catch (Exception ex) { //if we fail adding to table storage for the device simulator just continue Trace.TraceError("Failed to add simulated device : {0}", ex.Message); } } return(sampleIds); }
private async Task CheckIfDeviceExists(dynamic device, List <string> validationErrors) { // check if device exists if (await GetDeviceAsync(DeviceSchemaHelper.GetDeviceID(device)) != null) { validationErrors.Add(Strings.ValidationDeviceExists); } }
public void GetDeviceIDShouldReturnDeviceID() { var d = GetValidDevice(); string deviceID = DeviceSchemaHelper.GetDeviceID(d); Assert.AreEqual("test", deviceID); }
public async Task <ActionResult> Index() { string deviceId; DashboardModel model; DeviceListQuery query; DeviceListQueryResult queryResult; model = new DashboardModel(); query = new DeviceListQuery() { Skip = 0, Take = MaxDevicesToDisplayOnDashboard, SortColumn = "DeviceID" }; //The results of this query are used for populating the dropdown //As well as extracting location data. We want to include disabled //devices on the map, but not in the dropdown. The filters used //IN the query are apply additively to a "column". As a result, we //cannot filter on enabled AND disabled because the filters are //mutually exclusive. Also we cannot filter on !Pending. So to get //all that we need for both uses we need to just get all devices up //to the Take value and filter manually in the loop. The map will //filter out unregistered devices by virtue of their not having //location data. queryResult = await _deviceLogic.GetDevices(query); if ((queryResult != null) && (queryResult.Results != null)) { string enabledState = ""; dynamic props = null; foreach (dynamic devInfo in queryResult.Results) { try { deviceId = DeviceSchemaHelper.GetDeviceID(devInfo); props = DeviceSchemaHelper.GetDeviceProperties(devInfo); enabledState = props.HubEnabledState; } catch (DeviceRequiredPropertyNotFoundException) { continue; } if (!string.IsNullOrEmpty(deviceId) && !string.IsNullOrWhiteSpace(enabledState) && enabledState.ToLower() == "true") { model.DeviceIdsForDropdown.Add(new StringPair(deviceId, deviceId)); } } } model.DeviceLocations = _deviceLogic.ExtractLocationsData(queryResult.Results); model.MapApiQueryKey = _configProvider.GetConfigurationSettingValue("MapApiQueryKey"); return(View(model)); }
/// <summary> /// Adds a device to the DocumentDB. /// Throws a DeviceAlreadyRegisteredException if a device already exists in the database with the provided deviceId /// </summary> /// <param name="device"></param> /// <returns></returns> public async Task <dynamic> AddDeviceAsync(dynamic device) { string deviceId = DeviceSchemaHelper.GetDeviceID(device); dynamic existingDevice = await GetDeviceAsync(deviceId); if (existingDevice != null) { throw new DeviceAlreadyRegisteredException(deviceId); } device = await _docDbRestUtil.SaveNewDocumentAsync(device); return(device); }
/// <summary> /// Used by the event processor to update the initial data for the device /// without deleting the CommandHistory and the original created date /// This assumes the device controls and has full knowledge of its metadata except for: /// - CreatedTime /// - CommandHistory /// </summary> /// <param name="device">Device information to save to the backend Device Registry</param> /// <returns>Combined device that was saved to registry</returns> public async Task <dynamic> UpdateDeviceFromDeviceInfoPacketAsync(dynamic device) { if (device == null) { throw new ArgumentNullException("device"); } // Get original device document dynamic existingDevice = await GetDeviceAsync(DeviceSchemaHelper.GetDeviceID(device)); // Save the command history, original created date, and system properties (if any) of the existing device if (DeviceSchemaHelper.GetDeviceProperties(existingDevice) != null) { dynamic deviceProperties = DeviceSchemaHelper.GetDeviceProperties(device); deviceProperties.CreatedTime = DeviceSchemaHelper.GetCreatedTime(existingDevice); } device.CommandHistory = existingDevice.CommandHistory; // Copy the existing system properties, or initialize them if they do not exist if (existingDevice.SystemProperties != null) { device.SystemProperties = existingDevice.SystemProperties; } else { DeviceSchemaHelper.InitializeSystemProperties(device, null); } // Merge device back to existing so we don't drop missing data if (existingDevice is JObject) { existingDevice.Merge(device); } // If there is Telemetry or Command objects from device, replace instead of merge if (device.Telemetry != null) { existingDevice.Telemetry = device.Telemetry; } if (device.Commands != null) { existingDevice.Commands = device.Commands; } return(await _deviceRegistryCrudRepository.UpdateDeviceAsync(existingDevice)); }
public async Task <ActionResult> Index() { var model = new DashboardModel(); List <Infrastructure.Models.FilterInfo> filters = new List <Infrastructure.Models.FilterInfo>(); filters.Add(new Infrastructure.Models.FilterInfo() { ColumnName = "status", FilterType = FilterType.Status, FilterValue = "Running" }); var query = new DeviceListQuery() { Skip = 0, Take = MaxDevicesToDisplayOnDashboard, SortColumn = "DeviceID", Filters = filters }; DeviceListQueryResult queryResult = await _deviceLogic.GetDevices(query); if ((queryResult != null) && (queryResult.Results != null)) { foreach (dynamic devInfo in queryResult.Results) { string deviceId; try { deviceId = DeviceSchemaHelper.GetDeviceID(devInfo); } catch (DeviceRequiredPropertyNotFoundException) { continue; } model.DeviceIdsForDropdown.Add(new StringPair(deviceId, deviceId)); } } // Set key to empty if passed value 0 from arm template string key = _configProvider.GetConfigurationSettingValue("MapApiQueryKey"); model.MapApiQueryKey = key.Equals("0") ? string.Empty : key; return(View(model)); }
/// <summary> /// Updates an existing device in the DocumentDB /// Throws a DeviceNotRegisteredException is the device does not already exist in the DocumentDB /// </summary> /// <param name="device"></param> /// <returns></returns> public async Task <dynamic> UpdateDeviceAsync(dynamic device) { string deviceId = DeviceSchemaHelper.GetDeviceID(device); dynamic existingDevice = await GetDeviceAsync(deviceId); if (existingDevice == null) { throw new DeviceNotRegisteredException(deviceId); } string incomingRid = DeviceSchemaHelper.GetDocDbRid(device); if (string.IsNullOrWhiteSpace(incomingRid)) { // copy the existing _rid onto the incoming data if needed var existingRid = DeviceSchemaHelper.GetDocDbRid(existingDevice); if (string.IsNullOrWhiteSpace(existingRid)) { throw new InvalidOperationException("Could not find _rid property on existing device"); } device._rid = existingRid; } string incomingId = DeviceSchemaHelper.GetDocDbId(device); if (string.IsNullOrWhiteSpace(incomingId)) { // copy the existing id onto the incoming data if needed var existingId = DeviceSchemaHelper.GetDocDbId(existingDevice); if (string.IsNullOrWhiteSpace(existingId)) { throw new InvalidOperationException("Could not find id property on existing device"); } device.id = existingId; } DeviceSchemaHelper.UpdateUpdatedTime(device); device = await _docDbRestUtil.UpdateDocumentAsync(device); return(device); }
/// <summary> /// Adds the provided device to the IoT hub with the provided security keys /// </summary> /// <param name="device"></param> /// <param name="securityKeys"></param> /// <returns></returns> public async Task <dynamic> AddDeviceAsync(dynamic device, SecurityKeys securityKeys) { Azure.Devices.Device iotHubDevice = new Azure.Devices.Device(DeviceSchemaHelper.GetDeviceID(device)); var authentication = new AuthenticationMechanism { SymmetricKey = new SymmetricKey { PrimaryKey = securityKeys.PrimaryKey, SecondaryKey = securityKeys.SecondaryKey } }; iotHubDevice.Authentication = authentication; await AzureRetryHelper.OperationWithBasicRetryAsync <Azure.Devices.Device>(async() => await _deviceManager.AddDeviceAsync(iotHubDevice)); return(device); }
/// <summary> /// Used by the event processor to update the initial data for the device /// without deleting the CommandHistory and the original created date /// This assumes the device controls and has full knowledge of its metadata except for: /// - CreatedTime /// - CommandHistory /// </summary> /// <param name="device">Device information to save to the backend Device Registry</param> /// <returns>Combined device that was saved to registry</returns> public async Task <dynamic> UpdateDeviceFromDeviceInfoPacketAsync(dynamic device) { if (device == null) { throw new ArgumentNullException("device"); } dynamic existingDevice = await GetDeviceAsync(DeviceSchemaHelper.GetDeviceID(device)); // Save the command history and the original created date of the existing device if (DeviceSchemaHelper.GetDeviceProperties(existingDevice) != null) { dynamic deviceProperties = DeviceSchemaHelper.GetDeviceProperties(device); deviceProperties.CreatedTime = DeviceSchemaHelper.GetCreatedTime(existingDevice); } device.CommandHistory = existingDevice.CommandHistory; return(await _deviceRegistryCrudRepository.UpdateDeviceAsync(device)); }
private async Task <ActionResult> Add(UnregisteredDeviceModel model) { Debug.Assert(model != null, "model is a null reference."); Debug.Assert( model.DeviceType != null, "model.DeviceType is a null reference."); dynamic deviceWithKeys = await AddDeviceAsync(model); var newDevice = new RegisteredDeviceModel { HostName = this.iotHubName, DeviceType = model.DeviceType, DeviceId = DeviceSchemaHelper.GetDeviceID(deviceWithKeys.Device), PrimaryKey = deviceWithKeys.SecurityKeys.PrimaryKey, SecondaryKey = deviceWithKeys.SecurityKeys.SecondaryKey, InstructionsUrl = model.DeviceType.InstructionsUrl }; return(PartialView("_AddDeviceCopy", newDevice)); }
private async Task <List <dynamic> > LoadAllDevicesAsync() { var query = new DeviceListQuery() { Skip = 0, Take = MAX_DEVICES_TO_DISPLAY_ON_DASHBOARD, SortColumn = "DeviceID" }; string deviceId; var devices = new List <dynamic>(); DeviceListQueryResult queryResult = await _deviceLogic.GetDevices(query); if ((queryResult != null) && (queryResult.Results != null)) { string enabledState = ""; dynamic props = null; foreach (dynamic devInfo in queryResult.Results) { try { deviceId = DeviceSchemaHelper.GetDeviceID(devInfo); props = DeviceSchemaHelper.GetDeviceProperties(devInfo); enabledState = props.HubEnabledState; } catch (DeviceRequiredPropertyNotFoundException) { continue; } if (!string.IsNullOrWhiteSpace(deviceId)) { devices.Add(devInfo); } } } return(devices); }
public async Task <ActionResult> Index(string deviceId) { dynamic device = await _deviceLogic.GetDeviceAsync(deviceId); List <SelectListItem> commandListItems = CommandListItems(device); var deviceCommandsModel = new DeviceCommandModel { CommandHistory = new List <dynamic>(CommandHistorySchemaHelper.GetCommandHistory(device)), CommandsJson = JsonConvert.SerializeObject(device.Commands), SendCommandModel = new SendCommandModel { DeviceId = DeviceSchemaHelper.GetDeviceID(device), CommandSelectList = commandListItems, CanSendDeviceCommands = DeviceSchemaHelper.GetHubEnabledState(device) == true && PermsChecker.HasPermission(Permission.SendCommandToDevices) }, DeviceId = DeviceSchemaHelper.GetDeviceID(device) }; return(View(deviceCommandsModel)); }
public async Task <ActionResult> EditDeviceProperties(string deviceId) { EditDevicePropertiesModel model; IEnumerable <DevicePropertyValueModel> propValModels; model = new EditDevicePropertiesModel() { DevicePropertyValueModels = new List <DevicePropertyValueModel>() }; var device = await _deviceLogic.GetDeviceAsync(deviceId); if (!object.ReferenceEquals(device, null)) { model.DeviceId = DeviceSchemaHelper.GetDeviceID(device); propValModels = _deviceLogic.ExtractDevicePropertyValuesModels(device); propValModels = ApplyDevicePropertyOrdering(propValModels); model.DevicePropertyValueModels.AddRange(propValModels); } return(View("EditDeviceProperties", model)); }
public DeviceListLocationsModel ExtractLocationsData(List <dynamic> devices) { var result = new DeviceListLocationsModel(); //Initialize defaults around Seattle double minLat = 47.6; double maxLat = 47.6; double minLong = -122.3; double maxLong = -122.3; var locationList = new List <DeviceLocationModel>(); foreach (dynamic device in devices) { dynamic props = DeviceSchemaHelper.GetDeviceProperties(device); if (props.Longitude == null || props.Latitude == null) { continue; } double latitude; double longitude; try { latitude = DeviceSchemaHelper.GetDeviceProperties(device).Latitude; longitude = DeviceSchemaHelper.GetDeviceProperties(device).Longitude; } catch (FormatException) { continue; } var location = new DeviceLocationModel() { DeviceId = DeviceSchemaHelper.GetDeviceID(device), Longitude = longitude, Latitude = latitude }; locationList.Add(location); if (longitude < minLong) { minLong = longitude; } if (longitude > maxLong) { maxLong = longitude; } if (latitude < minLat) { minLat = latitude; } if (latitude > maxLat) { maxLat = latitude; } } var offset = 0.05; result.DeviceLocationList = locationList; result.MinimumLatitude = minLat - offset; result.MaximumLatitude = maxLat + offset; result.MinimumLongitude = minLong - offset; result.MaximumLongitude = maxLong + offset; return(result); }
private async Task ValidateDevice(dynamic device) { List <string> validationErrors = new List <string>(); if (ValidateDeviceId(device, validationErrors)) { await CheckIfDeviceExists(device, validationErrors); } if (validationErrors.Count > 0) { var validationException = new ValidationException(DeviceSchemaHelper.GetDeviceProperties(device) != null ? DeviceSchemaHelper.GetDeviceID(device) : null); foreach (string error in validationErrors) { validationException.Errors.Add(error); } throw validationException; } }
/// <summary> /// Adds the given device and assigned keys to the underlying repositories /// </summary> /// <param name="device">Device to add to repositories</param> /// <param name="securityKeys">Keys to assign to the device</param> /// <returns>Device that was added to the device registry</returns> private async Task <dynamic> AddDeviceToRepositoriesAsync(dynamic device, SecurityKeys securityKeys) { dynamic registryRepositoryDevice = null; ExceptionDispatchInfo capturedException = null; // if an exception happens at this point pass it up the stack to handle it // (Making this call first then the call against the Registry removes potential issues // with conflicting rollbacks if the operation happens to still be in progress.) await _iotHubRepository.AddDeviceAsync(device, securityKeys); try { registryRepositoryDevice = await _deviceRegistryCrudRepository.AddDeviceAsync(device); } catch (Exception ex) { // grab the exception so we can attempt an async removal of the device from the IotHub capturedException = ExceptionDispatchInfo.Capture(ex); } //Create a device in table storage if it is a simulated type of device //and the document was stored correctly without an exception bool isSimulatedAsBool = false; try { isSimulatedAsBool = (bool)device.IsSimulatedDevice; } catch (InvalidCastException ex) { Trace.TraceError("The IsSimulatedDevice property was in an invalid format. Exception Error Message: {0}", ex.Message); } if (capturedException == null && isSimulatedAsBool) { try { await _virtualDeviceStorage.AddOrUpdateDeviceAsync(new InitialDeviceConfig() { DeviceId = DeviceSchemaHelper.GetDeviceID(device), HostName = _configProvider.GetConfigurationSettingValue("iotHub.HostName"), Key = securityKeys.PrimaryKey }); } catch (Exception ex) { //if we fail adding to table storage for the device simulator just continue Trace.TraceError("Failed to add simulated device : {0}", ex.Message); } } // Since the rollback code runs async and async code cannot run within the catch block it is run here if (capturedException != null) { // This is a lazy attempt to remove the device from the Iot Hub. If it fails // the device will still remain in the Iot Hub. A more robust rollback may be needed // in some scenarios. await _iotHubRepository.TryRemoveDeviceAsync(DeviceSchemaHelper.GetDeviceID(device)); capturedException.Throw(); } return(registryRepositoryDevice); }
public DeviceListLocationsModel ExtractLocationsData(List <dynamic> devices) { var result = new DeviceListLocationsModel(); // Initialize defaults to opposite extremes to ensure mins and maxes are beyond any actual values double minLat = double.MaxValue; double maxLat = double.MinValue; double minLong = double.MaxValue; double maxLong = double.MinValue; var locationList = new List <DeviceLocationModel>(); foreach (dynamic device in devices) { dynamic props = DeviceSchemaHelper.GetDeviceProperties(device); if (props.Longitude == null || props.Latitude == null) { continue; } double latitude; double longitude; try { latitude = DeviceSchemaHelper.GetDeviceProperties(device).Latitude; longitude = DeviceSchemaHelper.GetDeviceProperties(device).Longitude; } catch (FormatException) { continue; } var location = new DeviceLocationModel() { DeviceId = DeviceSchemaHelper.GetDeviceID(device), Longitude = longitude, Latitude = latitude }; locationList.Add(location); if (longitude < minLong) { minLong = longitude; } if (longitude > maxLong) { maxLong = longitude; } if (latitude < minLat) { minLat = latitude; } if (latitude > maxLat) { maxLat = latitude; } } if (locationList.Count == 0) { // reinitialize bounds to center on Seattle area if no devices minLat = 47.6; maxLat = 47.6; minLong = -122.3; maxLong = -122.3; } double offset = 0.05; result.DeviceLocationList = locationList; result.MinimumLatitude = minLat - offset; result.MaximumLatitude = maxLat + offset; result.MinimumLongitude = minLong - offset; result.MaximumLongitude = maxLong + offset; return(result); }
private bool ValidateDeviceId(dynamic device, List <string> validationErrors) { if (DeviceSchemaHelper.GetDeviceProperties(device) == null || string.IsNullOrWhiteSpace(DeviceSchemaHelper.GetDeviceID(device))) { validationErrors.Add(Strings.ValidationDeviceIdMissing); return(false); } return(true); }
public void GetDeviceIDShouldThrowIfMissingDeviceID() { var d = GetDeviceWithMissingDeviceID(); Assert.Throws <DeviceRequiredPropertyNotFoundException>(() => DeviceSchemaHelper.GetDeviceID(d)); }