/// <summary> /// Handles the firmware update operation of single hardware device. /// </summary> /// <param name="progress">Operation progress.</param> /// <param name="uploadedFileId">The unique Id of the uploaded firmware file.</param> /// <param name="hardwareId">The Id of the hardware that will have its firmware updated.</param> /// <returns>Operation status as a string and the new firmware version if update was successful.</returns> private FirmwareOperationResult UpdateFirmware(IProgress <int> progress, string uploadedFileId, string hardwareId) { try { progress?.Report(0); // Get the Recording server folder configuration item containing all Recording servers var recordersConfigurationItem = _configApiClient.GetItem("/RecordingServerFolder"); // Search for the specified hardware path progress?.Report(2); var selectedHardwarePath = GetHardwareInvokeItemPathRecursive(recordersConfigurationItem, hardwareId); if (string.IsNullOrEmpty(selectedHardwarePath)) { progress?.Report(100); return(new FirmwareOperationResult { Status = "Failed: Cannot get the hardware configuration item.", NewFirmwareVersion = string.Empty }); } progress?.Report(5); // Use the path found to get the hardware configuration item itself var hardwareConfigurationItem = _configApiClient.GetItem(selectedHardwarePath); // Get the needed invoke info configuration item by calling the needed method var invokeInfoItem = _configApiClient.InvokeMethod(hardwareConfigurationItem, "UpdateFirmwareHardware"); if (invokeInfoItem != null) { // Modify the invoke info item with the needed method data ConfigurationApiHelper.SetPropertyValue(invokeInfoItem, "StorageId", uploadedFileId); // Call the method with the provided data var createTaskResult = _configApiClient.InvokeMethod(invokeInfoItem, "UpdateFirmwareHardware"); var taskPath = ConfigurationApiHelper.GetPropertyValue(createTaskResult, "Path"); if (!string.IsNullOrEmpty(taskPath)) { var taskData = GetTaskData(taskPath); while (taskData.TaskProgress < 100) { Thread.Sleep(2000); taskData = GetTaskData(taskPath); progress?.Report(taskData.TaskProgress); } progress?.Report(100); if (taskData.TaskState == "Success") { return(new FirmwareOperationResult { NewFirmwareVersion = taskData.NewFirmwareVersion, Status = taskData.TaskState }); } // If we get other result than success we format it and return var failedText = !string.IsNullOrEmpty(taskData.TaskErrorText) ? $"{taskData.TaskState}: {taskData.TaskErrorCode}-{taskData.TaskErrorText}" : taskData.TaskState; return(new FirmwareOperationResult { Status = failedText, NewFirmwareVersion = string.Empty }); } } // If we get to here something went wrong with the update progress?.Report(100); return(new FirmwareOperationResult { Status = "Failed: Operation completed without returning the new firmware version.", NewFirmwareVersion = string.Empty }); } catch (Exception ex) { progress?.Report(100); return(new FirmwareOperationResult { Status = $"Exception: {ex.Message}", NewFirmwareVersion = string.Empty }); } }
/// <summary> /// Handles the file upload operation via Config API. /// </summary> /// <param name="progress">Operation progress.</param> /// <param name="filePath">Path to the file that needs to be uploaded.</param> /// <returns>Operation status as a string and file upload Id if upload was successful.</returns> private FirmwareOperationResult UploadFirmwareFile(IProgress <int> progress, string filePath) { try { // Get the parent configuration item - Management Server var systemConfigurationItem = _configApiClient.GetItem("/"); // Get the needed invoke info configuration item by calling the needed method var invokeInfoItem = _configApiClient.InvokeMethod(systemConfigurationItem, "UploadFileChunk"); const int chunkSize = 1000 * 1024; Guid transferId = Guid.NewGuid(); string uploadedFileId = string.Empty; long chunksSent = 0; progress?.Report(0); using (var fileStream = File.OpenRead(filePath)) { var buffer = new byte[chunkSize]; // Split the file content to chunks long totalChunks = fileStream.Length / chunkSize + (fileStream.Length % chunkSize > 0 ? 1 : 0); // Create hash checksum byte[] fileChecksum = fileStream.GetSha256Hash(); for (int offset = 0; offset < fileStream.Length && string.IsNullOrEmpty(uploadedFileId); offset += chunkSize, chunksSent++) { int readBytes = fileStream.Read(buffer, 0, chunkSize); // The last chunk is usually smaller than the chunkSize. We recreate the buffer accordingly for better performance. if (readBytes < chunkSize) { buffer = new ArraySegment <byte>(buffer, 0, readBytes).ToArray(); } // If the invoke item is null we return if (invokeInfoItem == null) { progress?.Report(100); return(new FirmwareOperationResult { Status = "Failed: Invoke item is null.", UploadedFileId = string.Empty }); } // Modify the configuration item to send the file chunk ConfigurationApiHelper.SetPropertyValue(invokeInfoItem, "TransferId", transferId.ToString()); ConfigurationApiHelper.SetPropertyValue(invokeInfoItem, "ChunkData", Convert.ToBase64String(buffer)); ConfigurationApiHelper.SetPropertyValue(invokeInfoItem, "Offset", offset.ToString()); ConfigurationApiHelper.SetPropertyValue(invokeInfoItem, "Size", fileStream.Length.ToString()); ConfigurationApiHelper.SetPropertyValue(invokeInfoItem, "Checksum", Convert.ToBase64String(fileChecksum)); // Send the modified configuration item var result = _configApiClient.InvokeMethod(invokeInfoItem, "UploadFileChunk"); uploadedFileId = ConfigurationApiHelper.GetPropertyValue(result, "StorageId"); var status = ConfigurationApiHelper.GetPropertyValue(result, "State"); // Check if the returned result contains the uploaded file Id if (string.IsNullOrEmpty(uploadedFileId)) { // Uploaded file Id is not returned - calculate the progress and report it int currentProgress = (int)(((float)chunksSent / (float)totalChunks) * 100); progress?.Report(currentProgress); } else { // If we get the uploaded file Id this means the upload is finished progress?.Report(100); return(new FirmwareOperationResult { Status = status, UploadedFileId = uploadedFileId }); } } } // If we get to here something went wrong with the upload progress?.Report(100); return(new FirmwareOperationResult { Status = "Failed: Operation completed without returning upload Id.", UploadedFileId = string.Empty }); } catch (Exception ex) { progress?.Report(100); return(new FirmwareOperationResult { Status = $"Exception: {ex.Message}", UploadedFileId = string.Empty }); } }