iobroker.iot 3.6.0 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/admin/assets/index-5zouxn2w.js +680 -0
- package/admin/index_m.html +1 -1
- package/admin/rules/assets/{index-BRdNnGcA.js → index-DwYdaT5M.js} +80 -81
- package/admin/rules/customRuleBlocks.js +2 -2
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/AlexaResponse.js +101 -95
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/AlexaResponse.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Capabilities/Base.js +22 -36
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/Base.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/BrightnessController.js +19 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/BrightnessController.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorController.js +14 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorController.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorTemperatureController.js +19 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorTemperatureController.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ContactSensor.js +16 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ContactSensor.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/LockController.js +14 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/LockController.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Capabilities/ModeController.js +27 -28
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ModeController.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/MotionSensor.js +14 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/MotionSensor.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/PercentageController.js +14 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/PercentageController.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/PowerController.js +19 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/PowerController.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/Speaker.js +25 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/Speaker.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/TemperatureSensor.js +14 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/TemperatureSensor.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ThermostatController.js +37 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ThermostatController.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/index.js +32 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/index.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/Base.js +29 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/Base.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Directives/ChangeReport.js +34 -27
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/ChangeReport.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/Discovery.js +39 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/Discovery.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Directives/ReportState.js +19 -22
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/ReportState.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/index.js +14 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/index.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Base.js +36 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Base.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Closed.js +57 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Closed.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Open.js +57 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Open.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/index.js +12 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/index.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/AdjustableProperty.js +16 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/AdjustableProperty.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Base.js +127 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Base.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Brightness.js +18 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Brightness.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Color.js +38 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Color.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Properties/ColorTemperatureInKelvin.js +20 -29
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/ColorTemperatureInKelvin.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/DetectionState.js +23 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/DetectionState.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Properties/LockState.js +9 -12
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/LockState.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Mode.js +34 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Mode.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Muted.js +19 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Muted.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Percentage.js +18 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Percentage.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Properties/PowerState.js +9 -9
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/PowerState.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/TargetSetpoint.js +31 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/TargetSetpoint.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Temperature.js +22 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Temperature.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/ThermostatMode.js +49 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/ThermostatMode.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Volume.js +21 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Volume.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/index.js +38 -0
- package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/index.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/AdjustableControl.js +20 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/AdjustableControl.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/AdjustablePercentageControl.js +26 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/AdjustablePercentageControl.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/AirCondition.js +148 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/AirCondition.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Blind.js +13 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Blind.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/ContactSensor.js +17 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/ContactSensor.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Controls/Control.js +73 -104
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Control.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Ct.js +182 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Ct.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Dimmer.js +127 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Dimmer.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Door.js +10 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Door.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Gate.js +38 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Gate.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Hue.js +208 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Hue.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Controls/Light.js +15 -22
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Light.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Lock.js +35 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Lock.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Motion.js +17 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Motion.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/ReadOnlyDetector.js +26 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/ReadOnlyDetector.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Slider.js +10 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Slider.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Socket.js +21 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Socket.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Temperature.js +21 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Temperature.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Thermostat.js +85 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Thermostat.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/VacuumCleaner.js +27 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/VacuumCleaner.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Volume.js +116 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Volume.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/VolumeGroup.js +10 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/VolumeGroup.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Window.js +10 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/Window.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/index.js +121 -0
- package/build-backend/lib/AlexaSmartHomeV3/Controls/index.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Device.js +29 -30
- package/build-backend/lib/AlexaSmartHomeV3/Device.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/DeviceManager.js +392 -0
- package/build-backend/lib/AlexaSmartHomeV3/DeviceManager.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Exceptions/AlexaV3Exception.js +10 -0
- package/build-backend/lib/AlexaSmartHomeV3/Exceptions/AlexaV3Exception.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Exceptions/HourlyDeviceRateLimitExceeded.js +10 -0
- package/build-backend/lib/AlexaSmartHomeV3/Exceptions/HourlyDeviceRateLimitExceeded.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Exceptions/OverallDailyRateLimitExceeded.js +10 -0
- package/build-backend/lib/AlexaSmartHomeV3/Exceptions/OverallDailyRateLimitExceeded.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Helpers/AdapterProvider.js +12 -21
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/AdapterProvider.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/FileHelper.js +53 -0
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/FileHelper.js.map +1 -0
- package/{lib → build-backend/lib}/AlexaSmartHomeV3/Helpers/IotProxy.js +9 -26
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/IotProxy.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/Logger.js +93 -0
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/Logger.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/RateLimiter.js +112 -0
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/RateLimiter.js.map +1 -0
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/Utils.js +625 -0
- package/build-backend/lib/AlexaSmartHomeV3/Helpers/Utils.js.map +1 -0
- package/build-backend/lib/Utils.js +96 -0
- package/build-backend/lib/Utils.js.map +1 -0
- package/build-backend/lib/adminCommonSocket.js +715 -0
- package/build-backend/lib/adminCommonSocket.js.map +1 -0
- package/build-backend/lib/alexaCustom.js +542 -0
- package/build-backend/lib/alexaCustom.js.map +1 -0
- package/{lib → build-backend/lib}/alexaSmartHomeV2.js +4 -8
- package/{lib → build-backend/lib}/alexaSmartHomeV3.js +25 -45
- package/build-backend/lib/alexaSmartHomeV3.js.map +1 -0
- package/{lib → build-backend/lib}/alisa.js +41 -44
- package/{lib → build-backend/lib}/devices.js +11 -8
- package/build-backend/lib/devices.js.map +1 -0
- package/{lib → build-backend/lib}/functions.js +11 -8
- package/build-backend/lib/functions.js.map +1 -0
- package/{lib → build-backend/lib}/googleHome.js +25 -26
- package/{lib → build-backend/lib}/notifications.js +15 -22
- package/build-backend/lib/notifications.js.map +1 -0
- package/{lib → build-backend/lib}/remote.js +615 -636
- package/build-backend/lib/remote.js.map +1 -0
- package/{lib → build-backend/lib}/rooms.js +11 -8
- package/build-backend/lib/rooms.js.map +1 -0
- package/{lib → build-backend/lib}/texts.js +6 -4
- package/build-backend/lib/texts.js.map +1 -0
- package/build-backend/lib/translate.js +21 -0
- package/build-backend/lib/translate.js.map +1 -0
- package/{lib → build-backend/lib}/visuApp.js +45 -65
- package/build-backend/lib/visuApp.js.map +1 -0
- package/build-backend/main.js +1361 -0
- package/build-backend/main.js.map +1 -0
- package/io-package.json +14 -14
- package/package.json +18 -15
- package/admin/assets/index-DCbOB3g_.js +0 -681
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/BrightnessController.js +0 -15
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorController.js +0 -10
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorTemperatureController.js +0 -15
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ContactSensor.js +0 -10
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/LockController.js +0 -10
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/MotionSensor.js +0 -10
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/PercentageController.js +0 -10
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/PowerController.js +0 -15
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/Speaker.js +0 -20
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/TemperatureSensor.js +0 -10
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ThermostatController.js +0 -34
- package/lib/AlexaSmartHomeV3/Alexa/Capabilities/index.js +0 -14
- package/lib/AlexaSmartHomeV3/Alexa/Directives/Base.js +0 -27
- package/lib/AlexaSmartHomeV3/Alexa/Directives/Discovery.js +0 -39
- package/lib/AlexaSmartHomeV3/Alexa/Directives/index.js +0 -13
- package/lib/AlexaSmartHomeV3/Alexa/ModeValues/Base.js +0 -38
- package/lib/AlexaSmartHomeV3/Alexa/ModeValues/Closed.js +0 -55
- package/lib/AlexaSmartHomeV3/Alexa/ModeValues/Open.js +0 -56
- package/lib/AlexaSmartHomeV3/Alexa/ModeValues/index.js +0 -14
- package/lib/AlexaSmartHomeV3/Alexa/Properties/AdjustableProperty.js +0 -11
- package/lib/AlexaSmartHomeV3/Alexa/Properties/Base.js +0 -108
- package/lib/AlexaSmartHomeV3/Alexa/Properties/Brightness.js +0 -14
- package/lib/AlexaSmartHomeV3/Alexa/Properties/Color.js +0 -40
- package/lib/AlexaSmartHomeV3/Alexa/Properties/DetectionState.js +0 -22
- package/lib/AlexaSmartHomeV3/Alexa/Properties/Mode.js +0 -32
- package/lib/AlexaSmartHomeV3/Alexa/Properties/Muted.js +0 -17
- package/lib/AlexaSmartHomeV3/Alexa/Properties/Percentage.js +0 -14
- package/lib/AlexaSmartHomeV3/Alexa/Properties/TargetSetpoint.js +0 -28
- package/lib/AlexaSmartHomeV3/Alexa/Properties/Temperature.js +0 -20
- package/lib/AlexaSmartHomeV3/Alexa/Properties/ThermostatMode.js +0 -52
- package/lib/AlexaSmartHomeV3/Alexa/Properties/Volume.js +0 -19
- package/lib/AlexaSmartHomeV3/Alexa/Properties/index.js +0 -14
- package/lib/AlexaSmartHomeV3/Controls/AdjustableControl.js +0 -22
- package/lib/AlexaSmartHomeV3/Controls/AdjustablePercentageControl.js +0 -28
- package/lib/AlexaSmartHomeV3/Controls/AirCondition.js +0 -144
- package/lib/AlexaSmartHomeV3/Controls/Blind.js +0 -12
- package/lib/AlexaSmartHomeV3/Controls/ContactSensor.js +0 -17
- package/lib/AlexaSmartHomeV3/Controls/Ct.js +0 -172
- package/lib/AlexaSmartHomeV3/Controls/Dimmer.js +0 -124
- package/lib/AlexaSmartHomeV3/Controls/Door.js +0 -9
- package/lib/AlexaSmartHomeV3/Controls/Gate.js +0 -42
- package/lib/AlexaSmartHomeV3/Controls/Hue.js +0 -207
- package/lib/AlexaSmartHomeV3/Controls/Lock.js +0 -36
- package/lib/AlexaSmartHomeV3/Controls/Motion.js +0 -17
- package/lib/AlexaSmartHomeV3/Controls/ReadOnlyDetector.js +0 -25
- package/lib/AlexaSmartHomeV3/Controls/Slider.js +0 -10
- package/lib/AlexaSmartHomeV3/Controls/Socket.js +0 -21
- package/lib/AlexaSmartHomeV3/Controls/Temperature.js +0 -22
- package/lib/AlexaSmartHomeV3/Controls/Thermostat.js +0 -86
- package/lib/AlexaSmartHomeV3/Controls/VacuumCleaner.js +0 -28
- package/lib/AlexaSmartHomeV3/Controls/Volume.js +0 -109
- package/lib/AlexaSmartHomeV3/Controls/VolumeGroup.js +0 -9
- package/lib/AlexaSmartHomeV3/Controls/Window.js +0 -9
- package/lib/AlexaSmartHomeV3/Controls/index.js +0 -14
- package/lib/AlexaSmartHomeV3/DeviceManager.js +0 -415
- package/lib/AlexaSmartHomeV3/Exceptions/AlexaV3Exception.js +0 -8
- package/lib/AlexaSmartHomeV3/Exceptions/HourlyDeviceRateLimitExceeded.js +0 -5
- package/lib/AlexaSmartHomeV3/Exceptions/OverallDailyRateLimitExceeded.js +0 -5
- package/lib/AlexaSmartHomeV3/Helpers/FileHelper.js +0 -70
- package/lib/AlexaSmartHomeV3/Helpers/Logger.js +0 -95
- package/lib/AlexaSmartHomeV3/Helpers/RateLimiter.js +0 -82
- package/lib/AlexaSmartHomeV3/Helpers/Utils.js +0 -583
- package/lib/Utils.js +0 -608
- package/lib/adminCommonSocket.js +0 -781
- package/lib/alexaCustom.js +0 -622
- package/lib/translate.js +0 -19
- package/main.js +0 -1454
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const uuid_1 = require("uuid");
|
|
7
|
+
const Utils_1 = require("./Helpers/Utils");
|
|
8
|
+
const Logger_1 = __importDefault(require("./Helpers/Logger"));
|
|
5
9
|
/**
|
|
6
10
|
* This class hides the different iobroker controls representing physical devices from Alexa
|
|
7
11
|
* and makes them appear as a single endpoint.
|
|
@@ -10,63 +14,58 @@ const Logger = require('./Helpers/Logger');
|
|
|
10
14
|
* to be the same endpoint from Alexa's perspective.
|
|
11
15
|
* This leads to a situation where while Alexa believes controlling a single endpoint by sending a directive
|
|
12
16
|
* to change the endpoint's state, in reality, the states of multiple controls, i.e. physical devices, are changed.
|
|
13
|
-
*
|
|
14
|
-
* @class
|
|
15
17
|
*/
|
|
16
18
|
class Device {
|
|
19
|
+
log;
|
|
20
|
+
id;
|
|
21
|
+
friendlyName;
|
|
22
|
+
controls;
|
|
23
|
+
autoDetected;
|
|
24
|
+
roomName;
|
|
25
|
+
funcName;
|
|
26
|
+
toggle;
|
|
27
|
+
description;
|
|
28
|
+
lastReportedState;
|
|
17
29
|
constructor(opts) {
|
|
18
|
-
this.
|
|
19
|
-
this.
|
|
20
|
-
this.
|
|
21
|
-
this.
|
|
22
|
-
this.autoDetected = opts.autoDetected;
|
|
30
|
+
this.log = new Logger_1.default(this);
|
|
31
|
+
this.id = (0, Utils_1.defaultIfNullOrEmpty)((0, Utils_1.endpointId)(opts.id), (0, uuid_1.v4)());
|
|
32
|
+
this.friendlyName = (0, Utils_1.defaultIfNullOrEmpty)(opts.friendlyName, (0, uuid_1.v4)());
|
|
33
|
+
this.controls = (0, Utils_1.defaultIfNullOrEmpty)(opts.controls, []);
|
|
34
|
+
this.autoDetected = !!opts.autoDetected;
|
|
23
35
|
this.roomName = opts.roomName;
|
|
24
36
|
this.funcName = opts.funcName;
|
|
25
37
|
this.toggle = opts.toggle;
|
|
26
38
|
}
|
|
27
|
-
|
|
28
39
|
supports(event) {
|
|
29
40
|
return this.controls.find(c => c.supports(event)) !== undefined;
|
|
30
41
|
}
|
|
31
|
-
|
|
32
42
|
async handle(event) {
|
|
33
43
|
this.log.debug(`handling alexa event`);
|
|
34
44
|
this.log.silly(`${JSON.stringify(event)}`);
|
|
35
|
-
|
|
36
45
|
const promises = [];
|
|
37
46
|
if (this.toggle) {
|
|
38
47
|
// get current state
|
|
39
48
|
event.currentState = await this.reportState();
|
|
40
49
|
}
|
|
41
|
-
|
|
42
50
|
this.controls.forEach(control => promises.push(control.handle(event)));
|
|
43
51
|
const results = await Promise.allSettled(promises);
|
|
44
|
-
|
|
45
52
|
const fulfilled = results.find(item => item.status === 'fulfilled');
|
|
46
|
-
// @ts-ignore
|
|
47
53
|
return fulfilled !== undefined ? fulfilled.value : results[0].reason;
|
|
48
54
|
}
|
|
49
|
-
|
|
50
55
|
async reportState() {
|
|
51
56
|
const promises = [];
|
|
52
57
|
this.controls.forEach(control => promises.push(control.reportState()));
|
|
53
58
|
const results = await Promise.allSettled(promises);
|
|
54
|
-
|
|
55
|
-
// @ts-ignore
|
|
56
59
|
const properties = results.filter(item => item.status === 'fulfilled').flatMap(item => item.value);
|
|
57
|
-
|
|
58
|
-
return Utils.distinctByPropertyName(properties, 'name', true);
|
|
60
|
+
return (0, Utils_1.distinctByPropertyName)(properties, 'name', true);
|
|
59
61
|
}
|
|
60
|
-
|
|
61
62
|
get capabilities() {
|
|
62
63
|
const allCapabilities = this.controls.flatMap(item => item.supported);
|
|
63
|
-
return
|
|
64
|
+
return (0, Utils_1.distinctByPropertyName)(allCapabilities, 'namespace');
|
|
64
65
|
}
|
|
65
|
-
|
|
66
66
|
get displayCategories() {
|
|
67
67
|
return Array.from(new Set(this.controls.flatMap(item => item.categories)));
|
|
68
68
|
}
|
|
69
|
-
|
|
70
69
|
toString() {
|
|
71
70
|
const controls = this.controls;
|
|
72
71
|
const controlsAsString = function () {
|
|
@@ -74,11 +73,11 @@ class Device {
|
|
|
74
73
|
for (const ctrl of controls) {
|
|
75
74
|
repr += `${ctrl.toString()}, `;
|
|
76
75
|
}
|
|
77
|
-
repr = repr.slice(0, -2)
|
|
76
|
+
repr = `${repr.slice(0, -2)})`;
|
|
78
77
|
return repr;
|
|
79
78
|
};
|
|
80
|
-
return `${this.friendlyName}
|
|
79
|
+
return `${this.friendlyName}${controlsAsString()}`;
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
exports.default = Device;
|
|
83
|
+
//# sourceMappingURL=Device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Device.js","sourceRoot":"","sources":["../../../src/lib/AlexaSmartHomeV3/Device.ts"],"names":[],"mappings":"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","sourcesContent":["import { v4 as uuidv4 } from 'uuid';\nimport { endpointId, defaultIfNullOrEmpty, distinctByPropertyName } from './Helpers/Utils';\nimport Logger from './Helpers/Logger';\nimport type { AlexaV3Category, AlexaV3Namespace, AlexaV3ReportedState, AlexaV3Request } from './types';\nimport type Control from './Controls/Control';\nimport type { Base as CapabilitiesBase } from './Alexa/Capabilities/Base';\nimport type AlexaResponse from './Alexa/AlexaResponse';\n\n/**\n * This class hides the different iobroker controls representing physical devices from Alexa\n * and makes them appear as a single endpoint.\n * Due to differences in Alexa's and iobroker's endpoint/devices concepts, we have to merge some of the\n * by the type-detector detected controls to a single device, so that multiple controls are considered\n * to be the same endpoint from Alexa's perspective.\n * This leads to a situation where while Alexa believes controlling a single endpoint by sending a directive\n * to change the endpoint's state, in reality, the states of multiple controls, i.e. physical devices, are changed.\n */\nexport default class Device {\n public log: Logger;\n public id: string;\n public friendlyName: string;\n public controls: Control[];\n public autoDetected: boolean;\n public roomName?: string;\n public funcName?: string;\n public toggle?: boolean;\n public description?: string;\n public lastReportedState?: any;\n\n constructor(opts: {\n id: string;\n friendlyName: string;\n controls: Control[];\n autoDetected?: boolean;\n roomName?: string;\n funcName?: string;\n toggle?: boolean;\n }) {\n this.log = new Logger(this);\n this.id = defaultIfNullOrEmpty<string>(endpointId(opts.id), uuidv4());\n this.friendlyName = defaultIfNullOrEmpty<string>(opts.friendlyName, uuidv4());\n this.controls = defaultIfNullOrEmpty<Control[]>(opts.controls, []);\n this.autoDetected = !!opts.autoDetected;\n this.roomName = opts.roomName;\n this.funcName = opts.funcName;\n this.toggle = opts.toggle;\n }\n\n supports(event: AlexaV3Request): boolean {\n return this.controls.find(c => c.supports(event)) !== undefined;\n }\n\n async handle(event: AlexaV3Request): Promise<AlexaResponse> {\n this.log.debug(`handling alexa event`);\n this.log.silly(`${JSON.stringify(event)}`);\n\n const promises: Promise<AlexaResponse>[] = [];\n if (this.toggle) {\n // get current state\n event.currentState = await this.reportState();\n }\n\n this.controls.forEach(control => promises.push(control.handle(event)));\n const results = await Promise.allSettled(promises);\n\n const fulfilled = results.find(item => item.status === 'fulfilled');\n\n return fulfilled !== undefined ? fulfilled.value : (results[0] as any).reason;\n }\n\n async reportState(): Promise<AlexaV3ReportedState[]> {\n const promises: Promise<AlexaV3ReportedState[]>[] = [];\n this.controls.forEach(control => promises.push(control.reportState()));\n const results = await Promise.allSettled(promises);\n\n const properties: {\n namespace: AlexaV3Namespace;\n instance?: string;\n name: string;\n value: any;\n }[] = results.filter(item => item.status === 'fulfilled').flatMap(item => item.value);\n\n return distinctByPropertyName<{\n namespace: AlexaV3Namespace;\n instance?: string;\n name: string;\n value: any;\n }>(properties, 'name', true);\n }\n\n get capabilities(): CapabilitiesBase[] {\n const allCapabilities = this.controls.flatMap(item => item.supported);\n return distinctByPropertyName(allCapabilities, 'namespace');\n }\n\n get displayCategories(): AlexaV3Category[] {\n return Array.from(new Set(this.controls.flatMap(item => item.categories)));\n }\n\n toString(): string {\n const controls = this.controls;\n const controlsAsString = function (): string {\n let repr = ' (Controls: ';\n for (const ctrl of controls) {\n repr += `${ctrl.toString()}, `;\n }\n repr = `${repr.slice(0, -2)})`;\n return repr;\n };\n return `${this.friendlyName}${controlsAsString()}`;\n }\n}\n"]}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const Device_1 = __importDefault(require("./Device"));
|
|
40
|
+
const Utils = __importStar(require("./Helpers/Utils"));
|
|
41
|
+
const Directives_1 = __importDefault(require("./Alexa/Directives"));
|
|
42
|
+
const Controls_1 = __importDefault(require("./Controls"));
|
|
43
|
+
const Logger_1 = __importDefault(require("./Helpers/Logger"));
|
|
44
|
+
const AdapterProvider_1 = __importDefault(require("./Helpers/AdapterProvider"));
|
|
45
|
+
const AlexaResponse_1 = __importDefault(require("./Alexa/AlexaResponse"));
|
|
46
|
+
const IotProxy_1 = __importDefault(require("./Helpers/IotProxy"));
|
|
47
|
+
const RateLimiter_1 = __importDefault(require("./Helpers/RateLimiter"));
|
|
48
|
+
const OverallDailyRateLimitExceeded_1 = __importDefault(require("./Exceptions/OverallDailyRateLimitExceeded"));
|
|
49
|
+
const HourlyDeviceRateLimitExceeded_1 = __importDefault(require("./Exceptions/HourlyDeviceRateLimitExceeded"));
|
|
50
|
+
const ChangeReport_1 = __importDefault(require("./Alexa/Directives/ChangeReport"));
|
|
51
|
+
const Discovery_1 = __importDefault(require("./Alexa/Directives/Discovery"));
|
|
52
|
+
const ReportState_1 = __importDefault(require("./Alexa/Directives/ReportState"));
|
|
53
|
+
const node_crypto_1 = require("node:crypto");
|
|
54
|
+
class DeviceManager {
|
|
55
|
+
lang = 'en';
|
|
56
|
+
devices = [];
|
|
57
|
+
subscribed = [];
|
|
58
|
+
log;
|
|
59
|
+
eventsPausedTill = 0; // timestamp
|
|
60
|
+
collecting = false;
|
|
61
|
+
recollect = false;
|
|
62
|
+
/** Creates a Device Manager */
|
|
63
|
+
constructor() {
|
|
64
|
+
this.log = new Logger_1.default(this);
|
|
65
|
+
}
|
|
66
|
+
informAboutStatesChange() {
|
|
67
|
+
void AdapterProvider_1.default.get().setState('smart.updates3', true, true);
|
|
68
|
+
}
|
|
69
|
+
get language() {
|
|
70
|
+
return this.lang;
|
|
71
|
+
}
|
|
72
|
+
set language(value) {
|
|
73
|
+
this.lang = value;
|
|
74
|
+
}
|
|
75
|
+
matchDirective(event) {
|
|
76
|
+
if (ChangeReport_1.default.matches(event)) {
|
|
77
|
+
return new ChangeReport_1.default();
|
|
78
|
+
}
|
|
79
|
+
if (Discovery_1.default.matches(event)) {
|
|
80
|
+
return new Discovery_1.default();
|
|
81
|
+
}
|
|
82
|
+
if (ReportState_1.default.matches(event)) {
|
|
83
|
+
return new ReportState_1.default();
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
get endpoints() {
|
|
88
|
+
return this.devices;
|
|
89
|
+
}
|
|
90
|
+
endpointById(id) {
|
|
91
|
+
return this.devices.find(device => device.id === id);
|
|
92
|
+
}
|
|
93
|
+
addDevice(device) {
|
|
94
|
+
this.devices.push(device);
|
|
95
|
+
}
|
|
96
|
+
toDevice(detectedControls, friendlyName, autoDetected, roomName, funcName, toggle) {
|
|
97
|
+
const controls = [];
|
|
98
|
+
this.log.debug(`merging controls to a device with name ${friendlyName}`);
|
|
99
|
+
detectedControls.forEach(item => {
|
|
100
|
+
this.log.silly(`processing control: ${JSON.stringify(item)}`);
|
|
101
|
+
const control = Controls_1.default.factory(item);
|
|
102
|
+
if (control) {
|
|
103
|
+
this.log.debug(`${item.type} added to ${friendlyName}`);
|
|
104
|
+
controls.push(control);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this.log.debug(`control of type ${item.type} not supported yet. Skipped.`);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
if (controls.length === 0) {
|
|
111
|
+
// the controls are not supported yet...
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// create and add a new device to the collected devices
|
|
115
|
+
this.addDevice(new Device_1.default({
|
|
116
|
+
id: friendlyName,
|
|
117
|
+
friendlyName,
|
|
118
|
+
controls,
|
|
119
|
+
autoDetected,
|
|
120
|
+
roomName,
|
|
121
|
+
funcName,
|
|
122
|
+
toggle,
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
getName(name) {
|
|
126
|
+
if (!name) {
|
|
127
|
+
return '';
|
|
128
|
+
}
|
|
129
|
+
if (typeof name === 'object') {
|
|
130
|
+
return name[this.lang] || name.en || '';
|
|
131
|
+
}
|
|
132
|
+
return name;
|
|
133
|
+
}
|
|
134
|
+
async collectEndpoints() {
|
|
135
|
+
if (this.collecting) {
|
|
136
|
+
this.log.debug(`collecting devices already in progress. Skipping...`);
|
|
137
|
+
this.recollect = true;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.collecting = true;
|
|
141
|
+
this.log.debug(`(re)collecting devices...`);
|
|
142
|
+
try {
|
|
143
|
+
// const discoveryNeeded = this.devices.length > 0;
|
|
144
|
+
this.devices = [];
|
|
145
|
+
const defaultToggle = AdapterProvider_1.default.get().config.defaultToggle || false;
|
|
146
|
+
// collect all iobroker controls in terms of iobroker type detector (https://github.com/ioBroker/ioBroker.type-detector)
|
|
147
|
+
let detectedControls = await Utils.controls(AdapterProvider_1.default.get(), this.lang);
|
|
148
|
+
this.log.debug(`type detector found ${detectedControls.length} controls`);
|
|
149
|
+
// Normally, every control is a smart device. But due to the iobroker concept of 'rooms and functions'
|
|
150
|
+
// multiple controls might be merged to a single device.
|
|
151
|
+
// as long as not all controls mapped to a device...
|
|
152
|
+
// detectedControls = detectedControls.filter(c => ['light', 'dimmer'].includes(c.type));
|
|
153
|
+
const createdGroups = [];
|
|
154
|
+
while (detectedControls.length) {
|
|
155
|
+
// take the next control
|
|
156
|
+
const control = detectedControls[0];
|
|
157
|
+
let processedControls = [];
|
|
158
|
+
if (control.room?.common?.name) {
|
|
159
|
+
if (control.functionality?.common?.name) {
|
|
160
|
+
// controls in the same room with the same functionality
|
|
161
|
+
processedControls = detectedControls.filter(item => control.room &&
|
|
162
|
+
item.room?.id === control.room.id &&
|
|
163
|
+
control.functionality &&
|
|
164
|
+
item.functionality?.id === control.functionality.id);
|
|
165
|
+
this.toDevice(processedControls, Utils.friendlyNameByRoomAndFunctionName(control, this.lang), true, this.getName(control.room?.common?.name), this.getName(control.functionality?.common?.name), processedControls[0].object?.toggle ?? defaultToggle);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
this.log.debug(`Control of type [${control.type}] assigned to room [${this.getName(control.room.common.name)}] has no function. Skipped.`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else if (control.groupNames) {
|
|
172
|
+
// no room, but smart name (not only one)
|
|
173
|
+
control.groupNames.forEach(groupName => {
|
|
174
|
+
if (!createdGroups.includes(groupName)) {
|
|
175
|
+
createdGroups.push(groupName);
|
|
176
|
+
processedControls = detectedControls.filter(item => item.groupNames?.includes(groupName));
|
|
177
|
+
this.toDevice(processedControls, this.getName(groupName), false, undefined, undefined, processedControls[0].object?.toggle ?? defaultToggle);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
// neither room nor smart name
|
|
183
|
+
this.log.debug(`Control of type [${control.type}] has neither room no smart name. Skipped.`);
|
|
184
|
+
}
|
|
185
|
+
if (processedControls.length === 0) {
|
|
186
|
+
processedControls = [control];
|
|
187
|
+
}
|
|
188
|
+
// remove processed controls
|
|
189
|
+
const objectIds = processedControls.map(item => item.object?.id);
|
|
190
|
+
detectedControls = detectedControls.filter(item => item.object && !objectIds.includes(item.object.id));
|
|
191
|
+
}
|
|
192
|
+
// done
|
|
193
|
+
this.log.debug(`finished collecting devices. there is/are ${this.devices.length} device(s) in total`);
|
|
194
|
+
for (const device of this.devices) {
|
|
195
|
+
this.log.debug(`${device.toString()}`);
|
|
196
|
+
}
|
|
197
|
+
// a new discovery process is needed in case we had already devices and device collection was
|
|
198
|
+
// triggered again by, e.g., a change in room/function enums
|
|
199
|
+
// if (discoveryNeeded) {
|
|
200
|
+
// this.log.info(`Please delete all managed by ioBroker devices in your Alexa app and then start discovery`);
|
|
201
|
+
// }
|
|
202
|
+
// collect all relevant states to subscribe to updates
|
|
203
|
+
const stateIds = new Set(this.devices
|
|
204
|
+
.flatMap(d => d.controls)
|
|
205
|
+
.flatMap(item => item.supported)
|
|
206
|
+
.flatMap(item => item.properties)
|
|
207
|
+
.map(item => item.getId)
|
|
208
|
+
.filter(id => id));
|
|
209
|
+
this.log.debug(`registering for updates of total ${stateIds.size} states`);
|
|
210
|
+
const promises = [];
|
|
211
|
+
const newSubscribed = Array.from(stateIds);
|
|
212
|
+
// subscribe to updates
|
|
213
|
+
for (const id of newSubscribed) {
|
|
214
|
+
this.log.silly(`subscribing to updates of ${id}`);
|
|
215
|
+
if (!this.subscribed.includes(id)) {
|
|
216
|
+
this.subscribed.push(id);
|
|
217
|
+
promises.push(AdapterProvider_1.default.subscribe(id));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
this.subscribed.sort();
|
|
221
|
+
// wait till all promises are settled
|
|
222
|
+
const results = await Promise.allSettled(promises);
|
|
223
|
+
// unsubscribe from unused states
|
|
224
|
+
for (let i = this.subscribed.length - 1; i >= 0; i--) {
|
|
225
|
+
const id = this.subscribed[i];
|
|
226
|
+
if (!newSubscribed.includes(id)) {
|
|
227
|
+
this.log.silly(`unsubscribing from updates of ${id}`);
|
|
228
|
+
this.subscribed.splice(i, 1);
|
|
229
|
+
await AdapterProvider_1.default.unsubscribe(id);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const failedReasons = results.filter(item => item.status !== 'fulfilled').flatMap(item => item.reason);
|
|
233
|
+
if (failedReasons.length) {
|
|
234
|
+
this.log.debug(`failed to subscribe for updates of ${failedReasons.length} states`);
|
|
235
|
+
try {
|
|
236
|
+
for (const reason of failedReasons) {
|
|
237
|
+
this.log.silly(`failed subscribing: ${typeof reason === 'string' ? reason : JSON.stringify(reason)}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
// nop
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
catch (e) {
|
|
246
|
+
this.log.error(`failed to collect devices: ${e}`);
|
|
247
|
+
}
|
|
248
|
+
this.collecting = false;
|
|
249
|
+
// if during the collection a new collection was triggered, start collecting again
|
|
250
|
+
if (this.recollect) {
|
|
251
|
+
this.recollect = false;
|
|
252
|
+
setTimeout(() => this.collectEndpoints(), 1000);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async destroy() {
|
|
256
|
+
const promises = [];
|
|
257
|
+
for (const id of this.subscribed) {
|
|
258
|
+
this.log.silly(`unsubscribing from updates of ${id}`);
|
|
259
|
+
promises.push(AdapterProvider_1.default.subscribe(id));
|
|
260
|
+
}
|
|
261
|
+
await Promise.allSettled(promises);
|
|
262
|
+
this.subscribed = [];
|
|
263
|
+
}
|
|
264
|
+
publishStateChange(stateChange) {
|
|
265
|
+
if (this.eventsPausedTill < Date.now()) {
|
|
266
|
+
this.log.silly(`publishing ${JSON.stringify(stateChange)}`);
|
|
267
|
+
IotProxy_1.default.publishStateChange(stateChange);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
pauseEvents() {
|
|
271
|
+
this.eventsPausedTill = Date.now() + 30 * 60 * 1000; // 30 minutes
|
|
272
|
+
}
|
|
273
|
+
async executeWithinRateLimits(endpointId, awaitable, errorResponse) {
|
|
274
|
+
try {
|
|
275
|
+
await RateLimiter_1.default.incrementAndGet(endpointId);
|
|
276
|
+
return await awaitable();
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
if (error instanceof OverallDailyRateLimitExceeded_1.default || error instanceof HourlyDeviceRateLimitExceeded_1.default) {
|
|
280
|
+
this.log.warn(error.message);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
this.log.error(error.message);
|
|
284
|
+
}
|
|
285
|
+
return errorResponse;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async handleAlexaEvent(event) {
|
|
289
|
+
this.log.debug(`incoming Alexa event`);
|
|
290
|
+
this.log.silly(`${JSON.stringify(event)}`);
|
|
291
|
+
if (!event?.directive?.header) {
|
|
292
|
+
throw new Error('Alexa event header is missing');
|
|
293
|
+
}
|
|
294
|
+
let response;
|
|
295
|
+
const directive = this.matchDirective(event);
|
|
296
|
+
if (directive) {
|
|
297
|
+
response = await directive.handle(event, this);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
const endpointId = event?.directive?.endpoint?.endpointId;
|
|
301
|
+
const device = endpointId ? this.endpointById(endpointId) : undefined;
|
|
302
|
+
if (device) {
|
|
303
|
+
if (device.supports(event)) {
|
|
304
|
+
response = await this.executeWithinRateLimits(endpointId, async () => {
|
|
305
|
+
response = await device.handle(event);
|
|
306
|
+
if (!AlexaResponse_1.default.isErrorResponse(response)) {
|
|
307
|
+
// report state change via voice interaction
|
|
308
|
+
const propertyName = response.context?.properties[0].name;
|
|
309
|
+
const responseEvent = ChangeReport_1.default.get(device.id, propertyName || '', false, event.directive.header.messageId);
|
|
310
|
+
const directive = this.matchDirective(responseEvent);
|
|
311
|
+
if (directive) {
|
|
312
|
+
// BF[2024.02.04]: temporarily disabled as produced a huge number of events
|
|
313
|
+
// const stateChange = await directive.handle(responseEvent, this);
|
|
314
|
+
// get device state (not just one control)
|
|
315
|
+
const deviceState = await device.reportState();
|
|
316
|
+
if (JSON.stringify(device.lastReportedState) !== JSON.stringify(deviceState)) {
|
|
317
|
+
device.lastReportedState = deviceState;
|
|
318
|
+
// fire state change report to Alexa
|
|
319
|
+
// BF[2024.02.04]: temporarily disabled as produced a huge number of events
|
|
320
|
+
// this.publishStateChange(stateChange);
|
|
321
|
+
this.informAboutStatesChange();
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
this.log.debug(`ignoring state change event for ${endpointId} due to the same_ value [${JSON.stringify(deviceState)}]`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return response;
|
|
329
|
+
}, AlexaResponse_1.default.endpointUnreachable(event.directive.header.messageId).get());
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
response = AlexaResponse_1.default.directiveNotSupportedByDevice(device.friendlyName, event.directive.header.namespace, event.directive.header.messageId, event.directive.header.payloadVersion).get();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
response = AlexaResponse_1.default.endpointUnreachable(event.directive.header.messageId).get();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
this.log.silly(`response: ${JSON.stringify(response)}`);
|
|
340
|
+
return response;
|
|
341
|
+
}
|
|
342
|
+
async handleStateUpdate(id, state) {
|
|
343
|
+
// ignore updates not confirmed by a corresponding device
|
|
344
|
+
if (!state?.ack) {
|
|
345
|
+
this.log.silly(`ignoring state change event for ${id} due to state.ack == ${state?.ack}`);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
let notFound = true;
|
|
349
|
+
for (const device of this.devices) {
|
|
350
|
+
const property = device.controls
|
|
351
|
+
.flatMap(item => item.supported)
|
|
352
|
+
.flatMap(item => item.properties)
|
|
353
|
+
.find(item => item.getId === id);
|
|
354
|
+
if (property) {
|
|
355
|
+
notFound = false;
|
|
356
|
+
if (property.currentValue === state.val) {
|
|
357
|
+
this.log.debug(`ignoring state change event for ${id} due to the same value [${state.val}]`);
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
property.currentValue = state.val;
|
|
361
|
+
const responseEvent = Directives_1.default.ChangeReport.get(device.id, property.propertyName, true, (0, node_crypto_1.randomUUID)());
|
|
362
|
+
const directive = this.matchDirective(responseEvent);
|
|
363
|
+
if (directive) {
|
|
364
|
+
// BF[2024.02.04]: temporarily disabled as produced a huge number of events
|
|
365
|
+
// const stateChange = await directive.handle(event, this);
|
|
366
|
+
// get device state (not just one control)
|
|
367
|
+
const deviceState = await device.reportState();
|
|
368
|
+
if (JSON.stringify(device.lastReportedState) !== JSON.stringify(deviceState)) {
|
|
369
|
+
device.lastReportedState = deviceState;
|
|
370
|
+
this.informAboutStatesChange();
|
|
371
|
+
// fire state change report to Alexa
|
|
372
|
+
// BF[2024.02.04]: temporarily disabled as produced a huge number of events
|
|
373
|
+
// await this.executeWithinRateLimits(device.id, async () =>
|
|
374
|
+
// this.publishStateChange(stateChange), undefined);
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
this.log.debug(`ignoring state change event for ${id} due to the same_ value [${JSON.stringify(deviceState)}]`);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
// should be the only device having the id => stop processing here
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
// this should never happen
|
|
386
|
+
if (notFound) {
|
|
387
|
+
this.log.debug(`state id ${id} doesn't belong to any device`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
exports.default = DeviceManager;
|
|
392
|
+
//# sourceMappingURL=DeviceManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeviceManager.js","sourceRoot":"","sources":["../../../src/lib/AlexaSmartHomeV3/DeviceManager.ts"],"names":[],"mappings":"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","sourcesContent":["import Device from './Device';\nimport * as Utils from './Helpers/Utils';\nimport Directives from './Alexa/Directives';\nimport Controls from './Controls';\nimport type Control from './Controls/Control';\nimport Logger from './Helpers/Logger';\nimport AdapterProvider from './Helpers/AdapterProvider';\nimport AlexaResponse from './Alexa/AlexaResponse';\nimport IotProxy from './Helpers/IotProxy';\nimport RateLimiter from './Helpers/RateLimiter';\nimport OverallDailyRateLimitExceeded from './Exceptions/OverallDailyRateLimitExceeded';\nimport HourlyDeviceRateLimitExceeded from './Exceptions/HourlyDeviceRateLimitExceeded';\nimport type { AlexaV3EndpointID, AlexaV3Request, IotExternalPatternControl } from './types';\nimport ChangeReport from './Alexa/Directives/ChangeReport';\nimport Discovery from './Alexa/Directives/Discovery';\nimport ReportState from './Alexa/Directives/ReportState';\nimport { randomUUID } from 'node:crypto';\n\nexport default class DeviceManager {\n private lang: ioBroker.Languages = 'en';\n private devices: Device[] = [];\n private subscribed: string[] = [];\n private log: Logger;\n private eventsPausedTill = 0; // timestamp\n\n private collecting = false;\n private recollect = false;\n\n /** Creates a Device Manager */\n constructor() {\n this.log = new Logger(this);\n }\n\n informAboutStatesChange(): void {\n void AdapterProvider.get().setState('smart.updates3', true, true);\n }\n\n get language(): ioBroker.Languages {\n return this.lang;\n }\n\n set language(value: ioBroker.Languages) {\n this.lang = value;\n }\n\n matchDirective(event: AlexaV3Request): ChangeReport | Discovery | ReportState | null {\n if (ChangeReport.matches(event)) {\n return new ChangeReport();\n }\n if (Discovery.matches(event)) {\n return new Discovery();\n }\n if (ReportState.matches(event)) {\n return new ReportState();\n }\n\n return null;\n }\n\n get endpoints(): Device[] {\n return this.devices;\n }\n\n endpointById(id: AlexaV3EndpointID): Device | undefined {\n return this.devices.find(device => device.id === id);\n }\n\n addDevice(device: Device): void {\n this.devices.push(device);\n }\n\n toDevice(\n detectedControls: IotExternalPatternControl[],\n friendlyName: string,\n autoDetected: boolean,\n roomName: string | undefined,\n funcName: string | undefined,\n toggle?: boolean,\n ): Device | undefined {\n const controls: Control[] = [];\n\n this.log.debug(`merging controls to a device with name ${friendlyName}`);\n\n detectedControls.forEach(item => {\n this.log.silly(`processing control: ${JSON.stringify(item)}`);\n const control = Controls.factory(item);\n if (control) {\n this.log.debug(`${item.type} added to ${friendlyName}`);\n controls.push(control);\n } else {\n this.log.debug(`control of type ${item.type} not supported yet. Skipped.`);\n }\n });\n\n if (controls.length === 0) {\n // the controls are not supported yet...\n return;\n }\n\n // create and add a new device to the collected devices\n this.addDevice(\n new Device({\n id: friendlyName,\n friendlyName,\n controls,\n autoDetected,\n roomName,\n funcName,\n toggle,\n }),\n );\n }\n\n getName(name: ioBroker.StringOrTranslated | undefined): string {\n if (!name) {\n return '';\n }\n if (typeof name === 'object') {\n return name[this.lang] || name.en || '';\n }\n return name;\n }\n\n async collectEndpoints(): Promise<void> {\n if (this.collecting) {\n this.log.debug(`collecting devices already in progress. Skipping...`);\n this.recollect = true;\n return;\n }\n this.collecting = true;\n this.log.debug(`(re)collecting devices...`);\n try {\n // const discoveryNeeded = this.devices.length > 0;\n\n this.devices = [];\n const defaultToggle = AdapterProvider.get().config.defaultToggle || false;\n\n // collect all iobroker controls in terms of iobroker type detector (https://github.com/ioBroker/ioBroker.type-detector)\n let detectedControls = await Utils.controls(AdapterProvider.get(), this.lang);\n\n this.log.debug(`type detector found ${detectedControls.length} controls`);\n\n // Normally, every control is a smart device. But due to the iobroker concept of 'rooms and functions'\n // multiple controls might be merged to a single device.\n\n // as long as not all controls mapped to a device...\n\n // detectedControls = detectedControls.filter(c => ['light', 'dimmer'].includes(c.type));\n const createdGroups: string[] = [];\n\n while (detectedControls.length) {\n // take the next control\n const control = detectedControls[0];\n let processedControls: IotExternalPatternControl[] = [];\n\n if (control.room?.common?.name) {\n if (control.functionality?.common?.name) {\n // controls in the same room with the same functionality\n processedControls = detectedControls.filter(\n item =>\n control.room &&\n item.room?.id === control.room.id &&\n control.functionality &&\n item.functionality?.id === control.functionality.id,\n );\n this.toDevice(\n processedControls,\n Utils.friendlyNameByRoomAndFunctionName(control, this.lang),\n true,\n this.getName(control.room?.common?.name),\n this.getName(control.functionality?.common?.name),\n processedControls[0].object?.toggle ?? defaultToggle,\n );\n } else {\n this.log.debug(\n `Control of type [${control.type}] assigned to room [${this.getName(control.room.common.name)}] has no function. Skipped.`,\n );\n }\n } else if (control.groupNames) {\n // no room, but smart name (not only one)\n control.groupNames.forEach(groupName => {\n if (!createdGroups.includes(groupName)) {\n createdGroups.push(groupName);\n processedControls = detectedControls.filter(item => item.groupNames?.includes(groupName));\n this.toDevice(\n processedControls,\n this.getName(groupName),\n false,\n undefined,\n undefined,\n processedControls[0].object?.toggle ?? defaultToggle,\n );\n }\n });\n } else {\n // neither room nor smart name\n this.log.debug(`Control of type [${control.type}] has neither room no smart name. Skipped.`);\n }\n\n if (processedControls.length === 0) {\n processedControls = [control];\n }\n\n // remove processed controls\n const objectIds = processedControls.map(item => item.object?.id);\n detectedControls = detectedControls.filter(item => item.object && !objectIds.includes(item.object.id));\n }\n\n // done\n this.log.debug(`finished collecting devices. there is/are ${this.devices.length} device(s) in total`);\n for (const device of this.devices) {\n this.log.debug(`${device.toString()}`);\n }\n\n // a new discovery process is needed in case we had already devices and device collection was\n // triggered again by, e.g., a change in room/function enums\n // if (discoveryNeeded) {\n // this.log.info(`Please delete all managed by ioBroker devices in your Alexa app and then start discovery`);\n // }\n\n // collect all relevant states to subscribe to updates\n const stateIds = new Set(\n this.devices\n .flatMap(d => d.controls)\n .flatMap(item => item.supported)\n .flatMap(item => item.properties)\n .map(item => item.getId)\n .filter(id => id),\n );\n this.log.debug(`registering for updates of total ${stateIds.size} states`);\n const promises = [];\n const newSubscribed = Array.from(stateIds);\n // subscribe to updates\n for (const id of newSubscribed) {\n this.log.silly(`subscribing to updates of ${id}`);\n if (!this.subscribed.includes(id)) {\n this.subscribed.push(id);\n promises.push(AdapterProvider.subscribe(id));\n }\n }\n\n this.subscribed.sort();\n\n // wait till all promises are settled\n const results = await Promise.allSettled(promises);\n\n // unsubscribe from unused states\n for (let i = this.subscribed.length - 1; i >= 0; i--) {\n const id = this.subscribed[i];\n if (!newSubscribed.includes(id)) {\n this.log.silly(`unsubscribing from updates of ${id}`);\n this.subscribed.splice(i, 1);\n await AdapterProvider.unsubscribe(id);\n }\n }\n\n const failedReasons = results.filter(item => item.status !== 'fulfilled').flatMap(item => item.reason);\n if (failedReasons.length) {\n this.log.debug(`failed to subscribe for updates of ${failedReasons.length} states`);\n try {\n for (const reason of failedReasons) {\n this.log.silly(\n `failed subscribing: ${typeof reason === 'string' ? reason : JSON.stringify(reason)}`,\n );\n }\n } catch {\n // nop\n }\n }\n } catch (e) {\n this.log.error(`failed to collect devices: ${e}`);\n }\n\n this.collecting = false;\n\n // if during the collection a new collection was triggered, start collecting again\n if (this.recollect) {\n this.recollect = false;\n setTimeout(() => this.collectEndpoints(), 1000);\n }\n }\n\n async destroy(): Promise<void> {\n const promises = [];\n for (const id of this.subscribed) {\n this.log.silly(`unsubscribing from updates of ${id}`);\n promises.push(AdapterProvider.subscribe(id));\n }\n await Promise.allSettled(promises);\n\n this.subscribed = [];\n }\n\n publishStateChange(stateChange: AlexaResponse): void {\n if (this.eventsPausedTill < Date.now()) {\n this.log.silly(`publishing ${JSON.stringify(stateChange)}`);\n IotProxy.publishStateChange(stateChange);\n }\n }\n\n pauseEvents(): void {\n this.eventsPausedTill = Date.now() + 30 * 60 * 1000; // 30 minutes\n }\n\n async executeWithinRateLimits(\n endpointId: AlexaV3EndpointID,\n awaitable: () => Promise<AlexaResponse>,\n errorResponse: AlexaResponse,\n ): Promise<AlexaResponse> {\n try {\n await RateLimiter.incrementAndGet(endpointId);\n return await awaitable();\n } catch (error) {\n if (error instanceof OverallDailyRateLimitExceeded || error instanceof HourlyDeviceRateLimitExceeded) {\n this.log.warn(error.message);\n } else {\n this.log.error(error.message);\n }\n\n return errorResponse;\n }\n }\n\n async handleAlexaEvent(event: AlexaV3Request): Promise<AlexaResponse> {\n this.log.debug(`incoming Alexa event`);\n this.log.silly(`${JSON.stringify(event)}`);\n if (!event?.directive?.header) {\n throw new Error('Alexa event header is missing');\n }\n\n let response: AlexaResponse;\n const directive = this.matchDirective(event);\n if (directive) {\n response = await directive.handle(event, this);\n } else {\n const endpointId = event?.directive?.endpoint?.endpointId;\n const device = endpointId ? this.endpointById(endpointId) : undefined;\n\n if (device) {\n if (device.supports(event)) {\n response = await this.executeWithinRateLimits(\n endpointId!,\n async () => {\n response = await device.handle(event);\n if (!AlexaResponse.isErrorResponse(response)) {\n // report state change via voice interaction\n const propertyName = response.context?.properties[0].name;\n const responseEvent = ChangeReport.get(\n device.id,\n propertyName || '',\n false,\n event.directive.header.messageId,\n );\n const directive = this.matchDirective(responseEvent);\n if (directive) {\n // BF[2024.02.04]: temporarily disabled as produced a huge number of events\n // const stateChange = await directive.handle(responseEvent, this);\n // get device state (not just one control)\n const deviceState = await device.reportState();\n if (JSON.stringify(device.lastReportedState) !== JSON.stringify(deviceState)) {\n device.lastReportedState = deviceState;\n // fire state change report to Alexa\n // BF[2024.02.04]: temporarily disabled as produced a huge number of events\n // this.publishStateChange(stateChange);\n this.informAboutStatesChange();\n } else {\n this.log.debug(\n `ignoring state change event for ${endpointId} due to the same_ value [${JSON.stringify(deviceState)}]`,\n );\n }\n }\n }\n return response;\n },\n AlexaResponse.endpointUnreachable(event.directive.header.messageId).get(),\n );\n } else {\n response = AlexaResponse.directiveNotSupportedByDevice(\n device.friendlyName,\n event.directive.header.namespace,\n event.directive.header.messageId,\n event.directive.header.payloadVersion,\n ).get();\n }\n } else {\n response = AlexaResponse.endpointUnreachable(event.directive.header.messageId).get();\n }\n }\n\n this.log.silly(`response: ${JSON.stringify(response)}`);\n return response;\n }\n\n async handleStateUpdate(id: string, state: ioBroker.State | null | undefined): Promise<void> {\n // ignore updates not confirmed by a corresponding device\n if (!state?.ack) {\n this.log.silly(`ignoring state change event for ${id} due to state.ack == ${state?.ack}`);\n return;\n }\n\n let notFound = true;\n\n for (const device of this.devices) {\n const property = device.controls\n .flatMap(item => item.supported)\n .flatMap(item => item.properties)\n .find(item => item.getId === id);\n\n if (property) {\n notFound = false;\n if (property.currentValue === state.val) {\n this.log.debug(`ignoring state change event for ${id} due to the same value [${state.val}]`);\n } else {\n property.currentValue = state.val;\n\n const responseEvent = Directives.ChangeReport.get(\n device.id,\n property.propertyName,\n true,\n randomUUID(),\n );\n const directive = this.matchDirective(responseEvent);\n if (directive) {\n // BF[2024.02.04]: temporarily disabled as produced a huge number of events\n // const stateChange = await directive.handle(event, this);\n\n // get device state (not just one control)\n const deviceState = await device.reportState();\n\n if (JSON.stringify(device.lastReportedState) !== JSON.stringify(deviceState)) {\n device.lastReportedState = deviceState;\n this.informAboutStatesChange();\n // fire state change report to Alexa\n\n // BF[2024.02.04]: temporarily disabled as produced a huge number of events\n // await this.executeWithinRateLimits(device.id, async () =>\n // this.publishStateChange(stateChange), undefined);\n } else {\n this.log.debug(\n `ignoring state change event for ${id} due to the same_ value [${JSON.stringify(deviceState)}]`,\n );\n }\n }\n }\n\n // should be the only device having the id => stop processing here\n break;\n }\n }\n\n // this should never happen\n if (notFound) {\n this.log.debug(`state id ${id} doesn't belong to any device`);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class AlexaV3Exception extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = this.constructor.name;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
exports.default = AlexaV3Exception;
|
|
10
|
+
//# sourceMappingURL=AlexaV3Exception.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AlexaV3Exception.js","sourceRoot":"","sources":["../../../../src/lib/AlexaSmartHomeV3/Exceptions/AlexaV3Exception.ts"],"names":[],"mappings":";;AAAA,MAAqB,gBAAiB,SAAQ,KAAK;IAC/C,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACtC,CAAC;CACJ;AALD,mCAKC","sourcesContent":["export default class AlexaV3Exception extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const AlexaV3Exception_1 = __importDefault(require("./AlexaV3Exception"));
|
|
7
|
+
class HourlyDeviceRateLimitExceeded extends AlexaV3Exception_1.default {
|
|
8
|
+
}
|
|
9
|
+
exports.default = HourlyDeviceRateLimitExceeded;
|
|
10
|
+
//# sourceMappingURL=HourlyDeviceRateLimitExceeded.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HourlyDeviceRateLimitExceeded.js","sourceRoot":"","sources":["../../../../src/lib/AlexaSmartHomeV3/Exceptions/HourlyDeviceRateLimitExceeded.ts"],"names":[],"mappings":";;;;;AAAA,0EAAkD;AAElD,MAAqB,6BAA8B,SAAQ,0BAAgB;CAAG;AAA9E,gDAA8E","sourcesContent":["import AlexaV3Exception from './AlexaV3Exception';\n\nexport default class HourlyDeviceRateLimitExceeded extends AlexaV3Exception {}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const AlexaV3Exception_1 = __importDefault(require("./AlexaV3Exception"));
|
|
7
|
+
class OverallDailyRateLimitExceeded extends AlexaV3Exception_1.default {
|
|
8
|
+
}
|
|
9
|
+
exports.default = OverallDailyRateLimitExceeded;
|
|
10
|
+
//# sourceMappingURL=OverallDailyRateLimitExceeded.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OverallDailyRateLimitExceeded.js","sourceRoot":"","sources":["../../../../src/lib/AlexaSmartHomeV3/Exceptions/OverallDailyRateLimitExceeded.ts"],"names":[],"mappings":";;;;;AAAA,0EAAkD;AAElD,MAAqB,6BAA8B,SAAQ,0BAAgB;CAAG;AAA9E,gDAA8E","sourcesContent":["import AlexaV3Exception from './AlexaV3Exception';\n\nexport default class OverallDailyRateLimitExceeded extends AlexaV3Exception {}\n"]}
|