@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
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, beforeEach, jest } from '@jest/globals';
|
|
2
|
-
import {
|
|
3
|
-
reconcileDeviceSources,
|
|
4
|
-
getPreferredSource,
|
|
5
|
-
filterDevicesBySource,
|
|
6
|
-
markDeviceConnected,
|
|
7
|
-
shouldHideFromSource,
|
|
8
|
-
logReconciliationSummary,
|
|
9
|
-
DeviceSourceInfo,
|
|
10
|
-
} from '../../src/local/CloudLocalReconciliation';
|
|
11
|
-
import TuyaDevice from '../../src/cloud/device/TuyaDevice';
|
|
12
|
-
import Logger from '../../src/shared/util/Logger';
|
|
13
|
-
|
|
14
|
-
function makeMockLog(): Logger {
|
|
15
|
-
return {
|
|
16
|
-
debug: jest.fn(),
|
|
17
|
-
info: jest.fn(),
|
|
18
|
-
warn: jest.fn(),
|
|
19
|
-
error: jest.fn(),
|
|
20
|
-
log: jest.fn(),
|
|
21
|
-
} as unknown as Logger;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function createMockDevice(id: string, uuid: string): TuyaDevice {
|
|
25
|
-
return {
|
|
26
|
-
id,
|
|
27
|
-
uuid,
|
|
28
|
-
name: `Device ${id}`,
|
|
29
|
-
} as TuyaDevice;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
describe('CloudLocalReconciliation - Phase 4', () => {
|
|
33
|
-
let log: Logger;
|
|
34
|
-
|
|
35
|
-
beforeEach(() => {
|
|
36
|
-
log = makeMockLog();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe('reconcileDeviceSources', () => {
|
|
40
|
-
it('reconciles cloud-only devices', () => {
|
|
41
|
-
const cloudDevices = [
|
|
42
|
-
createMockDevice('cloud_001', 'uuid_001'),
|
|
43
|
-
createMockDevice('cloud_002', 'uuid_002'),
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
const result = reconcileDeviceSources(cloudDevices, [], log);
|
|
47
|
-
|
|
48
|
-
expect(result.size).toBe(2);
|
|
49
|
-
expect(result.get('uuid_001')).toEqual({
|
|
50
|
-
cloud: true,
|
|
51
|
-
local: false,
|
|
52
|
-
connectedTo: 'cloud',
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('reconciles local-only devices', () => {
|
|
57
|
-
const localDevices = [
|
|
58
|
-
createMockDevice('local_001', 'uuid_101'),
|
|
59
|
-
];
|
|
60
|
-
|
|
61
|
-
const result = reconcileDeviceSources([], localDevices, log);
|
|
62
|
-
|
|
63
|
-
expect(result.size).toBe(1);
|
|
64
|
-
expect(result.get('uuid_101')).toEqual({
|
|
65
|
-
cloud: false,
|
|
66
|
-
local: true,
|
|
67
|
-
localIP: undefined,
|
|
68
|
-
localVersion: undefined,
|
|
69
|
-
connectedTo: 'local',
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('reconciles hybrid devices (same UUID, both sources)', () => {
|
|
74
|
-
const cloudDevices = [createMockDevice('device_a', 'uuid_hybrid')];
|
|
75
|
-
const localDevices = [createMockDevice('device_a', 'uuid_hybrid')];
|
|
76
|
-
|
|
77
|
-
const result = reconcileDeviceSources(cloudDevices, localDevices, log);
|
|
78
|
-
|
|
79
|
-
expect(result.size).toBe(1);
|
|
80
|
-
const info = result.get('uuid_hybrid');
|
|
81
|
-
expect(info?.cloud).toBe(true);
|
|
82
|
-
expect(info?.local).toBe(true);
|
|
83
|
-
expect(info?.connectedTo).toBe('both');
|
|
84
|
-
|
|
85
|
-
const infoSpy = log.info as jest.MockedFunction<typeof log.info>;
|
|
86
|
-
expect(infoSpy).toHaveBeenCalledWith(expect.stringContaining('available via cloud AND local'));
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('handles mixed cloud-only, local-only, and hybrid devices', () => {
|
|
90
|
-
const cloudDevices = [
|
|
91
|
-
createMockDevice('cloud_only', 'uuid_cloud'),
|
|
92
|
-
createMockDevice('hybrid', 'uuid_hybrid'),
|
|
93
|
-
];
|
|
94
|
-
const localDevices = [
|
|
95
|
-
createMockDevice('local_only', 'uuid_local'),
|
|
96
|
-
createMockDevice('hybrid', 'uuid_hybrid'),
|
|
97
|
-
];
|
|
98
|
-
|
|
99
|
-
const result = reconcileDeviceSources(cloudDevices, localDevices, log);
|
|
100
|
-
|
|
101
|
-
expect(result.size).toBe(3);
|
|
102
|
-
expect(result.get('uuid_cloud')?.cloud).toBe(true);
|
|
103
|
-
expect(result.get('uuid_cloud')?.local).toBe(false);
|
|
104
|
-
expect(result.get('uuid_local')?.cloud).toBe(false);
|
|
105
|
-
expect(result.get('uuid_local')?.local).toBe(true);
|
|
106
|
-
expect(result.get('uuid_hybrid')?.cloud).toBe(true);
|
|
107
|
-
expect(result.get('uuid_hybrid')?.local).toBe(true);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('logs hybrid device detection', () => {
|
|
111
|
-
const cloudDevices = [createMockDevice('device', 'uuid_123')];
|
|
112
|
-
const localDevices = [createMockDevice('device', 'uuid_123')];
|
|
113
|
-
|
|
114
|
-
reconcileDeviceSources(cloudDevices, localDevices, log);
|
|
115
|
-
|
|
116
|
-
const infoSpy = log.info as jest.MockedFunction<typeof log.info>;
|
|
117
|
-
expect(infoSpy).toHaveBeenCalledWith(expect.stringContaining('available via cloud AND local'));
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe('getPreferredSource', () => {
|
|
122
|
-
it('prefers local when available', () => {
|
|
123
|
-
const sourceInfo: DeviceSourceInfo = { cloud: true, local: true };
|
|
124
|
-
expect(getPreferredSource(sourceInfo)).toBe('local');
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('uses cloud when local unavailable', () => {
|
|
128
|
-
const sourceInfo: DeviceSourceInfo = { cloud: true, local: false };
|
|
129
|
-
expect(getPreferredSource(sourceInfo)).toBe('cloud');
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('always prefers local when both available (ignores default param)', () => {
|
|
133
|
-
const sourceInfo: DeviceSourceInfo = { cloud: true, local: true };
|
|
134
|
-
// The defaultSource param is only used when local is unavailable
|
|
135
|
-
// When both are available, local is always preferred
|
|
136
|
-
expect(getPreferredSource(sourceInfo, 'local')).toBe('local');
|
|
137
|
-
expect(getPreferredSource(sourceInfo, 'cloud')).toBe('local');
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
describe('filterDevicesBySource', () => {
|
|
142
|
-
let sourceMap: Map<string, DeviceSourceInfo>;
|
|
143
|
-
|
|
144
|
-
beforeEach(() => {
|
|
145
|
-
sourceMap = new Map([
|
|
146
|
-
['uuid_cloud', { cloud: true, local: false }],
|
|
147
|
-
['uuid_local', { cloud: false, local: true }],
|
|
148
|
-
['uuid_hybrid', { cloud: true, local: true }],
|
|
149
|
-
]);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('filters to local-only devices', () => {
|
|
153
|
-
const devices = [
|
|
154
|
-
createMockDevice('cloud', 'uuid_cloud'),
|
|
155
|
-
createMockDevice('local', 'uuid_local'),
|
|
156
|
-
createMockDevice('hybrid', 'uuid_hybrid'),
|
|
157
|
-
];
|
|
158
|
-
|
|
159
|
-
const result = filterDevicesBySource(devices, 'local', sourceMap);
|
|
160
|
-
|
|
161
|
-
expect(result.length).toBe(2);
|
|
162
|
-
expect(result.map(d => d.uuid)).toContain('uuid_local');
|
|
163
|
-
expect(result.map(d => d.uuid)).toContain('uuid_hybrid');
|
|
164
|
-
expect(result.map(d => d.uuid)).not.toContain('uuid_cloud');
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('filters to cloud-only devices', () => {
|
|
168
|
-
const devices = [
|
|
169
|
-
createMockDevice('cloud', 'uuid_cloud'),
|
|
170
|
-
createMockDevice('local', 'uuid_local'),
|
|
171
|
-
createMockDevice('hybrid', 'uuid_hybrid'),
|
|
172
|
-
];
|
|
173
|
-
|
|
174
|
-
const result = filterDevicesBySource(devices, 'cloud', sourceMap);
|
|
175
|
-
|
|
176
|
-
expect(result.length).toBe(2);
|
|
177
|
-
expect(result.map(d => d.uuid)).toContain('uuid_cloud');
|
|
178
|
-
expect(result.map(d => d.uuid)).toContain('uuid_hybrid');
|
|
179
|
-
expect(result.map(d => d.uuid)).not.toContain('uuid_local');
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('returns all devices for both source filter', () => {
|
|
183
|
-
const devices = [
|
|
184
|
-
createMockDevice('cloud', 'uuid_cloud'),
|
|
185
|
-
createMockDevice('local', 'uuid_local'),
|
|
186
|
-
createMockDevice('hybrid', 'uuid_hybrid'),
|
|
187
|
-
];
|
|
188
|
-
|
|
189
|
-
const result = filterDevicesBySource(devices, 'both', sourceMap);
|
|
190
|
-
|
|
191
|
-
expect(result.length).toBe(3);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('excludes unknown devices from filter', () => {
|
|
195
|
-
const devices = [
|
|
196
|
-
createMockDevice('cloud', 'uuid_cloud'),
|
|
197
|
-
createMockDevice('unknown', 'uuid_unknown'),
|
|
198
|
-
];
|
|
199
|
-
|
|
200
|
-
const result = filterDevicesBySource(devices, 'cloud', sourceMap);
|
|
201
|
-
|
|
202
|
-
expect(result.length).toBe(1);
|
|
203
|
-
expect(result[0].uuid).toBe('uuid_cloud');
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
describe('markDeviceConnected', () => {
|
|
208
|
-
let sourceMap: Map<string, DeviceSourceInfo>;
|
|
209
|
-
|
|
210
|
-
beforeEach(() => {
|
|
211
|
-
sourceMap = new Map([
|
|
212
|
-
['uuid_001', { cloud: true, local: true, connectedTo: 'cloud' }],
|
|
213
|
-
]);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('updates device connection state to local', () => {
|
|
217
|
-
markDeviceConnected('uuid_001', 'local', sourceMap, log);
|
|
218
|
-
|
|
219
|
-
expect(sourceMap.get('uuid_001')?.connectedTo).toBe('both');
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('warns if marking unknown device as connected', () => {
|
|
223
|
-
markDeviceConnected('uuid_unknown', 'local', sourceMap, log);
|
|
224
|
-
|
|
225
|
-
const warnSpy = log.warn as jest.MockedFunction<typeof log.warn>;
|
|
226
|
-
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('unknown device'));
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('warns if marking device connected to unavailable source', () => {
|
|
230
|
-
const sourceInfo: DeviceSourceInfo = {
|
|
231
|
-
cloud: true,
|
|
232
|
-
local: false,
|
|
233
|
-
};
|
|
234
|
-
sourceMap.set('uuid_002', sourceInfo);
|
|
235
|
-
|
|
236
|
-
markDeviceConnected('uuid_002', 'local', sourceMap, log);
|
|
237
|
-
|
|
238
|
-
const warnSpy = log.warn as jest.MockedFunction<typeof log.warn>;
|
|
239
|
-
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('not available locally'));
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
describe('shouldHideFromSource', () => {
|
|
244
|
-
it('does not hide when source is both', () => {
|
|
245
|
-
const device = createMockDevice('test', 'uuid_test');
|
|
246
|
-
expect(shouldHideFromSource(device, 'cloud', 'both')).toBe(false);
|
|
247
|
-
expect(shouldHideFromSource(device, 'local', 'both')).toBe(false);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('hides cloud devices when source is local-only', () => {
|
|
251
|
-
const device = createMockDevice('test', 'uuid_test');
|
|
252
|
-
expect(shouldHideFromSource(device, 'cloud', 'local')).toBe(true);
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
it('hides local devices when source is cloud-only', () => {
|
|
256
|
-
const device = createMockDevice('test', 'uuid_test');
|
|
257
|
-
expect(shouldHideFromSource(device, 'local', 'cloud')).toBe(true);
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it('defaults to cloud-only when source undefined', () => {
|
|
261
|
-
const device = createMockDevice('test', 'uuid_test');
|
|
262
|
-
expect(shouldHideFromSource(device, 'local', undefined)).toBe(true);
|
|
263
|
-
expect(shouldHideFromSource(device, 'cloud', undefined)).toBe(false);
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
describe('logReconciliationSummary', () => {
|
|
268
|
-
it('logs reconciliation counts', () => {
|
|
269
|
-
const sourceMap = new Map<string, DeviceSourceInfo>([
|
|
270
|
-
['uuid_1', { cloud: true, local: true }],
|
|
271
|
-
['uuid_2', { cloud: true, local: false }],
|
|
272
|
-
['uuid_3', { cloud: false, local: true }],
|
|
273
|
-
]);
|
|
274
|
-
|
|
275
|
-
logReconciliationSummary(sourceMap, log);
|
|
276
|
-
|
|
277
|
-
const infoSpy = log.info as jest.MockedFunction<typeof log.info>;
|
|
278
|
-
const call = String(infoSpy.mock.calls[0][0]);
|
|
279
|
-
expect(call).toContain('1 hybrid');
|
|
280
|
-
expect(call).toContain('1 cloud-only');
|
|
281
|
-
expect(call).toContain('1 local-only');
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
85778e1add80c517
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
35d2f400f4ef8c0f
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# Get Local Keys for Your Devices
|
|
2
|
-
|
|
3
|
-
To get the local keys for your devices, you'll need an account on Tuya's IoT site. Don't be overwhelmed, there's a lot on that site but it's pretty easy to get what you need out of it. The free trial will give you enough access to the Tuya API to get the information you need, on up to 50 devices.
|
|
4
|
-
|
|
5
|
-
## 1 - Tuya Smart App
|
|
6
|
-
|
|
7
|
-
As a prerequisite, add all of your devices to the Tuya Smart app ([iOS](https://apps.apple.com/au/app/tuya-smart/id1034649547) / [Android](https://play.google.com/store/apps/details?id=com.tuya.smart&hl=en_AU&gl=US&pli=1))
|
|
8
|
-
|
|
9
|
-
## 2 - Sign up for an IoT account
|
|
10
|
-
|
|
11
|
-
Go to https://iot.tuya.com and click Sign Up
|
|
12
|
-
|
|
13
|
-

|
|
14
|
-
|
|
15
|
-
* Fill in your information
|
|
16
|
-
* Make up a company name if you need to
|
|
17
|
-
|
|
18
|
-

|
|
19
|
-
|
|
20
|
-
* Check Agree to Terms
|
|
21
|
-
* Click Agree
|
|
22
|
-
* You'll be emailed a code, enter it
|
|
23
|
-
|
|
24
|
-
## 3 - Sign in at iot.tuya.com
|
|
25
|
-
|
|
26
|
-
## 4 - Create a cloud project
|
|
27
|
-
|
|
28
|
-
* Click through the intro
|
|
29
|
-
* On the sidebar click cloud, then projects
|
|
30
|
-
* Click Free Trial under TRIAL EDITION
|
|
31
|
-
|
|
32
|
-

|
|
33
|
-
|
|
34
|
-
* Click Buy now in the new tab
|
|
35
|
-
|
|
36
|
-

|
|
37
|
-
|
|
38
|
-
* Close the Tuya Value Added Service tab/popup
|
|
39
|
-
* In the Tuya IoT Platform tab, click Subscribed to be taken back to Cloud -> Projects
|
|
40
|
-
* Click create
|
|
41
|
-
|
|
42
|
-

|
|
43
|
-
|
|
44
|
-
* Make sure you pick smart home PAAS and the correct region, this affects whether you will be able to access your devices in the following steps. Click create
|
|
45
|
-
|
|
46
|
-

|
|
47
|
-
|
|
48
|
-
* Click Authorize for the recommended APIs
|
|
49
|
-
|
|
50
|
-

|
|
51
|
-
|
|
52
|
-
## 5 - Link devices registered in Tuya app to the IoT site
|
|
53
|
-
|
|
54
|
-
* From your project, click the link devices tab, then Link devices by App Account, then Add App Account
|
|
55
|
-
|
|
56
|
-

|
|
57
|
-
|
|
58
|
-
* In the Tuya Smart app, click me at the bottom, then the scan button, then scan your QR code
|
|
59
|
-
|
|
60
|
-

|
|
61
|
-
|
|
62
|
-
* Confirm the sign in
|
|
63
|
-
|
|
64
|
-
## 6 - Get the keys for your devices
|
|
65
|
-
|
|
66
|
-
* Go to the device list tab
|
|
67
|
-
* Copy the device ID for your device
|
|
68
|
-
|
|
69
|
-

|
|
70
|
-
|
|
71
|
-
* In the sidebar, hover over "Cloud" and click on "API Explorer"
|
|
72
|
-
|
|
73
|
-

|
|
74
|
-
|
|
75
|
-
* In the sidebar, search for "get device information" endpoint and click on the highlighted option. (It should be under "General Devices management" section. Note: there is also another endpoint called "Get _the_ device information" which will not work.)
|
|
76
|
-
|
|
77
|
-
* In the "device_id" text field, paste in the device ID you copied and click "Submit Request"
|
|
78
|
-
|
|
79
|
-
* In the "Response" section, there should be a property called `local_key` which is your local key.
|
|
80
|
-
|
|
81
|
-

|
|
82
|
-
|
|
83
|
-
## 7 - Video Tutorial
|
|
84
|
-
|
|
85
|
-
* [YouTube](https://youtu.be/FpY-xsY-pZ8)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|