UNPKG

lavva.exalushome

Version:

Library implementing communication and abstraction layers for ExalusHome system

936 lines (935 loc) 62.9 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { TypedEvent } from '../../TypedEvent'; import { DeviceState, CommunicationWay, DeviceType, DeviceTaskTypeInfo, DeviceResponseTypeInfo, DeviceTasksInfo, DeviceResponseType, IconType } from './IDevice'; import { DeviceTaskPairExecutionResult } from './IDevicesService'; import { BatteryDeviceState, BinarySensorStateDeviceState, BlindCalibrationDeviceState, BlindErrorDeviceState, BlindOpenCloseTimeDeviceState, BlindPositionDeviceState, BlindRemoteButtonDeviceState, ChannelOnOffDeviceState, ConfigurationDeviceState, CurrentLightThresholdDeviceState, CurrentWindThresholdDeviceState, DoorBellDeviceState, FacadePositionDeviceState, FacadeRemoteButtonDeviceState, FacadeTypeDeviceState, FloodSensorDeviceState, GateControllerHealthDeviceState, GatePositionDeviceState, GatewayPositionDeviceState, HumiditySensorDeviceState, LightBrightnessDeviceState, LightColorDeviceState, LightRGBWDeviceState, LightWarmthDeviceState, MeasuredBrightnessDeviceState, MeasuredDistanceDeviceState, MeasuredEnergyDeviceState, MeasuredTemperatureDeviceState, MovementSensorDeviceState, OnlineCameraState, OvercurrentProtectionDeviceState, OvercurrentProtectionThresholdDeviceState, PressureSensorDeviceState, ReedStateDeviceState, RemoteButtonDeviceState, SignalStrenghtDeviceState, StateReliability, TamperProtectionDeviceState, VibrationSensorDeviceState, WindSpeedDeviceState, ChannelHallStateState, ChannelSceneExecutedState, IntercomDeviceState } from './IDeviceState'; import { DeviceChannel } from './DeviceChannel'; import { ChannelConfigurations, TaskExecution } from './IDeviceChannel'; import { Api } from '../../Api'; import { ExalusConnectionService } from '../ExalusConnectionService'; import { DependencyContainer } from '../../DependencyContainer'; import { DataFrame, Status, Method } from '../../DataFrame'; import { Device } from './Device'; import { DeviceControlFeature } from './IDeviceTask'; import { BlindActionEnum, FacadeActionEnum, GateActionEnum } from './Tasks/Tasks'; import { SessionService } from '../Session/SessionService'; import { ControllerConfigurationService } from '../Controller/ControllerConfigurationService'; import { DeviceTaskExecutionResult } from './TaskExecutionResult'; import { ManuallyPairedDevicesService } from './ManuallyPairedDevicesService'; import { RemoteStorageDataEntry } from '../IRemoteStorageService'; import { RemoteStorageService } from '../RemoteStorageService'; import { AccessLevel } from '../Users/IUser'; import { WebApiCacheService } from '../WebApi/WebApiCacheService'; import { ScenesService } from '../Scenes/ScenesService'; import { ResponseResult } from '../FieldChangeResult'; import { ParseObjToMap } from '../../Helpers'; import { AppState } from '../IAppStateService'; import { AppStateService } from '../AppStateService'; /** * @type Class */ export class DevicesService { constructor() { this._devices = []; this._onDevicesTasksChangedEvent = new TypedEvent(); this._onDeviceFoundEvent = new TypedEvent(); this._onDeviceRegisteredEvent = new TypedEvent(); this._onDeviceRemovedEvent = new TypedEvent(); this._onDeviceFirmwareVersionChangedEvent = new TypedEvent(); this._onDeviceStateChangedEvent = new TypedEvent(); this._onDeviceStateRefreshedOrChangedEvent = new TypedEvent(); this._connection = null; this._session = null; this._controllerConfiguration = null; this._synchronized = false; this._synchronizedDevicesStates = false; this._devicesChannelsStates = []; this._synchronizationTaskCompletionSource = null; this._deviceStatesSynchronizationTaskCompletionSource = null; this._connection = Api.Get(ExalusConnectionService.ServiceName); this._session = Api.Get(SessionService.ServiceName); this._controllerConfiguration = Api.Get(ControllerConfigurationService.ServiceName); this._onDeviceStateChangedEvent.Subscribe((args) => __awaiter(this, void 0, void 0, function* () { return this.PutDeviceStateOnList(args.Device, args.State); })); this._synchronizationTaskCompletionSource = new Promise((resolve) => { var _a; (_a = this._session) === null || _a === void 0 ? void 0 : _a.OnUserLoggedInEvent().Subscribe((user) => __awaiter(this, void 0, void 0, function* () { var _a; try { this._devices = yield this.GetPairedDevicesAsync(true); } catch (ex) { (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Error(DevicesService.ServiceName, `Failed to get paired devices: ${ex}`); } this._synchronized = true; resolve(); })); }); this._deviceStatesSynchronizationTaskCompletionSource = new Promise((resolve) => { var _a; (_a = this._session) === null || _a === void 0 ? void 0 : _a.OnUserLoggedInEvent().Subscribe((user) => __awaiter(this, void 0, void 0, function* () { var _a; try { yield this.WaitForSynchronizationAsync(); yield this.SyncDevicesStatesAsync(); } catch (ex) { (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Error(DevicesService.ServiceName, `Failed to sync devices states: ${ex}`); } this._synchronizedDevicesStates = true; resolve(); })); }); Api.Get(AppStateService.ServiceName).OnAppStateChanged().Subscribe((appState) => __awaiter(this, void 0, void 0, function* () { switch (appState) { case AppState.ReturnedFromSuspension: if (Api.Get(ExalusConnectionService.ServiceName).IsConnected() && this._synchronizedDevicesStates == true) this.SyncDevicesStatesAsync(); break; case AppState.Disconnected: break; case AppState.Connected: if (this._synchronizedDevicesStates == true) this.SyncDevicesStatesAsync(); break; } })); this._connection.SubscribeTo("/info/devices/tasks", (frame) => { this.ParseDeviceTaskInfo(frame.Data); }); this._connection.SubscribeTo("/info/devices/device/found", (frame) => { const foundDevices = this.MapApiDevices(frame.Data); foundDevices.forEach(device => { var _a; if (device.DeviceType == DeviceType.Scene) return; (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Debug(DevicesService.ServiceName, `Found device: ${device.Name} guid: ${device.Guid}`); this._onDeviceFoundEvent.Invoke(device); }); }); this._connection.SubscribeTo("/info/devices/device/firmware/updated", (frame) => { const deviceGuid = frame.Data.DeviceGuid; const version = frame.Data.Version; const dev = this._devices.find(a => a.Guid == deviceGuid); if (dev !== undefined) { this._onDeviceFirmwareVersionChangedEvent.Invoke({ Device: dev, FirmwareVersion: version }); dev.SoftwareVersion = version; dev.OnDeviceFirmwareVersionChangedEvent().Invoke({ FirmwareVersion: version }); } }); this._connection.SubscribeTo("/info/devices/device/state/changed", (frame) => { var _a; const state = frame.Data; const devices = this._devices.filter(a => a.Guid == state.DeviceGuid); if (devices.length > 0) { const device = devices[0]; const st = this.MapApiDeviceStateToDeviceState(device, state); if (st != null) { this._onDeviceStateRefreshedOrChangedEvent .Invoke({ Device: device, State: st }); if (st.TypeAsEnum == DeviceResponseType.SignalStrength) { device.Channels.forEach(channel => { /// object copy { ...state } let newState = new SignalStrenghtDeviceState(Object.assign({}, state)); newState.Data.Channel = channel.Number; this._onDeviceStateRefreshedOrChangedEvent .Invoke({ Device: device, State: newState }); }); } else if (st.TypeAsEnum == DeviceResponseType.BatteryState) { device.Channels.forEach(channel => { let newState = new BatteryDeviceState(Object.assign({}, state)); newState.Data.Channel = channel.Number; this._onDeviceStateRefreshedOrChangedEvent .Invoke({ Device: device, State: newState }); }); } /// react only if state data changes, not just state time! let channelState = device.States.find(a => a.TypeAsEnum === st.TypeAsEnum && a.Data.Channel === st.Data.Channel); if (channelState) { let compData = channelState.StatesComparisonData; if (st.TypeAsEnum == DeviceResponseType.BlindErrorState) { const errCodeNew = (_a = st.Data) === null || _a === void 0 ? void 0 : _a.ErrorCode; const errStateCurr = channelState.Data.ErrorCode; if (errCodeNew != errStateCurr) { this._onDeviceStateChangedEvent .Invoke({ Device: device, State: st }); return; } } // replace old state object data with new one channelState.Data = st.Data; // compare old state with new one if (compData !== st.StatesComparisonData) { this._onDeviceStateChangedEvent .Invoke({ Device: device, State: st }); if (st.TypeAsEnum == DeviceResponseType.SignalStrength) { device.Channels.forEach(channel => { /// object copy { ...state } let newState = new SignalStrenghtDeviceState(Object.assign({}, state)); newState.Data.Channel = channel.Number; this._onDeviceStateChangedEvent .Invoke({ Device: device, State: newState }); }); } else if (st.TypeAsEnum == DeviceResponseType.BatteryState) { device.Channels.forEach(channel => { let newState = new BatteryDeviceState(Object.assign({}, state)); newState.Data.Channel = channel.Number; this._onDeviceStateChangedEvent .Invoke({ Device: device, State: newState }); }); } } } else { device.States.push(st); this._onDeviceStateChangedEvent .Invoke({ Device: device, State: st }); if (st.TypeAsEnum == DeviceResponseType.SignalStrength) { device.Channels.forEach(channel => { /// object copy { ...state } let newState = new SignalStrenghtDeviceState(Object.assign({}, state)); newState.Data.Channel = channel.Number; this._onDeviceStateChangedEvent .Invoke({ Device: device, State: newState }); }); } else if (st.TypeAsEnum == DeviceResponseType.BatteryState) { device.Channels.forEach(channel => { let newState = new BatteryDeviceState(Object.assign({}, state)); newState.Data.Channel = channel.Number; this._onDeviceStateChangedEvent .Invoke({ Device: device, State: newState }); }); } } } } }); this._connection.SubscribeTo("/info/devices/devices/registered", (frame) => { Api.Get(WebApiCacheService.ServiceName).ClearCache(); const registeredDevices = this.MapApiDevices(frame.Data); registeredDevices.forEach(device => { var _a; (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Debug(DevicesService.ServiceName, `Registered device: ${device.Name} guid: ${device.Guid}`); this._devices.push(device); this._onDeviceRegisteredEvent.Invoke(device); }); }); this._connection.SubscribeTo("/info/devices/devices/removed", (frame) => { Api.Get(WebApiCacheService.ServiceName).ClearCache(); const removedDevices = this.MapApiDevices(frame.Data); removedDevices.forEach(device => { var _a; (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Debug(DevicesService.ServiceName, `Removed device: ${device.Name} guid: ${device.Guid}`); this._devices = this._devices.filter(a => a.Guid != device.Guid); this._onDeviceRemovedEvent.Invoke(device); }); }); } ProtocolGuidToProtocolName(guid) { switch (guid) { case "1fca7e8a-a2dc-4883-bd94-4e9b2012f685": return "ExtaLife"; case "cd25bdff-628c-4dbc-a16a-648c96a819d4": return "Portos 433MHz"; case "634c2bb2-1a4f-4db6-8dd4-d5fbaf92678e": return "Supla"; case "194aeb81-990c-4a02-9236-59e902958fda": return "RTSP"; case "b3e4644e-ab5b-494e-b3c5-66fabe7fff64": return "Wekta"; case "247198e1-e360-4355-9886-232ac1456eea": return "Lavva Wi-Fi"; default: return null; } } CanDisplaySceneDevices() { return this.CheckIfControllerSoftwareVersionIsEnough(6, 56); } CheckIfControllerSoftwareVersionIsEnough(requiredContainerMajor, requiredContainerMinor) { var _a, _b, _c; const versionString = (_c = (_b = (_a = this._session) === null || _a === void 0 ? void 0 : _a.User) === null || _b === void 0 ? void 0 : _b.SoftwareVersion) !== null && _c !== void 0 ? _c : null; if (!versionString || !versionString.includes('.')) return false; const segments = versionString.split('.'); if (segments.length !== 2) return false; const numbers = segments.map(s => parseInt(s, 10)); if (numbers.some(n => Number.isNaN(n) || n < 0)) return false; const [containerMajor, containerMinor] = numbers; return (containerMajor > requiredContainerMajor) || (containerMajor === requiredContainerMajor && containerMinor >= requiredContainerMinor); } CheckIfDeviceUsedInScenesAsync(dev) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f; try { let device; if (typeof dev == 'string') { const result = this.GetDevice(dev); if (result != null) device = result; else { (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Error(`Cannot check if device is used in scenes! Device with given guid not exists`); return Status.ResourceDoesNotExists; } } else { device = dev; } const resp = yield ((_b = this._connection) === null || _b === void 0 ? void 0 : _b.SendAndWaitForResponseAsync(new DeviceIsUsedInScenesRequest(device.Guid), 20000, false)); if (resp == null || resp.Status == null) { (_c = DependencyContainer.Log) === null || _c === void 0 ? void 0 : _c.Error(`Cannot check if device is used in scenes! Response or status is null!`); return Status.FatalError; } if (resp.Status != Status.OK) return resp.Status; if (resp.Data == null) { (_d = DependencyContainer.Log) === null || _d === void 0 ? void 0 : _d.Error(`Cannot check if device is used in scenes! No data!`); return Status.FatalError; } var seqList = yield Api.Get(ScenesService.ServiceName).GetSequencesListAsync(); if (seqList instanceof ResponseResult) { (_e = DependencyContainer.Log) === null || _e === void 0 ? void 0 : _e.Error(`Cannot check if device is used in scenes! Cannot get sequence list, ScenesServiceErrorCode: ${seqList.Type}`); return Status.Error; } const result = new DeviceUsedInScenes(); result.DeviceGuid = device.Guid; resp.Data.ConditionsAsCondition.forEach(cGuid => { const con = seqList.find(s => s.Guid == cGuid); if (con) result.ConditionsAsCondition.push(con); }); resp.Data.ConditionsAsTask.forEach(tGuid => { const con = seqList.find(s => s.Guid == tGuid); if (con) result.ConditionsAsCondition.push(con); }); return result; } catch (error) { (_f = DependencyContainer.Log) === null || _f === void 0 ? void 0 : _f.Error(`Cannot check if device is used in scenes! ${error}`); return Status.FatalError; } }); } CanEditDevicesInfo() { var _a, _b; if (this._session === null || this._session === undefined) return false; if (this._session.User === null || this._session.User === undefined) return false; return ((_b = (_a = this._session) === null || _a === void 0 ? void 0 : _a.User) === null || _b === void 0 ? void 0 : _b.AccessLevel) >= AccessLevel.Admin; } CanAddAndRemoveAndConfigureDevices() { var _a, _b; if (this._session === null || this._session === undefined) return false; if (this._session.User === null || this._session.User === undefined) return false; return ((_b = (_a = this._session) === null || _a === void 0 ? void 0 : _a.User) === null || _b === void 0 ? void 0 : _b.AccessLevel) >= AccessLevel.Installator; } GetDeviceChannelByChannelId(channelId) { return this._devices.firstOrDefault(device => device.Channels.any(channel => channel.ChannelId == channelId)) .Channels.firstOrDefault(channel => channel.ChannelId == channelId); } EnableFastStatesSyncAsync() { return __awaiter(this, void 0, void 0, function* () { var _a; const res = Api.Get(RemoteStorageService.ServiceName).SaveAsync("FastDevicesSync", false, true); (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Error(DevicesService.ServiceName, `EXIT CONFIGURATION MODE WILL BE FIRED! EnableFastStatesSyncAsync()`); yield Api.Get(ControllerConfigurationService.ServiceName).ExitConfigurationModeAsync(); return res; }); } DisableFastStatesSyncAsync() { return __awaiter(this, void 0, void 0, function* () { var _a; const res = Api.Get(RemoteStorageService.ServiceName).SaveAsync("FastDevicesSync", false, false); (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Error(DevicesService.ServiceName, `EXIT CONFIGURATION MODE WILL BE FIRED! DisableFastStatesSyncAsync()`); yield Api.Get(ControllerConfigurationService.ServiceName).ExitConfigurationModeAsync(); return res; }); } IsFastStatesSyncEnabledAsync() { return __awaiter(this, void 0, void 0, function* () { const res = yield Api.Get(RemoteStorageService.ServiceName).ReadAsync("FastDevicesSync", false, false); if (res instanceof RemoteStorageDataEntry) { return res.Data; } //Controller returns ResourceDoesNotExists if fastSync option was never enabled (no option in DB - default slow sync) if (res == Status.ResourceDoesNotExists) return false; return res; }); } GetDevicesForManualPairingAsync(protocol) { return __awaiter(this, void 0, void 0, function* () { let service = Api.Get(ManuallyPairedDevicesService.ServiceName); const regGuid = new RegExp("^[{]?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?$"); if (Array.isArray(protocol)) { return yield service.GetDevicesForManualPairingAsync(protocol); } else if (regGuid.test(protocol)) { return yield service.GetDevicesForManualPairingAsync(protocol); } else { return yield service.GetDevicesForManualPairingAsync(); } }); } AddManuallyPairedDevice(device) { return __awaiter(this, void 0, void 0, function* () { var _a; var res = yield Api.Get(ManuallyPairedDevicesService.ServiceName).AddManuallyPairedDeviceAsync(device); (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Error(DevicesService.ServiceName, `EXIT CONFIGURATION MODE WILL BE FIRED! AddManuallyPairedDevice()`); yield Api.Get(ControllerConfigurationService.ServiceName).ExitConfigurationModeAsync(); return res; }); } GetDeviceChannelStates(device, channel) { var _a, _b; return (_b = (_a = this._devicesChannelsStates.firstOrDefault(a => a.DeviceGuid == device.Guid)) === null || _a === void 0 ? void 0 : _a.ChannelsStates.filter(a => a.Channel == channel)) !== null && _b !== void 0 ? _b : []; } GetDeviceStates(device) { var _a, _b; return (_b = (_a = this._devicesChannelsStates.firstOrDefault(a => a.DeviceGuid == device.Guid)) === null || _a === void 0 ? void 0 : _a.ChannelsStates) !== null && _b !== void 0 ? _b : []; } PutDeviceStateOnList(device, state) { let deviceStatesOnList = this._devicesChannelsStates.firstOrDefault(a => a.DeviceGuid == device.Guid); if (deviceStatesOnList == null) { let s = new DeviceChannelStates(); s.Channel = state.Data.Channel; s.States = [state]; deviceStatesOnList = { DeviceGuid: device.Guid, ChannelsStates: [s] }; this._devicesChannelsStates.push(deviceStatesOnList); } else { let channel = deviceStatesOnList.ChannelsStates.firstOrDefault(a => a.Channel == state.Data.Channel); if (channel == null) { channel = new DeviceChannelStates(); channel.Channel = state.Data.Channel; channel.States = [state]; deviceStatesOnList.ChannelsStates.push(channel); } else { let currentState = channel.States.firstOrDefault(a => a.TypeAsEnum == state.TypeAsEnum); if (currentState != null) { if (currentState.TypeAsEnum == DeviceResponseType.BlindErrorState) { channel.States = channel.States.where(a => a.Data.ErrorCode != state.Data.ErrorCode).toArray(); } else { channel.States = channel.States.where(a => a.TypeAsEnum != state.TypeAsEnum).toArray(); } } channel.States.push(state); } } } WaitForSynchronizationAsync() { return this._synchronizationTaskCompletionSource; } WaitForDevicesStatesSynchronizationAsync() { return this._deviceStatesSynchronizationTaskCompletionSource; } GetCurrentlyRunningTaksAsync() { return __awaiter(this, void 0, void 0, function* () { var _a; const result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new GetRunningDevicesTasksRequest(), 15000, false)); if ((result === null || result === void 0 ? void 0 : result.Status) == Status.OK && result.Data != null) { this.ParseDeviceTaskInfo(result.Data); } }); } ParseDeviceTaskInfo(tasks) { const devicesTasks = []; tasks.forEach(taskChannelPair => { const pair = taskChannelPair.split(";"); const task = new DeviceTasksInfo(); task.DeviceGuid = pair[0]; task.Channel = Number(pair[1]); task.Status = TaskExecution.ExecutingTasks; devicesTasks.push(task); if (task.Channel === 0) { const device = this._devices.find(a => a.Guid == task.DeviceGuid); if (device !== undefined) { device.Channels.forEach(channel => { const task = new DeviceTasksInfo(); task.DeviceGuid = device.Guid; task.Channel = channel.Number; task.Status = TaskExecution.ExecutingTasks; devicesTasks.push(task); }); } } }); this._onDevicesTasksChangedEvent.Invoke(devicesTasks); } MapApiDeviceStateToDeviceState(device, state) { var _a; const st = state.state; switch (state.DataType) { case "ChannelOnOff": return new ChannelOnOffDeviceState(state); case "DoorBell": return new DoorBellDeviceState(state); case "ReedPosition": return new ReedStateDeviceState(state); case "BlindPosition": return new BlindPositionDeviceState(state); case "ButtonState": return new RemoteButtonDeviceState(state); case "LightColor": return new LightColorDeviceState(state); case "LightTemperature": return new LightWarmthDeviceState(state); case "LightBrightness": return new LightBrightnessDeviceState(state); case "TemperatureSensor": case "TemperatureState": case "MeasuredTemperature": return new MeasuredTemperatureDeviceState(state); case "BatteryState": return new BatteryDeviceState(state); case "MeasuredBrightness": case "DeviceBrightnessState": return new MeasuredBrightnessDeviceState(state); case "EnergyMeasuredPower": break; case "EnergyMeasuredCurrent": break; case "EnergyMeasuredVoltage": break; case "IEnergy": case "Energy": return new MeasuredEnergyDeviceState(state); case "DistanceSensor": return new MeasuredDistanceDeviceState(state); case "MovementSensor": return new MovementSensorDeviceState(state); case "BlindsControlButton": return new BlindRemoteButtonDeviceState(state); case "FacadeControlButton": return new FacadeRemoteButtonDeviceState(state); case "SignalStrength": return new SignalStrenghtDeviceState(state); case "GatePosition": return new GatePositionDeviceState(state); case "GatewayPosition": return new GatewayPositionDeviceState(state); case "GateControllerHealth": return new GateControllerHealthDeviceState(state); case "IBlindCalibrationStatus": case "BlindCalibration": return new BlindCalibrationDeviceState(state); case "HumiditySensor": case "HumidityState": return new HumiditySensorDeviceState(state); case "VibrationSensor": return new VibrationSensorDeviceState(state); case "DigitalInputSensor": return new BinarySensorStateDeviceState(state); case "ConfigurationState": return new ConfigurationDeviceState(state); case "BlindOpenCloseTime": case "IBlindOpenCloseTime": return new BlindOpenCloseTimeDeviceState(state); case "IOvercurrentProtection": case "OvercurrentProtection": return new OvercurrentProtectionDeviceState(state); case "IOvercurrentProtectionThreshold": case "OvercurrentProtectionThreshold": return new OvercurrentProtectionThresholdDeviceState(state); case "FacadePosition": case "FacadeState": return new FacadePositionDeviceState(state); case "FacadeTypeState": return new FacadeTypeDeviceState(state); case "CurrentWindThreshold": return new CurrentWindThresholdDeviceState(state); case "CurrentLightThreshold": return new CurrentLightThresholdDeviceState(state); case "WindSpeed": return new WindSpeedDeviceState(state); case "FloodSensor": return new FloodSensorDeviceState(state); case "PressureState": return new PressureSensorDeviceState(state); case "ITamperProtection": case "TamperProtection": return new TamperProtectionDeviceState(state); case "ILightRGBW": case "LightRGBW": return new LightRGBWDeviceState(state); case "OnlineCamera": case "IOnlineCamera": return new OnlineCameraState(state); case "BlindError": case "IBlindError": state.state.ErrorData = ParseObjToMap(state.state.ErrorData); return new BlindErrorDeviceState(state); case "HallState": return new ChannelHallStateState(state); case "SceneExecuted": return new ChannelSceneExecutedState(state); case "Intercom": return new IntercomDeviceState(state); default: (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Debug(DevicesService.ServiceName, `Not supported device state ${state.DataType}`); break; } return null; } GetServiceName() { return DevicesService.ServiceName; } SyncDevicesStatesAsync() { return __awaiter(this, arguments, void 0, function* (forceSlow = false) { var _a, _b, _c; const result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new GetDevicesStatesRequest(), 15000, false)); if (yield this.IsFastStatesSyncEnabledAsync()) { if (forceSlow) { let syncStatesRequest = new SyncDevicesStatesRequest(); syncStatesRequest.Data = true; const result = yield ((_b = this._connection) === null || _b === void 0 ? void 0 : _b.SendAndWaitForResponseAsync(syncStatesRequest, 35000, false)); return (result === null || result === void 0 ? void 0 : result.Status) == Status.OK; } else { return (result === null || result === void 0 ? void 0 : result.Status) == Status.OK; } } else { let syncStatesRequest = new SyncDevicesStatesRequest(); syncStatesRequest.Data = true; const result = yield ((_c = this._connection) === null || _c === void 0 ? void 0 : _c.SendAndWaitForResponseAsync(syncStatesRequest, 35000, false)); return (result === null || result === void 0 ? void 0 : result.Status) == Status.OK; } }); } OnDevicesTasksExecutionChangeEvent() { return this._onDevicesTasksChangedEvent; } OnDeviceStateChangedEvent() { return this._onDeviceStateChangedEvent; } OnDeviceStateRefreshedOrChangedEvent() { return this._onDeviceStateRefreshedOrChangedEvent; } OnDeviceRegisteredEvent() { return this._onDeviceRegisteredEvent; } OnDeviceRemovedEvent() { return this._onDeviceRemovedEvent; } OnDeviceFoundEvent() { return this._onDeviceFoundEvent; } MapApiDevices(devicesObjects) { const devices = []; if (devicesObjects == null) return []; devicesObjects.forEach(element => { var _a, _b, _c, _d; var device = new Device(); device.Guid = element.Guid; device.Name = element.DeviceName; device.ChannelsAmount = element.ChannelsNumber; device.DeviceType = element.DeviceType; device.CommunicationWay = element.CommunicationWay; device.DeviceState = element.DeviceState; device.IsEnabled = element.IsEnabled; device.IsVirtual = element.IsVirtual; device.SerialNumber = element.DeviceSerialNumber; device.ManufacturerGuid = element.ManufacturerGuid; device.ModelGuid = element.DeviceModelGuid; device.Model = element.DeviceModel; device.Name = element.DeviceName; device.ProtocolGuid = element.ProtocolGuid; if (element.IconType !== undefined && element.IconType !== null) device.IconType = element.IconType; else device.IconType = IconType.Unknown; try { (_a = element.AvailableTasks) === null || _a === void 0 ? void 0 : _a.forEach(task => { var typeInfo = new DeviceTaskTypeInfo(); if (device.CommunicationWay == CommunicationWay.OneWay) { switch (task) { case "IBlindPosition": typeInfo.InterfaceType = "IBlindPositionSimple"; break; } } else switch (task) { case "IGatePosition": typeInfo.InterfaceType = "IGatePulse"; break; case "IGatewayPosition": typeInfo.InterfaceType = "IGatewayPulse"; break; default: typeInfo.InterfaceType = task; break; } device.AvailableTaskTypes.push(typeInfo); }); (_b = element.AvailableResponses) === null || _b === void 0 ? void 0 : _b.forEach(response => { var typeInfo = new DeviceResponseTypeInfo(); typeInfo.InterfaceType = response; device.AvailableResponseTypes.push(typeInfo); }); (_c = element.ChannelsConfiguration) === null || _c === void 0 ? void 0 : _c.forEach(configuration => { var _a, _b, _c; try { var ch = new DeviceChannel(); ch.Number = configuration.Channel; device.Channels.push(ch); ch.SetDevice(device); ch.Name = configuration.ChannelName; ch.ChannelGroups = configuration.GroupsGuids; ch.IconName = configuration.IconName; ch.IsHidden = configuration.Hidden; ch.Configurations = configuration.Configurations; ch.CustomDataAndRolesSupported = configuration.CustomData !== undefined && configuration.CustomData !== null; if (configuration.CustomData !== undefined && configuration.CustomData !== null) ch.CustomData = configuration.CustomData; if (configuration.Roles !== undefined && configuration.Roles !== null) ch.Roles = configuration.Roles; (_a = configuration.AvailableResponses) === null || _a === void 0 ? void 0 : _a.forEach(response => { var typeInfo = new DeviceResponseTypeInfo(); typeInfo.InterfaceType = response; ch.AvailableResponseTypes.push(typeInfo); }); (_b = configuration.AvailableTasks) === null || _b === void 0 ? void 0 : _b.forEach(task => { var typeInfo = new DeviceTaskTypeInfo(); if (device.AvailableTaskTypes.any(a => a.InterfaceType == "IBlindPositionSimple")) { if (task == "IBlindPosition") typeInfo.InterfaceType = "IBlindPositionSimple"; } else { typeInfo.InterfaceType = task; } ch.AvailableTaskTypes.push(typeInfo); }); } catch (ex) { (_c = DependencyContainer.Log) === null || _c === void 0 ? void 0 : _c.Error(ex); } }); } catch (ex) { (_d = DependencyContainer.Log) === null || _d === void 0 ? void 0 : _d.Error(ex); } devices.push(device); }); return devices; } GetPairedDevicesAsync() { return __awaiter(this, arguments, void 0, function* (withScenes = false) { var _a, _b, _c; if (this._synchronized && !(yield ((_a = this._controllerConfiguration) === null || _a === void 0 ? void 0 : _a.DidCofigurationChangeAsync()))) { if (withScenes) return Promise.resolve(this._devices); else return Promise.resolve(this._devices.filter(d => d.DeviceType != DeviceType.Scene)); } const result = yield ((_b = this._connection) === null || _b === void 0 ? void 0 : _b.SendAndWaitForResponseAsync(new GetDevicesListRequest(), 15000, true)); if (result == null || result === undefined) return []; if (result.Status == Status.OK && result.Data != null) { this._devices = this.MapApiDevices(result.Data); if (withScenes) return this._devices; else return this._devices.filter(d => d.DeviceType != DeviceType.Scene); } else { (_c = DependencyContainer.Log) === null || _c === void 0 ? void 0 : _c.Error(DevicesService.ServiceName, `Failed to get devices. ${result.Status} ${result.Data}`); return []; } }); } GetDevicesAsync() { return __awaiter(this, arguments, void 0, function* (withScenes = false) { yield this.WaitForSynchronizationAsync(); return this.GetPairedDevicesAsync(withScenes); }); } GetFoundDevicesAsync() { return __awaiter(this, void 0, void 0, function* () { var _a, _b; const result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new GetFoundDevicesRequest(), 15000, false)); if (result == null) return []; if (result.Status == Status.OK && result.Data != null) return this.MapApiDevices(result.Data).where(a => a.DeviceType !== DeviceType.Scene).toArray(); else { (_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Error(DevicesService.ServiceName, `Failed to get found devices. ${result.Status} ${result.Data}`); return []; } }); } GetDevice(guid) { return this._devices.find(a => a.Guid === guid); } FindDevicesAsync() { return __awaiter(this, void 0, void 0, function* () { var _a; Api.Get(WebApiCacheService.ServiceName).ClearCache(); yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new SearchForDevicesRequest(), 35000, false)); }); } StopSearchingForDevices() { return __awaiter(this, void 0, void 0, function* () { var _a; yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new StopSearchingForDevicesRequest(), 20000, false)); }); } RegisterDeviceAsync(device) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; try { const req = new DevicePairRequest(); req.Data = device.Guid; const res = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(req, 20000, false)); (_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Error(DevicesService.ServiceName, `EXIT CONFIGURATION MODE WILL BE FIRED! RegisterDeviceAsync()`); Api.Get(ControllerConfigurationService.ServiceName).ExitConfigurationModeAsync(); if ((res === null || res === void 0 ? void 0 : res.Status) == Status.OK) { if (!(this._devices.any(d => d.Guid == device.Guid))) this._devices.push(device); this._onDeviceRegisteredEvent.Invoke(device); return DeviceTaskExecutionResult.Executed; } else return DeviceTaskExecutionResult.Failed; } catch (ex) { (_c = DependencyContainer.Log) === null || _c === void 0 ? void 0 : _c.Error(DevicesService.ServiceName, `Failed to paired devices: ${ex}`); return DeviceTaskExecutionResult.ControllerResponseTimeout; } }); } RemoveDeviceAsync(device_1) { return __awaiter(this, arguments, void 0, function* (device, force = false) { var _a, _b; var req = new DeviceUnpairRequest(); if (force) req = new ForceDeviceUnpairRequest(); req.Data = device.Guid; const res = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(req, 35000, false)); (_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Error(DevicesService.ServiceName, `EXIT CONFIGURATION MODE WILL BE FIRED! RemoveDeviceAsync()`); Api.Get(ControllerConfigurationService.ServiceName).ExitConfigurationModeAsync(); if ((res === null || res === void 0 ? void 0 : res.Status) == Status.OK) { this._devices = this._devices.where(a => a.Guid != device.Guid).toArray(); this._onDeviceRemovedEvent.Invoke(device); return DeviceTaskExecutionResult.Executed; } else return DeviceTaskExecutionResult.Failed; }); } MapDeviceTaskToDeviceTaskInfo(device, task) { let t = new DeviceTaskInfo(); const tsk = task; switch (tsk.FeatureType) { case DeviceControlFeature.SetTemperature: t.Data = tsk.Temperature; break; case DeviceControlFeature.SetLightBrightness: t.Data = tsk.Brightness; break; case DeviceControlFeature.SetLightColor: t = new LightColorTaskInfo(); const ts = tsk; t.R = ts.R; t.G = ts.G; t.B = ts.B; break; case DeviceControlFeature.SetLightTemperature: t.Data = tsk.Temperature; break; case DeviceControlFeature.SetGatePositionPrecise: switch (tsk.GateControlAction) { case GateActionEnum.Open: t.Data = 101; break; case GateActionEnum.Close: t.Data = 102; break; case GateActionEnum.Stop: t.Data = 103; break; case GateActionEnum.Percentage: t.Data = tsk.Position; break; } break; case DeviceControlFeature.SetBlindPosition: switch (tsk.Action) { case BlindActionEnum.Open: t.Data = 101; break; case BlindActionEnum.Close: t.Data = 102; break; case BlindActionEnum.Stop: t.Data = 103; break; case BlindActionEnum.Percentage: t.Data = tsk.Position; break; } break; case DeviceControlFeature.SetLightBrightnessDynamicly: t.Data = tsk.Brightness; break; case DeviceControlFeature.SetBlindOpenCloseTime: t.Data = tsk.Data; break; case DeviceControlFeature.SetBlindMicroventilation: t.Data = tsk.Position; break; case DeviceControlFeature.SetFacadePositionAndTilt: t = new FacadePositionTaskInfo(); const fp = tsk; t.FacadeAction = fp.FacadeAction; t.Tilt = fp.Tilt; t.Position = fp.Position; break; case DeviceControlFeature.LightRGBW: t.Data = tsk.Data; break; case DeviceControlFeature.GatePulse: case DeviceControlFeature.GatewayPulse: t.Data = 0; break; case DeviceControlFeature.TurnOnWithTimeout: t.Data = tsk.SwitchOffDelaySeconds; break; } t.Channel = tsk.Channel; t.DeviceGuid = device.Guid; t.ControlFeature = tsk.FeatureType; return t; } ExecuteDeviceTaskAsync(device, task) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g, _h; try { (_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Debug(DevicesService.ServiceName, `Preparing device task execution, device: ${device.Guid} task: ${task.TaskType} channel: ${task.Channel}`); let t = this.MapDeviceTaskToDeviceTaskInfo(device, task); try { const req = new ExecuteDeviceTaskRequest(t); (_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Debug(DevicesService.ServiceName, `Sending device task for execution, device: ${t.DeviceGuid} task: ${t.ControlFeature} channel: ${t.Channel} request: ${JSON.stringify(req)}`); const result = yield ((_c = this._connection) === null || _c === void 0 ? void 0 : _c.SendAndWaitForResponseAsync(req, 15000, false)); switch (result === null || result === void 0 ? void 0 : result.Status) {