@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.
Files changed (298) hide show
  1. package/README.md +354 -142
  2. package/config.schema.json +1221 -893
  3. package/dist/cloud/api/TuyaOpenAPI.js +108 -60
  4. package/dist/cloud/api/TuyaOpenAPI.js.map +1 -1
  5. package/dist/cloud/api/TuyaOpenMQ.js +45 -22
  6. package/dist/cloud/api/TuyaOpenMQ.js.map +1 -1
  7. package/dist/cloud/device/{TuyaDeviceManager.js → TuyaCloudDeviceManager.js} +146 -96
  8. package/dist/cloud/device/TuyaCloudDeviceManager.js.map +1 -0
  9. package/dist/cloud/device/TuyaCustomDeviceManager.js +75 -5
  10. package/dist/cloud/device/TuyaCustomDeviceManager.js.map +1 -1
  11. package/dist/cloud/device/TuyaDevice.js.map +1 -1
  12. package/dist/cloud/device/TuyaHomeDeviceManager.js +81 -13
  13. package/dist/cloud/device/TuyaHomeDeviceManager.js.map +1 -1
  14. package/dist/config.js +26 -5
  15. package/dist/config.js.map +1 -1
  16. package/dist/local/DynamicChildDiscovery.js +2 -1
  17. package/dist/local/DynamicChildDiscovery.js.map +1 -1
  18. package/dist/local/LocalDevice.js +16 -3
  19. package/dist/local/LocalDevice.js.map +1 -1
  20. package/dist/local/LocalDeviceManager.js +361 -164
  21. package/dist/local/LocalDeviceManager.js.map +1 -1
  22. package/dist/local/TuyaDiscovery.js +16 -7
  23. package/dist/local/TuyaDiscovery.js.map +1 -1
  24. package/dist/local/ZigbeeGatewayDetection.js +7 -4
  25. package/dist/local/ZigbeeGatewayDetection.js.map +1 -1
  26. package/dist/local/protocol/ProtocolUtilities.js +34 -17
  27. package/dist/local/protocol/ProtocolUtilities.js.map +1 -1
  28. package/dist/local/protocol/ProtocolV31V32.js +4 -2
  29. package/dist/local/protocol/ProtocolV31V32.js.map +1 -1
  30. package/dist/local/protocol/ProtocolV33.js +4 -2
  31. package/dist/local/protocol/ProtocolV33.js.map +1 -1
  32. package/dist/local/protocol/ProtocolV34.js +10 -5
  33. package/dist/local/protocol/ProtocolV34.js.map +1 -1
  34. package/dist/local/protocol/ProtocolV35.js +8 -4
  35. package/dist/local/protocol/ProtocolV35.js.map +1 -1
  36. package/dist/platform.js +253 -493
  37. package/dist/platform.js.map +1 -1
  38. package/dist/settings.js +0 -2
  39. package/dist/settings.js.map +1 -1
  40. package/dist/shared/TuyaDeviceManager.js +147 -0
  41. package/dist/shared/TuyaDeviceManager.js.map +1 -0
  42. package/dist/shared/TuyaHybridDeviceManager.js +215 -0
  43. package/dist/shared/TuyaHybridDeviceManager.js.map +1 -0
  44. package/dist/shared/accessory/AccessoryFactory.js +350 -0
  45. package/dist/shared/accessory/AccessoryFactory.js.map +1 -0
  46. package/dist/shared/{accessories → accessory}/AirConditionerAccessory.js +21 -15
  47. package/dist/shared/accessory/AirConditionerAccessory.js.map +1 -0
  48. package/dist/shared/{accessories → accessory}/AirPurifierAccessory.js.map +1 -1
  49. package/dist/shared/accessory/AirQualitySensorAccessory.js.map +1 -0
  50. package/dist/shared/{accessories → accessory}/BaseAccessory.js +16 -95
  51. package/dist/shared/accessory/BaseAccessory.js.map +1 -0
  52. package/dist/shared/{accessories → accessory}/BlindsAccessory.js.map +1 -1
  53. package/dist/shared/{accessories → accessory}/CameraAccessory.js +2 -2
  54. package/dist/shared/accessory/CameraAccessory.js.map +1 -0
  55. package/dist/shared/{accessories → accessory}/CarbonDioxideSensorAccessory.js.map +1 -1
  56. package/dist/shared/{accessories → accessory}/CarbonMonoxideSensorAccessory.js.map +1 -1
  57. package/dist/shared/{accessories → accessory}/ContactSensorAccessory.js.map +1 -1
  58. package/dist/shared/{accessories → accessory}/DehumidifierAccessory.js.map +1 -1
  59. package/dist/shared/{accessories → accessory}/DiffuserAccessory.js.map +1 -1
  60. package/dist/shared/{accessories → accessory}/DimmerAccessory.js.map +1 -1
  61. package/dist/shared/{accessories → accessory}/DoorbellAccessory.js.map +1 -1
  62. package/dist/shared/{accessories → accessory}/ExtractionHoodAccessory.js.map +1 -1
  63. package/dist/shared/{accessories → accessory}/FanAccessory.js.map +1 -1
  64. package/dist/shared/{accessories → accessory}/GarageDoorAccessory.js +19 -2
  65. package/dist/shared/accessory/GarageDoorAccessory.js.map +1 -0
  66. package/dist/shared/{accessories → accessory}/HeaterAccessory.js.map +1 -1
  67. package/dist/shared/{accessories → accessory}/HeaterAccessory_old.js.map +1 -1
  68. package/dist/shared/accessory/HumanPresenceSensorAccessory.js.map +1 -0
  69. package/dist/shared/{accessories → accessory}/HumidifierAccessory.js.map +1 -1
  70. package/dist/shared/accessory/IRAdapter.js +167 -0
  71. package/dist/shared/accessory/IRAdapter.js.map +1 -0
  72. package/dist/shared/accessory/IRAirConditionerAccessory.js.map +1 -0
  73. package/dist/shared/accessory/IRControlHubAccessory.js.map +1 -0
  74. package/dist/shared/accessory/IRControlHubSubAccessory.js.map +1 -0
  75. package/dist/shared/accessory/IRFanAccessory.js +90 -0
  76. package/dist/shared/accessory/IRFanAccessory.js.map +1 -0
  77. package/dist/shared/accessory/IRGenericAccessory.js.map +1 -0
  78. package/dist/shared/{accessories → accessory}/LeakSensorAccessory.js.map +1 -1
  79. package/dist/shared/{accessories → accessory}/LightAccessory.js.map +1 -1
  80. package/dist/shared/{accessories → accessory}/LightSensorAccessory.js.map +1 -1
  81. package/dist/shared/{accessories → accessory}/LocationWeatherAccessory.js +1 -1
  82. package/dist/shared/accessory/LocationWeatherAccessory.js.map +1 -0
  83. package/dist/shared/{accessories → accessory}/LockAccessory.js +3 -3
  84. package/dist/shared/{accessories → accessory}/LockAccessory.js.map +1 -1
  85. package/dist/shared/accessory/MotionSensorAccessory.js.map +1 -0
  86. package/dist/shared/accessory/OutletAccessory.js.map +1 -0
  87. package/dist/shared/{accessories → accessory}/PetFeederAccessory.js.map +1 -1
  88. package/dist/shared/{accessories → accessory}/SceneAccessory.js +1 -1
  89. package/dist/shared/accessory/SceneAccessory.js.map +1 -0
  90. package/dist/shared/accessory/SceneSwitchAccessory.js.map +1 -0
  91. package/dist/shared/accessory/SecuritySystemAccessory.js.map +1 -0
  92. package/dist/shared/{accessories → accessory}/SmokeSensorAccessory.js.map +1 -1
  93. package/dist/shared/{accessories → accessory}/SwitchAccessory.js +1 -45
  94. package/dist/shared/accessory/SwitchAccessory.js.map +1 -0
  95. package/dist/shared/accessory/TemperatureHumiditySensorAccessory.js.map +1 -0
  96. package/dist/shared/{accessories → accessory}/ThermostatAccessory.js.map +1 -1
  97. package/dist/shared/{accessories → accessory}/TowerRackAccessory.js.map +1 -1
  98. package/dist/shared/{accessories → accessory}/ValveAccessory.js.map +1 -1
  99. package/dist/shared/{accessories → accessory}/VibrationSensorAccessory.js.map +1 -1
  100. package/dist/shared/accessory/WeatherStationAccessory.js.map +1 -0
  101. package/dist/shared/accessory/WetBulbGlobeTemperatureAccessory.js.map +1 -0
  102. package/dist/shared/{accessories → accessory}/WhiteNoiseLightAccessory.js +1 -0
  103. package/dist/shared/accessory/WhiteNoiseLightAccessory.js.map +1 -0
  104. package/dist/shared/accessory/WindowAccessory.js.map +1 -0
  105. package/dist/shared/{accessories → accessory}/WindowCoveringAccessory.js.map +1 -1
  106. package/dist/shared/{accessories → accessory}/WirelessSwitchAccessory.js.map +1 -1
  107. package/dist/shared/accessory/characteristic/Active.js.map +1 -0
  108. package/dist/shared/accessory/characteristic/AirQuality.js.map +1 -0
  109. package/dist/shared/{accessories → accessory}/characteristic/CurrentRelativeHumidity.js +3 -0
  110. package/dist/shared/accessory/characteristic/CurrentRelativeHumidity.js.map +1 -0
  111. package/dist/shared/accessory/characteristic/CurrentTemperature.js.map +1 -0
  112. package/dist/shared/accessory/characteristic/CurrentWeather.js.map +1 -0
  113. package/dist/shared/accessory/characteristic/CurrentWeatherByOpenMeteo.js.map +1 -0
  114. package/dist/shared/{accessories → accessory}/characteristic/CurrentWetBulbGlobeTemperature.js +3 -2
  115. package/dist/shared/accessory/characteristic/CurrentWetBulbGlobeTemperature.js.map +1 -0
  116. package/dist/shared/{accessories → accessory}/characteristic/EnergyUsage.js +0 -5
  117. package/dist/shared/accessory/characteristic/EnergyUsage.js.map +1 -0
  118. package/dist/shared/{accessories → accessory}/characteristic/Light.js +28 -5
  119. package/dist/shared/accessory/characteristic/Light.js.map +1 -0
  120. package/dist/shared/accessory/characteristic/LightSensor.js.map +1 -0
  121. package/dist/shared/{accessories → accessory}/characteristic/LockPhysicalControls.js +3 -0
  122. package/dist/shared/accessory/characteristic/LockPhysicalControls.js.map +1 -0
  123. package/dist/shared/accessory/characteristic/MotionDetected.js.map +1 -0
  124. package/dist/shared/accessory/characteristic/Name.js.map +1 -0
  125. package/dist/shared/accessory/characteristic/OccupancyDetected.js.map +1 -0
  126. package/dist/shared/{accessories → accessory}/characteristic/On.js +1 -0
  127. package/dist/shared/accessory/characteristic/On.js.map +1 -0
  128. package/dist/shared/accessory/characteristic/OutletInUse.js.map +1 -0
  129. package/dist/shared/accessory/characteristic/ProgrammableSwitchEvent.js.map +1 -0
  130. package/dist/shared/{accessories → accessory}/characteristic/RelativeHumidityDehumidifierThreshold.js +3 -0
  131. package/dist/shared/accessory/characteristic/RelativeHumidityDehumidifierThreshold.js.map +1 -0
  132. package/dist/shared/accessory/characteristic/RotationSpeed.js.map +1 -0
  133. package/dist/shared/accessory/characteristic/SecuritySystemState.js.map +1 -0
  134. package/dist/shared/{accessories → accessory}/characteristic/SwingMode.js +3 -0
  135. package/dist/shared/accessory/characteristic/SwingMode.js.map +1 -0
  136. package/dist/shared/accessory/characteristic/TargetTemperature.js.map +1 -0
  137. package/dist/shared/accessory/characteristic/TemperatureDisplayUnits.js.map +1 -0
  138. package/dist/shared/util/ConfigHash.js +2 -2
  139. package/dist/shared/util/ConfigHash.js.map +1 -1
  140. package/dist/shared/util/ConfigMigrator.js +222 -0
  141. package/dist/shared/util/ConfigMigrator.js.map +1 -0
  142. package/dist/shared/util/FfmpegStreamingProcess.js +62 -0
  143. package/dist/shared/util/FfmpegStreamingProcess.js.map +1 -1
  144. package/dist/shared/util/InfraredTool.js +0 -2
  145. package/dist/shared/util/InfraredTool.js.map +1 -1
  146. package/dist/shared/util/Logger.js +85 -10
  147. package/dist/shared/util/Logger.js.map +1 -1
  148. package/dist/shared/util/TuyaStreamDelegate.js +194 -97
  149. package/dist/shared/util/TuyaStreamDelegate.js.map +1 -1
  150. package/dist/shared/util/util.js +59 -4
  151. package/dist/shared/util/util.js.map +1 -1
  152. package/docs/ADVANCED_OPTIONS.md +603 -0
  153. package/docs/CONFIG_GUIDE.md +616 -0
  154. package/docs/Get-Local-Keys-for-Your-Devices.md +246 -0
  155. package/{SUPPORTED_DEVICES.md → docs/SUPPORTED_DEVICES.md} +24 -3
  156. package/eslint.config.mjs +0 -1
  157. package/{jest.config.js → jest.config.ts} +5 -2
  158. package/package.json +12 -9
  159. package/test/ConfigMigrator.test.ts +1060 -0
  160. package/test/Logger.test.ts +482 -0
  161. package/test/accessoryFactory.data.test.ts +172 -0
  162. package/test/accessoryFactory.test.ts +64 -35
  163. package/test/airConditioner.test.ts +742 -0
  164. package/test/config.test.ts +17 -13
  165. package/test/custom.test.ts +2 -2
  166. package/test/errorHandling.test.ts +12 -12
  167. package/test/home.test.ts +1 -1
  168. package/test/hybridDeviceManager.test.ts +808 -0
  169. package/test/light.test.ts +250 -0
  170. package/test/localDevice.test.ts +21 -50
  171. package/test/localDeviceManager.behavior.test.ts +196 -31
  172. package/test/localDeviceManager.test.ts +124 -41
  173. package/test/mqttMessages.test.ts +33 -14
  174. package/test/platform.test.ts +337 -814
  175. package/test/platform.validation.local.test.ts +58 -119
  176. package/test/tuyaCustomDeviceManager.test.ts +106 -16
  177. package/test/tuyaDeviceManager.test.ts +636 -639
  178. package/test/tuyaDiscovery.test.ts +21 -33
  179. package/test/tuyaHomeDeviceManager.test.ts +109 -18
  180. package/test/tuyaOpenAPI.test.ts +25 -44
  181. package/test/tuyaOpenMQ.test.ts +15 -23
  182. package/test/util.test.ts +107 -7
  183. package/test/zigbee/LocalDevice.zigbee.test.ts +14 -18
  184. package/test/zigbee/LocalDeviceManager.cloud-discovery.test.ts +19 -20
  185. package/test/zigbee/LocalDeviceManager.zigbee.reconnect.test.ts +19 -20
  186. package/test/zigbee/LocalDeviceManager.zigbee.test.ts +73 -35
  187. package/test/zigbee/ZigbeeGatewayDetection.test.ts +2 -2
  188. package/ADVANCED_OPTIONS.md +0 -267
  189. package/dist/cloud/device/TuyaDeviceManager.js.map +0 -1
  190. package/dist/local/CloudLocalReconciliation.js +0 -180
  191. package/dist/local/CloudLocalReconciliation.js.map +0 -1
  192. package/dist/shared/AccessoryFactory.js +0 -276
  193. package/dist/shared/AccessoryFactory.js.map +0 -1
  194. package/dist/shared/accessories/AccessoryFactory.js +0 -305
  195. package/dist/shared/accessories/AccessoryFactory.js.map +0 -1
  196. package/dist/shared/accessories/AirConditionerAccessory.js.map +0 -1
  197. package/dist/shared/accessories/AirQualitySensorAccessory.js.map +0 -1
  198. package/dist/shared/accessories/BaseAccessory.js.map +0 -1
  199. package/dist/shared/accessories/CameraAccessory.js.map +0 -1
  200. package/dist/shared/accessories/GarageDoorAccessory.js.map +0 -1
  201. package/dist/shared/accessories/HumanPresenceSensorAccessory.js.map +0 -1
  202. package/dist/shared/accessories/IRAirConditionerAccessory.js.map +0 -1
  203. package/dist/shared/accessories/IRControlHubAccessory.js.map +0 -1
  204. package/dist/shared/accessories/IRControlHubSubAccessory.js.map +0 -1
  205. package/dist/shared/accessories/IRGenericAccessory.js.map +0 -1
  206. package/dist/shared/accessories/LocationWeatherAccessory.js.map +0 -1
  207. package/dist/shared/accessories/MotionSensorAccessory.js.map +0 -1
  208. package/dist/shared/accessories/OutletAccessory.js.map +0 -1
  209. package/dist/shared/accessories/SceneAccessory.js.map +0 -1
  210. package/dist/shared/accessories/SceneSwitchAccessory.js.map +0 -1
  211. package/dist/shared/accessories/SecuritySystemAccessory.js.map +0 -1
  212. package/dist/shared/accessories/SwitchAccessory.js.map +0 -1
  213. package/dist/shared/accessories/TemperatureHumiditySensorAccessory.js.map +0 -1
  214. package/dist/shared/accessories/WeatherStationAccessory.js.map +0 -1
  215. package/dist/shared/accessories/WetBulbGlobeTemperatureAccessory.js.map +0 -1
  216. package/dist/shared/accessories/WhiteNoiseLightAccessory.js.map +0 -1
  217. package/dist/shared/accessories/WindowAccessory.js.map +0 -1
  218. package/dist/shared/accessories/characteristic/Active.js.map +0 -1
  219. package/dist/shared/accessories/characteristic/AirQuality.js.map +0 -1
  220. package/dist/shared/accessories/characteristic/CurrentRelativeHumidity.js.map +0 -1
  221. package/dist/shared/accessories/characteristic/CurrentTemperature.js.map +0 -1
  222. package/dist/shared/accessories/characteristic/CurrentWeather.js.map +0 -1
  223. package/dist/shared/accessories/characteristic/CurrentWeatherByOpenMeteo.js.map +0 -1
  224. package/dist/shared/accessories/characteristic/CurrentWetBulbGlobeTemperature.js.map +0 -1
  225. package/dist/shared/accessories/characteristic/EnergyUsage.js.map +0 -1
  226. package/dist/shared/accessories/characteristic/Light.js.map +0 -1
  227. package/dist/shared/accessories/characteristic/LightSensor.js.map +0 -1
  228. package/dist/shared/accessories/characteristic/LockPhysicalControls.js.map +0 -1
  229. package/dist/shared/accessories/characteristic/MotionDetected.js.map +0 -1
  230. package/dist/shared/accessories/characteristic/Name.js.map +0 -1
  231. package/dist/shared/accessories/characteristic/OccupancyDetected.js.map +0 -1
  232. package/dist/shared/accessories/characteristic/On.js.map +0 -1
  233. package/dist/shared/accessories/characteristic/OutletInUse.js.map +0 -1
  234. package/dist/shared/accessories/characteristic/ProgrammableSwitchEvent.js.map +0 -1
  235. package/dist/shared/accessories/characteristic/RelativeHumidityDehumidifierThreshold.js.map +0 -1
  236. package/dist/shared/accessories/characteristic/RotationSpeed.js.map +0 -1
  237. package/dist/shared/accessories/characteristic/SecuritySystemState.js.map +0 -1
  238. package/dist/shared/accessories/characteristic/SwingMode.js.map +0 -1
  239. package/dist/shared/accessories/characteristic/TargetTemperature.js.map +0 -1
  240. package/dist/shared/accessories/characteristic/TemperatureDisplayUnits.js.map +0 -1
  241. package/test/zigbee/CloudLocalReconciliation.test.ts +0 -284
  242. package/tuya-local-configs/dev-1.hash +0 -1
  243. package/tuya-local-configs/device1.hash +0 -1
  244. package/wiki/Get-Local-Keys-for-Your-Devices.md +0 -85
  245. /package/dist/shared/{accessories → accessory}/AirPurifierAccessory.js +0 -0
  246. /package/dist/shared/{accessories → accessory}/AirQualitySensorAccessory.js +0 -0
  247. /package/dist/shared/{accessories → accessory}/BlindsAccessory.js +0 -0
  248. /package/dist/shared/{accessories → accessory}/CarbonDioxideSensorAccessory.js +0 -0
  249. /package/dist/shared/{accessories → accessory}/CarbonMonoxideSensorAccessory.js +0 -0
  250. /package/dist/shared/{accessories → accessory}/ContactSensorAccessory.js +0 -0
  251. /package/dist/shared/{accessories → accessory}/DehumidifierAccessory.js +0 -0
  252. /package/dist/shared/{accessories → accessory}/DiffuserAccessory.js +0 -0
  253. /package/dist/shared/{accessories → accessory}/DimmerAccessory.js +0 -0
  254. /package/dist/shared/{accessories → accessory}/DoorbellAccessory.js +0 -0
  255. /package/dist/shared/{accessories → accessory}/ExtractionHoodAccessory.js +0 -0
  256. /package/dist/shared/{accessories → accessory}/FanAccessory.js +0 -0
  257. /package/dist/shared/{accessories → accessory}/HeaterAccessory.js +0 -0
  258. /package/dist/shared/{accessories → accessory}/HeaterAccessory_old.js +0 -0
  259. /package/dist/shared/{accessories → accessory}/HumanPresenceSensorAccessory.js +0 -0
  260. /package/dist/shared/{accessories → accessory}/HumidifierAccessory.js +0 -0
  261. /package/dist/shared/{accessories → accessory}/IRAirConditionerAccessory.js +0 -0
  262. /package/dist/shared/{accessories → accessory}/IRControlHubAccessory.js +0 -0
  263. /package/dist/shared/{accessories → accessory}/IRControlHubSubAccessory.js +0 -0
  264. /package/dist/shared/{accessories → accessory}/IRGenericAccessory.js +0 -0
  265. /package/dist/shared/{accessories → accessory}/LeakSensorAccessory.js +0 -0
  266. /package/dist/shared/{accessories → accessory}/LightAccessory.js +0 -0
  267. /package/dist/shared/{accessories → accessory}/LightSensorAccessory.js +0 -0
  268. /package/dist/shared/{accessories → accessory}/MotionSensorAccessory.js +0 -0
  269. /package/dist/shared/{accessories → accessory}/OutletAccessory.js +0 -0
  270. /package/dist/shared/{accessories → accessory}/PetFeederAccessory.js +0 -0
  271. /package/dist/shared/{accessories → accessory}/SceneSwitchAccessory.js +0 -0
  272. /package/dist/shared/{accessories → accessory}/SecuritySystemAccessory.js +0 -0
  273. /package/dist/shared/{accessories → accessory}/SmokeSensorAccessory.js +0 -0
  274. /package/dist/shared/{accessories → accessory}/TemperatureHumiditySensorAccessory.js +0 -0
  275. /package/dist/shared/{accessories → accessory}/ThermostatAccessory.js +0 -0
  276. /package/dist/shared/{accessories → accessory}/TowerRackAccessory.js +0 -0
  277. /package/dist/shared/{accessories → accessory}/ValveAccessory.js +0 -0
  278. /package/dist/shared/{accessories → accessory}/VibrationSensorAccessory.js +0 -0
  279. /package/dist/shared/{accessories → accessory}/WeatherStationAccessory.js +0 -0
  280. /package/dist/shared/{accessories → accessory}/WetBulbGlobeTemperatureAccessory.js +0 -0
  281. /package/dist/shared/{accessories → accessory}/WindowAccessory.js +0 -0
  282. /package/dist/shared/{accessories → accessory}/WindowCoveringAccessory.js +0 -0
  283. /package/dist/shared/{accessories → accessory}/WirelessSwitchAccessory.js +0 -0
  284. /package/dist/shared/{accessories → accessory}/characteristic/Active.js +0 -0
  285. /package/dist/shared/{accessories → accessory}/characteristic/AirQuality.js +0 -0
  286. /package/dist/shared/{accessories → accessory}/characteristic/CurrentTemperature.js +0 -0
  287. /package/dist/shared/{accessories → accessory}/characteristic/CurrentWeather.js +0 -0
  288. /package/dist/shared/{accessories → accessory}/characteristic/CurrentWeatherByOpenMeteo.js +0 -0
  289. /package/dist/shared/{accessories → accessory}/characteristic/LightSensor.js +0 -0
  290. /package/dist/shared/{accessories → accessory}/characteristic/MotionDetected.js +0 -0
  291. /package/dist/shared/{accessories → accessory}/characteristic/Name.js +0 -0
  292. /package/dist/shared/{accessories → accessory}/characteristic/OccupancyDetected.js +0 -0
  293. /package/dist/shared/{accessories → accessory}/characteristic/OutletInUse.js +0 -0
  294. /package/dist/shared/{accessories → accessory}/characteristic/ProgrammableSwitchEvent.js +0 -0
  295. /package/dist/shared/{accessories → accessory}/characteristic/RotationSpeed.js +0 -0
  296. /package/dist/shared/{accessories → accessory}/characteristic/SecuritySystemState.js +0 -0
  297. /package/dist/shared/{accessories → accessory}/characteristic/TargetTemperature.js +0 -0
  298. /package/dist/shared/{accessories → accessory}/characteristic/TemperatureDisplayUnits.js +0 -0
@@ -1,50 +1,59 @@
1
1
  import { beforeEach, describe, expect, jest, test } from '@jest/globals';
2
2
  import { TuyaPlatform } from '../src/platform';
3
-
4
- jest.mock('../src/shared/util/Logger', () => ({
5
- __esModule: true,
6
- default: class Logger {
7
- log() {}
8
- info() {}
9
- warn() {}
10
- error() {}
11
- },
12
- PrefixLogger: class PrefixLogger {
13
- constructor(public log: unknown, public name: string, public debug: boolean) {}
14
- },
15
- }));
3
+ import { initLogger } from '../src/shared/util/Logger';
4
+ import { Logger } from 'homebridge';
5
+
6
+ // Mock Logger
7
+ const mockLog: Logger = {
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 Logger;
16
15
 
17
16
  jest.mock('../src/cloud/api/TuyaOpenAPI', () => {
18
17
  return class MockTuyaOpenAPI {
19
18
  log = console;
19
+ static getDefaultEndpoint = jest.fn().mockReturnValue([1]);
20
20
  };
21
21
  });
22
22
 
23
- jest.mock('../src/cloud/device/TuyaDeviceManager', () => {
24
- class MockTuyaDeviceManager {
25
- static readonly Events = {
26
- DEVICE_ADD: 'DEVICE_ADD',
27
- DEVICE_INFO_UPDATE: 'DEVICE_INFO_UPDATE',
28
- DEVICE_STATUS_UPDATE: 'DEVICE_STATUS_UPDATE',
29
- DEVICE_DELETE: 'DEVICE_DELETE',
30
- };
31
- }
32
- return MockTuyaDeviceManager;
33
- });
34
-
35
23
  jest.mock('../src/cloud/device/TuyaCustomDeviceManager', () => {
36
- return class MockTuyaCustomDeviceManager {};
24
+ return class MockTuyaCustomDeviceManager {
25
+ pullDevices = jest.fn().mockReturnValue([]);
26
+ updateInfraredRemotes = jest.fn();
27
+ getDeviceSchemaConfig = jest.fn();
28
+ devices = [];
29
+ api = mockAPI;
30
+ on = jest.fn();
31
+ };
37
32
  });
38
33
 
39
34
  jest.mock('../src/cloud/device/TuyaHomeDeviceManager', () => {
40
- return class MockTuyaHomeDeviceManager {};
35
+ return class MockTuyaHomeDeviceManager {
36
+ pullDevices = jest.fn().mockReturnValue([]);
37
+ updateInfraredRemotes = jest.fn();
38
+ getDeviceSchemaConfig = jest.fn();
39
+ devices = [];
40
+ api = mockAPI;
41
+ on = jest.fn();
42
+ };
41
43
  });
42
44
 
43
45
  jest.mock('../src/local/LocalDeviceManager', () => {
44
- return class MockLocalDeviceManager {};
46
+ return class MockLocalDeviceManager {
47
+ pullDevices = jest.fn().mockReturnValue([]);
48
+ updateInfraredRemotes = jest.fn();
49
+ getDeviceSchemaConfig = jest.fn();
50
+ devices = [];
51
+ api = mockAPI;
52
+ on = jest.fn();
53
+ };
45
54
  });
46
55
 
47
- jest.mock('../src/shared/accessories/AccessoryFactory', () => ({
56
+ jest.mock('../src/shared/accessory/AccessoryFactory', () => ({
48
57
  __esModule: true,
49
58
  default: {
50
59
  configAccessory: jest.fn(),
@@ -57,6 +66,13 @@ jest.mock('../src/shared/util/util', () => ({
57
66
  retry: jest.fn(async (fn: () => Promise<unknown>) => fn()),
58
67
  }));
59
68
 
69
+ jest.mock('../src/shared/util/ConfigMigrator', () => ({
70
+ __esModule: true,
71
+ default: class ConfigMigrator {
72
+ migrate(arg:any) { return arg; }
73
+ }
74
+ }));
75
+
60
76
  const mockAPI = {
61
77
  hap: {
62
78
  Service: {},
@@ -69,19 +85,13 @@ const mockAPI = {
69
85
  user: {
70
86
  persistPath: () => '/tmp',
71
87
  },
88
+ tokenInfo: {}
72
89
  } as any;
73
90
 
74
91
  describe('TuyaPlatform validation around cloud/local modes', () => {
75
- let log: any;
76
-
77
92
  beforeEach(() => {
78
- log = {
79
- debug: jest.fn(),
80
- info: jest.fn(),
81
- warn: jest.fn(),
82
- error: jest.fn(),
83
- };
84
93
  jest.clearAllMocks();
94
+ initLogger(mockLog);
85
95
  });
86
96
 
87
97
  test('rejects mode both when local block is missing', () => {
@@ -89,7 +99,7 @@ describe('TuyaPlatform validation around cloud/local modes', () => {
89
99
  platform: 'TuyaPlatform',
90
100
  name: 'Tuya',
91
101
  mode: 'both',
92
- options: {
102
+ cloud: {
93
103
  projectType: '2',
94
104
  accessId: 'id',
95
105
  accessKey: 'key',
@@ -102,9 +112,9 @@ describe('TuyaPlatform validation around cloud/local modes', () => {
102
112
  },
103
113
  };
104
114
 
105
- const platform = new TuyaPlatform(log, config, mockAPI);
115
+ const platform = new TuyaPlatform(mockLog, config, mockAPI);
106
116
  expect(platform.validate()).toBe(false);
107
- expect(log.error).toHaveBeenCalledWith('mode is "both" but no "local" config block found.');
117
+ expect(mockLog.error).toHaveBeenCalledWith('mode is "both" but no "local" config block found.');
108
118
  });
109
119
 
110
120
  test('rejects mode both when cloud options are missing', () => {
@@ -115,9 +125,9 @@ describe('TuyaPlatform validation around cloud/local modes', () => {
115
125
  local: { devices: [] },
116
126
  };
117
127
 
118
- const platform = new TuyaPlatform(log, config, mockAPI);
128
+ const platform = new TuyaPlatform(mockLog, config, mockAPI);
119
129
  expect(platform.validate()).toBe(false);
120
- expect(log.error).toHaveBeenCalledWith('Not configured — "options" block is required for cloud mode, exit.');
130
+ expect(mockLog.error).toHaveBeenCalledWith('Not configured — "cloud" block is required for cloud mode, exit.');
121
131
  });
122
132
 
123
133
  test('detects duplicate device override ids', () => {
@@ -125,7 +135,7 @@ describe('TuyaPlatform validation around cloud/local modes', () => {
125
135
  platform: 'TuyaPlatform',
126
136
  name: 'Tuya',
127
137
  mode: 'cloud',
128
- options: {
138
+ cloud: {
129
139
  projectType: '2',
130
140
  accessId: 'id',
131
141
  accessKey: 'key',
@@ -142,8 +152,8 @@ describe('TuyaPlatform validation around cloud/local modes', () => {
142
152
  },
143
153
  };
144
154
 
145
- const platform = new TuyaPlatform(log, config, mockAPI);
146
- expect(platform.validateDeviceOverrides()).toBe(false);
155
+ const platform = new TuyaPlatform(mockLog, config, mockAPI);
156
+ expect(platform.validateDeviceOverrides(config.cloud.deviceOverrides)).toBe(false);
147
157
  });
148
158
 
149
159
  test('detects duplicate schema codes inside one device override', () => {
@@ -151,7 +161,7 @@ describe('TuyaPlatform validation around cloud/local modes', () => {
151
161
  platform: 'TuyaPlatform',
152
162
  name: 'Tuya',
153
163
  mode: 'cloud',
154
- options: {
164
+ cloud: {
155
165
  projectType: '2',
156
166
  accessId: 'id',
157
167
  accessKey: 'key',
@@ -173,78 +183,7 @@ describe('TuyaPlatform validation around cloud/local modes', () => {
173
183
  },
174
184
  };
175
185
 
176
- const platform = new TuyaPlatform(log, config, mockAPI);
177
- expect(platform.validateSchema()).toBe(false);
178
- });
179
-
180
- test('resolves device config precedence: device, then product, then global', () => {
181
- const config = {
182
- platform: 'TuyaPlatform',
183
- name: 'Tuya',
184
- mode: 'cloud',
185
- options: {
186
- projectType: '2',
187
- accessId: 'id',
188
- accessKey: 'key',
189
- countryCode: 1,
190
- username: 'user@example.com',
191
- password: 'secret',
192
- appSchema: 'tuyaSmart',
193
- generateWeatherAccessory: false,
194
- weatherAPI: '',
195
- deviceOverrides: [
196
- { id: 'global', category: 'global-cat' },
197
- { id: 'prod-1', category: 'product-cat' },
198
- { id: 'device-1', category: 'device-cat' },
199
- ],
200
- },
201
- };
202
-
203
- const platform = new TuyaPlatform(log, config, mockAPI);
204
-
205
- const exact = platform.getDeviceConfig({ id: 'device-1', uuid: 'uuid-1', product_id: 'prod-1' } as any);
206
- const byProduct = platform.getDeviceConfig({ id: 'device-2', uuid: 'uuid-2', product_id: 'prod-1' } as any);
207
- const fallback = platform.getDeviceConfig({ id: 'device-3', uuid: 'uuid-3', product_id: 'prod-3' } as any);
208
-
209
- expect(exact?.category).toBe('device-cat');
210
- expect(byProduct?.category).toBe('product-cat');
211
- expect(fallback?.category).toBe('global-cat');
212
- });
213
-
214
- test('finds schema config case-insensitively and migrates oldCode', () => {
215
- const config = {
216
- platform: 'TuyaPlatform',
217
- name: 'Tuya',
218
- mode: 'cloud',
219
- options: {
220
- projectType: '2',
221
- accessId: 'id',
222
- accessKey: 'key',
223
- countryCode: 1,
224
- username: 'user@example.com',
225
- password: 'secret',
226
- appSchema: 'tuyaSmart',
227
- generateWeatherAccessory: false,
228
- weatherAPI: '',
229
- deviceOverrides: [
230
- {
231
- id: 'device-1',
232
- schema: [
233
- { oldCode: 'switch_1', code: 'new_switch_1', hidden: true },
234
- ],
235
- },
236
- ],
237
- },
238
- };
239
-
240
- const platform = new TuyaPlatform(log, config, mockAPI);
241
- const device = { id: 'device-1', uuid: 'device-1', product_id: 'prod-1' } as any;
242
-
243
- const result = platform.getDeviceSchemaConfig(device, 'SWITCH_1');
244
-
245
- expect(result).toBeDefined();
246
- expect(result?.code).toBe('switch_1');
247
- expect((result as any).newCode).toBe('new_switch_1');
248
- expect(result?.hidden).toBe(true);
186
+ const platform = new TuyaPlatform(mockLog, config, mockAPI);
187
+ expect(platform.validateSchema(config.cloud.deviceOverrides)).toBe(false);
249
188
  });
250
189
  });
@@ -2,20 +2,18 @@
2
2
  import { describe, expect, test, beforeEach, jest } from '@jest/globals';
3
3
  import TuyaCustomDeviceManager from '../src/cloud/device/TuyaCustomDeviceManager';
4
4
  import TuyaDevice from '../src/cloud/device/TuyaDevice';
5
+ import { TuyaPlatformCustomConfig, TuyaPluginMode } from '../src/config';
6
+ import { ExLogger, initLogger } from '../src/shared/util/Logger';
5
7
 
6
8
  // Mock Logger
7
- jest.mock('../src/shared/util/Logger', () => ({
8
- __esModule: true,
9
- default: class Logger {
10
- log() {}
11
- info() {}
12
- warn() {}
13
- error() {}
14
- },
15
- PrefixLogger: class PrefixLogger {
16
- constructor(public log: any, public name: string, public debug: boolean) {}
17
- },
18
- }));
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;
19
17
 
20
18
  // Mock TuyaOpenMQ
21
19
  jest.mock('../src/cloud/api/TuyaOpenMQ', () => {
@@ -30,16 +28,31 @@ jest.mock('../src/cloud/api/TuyaOpenMQ', () => {
30
28
  describe('TuyaCustomDeviceManager', () => {
31
29
  let manager: TuyaCustomDeviceManager;
32
30
  let mockAPI: any;
31
+ let mockConfig: any;
33
32
 
34
33
  beforeEach(() => {
34
+ jest.clearAllMocks();
35
+ initLogger(mockLog);
36
+
35
37
  mockAPI = {
36
38
  log: { log: console.log } as any,
37
39
  post: jest.fn(),
38
40
  get: jest.fn(),
39
41
  tokenInfo: { uid: 'test_uid' },
40
42
  };
41
-
42
- manager = new TuyaCustomDeviceManager(mockAPI, false);
43
+ mockConfig = {
44
+ projectType: '1',
45
+ endpoint: 'https://openapi.tuyaeu.com',
46
+ accessId: 'test_access_id',
47
+ accessKey: 'test_access_key',
48
+ username: 'user@example.com',
49
+ password: 'password',
50
+ generateWeatherAccessory: true,
51
+ weatherAPI: 'openweathermap',
52
+ forceIPv4: false
53
+ }
54
+
55
+ manager = new TuyaCustomDeviceManager(mockAPI, mockConfig, false);
43
56
  });
44
57
 
45
58
  describe('initialization', () => {
@@ -49,7 +62,7 @@ describe('TuyaCustomDeviceManager', () => {
49
62
  });
50
63
 
51
64
  test('sets MQTT version to 2.0', () => {
52
- const customManager = new TuyaCustomDeviceManager(mockAPI, false);
65
+ const customManager = new TuyaCustomDeviceManager(mockAPI, mockConfig, false);
53
66
  expect(customManager.mq.version).toBe('2.0');
54
67
  });
55
68
 
@@ -59,7 +72,7 @@ describe('TuyaCustomDeviceManager', () => {
59
72
  });
60
73
 
61
74
  test('supports debug mode', () => {
62
- const debugManager = new TuyaCustomDeviceManager(mockAPI, true);
75
+ const debugManager = new TuyaCustomDeviceManager(mockAPI, mockConfig, true);
63
76
  expect(debugManager.debug).toBe(true);
64
77
  });
65
78
  });
@@ -466,4 +479,81 @@ describe('TuyaCustomDeviceManager', () => {
466
479
  expect(mockAPI.post.mock.calls[0][1].asset_ids).toBe(assetIds.join(','));
467
480
  });
468
481
  });
482
+
483
+ describe('get device config', () => {
484
+ test('resolves device config precedence: device, then product, then global', () => {
485
+ const config = {
486
+ platform: 'TuyaPlatform',
487
+ name: 'Tuya',
488
+ mode: 'cloud',
489
+ cloud: {
490
+ projectType: '1',
491
+ endpoint: 'https://openapi.tuyaeu.com',
492
+ accessId: 'test_access_id',
493
+ accessKey: 'test_access_key',
494
+ username: 'user@example.com',
495
+ password: 'password',
496
+ generateWeatherAccessory: true,
497
+ weatherAPI: 'openweathermap',
498
+ forceIPv4: false,
499
+ deviceOverrides: [
500
+ { id: 'global', category: 'global-cat', configFor: TuyaPluginMode.cloud },
501
+ { id: 'prod-1', category: 'product-cat', configFor: TuyaPluginMode.cloud },
502
+ { id: 'device-1', category: 'device-cat', configFor: TuyaPluginMode.cloud },
503
+ ],
504
+ } as TuyaPlatformCustomConfig,
505
+ };
506
+
507
+ const deviceManager = new TuyaCustomDeviceManager(mockAPI, config.cloud, false);
508
+
509
+ const exact = deviceManager.getDeviceConfig({ id: 'device-1', uuid: 'uuid-1', product_id: 'prod-1' } as any);
510
+ const byProduct = deviceManager.getDeviceConfig({ id: 'device-2', uuid: 'uuid-2', product_id: 'prod-1' } as any);
511
+ const fallback = deviceManager.getDeviceConfig({ id: 'device-3', uuid: 'uuid-3', product_id: 'prod-3' } as any);
512
+
513
+ expect(exact?.category).toBe('device-cat');
514
+ expect(byProduct?.category).toBe('product-cat');
515
+ expect(fallback?.category).toBe('global-cat');
516
+ });
517
+ });
518
+
519
+ describe('get device config', () => {
520
+ test('finds schema config case-insensitively', () => {
521
+ const config = {
522
+ platform: 'TuyaPlatform',
523
+ name: 'Tuya',
524
+ mode: 'cloud',
525
+ cloud: {
526
+ projectType: '1',
527
+ endpoint: 'https://openapi.tuyaeu.com',
528
+ accessId: 'test_access_id',
529
+ accessKey: 'test_access_key',
530
+ username: 'user@example.com',
531
+ password: 'password',
532
+ generateWeatherAccessory: true,
533
+ weatherAPI: 'openweathermap',
534
+ forceIPv4: false,
535
+ deviceOverrides: [
536
+ {
537
+ id: 'device-1',
538
+ schema: [
539
+ { code: 'switch_1', newCode: 'new_switch_1', hidden: true },
540
+ ],
541
+ configFor: TuyaPluginMode.cloud
542
+ },
543
+ ],
544
+ } as TuyaPlatformCustomConfig,
545
+ };
546
+
547
+ const deviceManager = new TuyaCustomDeviceManager(mockAPI, config.cloud, false);
548
+
549
+ const device = { id: 'device-1', uuid: 'device-1', product_id: 'prod-1' } as any;
550
+
551
+ const result = deviceManager!.getDeviceSchemaConfig(device, 'SWITCH_1');
552
+
553
+ expect(result).toBeDefined();
554
+ expect(result?.code).toBe('switch_1');
555
+ expect((result as any).newCode).toBe('new_switch_1');
556
+ expect(result?.hidden).toBe(true);
557
+ });
558
+ });
469
559
  });