@homebridge-plugins/homebridge-tuya 3.0.0-beta.2 → 3.0.0-beta.21
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 +354 -142
- package/config.schema.json +1221 -893
- package/dist/cloud/api/TuyaOpenAPI.js +108 -60
- package/dist/cloud/api/TuyaOpenAPI.js.map +1 -1
- package/dist/cloud/api/TuyaOpenMQ.js +45 -22
- package/dist/cloud/api/TuyaOpenMQ.js.map +1 -1
- package/dist/cloud/device/{TuyaDeviceManager.js → TuyaCloudDeviceManager.js} +146 -96
- package/dist/cloud/device/TuyaCloudDeviceManager.js.map +1 -0
- package/dist/cloud/device/TuyaCustomDeviceManager.js +75 -5
- package/dist/cloud/device/TuyaCustomDeviceManager.js.map +1 -1
- package/dist/cloud/device/TuyaDevice.js.map +1 -1
- package/dist/cloud/device/TuyaHomeDeviceManager.js +81 -13
- package/dist/cloud/device/TuyaHomeDeviceManager.js.map +1 -1
- package/dist/config.js +26 -5
- package/dist/config.js.map +1 -1
- package/dist/local/DynamicChildDiscovery.js +2 -1
- package/dist/local/DynamicChildDiscovery.js.map +1 -1
- package/dist/local/LocalDevice.js +16 -3
- package/dist/local/LocalDevice.js.map +1 -1
- package/dist/local/LocalDeviceManager.js +361 -164
- package/dist/local/LocalDeviceManager.js.map +1 -1
- package/dist/local/TuyaDiscovery.js +16 -7
- package/dist/local/TuyaDiscovery.js.map +1 -1
- package/dist/local/ZigbeeGatewayDetection.js +7 -4
- package/dist/local/ZigbeeGatewayDetection.js.map +1 -1
- package/dist/local/protocol/ProtocolUtilities.js +34 -17
- package/dist/local/protocol/ProtocolUtilities.js.map +1 -1
- package/dist/local/protocol/ProtocolV31V32.js +4 -2
- package/dist/local/protocol/ProtocolV31V32.js.map +1 -1
- package/dist/local/protocol/ProtocolV33.js +4 -2
- package/dist/local/protocol/ProtocolV33.js.map +1 -1
- package/dist/local/protocol/ProtocolV34.js +10 -5
- package/dist/local/protocol/ProtocolV34.js.map +1 -1
- package/dist/local/protocol/ProtocolV35.js +8 -4
- package/dist/local/protocol/ProtocolV35.js.map +1 -1
- package/dist/platform.js +253 -493
- package/dist/platform.js.map +1 -1
- package/dist/settings.js +0 -2
- package/dist/settings.js.map +1 -1
- package/dist/shared/TuyaDeviceManager.js +147 -0
- package/dist/shared/TuyaDeviceManager.js.map +1 -0
- package/dist/shared/TuyaHybridDeviceManager.js +215 -0
- package/dist/shared/TuyaHybridDeviceManager.js.map +1 -0
- package/dist/shared/accessory/AccessoryFactory.js +350 -0
- package/dist/shared/accessory/AccessoryFactory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/AirConditionerAccessory.js +21 -15
- package/dist/shared/accessory/AirConditionerAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/AirPurifierAccessory.js.map +1 -1
- package/dist/shared/accessory/AirQualitySensorAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/BaseAccessory.js +16 -95
- package/dist/shared/accessory/BaseAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/BlindsAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/CameraAccessory.js +2 -2
- package/dist/shared/accessory/CameraAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/CarbonDioxideSensorAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/CarbonMonoxideSensorAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/ContactSensorAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/DehumidifierAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/DiffuserAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/DimmerAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/DoorbellAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/ExtractionHoodAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/FanAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/GarageDoorAccessory.js +19 -2
- package/dist/shared/accessory/GarageDoorAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/HeaterAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/HeaterAccessory_old.js.map +1 -1
- package/dist/shared/accessory/HumanPresenceSensorAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/HumidifierAccessory.js.map +1 -1
- package/dist/shared/accessory/IRAdapter.js +167 -0
- package/dist/shared/accessory/IRAdapter.js.map +1 -0
- package/dist/shared/accessory/IRAirConditionerAccessory.js.map +1 -0
- package/dist/shared/accessory/IRControlHubAccessory.js.map +1 -0
- package/dist/shared/accessory/IRControlHubSubAccessory.js.map +1 -0
- package/dist/shared/accessory/IRFanAccessory.js +90 -0
- package/dist/shared/accessory/IRFanAccessory.js.map +1 -0
- package/dist/shared/accessory/IRGenericAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/LeakSensorAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/LightAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/LightSensorAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/LocationWeatherAccessory.js +1 -1
- package/dist/shared/accessory/LocationWeatherAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/LockAccessory.js +3 -3
- package/dist/shared/{accessories → accessory}/LockAccessory.js.map +1 -1
- package/dist/shared/accessory/MotionSensorAccessory.js.map +1 -0
- package/dist/shared/accessory/OutletAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/PetFeederAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/SceneAccessory.js +1 -1
- package/dist/shared/accessory/SceneAccessory.js.map +1 -0
- package/dist/shared/accessory/SceneSwitchAccessory.js.map +1 -0
- package/dist/shared/accessory/SecuritySystemAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/SmokeSensorAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/SwitchAccessory.js +1 -45
- package/dist/shared/accessory/SwitchAccessory.js.map +1 -0
- package/dist/shared/accessory/TemperatureHumiditySensorAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/ThermostatAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/TowerRackAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/ValveAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/VibrationSensorAccessory.js.map +1 -1
- package/dist/shared/accessory/WeatherStationAccessory.js.map +1 -0
- package/dist/shared/accessory/WetBulbGlobeTemperatureAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/WhiteNoiseLightAccessory.js +1 -0
- package/dist/shared/accessory/WhiteNoiseLightAccessory.js.map +1 -0
- package/dist/shared/accessory/WindowAccessory.js.map +1 -0
- package/dist/shared/{accessories → accessory}/WindowCoveringAccessory.js.map +1 -1
- package/dist/shared/{accessories → accessory}/WirelessSwitchAccessory.js.map +1 -1
- package/dist/shared/accessory/characteristic/Active.js.map +1 -0
- package/dist/shared/accessory/characteristic/AirQuality.js.map +1 -0
- package/dist/shared/{accessories → accessory}/characteristic/CurrentRelativeHumidity.js +3 -0
- package/dist/shared/accessory/characteristic/CurrentRelativeHumidity.js.map +1 -0
- package/dist/shared/accessory/characteristic/CurrentTemperature.js.map +1 -0
- package/dist/shared/accessory/characteristic/CurrentWeather.js.map +1 -0
- package/dist/shared/accessory/characteristic/CurrentWeatherByOpenMeteo.js.map +1 -0
- package/dist/shared/{accessories → accessory}/characteristic/CurrentWetBulbGlobeTemperature.js +3 -2
- package/dist/shared/accessory/characteristic/CurrentWetBulbGlobeTemperature.js.map +1 -0
- package/dist/shared/{accessories → accessory}/characteristic/EnergyUsage.js +0 -5
- package/dist/shared/accessory/characteristic/EnergyUsage.js.map +1 -0
- package/dist/shared/{accessories → accessory}/characteristic/Light.js +28 -5
- package/dist/shared/accessory/characteristic/Light.js.map +1 -0
- package/dist/shared/accessory/characteristic/LightSensor.js.map +1 -0
- package/dist/shared/{accessories → accessory}/characteristic/LockPhysicalControls.js +3 -0
- package/dist/shared/accessory/characteristic/LockPhysicalControls.js.map +1 -0
- package/dist/shared/accessory/characteristic/MotionDetected.js.map +1 -0
- package/dist/shared/accessory/characteristic/Name.js.map +1 -0
- package/dist/shared/accessory/characteristic/OccupancyDetected.js.map +1 -0
- package/dist/shared/{accessories → accessory}/characteristic/On.js +1 -0
- package/dist/shared/accessory/characteristic/On.js.map +1 -0
- package/dist/shared/accessory/characteristic/OutletInUse.js.map +1 -0
- package/dist/shared/accessory/characteristic/ProgrammableSwitchEvent.js.map +1 -0
- package/dist/shared/{accessories → accessory}/characteristic/RelativeHumidityDehumidifierThreshold.js +3 -0
- package/dist/shared/accessory/characteristic/RelativeHumidityDehumidifierThreshold.js.map +1 -0
- package/dist/shared/accessory/characteristic/RotationSpeed.js.map +1 -0
- package/dist/shared/accessory/characteristic/SecuritySystemState.js.map +1 -0
- package/dist/shared/{accessories → accessory}/characteristic/SwingMode.js +3 -0
- package/dist/shared/accessory/characteristic/SwingMode.js.map +1 -0
- package/dist/shared/accessory/characteristic/TargetTemperature.js.map +1 -0
- package/dist/shared/accessory/characteristic/TemperatureDisplayUnits.js.map +1 -0
- package/dist/shared/util/ConfigHash.js +2 -2
- package/dist/shared/util/ConfigHash.js.map +1 -1
- package/dist/shared/util/ConfigMigrator.js +222 -0
- package/dist/shared/util/ConfigMigrator.js.map +1 -0
- package/dist/shared/util/FfmpegStreamingProcess.js +62 -0
- package/dist/shared/util/FfmpegStreamingProcess.js.map +1 -1
- package/dist/shared/util/InfraredTool.js +0 -2
- package/dist/shared/util/InfraredTool.js.map +1 -1
- package/dist/shared/util/Logger.js +85 -10
- package/dist/shared/util/Logger.js.map +1 -1
- package/dist/shared/util/TuyaStreamDelegate.js +194 -97
- package/dist/shared/util/TuyaStreamDelegate.js.map +1 -1
- package/dist/shared/util/util.js +59 -4
- package/dist/shared/util/util.js.map +1 -1
- package/docs/ADVANCED_OPTIONS.md +603 -0
- package/docs/CONFIG_GUIDE.md +616 -0
- package/docs/Get-Local-Keys-for-Your-Devices.md +246 -0
- package/{SUPPORTED_DEVICES.md → docs/SUPPORTED_DEVICES.md} +24 -3
- package/eslint.config.mjs +0 -1
- package/{jest.config.js → jest.config.ts} +5 -2
- package/package.json +12 -9
- package/test/ConfigMigrator.test.ts +1060 -0
- package/test/Logger.test.ts +482 -0
- package/test/accessoryFactory.data.test.ts +172 -0
- package/test/accessoryFactory.test.ts +64 -35
- package/test/airConditioner.test.ts +742 -0
- package/test/config.test.ts +17 -13
- package/test/custom.test.ts +2 -2
- package/test/errorHandling.test.ts +12 -12
- package/test/home.test.ts +1 -1
- package/test/hybridDeviceManager.test.ts +808 -0
- package/test/light.test.ts +250 -0
- package/test/localDevice.test.ts +21 -50
- package/test/localDeviceManager.behavior.test.ts +196 -31
- package/test/localDeviceManager.test.ts +124 -41
- package/test/mqttMessages.test.ts +33 -14
- package/test/platform.test.ts +337 -814
- package/test/platform.validation.local.test.ts +58 -119
- package/test/tuyaCustomDeviceManager.test.ts +106 -16
- package/test/tuyaDeviceManager.test.ts +636 -639
- package/test/tuyaDiscovery.test.ts +21 -33
- package/test/tuyaHomeDeviceManager.test.ts +109 -18
- package/test/tuyaOpenAPI.test.ts +25 -44
- package/test/tuyaOpenMQ.test.ts +15 -23
- package/test/util.test.ts +107 -7
- package/test/zigbee/LocalDevice.zigbee.test.ts +14 -18
- package/test/zigbee/LocalDeviceManager.cloud-discovery.test.ts +19 -20
- package/test/zigbee/LocalDeviceManager.zigbee.reconnect.test.ts +19 -20
- package/test/zigbee/LocalDeviceManager.zigbee.test.ts +73 -35
- package/test/zigbee/ZigbeeGatewayDetection.test.ts +2 -2
- package/ADVANCED_OPTIONS.md +0 -267
- package/dist/cloud/device/TuyaDeviceManager.js.map +0 -1
- package/dist/local/CloudLocalReconciliation.js +0 -180
- package/dist/local/CloudLocalReconciliation.js.map +0 -1
- package/dist/shared/AccessoryFactory.js +0 -276
- package/dist/shared/AccessoryFactory.js.map +0 -1
- package/dist/shared/accessories/AccessoryFactory.js +0 -305
- package/dist/shared/accessories/AccessoryFactory.js.map +0 -1
- package/dist/shared/accessories/AirConditionerAccessory.js.map +0 -1
- package/dist/shared/accessories/AirQualitySensorAccessory.js.map +0 -1
- package/dist/shared/accessories/BaseAccessory.js.map +0 -1
- package/dist/shared/accessories/CameraAccessory.js.map +0 -1
- package/dist/shared/accessories/GarageDoorAccessory.js.map +0 -1
- package/dist/shared/accessories/HumanPresenceSensorAccessory.js.map +0 -1
- package/dist/shared/accessories/IRAirConditionerAccessory.js.map +0 -1
- package/dist/shared/accessories/IRControlHubAccessory.js.map +0 -1
- package/dist/shared/accessories/IRControlHubSubAccessory.js.map +0 -1
- package/dist/shared/accessories/IRGenericAccessory.js.map +0 -1
- package/dist/shared/accessories/LocationWeatherAccessory.js.map +0 -1
- package/dist/shared/accessories/MotionSensorAccessory.js.map +0 -1
- package/dist/shared/accessories/OutletAccessory.js.map +0 -1
- package/dist/shared/accessories/SceneAccessory.js.map +0 -1
- package/dist/shared/accessories/SceneSwitchAccessory.js.map +0 -1
- package/dist/shared/accessories/SecuritySystemAccessory.js.map +0 -1
- package/dist/shared/accessories/SwitchAccessory.js.map +0 -1
- package/dist/shared/accessories/TemperatureHumiditySensorAccessory.js.map +0 -1
- package/dist/shared/accessories/WeatherStationAccessory.js.map +0 -1
- package/dist/shared/accessories/WetBulbGlobeTemperatureAccessory.js.map +0 -1
- package/dist/shared/accessories/WhiteNoiseLightAccessory.js.map +0 -1
- package/dist/shared/accessories/WindowAccessory.js.map +0 -1
- package/dist/shared/accessories/characteristic/Active.js.map +0 -1
- package/dist/shared/accessories/characteristic/AirQuality.js.map +0 -1
- package/dist/shared/accessories/characteristic/CurrentRelativeHumidity.js.map +0 -1
- package/dist/shared/accessories/characteristic/CurrentTemperature.js.map +0 -1
- package/dist/shared/accessories/characteristic/CurrentWeather.js.map +0 -1
- package/dist/shared/accessories/characteristic/CurrentWeatherByOpenMeteo.js.map +0 -1
- package/dist/shared/accessories/characteristic/CurrentWetBulbGlobeTemperature.js.map +0 -1
- package/dist/shared/accessories/characteristic/EnergyUsage.js.map +0 -1
- package/dist/shared/accessories/characteristic/Light.js.map +0 -1
- package/dist/shared/accessories/characteristic/LightSensor.js.map +0 -1
- package/dist/shared/accessories/characteristic/LockPhysicalControls.js.map +0 -1
- package/dist/shared/accessories/characteristic/MotionDetected.js.map +0 -1
- package/dist/shared/accessories/characteristic/Name.js.map +0 -1
- package/dist/shared/accessories/characteristic/OccupancyDetected.js.map +0 -1
- package/dist/shared/accessories/characteristic/On.js.map +0 -1
- package/dist/shared/accessories/characteristic/OutletInUse.js.map +0 -1
- package/dist/shared/accessories/characteristic/ProgrammableSwitchEvent.js.map +0 -1
- package/dist/shared/accessories/characteristic/RelativeHumidityDehumidifierThreshold.js.map +0 -1
- package/dist/shared/accessories/characteristic/RotationSpeed.js.map +0 -1
- package/dist/shared/accessories/characteristic/SecuritySystemState.js.map +0 -1
- package/dist/shared/accessories/characteristic/SwingMode.js.map +0 -1
- package/dist/shared/accessories/characteristic/TargetTemperature.js.map +0 -1
- package/dist/shared/accessories/characteristic/TemperatureDisplayUnits.js.map +0 -1
- package/test/zigbee/CloudLocalReconciliation.test.ts +0 -284
- package/tuya-local-configs/dev-1.hash +0 -1
- package/tuya-local-configs/device1.hash +0 -1
- package/wiki/Get-Local-Keys-for-Your-Devices.md +0 -85
- /package/dist/shared/{accessories → accessory}/AirPurifierAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/AirQualitySensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/BlindsAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/CarbonDioxideSensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/CarbonMonoxideSensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/ContactSensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/DehumidifierAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/DiffuserAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/DimmerAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/DoorbellAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/ExtractionHoodAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/FanAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/HeaterAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/HeaterAccessory_old.js +0 -0
- /package/dist/shared/{accessories → accessory}/HumanPresenceSensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/HumidifierAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/IRAirConditionerAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/IRControlHubAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/IRControlHubSubAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/IRGenericAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/LeakSensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/LightAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/LightSensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/MotionSensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/OutletAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/PetFeederAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/SceneSwitchAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/SecuritySystemAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/SmokeSensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/TemperatureHumiditySensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/ThermostatAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/TowerRackAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/ValveAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/VibrationSensorAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/WeatherStationAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/WetBulbGlobeTemperatureAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/WindowAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/WindowCoveringAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/WirelessSwitchAccessory.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/Active.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/AirQuality.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/CurrentTemperature.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/CurrentWeather.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/CurrentWeatherByOpenMeteo.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/LightSensor.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/MotionDetected.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/Name.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/OccupancyDetected.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/OutletInUse.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/ProgrammableSwitchEvent.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/RotationSpeed.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/SecuritySystemState.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/TargetTemperature.js +0 -0
- /package/dist/shared/{accessories → accessory}/characteristic/TemperatureDisplayUnits.js +0 -0
|
@@ -2,19 +2,17 @@
|
|
|
2
2
|
import { describe, expect, it, beforeEach, jest } from '@jest/globals';
|
|
3
3
|
import EventEmitter from 'events';
|
|
4
4
|
import LocalDevice, { LocalDeviceContext } from '../../src/local/LocalDevice';
|
|
5
|
+
import { ExLogger, initLogger } from '../../src/shared/util/Logger';
|
|
5
6
|
|
|
6
7
|
// ── Logger mock ───────────────────────────────────────────────────────────────
|
|
7
|
-
|
|
8
|
-
jest.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
debug() {}; info() {}; warn() {}; error() {};
|
|
16
|
-
},
|
|
17
|
-
}));
|
|
8
|
+
const mockLog: ExLogger = {
|
|
9
|
+
debug: jest.fn(),
|
|
10
|
+
info: jest.fn(),
|
|
11
|
+
warn: jest.fn(),
|
|
12
|
+
error: jest.fn(),
|
|
13
|
+
log: jest.fn(),
|
|
14
|
+
success: jest.fn(),
|
|
15
|
+
} as unknown as ExLogger;
|
|
18
16
|
|
|
19
17
|
// ── Protocol mock ──────────────────────────────────────────────────────────────
|
|
20
18
|
|
|
@@ -46,11 +44,6 @@ jest.mock('net', () => ({
|
|
|
46
44
|
}));
|
|
47
45
|
|
|
48
46
|
// ── Helpers ────────────────────────────────────────────────────────────────────
|
|
49
|
-
|
|
50
|
-
function makeLogger() {
|
|
51
|
-
return { log: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn(), debug: jest.fn() } as any;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
47
|
function makeParent(overrides: Partial<LocalDeviceContext> = {}): LocalDevice {
|
|
55
48
|
const ctx: LocalDeviceContext = {
|
|
56
49
|
id: 'gateway_001',
|
|
@@ -60,7 +53,7 @@ function makeParent(overrides: Partial<LocalDeviceContext> = {}): LocalDevice {
|
|
|
60
53
|
name: 'Test Gateway',
|
|
61
54
|
...overrides,
|
|
62
55
|
};
|
|
63
|
-
return new LocalDevice(ctx
|
|
56
|
+
return new LocalDevice(ctx);
|
|
64
57
|
}
|
|
65
58
|
|
|
66
59
|
function makeChild(parent: LocalDevice, cid: string): LocalDevice {
|
|
@@ -71,7 +64,7 @@ function makeChild(parent: LocalDevice, cid: string): LocalDevice {
|
|
|
71
64
|
version: '3.3',
|
|
72
65
|
name: 'Test Child',
|
|
73
66
|
};
|
|
74
|
-
const child = new LocalDevice(ctx
|
|
67
|
+
const child = new LocalDevice(ctx);
|
|
75
68
|
child.parentDevice = parent;
|
|
76
69
|
child.childId = cid;
|
|
77
70
|
parent.children.set(cid, child);
|
|
@@ -81,6 +74,9 @@ function makeChild(parent: LocalDevice, cid: string): LocalDevice {
|
|
|
81
74
|
// ── Tests ──────────────────────────────────────────────────────────────────────
|
|
82
75
|
|
|
83
76
|
describe('LocalDevice – Zigbee parent/child', () => {
|
|
77
|
+
beforeEach(() => {
|
|
78
|
+
initLogger(mockLog);
|
|
79
|
+
});
|
|
84
80
|
|
|
85
81
|
describe('children Map', () => {
|
|
86
82
|
it('starts as an empty Map', () => {
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { describe, expect, it, beforeEach, afterEach, jest } from '@jest/globals';
|
|
2
2
|
import LocalDeviceManager from '../../src/local/LocalDeviceManager';
|
|
3
3
|
import { LocalConfig } from '../../src/local/config';
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
4
|
+
import { ExLogger, initLogger } from '../../src/shared/util/Logger';
|
|
5
|
+
|
|
6
|
+
// Mock Logger
|
|
7
|
+
const mockLog: ExLogger = {
|
|
8
|
+
debug: jest.fn(),
|
|
9
|
+
info: jest.fn(),
|
|
10
|
+
warn: jest.fn(),
|
|
11
|
+
error: jest.fn(),
|
|
12
|
+
log: jest.fn(),
|
|
13
|
+
success: jest.fn(),
|
|
14
|
+
} as unknown as ExLogger;
|
|
15
15
|
|
|
16
16
|
describe('LocalDeviceManager – Cloud-based child discovery', () => {
|
|
17
|
-
let log: Logger;
|
|
18
17
|
let manager: LocalDeviceManager;
|
|
19
18
|
|
|
20
19
|
const GATEWAY_ID = 'cloud_gw_001';
|
|
@@ -22,7 +21,7 @@ describe('LocalDeviceManager – Cloud-based child discovery', () => {
|
|
|
22
21
|
const DEVICE_IP = '192.168.1.200';
|
|
23
22
|
|
|
24
23
|
beforeEach(() => {
|
|
25
|
-
|
|
24
|
+
initLogger(mockLog);
|
|
26
25
|
});
|
|
27
26
|
|
|
28
27
|
afterEach(() => {
|
|
@@ -46,7 +45,7 @@ describe('LocalDeviceManager – Cloud-based child discovery', () => {
|
|
|
46
45
|
],
|
|
47
46
|
};
|
|
48
47
|
|
|
49
|
-
manager = new LocalDeviceManager(config
|
|
48
|
+
manager = new LocalDeviceManager(config);
|
|
50
49
|
|
|
51
50
|
const cloudDevices = [
|
|
52
51
|
{ id: GATEWAY_ID },
|
|
@@ -65,7 +64,7 @@ describe('LocalDeviceManager – Cloud-based child discovery', () => {
|
|
|
65
64
|
devices: [],
|
|
66
65
|
};
|
|
67
66
|
|
|
68
|
-
manager = new LocalDeviceManager(config
|
|
67
|
+
manager = new LocalDeviceManager(config);
|
|
69
68
|
|
|
70
69
|
const cloudDevices = [
|
|
71
70
|
{ id: 'unknown_gw', gateway_id: undefined },
|
|
@@ -74,7 +73,7 @@ describe('LocalDeviceManager – Cloud-based child discovery', () => {
|
|
|
74
73
|
|
|
75
74
|
manager.discoverChildrenFromCloud(cloudDevices);
|
|
76
75
|
|
|
77
|
-
const debugSpy =
|
|
76
|
+
const debugSpy = jest.spyOn(mockLog, 'debug');
|
|
78
77
|
expect(debugSpy.mock.calls.length).toBeGreaterThan(0);
|
|
79
78
|
});
|
|
80
79
|
|
|
@@ -91,7 +90,7 @@ describe('LocalDeviceManager – Cloud-based child discovery', () => {
|
|
|
91
90
|
],
|
|
92
91
|
};
|
|
93
92
|
|
|
94
|
-
manager = new LocalDeviceManager(config
|
|
93
|
+
manager = new LocalDeviceManager(config);
|
|
95
94
|
|
|
96
95
|
// Should not throw
|
|
97
96
|
expect(() => {
|
|
@@ -115,7 +114,7 @@ describe('LocalDeviceManager – Cloud-based child discovery', () => {
|
|
|
115
114
|
],
|
|
116
115
|
};
|
|
117
116
|
|
|
118
|
-
manager = new LocalDeviceManager(config
|
|
117
|
+
manager = new LocalDeviceManager(config);
|
|
119
118
|
|
|
120
119
|
const cloudDevices = [
|
|
121
120
|
{ id: GATEWAY_ID },
|
|
@@ -125,7 +124,7 @@ describe('LocalDeviceManager – Cloud-based child discovery', () => {
|
|
|
125
124
|
manager.discoverChildrenFromCloud(cloudDevices);
|
|
126
125
|
|
|
127
126
|
// Should not log auto-discovery (device is not a gateway)
|
|
128
|
-
const infoSpy =
|
|
127
|
+
const infoSpy = jest.spyOn(mockLog, 'info');
|
|
129
128
|
const callsWithAutoDiscovery = infoSpy.mock.calls.filter(c =>
|
|
130
129
|
String(c[0]).includes('auto-discovery'),
|
|
131
130
|
);
|
|
@@ -146,7 +145,7 @@ describe('LocalDeviceManager – Cloud-based child discovery', () => {
|
|
|
146
145
|
],
|
|
147
146
|
};
|
|
148
147
|
|
|
149
|
-
manager = new LocalDeviceManager(config
|
|
148
|
+
manager = new LocalDeviceManager(config);
|
|
150
149
|
|
|
151
150
|
const cloudDevices = [
|
|
152
151
|
{ id: GATEWAY_ID },
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { describe, expect, it, beforeEach, afterEach, jest } from '@jest/globals';
|
|
2
2
|
import LocalDeviceManager from '../../src/local/LocalDeviceManager';
|
|
3
|
-
import { LocalConfig
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
3
|
+
import { LocalConfig } from '../../src/local/config';
|
|
4
|
+
import { ExLogger, initLogger } from '../../src/shared/util/Logger';
|
|
5
|
+
|
|
6
|
+
// Mock Logger
|
|
7
|
+
const mockLog: ExLogger = {
|
|
8
|
+
debug: jest.fn(),
|
|
9
|
+
info: jest.fn(),
|
|
10
|
+
warn: jest.fn(),
|
|
11
|
+
error: jest.fn(),
|
|
12
|
+
log: jest.fn(),
|
|
13
|
+
success: jest.fn(),
|
|
14
|
+
} as unknown as ExLogger;
|
|
16
15
|
|
|
17
16
|
describe('LocalDeviceManager – Zigbee gateway reconnection', () => {
|
|
18
|
-
let log: Logger;
|
|
19
17
|
let manager: LocalDeviceManager;
|
|
20
18
|
|
|
21
19
|
const GATEWAY_ID = 'gw_reconnect_001';
|
|
@@ -50,8 +48,8 @@ describe('LocalDeviceManager – Zigbee gateway reconnection', () => {
|
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
beforeEach(() => {
|
|
53
|
-
|
|
54
|
-
manager = new LocalDeviceManager(zigbeeReconnectConfig()
|
|
51
|
+
initLogger(mockLog);
|
|
52
|
+
manager = new LocalDeviceManager(zigbeeReconnectConfig());
|
|
55
53
|
});
|
|
56
54
|
|
|
57
55
|
afterEach(() => {
|
|
@@ -81,6 +79,7 @@ describe('LocalDeviceManager – Zigbee gateway reconnection', () => {
|
|
|
81
79
|
ip: DEVICE_IP,
|
|
82
80
|
tuyaKey: DEVICE_KEY,
|
|
83
81
|
dpMapping: { 'switch_1': 1, 'bright_value': 2 },
|
|
82
|
+
isZigbeeGateway: true
|
|
84
83
|
},
|
|
85
84
|
{
|
|
86
85
|
tuyaDeviceId: CHILD_ID,
|
|
@@ -94,7 +93,7 @@ describe('LocalDeviceManager – Zigbee gateway reconnection', () => {
|
|
|
94
93
|
],
|
|
95
94
|
};
|
|
96
95
|
|
|
97
|
-
const mgr = new LocalDeviceManager(configWithOverride
|
|
96
|
+
const mgr = new LocalDeviceManager(configWithOverride);
|
|
98
97
|
// Should initialize without error even with per-child DP overrides
|
|
99
98
|
await mgr.initLocalDevices();
|
|
100
99
|
|
|
@@ -131,7 +130,7 @@ describe('LocalDeviceManager – Zigbee gateway reconnection', () => {
|
|
|
131
130
|
],
|
|
132
131
|
};
|
|
133
132
|
|
|
134
|
-
const mgr = new LocalDeviceManager(configWithCategoryOverride
|
|
133
|
+
const mgr = new LocalDeviceManager(configWithCategoryOverride);
|
|
135
134
|
await mgr.initLocalDevices();
|
|
136
135
|
|
|
137
136
|
const gwDevice = mgr.getDevice(GATEWAY_ID);
|
|
@@ -173,10 +172,10 @@ describe('LocalDeviceManager – Zigbee gateway reconnection', () => {
|
|
|
173
172
|
],
|
|
174
173
|
};
|
|
175
174
|
|
|
176
|
-
const mgr = new LocalDeviceManager(multiChildConfig
|
|
175
|
+
const mgr = new LocalDeviceManager(multiChildConfig);
|
|
176
|
+
const infoSpy = jest.spyOn(mockLog, 'info');
|
|
177
177
|
await mgr.initLocalDevices();
|
|
178
178
|
|
|
179
|
-
const infoSpy = log.info as jest.MockedFunction<typeof log.info>;
|
|
180
179
|
const infoCalls = infoSpy.mock.calls.map(c => String(c[0]));
|
|
181
180
|
const gatewayLine = infoCalls.find(s => s.includes('Zigbee gateway detected'));
|
|
182
181
|
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { describe, expect, it, beforeEach, afterEach, jest } from '@jest/globals';
|
|
2
2
|
import LocalDeviceManager from '../../src/local/LocalDeviceManager';
|
|
3
3
|
import { LocalConfig } from '../../src/local/config';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import TuyaDevice from '../../src/cloud/device/TuyaDevice';
|
|
5
|
+
import TuyaCloudDeviceManager from '../../src/cloud/device/TuyaCloudDeviceManager';
|
|
6
|
+
import Logger, { ExLogger, initLogger } from '../../src/shared/util/Logger';
|
|
6
7
|
|
|
7
8
|
// ── Logger mock ───────────────────────────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} as unknown as Logger;
|
|
17
|
-
}
|
|
9
|
+
const mockLog: ExLogger = {
|
|
10
|
+
debug: jest.fn(),
|
|
11
|
+
info: jest.fn(),
|
|
12
|
+
warn: jest.fn(),
|
|
13
|
+
error: jest.fn(),
|
|
14
|
+
log: jest.fn(),
|
|
15
|
+
success: jest.fn(),
|
|
16
|
+
} as unknown as ExLogger;
|
|
18
17
|
|
|
19
18
|
// ── Minimal config helpers ──────────────────────────────────────────────────
|
|
20
19
|
|
|
@@ -82,11 +81,10 @@ function standaloneConfig(): LocalConfig {
|
|
|
82
81
|
// ── Tests ──────────────────────────────────────────────────────────────────────
|
|
83
82
|
|
|
84
83
|
describe('LocalDeviceManager – Zigbee integration', () => {
|
|
85
|
-
let log: Logger;
|
|
86
84
|
let manager: LocalDeviceManager;
|
|
87
85
|
|
|
88
86
|
beforeEach(() => {
|
|
89
|
-
|
|
87
|
+
initLogger(mockLog);
|
|
90
88
|
});
|
|
91
89
|
|
|
92
90
|
afterEach(() => {
|
|
@@ -98,7 +96,7 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
98
96
|
|
|
99
97
|
describe('initLocalDevices() – child device handling', () => {
|
|
100
98
|
it('does not register child devices as TuyaDevices during first init pass', async () => {
|
|
101
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
99
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
102
100
|
await manager.initLocalDevices();
|
|
103
101
|
|
|
104
102
|
// Only the gateway should be in the device list initially
|
|
@@ -110,17 +108,17 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
110
108
|
});
|
|
111
109
|
|
|
112
110
|
it('registers standalone devices normally', async () => {
|
|
113
|
-
manager = new LocalDeviceManager(standaloneConfig()
|
|
111
|
+
manager = new LocalDeviceManager(standaloneConfig());
|
|
114
112
|
await manager.initLocalDevices();
|
|
115
113
|
|
|
116
114
|
expect(manager.devices.map(d => d.id)).toContain('standalone_001');
|
|
117
115
|
});
|
|
118
116
|
|
|
119
117
|
it('logs gateway relationships when detected', async () => {
|
|
120
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
118
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
119
|
+
const infoSpy = jest.spyOn(mockLog, 'info');
|
|
121
120
|
await manager.initLocalDevices();
|
|
122
121
|
|
|
123
|
-
const infoSpy = log.info as jest.MockedFunction<typeof log.info>;
|
|
124
122
|
const infoCalls = infoSpy.mock.calls.map(c => String(c[0]));
|
|
125
123
|
const gatewayLine = infoCalls.find(s => s.includes('Zigbee gateway'));
|
|
126
124
|
expect(gatewayLine).toBeDefined();
|
|
@@ -128,7 +126,7 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
128
126
|
});
|
|
129
127
|
|
|
130
128
|
it('proceeds without fatal errors when no Zigbee devices in config', async () => {
|
|
131
|
-
manager = new LocalDeviceManager(standaloneConfig()
|
|
129
|
+
manager = new LocalDeviceManager(standaloneConfig());
|
|
132
130
|
await expect(manager.initLocalDevices()).resolves.not.toThrow();
|
|
133
131
|
});
|
|
134
132
|
});
|
|
@@ -160,30 +158,70 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
160
158
|
],
|
|
161
159
|
};
|
|
162
160
|
|
|
163
|
-
manager = new LocalDeviceManager(badConfig
|
|
161
|
+
manager = new LocalDeviceManager(badConfig);
|
|
162
|
+
const errorSpy = jest.spyOn(mockLog, 'error');
|
|
164
163
|
await expect(manager.initLocalDevices()).resolves.not.toThrow();
|
|
165
164
|
|
|
166
|
-
const errorSpy = log.error as jest.MockedFunction<typeof log.error>;
|
|
167
165
|
const errorCalls = errorSpy.mock.calls.map(c => String(c[0]));
|
|
168
166
|
const zigbeeErrorLine = errorCalls.find(s => s.includes('Zigbee'));
|
|
169
167
|
expect(zigbeeErrorLine).toBeDefined();
|
|
170
168
|
});
|
|
171
169
|
});
|
|
172
170
|
|
|
171
|
+
// ── _syncConnectionInfo: shared local connection metadata ───────────────
|
|
172
|
+
|
|
173
|
+
describe('_syncConnectionInfo()', () => {
|
|
174
|
+
it('copies connection metadata from the sub-device to the parent when the parent is missing it', () => {
|
|
175
|
+
manager = new LocalDeviceManager(standaloneConfig());
|
|
176
|
+
const parent = new TuyaDevice({ id: 'parent', name: 'Parent' });
|
|
177
|
+
const sub = new TuyaDevice({ id: 'sub', name: 'Sub' });
|
|
178
|
+
|
|
179
|
+
(sub as TuyaDevice & { localIp?: string }).localIp = '192.168.1.11';
|
|
180
|
+
(sub as TuyaDevice & { localKey?: string }).localKey = 'sub-key';
|
|
181
|
+
(sub as TuyaDevice & { localVersion?: string }).localVersion = '3.4';
|
|
182
|
+
|
|
183
|
+
(manager as any)._syncConnectionInfo(parent, sub);
|
|
184
|
+
|
|
185
|
+
expect((parent as TuyaDevice & { localIp?: string }).localIp).toBe('192.168.1.11');
|
|
186
|
+
expect((parent as TuyaDevice & { localKey?: string }).localKey).toBe('sub-key');
|
|
187
|
+
expect((parent as TuyaDevice & { localVersion?: string }).localVersion).toBe('3.4');
|
|
188
|
+
expect((sub as TuyaDevice & { localIp?: string }).localIp).toBe('192.168.1.11');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('prefers sub-device values over parent values when both are already populated', () => {
|
|
192
|
+
manager = new LocalDeviceManager(standaloneConfig());
|
|
193
|
+
const parent = new TuyaDevice({ id: 'parent', name: 'Parent' });
|
|
194
|
+
const sub = new TuyaDevice({ id: 'sub', name: 'Sub' });
|
|
195
|
+
|
|
196
|
+
(parent as TuyaDevice & { localIp?: string }).localIp = '192.168.1.10';
|
|
197
|
+
(parent as TuyaDevice & { localKey?: string }).localKey = 'parent-key';
|
|
198
|
+
(parent as TuyaDevice & { localVersion?: string }).localVersion = '3.3';
|
|
199
|
+
(sub as TuyaDevice & { localIp?: string }).localIp = '192.168.1.12';
|
|
200
|
+
(sub as TuyaDevice & { localKey?: string }).localKey = 'sub-key';
|
|
201
|
+
(sub as TuyaDevice & { localVersion?: string }).localVersion = '3.5';
|
|
202
|
+
|
|
203
|
+
(manager as any)._syncConnectionInfo(parent, sub);
|
|
204
|
+
|
|
205
|
+
expect((parent as TuyaDevice & { localIp?: string }).localIp).toBe('192.168.1.12');
|
|
206
|
+
expect((parent as TuyaDevice & { localKey?: string }).localKey).toBe('sub-key');
|
|
207
|
+
expect((parent as TuyaDevice & { localVersion?: string }).localVersion).toBe('3.5');
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
173
211
|
// ── sendCommands: Zigbee child routing ─────────────────────────────────────
|
|
174
212
|
|
|
175
213
|
describe('sendCommands() – Zigbee child routing', () => {
|
|
176
214
|
it('returns without acting when device has no dpMapping (unknown device)', async () => {
|
|
177
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
215
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
178
216
|
await manager.initLocalDevices();
|
|
179
217
|
|
|
180
218
|
// CHILD_ID_A is not yet registered in the first pass
|
|
181
219
|
const result = await manager.sendCommands('nonexistent_device', [{ code: 'switch_1', value: true }]);
|
|
182
|
-
expect(result).
|
|
220
|
+
expect(result).toBe(false);
|
|
183
221
|
});
|
|
184
222
|
|
|
185
223
|
it('handles sendCommands for a known device that has a dpMapping', async () => {
|
|
186
|
-
manager = new LocalDeviceManager(standaloneConfig()
|
|
224
|
+
manager = new LocalDeviceManager(standaloneConfig());
|
|
187
225
|
await manager.initLocalDevices();
|
|
188
226
|
|
|
189
227
|
// 'standalone_001' is in the device list but has no IP connection (autoDiscover=false, no connect called)
|
|
@@ -198,14 +236,14 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
198
236
|
|
|
199
237
|
describe('stopLocalDevices()', () => {
|
|
200
238
|
it('does not throw when called with Zigbee gateway config and no active connections', async () => {
|
|
201
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
239
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
202
240
|
await manager.initLocalDevices();
|
|
203
241
|
|
|
204
242
|
expect(() => manager.stopLocalDevices()).not.toThrow();
|
|
205
243
|
});
|
|
206
244
|
|
|
207
245
|
it('can be called multiple times without error', async () => {
|
|
208
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
246
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
209
247
|
await manager.initLocalDevices();
|
|
210
248
|
|
|
211
249
|
expect(() => {
|
|
@@ -220,11 +258,11 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
220
258
|
describe('_setupZigbeeChildren() – via gateway connect event', () => {
|
|
221
259
|
it('emits DEVICE_ADD for child when gateway connects', async () => {
|
|
222
260
|
const EventEmitter = (await import('events')).default;
|
|
223
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
261
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
224
262
|
await manager.initLocalDevices();
|
|
225
263
|
|
|
226
264
|
const deviceAddEvents: string[] = [];
|
|
227
|
-
manager.on(
|
|
265
|
+
manager.on(TuyaCloudDeviceManager.Events.DEVICE_ADD, (device: any) => {
|
|
228
266
|
deviceAddEvents.push(device.id);
|
|
229
267
|
});
|
|
230
268
|
|
|
@@ -249,7 +287,7 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
249
287
|
});
|
|
250
288
|
|
|
251
289
|
it('correctly maps child deviceId <-> cid in the relationship', async () => {
|
|
252
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
290
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
253
291
|
await manager.initLocalDevices();
|
|
254
292
|
|
|
255
293
|
const gatewayRelationships = (manager as any).gatewayRelationships as Map<string, any>;
|
|
@@ -271,7 +309,7 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
271
309
|
|
|
272
310
|
describe('getDevice()', () => {
|
|
273
311
|
it('returns the gateway TuyaDevice by ID', async () => {
|
|
274
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
312
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
275
313
|
await manager.initLocalDevices();
|
|
276
314
|
|
|
277
315
|
const gw = manager.getDevice(GATEWAY_ID);
|
|
@@ -281,7 +319,7 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
281
319
|
});
|
|
282
320
|
|
|
283
321
|
it('returns undefined for a child device before parent connects', async () => {
|
|
284
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
322
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
285
323
|
await manager.initLocalDevices();
|
|
286
324
|
|
|
287
325
|
// Children not yet registered (lazy registration happens on parent connect)
|
|
@@ -290,7 +328,7 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
290
328
|
});
|
|
291
329
|
|
|
292
330
|
it('returns undefined for a completely unknown device', async () => {
|
|
293
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
331
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
294
332
|
await manager.initLocalDevices();
|
|
295
333
|
|
|
296
334
|
expect(manager.getDevice('no_such_device')).toBeUndefined();
|
|
@@ -315,7 +353,7 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
315
353
|
],
|
|
316
354
|
};
|
|
317
355
|
|
|
318
|
-
manager = new LocalDeviceManager(mixedConfig
|
|
356
|
+
manager = new LocalDeviceManager(mixedConfig);
|
|
319
357
|
await manager.initLocalDevices();
|
|
320
358
|
|
|
321
359
|
const ids = manager.devices.map(d => d.id);
|
|
@@ -326,7 +364,7 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
326
364
|
});
|
|
327
365
|
|
|
328
366
|
it('detects the correct number of gateway relationships', async () => {
|
|
329
|
-
manager = new LocalDeviceManager(zigbeeConfig()
|
|
367
|
+
manager = new LocalDeviceManager(zigbeeConfig());
|
|
330
368
|
await manager.initLocalDevices();
|
|
331
369
|
|
|
332
370
|
const gatewayRelationships = (manager as any).gatewayRelationships as Map<string, any>;
|
|
@@ -334,7 +372,7 @@ describe('LocalDeviceManager – Zigbee integration', () => {
|
|
|
334
372
|
});
|
|
335
373
|
|
|
336
374
|
it('has no gateway relationships for purely standalone config', async () => {
|
|
337
|
-
manager = new LocalDeviceManager(standaloneConfig()
|
|
375
|
+
manager = new LocalDeviceManager(standaloneConfig());
|
|
338
376
|
await manager.initLocalDevices();
|
|
339
377
|
|
|
340
378
|
const gatewayRelationships = (manager as any).gatewayRelationships as Map<string, any>;
|
|
@@ -112,13 +112,13 @@ describe('ZigbeeGatewayDetection', () => {
|
|
|
112
112
|
device('child_1', { parentDeviceId: 'gw_1' }),
|
|
113
113
|
];
|
|
114
114
|
expect(() => ZigbeeGatewayDetection.detectFromDevices(devices))
|
|
115
|
-
.toThrow('parentDeviceId but is missing zigbeeChildId');
|
|
115
|
+
.toThrow('Device "child_1" has parentDeviceId:gw_1 but is missing zigbeeChildId. Both fields are required for Zigbee sub-devices.');
|
|
116
116
|
});
|
|
117
117
|
|
|
118
118
|
it('throws when zigbeeChildId is set without parentDeviceId', () => {
|
|
119
119
|
const devices = [device('child_1', { zigbeeChildId: '0011223344556601' })];
|
|
120
120
|
expect(() => ZigbeeGatewayDetection.detectFromDevices(devices))
|
|
121
|
-
.toThrow('zigbeeChildId but is missing parentDeviceId');
|
|
121
|
+
.toThrow('Device "child_1" has zigbeeChildId:0011223344556601 but is missing parentDeviceId. Both fields are required for Zigbee sub-devices.');
|
|
122
122
|
});
|
|
123
123
|
|
|
124
124
|
it('throws for an invalid CID (too short)', () => {
|