diff --git a/anslq25/MessagesMock.ts b/anslq25/MessagesMock.ts index 12db9592..b7d44250 100644 --- a/anslq25/MessagesMock.ts +++ b/anslq25/MessagesMock.ts @@ -11,7 +11,7 @@ export class MessagesMock { constructor() { } public static process(msg: Inbound) { - switch (msg.protocol) { + switch (msg. protocol) { case Protocol.Broadcast: { switch (sys.controllerType) { case ControllerType.IntelliCenter: diff --git a/app.ts b/app.ts index b9a34a6d..5fc5cd6a 100755 --- a/app.ts +++ b/app.ts @@ -39,16 +39,8 @@ export async function initAsync() { await conn.initAsync(); await sys.start(); await webApp.initAutoBackup(); - await sl.connectAsync(); + await sl.initAsync(); } catch (err) { console.log(`Error Initializing nodejs-PoolController ${err.message}`); } - //return Promise.resolve() - // .then(function () { config.init(); }) - // .then(function () { logger.init(); }) - // .then(function () { conn.init(); }) - // .then(function () { sys.init(); }) - // .then(function () { state.init(); }) - // .then(function () { webApp.init(); }) - // .then(function () { sys.start(); }); } export async function startPacketCapture(bResetLogs: boolean) { @@ -78,6 +70,7 @@ export async function stopAsync(): Promise { await sys.stopAsync(); await state.stopAsync(); await conn.stopAsync(); + await sl.stopAsync(); await webApp.stopAsync(); await config.updateAsync(); await logger.stopAsync(); diff --git a/controller/Equipment.ts b/controller/Equipment.ts index 30c940d1..13612512 100644 --- a/controller/Equipment.ts +++ b/controller/Equipment.ts @@ -34,6 +34,7 @@ import { NixieControlPanel } from "./nixie/Nixie"; import { NixieBoard } from 'controller/boards/NixieBoard'; import { MockSystemBoard } from "../anslq25/boards/MockSystemBoard"; import { MockBoardFactory } from "../anslq25/boards/MockBoardFactory"; +import { ScreenLogicComms } from "./comms/ScreenLogic"; interface IPoolSystem { cfgPath: string; @@ -335,6 +336,7 @@ export class PoolSystem implements IPoolSystem { public chemControllers: ChemControllerCollection; public chemDosers: ChemDoserCollection; public filters: FilterCollection; + public screenlogic: ScreenLogicComms; public appVersion: string; public get dirty(): boolean { return this._isDirty; } public set dirty(val) { @@ -819,17 +821,6 @@ export class Options extends EqItem { public set cleanerSolarDelay(val: boolean) { this.setDataVal('cleanerSolarDelay', val); } public get cleanerSolarDelayTime(): number { return this.data.cleanerSolarDelayTime; } public set cleanerSolarDelayTime(val: number) { this.setDataVal('cleanerSolarDelayTime', val); } - - //public get airTempAdj(): number { return typeof this.data.airTempAdj === 'undefined' ? 0 : this.data.airTempAdj; } - //public set airTempAdj(val: number) { this.setDataVal('airTempAdj', val); } - //public get waterTempAdj1(): number { return typeof this.data.waterTempAdj1 === 'undefined' ? 0 : this.data.waterTempAdj1; } - //public set waterTempAdj1(val: number) { this.setDataVal('waterTempAdj1', val); } - //public get solarTempAdj1(): number { return typeof this.data.solarTempAdj1 === 'undefined' ? 0 : this.data.solarTempAdj1; } - //public set solarTempAdj1(val: number) { this.setDataVal('solarTempAdj1', val); } - //public get waterTempAdj2(): number { return typeof this.data.waterTempAdj2 === 'undefined' ? 0 : this.data.waterTempAdj2; } - //public set waterTempAdj2(val: number) { this.setDataVal('waterTempAdj2', val); } - //public get solarTempAdj2(): number { return typeof this.data.solarTempAdj2 === 'undefined' ? 0 : this.data.solarTempAdj2; } - //public set solarTempAdj2(val: number) { this.setDataVal('solarTempAd2', val); } } export class VacationOptions extends ChildEqItem { public initData() { @@ -2652,4 +2643,21 @@ export class AlarmSetting extends ChildEqItem { public get high(): number { return this.data.high; } public set high(val: number) { this.setDataVal('high', val); } } +export class Screenlogic extends EqItem { + ctor(data: any, name?: any): General { return new General(data, name || 'pool'); } + public get enabled(): boolean { return this.data.enabled; } + public set enabled(val: boolean) { this.setDataVal('enabled', val); } + public get type(): 'local'|'remote' { return this.data.type; } + public set type(val: 'local'|'remote') { this.setDataVal('type', val); } + public get systemName(): string { return this.data.systemName; } + public set systemName(val: string) { this.setDataVal('systemName', val); } + public get password(): string { return this.data.password; } + public set password(val: string) { this.setDataVal('password', val); } + + public clear(master: number = -1) { + if (master === -1) + super.clear(); + } + +} export let sys = new PoolSystem(); \ No newline at end of file diff --git a/controller/State.ts b/controller/State.ts index 56f3ccb6..f333f0e2 100644 --- a/controller/State.ts +++ b/controller/State.ts @@ -966,7 +966,7 @@ export class PumpState extends EqState { this.hasChanged = true; } } - public get virtualControllerStatus(): number { +/* public get virtualControllerStatus(): number { return typeof (this.data.virtualControllerStatus) !== 'undefined' ? this.data.virtualControllerStatus.val : -1; } public set virtualControllerStatus(val: number) { @@ -974,7 +974,7 @@ export class PumpState extends EqState { this.data.virtualControllerStatus = sys.board.valueMaps.virtualControllerStatus.transform(val); this.hasChanged = true; } - } + } */ public get targetSpeed(): number { return this.data.targetSpeed; } // used for virtual controller public set targetSpeed(val: number) { this.setDataVal('targetSpeed', val); } public get type() { return typeof (this.data.type) !== 'undefined' ? this.data.type.val : -1; } diff --git a/controller/boards/EasyTouchBoard.ts b/controller/boards/EasyTouchBoard.ts index b8e9130a..7c9901ba 100644 --- a/controller/boards/EasyTouchBoard.ts +++ b/controller/boards/EasyTouchBoard.ts @@ -16,16 +16,17 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ +import { sl } from '../../controller/comms/ScreenLogic'; import * as extend from 'extend'; import { logger } from '../../logger/Logger'; import { conn } from '../comms/Comms'; import { Message, Outbound, Protocol, Response } from '../comms/messages/Messages'; import { Timestamp, utils } from '../Constants'; -import { Body, ChemController, ConfigVersion, CustomName, EggTimer, Feature, Heater, ICircuit, LightGroup, LightGroupCircuit, Options, PoolSystem, Pump, Schedule, sys } from '../Equipment'; +import { Body, ChemController, ConfigVersion, CustomName, EggTimer, Feature, Heater, ICircuit, LightGroup, LightGroupCircuit, Options, PoolSystem, Pump, Schedule, sys, Valve } from '../Equipment'; import { InvalidEquipmentDataError, InvalidEquipmentIdError, InvalidOperationError } from '../Errors'; import { ncp } from "../nixie/Nixie"; import { BodyTempState, ChlorinatorState, ICircuitGroupState, ICircuitState, LightGroupState, state } from '../State'; -import { BodyCommands, byteValueMap, ChemControllerCommands, ChlorinatorCommands, CircuitCommands, ConfigQueue, ConfigRequest, EquipmentIdRange, FeatureCommands, HeaterCommands, PumpCommands, ScheduleCommands, SystemBoard, SystemCommands } from './SystemBoard'; +import { BodyCommands, byteValueMap, ChemControllerCommands, ChlorinatorCommands, CircuitCommands, ConfigQueue, ConfigRequest, EquipmentIdRange, FeatureCommands, HeaterCommands, PumpCommands, ScheduleCommands, SystemBoard, SystemCommands, ValveCommands } from './SystemBoard'; export class EasyTouchBoard extends SystemBoard { public needsConfigChanges: boolean = false; @@ -93,7 +94,7 @@ export class EasyTouchBoard extends SystemBoard { [30, { name: 'fiberoptic', desc: 'Fiber Optic' }], [31, { name: 'fiberworks', desc: 'Fiber Works' }], [32, { name: 'fillline', desc: 'Fill Line' }], - [33, { name: 'floorclnr', desc: 'Floor CLeaner' }], + [33, { name: 'floorclnr', desc: 'Floor Cleaner' }], [34, { name: 'fogger', desc: 'Fogger' }], [35, { name: 'fountain', desc: 'Fountain' }], [36, { name: 'fountain1', desc: 'Fountain 1' }], @@ -409,6 +410,7 @@ export class EasyTouchBoard extends SystemBoard { eq.maxFeatures = md.features = typeof mt.features !== 'undefined' ? mt.features : 8; eq.maxValves = md.valves = typeof mt.valves !== 'undefined' ? mt.valves : mt.shared ? 4 : 2; eq.maxPumps = md.maxPumps = typeof mt.pumps !== 'undefined' ? mt.pumps : 2; + eq.maxHeaters = md.maxHeaters = typeof mt.heaters !== 'undefined' ? mt.heaters : 2; eq.shared = mt.shared; eq.single = typeof mt.single !== 'undefined' ? mt.single : false; eq.dual = false; @@ -468,6 +470,7 @@ export class EasyTouchBoard extends SystemBoard { public schedules: TouchScheduleCommands = new TouchScheduleCommands(this); public heaters: TouchHeaterCommands = new TouchHeaterCommands(this); public chemControllers: TouchChemControllerCommands = new TouchChemControllerCommands(this); + public valves: TouchValveCommands = new TouchValveCommands(this); protected _configQueue: TouchConfigQueue = new TouchConfigQueue(); public reloadConfig() { //sys.resetSystem(); @@ -615,7 +618,7 @@ export class TouchConfigQueue extends ConfigQueue { .catch((err) => { logger.error(`Error sending configuration request message on port ${out.portId}: ${err.message};`); }) - .finally(()=>{ + .finally(() => { setTimeout(() => { self.processNext(out); }, 50); }) @@ -636,7 +639,7 @@ export class TouchConfigQueue extends ConfigQueue { } } export class TouchScheduleCommands extends ScheduleCommands { - public async setScheduleAsync(data: any): Promise { + public async setScheduleAsync(data: any, send: boolean = true): Promise { try { let id = typeof data.id === 'undefined' ? -1 : parseInt(data.id, 10); if (id <= 0) id = sys.schedules.getNextEquipmentId(new EquipmentIdRange(1, sys.equipment.maxSchedules)); @@ -709,20 +712,22 @@ export class TouchScheduleCommands extends ScheduleCommands { else if (endTimeType === sys.board.valueMaps.scheduleTimeTypes.getValue('sunset')) endTime = sunset; } - let out = Outbound.create({ - action: 145, - payload: [ - id, - circuit, - Math.floor(startTime / 60), - startTime - (Math.floor(startTime / 60) * 60), - schedType === sys.board.valueMaps.scheduleTypes.getValue('runonce') ? sys.board.valueMaps.scheduleTypes.getValue('runonce') : Math.floor(endTime / 60), - endTime - (Math.floor(endTime / 60) * 60), - schedDays], - retries: 2 - // ,response: Response.create({ action: 1, payload: [145] }) - }); - await out.sendAsync(); + if (send) { + let out = Outbound.create({ + action: 145, + payload: [ + id, + circuit, + Math.floor(startTime / 60), + startTime - (Math.floor(startTime / 60) * 60), + schedType === sys.board.valueMaps.scheduleTypes.getValue('runonce') ? sys.board.valueMaps.scheduleTypes.getValue('runonce') : Math.floor(endTime / 60), + endTime - (Math.floor(endTime / 60) * 60), + schedDays], + retries: 2 + // ,response: Response.create({ action: 1, payload: [145] }) + }); + await out.sendAsync(); + } sched.circuit = ssched.circuit = circuit; sched.scheduleDays = ssched.scheduleDays = schedDays; sched.scheduleType = ssched.scheduleType = schedType; @@ -739,8 +744,10 @@ export class TouchScheduleCommands extends ScheduleCommands { // For good measure russ is sending out a config request for // the schedule in question. If there was a failure on the // OCP side this will resolve it. - let req = Outbound.create({ action: 209, payload: [sched.id], retries: 2 }); - await req.sendAsync(); + if (send) { + let req = Outbound.create({ action: 209, payload: [sched.id], retries: 2 }); + await req.sendAsync(); + } state.schedules.sortById(); return sched; } @@ -780,27 +787,29 @@ export class TouchScheduleCommands extends ScheduleCommands { return Promise.reject(err); } } - public async setEggTimerAsync(data?: any): Promise { + public async setEggTimerAsync(data?: any, send: boolean = true): Promise { let id = typeof data.id === 'undefined' ? -1 : parseInt(data.id, 10); if (id <= 0) id = sys.schedules.getNextEquipmentId(new EquipmentIdRange(1, sys.equipment.maxSchedules)); if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError(`Invalid schedule/eggTimer id: ${data.id} or all schedule/eggTimer ids filled (${sys.eggTimers.length + sys.schedules.length} used out of ${sys.equipment.maxSchedules})`, data.id, 'Schedule')); let circuit = sys.circuits.getInterfaceById(data.circuit); if (typeof circuit === 'undefined') return Promise.reject(new InvalidEquipmentIdError(`Invalid circuit id: ${data.circuit} for schedule id ${data.id}`, data.id, 'Schedule')); - let out = Outbound.create({ - action: 145, - payload: [ - id, - circuit.id, - 25, - 0, - utils.makeBool(data.dontStop) ? 27 : Math.floor(parseInt(data.runTime, 10) / 60), - utils.makeBool(data.dontStop) ? 0 : data.runTime - (Math.floor(parseInt(data.runTime, 10) / 60) * 60), - 0], - retries: 2 - }); try { - await out.sendAsync(); + if (send) { + let out = Outbound.create({ + action: 145, + payload: [ + id, + circuit.id, + 25, + 0, + utils.makeBool(data.dontStop) ? 27 : Math.floor(parseInt(data.runTime, 10) / 60), + utils.makeBool(data.dontStop) ? 0 : data.runTime - (Math.floor(parseInt(data.runTime, 10) / 60) * 60), + 0], + retries: 2 + }); + await out.sendAsync(); + } let eggTimer = sys.eggTimers.getItemById(id, true); eggTimer.circuit = circuit.id; eggTimer.runTime = circuit.eggTimer = typeof data.runTime !== 'undefined' ? data.runTime : circuit.eggTimer || 720; @@ -809,8 +818,10 @@ export class TouchScheduleCommands extends ScheduleCommands { // For good measure russ is sending out a config request for // the schedule in question. If there was a failure on the // OCP side this will resolve it. - let req = Outbound.create({ action: 209, payload: [eggTimer.id], retries: 2 }); - await req.sendAsync(); + if (send) { + let req = Outbound.create({ action: 209, payload: [eggTimer.id], retries: 2 }); + await req.sendAsync(); + } return eggTimer; } catch (err) { @@ -1000,22 +1011,24 @@ class TouchSystemCommands extends SystemCommands { return Promise.reject(err); } } - public async setCustomNameAsync(data: any): Promise { + public async setCustomNameAsync(data: any, send: boolean = true): Promise { let id = parseInt(data.id, 10); if (isNaN(id)) throw new InvalidEquipmentIdError('Invalid Custom Name Id', data.id, 'customName'); if (id > sys.equipment.maxCustomNames) throw new InvalidEquipmentIdError('Custom Name Id out of range', data.id, 'customName'); let cname = sys.customNames.getItemById(id); // No need to make any changes. Just return. if (cname.name === data.name) return cname; - let out = Outbound.create({ - action: 138, - payload: [data.id], - response: true, - retries: 3 - }); - out.appendPayloadString(data.name, 11); try { - await out.sendAsync(); + if (send) { + let out = Outbound.create({ + action: 138, + payload: [data.id], + response: true, + retries: 3 + }); + out.appendPayloadString(data.name, 11); + await out.sendAsync(); + } let c = sys.customNames.getItemById(id, true); c.name = data.name; @@ -1349,7 +1362,7 @@ export class TouchCircuitCommands extends CircuitCommands { // return []; // } //} - public async setCircuitAsync(data: any): Promise { + public async setCircuitAsync(data: any, send: boolean = true): Promise { try { // example [255,0,255][165,33,16,34,139,5][17,14,209,0,0][2,120] // set circuit 17 to function 14 and name 209 @@ -1368,15 +1381,17 @@ export class TouchCircuitCommands extends CircuitCommands { let nameByte = 3; // set default `Aux 1` if (typeof data.nameId !== 'undefined') nameByte = data.nameId; else if (typeof circuit.name !== 'undefined') nameByte = circuit.nameId; - let out = Outbound.create({ - action: 139, - payload: [parseInt(data.id, 10), typeByte | (utils.makeBool(data.freeze) ? 64 : 0), nameByte, 0, 0], - retries: 3, - response: true - }); - await out.sendAsync(); - circuit = sys.circuits.getInterfaceById(data.id); - let cstate = state.circuits.getInterfaceById(data.id); + if (send) { + let out = Outbound.create({ + action: 139, + payload: [parseInt(data.id, 10), typeByte | (utils.makeBool(data.freeze) ? 64 : 0), nameByte, 0, 0], + retries: 3, + response: true + }); + await out.sendAsync(); + } + circuit = sys.circuits.getInterfaceById(data.id, true); + let cstate = state.circuits.getInterfaceById(data.id, true); circuit.nameId = cstate.nameId = nameByte; circuit.name = cstate.name = sys.board.valueMaps.circuitNames.transform(nameByte).desc; circuit.showInFeatures = cstate.showInFeatures = typeof data.showInFeatures !== 'undefined' ? utils.makeBool(data.showInFeatures) : circuit.showInFeatures; @@ -1392,7 +1407,7 @@ export class TouchCircuitCommands extends CircuitCommands { if (typeof eggTimer !== 'undefined') await sys.board.schedules.deleteEggTimerAsync({ id: eggTimer.id }); } else { - await sys.board.schedules.setEggTimerAsync({ id: typeof eggTimer !== 'undefined' ? eggTimer.id : -1, runTime: circuit.eggTimer, dontStop: circuit.dontStop, circuit: circuit.id }); + await sys.board.schedules.setEggTimerAsync({ id: typeof eggTimer !== 'undefined' ? eggTimer.id : -1, runTime: circuit.eggTimer, dontStop: circuit.dontStop, circuit: circuit.id }, false); } } catch (err) { @@ -1429,6 +1444,7 @@ export class TouchCircuitCommands extends CircuitCommands { val = false; } let cstate = state.circuits.getInterfaceById(id); + await sl.circuits.setCircuitStateAsync(id, val); let out = Outbound.create({ action: 134, payload: [id, val ? 1 : 0], @@ -1451,7 +1467,7 @@ export class TouchCircuitCommands extends CircuitCommands { return await this.setCircuitStateAsync(id, !cstate.isOn); } - public async setLightGroupAsync(obj: any): Promise { + public async setLightGroupAsync(obj: any, send: boolean = true): Promise { try { let group: LightGroup = null; let id = typeof obj.id !== 'undefined' ? parseInt(obj.id, 10) : -1; @@ -1485,69 +1501,73 @@ export class TouchCircuitCommands extends CircuitCommands { if (sys.equipment.maxIntelliBrites === 8) { // Easytouch - let out = Outbound.create({ - action: 167, - retries: 3, - response: true - }); - const lgcircuits = group.circuits.get(); - for (let circ = 0; circ < 8; circ++) { - const lgcirc = lgcircuits[circ]; - if (typeof lgcirc === 'undefined') out.payload.push(0, 0, 0, 0); - else { - out.payload.push(lgcirc.circuit); - out.payload.push(((lgcirc.position - 1) << 4) + lgcirc.color); - out.payload.push(lgcirc.swimDelay << 1); - out.payload.push(0); + if (send) { + let out = Outbound.create({ + action: 167, + retries: 3, + response: true + }); + const lgcircuits = group.circuits.get(); + for (let circ = 0; circ < 8; circ++) { + const lgcirc = lgcircuits[circ]; + if (typeof lgcirc === 'undefined') out.payload.push(0, 0, 0, 0); + else { + out.payload.push(lgcirc.circuit); + out.payload.push(((lgcirc.position - 1) << 4) + lgcirc.color); + out.payload.push(lgcirc.swimDelay << 1); + out.payload.push(0); + } } + await out.sendAsync(); } - await out.sendAsync(); } else { // Intellitouch const lgcircuits = group.circuits.get(); - - let out = Outbound.create({ - action: 167, - retries: 3, - payload: [1], - response: true - }); - for (let circ = 0; circ < 5; circ++) { - const lgcirc = lgcircuits[circ]; - if (typeof lgcirc === 'undefined') out.payload.push.apply([0, 0, 0, 0]); - else { - out.payload.push(lgcirc.id); - out.payload.push(((lgcirc.position - 1) << 4) + lgcirc.color); - out.payload.push(lgcirc.swimDelay << 1); - out.payload.push(0); + if (send) { + + let out = Outbound.create({ + action: 167, + retries: 3, + payload: [1], + response: true + }); + for (let circ = 0; circ < 5; circ++) { + const lgcirc = lgcircuits[circ]; + if (typeof lgcirc === 'undefined') out.payload.push.apply([0, 0, 0, 0]); + else { + out.payload.push(lgcirc.id); + out.payload.push(((lgcirc.position - 1) << 4) + lgcirc.color); + out.payload.push(lgcirc.swimDelay << 1); + out.payload.push(0); + } } - } - await out.sendAsync(); - - out = Outbound.create({ - action: 167, - retries: 3, - payload: [2], - response: true - }); - for (let circ = 5; circ < 10; circ++) { - const lgcirc = lgcircuits[circ]; - if (typeof lgcirc === 'undefined') out.payload.push.apply([0, 0, 0, 0]); - else { - out.payload.push(lgcirc.id); - out.payload.push(((lgcirc.position - 1) << 4) + lgcirc.color); - out.payload.push(lgcirc.swimDelay << 1); - out.payload.push(0); + if (send) await out.sendAsync(); + + out = Outbound.create({ + action: 167, + retries: 3, + payload: [2], + response: true + }); + for (let circ = 5; circ < 10; circ++) { + const lgcirc = lgcircuits[circ]; + if (typeof lgcirc === 'undefined') out.payload.push.apply([0, 0, 0, 0]); + else { + out.payload.push(lgcirc.id); + out.payload.push(((lgcirc.position - 1) << 4) + lgcirc.color); + out.payload.push(lgcirc.swimDelay << 1); + out.payload.push(0); + } } - } - await out.sendAsync(); + if (send) await out.sendAsync(); - out = Outbound.create({ - action: 231, - payload: [0] - }); - await out.sendAsync(); + out = Outbound.create({ + action: 231, + payload: [0] + }); + await out.sendAsync(); + } sys.emitData('lightGroupConfig', group.get(true)); return group; } @@ -1750,7 +1770,7 @@ class TouchFeatureCommands extends FeatureCommands { } class TouchChlorinatorCommands extends ChlorinatorCommands { - public async setChlorAsync(obj: any): Promise { + public async setChlorAsync(obj: any, send: boolean = true): Promise { try { let id = parseInt(obj.id, 10); // Bail out right away if this is not controlled by the OCP. @@ -1762,7 +1782,7 @@ class TouchChlorinatorCommands extends ChlorinatorCommands { id = 1; isAdd = true; } - let chlor = sys.chlorinators.getItemById(id); + let chlor = sys.chlorinators.getItemById(id, isAdd); if (chlor.master !== 0 && !isAdd) return super.setChlorAsync(obj); // RKS: I am not even sure this can be done with Touch as the master on the RS485 bus. if (typeof chlor.master === 'undefined') chlor.master = 0; @@ -1806,17 +1826,20 @@ class TouchChlorinatorCommands extends ChlorinatorCommands { if (typeof obj.ignoreSaltReading !== 'undefined') chlor.ignoreSaltReading = utils.makeBool(obj.ignoreSaltReading); - let out = Outbound.create({ - dest: 16, - action: 153, - // removed disable ? 0 : (spaSetpoint << 1) + 1 because only deleteChlorAsync should remove it from the OCP - payload: [(disabled ? 0 : isDosing ? 100 << 1 : spaSetpoint << 1) + 1, disabled ? 0 : isDosing ? 100 : poolSetpoint, - utils.makeBool(superChlorinate) && superChlorHours > 0 ? superChlorHours + 128 : 0, // We only want to set the superChlor when the user sends superChlor = true - 0, 0, 0, 0, 0, 0, 0], - retries: 3, - response: true, - }); - await out.sendAsync(); + if (send) { + + let out = Outbound.create({ + dest: 16, + action: 153, + // removed disable ? 0 : (spaSetpoint << 1) + 1 because only deleteChlorAsync should remove it from the OCP + payload: [(disabled ? 0 : isDosing ? 100 << 1 : spaSetpoint << 1) + 1, disabled ? 0 : isDosing ? 100 : poolSetpoint, + utils.makeBool(superChlorinate) && superChlorHours > 0 ? superChlorHours + 128 : 0, // We only want to set the superChlor when the user sends superChlor = true + 0, 0, 0, 0, 0, 0, 0], + retries: 3, + response: true, + }); + await out.sendAsync(); + }; let schlor = state.chlorinators.getItemById(id, true); chlor.disabled = disabled; schlor.isActive = chlor.isActive = true; @@ -1832,14 +1855,16 @@ class TouchChlorinatorCommands extends ChlorinatorCommands { chlor.isDosing = isDosing; chlor.portId = portId; chlor.saltTarget = saltTarget; - out = Outbound.create({ - dest: 16, - action: 217, - payload: [0], - retries: 3, - response: true, - }) - await out.sendAsync(); + if (send) { + let out = Outbound.create({ + dest: 16, + action: 217, + payload: [0], + retries: 3, + response: true, + }) + await out.sendAsync(); + } state.emitEquipmentChanges(); return state.chlorinators.getItemById(id); } catch (err) { @@ -1914,7 +1939,7 @@ class TouchPumpCommands extends PumpCommands { } } - public async setPumpAsync(data: any): Promise { + public async setPumpAsync(data: any, send: boolean = true): Promise { // Rules regarding Pumps in *Touch // In *Touch there are basically three classifications of pumps. These include those under control of RS485, Dual Speed, and Single Speed. // 485 Controlled pumps - Any of the IntelliFlo pumps. These are managed by the control panel. @@ -2063,155 +2088,157 @@ class TouchPumpCommands extends PumpCommands { } else { let arr = []; - let outc = Outbound.create({ - action: 155, - payload: [id, ntype], - retries: 2, - response: Response.create({ action: 1, payload: [155] }) - }); - data.address = id + 95; - outc.appendPayloadBytes(0, 44); - if (type.val === 128) { - outc.setPayloadByte(3, 2); - data.model = 0; - } - if (typeof type.maxPrimingTime !== 'undefined' && type.maxPrimingTime > 0 && type.val >= 64) { - // We need to set all of this back to data since later pump.set is called to set the data after success. - data.primingTime = typeof data.primingTime !== 'undefined' ? isNaN(parseInt(data.primingTime, 10)) ? pump.primingTime || 0 : 0 : pump.primingTime; - data.primingSpeed = typeof data.primingSpeed !== 'undefined' ? parseInt(data.primingSpeed, 10) : pump.primingSpeed || type.minSpeed; - outc.setPayloadByte(2, data.primingTime); - outc.setPayloadByte(21, Math.floor(data.primingSpeed / 256)); - outc.setPayloadByte(30, data.primingSpeed % 256); - } - if (type.val === 1) { // Any VF pump. - // We need to set all of this back to data since later pump.set is called to set the data after success. - data.backgroundCircuit = typeof data.backgroundCircuit !== 'undefined' ? parseInt(data.backgroundCircuit, 10) : pump.backgroundCircuit || 6; - data.filterSize = typeof data.filterSize !== 'undefined' ? parseInt(data.filterSize, 10) : pump.filterSize || 15000; - data.turnovers = typeof data.turnovers !== 'undefined' ? parseInt(data.turnovers, 10) : pump.turnovers || 2; - data.manualFilterGPM = typeof data.manualFilterGPM !== 'undefined' ? parseInt(data.manualFilterGPM, 10) : pump.manualFilterGPM || 30; - data.primingSpeed = typeof data.primingSpeed !== 'undefined' ? parseInt(data.primingSpeed, 10) : pump.primingSpeed || 55; - data.primingTime = typeof data.primingTime !== 'undefined' ? parseInt(data.primingTime, 10) : pump.primingTime || 0; - data.maxSystemTime = typeof data.maxSystemTime !== 'undefined' ? parseInt(data.maxSystemTime, 10) : pump.maxSystemTime || 0; - data.maxPressureIncrease = typeof data.maxPressureIncrease != 'undefined' ? parseInt(data.maxPressureIncrease, 10) : pump.maxPressureIncrease || 0; - data.backwashFlow = typeof data.backwashFlow !== 'undefined' ? parseInt(data.backwashFlow, 10) : pump.backwashFlow || 60; - data.backwashTime = typeof data.backwashTime !== 'undefined' ? parseInt(data.bacwashTime, 10) : pump.backwashTime || 5; - data.rinseTime = typeof data.rinseTime !== 'undefined' ? parseInt(data.rinseTime, 10) : pump.rinseTime || 1; - data.vacuumFlow = typeof data.vacuumFlow !== 'undefined' ? parseInt(data.vacuumFlow, 10) : pump.vacuumFlow || 50; - data.vacuumTime = typeof data.vacuumTime !== 'undefined' ? parseInt(data.vacuumTime, 10) : pump.vacuumTime || 10; - data.model = 0; - outc.setPayloadByte(1, data.backgroundCircuit); - outc.setPayloadByte(2, data.filterSize); - outc.setPayloadByte(3, data.turnovers); - outc.setPayloadByte(21, data.manualFilterGPM); - outc.setPayloadByte(22, data.primingSpeed); - outc.setPayloadByte(23, data.primingTime | data.maxSystemTime << 4, 5); - outc.setPayloadByte(24, data.maxPressureIncrease); - outc.setPayloadByte(25, data.backwashFlow); - outc.setPayloadByte(26, data.backwashTime); - outc.setPayloadByte(27, data.rinseTime); - outc.setPayloadByte(28, data.vacuumFlow); - outc.setPayloadByte(30, data.vacuumTime); - } - if (typeof type.maxCircuits !== 'undefined' && type.maxCircuits > 0 && typeof data.circuits !== 'undefined') { // This pump type supports circuits - // Do some validation to make sure we don't have a condition where a circuit is declared twice. - let arrCircuits = []; - // Below is a very strange mess that goofs up the circuit settings. - //{id:1, circuits:[{speed:1750, units:{val:0}, id:1, circuit:6}, {speed:2100, units:{val:0}, id:2, circuit:6}]} - let ubyte = 0; - for (let i = 1; i <= data.circuits.length && i <= type.maxCircuits; i++) { - // RKS: This notion of always returning the max number of circuits was misguided. It leaves gaps in the circuit definitions and makes the pump - // layouts difficult when there are a variety of supported circuits. For instance with SF pumps you only get 4. - let c = i > data.circuits.length ? { speed: type.minSpeed || 0, flow: type.minFlow || 0, circuit: 0 } : data.circuits[i - 1]; - //{speed:1750, units:{val:0}, id:1, circuit:6} - let speed = parseInt(c.speed, 10); - let flow = parseInt(c.flow, 10); - let circuit = parseInt(c.circuit, 10); - if (isNaN(circuit)) return Promise.reject(new InvalidEquipmentDataError(`An invalid pump circuit was supplied for pump ${pump.name}. ${JSON.stringify(c)}`, 'Pump', data)) - if (isNaN(speed)) speed = type.minSpeed; - if (isNaN(flow)) flow = type.minFlow; - outc.setPayloadByte((i * 2) + 3, circuit, 0); - let units; - if (type.name === 'vf') units = sys.board.valueMaps.pumpUnits.getValue('gpm'); - else if (type.name === 'vs') units = sys.board.valueMaps.pumpUnits.getValue('rpm'); - else units = sys.board.valueMaps.pumpUnits.encode(c.units); - c.units = units; - if (isNaN(units)) units = sys.board.valueMaps.pumpUnits.getValue('rpm'); - if (typeof type.minSpeed !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('rpm')) { - outc.setPayloadByte((i * 2) + 4, Math.floor(speed / 256)); // Set to rpm - outc.setPayloadByte(i + 21, speed % 256); - c.speed = speed; - ubyte |= (1 << (i - 1)); - } - else if (typeof type.minFlow !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('gpm')) { - outc.setPayloadByte(i * 2 + 4, flow); // Set to gpm - c.flow = flow; - } - c.id = i; - c.circuit = circuit; - if (arrCircuits.includes(c.circuit)) return Promise.reject(new InvalidEquipmentDataError(`Configuration for pump ${pump.name} is not correct circuit #${c.circuit} as included more than once. ${JSON.stringify(c)}`, 'Pump', data)) - arrCircuits.push(c.circuit); + if (send) { + let outc = Outbound.create({ + action: 155, + payload: [id, ntype], + retries: 2, + response: Response.create({ action: 1, payload: [155] }) + }); + data.address = id + 95; + outc.appendPayloadBytes(0, 44); + if (type.val === 128) { + outc.setPayloadByte(3, 2); + data.model = 0; } - if (type.name === 'vsf') outc.setPayloadByte(4, ubyte); - } - else if (typeof type.maxCircuits !== 'undefined' && type.maxCircuits > 0 && typeof data.circuits === 'undefined') { // This pump type supports circuits and the payload did not contain them. - // Copy the data from the circuits array. That way when we call pump.set to set the data back it will be persisted correctly. - data.circuits = extend(true, {}, pump.circuits.get()); - let ubyte = 0; - for (let i = 1; i <= data.circuits.length; i++) data.circuits[i].id = i; - for (let i = 1; i <= pump.circuits.length && i <= type.maxCircuits; i++) { - let c = pump.circuits.getItemByIndex(i - 1); - let speed = c.speed; - let flow = c.flow; - let circuit = c.circuit; - if (isNaN(speed)) speed = type.minSpeed; - if (isNaN(flow)) flow = type.minFlow; - outc.setPayloadByte((i * 2) + 3, circuit, 0); - let units; - if (type.name === 'vf') units = sys.board.valueMaps.pumpUnits.getValue('gpm'); - else if (type.name === 'vs') units = sys.board.valueMaps.pumpUnits.getValue('rpm'); - else units = c.units; - if (isNaN(units)) units = sys.board.valueMaps.pumpUnits.getValue('rpm'); - c.units = units; - if (typeof type.minSpeed !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('rpm')) { - outc.setPayloadByte((i * 2) + 4, Math.floor(speed / 256)); // Set to rpm - outc.setPayloadByte(i + 21, speed % 256); - ubyte |= (1 << (i - 1)); - } - else if (typeof type.minFlow !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('gpm')) { - outc.setPayloadByte((i * 2) + 4, flow); // Set to gpm + if (typeof type.maxPrimingTime !== 'undefined' && type.maxPrimingTime > 0 && type.val >= 64) { + // We need to set all of this back to data since later pump.set is called to set the data after success. + data.primingTime = typeof data.primingTime !== 'undefined' ? isNaN(parseInt(data.primingTime, 10)) ? pump.primingTime || 0 : 0 : pump.primingTime; + data.primingSpeed = typeof data.primingSpeed !== 'undefined' ? parseInt(data.primingSpeed, 10) : pump.primingSpeed || type.minSpeed; + outc.setPayloadByte(2, data.primingTime); + outc.setPayloadByte(21, Math.floor(data.primingSpeed / 256)); + outc.setPayloadByte(30, data.primingSpeed % 256); + } + if (type.val === 1) { // Any VF pump. + // We need to set all of this back to data since later pump.set is called to set the data after success. + data.backgroundCircuit = typeof data.backgroundCircuit !== 'undefined' ? parseInt(data.backgroundCircuit, 10) : pump.backgroundCircuit || 6; + data.filterSize = typeof data.filterSize !== 'undefined' ? parseInt(data.filterSize, 10) : pump.filterSize || 15000; + data.turnovers = typeof data.turnovers !== 'undefined' ? parseInt(data.turnovers, 10) : pump.turnovers || 2; + data.manualFilterGPM = typeof data.manualFilterGPM !== 'undefined' ? parseInt(data.manualFilterGPM, 10) : pump.manualFilterGPM || 30; + data.primingSpeed = typeof data.primingSpeed !== 'undefined' ? parseInt(data.primingSpeed, 10) : pump.primingSpeed || 55; + data.primingTime = typeof data.primingTime !== 'undefined' ? parseInt(data.primingTime, 10) : pump.primingTime || 0; + data.maxSystemTime = typeof data.maxSystemTime !== 'undefined' ? parseInt(data.maxSystemTime, 10) : pump.maxSystemTime || 0; + data.maxPressureIncrease = typeof data.maxPressureIncrease != 'undefined' ? parseInt(data.maxPressureIncrease, 10) : pump.maxPressureIncrease || 0; + data.backwashFlow = typeof data.backwashFlow !== 'undefined' ? parseInt(data.backwashFlow, 10) : pump.backwashFlow || 60; + data.backwashTime = typeof data.backwashTime !== 'undefined' ? parseInt(data.bacwashTime, 10) : pump.backwashTime || 5; + data.rinseTime = typeof data.rinseTime !== 'undefined' ? parseInt(data.rinseTime, 10) : pump.rinseTime || 1; + data.vacuumFlow = typeof data.vacuumFlow !== 'undefined' ? parseInt(data.vacuumFlow, 10) : pump.vacuumFlow || 50; + data.vacuumTime = typeof data.vacuumTime !== 'undefined' ? parseInt(data.vacuumTime, 10) : pump.vacuumTime || 10; + data.model = 0; + outc.setPayloadByte(1, data.backgroundCircuit); + outc.setPayloadByte(2, data.filterSize); + outc.setPayloadByte(3, data.turnovers); + outc.setPayloadByte(21, data.manualFilterGPM); + outc.setPayloadByte(22, data.primingSpeed); + outc.setPayloadByte(23, data.primingTime | data.maxSystemTime << 4, 5); + outc.setPayloadByte(24, data.maxPressureIncrease); + outc.setPayloadByte(25, data.backwashFlow); + outc.setPayloadByte(26, data.backwashTime); + outc.setPayloadByte(27, data.rinseTime); + outc.setPayloadByte(28, data.vacuumFlow); + outc.setPayloadByte(30, data.vacuumTime); + } + if (typeof type.maxCircuits !== 'undefined' && type.maxCircuits > 0 && typeof data.circuits !== 'undefined') { // This pump type supports circuits + // Do some validation to make sure we don't have a condition where a circuit is declared twice. + let arrCircuits = []; + // Below is a very strange mess that goofs up the circuit settings. + //{id:1, circuits:[{speed:1750, units:{val:0}, id:1, circuit:6}, {speed:2100, units:{val:0}, id:2, circuit:6}]} + let ubyte = 0; + for (let i = 1; i <= data.circuits.length && i <= type.maxCircuits; i++) { + // RKS: This notion of always returning the max number of circuits was misguided. It leaves gaps in the circuit definitions and makes the pump + // layouts difficult when there are a variety of supported circuits. For instance with SF pumps you only get 4. + let c = i > data.circuits.length ? { speed: type.minSpeed || 0, flow: type.minFlow || 0, circuit: 0 } : data.circuits[i - 1]; + //{speed:1750, units:{val:0}, id:1, circuit:6} + let speed = parseInt(c.speed, 10); + let flow = parseInt(c.flow, 10); + let circuit = parseInt(c.circuit, 10); + if (isNaN(circuit)) return Promise.reject(new InvalidEquipmentDataError(`An invalid pump circuit was supplied for pump ${pump.name}. ${JSON.stringify(c)}`, 'Pump', data)) + if (isNaN(speed)) speed = type.minSpeed; + if (isNaN(flow)) flow = type.minFlow; + outc.setPayloadByte((i * 2) + 3, circuit, 0); + let units; + if (type.name === 'vf') units = sys.board.valueMaps.pumpUnits.getValue('gpm'); + else if (type.name === 'vs') units = sys.board.valueMaps.pumpUnits.getValue('rpm'); + else units = sys.board.valueMaps.pumpUnits.encode(c.units); + c.units = units; + if (isNaN(units)) units = sys.board.valueMaps.pumpUnits.getValue('rpm'); + if (typeof type.minSpeed !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('rpm')) { + outc.setPayloadByte((i * 2) + 4, Math.floor(speed / 256)); // Set to rpm + outc.setPayloadByte(i + 21, speed % 256); + c.speed = speed; + ubyte |= (1 << (i - 1)); + } + else if (typeof type.minFlow !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('gpm')) { + outc.setPayloadByte(i * 2 + 4, flow); // Set to gpm + c.flow = flow; + } + c.id = i; + c.circuit = circuit; + if (arrCircuits.includes(c.circuit)) return Promise.reject(new InvalidEquipmentDataError(`Configuration for pump ${pump.name} is not correct circuit #${c.circuit} as included more than once. ${JSON.stringify(c)}`, 'Pump', data)) + arrCircuits.push(c.circuit); } + if (type.name === 'vsf') outc.setPayloadByte(4, ubyte); } - if (type.name === 'vsf') outc.setPayloadByte(4, ubyte); + else if (typeof type.maxCircuits !== 'undefined' && type.maxCircuits > 0 && typeof data.circuits === 'undefined') { // This pump type supports circuits and the payload did not contain them. + // Copy the data from the circuits array. That way when we call pump.set to set the data back it will be persisted correctly. + data.circuits = extend(true, {}, pump.circuits.get()); + let ubyte = 0; + for (let i = 1; i <= data.circuits.length; i++) data.circuits[i].id = i; + for (let i = 1; i <= pump.circuits.length && i <= type.maxCircuits; i++) { + let c = pump.circuits.getItemByIndex(i - 1); + let speed = c.speed; + let flow = c.flow; + let circuit = c.circuit; + if (isNaN(speed)) speed = type.minSpeed; + if (isNaN(flow)) flow = type.minFlow; + outc.setPayloadByte((i * 2) + 3, circuit, 0); + let units; + if (type.name === 'vf') units = sys.board.valueMaps.pumpUnits.getValue('gpm'); + else if (type.name === 'vs') units = sys.board.valueMaps.pumpUnits.getValue('rpm'); + else units = c.units; + if (isNaN(units)) units = sys.board.valueMaps.pumpUnits.getValue('rpm'); + c.units = units; + if (typeof type.minSpeed !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('rpm')) { + outc.setPayloadByte((i * 2) + 4, Math.floor(speed / 256)); // Set to rpm + outc.setPayloadByte(i + 21, speed % 256); + ubyte |= (1 << (i - 1)); + } + else if (typeof type.minFlow !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('gpm')) { + outc.setPayloadByte((i * 2) + 4, flow); // Set to gpm + } + } + if (type.name === 'vsf') outc.setPayloadByte(4, ubyte); + } + /* return new Promise((resolve, reject) => { + outc.onComplete = (err, msg) => { + if (err) reject(err); + else { + pump = sys.pumps.getItemById(id, true); + // RKS: 05-20-22 Boooh to this if the payload does not include its + // circuits we have just destroyed the pump definition. So I added code to + // make sure that the data is complete. + pump.set(data); // Sets all the data back to the pump. + let spump = state.pumps.getItemById(id, true); + spump.name = pump.name; + spump.type = pump.type; + spump.emitEquipmentChange(); + resolve(pump); + const pumpConfigRequest = Outbound.create({ + action: 216, + payload: [pump.id], + retries: 2, + response: true + }); + conn.queueSendMessage(pumpConfigRequest); + } + }; + conn.queueSendMessage(outc); + }); */ + + + await outc.sendAsync(); } - /* return new Promise((resolve, reject) => { - outc.onComplete = (err, msg) => { - if (err) reject(err); - else { - pump = sys.pumps.getItemById(id, true); - // RKS: 05-20-22 Boooh to this if the payload does not include its - // circuits we have just destroyed the pump definition. So I added code to - // make sure that the data is complete. - pump.set(data); // Sets all the data back to the pump. - let spump = state.pumps.getItemById(id, true); - spump.name = pump.name; - spump.type = pump.type; - spump.emitEquipmentChange(); - resolve(pump); - const pumpConfigRequest = Outbound.create({ - action: 216, - payload: [pump.id], - retries: 2, - response: true - }); - conn.queueSendMessage(pumpConfigRequest); - } - }; - conn.queueSendMessage(outc); - }); */ - - - await outc.sendAsync(); pump = sys.pumps.getItemById(id, true); // RKS: 05-20-22 Boooh to this if the payload does not include its // circuits we have just destroyed the pump definition. So I added code to @@ -2221,13 +2248,15 @@ class TouchPumpCommands extends PumpCommands { spump.name = pump.name; spump.type = pump.type; spump.emitEquipmentChange(); - const pumpConfigRequest = Outbound.create({ - action: 216, - payload: [pump.id], - retries: 2, - response: true - }); - await pumpConfigRequest.sendAsync();; + if (send){ + const pumpConfigRequest = Outbound.create({ + action: 216, + payload: [pump.id], + retries: 2, + response: true + }); + await pumpConfigRequest.sendAsync(); + } return pump; } } @@ -2325,12 +2354,14 @@ class TouchHeaterCommands extends HeaterCommands { } } // RKS: Not sure what to do with this as the heater data for Touch isn't actually processed anywhere. - public async setHeaterAsync(obj: any): Promise { + public async setHeaterAsync(obj: any, send: boolean = true): Promise { if (obj.master === 1 || parseInt(obj.id, 10) > 255) return super.setHeaterAsync(obj); let id = typeof obj.id === 'undefined' ? -1 : parseInt(obj.id, 10); if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError('Heater Id is not valid.', obj.id, 'Heater')); let heater: Heater; let address: number; + let htype; + let out = Outbound.create({ action: 162, payload: [5, 0, 0], @@ -2339,7 +2370,6 @@ class TouchHeaterCommands extends HeaterCommands { // data. response: Response.create({ dest: -1, action: 34 }) }); - let htype; if (id <= 0) { // Touch only supports two installed heaters. So the type determines the id. if (sys.heaters.length > sys.equipment.maxHeaters) return Promise.reject(new InvalidEquipmentDataError('The maximum number of heaters are already installed.', 'Heater', sys.heaters.length)); @@ -2443,8 +2473,9 @@ class TouchHeaterCommands extends HeaterCommands { break; } } - - await out.sendAsync(); + if (send) { + await out.sendAsync(); + } heater = sys.heaters.getItemById(id, true); let sheater = state.heaters.getItemById(id, true); for (var s in obj) { @@ -2547,13 +2578,20 @@ class TouchHeaterCommands extends HeaterCommands { } } sys.board.valueMaps.heatSources.set(32, { name: 'nochange', desc: 'No Change' }); + // Now set the body data. + for (let i = 0; i < sys.bodies.length; i++) { + let body = sys.bodies.getItemByIndex(i); + let btemp = state.temps.bodies.getItemById(body.id, body.isActive !== false); + let opts = sys.board.heaters.getInstalledHeaterTypes(body.id); + btemp.heaterOptions = opts; + } this.setActiveTempSensors(); } } class TouchChemControllerCommands extends ChemControllerCommands { // This method is not meant to be called directly. The setChemControllerAsync method does some routing to set IntelliChem correctly // if an OCP is involved. This is the reason that the method is protected. - protected async setIntelliChemAsync(data: any): Promise { + protected async setIntelliChemAsync(data: any, send: boolean = true): Promise { try { let chem = sys.board.chemControllers.findChemController(data); @@ -2625,28 +2663,30 @@ class TouchChemControllerCommands extends ChemControllerCommands { let orpTankLevel = typeof data.orp !== 'undefined' && typeof data.orp.tank !== 'undefined' && typeof data.orp.tank.level !== 'undefined' ? parseInt(data.orp.tank.level, 10) : schem.orp.tank.level; // OCP needs to set the IntelliChem as active so it knows that it exists - let out = Outbound.create({ - action: 211, - payload: [], - retries: 3, // We are going to try 4 times. - response: Response.create({ protocol: Protocol.IntelliChem, action: 1, payload: [211] }), - onAbort: () => { } - }); - out.insertPayloadBytes(0, 0, 22); - out.setPayloadByte(0, address - 144); - out.setPayloadByte(1, Math.floor((pHSetpoint * 100) / 256) || 0); - out.setPayloadByte(2, Math.round((pHSetpoint * 100) % 256) || 0); - out.setPayloadByte(3, Math.floor(orpSetpoint / 256) || 0); - out.setPayloadByte(4, Math.round(orpSetpoint % 256) || 0); - out.setPayloadByte(5, phEnabled ? acidTankLevel + 1 : 0); - out.setPayloadByte(6, orpEnabled ? orpTankLevel + 1 : 0); - out.setPayloadByte(7, Math.floor(calciumHardness / 256) || 0); - out.setPayloadByte(8, Math.round(calciumHardness % 256) || 0); - out.setPayloadByte(9, parseInt(data.cyanuricAcid, 10), chem.cyanuricAcid || 0); - out.setPayloadByte(11, Math.floor(alkalinity / 256) || 0); - out.setPayloadByte(12, Math.round(alkalinity % 256) || 0); - out.setPayloadByte(13, Math.round(saltLevel / 50) || 20); - await out.sendAsync(); + if (send) { + let out = Outbound.create({ + action: 211, + payload: [], + retries: 3, // We are going to try 4 times. + response: Response.create({ protocol: Protocol.IntelliChem, action: 1, payload: [211] }), + onAbort: () => { } + }); + out.insertPayloadBytes(0, 0, 22); + out.setPayloadByte(0, address - 144); + out.setPayloadByte(1, Math.floor((pHSetpoint * 100) / 256) || 0); + out.setPayloadByte(2, Math.round((pHSetpoint * 100) % 256) || 0); + out.setPayloadByte(3, Math.floor(orpSetpoint / 256) || 0); + out.setPayloadByte(4, Math.round(orpSetpoint % 256) || 0); + out.setPayloadByte(5, phEnabled ? acidTankLevel + 1 : 0); + out.setPayloadByte(6, orpEnabled ? orpTankLevel + 1 : 0); + out.setPayloadByte(7, Math.floor(calciumHardness / 256) || 0); + out.setPayloadByte(8, Math.round(calciumHardness % 256) || 0); + out.setPayloadByte(9, parseInt(data.cyanuricAcid, 10), chem.cyanuricAcid || 0); + out.setPayloadByte(11, Math.floor(alkalinity / 256) || 0); + out.setPayloadByte(12, Math.round(alkalinity % 256) || 0); + out.setPayloadByte(13, Math.round(saltLevel / 50) || 20); + await out.sendAsync(); + } chem = sys.chemControllers.getItemById(data.id, true); schem = state.chemControllers.getItemById(data.id, true); chem.master = 0; @@ -2727,3 +2767,23 @@ class TouchChemControllerCommands extends ChemControllerCommands { } } } +class TouchValveCommands extends ValveCommands { + public async setValveAsync(obj: any, send: boolean = false): Promise { + try { + let id = typeof obj.id !== 'undefined' ? parseInt(obj.id, 10) : -1; + obj.master = 0; + if (isNaN(id) || id <= 0) id = Math.max(sys.valves.getMaxId(false, 49) + 1, 50); + + if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError(`EasyTouch: Valve Id has not been defined ${id}`, obj.id, 'Valve')); + let valve = sys.valves.getItemById(id, true); + // Set all the valve properies. + let vstate = state.valves.getItemById(valve.id, true); + valve.isActive = true; + valve.circuit = typeof obj.circuit !== 'undefined' ? obj.circuit : valve.circuit; + valve.name = typeof obj.name !== 'undefined' ? obj.name : valve.name; + valve.connectionId = typeof obj.connectionId ? obj.connectionId : valve.connectionId; + + return valve; + } catch (err) { logger.error(`Nixie: Error setting valve definition. ${err.message}`); return Promise.reject(err); } + } +} \ No newline at end of file diff --git a/controller/boards/SystemBoard.ts b/controller/boards/SystemBoard.ts index 7ad8f1ae..ade10707 100644 --- a/controller/boards/SystemBoard.ts +++ b/controller/boards/SystemBoard.ts @@ -1438,7 +1438,7 @@ export class SystemCommands extends BoardCommands { catch (err) { reject(err); } }); } - public async setCustomNameAsync(data: any): Promise { + public async setCustomNameAsync(data: any, send: boolean = false): Promise { return new Promise((resolve, reject) => { let id = parseInt(data.id, 10); if (isNaN(id)) return reject(new InvalidEquipmentIdError('Invalid Custom Name Id', data.id, 'customName')); @@ -1968,7 +1968,7 @@ export class PumpCommands extends BoardCommands { return this.board.valueMaps.pumpUnits.transform(val); } } - public async setPumpAsync(data: any): Promise { + public async setPumpAsync(data: any, send: boolean = true): Promise { try { let id = typeof data.id === 'undefined' ? -1 : parseInt(data.id, 10); if (id <= 0) id = sys.pumps.filter(elem => elem.master === 1).getMaxId(false, 49) + 1; @@ -2697,7 +2697,7 @@ export class CircuitCommands extends BoardCommands { return cf; } public getCircuitNames() { return [...sys.board.valueMaps.circuitNames.toArray(), ...sys.board.valueMaps.customNames.toArray()]; } - public async setCircuitAsync(data: any): Promise { + public async setCircuitAsync(data: any, send: boolean = true): Promise { try { let id = parseInt(data.id, 10); if (id <= 0 || typeof data.id === 'undefined') { @@ -2812,7 +2812,7 @@ export class CircuitCommands extends BoardCommands { }); } - public async setLightGroupAsync(obj: any): Promise { + public async setLightGroupAsync(obj: any, send: boolean = true): Promise { let group: LightGroup = null; let id = typeof obj.id !== 'undefined' ? parseInt(obj.id, 10) : -1; if (id <= 0) { @@ -3377,7 +3377,7 @@ export class ChlorinatorCommands extends BoardCommands { } catch (err) { logger.error(`Error validating chlorinators for restore: ${err.message}`); } } - public async setChlorAsync(obj: any): Promise { + public async setChlorAsync(obj: any, send: boolean = true): Promise { try { let id = parseInt(obj.id, 10); let chlor: Chlorinator; @@ -3615,7 +3615,7 @@ export class ScheduleCommands extends BoardCommands { } }; } - public async setScheduleAsync(data: any): Promise { + public async setScheduleAsync(data: any, send: boolean = true): Promise { let id = typeof data.id === 'undefined' ? -1 : parseInt(data.id, 10); if (id <= 0) id = sys.schedules.getNextEquipmentId(new EquipmentIdRange(1, sys.equipment.maxSchedules)); if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError(`Invalid schedule id: ${data.id}`, data.id, 'Schedule')); @@ -3726,7 +3726,7 @@ export class ScheduleCommands extends BoardCommands { } } catch (err) { logger.error(`Error synchronizing schedule states`); } } - public async setEggTimerAsync(data?: any): Promise { return Promise.resolve(sys.eggTimers.getItemByIndex(1)); } + public async setEggTimerAsync(data?: any, send: boolean = true): Promise { return Promise.resolve(sys.eggTimers.getItemByIndex(1)); } public async deleteEggTimerAsync(data?: any): Promise { return Promise.resolve(sys.eggTimers.getItemByIndex(1)); } public includesCircuit(sched: Schedule, circuit: number) { let bIncludes = false; @@ -4008,7 +4008,7 @@ export class HeaterCommands extends BoardCommands { heater[s] = obj[s]; } } - public async setHeaterAsync(obj: any): Promise { + public async setHeaterAsync(obj: any, send: boolean = true): Promise { try { let id = typeof obj.id === 'undefined' ? -1 : parseInt(obj.id, 10); if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError('Heater Id is not valid.', obj.id, 'Heater')); @@ -4547,7 +4547,7 @@ export class ValveCommands extends BoardCommands { else vstate.isDiverted = isDiverted; } - public async setValveAsync(obj: any): Promise { + public async setValveAsync(obj: any, send: boolean = true): Promise { try { let id = typeof obj.id !== 'undefined' ? parseInt(obj.id, 10) : -1; obj.master = 1; @@ -4989,7 +4989,7 @@ export class ChemControllerCommands extends BoardCommands { if (!isNaN(id)) return sys.chemControllers.find(x => x.id === id); else if (!isNaN(address)) return sys.chemControllers.find(x => x.address === address); } - public async setChemControllerAsync(data: any): Promise { + public async setChemControllerAsync(data: any, send: boolean = true): Promise { // The following are the rules related to when an OCP is present. // ============================================================== // 1. IntelliChem cannot be controlled/polled via Nixie, since there is no enable/disable from the OCP at this point we don't know who is in control of polling. @@ -5000,8 +5000,9 @@ export class ChemControllerCommands extends BoardCommands { // ============================================================= // 1. All chemControllers will be controlled via Nixie (IntelliChem, REM Chem). try { + let c1 = sys.chemControllers.getItemById(1); let chem = sys.board.chemControllers.findChemController(data); - let isAdd = typeof chem === 'undefined'; + let isAdd = typeof chem === 'undefined' || typeof chem.isActive === 'undefined'; let type = sys.board.valueMaps.chemControllerTypes.encode(isAdd ? data.type : chem.type); if (typeof type === 'undefined') return Promise.reject(new InvalidEquipmentDataError(`The chem controller type could not be determined ${data.type || type}`, 'chemController', type)); if (isAdd && sys.equipment.maxChemControllers <= sys.chemControllers.length) return Promise.reject(new InvalidEquipmentDataError(`The maximum number of chem controllers have been added to your controller`, 'chemController', sys.equipment.maxChemControllers)); diff --git a/controller/comms/Comms.ts b/controller/comms/Comms.ts index a30daf20..40bee78b 100755 --- a/controller/comms/Comms.ts +++ b/controller/comms/Comms.ts @@ -54,6 +54,12 @@ export class Connection { return cfg; } catch (err) { logger.error(`Error deleting aux port`) } } + public async setScreenlogicAsync(data: any){ + let ccfg = config.getSection('controller.screenlogic'); + if (typeof data.type === 'undefined' || data.type !== 'local' || data.type !== 'remote' ) return Promise.reject(new InvalidEquipmentDataError(`Invalid Screenlogic type (${data.type}). Allowed values are 'local' or 'remote'`, 'Screenlogic', 'screenlogic')); + if ((data.address as string).slice(8) !== 'Pentair:') return Promise.reject(new InvalidEquipmentDataError(`Invalid address (${data.address}). Must start with 'Pentair:'`, 'Screenlogic', 'screenlogic')); + } + public async setPortAsync(data: any): Promise { try { let ccfg = config.getSection('controller'); @@ -826,7 +832,8 @@ export class RS485Port { } } // make public for now; should enable writing directly to mock port at Conn level... - public pushIn(pkt:Buffer) { this._inBuffer.push.apply(this._inBuffer, pkt.toJSON().data); if (sys.isReady) setImmediate(() => { this.processPackets(); }); } + public pushIn(pkt:Buffer) { + this._inBuffer.push.apply(this._inBuffer, pkt.toJSON().data); if (sys.isReady) setImmediate(() => { this.processPackets(); }); } private pushOut(msg) { this._outBuffer.push(msg); setImmediate(() => { this.processPackets(); }); } diff --git a/controller/comms/ScreenLogic.ts b/controller/comms/ScreenLogic.ts index a57dc669..27152add 100644 --- a/controller/comms/ScreenLogic.ts +++ b/controller/comms/ScreenLogic.ts @@ -1,98 +1,240 @@ -import { ControllerType } from '../../controller/Constants'; -import { sys } from '../../controller/Equipment'; -import { state } from '../../controller/State'; +import { ControllerType, utils } from '../../controller/Constants'; +import { LightGroup, LightGroupCircuit, sys, Valve } from '../../controller/Equipment'; +import { CircuitState, state, ValveState } from '../../controller/State'; import * as ScreenLogic from 'node-screenlogic'; +import { SLControllerConfigData, SLEquipmentConfigurationData, Valves, type HeaterConfig } from 'node-screenlogic/dist/messages/state/EquipmentConfig'; +import { EasyTouchBoard } from '../../controller/boards/EasyTouchBoard'; +import { IntelliTouchBoard } from '../../controller/boards/IntelliTouchBoard'; +import { logger } from '../../logger/Logger'; +import { SLSystemTimeData } from 'node-screenlogic/dist/messages/state/EquipmentConfig'; +import { SLIntellichlorData } from 'node-screenlogic/dist/messages/state/ChlorMessage'; +import { SLChemData } from 'node-screenlogic/dist/messages/state/ChemMessage'; +import { SLScheduleData } from 'node-screenlogic/dist/messages/state/ScheduleMessage'; +import { webApp } from '../../web/Server'; +import { SLPumpStatusData } from 'node-screenlogic/dist/messages/state/PumpMessage'; +import { delayMgr } from '../../controller/Lockouts'; +import { SLEquipmentStateData } from 'node-screenlogic/dist/messages/state/EquipmentState'; +import { config } from '../../config/Config'; +import { InvalidEquipmentDataError, InvalidEquipmentIdError } from '../../controller/Errors'; +import extend = require('extend'); -export class ScreenLogicComms { - constructor() { }; +// Todo - service, timeout? + +export class ScreenLogicComms { + constructor() { + this._client = ScreenLogic.screenlogic; + }; + public counter: SLCounter = new SLCounter(); + private _gateway: ScreenLogic.RemoteLogin; + private _client: ScreenLogic.UnitConnection; + private _pollTimer: NodeJS.Timeout; + public circuits: SLCircuits; + private _pollCountError: number = 0; + public isOpen: boolean = false; + private _cfg: any; + private pollingInterval = 10000; + public enabled: boolean = false; - public async connectAsync() { + public async initAsync() { + this.circuits = new SLCircuits(this._client); + let cfg = config.getSection('controller.screenlogic'); + if (typeof cfg !== 'undefined') this._cfg = cfg; + this.enabled = this._cfg.enabled; + if (!this._cfg.enabled) { + return; + } - const systemName = 'Pentair: 00-45-F4'; - const password = '1111'; + let systemName = this._cfg.systemName; // 'Pentair: 00-00-00'; + let password = this._cfg.password; // '1111'; - let gateway = new ScreenLogic.RemoteLogin(systemName); - var unit = await gateway.connect(); + this._gateway = new ScreenLogic.RemoteLogin(systemName); + this._gateway.on('error', async (err) => { + logger.error(`Screenlogic Gateway Error: ${err.message}`); + this.isOpen = false; + await this._gateway.closeAsync(); + return Promise.resolve(false); + }) + let unit = await this._gateway.connect(); if (!unit || !unit.gatewayFound || unit.ipAddr === '') { - console.log('no unit found by that name'); + logger.error(`Screenlogic: No unit found called ${systemName}`); + this.isOpen = false; return; } - console.log('unit ' + gateway.systemName + ' found at ' + unit.ipAddr + ':' + unit.port); - let client = ScreenLogic.screenlogic + await this._gateway.closeAsync(); + this.isOpen = true; + logger.info(`Screenlogic: Unit ${this._gateway.systemName} found at ${unit.ipAddr}:${unit.port}`); + let delayCount = 0; + state.status = sys.board.valueMaps.controllerStatus.transform(0, 0); + state.emitControllerChange(); try { - client.init(unit.ipAddr, unit.port, password, 12345); - await client.connect(); - let addClient = await client.addClient(); + this._client.init(unit.ipAddr, unit.port, password, Math.min(Math.max(1, Math.trunc(Math.random() * 10000)), 10000)); // fix - can remove senderid with next push - will be assigned randomly + await this._client.connectAsync(); + let ver = await this._client.getVersionAsync(); + logger.info(`Screenlogic: connect to ${systemName} ${ver} at ${unit.ipAddr}:${unit.port}`); + let addClient = await this._client.addClientAsync(); console.log(`Add client result: ${addClient}`); - // let controller = await client.equipment.getControllerConfig(); - // console.log(`Controller: ${JSON.stringify(controller,null,2)}`); - let controller = await client.equipment.getControllerConfig(); - console.log(`Controller: ${JSON.stringify(controller,null,2)}`); - let equipConfig = await client.equipment.getEquipmentConfiguration(); - console.log(`Equipment config: ${JSON.stringify(equipConfig,null,2)}`); - let equipmentState = await client.equipment.getEquipmentState(); - console.log(`Equipment State: ${JSON.stringify(equipmentState,null,2)}`); - - let combined = { - equipConfig, - equipmentState + + let customNames = await this._client.equipment.getCustomNamesAsync(); + console.log(customNames); + let equipConfig = await this._client.equipment.getEquipmentConfigurationAsync(); + console.log(`Equipment config: ${JSON.stringify(equipConfig, null, 2)}`); + await Controller.decodeEquipment(equipConfig); + let controller = await this._client.equipment.getControllerConfigAsync(); + await Controller.decodeCustomNames(customNames); + console.log(`Controller: ${JSON.stringify(controller, null, 2)}`); + await Controller.decodeController(controller); + let systemTime = await this._client.equipment.getSystemTimeAsync(); + // console.log(`System Time: ${JSON.stringify(systemTime)}`) + Controller.decodeDateTime(systemTime); + // PUMPS + let pumpArr = sys.pumps.get(); + for (let i = 0; i < pumpArr.length; i++){ + let pumpStatus = await this._client.pump.getPumpStatusAsync(i); + console.log(`Pump ${i+1}: ${JSON.stringify(pumpStatus)}`); + await Controller.decodePump(i+1, pumpStatus); } + // pumpStatus = await client.pump.getPumpStatus(1); + // console.log(`Pump 21 ${JSON.stringify(pumpStatus)}`); + let recurringSched = await this._client.schedule.getScheduleDataAsync(0); + console.log(`reccuring schedules: ${JSON.stringify(recurringSched)}`); + + let runOnceSched = await this._client.schedule.getScheduleDataAsync(1); + console.log(`Run once schedules: ${JSON.stringify(runOnceSched)}`); + await Controller.decodeSchedules(recurringSched, runOnceSched); + + let intellichlor = await this._client.chlor.getIntellichlorConfigAsync(); + // console.log(`Intellichlor: ${JSON.stringify(intellichlor)}`); + await Controller.decodeIntellichlor(intellichlor); + let chem = await this._client.chem.getChemicalDataAsync(); + console.log(`Chem data: ${JSON.stringify(chem)}`); + await Controller.decodeChemController(chem); + + let equipmentState = await this._client.equipment.getEquipmentStateAsync(); + console.log(equipmentState); + await Controller.decodeEquipmentState(equipmentState); + // state.mode = 0; + // webApp.emitToClients('panelMode', { mode: state.mode, remaining: 0 }); + state.status = sys.board.valueMaps.controllerStatus.transform(1, 100); + sys.board.circuits.syncVirtualCircuitStates() + state.emitControllerChange(); + + this._client.on('equipmentState', async function (data) { await Controller.decodeEquipmentState(data); }) + this._client.on('intellichlorConfig', async function (data) { + await Controller.decodeIntellichlor(data); + }); + this._client.on('equipmentConfig', async function (data) { + await Controller.decodeEquipment(data); + }); + this._client.on('chemicalData', async function (data) { + await Controller.decodeChemController(data); + + }); + this._client.on('getSystemTime', async function (data) { + Controller.decodeDateTime(data); + }); + //client.on('getScheduleData', async function(){await Controller.decodeSchedules(recurringSched, runOnceSched);}); // how do we know if this is recurring or runonce? Investigate. + this._client.on('cancelDelay', async function (data) { + console.log(`cancelDelay: ${data}`) + }) // not programmed yet}); + this._client.on('equipmentConfiguration', async function (data) { + console.log(`equipConfig ${data}`) + })// which one?}); + this._client.on('getPumpStatus', async function (data) { + console.log(`getPumpStatus: ${JSON.stringify(data)}`); + // await Controller.decodePump(1, pumpStatus); + }); // how do we know which pump id? Investigate. + this._client.on('weatherForecast', async function (data) { + console.log(`weatherforecast: ${JSON.stringify(data)}`) + }); + this._client.on('circuitStateChanged', async function (data) { + console.log(`circuitstatechanged: ${JSON.stringify(data)}`) + }); + this._client.on('setPointChanged', async function (data) { + console.log(`setpointchanged: ${JSON.stringify(data)}`) + }); + + // not working + + this._client.on('heatModeChanged', async function (data) { + console.log(`heat mode changed: ${JSON.stringify(data)}`); + }); + this._client.on('intellibriteDelay', async function (data) { + console.log(`intellibrite delay: ${JSON.stringify(data)}`) + }); + this._client.on('weatherForecastChanged', async function () { + console.log(`weather forecast changed}`); + // found - no data returned; need to request data + }); + // No data comes through... maybe need to request weather data again? + this._client.on('scheduleChanged', async function (data) { + console.log(`schedule changed: ${JSON.stringify(data)}`); + let recurringSched = await this._client.schedule.getScheduleData(0); + console.log(`reccuring schedules: ${JSON.stringify(recurringSched)}`); + let runOnceSched = await this._client.schedule.getScheduleData(1); + console.log(`Run once schedules: ${JSON.stringify(runOnceSched)}`); + await Controller.decodeSchedules(recurringSched, runOnceSched); + }); + this._client.on('error', (e) => { + // if the error event from the net.socket isn't caught, it sometimes crashes the app. + logger.error(`Screenlogic error (net.socket): ${e.message}`); + }) + this._client.on('clientError', (e) => { + // if the error event from the net.socket isn't caught, it sometimes crashes the app. + logger.error(`Screenlogic client error (net.socket): ${e.message}`); + }) + this._client.on('loginFailed', (data) => { + logger.error(`Screenlogic login failed. Invalid password.`); + this.isOpen = false; + }) + this._client.on('bytesRead', (bytes) => { + console.log(`SL Bytes Read: ${bytes}`); + this.counter.bytesReceived += bytes; + this.emitScreenlogicStats(); + }); + this._client.on('bytesWritten', (bytes) => { + console.log(`SL Bytes written: ${bytes}`); + this.counter.bytesSent += bytes; + this.emitScreenlogicStats(); + }); + this.pollAsync(); + // console.log(`Equipment State: ${JSON.stringify(equipmentState, null, 2)}`); /* // EQUIPMENT - let equipmentState = await client.equipment.getEquipmentState(); - console.log(`Equipment State: ${JSON.stringify(equipmentState)}`); - let result = await client.getVersion(); - console.log(`Pool Version: ${result}`); - let controller = await client.equipment.getControllerConfig(); - console.log(`Controller: ${JSON.stringify(controller)}`); - let equipConfig = await client.equipment.getEquipmentConfiguration(); - console.log(`Equipment config: ${JSON.stringify(equipConfig)}`); + + let cancelDelay = await client.equipment.cancelDelay(); console.log(`Cancel delay: ${cancelDelay}`); let weatherForecast = await client.equipment.getWeatherForecast(); console.log(`Weather: ${JSON.stringify(weatherForecast)}`); - let systemTime = await client.equipment.getSystemTime(); - console.log(`System Time: ${JSON.stringify(systemTime)}`) - let dt = systemTime.date; - dt.setHours(12); let sysTime = await screenlogic.equipment.setSystemTime(dt, true); console.log(`set time result: ${sysTime}`); let hist = await screenlogic.equipment.getHistoryData() console.log(`history data: ${JSON.stringify(hist)}`) - + // CHLOR - let intellichlor = await client.chlor.getIntellichlorConfig(); - console.log(`Intellichlor: ${JSON.stringify(intellichlor)}`); let chlorOutput = await client.chlor.setIntellichlorOutput(12,0); console.log(`Chlor output: ${JSON.stringify(chlorOutput)}`) - + // CHEM - let chem = await client.chem.getChemicalData(); - console.log(`Chem data: ${JSON.stringify(chem)}`); let chemHist = await screenlogic.chem.getChemHistoryData() console.log(`history data: ${JSON.stringify(chemHist)}`) - + // SCHEDULES - let recurringSched = await client.schedule.getScheduleData(0); - console.log(`reccuring schedules: ${JSON.stringify(recurringSched)}`); - let runOnceSched = await client.schedule.getScheduleData(1); - console.log(`Run once schedules: ${JSON.stringify(runOnceSched)}`); + let addSched = await client.schedule.addNewScheduleEvent(SchedTypes.RECURRING); console.log(`Add sched response: ${addSched}`); let setSched = await client.schedule.setScheduleEventById(10, 2,500,1200,127,0,1,99); console.log(`Set sched result: ${setSched}`); let delSched = await client.schedule.deleteScheduleEventById(10); console.log(`Deleted sched result: ${delSched}`); - + // PUMPS - let pumpStatus = await client.pump.getPumpStatus(0); - console.log(`Pump 0: ${JSON.stringify(pumpStatus)}`); - let pumpRes = await client.pump.setPumpSpeed(0,1,2000,true); - console.log(`Pump speed response: ${pumpRes}`) + // let pumpRes = await client.pump.setPumpSpeed(0,1,2000,true); + // console.log(`Pump speed response: ${pumpRes}`) // BODIES let setPointChanged = await client.bodies.setSetPoint(1, 101) @@ -103,276 +245,761 @@ export class ScreenLogicComms { // CIRCUITS let lightRes = await client.circuits.sendLightCommand(LightCommands.LIGHT_CMD_COLOR_MODE_PARTY); console.log(`Light result: ${lightRes}`); - // NOT WORKING... - let cstate = await client.circuits.setCircuitState(3, true); - console.log(`Circuit state: ${JSON.stringify(cstate)}`); + // let circRun = await client.circuits.setCircuitRuntimebyId(4, 5); console.log(`circ run res: ${circRun}`); */ - setTimeout(async () => { - console.log(`closing connection after 60s`); - await client.close(); - }, 60 * 1000) - console.log(`Waiting 60s.`) + // setTimeout(async () => { + // console.log(`closing connection after 60s`); + // await client.closeAsync(); + // }, 120 * 1000) + // let close = await client.closeAsync(); + // console.log(`client closed: ${close}`); } catch (error) { - console.log(`Error: ${error.message}`); - client.close(); + logger.error(`Screenlogic error: ${error.message}`); + await this._client.closeAsync(); + return Promise.resolve(error); } } + public async stopAsync() { + await this._client.closeAsync(); + this._client.removeAllListeners(); + this.isOpen = false; + if (typeof this._pollTimer !== 'undefined') clearTimeout(this._pollTimer); + this._pollTimer = null; + } + public async setScreenlogicAsync(data) { + let enabled = typeof data.enabled !== 'undefined' ? utils.makeBool(data.enabled) : false; + let systemName = typeof data.systemName !== 'undefined' ? data.systemName : this._cfg.systemName; + let password = typeof data.password !== 'undefined' ? data.password : this._cfg.password; + let regx = /Pentair: (?:(?:\d|[A-Z])(?:\d|[A-Z])-){2}(?:\d|[A-Z])(?:\d|[A-Z])/g; + let type = typeof data.type !== 'undefined' ? data.type : this._cfg.type; + if (type !== 'remote' && type !== 'local') return Promise.reject(new InvalidEquipmentDataError(`An invalid type was supplied for Screenlogic ${type}. Must be remote or local.`, 'Screenlogic', data)); + if (systemName.match(regx) === null) return Promise.reject(new InvalidEquipmentDataError(`An invalid system name was supplied for Screenlogic ${systemName}}. Must be in the format 'Pentair: xx-xx-xx'.`, 'Screenlogic', data)); + if (password.length > 4) return Promise.reject(new InvalidEquipmentDataError(`An invalid password was supplied for Screenlogic ${password}. (Length must be <= 4)}`, 'Screenlogic', data)); + this.enabled = enabled; + if (this._cfg.enabled && !enabled || this._cfg.systemName !== systemName || this._cfg.password !== password || this._cfg.cype !== type) { + await this.stopAsync(); + } + let obj = { + enabled, + type, + systemName, + password + } + config.setSection('controller.screenlogic', obj); + this._cfg = config.getSection('controller.screenlogic'); + if (this._cfg.enabled) { + let error = await this.initAsync(); + if (typeof error !== 'undefined') return Promise.reject(error); + } + } + public async pollAsync() { + let self = this; + try { + if (typeof this._pollTimer !== 'undefined' || this._pollTimer) clearTimeout(this._pollTimer); + this._pollTimer = null; + if (!this.isOpen) { return; }; + let numPumps = sys.pumps.get().length; + for (let i = 1; i < numPumps + 1; i++) { + let pumpStatus = await self._client.pump.getPumpStatusAsync(i - 1); + console.log(`Pump ${i}: ${JSON.stringify(pumpStatus)}`); + await Controller.decodePump(i, pumpStatus); + } + } + catch (err) { + logger.error(`Error polling screenlogic (${this._pollCountError} errors)- ${err}`); this._pollCountError++; + if (this._pollCountError > 10) { + await this.initAsync(); + } + } + finally { this._pollTimer = setTimeout(async () => await self.pollAsync(), this.pollingInterval || 10000); } + } + public static async searchAsync() { + try { + `` + let finder = new ScreenLogic.FindUnits(); + let localUnit = await finder.searchAsync(); + return Promise.resolve(localUnit); + } + catch (err) { + logger.error(`Screenlogic: Error searching for units: ${err.message}`); + return Promise.reject(err); + } + } + public get stats() { + let status = this.isOpen ? 'open' : this._cfg.enabled ? 'closed' : 'disabled'; + let socketStatus = this._client.status(); + return extend(true, { status: status }, this.counter, socketStatus); + } + public emitScreenlogicStats() { + webApp.emitToChannel('screenlogicStats', 'screenlogicStats', this.stats); + } } class Controller { - public decodeConfig(config: SLControllerConfigData) { - + public static async decodeController(config: SLControllerConfigData) { + sys.general.options.units = state.temps.units = config.degC ? sys.board.valueMaps.tempUnits.getValue('C') : sys.board.valueMaps.tempUnits.getValue('F'); + let lightGroup: any = { circuits: [] }; + let lgCircId = 1; + for (let i = 0; i < config.circuitArray.length; i++) { + let _circ = config.circuitArray[i]; + let data: any = { + id: _circ.circuitId, + type: _circ.function, + nameId: _circ.nameIndex < 101 ? _circ.nameIndex + 1 : _circ.nameIndex + 99, // custom names are 100 off from the rs485 packets + // name: _circ.name, // determined from id + // cstate.isActive = circuit.isActive = true, // added by setCircuitAsync + freeze: _circ.freeze, + eggTimer: _circ.eggTimer, + showInFeatures: _circ.interface !== 4 && _circ.interface !== 5, // 0 = pool; 1 = spa; 2 = features; 4 = lights; 5 = hide - } - public decodeEquipment(equip: SLEquipmentConfigurationData) { - if (sys.controllerType !== ControllerType.EasyTouch && this.isEasyTouch(equip.controllerType)) { - sys.controllerType = ControllerType.EasyTouch; + } + if (_circ.function === 5) { + let lgCirc = { + color: _circ.colorSet, + swimDelay: _circ.colorStagger, + position: _circ.colorPos, + id: lgCircId, + ...data + } + lgCircId++; + lightGroup.circuits.push(lgCirc, false); + } + await sys.board.circuits.setCircuitAsync(data, false); + } + if (lightGroup.circuits.length === 0) { + sys.lightGroups.removeItemById(192); + state.lightGroups.removeItemById(192); } - else if (sys.controllerType !== ControllerType.IntelliTouch && this.isIntelliTouch(equip.controllerType)) { - sys.controllerType = ControllerType.IntelliTouch; + else { + lightGroup.id = 192; + await sys.board.circuits.setLightGroupAsync(lightGroup, false); } + // now go back through and remove and circuits that aren't in the received list + let circuits = sys.circuits.get(); + for (let i = 0; i < circuits.length; i++) { + let circuit = sys.circuits.getItemById(circuits[i].id); + let _circ = config.circuitArray.find(el => { return el.circuitId === circuit.id }); + if (typeof _circ === 'undefined') { + sys.circuits.removeItemById(circuit.id); + state.circuits.removeItemById(circuit.id); + } + } + let features = sys.features.get(); + for (let i = 0; i < features.length; i++) { + let feature = sys.features.getItemById(features[i].id); + let _circ = config.circuitArray.find(el => { return el.circuitId === feature.id }); + if (typeof _circ === 'undefined') { + sys.features.removeItemById(feature.id); + state.features.removeItemById(feature.id); + } + } - this.decodeHeaters(equip.heaterConfig) - } - public decodeHeaters(heaterConfig: HeaterConfig) { - let hasHeatpump: boolean; - if (heaterConfig.thermaFloCoolPresent) { - sys.heaters.removeItemById(1); - state.heaters.removeItemById(1); - sys.heaters.removeItemById(2); - state.heaters.removeItemById(2); - sys.heaters.removeItemById(3); - state.heaters.removeItemById(3); - let hybrid = sys.heaters.getItemById(4, true); - let shybrid = state.heaters.getItemById(4, true); - // [5, { name: 'hybrid', desc: 'Hybrid', hasAddress: true }], - shybrid.type = hybrid.type = 5; - hybrid.address = 112; // Touch only supports address 1. - hybrid.isActive = true; - hybrid.master = 0; - hybrid.body = sys.equipment.shared ? 32 : 0; - if (typeof hybrid.name === 'undefined') shybrid.name = hybrid.name = 'UltraTemp ETi'; - // The following 2 values need to come from somewhere. - if (typeof hybrid.economyTime === 'undefined') hybrid.economyTime = 1; - if (typeof hybrid.maxBoostTemp === 'undefined') hybrid.maxBoostTemp = 5; - hasHeatpump = false; // You cannot have a heatpump and a hybrid heater. + /* if (config.equipment.POOL_CHLORPRESENT) { + let chlor = sys.chlorinators.getItemById(1, true); + let chlorState = state.chlorinators.getItemById(1, true); + chlorState.isActive = chlor.isActive = true; + } + else { + sys.chlorinators.removeItemById(1); + state.chlorinators.removeItemById(1); + }; */ + if (config.equipment.POOL_IFLOWPRESENT0) { + let pump = sys.pumps.getItemById(1, true); + let sPump = state.pumps.getItemById(1, true); + sPump.isActive = pump.isActive = true; } else { - // Hybrid heaters and gas heaters cannot co-exist but it appears you cannot disable the gas - // heater on the touch panels. - sys.heaters.removeItemById(4); - state.heaters.removeItemById(4); - let heater = sys.heaters.getItemById(1, true); - let hstate = state.heaters.getItemById(1, true); - heater.body = sys.equipment.shared ? 32 : 0; - // [1, { name: 'gas', desc: 'Gas Heater', hasAddress: false }], - heater.type = hstate.type = 1; - heater.isActive = true; - heater.master = 0; - if (typeof heater.name === 'undefined') heater.name = hstate.name = 'Gas Heater'; - if (typeof heater.cooldownDelay === 'undefined') heater.cooldownDelay = 5; - } - // Check to see if a heatpump is installed. This will replace the solar heater so they cannot coexist. - if (hasHeatpump) { - // Remove the solar heater. This will be replaced with the heatpump. - sys.heaters.removeItemById(2); - state.heaters.removeItemById(2); - let heatpump = sys.heaters.getItemById(3, true); - let sheatpump = state.heaters.getItemById(3, true); - // [3, { name: 'heatpump', desc: 'Heat Pump', hasAddress: true, hasPreference: true }], - heatpump.type = sheatpump.type = 3; - heatpump.body = sys.equipment.shared ? 32 : 0; - heatpump.isActive = true; - heatpump.master = 0; - - if (typeof heatpump.name === 'undefined') sheatpump.name = heatpump.name = 'UltraTemp'; - // heatpump.heatingEnabled = (msg.extractPayloadByte(1) & 0x01) === 1; - // heatpump.coolingEnabled = (msg.extractPayloadByte(1) & 0x02) === 2; - sys.board.equipmentIds.invalidIds.add(20); // exclude Aux Extra - } - else if (heaterConfig.poolSolarPresent) { - sys.heaters.removeItemById(3); - state.heaters.removeItemById(3); - let solar = sys.heaters.getItemById(2, true); - let ssolar = sys.heaters.getItemById(2, true); - // [2, { name: 'solar', desc: 'Solar Heater', hasAddress: false, hasPreference: true }], - solar.type = ssolar.type = 2; - solar.body = sys.equipment.shared ? 32 : 0; - solar.isActive = true; - solar.master = 0; - if (typeof solar.name === 'undefined') solar.name = ssolar.name = 'Solar Heater'; - // solar.freeze = (msg.extractPayloadByte(1) & 0x80) >> 7 === 1; - // solar.coolingEnabled = (msg.extractPayloadByte(1) & 0x20) >> 5 === 1; - // solar.startTempDelta = ((msg.extractPayloadByte(2) & 0xE) >> 1) + 3; - // solar.stopTempDelta = ((msg.extractPayloadByte(2) & 0xC0) >> 6) + 2; - sys.board.equipmentIds.invalidIds.add(20); // exclude Aux Extra + sys.pumps.removeItemById(1); + state.pumps.removeItemById(1); + }; + if (config.equipment.POOL_IFLOWPRESENT1) { + let pump = sys.pumps.getItemById(2, true); + let sPump = state.pumps.getItemById(2, true); + sPump.isActive = pump.isActive = true; } else { - sys.board.equipmentIds.invalidIds.remove(20); // Allow access to Aux Extra + sys.pumps.removeItemById(2); + state.pumps.removeItemById(2); + }; + if (config.equipment.POOL_IFLOWPRESENT2) { + let pump = sys.pumps.getItemById(3, true); + let sPump = state.pumps.getItemById(3, true); + sPump.isActive = pump.isActive = true; } - } + else { + sys.pumps.removeItemById(3); + state.pumps.removeItemById(3); + }; + if (config.equipment.POOL_IFLOWPRESENT3) { + let pump = sys.pumps.getItemById(4, true); + let sPump = state.pumps.getItemById(4, true); + sPump.isActive = pump.isActive = true; + } + else { + sys.pumps.removeItemById(4); + state.pumps.removeItemById(4); + }; + if (config.equipment.POOL_IFLOWPRESENT4) { + let pump = sys.pumps.getItemById(5, true); + let sPump = state.pumps.getItemById(5, true); + sPump.isActive = pump.isActive = true; + } + else { + sys.pumps.removeItemById(5); + state.pumps.removeItemById(5); + }; + if (config.equipment.POOL_IFLOWPRESENT5) { + let pump = sys.pumps.getItemById(6, true); + let sPump = state.pumps.getItemById(6, true); + sPump.isActive = pump.isActive = true; + } + else { + sys.pumps.removeItemById(6); + state.pumps.removeItemById(6); + }; + if (config.equipment.POOL_IFLOWPRESENT6) { + let pump = sys.pumps.getItemById(7, true); + let sPump = state.pumps.getItemById(7, true); + sPump.isActive = pump.isActive = true; + } + else { + sys.pumps.removeItemById(7); + state.pumps.removeItemById(7); + }; + if (config.equipment.POOL_IFLOWPRESENT7) { + let pump = sys.pumps.getItemById(8, true); + let sPump = state.pumps.getItemById(8, true); + sPump.isActive = pump.isActive = true; + } + else { + sys.pumps.removeItemById(8); + state.pumps.removeItemById(8); + }; - isEasyTouch(controllerType) { - return controllerType === 14 || controllerType === 13; + /* // deal with these in other places + if (config.equipment.POOL_NO_SPECIAL_LIGHTS) { }; // ?? Nothing to see here? + if (config.equipment.POOL_MAGICSTREAMPRESENT) { }; // Ya, so what? + if (config.equipment.POOL_IBRITEPRESENT) { }; + // set in equip message + if (config.equipment.POOL_SOLARPRESENT) { }; + if (config.equipment.POOL_SOLARHEATPUMP) { }; + if (config.equipment.POOL_HEATPUMPHASCOOL) { }; + if (config.equipment.POOL_ICHEMPRESENT) { }; */ } - - isIntelliTouch(controllerType) { - return controllerType !== 14 && controllerType !== 13 && controllerType !== 10; + public static async decodeEquipmentState(eqstate: SLEquipmentStateData) { + /* + { + ok: 0, + freezeMode: 0, + remotes: 32, + poolDelay: 0, + spaDelay: 0, + cleanerDelay: 0, + airTemp: 67, + bodiesCount: 2, + bodies: [ + { + id: 1, + currentTemp: 62, + heatStatus: 0, + setPoint: 79, + coolSetPoint: 0, + heatMode: 0 + }, + { + id: 2, + currentTemp: 64, + heatStatus: 0, + setPoint: 101, + coolSetPoint: 67, + heatMode: 3 + } + ], + circuitArray: [ + { + id: 1, + state: 0, + colorSet: 0, + colorPos: 0, + colorStagger: 0, + delay: 0 + }, + ... + ], + pH: 0, + orp: 0, + saturation: 0, + saltPPM: 0, + pHTank: 0, + orpTank: 0, + alarms: 0 } + */ + try { + /* public boolean isDeviceready() { + return this.m_Ok == 1; + } + + public boolean isDeviceSync() { + return this.m_Ok == 2; + } + + public boolean isDeviceServiceMode() { + return this.m_Ok == 3; + } */ + if (eqstate.ok === 1) { + state.mode = 0; // ready + state.status = sys.board.valueMaps.controllerStatus.transform(1); + } + else if (eqstate.ok === 2) { + // syncronizing... + state.mode = 0; + state.status = sys.board.valueMaps.controllerStatus.transform(2); + } + else if (eqstate.ok === 3) { + // service mode + state.mode = 1; + state.status = sys.board.valueMaps.controllerStatus.transform(1); + } + if (eqstate.freezeMode) { + state.mode = state.mode === 1 ? 1 : 8; + state.freeze = true; + } + else { + state.freeze = false; + } - isEasyTouchLite(controllerType, hwType) { - return controllerType === 13 && (hwType & 4) !== 0; + // set delays + if (eqstate.cleanerDelay) { + let cleaner: CircuitState = state.circuits.find(elem => elem.type === 5); + let bodyIsOn = state.temps.bodies.getBodyIsOn(); + let bodyId = bodyIsOn.circuit === 6 ? 1 : 2; + delayMgr.setCleanerStartDelay(cleaner, bodyId, 60); + } + if (eqstate.poolDelay) { delayMgr.setManualPriorityDelay(state.circuits.getItemById(6)) }; + if (eqstate.spaDelay) { delayMgr.setManualPriorityDelay(state.circuits.getItemById(1)) }; + state.temps.air = eqstate.airTemp; + for (let i = 0; i < eqstate.bodies.length; i++) { + let slbody = eqstate.bodies[i]; + let tbody = state.temps.bodies.getItemById(i + 1); + tbody.setPoint = slbody.setPoint; + tbody.heatMode = slbody.heatMode; // FIX - Heat mode and set point not working??? + tbody.heatStatus = slbody.heatStatus; + } + for (let i = 0; i < eqstate.circuitArray.length; i++) { + let slcirc = eqstate.circuitArray[i]; + let cstate = state.circuits.getInterfaceById(slcirc.id); + let slcircIsOn = utils.makeBool(slcirc.state); + if (cstate.isOn !== slcircIsOn) { + sys.board.circuits.setEndTime(sys.circuits.getItemById(cstate.id), cstate, slcircIsOn); + cstate.isOn = slcircIsOn; + if (cstate.id === 1 || cstate.id === 6) { + let tbody = state.temps.bodies.getBodyByCircuitId(cstate.id); + tbody.isOn = slcircIsOn; + } + } + if (slcirc.delay) { + // ?? + } + } + let schem = state.chemControllers.getItemById(1); + if (schem.isActive) { + /* pH: 0, + orp: 0, + saturation: 0, + saltPPM: 0, + pHTank: 0, + orpTank: 0, + alarms: 0 */ + let address = 144; + let chem = sys.chemControllers.getItemByAddress(address, true); + let schem = state.chemControllers.getItemById(chem.id, true); + schem.orp.level = eqstate.orp; + schem.saturationIndex = eqstate.saturation; + schem.ph.tank.level = eqstate.pHTank; + schem.orp.tank.level = eqstate.orpTank; + // saltPPM ==> set by intellichlor msg + // schem.alarms. ==> Need alarm mapping... + webApp.emitToClients('chemController', schem.getExtended()); // emit extended data + } + state.emitControllerChange(); + state.emitEquipmentChanges(); + } catch(err) { + logger.error(`Caught error in decodeEquipmentState: ${err.message}`); } +} + public static async decodeCustomNames(customNames: string[]) { + for (let i = 0; i < sys.equipment.maxCustomNames; i++) { + let data = { + id: i, + name: customNames[i] + } + try { - isDualBody(controllerType) { - return controllerType === 5; + await sys.board.system.setCustomNameAsync(data, false) + } + catch (err) { + logger.error(`Error setting custom name ${JSON.stringify(data)}`); + }; } } + public static async decodeEquipment(equip: SLEquipmentConfigurationData) { + if (sys.controllerType !== ControllerType.EasyTouch && Controller.isEasyTouch(equip.controllerType)) { + sys.controllerType = ControllerType.EasyTouch; + (sys.board as EasyTouchBoard).initExpansionModules(equip.controllerType, equip.hardwareType); + } + else if (sys.controllerType !== ControllerType.IntelliTouch && Controller.isIntelliTouch(equip.controllerType)) { + sys.controllerType = ControllerType.IntelliTouch; + (sys.board as IntelliTouchBoard).initExpansionModules(equip.controllerType, equip.hardwareType); + } -export let sl = new ScreenLogicComms(); -export interface SLEquipmentStateData { - ok: number; - freezeMode: number; - remotes: number; - poolDelay: number; - spaDelay: number; - cleanerDelay: number; - airTemp: number; - bodiesCount: number; - bodies: {}[], - currentTemp: any[]; - heatStatus: any[]; - setPoint: any[]; - coolSetPoint: any[]; - heatMode: any[]; - circuitArray: any[]; - pH: number; - orp: number; - saturation: number; - saltPPM: number; - pHTank: number; - orpTank: number; - alarms: number; + await Controller.decodeHeaters(equip.heaterConfig); + await Controller.decodeValves(equip.valves); + sys.general.options.pumpDelay = equip.delays.pumpOffDuringValveAction; + if (equip.delays.poolPumpOnDuringHeaterCooldown) { + for (let i = 0; i < sys.bodies.length; i++) { + let bs = state.temps.bodies.getItemById(i + 1); + bs.heaterCooldownDelay = true; + } + } + + if (equip.misc.intelliChem) { + let chem = sys.chemControllers.getItemById(1, true); + let schem = state.chemControllers.getItemById(1, true); + schem.isActive = chem.isActive = true; + } + else { + sys.chemControllers.removeItemById(1); + state.chemControllers.removeItemById(1); + } + sys.equipment.controllerFirmware = `${Math.floor(equip.version / 1000).toString()}.${(equip.version % 1000).toString()}`; +} + public static async decodeHeaters(heaterConfig: HeaterConfig) { + let address: number; + let id: number; + let type: number = 1; + let cooling: boolean = false; + let body: number = 32; + // how do we know the heater is a hybrid (type=4)?? + // if no hybrid, we do have a gas heater; + // it may not be possible to set a Hybrid heater from SL... + // will go with that until we learn otherwise + let data: any = { + address, + id, + type, + cooling, + body + } + try { + let heater = state.heaters.getItemById(1); + if (heater.type === 0) { + // to add a heater, id must be 0; + // await sys.board.heaters.setHeaterAsync(data, false) + } + else { + data.id = 1; + } + await sys.board.heaters.setHeaterAsync(data, false); + } + catch (err) { + logger.error(`Error setting gas heater: ${err.message}`) + } + let add = false; + if (heaterConfig.thermaFloPresent) { + let heater = sys.heaters.getItemById(3); + if (!heater.isActive) { + data.address = 112; + data.type = 3; + if (heaterConfig.thermaFloCoolPresent) cooling = true; + add = true; + } + } + else if (heaterConfig.body1SolarPresent) { + let heater = sys.heaters.getItemById(2); + if (!heater.isActive) { + data.type = 2; + add = true; + } + } + else if (heaterConfig.solarHeatPumpPresent) { + let heater = sys.heaters.getItemById(3); + if (!heater.isActive) { + data.type = 3; + add = true; + } + } + if (add) { + sys.board.heaters.setHeaterAsync(data, false).catch((err) => { + logger.error(`Error setting additional heaters: ${err.message}`) + }); + } } -export interface SLControllerConfigData { - controllerId: number; - minSetPoint: number[]; - maxSetPoint: number[]; - degC: boolean; - controllerType; - circuitCount: number, - hwType; - controllerData; - equipFlags; - genCircuitName; - interfaceTabFlags: number; - bodyArray: any[]; - colorCount: number; - colorArray: any[]; - pumpCircCount: number; - pumpCircArray: any[]; - showAlarms: number; + public static async decodeValves(valves: Valves[]) { + for (let i = 0; i < valves.length; i++) { + let _valve = valves[i]; + // let valve: Valve = sys.valves.getItemById(_valve.valveIndex + 1); + let data: any = { + id: _valve.valveIndex + 1, + name: _valve.valveName, + circuit: _valve.deviceId, + } + await sys.board.valves.setValveAsync(data, false); + } + /* "valves": [ + { + "loadCenterIndex": 0, + "valveIndex": 0, + "valveName": "A", + "loadCenterName": "1", + "deviceId": 0 + }, + { + "loadCenterIndex": 0, + "valveIndex": 1, + "valveName": "B", + "loadCenterName": "1", + "deviceId": 0 + } + ], */ } + public static async decodeIntellichlor(slchlor: SLIntellichlorData) { + // Intellichlor: {"installed":false,"status":1,"poolSetPoint":12,"spaSetPoint":0,"salt":0,"flags":0,"superChlorTimer":0} + let chlor = sys.chlorinators.getItemById(1); + if (slchlor.installed) { + let data: any = { + id: chlor.isActive ? chlor.id : 0, + superChlorHours: slchlor.superChlorTimer, + poolSetpoint: slchlor.poolSetPoint, + spaSetpoint: slchlor.spaSetPoint, + } + await sys.board.chlorinator.setChlorAsync(data, false); + let chlorState = state.chlorinators.getItemById(1, true); + chlorState.saltLevel = slchlor.salt; + state.emitEquipmentChanges(); + } + else { + sys.chlorinators.removeItemById(1); + state.chlorinators.removeItemById(1); + }; -export interface SLSystemTimeData { - date: Date; - year: any; - month: any; - dayOfWeek: any; - day: any; - hour: any; - minute: any; - second: any; - millisecond: any; - adjustForDST: boolean; } - -export interface SLEquipmentConfigurationData { - controllerType: number; - hardwareType: number; - expansionsCount: number; - version: number; - heaterConfig: HeaterConfig; - valves: any[]; - delays: Delays; - misc: Misc; + public static async decodeChemController(slchem: SLChemData) { + // Chem data: {"isValid":true,"pH":0,"orp":0,"pHSetPoint":0,"orpSetPoint":0,"pHTankLevel":0,"orpTankLevel":0,"saturation":0,"calcium":0,"cyanuricAcid":0,"alkalinity":0,"saltPPM":0,"temperature":0,"balance":0,"corrosive":false,"scaling":false,"error":false} + let data: any = { + id: 1, + address: 144, + calciumHardness: slchem.calcium, + cyanuricAcid: slchem.cyanuricAcid, + alkalanity: slchem.alkalinity, + body: 32, + ph: { + setpoint: slchem.pHSetPoint, + enabled: true, + tank: slchem.pHTankLevel + }, + orp: { + setpoint: slchem.orpSetPoint, + enabled: true, + tank: slchem.orpTankLevel + }, + type: 2 + } + let chem = sys.chemControllers.getItemById(1); + if (chem.isActive) { + let schem = state.chemControllers.getItemById(1); + await sys.board.chemControllers.setChemControllerAsync(data, false); + schem.ph.level = slchem.pH; + schem.orp.level = slchem.orp; + schem.saturationIndex = slchem.saturation; + schem.alarms.bodyFault = slchem.error ? 1 : 0; // maybe a better place to assign the error? + state.emitEquipmentChanges(); + } } + public static async decodePump(id: number, slpump: SLPumpStatusData) { + /* Pump 0: {"pumpCircuits":[ + {"circuitId":6,"speed":2600,"isRPMs":true}, + {"circuitId":1,"speed":2000,"isRPMs":true}, + {"circuitId":2,"speed":2500,"isRPMs":true}, + {"circuitId":3,"speed":2800,"isRPMs":true}, + {"circuitId":11,"speed":2890,"isRPMs":true}, + {"circuitId":14,"speed":1500,"isRPMs":true}, + {"circuitId":129,"speed":2300,"isRPMs":true}, + {"circuitId":13,"speed":2860,"isRPMs":true}], + "pumpType":2, + "isRunning":true, + "pumpWatts":0, + "pumpRPMs":0, + "pumpUnknown1":0, + "pumpGPMs":255, + "pumpUnknown2":255} */ + let pump = sys.pumps.getItemById(id, true); + let ptype = 0; + switch (slpump.pumpType as any) { + case 2: + case 3: //ScreenLogic.PumpTypes.PUMP_TYPE_INTELLIFLOVS: + ptype = 128; + break; + case 5: //ScreenLogic.PumpTypes.PUMP_TYPE_INTELLIFLOVF: + ptype = 1; + break; + case 4: //ScreenLogic.PumpTypes.PUMP_TYPE_INTELLIFLOVSF: + ptype = 64; + break; + } + let data = { + type: ptype, + name: pump.name || `Pump ${id}`, + circuits: [] + }; + for (let i = 0; i < slpump.pumpCircuits.length; i++) { + let pumpCirc = { + circuit: slpump.pumpCircuits[i].circuitId, + speed: slpump.pumpCircuits[i].isRPMs ? slpump.pumpCircuits[i].speed : undefined, + flow: slpump.pumpCircuits[i].isRPMs ? undefined : slpump.pumpCircuits[i].speed + } + data.circuits[i] = pumpCirc; + } + data.type = ptype; + data.name = typeof pump.name !== 'undefined' ? pump.name : `Pump ${id}` + pump.set(data); + // await sys.board.pumps.setPumpAsync(data, false); + let pstate = state.pumps.getItemById(id, true); + pstate.type = data.type; + pstate.name = data.name; + pstate.watts = slpump.pumpWatts; + pstate.rpm = slpump.pumpRPMs; + pstate.flow = slpump.pumpGPMs === 255 ? 0 : slpump.pumpGPMs; + pstate.command = (pstate.rpm > 0 || pstate.watts > 0) ? 10 : 0; + state.emitEquipmentChanges(); -export interface HeaterConfig { - poolSolarPresent: boolean, - spaSolarPresent: boolean, - thermaFloCoolPresent: boolean, - solarHeatPumpPresent: boolean, - thermaFloPresent: boolean, } + public static async decodeSchedules(slrecurring: SLScheduleData[], slrunonce: SLScheduleData[]) { + /* reccuring schedules: [{"scheduleId":1,"circuitId":6,"startTime":"1800","stopTime":"0700","dayMask":127,"flags":0,"heatCmd":4,"heatSetPoint":70,"days":["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]}, + + {"scheduleId":4,"circuitId":2,"startTime":"1800","stopTime":"2300","dayMask":127,"flags":0,"heatCmd":0,"heatSetPoint":0,"days":["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]},{"scheduleId":11,"circuitId":6,"startTime":"0800","stopTime":"1700","dayMask":127,"flags":0,"heatCmd":4,"heatSetPoint":70,"days":["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]}] + + Run once schedules: [{"scheduleId":12,"circuitId":6,"startTime":"0800","stopTime":"1100","dayMask":1,"flags":1,"heatCmd":4,"heatSetPoint":70,"days":["Mon"]},{"scheduleId":13,"circuitId":6,"startTime":"0800","stopTime":"1100","dayMask":1,"flags":1,"heatCmd":4,"heatSetPoint":70,"days":["Mon"]}] */ + + for (let i = 0; i < slrecurring.length; i++) { + let slsched = slrecurring[i]; + let data = { + id: slsched.scheduleId, + circuit: slsched.circuitId, + startTime: Math.floor(slsched.startTime / 100) * 60 + slsched.startTime % 100, + endTime: Math.floor(slsched.stopTime / 100) * 60 + slsched.stopTime % 100, + scheduleDays: slsched.dayMask, + changeHeatSetPoint: slsched.heatCmd > 0, + heatSetPoint: slsched.heatSetPoint, + schedType: 128 // recurring + } + try { + await sys.board.schedules.setScheduleAsync(data, false) + } catch (err) { + logger.error(`Error setting schedule ${slsched.scheduleId}. ${err.message}`); + } + } + for (let i = 0; i < slrunonce.length; i++) { + let slsched = slrunonce[i]; + let data = { + id: slsched.scheduleId, + circuit: slsched.circuitId, + startTime: Math.floor(slsched.startTime / 100) * 60 + slsched.startTime % 100, + endTime: Math.floor(slsched.stopTime / 100) * 60 + slsched.stopTime % 100, + scheduleDays: slsched.dayMask, + changeHeatSetPoint: slsched.heatCmd > 0, + heatSetPoint: slsched.heatSetPoint, + schedType: 0 // runonce + } + try { + await sys.board.schedules.setScheduleAsync(data, false); + sys.board.system.setTZ(); + } catch (err) { + logger.error(`Error setting schedule ${slsched.scheduleId}. ${err.message}`); + } + } -export interface Delays { - poolPumpOnDuringHeaterCooldown: boolean, - spaPumpOnDuringHeaterCooldown: boolean, - pumpOffDuringValveAction +} + public static decodeDateTime(systime: SLSystemTimeData) { + // System Time: {"date":"2022-11-07T16:04:32.000Z","year":2022,"month":11,"dayOfWeek":1,"day":7,"hour":8,"minute":4,"second":32,"millisecond":0,"adjustForDST":true} + if (sys.general.options.clockSource !== 'server') { + state.time.year = systime.year; + state.time.month = systime.month; + state.time.date = systime.day; + state.time.hours = systime.hour; + state.time.minutes = systime.minute; + state.time.seconds = systime.second; + sys.general.options.adjustDST = systime.adjustForDST; + state.emitEquipmentChanges(); + } +} + /* + Controller Types + // Dual Intellitouch + I10_3D = 5; + // Intellitouch + I5 = 0; + I7_3 = 1; + I9_3 = 2; + I5S = 3; + I9_3S = 4; + I10X = 6; + // Not intellitouch... + SUNTOUCH = 10; + // EasyTouch + EASYTOUCH2 = 13; //hwType & 4 = EasyTouchLite + EASYTOUCH = 14; + */ + static isEasyTouch(controllerType) { + return controllerType === 14 || controllerType === 13; } -export interface Misc { - intelliChem: boolean, - spaManualHeat: boolean + static isIntelliTouch(controllerType) { + return controllerType !== 14 && controllerType !== 13 && controllerType !== 10; } -export interface Valves { - loadCenterIndex: number, - valveIndex: number, - valveName: string, - loadCenterName: string, - deviceId: any + static isEasyTouchLite(controllerType, hwType) { + return controllerType === 13 && (hwType & 4) !== 0; } -export interface SLWeatherForecastData { - version: number; - zip: string; - lastUpdate: Date; - lastRequest: Date; - dateText: string; - text: string; - currentTemperature: number; - humidity: number; - wind: string; - pressure: number; - dewPoint: number; - windChill: number; - visibility: number; - dayData: SLWeatherForecastDayData[]; - sunrise: number; - sunset: number; + static isDualBody(controllerType) { + return controllerType === 5; } -export interface SLWeatherForecastDayData { - dayTime: Date; - highTemp: number; - lowTemp: number; - text: string; } - -export interface TimeTimePointPairs { - on: Date; - off: Date; +export class SLCommands { + constructor(unit: ScreenLogic.UnitConnection) { + this._unit = unit; + } + protected _unit: ScreenLogic.UnitConnection; } -export interface TimeTempPointPairs { - time: Date; - temp: number; +export class SLCircuits extends SLCommands { + public async setCircuitStateAsync(id: number, val: boolean) { + if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError('Circuit or Feature id not valid', id, 'Circuit')); + let c = sys.circuits.getInterfaceById(id); + // if (id === 192 || c.type === 3) return await sys.board.circuits.setLightGroupThemeAsync(id - 191, val ? 1 : 0); + // if (id >= 192) return await sys.board.circuits.setCircuitGroupStateAsync(id, val); + await this._unit.circuits.setCircuitStateAsync(id, val); + let cstate = state.circuits.getInterfaceById(id); + cstate.isOn = val; + state.emitEquipmentChanges(); + return cstate; + } } - -export interface SLHistoryData { - airTemps: TimeTempPointPairs[]; - poolTemps: TimeTempPointPairs[]; - poolSetPointTemps: TimeTempPointPairs[]; - spaTemps: TimeTempPointPairs[]; - spaSetPointTemps: TimeTempPointPairs[]; - poolRuns: TimeTimePointPairs[]; - spaRuns: TimeTimePointPairs[]; - solarRuns: TimeTimePointPairs[]; - heaterRuns: TimeTimePointPairs[]; - lightRuns: TimeTimePointPairs[]; +export class SLCounter { + constructor() { + this.bytesReceived = 0; + this.bytesSent = 0; + } + public bytesReceived: number; + public bytesSent: number; + public toLog(): string { + return `{ "bytesReceived": ${this.bytesReceived}, "bytesSent": ${this.bytesSent} }`; + } } + +export let sl = new ScreenLogicComms(); diff --git a/defaultConfig.json b/defaultConfig.json index be118ac5..c551d705 100755 --- a/defaultConfig.json +++ b/defaultConfig.json @@ -28,8 +28,13 @@ "keepCount": 5, "njsPC": true, "servers": [] + }, + "screenlogic": { + "enabled": false, + "type": "local", + "systemName": "Pentair: 00-00-00", + "password": 1234 } - }, "web": { "servers": { diff --git a/package-lock.json b/package-lock.json index 46b811d1..e10224ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "7.7.0", "license": "GNU Affero General Public License v3.0", "dependencies": { - "@influxdata/influxdb-client": "^1.25.0", + "@influxdata/influxdb-client": "^1.32.0", "eslint-config-promise": "^2.0.2", "express": "^4.18.1", "extend": "^3.0.2", @@ -60,9 +60,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "engines": { "node": ">=6.9.0" } @@ -175,13 +175,13 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", + "espree": "^9.4.0", "globals": "^13.15.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -191,25 +191,31 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", - "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", + "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, "funding": { "type": "github", "url": "https://github.com/sponsors/nzakas" @@ -221,9 +227,9 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, "node_modules/@influxdata/influxdb-client": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@influxdata/influxdb-client/-/influxdb-client-1.28.0.tgz", - "integrity": "sha512-mTNsyBpVW3qT1dn9SH/LaQDlcotpSH+64aR00E7hONXyVntVUSLEbH0ijHs+Hwk1dQS+WmvNduhdeFr/vHZ+Kw==" + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/@influxdata/influxdb-client/-/influxdb-client-1.32.0.tgz", + "integrity": "sha512-TNKpDGYoBD3bZKn9xySeMiu6NcRKsJ8hPkmiCzYl/C6ur8DWlWfiZkviEdzabyhKC83EjarQSzhlJ2wvnIK9yg==" }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", @@ -506,11 +512,6 @@ "@types/node": "*" } }, - "node_modules/@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" - }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -531,9 +532,9 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" }, "node_modules/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -543,9 +544,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.30", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", - "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", "dev": true, "dependencies": { "@types/node": "*", @@ -586,9 +587,9 @@ } }, "node_modules/@types/node": { - "version": "16.11.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.48.tgz", - "integrity": "sha512-Z9r9UWlNeNkYnxybm+1fc0jxUNjZqRekTAr1pG0qdXe9apT9yCiqk1c4VvKQJsFpnchU4+fLl25MabSLA2wxIw==" + "version": "16.18.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", + "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==" }, "node_modules/@types/qs": { "version": "6.9.7", @@ -602,6 +603,12 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "node_modules/@types/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", @@ -613,17 +620,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.0.tgz", - "integrity": "sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.0.tgz", + "integrity": "sha512-5TJh2AgL6+wpL8H/GTSjNb4WrjKoR2rqvFxR/DDTqYNk6uXn8BJMEcncLSpMbf/XV1aS0jAjYwn98uvVCiAywQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/type-utils": "5.33.0", - "@typescript-eslint/utils": "5.33.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/type-utils": "5.42.0", + "@typescript-eslint/utils": "5.42.0", "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" @@ -646,14 +653,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.0.tgz", - "integrity": "sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.0.tgz", + "integrity": "sha512-Ixh9qrOTDRctFg3yIwrLkgf33AHyEIn6lhyf5cCfwwiGtkWhNpVKlEZApi3inGQR/barWnY7qY8FbGKBO7p3JA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/typescript-estree": "5.33.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/typescript-estree": "5.42.0", "debug": "^4.3.4" }, "engines": { @@ -673,13 +680,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.0.tgz", - "integrity": "sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.0.tgz", + "integrity": "sha512-l5/3IBHLH0Bv04y+H+zlcLiEMEMjWGaCX6WyHE5Uk2YkSGAMlgdUPsT/ywTSKgu9D1dmmKMYgYZijObfA39Wow==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0" + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/visitor-keys": "5.42.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -690,12 +697,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.0.tgz", - "integrity": "sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.0.tgz", + "integrity": "sha512-HW14TXC45dFVZxnVW8rnUGnvYyRC0E/vxXShFCthcC9VhVTmjqOmtqj6H5rm9Zxv+ORxKA/1aLGD7vmlLsdlOg==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.33.0", + "@typescript-eslint/typescript-estree": "5.42.0", + "@typescript-eslint/utils": "5.42.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -716,9 +724,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.0.tgz", - "integrity": "sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.0.tgz", + "integrity": "sha512-t4lzO9ZOAUcHY6bXQYRuu+3SSYdD9TS8ooApZft4WARt4/f2Cj/YpvbTe8A4GuhT4bNW72goDMOy7SW71mZwGw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -729,13 +737,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.0.tgz", - "integrity": "sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.0.tgz", + "integrity": "sha512-2O3vSq794x3kZGtV7i4SCWZWCwjEtkWfVqX4m5fbUBomOsEOyd6OAD1qU2lbvV5S8tgy/luJnOYluNyYVeOTTg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/visitor-keys": "5.42.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -756,17 +764,19 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.0.tgz", - "integrity": "sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.0.tgz", + "integrity": "sha512-JZ++3+h1vbeG1NUECXQZE3hg0kias9kOtcQr3+JVQ3whnjvKuMyktJAAIj6743OeNPnGBmjj7KEmiDL7qsdnCQ==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/typescript-estree": "5.33.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/typescript-estree": "5.42.0", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -780,12 +790,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.0.tgz", - "integrity": "sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.0.tgz", + "integrity": "sha512-QHbu5Hf/2lOEOwy+IUw0GoSCuAzByTAWWrOTKzTzsotiUnWFpuKnXcAhC9YztAf2EElQ0VvIK+pHJUPkM0q7jg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.33.0", + "@typescript-eslint/types": "5.42.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -815,9 +825,9 @@ } }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "bin": { "acorn": "bin/acorn" }, @@ -948,18 +958,19 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "engines": { "node": ">=8" } }, "node_modules/array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -1043,9 +1054,9 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -1055,7 +1066,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", + "qs": "6.11.0", "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -1091,6 +1102,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -1275,11 +1287,6 @@ "minimist": "^1.1.0" } }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1464,6 +1471,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "dependencies": { "path-type": "^4.0.0" }, @@ -1569,9 +1577,9 @@ } }, "node_modules/engine.io-client": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz", - "integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz", + "integrity": "sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", @@ -1637,30 +1645,31 @@ } }, "node_modules/es-abstract": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", - "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", + "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", "dependencies": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.1", + "get-intrinsic": "^1.1.3", "get-symbol-description": "^1.0.0", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-symbols": "^1.0.3", "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", + "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", + "object-inspect": "^1.12.2", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", + "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", "string.prototype.trimend": "^1.0.5", "string.prototype.trimstart": "^1.0.5", "unbox-primitive": "^1.0.2" @@ -1713,13 +1722,14 @@ } }, "node_modules/eslint": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.21.0.tgz", - "integrity": "sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==", - "dependencies": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.10.4", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", + "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", + "dependencies": { + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -1729,21 +1739,21 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.3", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", + "glob-parent": "^6.0.2", "globals": "^13.15.0", - "globby": "^11.1.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -1754,8 +1764,7 @@ "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -2376,9 +2385,9 @@ } }, "node_modules/eslint-plugin-promise": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz", - "integrity": "sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2478,9 +2487,9 @@ } }, "node_modules/espree": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz", - "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", @@ -2595,13 +2604,13 @@ } }, "node_modules/express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.0", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", @@ -2620,7 +2629,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.10.3", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", @@ -2672,9 +2681,10 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -2690,6 +2700,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -2754,6 +2765,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2872,9 +2884,9 @@ } }, "node_modules/flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==" + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "node_modules/fn.name": { "version": "1.1.0", @@ -2959,9 +2971,9 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", - "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -3085,6 +3097,7 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -3751,9 +3764,9 @@ } }, "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "engines": { "node": ">= 0.4" }, @@ -3762,9 +3775,9 @@ } }, "node_modules/is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dependencies": { "has": "^1.0.3" }, @@ -3828,6 +3841,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "engines": { "node": ">=0.12.0" } @@ -3846,6 +3860,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -3987,9 +4009,9 @@ } }, "node_modules/js-sdsl": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-2.1.4.tgz", - "integrity": "sha512-/Ew+CJWHNddr7sjwgxaVeIORIH4AMVC9dy0hPf540ZGMVgS9d3ajwuVdyhDt6/QUvT8ATjR3yuYBKsS79F+H4A==" + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -4206,6 +4228,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "engines": { "node": ">= 8" } @@ -4222,6 +4245,7 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -4280,9 +4304,12 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/mkdirp": { "version": "1.0.4", @@ -4420,6 +4447,12 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -4449,8 +4482,8 @@ } }, "node_modules/node-screenlogic": { - "version": "1.10.1", - "resolved": "git+ssh://git@github.com/tagyoureit/node-screenlogic.git#22559cfc76a9e9c969dc6d491ab745809bc9dcd0", + "version": "2.0.0", + "resolved": "git+ssh://git@github.com/tagyoureit/node-screenlogic.git#99e09c1c29bf732763acdaace7c021841248605b", "license": "MIT", "dependencies": { "debug": "^4.3.2", @@ -4502,14 +4535,19 @@ } }, "node_modules/number-allocator": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.10.tgz", - "integrity": "sha512-K4AvNGKo9lP6HqsZyfSr9KDaqnwFzW203inhQEOwFrmFaYevpdX4VNwdOLk197aHujzbT//z6pCBrCOUYSM5iw==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.12.tgz", + "integrity": "sha512-sGB0qoQGmKimery9JubBQ9pQUr1V/LixJAk3Ygp7obZf6mpSXime8d7XHEobbIimkdZpgjkNlLt6G7LPEWFYWg==", "dependencies": { "debug": "^4.3.1", - "js-sdsl": "^2.1.2" + "js-sdsl": "4.1.4" } }, + "node_modules/number-allocator/node_modules/js-sdsl": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", + "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4535,9 +4573,9 @@ } }, "node_modules/object.assign": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz", - "integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -4827,6 +4865,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "engines": { "node": ">=8" } @@ -4835,6 +4874,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "engines": { "node": ">=8.6" }, @@ -4893,9 +4933,9 @@ } }, "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dependencies": { "side-channel": "^1.0.4" }, @@ -5147,10 +5187,23 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-stable-stringify": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", - "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.1.tgz", + "integrity": "sha512-dVHE6bMtS/bnL2mwualjc6IxEv1F+OCUpA46pKUj6F8uDbUM0jCCulPqRNPSnWwGNKx5etqMjZYdXtrm5KJZGA==", "engines": { "node": ">=10" } @@ -5161,9 +5214,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -5316,6 +5369,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, "engines": { "node": ">=8" } @@ -5367,16 +5421,16 @@ } }, "node_modules/socket.io": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz", - "integrity": "sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz", + "integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", "engine.io": "~6.2.0", "socket.io-adapter": "~2.4.0", - "socket.io-parser": "~4.0.4" + "socket.io-parser": "~4.2.0" }, "engines": { "node": ">=10.0.0" @@ -5388,20 +5442,20 @@ "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" }, "node_modules/socket.io-client": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz", - "integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.3.tgz", + "integrity": "sha512-I/hqDYpQ6JKwtJOf5ikM+Qz+YujZPMEl6qBLhxiP0nX+TfXKhW4KZZG8lamrD6Y5ngjmYHreESVasVCgi5Kl3A==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", - "engine.io-client": "~6.2.1", + "engine.io-client": "~6.2.3", "socket.io-parser": "~4.2.0" }, "engines": { "node": ">=10.0.0" } }, - "node_modules/socket.io-client/node_modules/socket.io-parser": { + "node_modules/socket.io-parser": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz", "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==", @@ -5413,19 +5467,6 @@ "node": ">=10.0.0" } }, - "node_modules/socket.io-parser": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz", - "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==", - "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5702,6 +5743,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -5836,9 +5878,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5913,11 +5955,6 @@ "node": ">= 0.4.0" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -5974,10 +6011,11 @@ } }, "node_modules/winston": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.1.tgz", - "integrity": "sha512-r+6YAiCR4uI3N8eQNOg8k3P3PqwAm20cLKlzVD9E66Ch39+LZC+VH1UKf9JemQj2B3QoUHfKD7Poewn0Pr3Y1w==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", + "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==", "dependencies": { + "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", @@ -6139,9 +6177,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==" + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" }, "@babel/highlight": { "version": "7.18.6", @@ -6229,13 +6267,13 @@ } }, "@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", + "espree": "^9.4.0", "globals": "^13.15.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -6245,19 +6283,19 @@ } }, "@humanwhocodes/config-array": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", - "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", + "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, - "@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==" + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" }, "@humanwhocodes/object-schema": { "version": "1.2.1", @@ -6265,9 +6303,9 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, "@influxdata/influxdb-client": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@influxdata/influxdb-client/-/influxdb-client-1.28.0.tgz", - "integrity": "sha512-mTNsyBpVW3qT1dn9SH/LaQDlcotpSH+64aR00E7hONXyVntVUSLEbH0ijHs+Hwk1dQS+WmvNduhdeFr/vHZ+Kw==" + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/@influxdata/influxdb-client/-/influxdb-client-1.32.0.tgz", + "integrity": "sha512-TNKpDGYoBD3bZKn9xySeMiu6NcRKsJ8hPkmiCzYl/C6ur8DWlWfiZkviEdzabyhKC83EjarQSzhlJ2wvnIK9yg==" }, "@jridgewell/resolve-uri": { "version": "3.1.0", @@ -6460,11 +6498,6 @@ "@types/node": "*" } }, - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" - }, "@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -6485,9 +6518,9 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" }, "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", "dev": true, "requires": { "@types/body-parser": "*", @@ -6497,9 +6530,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.30", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", - "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", "dev": true, "requires": { "@types/node": "*", @@ -6540,9 +6573,9 @@ } }, "@types/node": { - "version": "16.11.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.48.tgz", - "integrity": "sha512-Z9r9UWlNeNkYnxybm+1fc0jxUNjZqRekTAr1pG0qdXe9apT9yCiqk1c4VvKQJsFpnchU4+fLl25MabSLA2wxIw==" + "version": "16.18.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", + "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==" }, "@types/qs": { "version": "6.9.7", @@ -6556,6 +6589,12 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "@types/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", @@ -6567,69 +6606,70 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.0.tgz", - "integrity": "sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.0.tgz", + "integrity": "sha512-5TJh2AgL6+wpL8H/GTSjNb4WrjKoR2rqvFxR/DDTqYNk6uXn8BJMEcncLSpMbf/XV1aS0jAjYwn98uvVCiAywQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/type-utils": "5.33.0", - "@typescript-eslint/utils": "5.33.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/type-utils": "5.42.0", + "@typescript-eslint/utils": "5.42.0", "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "@typescript-eslint/parser": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.0.tgz", - "integrity": "sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.0.tgz", + "integrity": "sha512-Ixh9qrOTDRctFg3yIwrLkgf33AHyEIn6lhyf5cCfwwiGtkWhNpVKlEZApi3inGQR/barWnY7qY8FbGKBO7p3JA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/typescript-estree": "5.33.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/typescript-estree": "5.42.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.0.tgz", - "integrity": "sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.0.tgz", + "integrity": "sha512-l5/3IBHLH0Bv04y+H+zlcLiEMEMjWGaCX6WyHE5Uk2YkSGAMlgdUPsT/ywTSKgu9D1dmmKMYgYZijObfA39Wow==", "dev": true, "requires": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0" + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/visitor-keys": "5.42.0" } }, "@typescript-eslint/type-utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.0.tgz", - "integrity": "sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.0.tgz", + "integrity": "sha512-HW14TXC45dFVZxnVW8rnUGnvYyRC0E/vxXShFCthcC9VhVTmjqOmtqj6H5rm9Zxv+ORxKA/1aLGD7vmlLsdlOg==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.33.0", + "@typescript-eslint/typescript-estree": "5.42.0", + "@typescript-eslint/utils": "5.42.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.0.tgz", - "integrity": "sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.0.tgz", + "integrity": "sha512-t4lzO9ZOAUcHY6bXQYRuu+3SSYdD9TS8ooApZft4WARt4/f2Cj/YpvbTe8A4GuhT4bNW72goDMOy7SW71mZwGw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.0.tgz", - "integrity": "sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.0.tgz", + "integrity": "sha512-2O3vSq794x3kZGtV7i4SCWZWCwjEtkWfVqX4m5fbUBomOsEOyd6OAD1qU2lbvV5S8tgy/luJnOYluNyYVeOTTg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/visitor-keys": "5.42.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -6638,26 +6678,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.0.tgz", - "integrity": "sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.0.tgz", + "integrity": "sha512-JZ++3+h1vbeG1NUECXQZE3hg0kias9kOtcQr3+JVQ3whnjvKuMyktJAAIj6743OeNPnGBmjj7KEmiDL7qsdnCQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/typescript-estree": "5.33.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/typescript-estree": "5.42.0", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.0.tgz", - "integrity": "sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.0.tgz", + "integrity": "sha512-QHbu5Hf/2lOEOwy+IUw0GoSCuAzByTAWWrOTKzTzsotiUnWFpuKnXcAhC9YztAf2EElQ0VvIK+pHJUPkM0q7jg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.33.0", + "@typescript-eslint/types": "5.42.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -6677,9 +6719,9 @@ } }, "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" }, "acorn-jsx": { "version": "5.3.2", @@ -6770,16 +6812,17 @@ "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true }, "array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0" } }, @@ -6836,9 +6879,9 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -6848,7 +6891,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", + "qs": "6.11.0", "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -6882,6 +6925,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -7024,11 +7068,6 @@ "minimist": "^1.1.0" } }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -7164,6 +7203,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "requires": { "path-type": "^4.0.0" } @@ -7266,9 +7306,9 @@ } }, "engine.io-client": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz", - "integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz", + "integrity": "sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==", "requires": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", @@ -7291,30 +7331,31 @@ "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==" }, "es-abstract": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", - "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", + "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.1", + "get-intrinsic": "^1.1.3", "get-symbol-description": "^1.0.0", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-symbols": "^1.0.3", "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", + "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", + "object-inspect": "^1.12.2", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", + "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", "string.prototype.trimend": "^1.0.5", "string.prototype.trimstart": "^1.0.5", "unbox-primitive": "^1.0.2" @@ -7349,13 +7390,14 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "eslint": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.21.0.tgz", - "integrity": "sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==", - "requires": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.10.4", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", + "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", + "requires": { + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -7365,21 +7407,21 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.3", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", + "glob-parent": "^6.0.2", "globals": "^13.15.0", - "globby": "^11.1.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -7390,8 +7432,7 @@ "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "dependencies": { "eslint-scope": { @@ -7873,9 +7914,9 @@ } }, "eslint-plugin-promise": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz", - "integrity": "sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", "dev": true, "requires": {} }, @@ -7917,9 +7958,9 @@ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==" }, "espree": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz", - "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", "requires": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", @@ -7998,13 +8039,13 @@ } }, "express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.0", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", @@ -8023,7 +8064,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.10.3", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", @@ -8071,9 +8112,10 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -8086,6 +8128,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -8142,6 +8185,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -8237,9 +8281,9 @@ } }, "flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==" + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "fn.name": { "version": "1.1.0", @@ -8303,9 +8347,9 @@ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, "get-intrinsic": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", - "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -8395,6 +8439,7 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -8897,14 +8942,14 @@ } }, "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" }, "is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "requires": { "has": "^1.0.3" } @@ -8943,7 +8988,8 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true }, "is-number-object": { "version": "1.0.7", @@ -8953,6 +8999,11 @@ "has-tostringtag": "^1.0.0" } }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -9049,9 +9100,9 @@ "dev": true }, "js-sdsl": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-2.1.4.tgz", - "integrity": "sha512-/Ew+CJWHNddr7sjwgxaVeIORIH4AMVC9dy0hPf540ZGMVgS9d3ajwuVdyhDt6/QUvT8ATjR3yuYBKsS79F+H4A==" + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==" }, "js-tokens": { "version": "4.0.0", @@ -9230,7 +9281,8 @@ "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true }, "methods": { "version": "1.1.2", @@ -9241,6 +9293,7 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -9278,9 +9331,9 @@ } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" }, "mkdirp": { "version": "1.0.4", @@ -9393,6 +9446,12 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -9414,8 +9473,8 @@ "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==" }, "node-screenlogic": { - "version": "git+ssh://git@github.com/tagyoureit/node-screenlogic.git#22559cfc76a9e9c969dc6d491ab745809bc9dcd0", - "from": "node-screenlogic@https://github.com/tagyoureit/node-screenlogic.git#typescript", + "version": "git+ssh://git@github.com/tagyoureit/node-screenlogic.git#99e09c1c29bf732763acdaace7c021841248605b", + "from": "node-screenlogic@tagyoureit/node-screenlogic#typescript", "requires": { "debug": "^4.3.2", "smart-buffer": "^4.2.0", @@ -9462,12 +9521,19 @@ } }, "number-allocator": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.10.tgz", - "integrity": "sha512-K4AvNGKo9lP6HqsZyfSr9KDaqnwFzW203inhQEOwFrmFaYevpdX4VNwdOLk197aHujzbT//z6pCBrCOUYSM5iw==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.12.tgz", + "integrity": "sha512-sGB0qoQGmKimery9JubBQ9pQUr1V/LixJAk3Ygp7obZf6mpSXime8d7XHEobbIimkdZpgjkNlLt6G7LPEWFYWg==", "requires": { "debug": "^4.3.1", - "js-sdsl": "^2.1.2" + "js-sdsl": "4.1.4" + }, + "dependencies": { + "js-sdsl": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", + "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==" + } } }, "object-assign": { @@ -9486,9 +9552,9 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object.assign": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz", - "integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -9702,12 +9768,14 @@ "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true }, "prelude-ls": { "version": "1.2.1", @@ -9748,9 +9816,9 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "requires": { "side-channel": "^1.0.4" } @@ -9904,10 +9972,20 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, "safe-stable-stringify": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", - "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.1.tgz", + "integrity": "sha512-dVHE6bMtS/bnL2mwualjc6IxEv1F+OCUpA46pKUj6F8uDbUM0jCCulPqRNPSnWwGNKx5etqMjZYdXtrm5KJZGA==" }, "safer-buffer": { "version": "2.1.2", @@ -9915,9 +9993,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -10046,7 +10124,8 @@ "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true }, "slice-ansi": { "version": "2.1.0", @@ -10087,16 +10166,16 @@ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" }, "socket.io": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz", - "integrity": "sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz", + "integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==", "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", "engine.io": "~6.2.0", "socket.io-adapter": "~2.4.0", - "socket.io-parser": "~4.0.4" + "socket.io-parser": "~4.2.0" } }, "socket.io-adapter": { @@ -10105,34 +10184,22 @@ "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" }, "socket.io-client": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz", - "integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.3.tgz", + "integrity": "sha512-I/hqDYpQ6JKwtJOf5ikM+Qz+YujZPMEl6qBLhxiP0nX+TfXKhW4KZZG8lamrD6Y5ngjmYHreESVasVCgi5Kl3A==", "requires": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", - "engine.io-client": "~6.2.1", + "engine.io-client": "~6.2.3", "socket.io-parser": "~4.2.0" - }, - "dependencies": { - "socket.io-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz", - "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==", - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - } - } } }, "socket.io-parser": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz", - "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz", + "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==", "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" } }, @@ -10354,6 +10421,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "requires": { "is-number": "^7.0.0" } @@ -10442,9 +10510,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true }, "unbox-primitive": { @@ -10497,11 +10565,6 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" - }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -10543,10 +10606,11 @@ } }, "winston": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.1.tgz", - "integrity": "sha512-r+6YAiCR4uI3N8eQNOg8k3P3PqwAm20cLKlzVD9E66Ch39+LZC+VH1UKf9JemQj2B3QoUHfKD7Poewn0Pr3Y1w==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", + "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==", "requires": { + "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", diff --git a/package.json b/package.json index f4431d54..93ad4d19 100755 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "watch": "tsc -w" }, "dependencies": { - "@influxdata/influxdb-client": "^1.25.0", + "@influxdata/influxdb-client": "^1.32.0", "eslint-config-promise": "^2.0.2", "express": "^4.18.1", "extend": "^3.0.2", diff --git a/web/Server.ts b/web/Server.ts index c6b46f64..7672a7a4 100755 --- a/web/Server.ts +++ b/web/Server.ts @@ -231,8 +231,7 @@ export class WebServer { else logger.info(`Auto-backup initialized Last Backup: ${Timestamp.toISOLocal(new Date(this.lastBackup))}`); // Lets wait a good 20 seconds before we auto-backup anything. Now that we are initialized let the OCP have its way with everything. - await setTimeout(20000); - this.checkAutoBackup(); + setTimeoutSync(()=>{this.checkAutoBackup();}, 20000); } catch (err) { logger.error(`Error initializing auto-backup: ${err.message}`); } } @@ -657,11 +656,16 @@ export class HttpServer extends ProtoServer { if (!sendMessages) sock.leave('msgLogger'); else sock.join('msgLogger'); }); - sock.on('sendRS485PortStats', function (sendPortStatus: boolean) { - console.log(`sendRS485PortStats set to ${sendPortStatus}`); - if (!sendPortStatus) sock.leave('rs485PortStats'); + sock.on('sendRS485PortStats', function (sendPortStats: boolean) { + console.log(`sendRS485PortStats set to ${sendPortStats}`); + if (!sendPortStats) sock.leave('rs485PortStats'); else sock.join('rs485PortStats'); }); + sock.on('sendScreenlogicStats', function (sendScreenlogicStats: boolean) { + console.log(`sendScreenlogicStats set to ${sendScreenlogicStats}`); + if (!sendScreenlogicStats) sock.leave('screenlogicStats'); + else sock.join('screenlogicStats'); + }); StateSocket.initSockets(sock); ConfigSocket.initSockets(sock); } diff --git a/web/interfaces/influxInterface.ts b/web/interfaces/influxInterface.ts index 5c7ed7eb..c7545c48 100644 --- a/web/interfaces/influxInterface.ts +++ b/web/interfaces/influxInterface.ts @@ -100,10 +100,14 @@ export class InfluxInterfaceBindings extends BaseInterfaceBindings { writeSuccess: function(lines){ logger.silly(`InfluxDB successfully wrote ${lines.length} lines.`) }, + writeRetrySkipped: function(entry){ + logger.silly(`Influx write retry skipped ${JSON.stringify(entry)}`); + }, maxRetryTime: DEFAULT_WriteOptions.maxRetryTime, exponentialBase: DEFAULT_WriteOptions.exponentialBase, randomRetry: DEFAULT_WriteOptions.randomRetry, maxBatchBytes: 4096 + } this.writeApi = influxDB.getWriteApi(org, bucket, 'ms', writeOptions); diff --git a/web/services/config/Config.ts b/web/services/config/Config.ts index 29506887..025d6e25 100755 --- a/web/services/config/Config.ts +++ b/web/services/config/Config.ts @@ -20,7 +20,7 @@ import * as path from "path"; import * as express from "express"; import * as extend from 'extend'; import * as multer from 'multer'; -import { sys, LightGroup, ControllerType, Pump, Valve, Body, General, Circuit, ICircuit, Feature, CircuitGroup, CustomNameCollection, Schedule, Chlorinator, Heater } from "../../../controller/Equipment"; +import { sys, LightGroup, ControllerType, Pump, Valve, Body, General, Circuit, ICircuit, Feature, CircuitGroup, CustomNameCollection, Schedule, Chlorinator, Heater, Screenlogic } from "../../../controller/Equipment"; import { config } from "../../../config/Config"; import { logger } from "../../../logger/Logger"; import { utils } from "../../../controller/Constants"; @@ -30,6 +30,8 @@ import { stopPacketCaptureAsync, startPacketCapture } from '../../../app'; import { conn } from "../../../controller/comms/Comms"; import { webApp, BackupFile, RestoreFile } from "../../Server"; import { release } from "os"; +import { ScreenLogicComms, sl } from "../../../controller/comms/ScreenLogic"; +import { screenlogic } from "node-screenlogic"; export class ConfigRoute { public static initRoutes(app: express.Application) { @@ -79,6 +81,18 @@ export class ConfigRoute { return res.status(200).send(opts); } catch (err) { next(err); } }); + app.get('/config/options/screenlogic', async (req, res, next) => { + try { + let localUnit = await ScreenLogicComms.searchAsync(); + let cfg = config.getSection('controller.screenlogic'); + let data = { + cfg, + localUnit, + types: [{ val: 'local', name: 'Local', desc: 'Local Screenlogic' }, { val: 'remote', name: 'Remote', desc: 'Remote Screenlogic' }] + } + return res.status(200).send(data); + } catch (err) { next(err); } + }); app.get('/config/options/circuits', async (req, res, next) => { try { let opts = { @@ -828,6 +842,13 @@ export class ConfigRoute { } catch (err) { next(err); } }); + app.put('/app/screenlogic', async (req, res, next) => { + try { + let screenlogic = await sl.setScreenlogicAsync(req.body); + return res.status(200).send(screenlogic); + } + catch (err) { next(err); } + }); app.delete('/app/rs485Port', async (req, res, next) => { try { let port = await conn.deleteAuxPort(req.body);