UNPKG

lavva.exalushome

Version:

Library implementing communication and abstraction layers for ExalusHome system

450 lines 21.1 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 { Event } from "../../Event"; import { ControllerConfigurationErrorCode } from "./IControllerConfigurationService"; import { TypedEvent } from '../../TypedEvent'; import { Api } from "../../Api"; import { ExalusConnectionService } from '../ExalusConnectionService'; import { SessionService } from '../Session/SessionService'; import { DataFrame, Method, Status } from '../../DataFrame'; import { LocalStorageService } from "../LocalStorageService"; import { WebApiCacheService } from "../WebApi/WebApiCacheService"; import { Task } from '../../Helpers'; import { ControllerExtensionsService } from './ControllerExtensionsService'; import { AccessLevel } from "../Users/IUser"; import { ResponseResult } from "../FieldChangeResult"; import { DependencyContainer } from "../../DependencyContainer"; export class ControllerConfigurationService { GetServiceName() { return ControllerConfigurationService.ServiceName; } constructor() { this._connection = null; this._session = null; this._localStorage = null; this._onEnteredConfigurationEvent = new Event(); this._onExitedConfigurationEvent = new Event(); this._onConfigurationTimeCheckedEvent = new TypedEvent(); this._configurationTime = new Date(); this._appEnteredConfigurationMode = false; this._didConfigurationChange = false; this._synchronizationTaskCompletionSource = new Promise((resolve) => { Api.Get(SessionService.ServiceName).OnUserLoggedInEvent().Subscribe((user) => __awaiter(this, void 0, void 0, function* () { if (ControllerConfigurationService.ConfigurationTimeRetrieved !== null) this._didConfigurationChange = yield this.CheckIfConfigurationTimeHasChangedAsync(ControllerConfigurationService.ConfigurationTimeRetrieved); else this._didConfigurationChange = yield this.CheckIfConfigurationHasChangedAsync(); if (this._didConfigurationChange) Api.Get(WebApiCacheService.ServiceName).ClearCache(); resolve(); })); }); this._connection = Api.Get(ExalusConnectionService.ServiceName); this._session = Api.Get(SessionService.ServiceName); this._localStorage = Api.Get(LocalStorageService.ServiceName); let removeSubCallback = this._connection.SubscribeTo("/info/configuration/mode/entry", (frame) => { Api.Get(WebApiCacheService.ServiceName).ClearCache(); if (!this._appEnteredConfigurationMode) this._onEnteredConfigurationEvent.Invoke(); }); let removeSubCallback2 = this._connection.SubscribeTo("/info/configuration/mode/exit", (frame) => { Api.Get(WebApiCacheService.ServiceName).ClearCache(); if (!this._appEnteredConfigurationMode) this._onExitedConfigurationEvent.Invoke(); }); } ImportControllerConfigurationAsync(file) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; let conf = yield file.text(); let chunks = this.SplitStringBySize(conf); let req = new ImportControllerConfigurationRequest(""); req.Status = Status.MultiDataResponseStart; let result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(req, 6000, false)); if (result === undefined || (result === null || result === void 0 ? void 0 : result.Status) != Status.OK) return Status.Error; for (const chunk of chunks) { let req = new ImportControllerConfigurationRequest(chunk); req.Status = Status.MultiDataResponse; let result = yield ((_b = this._connection) === null || _b === void 0 ? void 0 : _b.SendAndWaitForResponseAsync(req, 6000, false)); if (result === undefined || (result === null || result === void 0 ? void 0 : result.Status) != Status.OK) return Status.Error; } req.Status = Status.MultiDataResponseStop; let result2 = yield ((_c = this._connection) === null || _c === void 0 ? void 0 : _c.SendAndWaitForResponseAsync(req, 120000, false)); if (result2 === undefined || (result2 === null || result2 === void 0 ? void 0 : result2.Status) != Status.OK) return Status.Error; return Status.OK; }); } SplitStringBySize(input, maxSizeInBytes = 100000) { // Calculate the approximate maximum number of characters const maxChars = Math.floor(maxSizeInBytes / 2); const result = []; let startIndex = 0; while (startIndex < input.length) { // Get the chunk of the string let chunk = input.slice(startIndex, startIndex + maxChars); // Check the actual byte size of the chunk and adjust if necessary while (new Blob([chunk]).size > maxSizeInBytes) { // Reduce the size of the chunk until it fits within the byte limit chunk = chunk.slice(0, -1); } // Add the chunk to the result array result.push(chunk); // Move to the next chunk startIndex += chunk.length; } return result; } GetControllerSystemTimeAsync() { return __awaiter(this, void 0, void 0, function* () { var _a, _b; try { var result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new GetControllerTimeRequest(), 8000, false)); if (result == null || result.Status == null) return Status.Error; if (result.Status != Status.OK) return result.Status; if (result.Data == null) return Status.ResourceIsNotAvailable; return new Date(result.Data); } catch (error) { (_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Error(ControllerConfigurationService.ServiceName, `Cannot get current controller time! ${error}`); return Status.FatalError; } }); } SetControllerSystemTimeAsync(date) { return __awaiter(this, void 0, void 0, function* () { var _a, _b; try { var result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new SetControllerTimeRequest(date.toISOString()), 8000, false)); if (result == null || result.Status == null) return Status.Error; return result.Status; } catch (error) { (_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Error(ControllerConfigurationService.ServiceName, `Cannot set current controller time! ${error}`); return Status.FatalError; } }); } StartNtpTimeSynchronizationAsync() { return __awaiter(this, void 0, void 0, function* () { var _a, _b; try { var result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new SetNtpControllerTimeRequest(), 8000, false)); if (result == null || result.Status == null) return Status.Error; return result.Status; } catch (error) { (_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Error(ControllerConfigurationService.ServiceName, `Cannot set current controller time! ${error}`); return Status.FatalError; } }); } FactoryResetAsync(func) { return __awaiter(this, void 0, void 0, function* () { var _a, _b; try { Api.Get(WebApiCacheService.ServiceName).ClearCache(); var result = (_b = (yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new DoFactoryResetRequest(), 2000, false)))) === null || _b === void 0 ? void 0 : _b.Status; if (result == Status.OK) { let Seconds = 300; //in seconds let currentProgress = 0; let progressPerStep = 100 / Seconds; let id = setInterval(() => { currentProgress += progressPerStep; func(parseFloat(currentProgress.toPrecision(1))); }, 1000); yield Task.Delay(Seconds * 1000); Api.Get(WebApiCacheService.ServiceName).ClearCache(); clearInterval(id); return Status.OK; } else return result; } catch (e) { return Status.FatalError; } }); } RollbackLastUpdateAsync(func) { return __awaiter(this, void 0, void 0, function* () { var _a, _b; try { Api.Get(WebApiCacheService.ServiceName).ClearCache(); var result = (_b = (yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new RestorePreviousVersionRequest(), 2000, false)))) === null || _b === void 0 ? void 0 : _b.Status; if (result == Status.OK) { let Seconds = 420; //in seconds let currentProgress = 0; let progressPerStep = 100 / Seconds; let id = setInterval(() => { currentProgress += progressPerStep; func(parseFloat(currentProgress.toPrecision(1))); }, 1000); yield Task.Delay(Seconds * 1000); Api.Get(WebApiCacheService.ServiceName).ClearCache(); clearInterval(id); return Status.OK; } else return result; } catch (e) { return Status.FatalError; } }); } RestartControllerAsync(func) { return __awaiter(this, void 0, void 0, function* () { var _a, _b; try { Api.Get(WebApiCacheService.ServiceName).ClearCache(); var result = (_b = (yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new RestartControllerRequest(), 2000, false)))) === null || _b === void 0 ? void 0 : _b.Status; if (result == Status.OK) { let Seconds = 240; //in seconds let currentProgress = 0; let progressPerStep = 100 / Seconds; let id = setInterval(() => { currentProgress += progressPerStep; func(parseFloat(currentProgress.toPrecision(1))); }, 1000); yield Task.Delay(Seconds * 1000); Api.Get(WebApiCacheService.ServiceName).ClearCache(); clearInterval(id); return Status.OK; } else return result; } catch (e) { return Status.FatalError; } }); } DidCofigurationChangeAsync() { return __awaiter(this, void 0, void 0, function* () { let result = yield this._synchronizationTaskCompletionSource; return Promise.resolve(this._didConfigurationChange); }); } GetLastKnownConfigurationChangeTime() { var _a; const result = (_a = this._localStorage) === null || _a === void 0 ? void 0 : _a.Read(this.GetServiceName(), "last_configuration_time"); if (result != null) return new Date(result); else return new Date(); } SaveLastConfigurationChangeTime(time) { var _a; (_a = this._localStorage) === null || _a === void 0 ? void 0 : _a.Save(this.GetServiceName(), "last_configuration_time", time.toString()); } EnterConfigurationModeAsync() { return __awaiter(this, void 0, void 0, function* () { var _a; this._appEnteredConfigurationMode = true; Api.Get(WebApiCacheService.ServiceName).ClearCache(); yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new EntryConfigurationModeRequest(), 20000, false)); }); } ExitConfigurationModeAsync() { return __awaiter(this, void 0, void 0, function* () { var _a; this._appEnteredConfigurationMode = true; Api.Get(WebApiCacheService.ServiceName).ClearCache(); yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new ExitConfigurationModeRequest(), 20000, false)); Api.Get(WebApiCacheService.ServiceName).ClearCache(); this._appEnteredConfigurationMode = false; }); } OnEnteredConfigurationEvent() { return this._onEnteredConfigurationEvent; } OnExitedConfigurationEvent() { return this._onExitedConfigurationEvent; } OnConfigurationTimeCheckedEvent() { return this._onConfigurationTimeCheckedEvent; } GetLastConfigurationChangeTimeAsync() { 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 LastChangeTimeRequest(), 20000, false)); if (result == null || (result === null || result === void 0 ? void 0 : result.Status) != Status.OK) throw new Error("Failed to get last configuration change time"); this._configurationTime = new Date(result.Data); return this._configurationTime; }); } CheckIfConfigurationHasChangedAsync() { return __awaiter(this, void 0, void 0, function* () { const result = yield this.GetLastConfigurationChangeTimeAsync(); if (this.GetLastKnownConfigurationChangeTime().toString() != result.toString()) { this.SaveLastConfigurationChangeTime(result); this._onConfigurationTimeCheckedEvent.Invoke(result); Api.Get(WebApiCacheService.ServiceName).ClearCache(); return true; } else return false; }); } CheckIfConfigurationTimeHasChangedAsync(currentConfigurationTime) { return __awaiter(this, void 0, void 0, function* () { if (this.GetLastKnownConfigurationChangeTime().toString() != currentConfigurationTime.toString()) { this.SaveLastConfigurationChangeTime(currentConfigurationTime); this._onConfigurationTimeCheckedEvent.Invoke(currentConfigurationTime); Api.Get(WebApiCacheService.ServiceName).ClearCache(); return true; } else return false; }); } CanExportOrImportControllerConfigurationAsync() { return __awaiter(this, void 0, void 0, function* () { try { let ext = yield Api.Get(ControllerExtensionsService.ServiceName).GetExtensionsInfoAsync(); let user = Api.Get(SessionService.ServiceName).User; if (user == null || user.AccessLevel == null) return false; return user.AccessLevel >= AccessLevel.Admin && ext.any(e => e.ExtensionGuid == "f4f0f066-7c43-46c6-a0bd-aedf93903dc0"); } catch (e) { return false; } }); } ExportControllerConfigurationAsync() { return __awaiter(this, void 0, void 0, function* () { var _a; let data = []; let err = null; yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndHandleResponseAsync(new ExportControllerConfigurationRequest(), 30000, (result) => { switch (result.Status) { case Status.MultiDataResponseStart: break; case Status.MultiDataResponse: if (result.Data != null && result.Data !== undefined) data.push(result.Data); break; case Status.MultiDataResponseStop: break; case Status.Error: case Status.FatalError: err = new ResponseResult(ControllerConfigurationErrorCode.CannotExportConfiguration, "Cannot export configuration! Controller returned error!"); } }, true)); let prettyPrint = JSON.stringify(JSON.parse(data.join('')), null, 2); console.log(prettyPrint); if (err != null) return err; return Api.ExportStringAsFileToDownload(this.GetCurrentTimestampedFilename(), prettyPrint); }); } GetCurrentTimestampedFilename() { var _a, _b; const now = new Date(); const hours = now.getHours().toString().padStart(2, '0'); const minutes = now.getMinutes().toString().padStart(2, '0'); const day = now.getDate().toString().padStart(2, '0'); const month = (now.getMonth() + 1).toString().padStart(2, '0'); // Month is zero-based const year = now.getFullYear().toString(); return `${(_b = (_a = this._connection) === null || _a === void 0 ? void 0 : _a.GetAuthorizationInfo()) === null || _b === void 0 ? void 0 : _b.SerialNumber}_${hours}-${minutes}-${day}-${month}-${year}-config.cexp`; } } ControllerConfigurationService.ServiceName = "ControllerConfigurationService"; ControllerConfigurationService.ConfigurationTimeRetrieved = null; class ImportControllerConfigurationRequest extends DataFrame { constructor(data) { super(); this.Resource = "/configuration/backup/import"; this.Method = Method.Put; this.Data = data; } } class ExportControllerConfigurationRequest extends DataFrame { constructor() { super(); this.Resource = "/configuration/backup/export"; this.Method = Method.Get; } } class RestartControllerRequest extends DataFrame { constructor() { super(); this.Resource = "/controller/restart"; this.Method = Method.Post; } } class DoFactoryResetRequest extends DataFrame { constructor() { super(); this.Resource = "/controller/factory_reset"; this.Method = Method.Post; } } class RestorePreviousVersionRequest extends DataFrame { constructor() { super(); this.Resource = "/controller/backups/restore/previous"; this.Method = Method.Post; } } class EntryConfigurationModeRequest extends DataFrame { constructor() { super(); this.Resource = "/system/configuration/mode/entry"; this.Method = Method.Put; } } class ExitConfigurationModeRequest extends DataFrame { constructor() { super(); this.Resource = "/system/configuration/mode/exit"; this.Method = Method.Put; } } class LastChangeTimeRequest extends DataFrame { constructor() { super(); this.Resource = "/system/configuration/change/time"; this.Method = Method.Get; } } class GetControllerTimeRequest extends DataFrame { constructor() { super(); this.Resource = "/system/time"; this.Method = Method.Get; } } class SetControllerTimeRequest extends DataFrame { constructor(date) { super(); this.Resource = "/system/time"; this.Method = Method.Put; this.Data = date; } } class SetNtpControllerTimeRequest extends DataFrame { constructor() { super(); this.Resource = "/system/time/ntp/update"; this.Method = Method.Put; } } //# sourceMappingURL=ControllerConfigurationService.js.map