private IEnumerable <XProtectHardware> GetHardwareFromProfessional()
        {
            const string configPath = @"C:\ProgramData\Milestone\Milestone Surveillance\Configuration.xml";

            return(XProtectHardware.GetHardwareFromProfessionalConfigFile(configPath));
        }
        private bool AddCamera(XProtectHardware newHardwareInfo, string recorderName, string cameraGroupName)
        {
            Log("");
            Log($"Preparing to add {newHardwareInfo.DisplayName}...");
            var managementServer = new ManagementServer(EnvironmentManager.Instance.MasterSite);

            _recordingServer = _recordingServer ?? managementServer.RecordingServerFolder.RecordingServers.FirstOrDefault(x => x.Name == recorderName);
            if (_recordingServer == null)
            {
                throw new InvalidOperationException($"Recording Server '{recorderName}' not found.");
            }

            Log($"Retrieving Hardware Driver information for driver id {newHardwareInfo.DriverId}...");
            var hardwareDriverPath = _recordingServer.HardwareDriverFolder.HardwareDrivers.FirstOrDefault(d => d.Number == newHardwareInfo.DriverId)?.Path;

            if (hardwareDriverPath == null)
            {
                Log($"Hardware driver {newHardwareInfo.DriverId} not found. Skipping {newHardwareInfo.DisplayName}.");
                return(false);
            }

            Log($"Attempting to decrypt hardware credentials...");
            var decryptor = new StringDecryptor();
            var creds     = decryptor.Decrypt(newHardwareInfo.EncryptedPassword);

            Log($"Result '{creds.Username}:{creds.Password}'");
            Log($"Adding {newHardwareInfo.DisplayName} to Advanced VMS...");
            var uri = new Uri($"http://{newHardwareInfo.IPAddress}:{newHardwareInfo.HttpPort}");
            var addHardwareServerTask = _recordingServer.AddHardware(uri.ToString(), hardwareDriverPath, creds.Username, creds.Password ?? string.Empty);

            var t1 = DateTime.Now;

            while (addHardwareServerTask.State != StateEnum.Error && addHardwareServerTask.State != StateEnum.Success)
            {
                if (DateTime.Now - t1 > TimeSpan.FromMinutes(5))
                {
                    Log("Timeout of 5 minutes reached during add hardware. Current task state is " + addHardwareServerTask.State);
                    break;
                }
                System.Threading.Thread.Sleep(1000);
                addHardwareServerTask.UpdateState();
            }

            if (addHardwareServerTask.State != StateEnum.Success)
            {
                Log($"Operation did not complete. Last state was '{addHardwareServerTask.State}'. Error: {addHardwareServerTask.ErrorText}");
                return(false);
            }
            Log($"Hardware added successfully. Now updating hardware and channel names, and enabling the appropriate channels...");

            var hardware = new Hardware(EnvironmentManager.Instance.MasterSite.ServerId, addHardwareServerTask.Path);

            hardware.Name    = newHardwareInfo.DisplayName;
            hardware.Enabled = true;
            try
            {
                hardware.Save();
            }
            catch (Exception ex)
            {
                Log("Rename of hardware failed with error " + ex.Message);
            }

            var xppCameras = newHardwareInfo.GetCameras();
            var cameras    = hardware.CameraFolder.Cameras.OrderBy(c => c.Channel).ToList();

            foreach (var camera in cameras)
            {
                try
                {
                    var xppCamera = xppCameras.FirstOrDefault(c => c.Channel == camera.Channel);
                    camera.Name = xppCamera?.DisplayName ??
                                  $"Camera {camera.Channel + 1}";
                    camera.Enabled = xppCamera?.Enabled ?? false;
                    camera.Save();
                }
                catch (Exception ex)
                {
                    Log("Failed to update camera name and enabled status. Error " + ex.Message);
                }
            }

            var microphones = hardware.MicrophoneFolder.Microphones.OrderBy(m => m.Channel).Select(m => (dynamic)m);

            UpdateDevices(microphones, newHardwareInfo.DisplayName, "Microphone");
            var speakers = hardware.SpeakerFolder.Speakers.OrderBy(m => m.Channel).Select(m => (dynamic)m);

            UpdateDevices(speakers, newHardwareInfo.DisplayName, "Speaker");
            var inputs = hardware.InputEventFolder.InputEvents.OrderBy(m => m.Channel).Select(m => (dynamic)m);

            UpdateDevices(inputs, newHardwareInfo.DisplayName, "Input");
            var outputs = hardware.OutputFolder.Outputs.OrderBy(m => m.Channel).Select(m => (dynamic)m);

            UpdateDevices(outputs, newHardwareInfo.DisplayName, "Output");
            var metadata = hardware.MetadataFolder.Metadatas.OrderBy(m => m.Channel).Select(m => (dynamic)m);

            UpdateDevices(metadata, newHardwareInfo.DisplayName, "Metadata");

            // alter other camera properties(?)
            var cameraGroup = FindOrAddCameraGroup(managementServer, cameraGroupName);

            foreach (var camera in cameras)
            {
                cameraGroup?.CameraFolder.AddDeviceGroupMember(camera.Path);
            }
            Log($"Sucessfully added {newHardwareInfo.DisplayName} and updated channel names and state");
            return(true);
        }