lavva.exalushome
Version:
Library implementing communication and abstraction layers for ExalusHome system
1,025 lines • 55.4 kB
JavaScript
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 { Api } from "../../Api";
import { DataFrame, Method, Status } from "../../DataFrame";
import { DependencyContainer } from "../../DependencyContainer";
import { Guid } from "../../Guid";
import { Helpers } from "../../Helpers";
import { ControllerConfigurationService } from "../Controller/ControllerConfigurationService";
import { GeolocationService } from "../Controller/GeolocationService";
import { Coordinates, CoordinatesWithSourceInfo } from "../Controller/IGeolocationService";
import { DevicesService } from "../Devices/DevicesService";
import { DeviceResponseType, DeviceTaskType } from "../Devices/IDevice";
import { DeviceState, EnergyMeasurementParameter, StateReliability } from "../Devices/IDeviceState";
import { DeviceControlFeature } from "../Devices/IDeviceTask";
import { DeviceTaskExecutionResult } from "../Devices/TaskExecutionResult";
import { DeviceTask } from "../Devices/Tasks/DeviceTask";
import { ChangeGatePositionPulse, ChangeGatewayPositionPulse, FacadeActionEnum, GetDeviceState, GetFacadeType, IdentifyDevice, LightRGBW, SetBlindMicroventilation, SetBlindOpenCloseTime, SetBlindPosition, SetBlindPositionSimple, SetFacadePosition, SetGatePositionPrecise, SetLightBrightness, SetLightBrightnessDynamicly, SetLightColor, SetLightTemperature, SetTemperature, ToggleState, TurnOff, TurnOn, TurnOnWithTime } from "../Devices/Tasks/Tasks";
import { ExalusConnectionService } from "../ExalusConnectionService";
import { ResponseResult } from "../FieldChangeResult";
import { UpdatesProvider } from "../Updates/UpdatesProvider";
import { ScenesServiceErrorCode } from "./IScenesService";
import { DeviceStateArgument, DeviceStateComparisonMethod, DeviceStateComparisonParams, NumberParam, TimeSpanParam } from "./LeftArgumentTypes";
import { ArgumentType, ConditionsTypes, HandledType, UnsupportedScenesDeviceState, DeviceStateType, SceneTaskTypeNum, SceneTaskType, SupportedTaskTypes } from "./Scenes";
import { SequenceBuilder, SequenceRequestData } from "./ScenesBuilder";
/**
* @type Class
*/
export class ScenesService {
constructor() {
this._connection = Api.Get(ExalusConnectionService.ServiceName);
this._configurationService = Api.Get(ControllerConfigurationService.ServiceName);
}
GetServiceName() {
return ScenesService.ServiceName;
}
GetSequencesListAsync() {
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 GetSequencesListRequest(), 12000, false));
(_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Debug(`GetSequencesListAsync result:\n ${JSON.stringify(result)}}`);
if (result == null)
return new ResponseResult(ScenesServiceErrorCode.OtherError, `Cannot get sequences list - response is null.`);
if (result.Status != Status.OK)
return new ResponseResult(ScenesServiceErrorCode.OtherError, `Cannot get sequences list - controller responded with response code ${result.Status}.`);
if (result.Data == null)
return new ResponseResult(ScenesServiceErrorCode.NoData, `Cannot get sequences list - controller responded with status OK, but response does not contain data!`);
return result.Data;
});
}
GetSequenceAsync(sequence) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
let sequenceGuid = "";
if (typeof sequence == 'string') {
sequenceGuid = sequence;
}
else {
sequenceGuid = sequence.Guid;
}
const result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new GetSequenceDetailsRequest(sequenceGuid), 12000, false));
if (result == null)
return new ResponseResult(ScenesServiceErrorCode.OtherError, `Cannot get sequence - response is null.`);
if (result.Status != Status.OK)
return new ResponseResult(ScenesServiceErrorCode.OtherError, `Cannot get sequence - controller responded with response code ${result.Status}.`);
if (result.Data == null)
return new ResponseResult(ScenesServiceErrorCode.NoData, `Cannot get sequence - controller responded with status OK, but response does not contain data!`);
const raw = result.Data;
return this.MapSequence(raw);
});
}
GetSequenceBuilder(newSequenceName, newSequenceIcon) {
return new SequenceBuilder(newSequenceName, newSequenceIcon);
}
CreateSequenceAsync(sequence) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d;
try {
yield this._configurationService.EnterConfigurationModeAsync();
(_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Debug(`Creating sequence ${sequence.Name} json: \n${JSON.stringify(sequence)}`);
const result = yield ((_b = this._connection) === null || _b === void 0 ? void 0 : _b.SendAndWaitForResponseAsync(new CreateSequenceRequest(sequence), 20000, false));
if (result == null || result.Status == null)
return Status.Error;
return result.Status;
}
catch (error) {
(_c = DependencyContainer.Log) === null || _c === void 0 ? void 0 : _c.Error(`Creating sequence ${sequence.Name} error: ${error}`);
return Status.FatalError;
}
finally {
(_d = DependencyContainer.Log) === null || _d === void 0 ? void 0 : _d.Error(ScenesService.ServiceName, `EXIT CONFIGURATION MODE WILL BE FIRED! CreateSequenceAsync()`);
yield this._configurationService.ExitConfigurationModeAsync();
}
});
}
CheckIfSequenceIsUsedInAnotherSequenceAsync(sequence) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
try {
let sequenceGuid = "";
if (typeof sequence == 'string') {
sequenceGuid = sequence;
}
else {
sequenceGuid = sequence.Guid;
}
const result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new GetSequenceUsedInRequest(sequenceGuid), 12000, false));
if (result == null)
return new ResponseResult(ScenesServiceErrorCode.OtherError, `Cannot get sequence - response is null.`);
switch (result.Status) {
case Status.WrongData:
return new ResponseResult(ScenesServiceErrorCode.InvalidSceneGuid, `Cannot check if sequence is used in another sequence! Sequence not found, invalid sequence guid!`);
case Status.OK:
if (result.Data == null)
return new ResponseResult(ScenesServiceErrorCode.NoData, `Cannot get sequence - controller responded with status OK, but response does not contain data!`);
else
return result.Data;
default:
return new ResponseResult(ScenesServiceErrorCode.OtherError, `Cannot check if sequence is used in another sequence! Controller responded with code: ${result.Status}`);
}
}
catch (error) {
return new ResponseResult(ScenesServiceErrorCode.FatalError, `Cannot check if sequence is used in another sequence! Fatal error! ${error}`);
}
});
}
DeleteSequenceAsync(sequence) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
try {
let sequenceGuid = "";
if (typeof sequence == 'string') {
sequenceGuid = sequence;
}
else {
sequenceGuid = sequence.Guid;
}
yield this._configurationService.EnterConfigurationModeAsync();
const result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new DeleteSequenceRequest(sequenceGuid), 12000, false));
if (result == null || result.Status == null)
return Status.Error;
return result.Status;
}
catch (error) {
return Status.FatalError;
}
finally {
(_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Error(ScenesService.ServiceName, `EXIT CONFIGURATION MODE WILL BE FIRED! DeleteSequenceAsync()`);
yield this._configurationService.ExitConfigurationModeAsync();
}
});
}
EditSequenceAsync(sequence) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c;
try {
const request = {
Guid: sequence.Guid,
Icon: sequence.Icon,
Name: sequence.Name,
Condition: sequence
};
yield this._configurationService.EnterConfigurationModeAsync();
const result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new EditSequenceRequest(request), 20000, 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(`Editing sequence ${sequence.Name} error: ${error}`);
return Status.FatalError;
}
finally {
(_c = DependencyContainer.Log) === null || _c === void 0 ? void 0 : _c.Error(ScenesService.ServiceName, `EXIT CONFIGURATION MODE WILL BE FIRED! EditSequenceAsync()`);
yield this._configurationService.ExitConfigurationModeAsync();
}
});
}
EnableSequenceAsync(sequence) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
let sequenceGuid = "";
if (typeof sequence == 'string') {
sequenceGuid = sequence;
}
else {
sequenceGuid = sequence.Guid;
}
const result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new EnableSequenceRequest(sequenceGuid), 12000, false));
if (result == null || result.Status == null)
return Status.Error;
return result.Status;
});
}
DisableSequenceAsync(sequence) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
let sequenceGuid = "";
if (typeof sequence == 'string') {
sequenceGuid = sequence;
}
else {
sequenceGuid = sequence.Guid;
}
const result = yield ((_a = this._connection) === null || _a === void 0 ? void 0 : _a.SendAndWaitForResponseAsync(new DisableSequenceRequest(sequenceGuid), 12000, false));
if (result == null || result.Status == null)
return Status.Error;
return result.Status;
});
}
RunSequenceAsync(sequence) {
return __awaiter(this, void 0, void 0, function* () {
let sequenceDeviceGuid = "";
if (typeof sequence == 'string') {
const res = yield this.GetSequencesListAsync();
if (res.Type != null)
return Status.Error;
else {
const seq = res.find(s => s.Guid == sequence);
if (!seq)
return Status.Error;
sequenceDeviceGuid = seq.DeviceGuid;
}
}
else {
sequenceDeviceGuid = sequence.DeviceGuid;
}
const tsk = new TurnOn();
tsk.Channel = 1;
tsk.DeviceGuid = sequenceDeviceGuid;
const result = yield Api.Get(DevicesService.ServiceName).ExecuteDeviceTaskAsync({ Guid: sequenceDeviceGuid }, tsk);
switch (result) {
case DeviceTaskExecutionResult.Executed:
return Status.OK;
case DeviceTaskExecutionResult.DeviceNotFound:
return Status.WrongData;
default:
return Status.Error;
}
});
}
GetUtilsAsync() {
return __awaiter(this, void 0, void 0, function* () {
const astronomicalClockSunCalc = yield this.SunCalculatorAsync();
return {
GetSunRiseTime: astronomicalClockSunCalc.GetSunRiseTime,
GetSunSetTime: astronomicalClockSunCalc.GetSunSetTime,
ParseLinearScaleToLux: this._parseLinearScaleToLux,
ParseLuxToLinearScale: this._parseLuxToLinearScale,
};
});
}
_parseLinearScaleToLux(linearScaleVal) {
if (linearScaleVal < 0.0 || linearScaleVal > 1.0)
return undefined;
return Math.round(Math.pow(10, (linearScaleVal * 5)));
}
_parseLuxToLinearScale(lux) {
if (lux <= 0)
return 0;
const res = (Math.log10(lux) / 5.0);
return res > 1.0 ? 1 : res;
}
SunCalculatorAsync() {
return __awaiter(this, void 0, void 0, function* () {
var _a;
const srv = Api.Get(GeolocationService.ServiceName);
const cords = new Coordinates();
let recalculationDone = false;
cords.Latitude = 49.9958888026741;
cords.Longitude = 18.9172596008914;
try {
if (yield srv.IsControllerGeolocationSetAsync()) {
const controlerCords = yield srv.GetControlllerGeolocationAsync();
if (controlerCords instanceof CoordinatesWithSourceInfo) {
cords.Latitude = controlerCords.Latitude;
cords.Longitude = controlerCords.Longitude;
}
}
}
catch (error) {
(_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Warning(`Cannot get localization data, using default values: 49.9958888026741, 18.9172596008914. Error: ${error}`);
}
const hasDST = (date = new Date()) => {
const january = new Date(date.getFullYear(), 0, 1).getTimezoneOffset();
const july = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
return Math.max(january, july) !== date.getTimezoneOffset();
};
const calculateDifferenceSunAndLocalTime = (dayNumberOfDateTime) => {
const ellipticalOrbitPart1 = 7.95204 * Math.sin((0.01768 * dayNumberOfDateTime) + 3.03217);
const ellipticalOrbitPart2 = 9.98906 * Math.sin((0.03383 * dayNumberOfDateTime) + 3.46870);
let differenceSunAndLocalTime = ellipticalOrbitPart1 + ellipticalOrbitPart2 + (cords.Longitude - Math.round(cords.Longitude / 15) * 15) * 4;
if (hasDST())
differenceSunAndLocalTime -= 60;
return differenceSunAndLocalTime;
};
const calculateDeclination = (numberOfDaysSinceFirstOfJanuary) => {
return Math.asin(-0.39795 * Math.cos(2.0 * Math.PI * (numberOfDaysSinceFirstOfJanuary + 10.0) / 365.0));
};
const calculateTanSunPosition = (declanationOfTheSun) => {
const limitTanSunPosition = (tanSunPosition) => {
if (tanSunPosition < -1)
tanSunPosition = -1.0;
if (tanSunPosition > 1)
tanSunPosition = 1.0;
return tanSunPosition;
};
const latitudeRadians = cords.Latitude * Math.PI / 180;
const sinSunPosition = Math.sin(latitudeRadians) * Math.sin(declanationOfTheSun);
const cosSunPosition = Math.cos(latitudeRadians) * Math.cos(declanationOfTheSun);
let tanSunPosition = sinSunPosition / cosSunPosition;
tanSunPosition = limitTanSunPosition(tanSunPosition);
return tanSunPosition;
};
const calculateSunRiseInternal = (tanSunPosition, differenceSunAndLocalTime) => {
let sunRise = (720.0 - 720.0 / Math.PI * Math.acos(-tanSunPosition) - differenceSunAndLocalTime);
if (sunRise < 0)
sunRise += 1440;
return sunRise;
};
const calculateSunSetInternal = (tanSunPosition, differenceSunAndLocalTime) => {
let sunSet = (720.0 + 720.0 / Math.PI * Math.acos(-tanSunPosition) - differenceSunAndLocalTime);
if (sunSet > 1439)
sunSet -= 1439;
return sunSet;
};
const createDateTime = (timeInMinutes) => {
const hour = Math.ceil(timeInMinutes / 60);
const minute = timeInMinutes - (hour * 60);
const now = new Date();
return new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minute);
};
const calclateSunRise = (offset) => {
const dat = new Date();
dat.setDate(dat.getDate() + offset);
const calculateDayOfYear = (date) => Math.floor((date.valueOf() - new Date(date.getFullYear(), 0, 0).valueOf()) / 1000 / 60 / 60 / 24);
const dayNumberOfDateTime = calculateDayOfYear(dat);
const differenceSunAndLocalTime = calculateDifferenceSunAndLocalTime(dayNumberOfDateTime);
const declanationOfTheSun = calculateDeclination(dayNumberOfDateTime);
const tanSunPosition = calculateTanSunPosition(declanationOfTheSun);
const sunRiseInMinutes = calculateSunRiseInternal(tanSunPosition, differenceSunAndLocalTime);
const result = createDateTime(sunRiseInMinutes);
if (new Date() > result && !recalculationDone) {
recalculationDone = true;
return calclateSunRise(1);
}
else {
recalculationDone = false;
return new Date(dat.getFullYear(), dat.getMonth(), dat.getDate(), result.getHours(), result.getMinutes());
}
};
const calculateSunSet = (offset) => {
const dat = new Date();
dat.setDate(dat.getDate() + offset);
const calculateDayOfYear = (date) => Math.floor((date.valueOf() - new Date(date.getFullYear(), 0, 0).valueOf()) / 1000 / 60 / 60 / 24);
const dayNumberOfDateTime = calculateDayOfYear(dat);
const differenceSunAndLocalTime = calculateDifferenceSunAndLocalTime(dayNumberOfDateTime);
const declanationOfTheSun = calculateDeclination(dayNumberOfDateTime);
const tanSunPosition = calculateTanSunPosition(declanationOfTheSun);
const sunRiseInMinutes = Math.floor(calculateSunSetInternal(tanSunPosition, differenceSunAndLocalTime));
const result = createDateTime(sunRiseInMinutes);
if (new Date() > result && !recalculationDone) {
recalculationDone = true;
return calculateSunSet(1);
}
else {
recalculationDone = false;
return new Date(dat.getFullYear(), dat.getMonth(), dat.getDate(), result.getHours(), result.getMinutes());
}
};
return {
GetSunRiseTime: () => calclateSunRise(0),
GetSunSetTime: () => calculateSunSet(0)
};
});
}
MapSequence(rawSequenceResponse, ignoreRightArgument = false) {
//Copy all values that are unchanged between raw and typed Sequence object
const data = Object.assign({}, rawSequenceResponse);
//Create temporary task guid - it allows to remove single task in builder, task guids are not supported by backend so it exists only in library
//Here we also here handle task backward compatibility issue - remap DeviceTasks to ControllerTasks
const findLastRightArgumentAndRefactorTasks = (rawSequence) => {
//Last arg
if (rawSequence.RightArgumentType == ArgumentTypeNum.Null) {
//Remap DeviceTasks to ControllerTasks - this code coud be removed in future
if (!Object.hasOwn(rawSequence.Tasks, "ControllerTasks") && Object.hasOwn(rawSequence.Tasks, "DevicesTasks")) {
delete Object.assign(rawSequence.Tasks, { ["ControllerTasks"]: rawSequence.Tasks["DevicesTasks"] })["DevicesTasks"];
rawSequence.Tasks.ControllerTasks.map((t) => {
t.TaskType = SceneTaskTypeNum.DeviceTask;
t.RunParallel = false;
});
}
//Generate task guids if not exists
//Task guids are implemented from software 2.9.6.5 so we need to generate them for older SW.
if (rawSequence.Tasks.ControllerTasks != undefined) {
rawSequence.Tasks.ControllerTasks.map((t) => {
if ((t === null || t === void 0 ? void 0 : t.Guid) == null) {
t.Guid = Guid.NewGuid();
}
});
}
}
else {
if (!Object.hasOwn(rawSequence.Tasks, "ControllerTasks") && Object.hasOwn(rawSequence.Tasks, "DevicesTasks")) {
delete Object.assign(rawSequence.Tasks, { ["ControllerTasks"]: rawSequence.Tasks["DevicesTasks"] })["DevicesTasks"];
}
return findLastRightArgumentAndRefactorTasks(rawSequence.RightArgument);
}
};
findLastRightArgumentAndRefactorTasks(rawSequenceResponse);
data._rawRequestData = JSON.parse(JSON.stringify(rawSequenceResponse));
//Preform mappings for correct types
if (!ignoreRightArgument) {
data.RightArgumentType = this.MapArgumentType(rawSequenceResponse.RightArgumentType);
data.RightArgument = this.MapRightArgument(rawSequenceResponse.RightArgument, data.RightArgumentType);
}
else {
data.RightArgument = null;
data.RightArgumentType = ArgumentType.Null;
}
data.LeftArgumentType = this.MapArgumentType(rawSequenceResponse.LeftArgumentType);
data.LeftArgument = this.MapLeftArgument(rawSequenceResponse.LeftArgument, data.LeftArgumentType);
data.Tasks.ControllerTasks = this.MapControllerTasks(rawSequenceResponse.Tasks.ControllerTasks);
if (data.DoesHaveTriggers === undefined) {
data.DoesHaveTriggers = data.LeftArgumentType == ArgumentType.Null;
}
return data;
}
/**
* Functions map all nested right arguments recursively
* @param arg
* @returns
*/
MapRightArgument(arg, argType) {
if (arg.HandledType == 0)
return arg;
arg.LeftArgumentType = this.MapArgumentType(arg.LeftArgumentType);
arg.LeftArgument = this.MapLeftArgument(arg.LeftArgument, arg.LeftArgumentType);
arg.Tasks.ControllerTasks = this.MapControllerTasks(arg.Tasks.ControllerTasks);
//Remove old taks if exists
if (Object.hasOwn(arg.Tasks, "DevicesTasks"))
delete arg.Tasks["DevicesTasks"];
switch (argType) {
case ArgumentType.Condition:
arg.RightArgumentType = this.MapArgumentType(arg.RightArgumentType);
arg.RightArgument = this.MapRightArgument(arg.RightArgument, arg.RightArgumentType);
}
return arg;
}
/**
* Function maps raw LeftArgument JSON to object-key typed parameters property
* @param arg
* @returns
*/
MapLeftArgument(arg, argType) {
let result = new LeftArgument();
result.HandledType = arg.HandledType;
switch (argType) {
case ArgumentType.ArgumentAsAstronomicalClock: {
result.Argument.ArgumentAsAstronomicalClock = {
Position: arg.Argument
};
break;
}
case ArgumentType.ArgumentAsAstronomicalClockWithOffset: {
result.Argument.ArgumentAsAstronomicalClockWithOffset = {
Offset: arg.Argument.Offset,
Position: arg.Argument.Position
};
break;
}
case ArgumentType.ArgumentAsBoolean: {
result.Argument.ArgumentAsBoolean = arg.Argument;
break;
}
case ArgumentType.ArgumentAsDayOfWeek: {
result.Argument.ArgumentAsDayOfWeek = arg.Argument;
break;
}
case ArgumentType.ArgumentAsDaysOfWeek: {
result.Argument.ArgumentAsDaysOfWeek = arg.Argument;
break;
}
case ArgumentType.ArgumentAsInt: {
result.Argument.ArgumentAsInt = arg.Argument;
break;
}
case ArgumentType.ArgumentAsTimeout: {
result.Argument.ArgumentAsTimeout = arg.Argument;
break;
}
case ArgumentType.ArgumentAsTimeSpan: {
result.Argument.ArgumentAsTimeSpan = {
days: arg.Argument.days,
hours: arg.Argument.hours,
minutes: arg.Argument.minutes,
seconds: arg.Argument.seconds
};
break;
}
case ArgumentType.ArgumentAsTime: {
result.Argument.ArgumentAsTime = {
Hour: arg.Argument.Hour,
Minute: arg.Argument.Minute,
Second: arg.Argument.Second
};
break;
}
case ArgumentType.ArgumentAsDeviceState: {
const devStateArg = new DeviceStateArgument();
devStateArg.Type = this.MapDeviceStateTypeToResponseType(arg.Argument.DeviceStateType);
devStateArg.SetCheckDeviceState(this.CreateDeviceState(arg.Argument.CheckedDeviceState, arg.Argument.Channel, devStateArg.Type));
devStateArg.DeviceGuid = arg.Argument.DeviceGuid;
devStateArg.ComparisonMethod = arg.Argument.ComparisonMethod == undefined ? DeviceStateComparisonMethod.Default : arg.Argument.ComparisonMethod;
if (arg.Argument.ComparisonParams != null) {
Object.entries(arg.Argument.ComparisonParams).forEach(k => {
switch (k[0]) {
case "DeltaValue":
case "StateRepeatCount":
devStateArg.SetComparisonParam(DeviceStateComparisonParams[k[0]], new NumberParam(k[1]));
break;
case "DeltaCalculationTimeRange":
case "StateRepeatTimeRange":
devStateArg.SetComparisonParam(DeviceStateComparisonParams[k[0]], new TimeSpanParam(k[1]));
break;
}
});
}
result.Argument.ArgumentAsDeviceState = devStateArg;
break;
}
case ArgumentType.ArgumentAsConditionInfo: {
result.Argument.ArgumentAsConditionInfo = {
DeviceGuid: arg.Argument.DeviceGuid
};
break;
}
}
return result;
}
/**
* Function changes numeric based enum to string based enum, string enum is more user frienldy and is used for key of left argument typed property
* @param argumentType
* @returns
*/
MapArgumentType(argumentType) {
return ArgumentType[ArgumentTypeNum[argumentType]];
}
/**
* Maps types of device state from Scenes extension state enum to general device states enum in library
* @param stateType
* @returns
*/
MapDeviceStateTypeToResponseType(stateType) {
switch (stateType) {
case DeviceStateType.BatteryState:
return DeviceResponseType.BatteryState;
case DeviceStateType.BinarySensor:
return DeviceResponseType.BinarySensorState;
case DeviceStateType.BlindPosition:
return DeviceResponseType.BlindPosition;
case DeviceStateType.Brightness:
return DeviceResponseType.MeasuredBrightness;
case DeviceStateType.ButtonState:
return DeviceResponseType.RemoteButtonState;
case DeviceStateType.ChannelOnOff:
return DeviceResponseType.ChannelOnOffState;
case DeviceStateType.DoorBell:
return DeviceResponseType.DoorBellState;
case DeviceStateType.Energy:
return DeviceResponseType.MeasuredEnergy;
case DeviceStateType.FloodSensor:
return DeviceResponseType.FloodSensorState;
case DeviceStateType.GatePosition:
return DeviceResponseType.GatePosition;
//case DeviceStateType.HeatSensor:
// return DeviceResponseType.
case DeviceStateType.LightBrightness:
return DeviceResponseType.LightBrightness;
case DeviceStateType.LightColor:
return DeviceResponseType.LightColor;
case DeviceStateType.LightTemperature:
return DeviceResponseType.LightWarmth;
//case DeviceStateType.MeasuredCurrent:
// return DeviceResponseType.
//case DeviceStateType.MeasuredPower:
// return DeviceResponseType
// case DeviceStateType.MeasuredVoltage:
// return DeviceResponseType.
case DeviceStateType.ReedState:
return DeviceResponseType.ReedState;
case DeviceStateType.SmokeSensor:
return DeviceResponseType.SmokeSensorState;
case DeviceStateType.Temperature:
return DeviceResponseType.MeasuredTemperature;
case DeviceStateType.Humidity:
return DeviceResponseType.HumiditySensorState;
case DeviceStateType.BlindsControlButton:
return DeviceResponseType.BlindRemoteButtonState;
case DeviceStateType.FacadeControlButton:
return DeviceResponseType.FacadeRemoteButtonState;
case DeviceStateType.Movement:
return DeviceResponseType.MovementSensorState;
case DeviceStateType.AirPressure:
return DeviceResponseType.PressureSensorState;
case DeviceStateType.WindSpeed:
return DeviceResponseType.WindSpeedState;
case DeviceStateType.WindThreshold:
return DeviceResponseType.CurrentWindThreshold;
default:
return DeviceResponseType.Unknown;
}
}
/**
* Function converts device state from Scenes extension to general device states in library
* @param argumentData
* @param responseType
* @returns
*/
CreateDeviceState(argumentData, channel, responseType) {
switch (responseType) {
case DeviceResponseType.BatteryState: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
Percentage: argumentData.Percentage,
State: argumentData.State,
Time: "",
};
return state;
}
case DeviceResponseType.BinarySensorState: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
State: argumentData.State,
Time: "",
};
return state;
}
case DeviceResponseType.BlindPosition: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
Position: argumentData.Position,
RawPosition: argumentData.RawPosition,
Time: "",
};
return state;
}
case DeviceResponseType.LightBrightness: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
Brightness: argumentData.Brightness,
Time: "",
};
return state;
}
case DeviceResponseType.MeasuredBrightness: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
Brightness: argumentData.Brightness,
Time: "",
};
return state;
}
case DeviceResponseType.RemoteButtonState: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
State: argumentData.State,
Time: "",
};
return state;
}
case DeviceResponseType.ChannelOnOffState: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
State: argumentData.State,
Time: "",
};
return state;
}
case DeviceResponseType.DoorBellState: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
State: argumentData.State,
Time: "",
};
return state;
}
case DeviceResponseType.MeasuredEnergy: {
const params = new Map();
for (let [k, v] of Object.entries(argumentData.MeasurementParameters))
params.set(EnergyMeasurementParameter[k], v);
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
MeasurementParameters: params,
Time: "",
};
return state;
}
case DeviceResponseType.FloodSensorState: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
State: argumentData.State,
Time: "",
};
return state;
}
case DeviceResponseType.GatePosition: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
Position: argumentData.Position,
PositionType: argumentData.PositionType,
Time: "",
};
return state;
}
case DeviceResponseType.LightColor: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
R: argumentData.R,
G: argumentData.G,
B: argumentData.B,
Time: "",
};
return state;
}
case DeviceResponseType.LightWarmth: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
Temperature: argumentData.Temperature,
Time: "",
};
return state;
}
case DeviceResponseType.ReedState: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
State: argumentData.State,
Time: "",
};
return state;
}
case DeviceResponseType.SmokeSensorState:
throw new UnsupportedScenesDeviceState("Unsupported device state!");
case DeviceResponseType.MeasuredTemperature: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
Temperature: argumentData.Temperature,
Time: "",
Type: argumentData.Type
};
return state;
}
case DeviceResponseType.HumiditySensorState: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
Humidity: argumentData.Humidity,
Time: "",
Type: argumentData.Type
};
return state;
}
case DeviceResponseType.BlindRemoteButtonState: {
const state = {
Channel: channel,
StateReliability: StateReliability.Unconfident,
State: argumentData.State,
Time: "",
};
return state;
}
case DeviceResponseType.LightRGBWState: {
const state = {
StateReliability: StateReliability.Unconfident,
Channel: channel,
Time: "",
Brightness: 100,
R: argumentData.R,
G: argumentData.G,
B: argumentData.B,
W: argumentData.W,
};
return state;
}
case DeviceResponseType.FacadeRemoteButtonState: {
const state = {
Channel: channel,
Time: "",
StateReliability: StateReliability.Unconfident,
State: argumentData.State
};
return state;
}
case DeviceResponseType.MovementSensorState: {
const state = {
Channel: channel,
Time: "",
StateReliability: StateReliability.Unconfident,
Movement: argumentData.Movement,
Intensity: argumentData.Intensity
};
return state;
}
case DeviceResponseType.PressureSensorState: {
const state = {
Channel: channel,
Time: "",
StateReliability: StateReliability.Unconfident,
Pressure: argumentData.Pressure,
PressureType: argumentData.PressureType
};
return state;
}
case DeviceResponseType.WindSpeedState: {
const state = {
Channel: channel,
Time: "",
StateReliability: StateReliability.Unconfident,
Value: argumentData.Value
};
return state;
}
case DeviceResponseType.CurrentWindThreshold: {
const state = {
Channel: channel,
Time: "",
StateReliability: StateReliability.Unconfident,
WindThreshold: argumentData.WindThreshold
};
return state;
}
case DeviceResponseType.Unknown:
return new DeviceState();
default:
throw new UnsupportedScenesDeviceState("Unsupported device state!");
}
}
MapDeviceTask(rawTasks) {
var _a;
let result = new DeviceTask();
let tsk = rawTasks;
(_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Debug(`[TASK] object: ${JSON.stringify(tsk)}`);
switch (tsk.ControlFeature) {
case DeviceControlFeature.TurnOn: {
result = new TurnOn();
result.TaskType = DeviceTaskType.TurnOn;
break;
}
case DeviceControlFeature.TurnOff: {
result = new TurnOff();
result.TaskType = DeviceTaskType.TurnOff;
break;
}
case DeviceControlFeature.ToggleState: {
result = new ToggleState();
result.TaskType = DeviceTaskType.TogleState;
break;
}
case DeviceControlFeature.SetBlindPosition: {
const dev = Api.Get(DevicesService.ServiceName).GetDevice(tsk.DeviceGuid);
if (dev === null || dev === void 0 ? void 0 : dev.AvailableTaskTypes.any(a => a.InterfaceType == "IBlindPositionSimple")) {
result = new SetBlindPositionSimple();
result.TaskType = DeviceTaskType.SetBlindPositionSimple;
result.Action = tsk.Data.Action;
}
else {
result = new SetBlindPosition();
result.TaskType = DeviceTaskType.SetBlindPosition;
result.Action = tsk.Data.Action;
result.Position = tsk.Data.Position;
}
break;
}
case DeviceControlFeature.SetLightColor:
result = new SetLightColor();
result.TaskType = DeviceTaskType.SetLightColor;
result.R = tsk.Data.R;
result.G = tsk.Data.G;
result.B = tsk.Data.B;
break;
case DeviceControlFeature.SetLightTemperature:
result = new SetLightTemperature();
result.TaskType = DeviceTaskType.SetLightTemperature;
result.Temperature = tsk.Data.Temperature;
break;
case DeviceControlFeature.SetLightBrightness:
result = new SetLightBrightness();
result.TaskType = DeviceTaskType.SetLightBrightness;
result.Brightness = tsk.Data.Brightness;
break;
case DeviceControlFeature.SetTemperature:
result = new SetTemperature();
result.TaskType = DeviceTaskType.SetTemperature;
result.Temperature = tsk.Data.Temperature;
break;
case DeviceControlFeature.GetState:
result = new GetDeviceState();
result.TaskType = DeviceTaskType.GetChannelsState;
break;
case DeviceControlFeature.TurnOnWithTimeout:
result = new TurnOnWithTime();
result.TaskType = DeviceTaskType.TurnOnWithTime;
result.SwitchOffDelaySeconds = tsk.Data.SwitchOffDelaySeconds;
break;
case DeviceControlFeature.SetLightBrightnessDynamicly:
result = new SetLightBrightnessDynamicly();
result.TaskType = DeviceTaskType.SetLightBrightnessDynamicly;
result.Brightness = tsk.Data.Brightness;
break;
case DeviceControlFeature.IdentifyDevice:
result = new IdentifyDevice();
result.TaskType = DeviceTaskType.IdentifyDevice;
break;
case DeviceControlFeature.SetBlindOpenCloseTime:
result = new SetBlindOpenCloseTime();
result.TaskType = DeviceTaskType.SetBlindOpenCloseTime;
result.Data.CloseTime = tsk.Data;
break;
case DeviceControlFeature.SetBlindMicroventilation:
result = new SetBlindMicroventilation();
result.TaskType = DeviceTaskType.SetBlindMicroventilation;
result.Position = tsk.Data.Position;
break;
case DeviceControlFeature.GatewayPulse:
result = new ChangeGatewayPositionPulse();
result.TaskType = DeviceTaskType.ChangeGatewayPositionPulse;
break;
case DeviceControlFeature.GatePulse:
result = new ChangeGatePositionPulse();
result.TaskType = DeviceTaskType.ChangeGatePositionPulse;
break;
case DeviceControlFeature.SetFacadePositionAndTilt:
result = new SetFacadePosition();
result.TaskType = DeviceTaskType.SetFacadePosition;
result.Position = tsk.Data.Position;
result.Tilt = tsk.Data.Tilt;
result.FacadeAction = FacadeActionEnum.TiltAndPercentage;
break;
case DeviceControlFeature.GetFacadeType:
result = new GetFacadeType();
result.TaskType = DeviceTaskType.GetFacadeType;
break;
case DeviceControlFeature.LightRGBW:
result = new LightRGBW();
result.TaskType = DeviceTaskType.LightRGBW;
result.Data = tsk.Data;
break;
case DeviceControlFeature.SetGatePositionPrecise:
result = new SetGatePositionPrecise();
result.TaskType = DeviceTaskType.PreciseGateControl;
result.Position = tsk.Data.Position;
result.GateControlAction = tsk.Data.GateControlAction;
break;
default:
break;
}
result.Channel = tsk.Channel;
result.DeviceGuid = tsk.DeviceGuid;
result.FeatureType = tsk.ControlFeature;
result.Guid = Guid.NewGuid();
return result;
}
MapControllerTasks(rawTasks) {
var _a, _b;
const result = [];
(_a = DependencyContainer.Log) === null || _a === void 0 ? void 0 : _a.Debug(`[TASKS] received tasks object: ${JSON.stringify(rawTasks)}`);
for (let tsk of rawTasks) {
const task = new ControllerTasks();
task.Guid = tsk.Guid;
task.TaskId = Helpers.GenerateMd5(JSON.stringify(tsk));
switch (tsk.TaskType) {
case SceneTaskTypeNum.DeviceTask:
task.TaskType = SceneTaskType.DeviceTask;
task.Task.DeviceTask = this.MapDeviceTask(tsk);
break;
case SceneTaskTypeNum.DelayTask:
task.TaskType = SceneTaskType.DelayTask;
task.Task.DelayTask = {
Delay: new TimeSpanParam(tsk.Delay)
};
break;
case SceneTaskTypeNum.NotifyTask:
task.TaskType = SceneTaskType.NotifyTask;
task.Task.NotifyTask = {
Message: tsk.Message,
NotifyType: tsk.NotifyType,
NotificationClients: tsk.NotificationClients
};
break;
case SceneTaskTypeNum.LockExecution:
case SceneTaskTypeNum.LockExecution:
task.TaskType = SceneTaskType.LockExecution;
(_b = DependencyContainer.Log) === null || _b === void 0 ? void 0 : _b.Debug(`[TASKS] received task LockExecution object: ${JSON.stringify(tsk)}`);
task.Task.LockExecution = {
LockStartHour: new TimeSpanParam(tsk.LockStartHour), // (tsk as any).LockStartHour as TimeSpanParam, //
LockEndHour: new TimeSpanParam(tsk.LockEndHour), // (tsk as any).LockEndHour as TimeSpanParam, //
LockType: tsk.LockType,
ResetLockScenesGuids: tsk.ResetLockScenesGuids
};
break;
case SceneTaskTypeNum.Unknown:
break;
}
r