@homebridge-plugins/homebridge-tuya 3.0.0-beta.0 → 3.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +166 -145
  3. package/config.schema.json +976 -11
  4. package/dist/{core → cloud/api}/TuyaOpenAPI.js +16 -7
  5. package/dist/cloud/api/TuyaOpenAPI.js.map +1 -0
  6. package/dist/{core → cloud/api}/TuyaOpenMQ.js +13 -11
  7. package/dist/cloud/api/TuyaOpenMQ.js.map +1 -0
  8. package/dist/cloud/device/TuyaCustomDeviceManager.js.map +1 -0
  9. package/dist/{device → cloud/device}/TuyaDevice.js +14 -1
  10. package/dist/cloud/device/TuyaDevice.js.map +1 -0
  11. package/dist/{device → cloud/device}/TuyaDeviceManager.js +12 -3
  12. package/dist/cloud/device/TuyaDeviceManager.js.map +1 -0
  13. package/dist/cloud/device/TuyaHomeDeviceManager.js.map +1 -0
  14. package/dist/config.js +1 -0
  15. package/dist/config.js.map +1 -1
  16. package/dist/local/CloudLocalReconciliation.js +180 -0
  17. package/dist/local/CloudLocalReconciliation.js.map +1 -0
  18. package/dist/local/DynamicChildDiscovery.js +154 -0
  19. package/dist/local/DynamicChildDiscovery.js.map +1 -0
  20. package/dist/local/LocalDevice.js +419 -0
  21. package/dist/local/LocalDevice.js.map +1 -0
  22. package/dist/local/LocalDeviceManager.js +981 -0
  23. package/dist/local/LocalDeviceManager.js.map +1 -0
  24. package/dist/local/TuyaDiscovery.js +248 -0
  25. package/dist/local/TuyaDiscovery.js.map +1 -0
  26. package/dist/local/ZigbeeEventDetection.js +213 -0
  27. package/dist/local/ZigbeeEventDetection.js.map +1 -0
  28. package/dist/local/ZigbeeGatewayDetection.js +109 -0
  29. package/dist/local/ZigbeeGatewayDetection.js.map +1 -0
  30. package/dist/local/config.js +6 -0
  31. package/dist/local/config.js.map +1 -0
  32. package/dist/local/protocol/ChildPayloadUtility.js +94 -0
  33. package/dist/local/protocol/ChildPayloadUtility.js.map +1 -0
  34. package/dist/local/protocol/Protocol.js +3 -0
  35. package/dist/local/protocol/Protocol.js.map +1 -0
  36. package/dist/local/protocol/ProtocolFactory.js +27 -0
  37. package/dist/local/protocol/ProtocolFactory.js.map +1 -0
  38. package/dist/local/protocol/ProtocolUtilities.js +329 -0
  39. package/dist/local/protocol/ProtocolUtilities.js.map +1 -0
  40. package/dist/local/protocol/ProtocolV31V32.js +60 -0
  41. package/dist/local/protocol/ProtocolV31V32.js.map +1 -0
  42. package/dist/local/protocol/ProtocolV33.js +52 -0
  43. package/dist/local/protocol/ProtocolV33.js.map +1 -0
  44. package/dist/local/protocol/ProtocolV34.js +104 -0
  45. package/dist/local/protocol/ProtocolV34.js.map +1 -0
  46. package/dist/local/protocol/ProtocolV35.js +77 -0
  47. package/dist/local/protocol/ProtocolV35.js.map +1 -0
  48. package/dist/platform.js +284 -67
  49. package/dist/platform.js.map +1 -1
  50. package/dist/shared/AccessoryFactory.js +276 -0
  51. package/dist/shared/AccessoryFactory.js.map +1 -0
  52. package/dist/{accessory → shared/accessories}/AccessoryFactory.js +2 -2
  53. package/dist/shared/accessories/AccessoryFactory.js.map +1 -0
  54. package/dist/shared/accessories/AirConditionerAccessory.js.map +1 -0
  55. package/dist/{accessory → shared/accessories}/AirPurifierAccessory.js +1 -1
  56. package/dist/shared/accessories/AirPurifierAccessory.js.map +1 -0
  57. package/dist/shared/accessories/AirQualitySensorAccessory.js.map +1 -0
  58. package/dist/{accessory → shared/accessories}/BaseAccessory.js +139 -35
  59. package/dist/shared/accessories/BaseAccessory.js.map +1 -0
  60. package/dist/shared/accessories/BlindsAccessory.js +199 -0
  61. package/dist/shared/accessories/BlindsAccessory.js.map +1 -0
  62. package/dist/{accessory → shared/accessories}/CameraAccessory.js +7 -3
  63. package/dist/shared/accessories/CameraAccessory.js.map +1 -0
  64. package/dist/shared/accessories/CarbonDioxideSensorAccessory.js.map +1 -0
  65. package/dist/shared/accessories/CarbonMonoxideSensorAccessory.js.map +1 -0
  66. package/dist/shared/accessories/ContactSensorAccessory.js.map +1 -0
  67. package/dist/shared/accessories/DehumidifierAccessory.js.map +1 -0
  68. package/dist/shared/accessories/DiffuserAccessory.js.map +1 -0
  69. package/dist/shared/accessories/DimmerAccessory.js.map +1 -0
  70. package/dist/{accessory → shared/accessories}/DoorbellAccessory.js +3 -1
  71. package/dist/shared/accessories/DoorbellAccessory.js.map +1 -0
  72. package/dist/{accessory → shared/accessories}/ExtractionHoodAccessory.js +4 -2
  73. package/dist/shared/accessories/ExtractionHoodAccessory.js.map +1 -0
  74. package/dist/{accessory → shared/accessories}/FanAccessory.js +10 -4
  75. package/dist/shared/accessories/FanAccessory.js.map +1 -0
  76. package/dist/shared/accessories/GarageDoorAccessory.js.map +1 -0
  77. package/dist/shared/accessories/HeaterAccessory.js.map +1 -0
  78. package/dist/shared/accessories/HeaterAccessory_old.js.map +1 -0
  79. package/dist/shared/accessories/HumanPresenceSensorAccessory.js.map +1 -0
  80. package/dist/{accessory → shared/accessories}/HumidifierAccessory.js +3 -1
  81. package/dist/shared/accessories/HumidifierAccessory.js.map +1 -0
  82. package/dist/{accessory → shared/accessories}/IRAirConditionerAccessory.js +2 -2
  83. package/dist/shared/accessories/IRAirConditionerAccessory.js.map +1 -0
  84. package/dist/shared/accessories/IRControlHubAccessory.js.map +1 -0
  85. package/dist/shared/accessories/IRControlHubSubAccessory.js.map +1 -0
  86. package/dist/shared/accessories/IRGenericAccessory.js.map +1 -0
  87. package/dist/shared/accessories/LeakSensorAccessory.js.map +1 -0
  88. package/dist/shared/accessories/LightAccessory.js.map +1 -0
  89. package/dist/shared/accessories/LightSensorAccessory.js.map +1 -0
  90. package/dist/shared/accessories/LocationWeatherAccessory.js.map +1 -0
  91. package/dist/shared/accessories/LockAccessory.js.map +1 -0
  92. package/dist/shared/accessories/MotionSensorAccessory.js.map +1 -0
  93. package/dist/shared/accessories/OutletAccessory.js.map +1 -0
  94. package/dist/shared/accessories/PetFeederAccessory.js.map +1 -0
  95. package/dist/shared/accessories/SceneAccessory.js.map +1 -0
  96. package/dist/{accessory → shared/accessories}/SceneSwitchAccessory.js +1 -1
  97. package/dist/shared/accessories/SceneSwitchAccessory.js.map +1 -0
  98. package/dist/shared/accessories/SecuritySystemAccessory.js.map +1 -0
  99. package/dist/shared/accessories/SmokeSensorAccessory.js.map +1 -0
  100. package/dist/shared/accessories/SwitchAccessory.js +148 -0
  101. package/dist/shared/accessories/SwitchAccessory.js.map +1 -0
  102. package/dist/shared/accessories/TemperatureHumiditySensorAccessory.js.map +1 -0
  103. package/dist/shared/accessories/ThermostatAccessory.js.map +1 -0
  104. package/dist/shared/accessories/TowerRackAccessory.js.map +1 -0
  105. package/dist/{accessory → shared/accessories}/ValveAccessory.js +1 -1
  106. package/dist/shared/accessories/ValveAccessory.js.map +1 -0
  107. package/dist/{accessory → shared/accessories}/VibrationSensorAccessory.js +7 -3
  108. package/dist/shared/accessories/VibrationSensorAccessory.js.map +1 -0
  109. package/dist/shared/accessories/WeatherStationAccessory.js.map +1 -0
  110. package/dist/shared/accessories/WetBulbGlobeTemperatureAccessory.js.map +1 -0
  111. package/dist/shared/accessories/WhiteNoiseLightAccessory.js.map +1 -0
  112. package/dist/shared/accessories/WindowAccessory.js.map +1 -0
  113. package/dist/shared/accessories/WindowCoveringAccessory.js.map +1 -0
  114. package/dist/shared/accessories/WirelessSwitchAccessory.js.map +1 -0
  115. package/dist/shared/accessories/characteristic/Active.js.map +1 -0
  116. package/dist/{accessory → shared/accessories}/characteristic/AirQuality.js +1 -1
  117. package/dist/shared/accessories/characteristic/AirQuality.js.map +1 -0
  118. package/dist/shared/accessories/characteristic/CurrentRelativeHumidity.js.map +1 -0
  119. package/dist/shared/accessories/characteristic/CurrentTemperature.js.map +1 -0
  120. package/dist/shared/accessories/characteristic/CurrentWeather.js.map +1 -0
  121. package/dist/shared/accessories/characteristic/CurrentWeatherByOpenMeteo.js.map +1 -0
  122. package/dist/shared/accessories/characteristic/CurrentWetBulbGlobeTemperature.js.map +1 -0
  123. package/dist/shared/accessories/characteristic/EnergyUsage.js.map +1 -0
  124. package/dist/shared/accessories/characteristic/Light.js.map +1 -0
  125. package/dist/shared/accessories/characteristic/LightSensor.js.map +1 -0
  126. package/dist/shared/accessories/characteristic/LockPhysicalControls.js.map +1 -0
  127. package/dist/{accessory → shared/accessories}/characteristic/MotionDetected.js +1 -1
  128. package/dist/shared/accessories/characteristic/MotionDetected.js.map +1 -0
  129. package/dist/shared/accessories/characteristic/Name.js.map +1 -0
  130. package/dist/shared/accessories/characteristic/OccupancyDetected.js.map +1 -0
  131. package/dist/{accessory → shared/accessories}/characteristic/On.js +1 -1
  132. package/dist/shared/accessories/characteristic/On.js.map +1 -0
  133. package/dist/shared/accessories/characteristic/OutletInUse.js.map +1 -0
  134. package/dist/{accessory → shared/accessories}/characteristic/ProgrammableSwitchEvent.js +2 -2
  135. package/dist/shared/accessories/characteristic/ProgrammableSwitchEvent.js.map +1 -0
  136. package/dist/shared/accessories/characteristic/RelativeHumidityDehumidifierThreshold.js.map +1 -0
  137. package/dist/shared/accessories/characteristic/RotationSpeed.js.map +1 -0
  138. package/dist/shared/accessories/characteristic/SecuritySystemState.js.map +1 -0
  139. package/dist/shared/accessories/characteristic/SwingMode.js.map +1 -0
  140. package/dist/shared/accessories/characteristic/TargetTemperature.js.map +1 -0
  141. package/dist/shared/accessories/characteristic/TemperatureDisplayUnits.js.map +1 -0
  142. package/dist/shared/util/ConfigHash.js +79 -0
  143. package/dist/shared/util/ConfigHash.js.map +1 -0
  144. package/dist/shared/util/FfmpegStreamingProcess.js.map +1 -0
  145. package/dist/shared/util/InfraredTool.js.map +1 -0
  146. package/dist/shared/util/Logger.js.map +1 -0
  147. package/dist/shared/util/TuyaRecordingDelegate.js.map +1 -0
  148. package/dist/shared/util/TuyaStreamDelegate.js.map +1 -0
  149. package/dist/shared/util/color.js.map +1 -0
  150. package/dist/shared/util/util.js +135 -0
  151. package/dist/shared/util/util.js.map +1 -0
  152. package/eslint.config.mjs +52 -0
  153. package/jest.config.js +6 -0
  154. package/package.json +23 -28
  155. package/test/__mocks__/@homebridge-camera-utils.js +10 -0
  156. package/test/__mocks__/color-convert.js +24 -0
  157. package/test/__mocks__/kelvin-to-rgb.js +21 -0
  158. package/test/accessoryFactory.test.ts +522 -0
  159. package/test/config.test.ts +430 -0
  160. package/test/custom.test.ts +4 -4
  161. package/test/errorHandling.test.ts +570 -0
  162. package/test/errorHandlingCoverage.test.ts +410 -0
  163. package/test/home.test.ts +4 -4
  164. package/test/localDevice.test.ts +616 -0
  165. package/test/localDeviceManager.behavior.test.ts +185 -0
  166. package/test/localDeviceManager.test.ts +327 -0
  167. package/test/mqttMessages.test.ts +495 -0
  168. package/test/platform.test.ts +1310 -0
  169. package/test/platform.validation.local.test.ts +250 -0
  170. package/test/protocol.test.ts +446 -0
  171. package/test/protocolUtilities.test.ts +351 -0
  172. package/test/sanitizeName.test.ts +2 -1
  173. package/test/tuyaCustomDeviceManager.test.ts +469 -0
  174. package/test/tuyaDevice.test.ts +425 -0
  175. package/test/tuyaDeviceManager.test.ts +813 -0
  176. package/test/tuyaDiscovery.test.ts +439 -0
  177. package/test/tuyaHomeDeviceManager.test.ts +540 -0
  178. package/test/tuyaOpenAPI.test.ts +404 -0
  179. package/test/tuyaOpenMQ.test.ts +444 -0
  180. package/test/util.test.ts +318 -0
  181. package/test/util.ts +4 -3
  182. package/test/zigbee/ChildPayloadUtility.test.ts +199 -0
  183. package/test/zigbee/CloudLocalReconciliation.test.ts +284 -0
  184. package/test/zigbee/DynamicChildDiscovery.test.ts +333 -0
  185. package/test/zigbee/LocalDevice.zigbee.test.ts +274 -0
  186. package/test/zigbee/LocalDeviceManager.cloud-discovery.test.ts +163 -0
  187. package/test/zigbee/LocalDeviceManager.zigbee.reconnect.test.ts +200 -0
  188. package/test/zigbee/LocalDeviceManager.zigbee.test.ts +344 -0
  189. package/test/zigbee/ZigbeeEventDetection.test.ts +418 -0
  190. package/test/zigbee/ZigbeeGatewayDetection.test.ts +222 -0
  191. package/tuya-local-configs/dev-1.hash +1 -0
  192. package/tuya-local-configs/device1.hash +1 -0
  193. package/wiki/Get-Local-Keys-for-Your-Devices.md +85 -0
  194. package/dist/accessory/AccessoryFactory.js.map +0 -1
  195. package/dist/accessory/AirConditionerAccessory.js.map +0 -1
  196. package/dist/accessory/AirPurifierAccessory.js.map +0 -1
  197. package/dist/accessory/AirQualitySensorAccessory.js.map +0 -1
  198. package/dist/accessory/BaseAccessory.js.map +0 -1
  199. package/dist/accessory/CameraAccessory.js.map +0 -1
  200. package/dist/accessory/CarbonDioxideSensorAccessory.js.map +0 -1
  201. package/dist/accessory/CarbonMonoxideSensorAccessory.js.map +0 -1
  202. package/dist/accessory/ContactSensorAccessory.js.map +0 -1
  203. package/dist/accessory/DehumidifierAccessory.js.map +0 -1
  204. package/dist/accessory/DiffuserAccessory.js.map +0 -1
  205. package/dist/accessory/DimmerAccessory.js.map +0 -1
  206. package/dist/accessory/DoorbellAccessory.js.map +0 -1
  207. package/dist/accessory/ExtractionHoodAccessory.js.map +0 -1
  208. package/dist/accessory/FanAccessory.js.map +0 -1
  209. package/dist/accessory/GarageDoorAccessory.js.map +0 -1
  210. package/dist/accessory/HeaterAccessory.js.map +0 -1
  211. package/dist/accessory/HeaterAccessory_old.js.map +0 -1
  212. package/dist/accessory/HumanPresenceSensorAccessory.js.map +0 -1
  213. package/dist/accessory/HumidifierAccessory.js.map +0 -1
  214. package/dist/accessory/IRAirConditionerAccessory.js.map +0 -1
  215. package/dist/accessory/IRControlHubAccessory.js.map +0 -1
  216. package/dist/accessory/IRControlHubSubAccessory.js.map +0 -1
  217. package/dist/accessory/IRGenericAccessory.js.map +0 -1
  218. package/dist/accessory/LeakSensorAccessory.js.map +0 -1
  219. package/dist/accessory/LightAccessory.js.map +0 -1
  220. package/dist/accessory/LightSensorAccessory.js.map +0 -1
  221. package/dist/accessory/LocationWeatherAccessory.js.map +0 -1
  222. package/dist/accessory/LockAccessory.js.map +0 -1
  223. package/dist/accessory/MotionSensorAccessory.js.map +0 -1
  224. package/dist/accessory/OutletAccessory.js.map +0 -1
  225. package/dist/accessory/PetFeederAccessory.js.map +0 -1
  226. package/dist/accessory/SceneAccessory.js.map +0 -1
  227. package/dist/accessory/SceneSwitchAccessory.js.map +0 -1
  228. package/dist/accessory/SecuritySystemAccessory.js.map +0 -1
  229. package/dist/accessory/SmokeSensorAccessory.js.map +0 -1
  230. package/dist/accessory/SwitchAccessory.js +0 -85
  231. package/dist/accessory/SwitchAccessory.js.map +0 -1
  232. package/dist/accessory/TemperatureHumiditySensorAccessory.js.map +0 -1
  233. package/dist/accessory/ThermostatAccessory.js.map +0 -1
  234. package/dist/accessory/TowerRackAccessory.js.map +0 -1
  235. package/dist/accessory/ValveAccessory.js.map +0 -1
  236. package/dist/accessory/VibrationSensorAccessory.js.map +0 -1
  237. package/dist/accessory/WeatherStationAccessory.js.map +0 -1
  238. package/dist/accessory/WetBulbGlobeTemperatureAccessory.js.map +0 -1
  239. package/dist/accessory/WhiteNoiseLightAccessory.js.map +0 -1
  240. package/dist/accessory/WindowAccessory.js.map +0 -1
  241. package/dist/accessory/WindowCoveringAccessory.js.map +0 -1
  242. package/dist/accessory/WirelessSwitchAccessory.js.map +0 -1
  243. package/dist/accessory/characteristic/Active.js.map +0 -1
  244. package/dist/accessory/characteristic/AirQuality.js.map +0 -1
  245. package/dist/accessory/characteristic/CurrentRelativeHumidity.js.map +0 -1
  246. package/dist/accessory/characteristic/CurrentTemperature.js.map +0 -1
  247. package/dist/accessory/characteristic/CurrentWeather.js.map +0 -1
  248. package/dist/accessory/characteristic/CurrentWeatherByOpenMeteo.js.map +0 -1
  249. package/dist/accessory/characteristic/CurrentWetBulbGlobeTemperature.js.map +0 -1
  250. package/dist/accessory/characteristic/EnergyUsage.js.map +0 -1
  251. package/dist/accessory/characteristic/Light.js.map +0 -1
  252. package/dist/accessory/characteristic/LightSensor.js.map +0 -1
  253. package/dist/accessory/characteristic/LockPhysicalControls.js.map +0 -1
  254. package/dist/accessory/characteristic/MotionDetected.js.map +0 -1
  255. package/dist/accessory/characteristic/Name.js.map +0 -1
  256. package/dist/accessory/characteristic/OccupancyDetected.js.map +0 -1
  257. package/dist/accessory/characteristic/On.js.map +0 -1
  258. package/dist/accessory/characteristic/OutletInUse.js.map +0 -1
  259. package/dist/accessory/characteristic/ProgrammableSwitchEvent.js.map +0 -1
  260. package/dist/accessory/characteristic/RelativeHumidityDehumidifierThreshold.js.map +0 -1
  261. package/dist/accessory/characteristic/RotationSpeed.js.map +0 -1
  262. package/dist/accessory/characteristic/SecuritySystemState.js.map +0 -1
  263. package/dist/accessory/characteristic/SwingMode.js.map +0 -1
  264. package/dist/accessory/characteristic/TargetTemperature.js.map +0 -1
  265. package/dist/accessory/characteristic/TemperatureDisplayUnits.js.map +0 -1
  266. package/dist/core/TuyaOpenAPI.js.map +0 -1
  267. package/dist/core/TuyaOpenMQ.js.map +0 -1
  268. package/dist/device/TuyaCustomDeviceManager.js.map +0 -1
  269. package/dist/device/TuyaDevice.js.map +0 -1
  270. package/dist/device/TuyaDeviceManager.js.map +0 -1
  271. package/dist/device/TuyaHomeDeviceManager.js.map +0 -1
  272. package/dist/util/FfmpegStreamingProcess.js.map +0 -1
  273. package/dist/util/InfraredTool.js.map +0 -1
  274. package/dist/util/Logger.js.map +0 -1
  275. package/dist/util/TuyaRecordingDelegate.js.map +0 -1
  276. package/dist/util/TuyaStreamDelegate.js.map +0 -1
  277. package/dist/util/color.js.map +0 -1
  278. package/dist/util/util.js +0 -63
  279. package/dist/util/util.js.map +0 -1
  280. /package/dist/{device → cloud/device}/TuyaCustomDeviceManager.js +0 -0
  281. /package/dist/{device → cloud/device}/TuyaHomeDeviceManager.js +0 -0
  282. /package/dist/{accessory → shared/accessories}/AirConditionerAccessory.js +0 -0
  283. /package/dist/{accessory → shared/accessories}/AirQualitySensorAccessory.js +0 -0
  284. /package/dist/{accessory → shared/accessories}/CarbonDioxideSensorAccessory.js +0 -0
  285. /package/dist/{accessory → shared/accessories}/CarbonMonoxideSensorAccessory.js +0 -0
  286. /package/dist/{accessory → shared/accessories}/ContactSensorAccessory.js +0 -0
  287. /package/dist/{accessory → shared/accessories}/DehumidifierAccessory.js +0 -0
  288. /package/dist/{accessory → shared/accessories}/DiffuserAccessory.js +0 -0
  289. /package/dist/{accessory → shared/accessories}/DimmerAccessory.js +0 -0
  290. /package/dist/{accessory → shared/accessories}/GarageDoorAccessory.js +0 -0
  291. /package/dist/{accessory → shared/accessories}/HeaterAccessory.js +0 -0
  292. /package/dist/{accessory → shared/accessories}/HeaterAccessory_old.js +0 -0
  293. /package/dist/{accessory → shared/accessories}/HumanPresenceSensorAccessory.js +0 -0
  294. /package/dist/{accessory → shared/accessories}/IRControlHubAccessory.js +0 -0
  295. /package/dist/{accessory → shared/accessories}/IRControlHubSubAccessory.js +0 -0
  296. /package/dist/{accessory → shared/accessories}/IRGenericAccessory.js +0 -0
  297. /package/dist/{accessory → shared/accessories}/LeakSensorAccessory.js +0 -0
  298. /package/dist/{accessory → shared/accessories}/LightAccessory.js +0 -0
  299. /package/dist/{accessory → shared/accessories}/LightSensorAccessory.js +0 -0
  300. /package/dist/{accessory → shared/accessories}/LocationWeatherAccessory.js +0 -0
  301. /package/dist/{accessory → shared/accessories}/LockAccessory.js +0 -0
  302. /package/dist/{accessory → shared/accessories}/MotionSensorAccessory.js +0 -0
  303. /package/dist/{accessory → shared/accessories}/OutletAccessory.js +0 -0
  304. /package/dist/{accessory → shared/accessories}/PetFeederAccessory.js +0 -0
  305. /package/dist/{accessory → shared/accessories}/SceneAccessory.js +0 -0
  306. /package/dist/{accessory → shared/accessories}/SecuritySystemAccessory.js +0 -0
  307. /package/dist/{accessory → shared/accessories}/SmokeSensorAccessory.js +0 -0
  308. /package/dist/{accessory → shared/accessories}/TemperatureHumiditySensorAccessory.js +0 -0
  309. /package/dist/{accessory → shared/accessories}/ThermostatAccessory.js +0 -0
  310. /package/dist/{accessory → shared/accessories}/TowerRackAccessory.js +0 -0
  311. /package/dist/{accessory → shared/accessories}/WeatherStationAccessory.js +0 -0
  312. /package/dist/{accessory → shared/accessories}/WetBulbGlobeTemperatureAccessory.js +0 -0
  313. /package/dist/{accessory → shared/accessories}/WhiteNoiseLightAccessory.js +0 -0
  314. /package/dist/{accessory → shared/accessories}/WindowAccessory.js +0 -0
  315. /package/dist/{accessory → shared/accessories}/WindowCoveringAccessory.js +0 -0
  316. /package/dist/{accessory → shared/accessories}/WirelessSwitchAccessory.js +0 -0
  317. /package/dist/{accessory → shared/accessories}/characteristic/Active.js +0 -0
  318. /package/dist/{accessory → shared/accessories}/characteristic/CurrentRelativeHumidity.js +0 -0
  319. /package/dist/{accessory → shared/accessories}/characteristic/CurrentTemperature.js +0 -0
  320. /package/dist/{accessory → shared/accessories}/characteristic/CurrentWeather.js +0 -0
  321. /package/dist/{accessory → shared/accessories}/characteristic/CurrentWeatherByOpenMeteo.js +0 -0
  322. /package/dist/{accessory → shared/accessories}/characteristic/CurrentWetBulbGlobeTemperature.js +0 -0
  323. /package/dist/{accessory → shared/accessories}/characteristic/EnergyUsage.js +0 -0
  324. /package/dist/{accessory → shared/accessories}/characteristic/Light.js +0 -0
  325. /package/dist/{accessory → shared/accessories}/characteristic/LightSensor.js +0 -0
  326. /package/dist/{accessory → shared/accessories}/characteristic/LockPhysicalControls.js +0 -0
  327. /package/dist/{accessory → shared/accessories}/characteristic/Name.js +0 -0
  328. /package/dist/{accessory → shared/accessories}/characteristic/OccupancyDetected.js +0 -0
  329. /package/dist/{accessory → shared/accessories}/characteristic/OutletInUse.js +0 -0
  330. /package/dist/{accessory → shared/accessories}/characteristic/RelativeHumidityDehumidifierThreshold.js +0 -0
  331. /package/dist/{accessory → shared/accessories}/characteristic/RotationSpeed.js +0 -0
  332. /package/dist/{accessory → shared/accessories}/characteristic/SecuritySystemState.js +0 -0
  333. /package/dist/{accessory → shared/accessories}/characteristic/SwingMode.js +0 -0
  334. /package/dist/{accessory → shared/accessories}/characteristic/TargetTemperature.js +0 -0
  335. /package/dist/{accessory → shared/accessories}/characteristic/TemperatureDisplayUnits.js +0 -0
  336. /package/dist/{util → shared/util}/FfmpegStreamingProcess.js +0 -0
  337. /package/dist/{util → shared/util}/InfraredTool.js +0 -0
  338. /package/dist/{util → shared/util}/Logger.js +0 -0
  339. /package/dist/{util → shared/util}/TuyaRecordingDelegate.js +0 -0
  340. /package/dist/{util → shared/util}/TuyaStreamDelegate.js +0 -0
  341. /package/dist/{util → shared/util}/color.js +0 -0
@@ -0,0 +1,185 @@
1
+ import { beforeEach, describe, expect, jest, test } from '@jest/globals';
2
+ import LocalDeviceManager from '../src/local/LocalDeviceManager';
3
+ import type { LocalConfig } from '../src/local/config';
4
+
5
+ const createdConnections: any[] = [];
6
+
7
+ jest.mock('../src/local/LocalDevice', () => ({
8
+ __esModule: true,
9
+ default: class MockLocalDevice extends (require('events').EventEmitter) {
10
+ public update = jest.fn();
11
+ public connect = jest.fn();
12
+ public disconnect = jest.fn();
13
+ public context: any;
14
+
15
+ constructor(context: any) {
16
+ super();
17
+ this.context = context;
18
+ createdConnections.push(this);
19
+ }
20
+ },
21
+ }));
22
+
23
+ jest.mock('../src/local/TuyaDiscovery', () => ({
24
+ __esModule: true,
25
+ default: class MockTuyaDiscovery {
26
+ public on = jest.fn();
27
+ public start = jest.fn();
28
+ public stop = jest.fn();
29
+ },
30
+ }));
31
+
32
+ jest.mock('../src/shared/util/Logger', () => ({
33
+ __esModule: true,
34
+ default: class Logger {
35
+ log() {}
36
+ info() {}
37
+ warn() {}
38
+ error() {}
39
+ debug() {}
40
+ },
41
+ PrefixLogger: class PrefixLogger {
42
+ constructor(public parentLog: unknown, public name: string, public debugMode: boolean) {}
43
+ log() {}
44
+ info() {}
45
+ warn() {}
46
+ error() {}
47
+ debug() {}
48
+ },
49
+ }));
50
+
51
+ describe('LocalDeviceManager command and local mapping behavior', () => {
52
+ let log: any;
53
+
54
+ beforeEach(() => {
55
+ createdConnections.length = 0;
56
+ log = {
57
+ log: jest.fn(),
58
+ info: jest.fn(),
59
+ warn: jest.fn(),
60
+ error: jest.fn(),
61
+ debug: jest.fn(),
62
+ };
63
+ jest.clearAllMocks();
64
+ });
65
+
66
+ test('warns when auto-discovery is disabled and a device has no local key', async () => {
67
+ const config: LocalConfig = {
68
+ autoDiscoverDevices: false,
69
+ devices: [
70
+ {
71
+ tuyaDeviceId: 'dev-1',
72
+ ip: '192.168.1.10',
73
+ },
74
+ ],
75
+ };
76
+
77
+ const manager = new LocalDeviceManager(config, log);
78
+ await manager.initLocalDevices();
79
+
80
+ expect(manager.getDevice('dev-1')).toBeDefined();
81
+ expect(createdConnections).toHaveLength(0);
82
+ });
83
+
84
+ test('translates command codes to DPs using merged mapping and sends update', async () => {
85
+ const config: LocalConfig = {
86
+ autoDiscoverDevices: false,
87
+ devices: [
88
+ {
89
+ tuyaDeviceId: 'dev-1',
90
+ ip: '192.168.1.10',
91
+ tuyaKey: 'abcdef1234567890',
92
+ protocolVersion: '3.5',
93
+ dpMapping: {
94
+ switch_1: 7,
95
+ bright_value: 8,
96
+ },
97
+ },
98
+ ],
99
+ };
100
+
101
+ const manager = new LocalDeviceManager(config, log);
102
+ await manager.initLocalDevices();
103
+
104
+ const result = await manager.sendCommands('dev-1', [
105
+ { code: 'switch_1', value: true },
106
+ { code: 'bright_value', value: 42 },
107
+ { code: 'unknown_code', value: false },
108
+ ]);
109
+
110
+ expect(result).toBe(true);
111
+ expect(createdConnections).toHaveLength(1);
112
+ expect(createdConnections[0].update).toHaveBeenCalledWith({
113
+ '7': true,
114
+ '8': 42,
115
+ });
116
+ });
117
+
118
+ test('returns undefined and warns for unknown local device id', async () => {
119
+ const config: LocalConfig = {
120
+ autoDiscoverDevices: false,
121
+ devices: [],
122
+ };
123
+
124
+ const manager = new LocalDeviceManager(config, log);
125
+ await manager.initLocalDevices();
126
+
127
+ const result = await manager.sendCommands('missing-device', [{ code: 'switch_1', value: true }]);
128
+
129
+ expect(result).toBeUndefined();
130
+ });
131
+
132
+ test('updates existing configured device IP on discovery and disconnects stale connection', async () => {
133
+ const config: LocalConfig = {
134
+ autoDiscoverDevices: false,
135
+ devices: [
136
+ {
137
+ tuyaDeviceId: 'dev-1',
138
+ ip: '192.168.1.10',
139
+ tuyaKey: 'abcdef1234567890',
140
+ protocolVersion: '3.5',
141
+ },
142
+ ],
143
+ };
144
+
145
+ const manager = new LocalDeviceManager(config, log);
146
+ await manager.initLocalDevices();
147
+ manager.connectAllDevices();
148
+
149
+ expect(createdConnections).toHaveLength(1);
150
+
151
+ (manager as any)._onDiscovered({
152
+ id: 'dev-1',
153
+ ip: '192.168.1.22',
154
+ version: '3.5',
155
+ });
156
+
157
+ const device = manager.getDevice('dev-1');
158
+
159
+ expect(device?.ip).toBe('192.168.1.22');
160
+ expect(createdConnections[0].disconnect).toHaveBeenCalled();
161
+ });
162
+
163
+ test('creates placeholder device for discovered unknown IDs', async () => {
164
+ const config: LocalConfig = {
165
+ autoDiscoverDevices: false,
166
+ devices: [],
167
+ };
168
+
169
+ const manager = new LocalDeviceManager(config, log);
170
+ await manager.initLocalDevices();
171
+
172
+ (manager as any)._onDiscovered({
173
+ id: 'new-dev',
174
+ ip: '192.168.1.30',
175
+ version: '3.5',
176
+ productKey: 'prod1',
177
+ });
178
+
179
+ const discovered = manager.getDevice('new-dev');
180
+
181
+ expect(discovered).toBeDefined();
182
+ expect(discovered?.ip).toBe('192.168.1.30');
183
+ expect(discovered?.product_id).toBe('prod1');
184
+ });
185
+ });
@@ -0,0 +1,327 @@
1
+ /* eslint-disable no-console */
2
+ import { describe, expect, test, beforeEach, afterEach, jest } from '@jest/globals';
3
+ import LocalDeviceManager from '../src/local/LocalDeviceManager';
4
+ import { LocalConfig } from '../src/local/config';
5
+ import Logger from '../src/shared/util/Logger';
6
+ import TuyaDevice from '../src/cloud/device/TuyaDevice';
7
+
8
+ // Mock Logger
9
+ const mockLog: Logger = {
10
+ debug: jest.fn(),
11
+ info: jest.fn(),
12
+ warn: jest.fn(),
13
+ error: jest.fn(),
14
+ log: jest.fn(),
15
+ } as unknown as Logger;
16
+
17
+ describe('LocalDeviceManager', () => {
18
+ let manager: LocalDeviceManager;
19
+
20
+ beforeEach(() => {
21
+ const config: LocalConfig = {
22
+ devices: [],
23
+ };
24
+ manager = new LocalDeviceManager(config, mockLog);
25
+ });
26
+
27
+ afterEach(() => {
28
+ jest.clearAllMocks();
29
+ });
30
+
31
+ describe('initialization', () => {
32
+ test('creates manager instance with config', () => {
33
+ expect(manager).toBeDefined();
34
+ expect(manager).toBeInstanceOf(LocalDeviceManager);
35
+ });
36
+
37
+ test('initializes with empty devices', () => {
38
+ expect(manager.devices.length).toBe(0);
39
+ });
40
+
41
+ test('stops MQTT on initialization', () => {
42
+ // MQTT should be stopped during construction
43
+ expect(manager).toBeDefined();
44
+ });
45
+ });
46
+
47
+ describe('device management', () => {
48
+ test('can register a device', async () => {
49
+ const deviceId = 'test_device_1';
50
+ const deviceConfig = {
51
+ tuyaDeviceId: deviceId,
52
+ ip: '192.168.1.100',
53
+ tuyaKey: 'testlocalkey123456',
54
+ protocolVersion: '3.5',
55
+ };
56
+
57
+ await manager.initLocalDevices();
58
+
59
+ // After init, MQTT should be stopped
60
+ expect(manager).toBeDefined();
61
+ });
62
+
63
+ test('extends TuyaDeviceManager correctly', () => {
64
+ expect(manager).toBeInstanceOf(LocalDeviceManager);
65
+ // Should have inherited properties from TuyaDeviceManager
66
+ expect(manager.devices).toBeDefined();
67
+ expect(typeof manager.devices).toBe('object');
68
+ });
69
+ });
70
+
71
+ describe('configuration', () => {
72
+ test('accepts local config with empty devices', () => {
73
+ const config: LocalConfig = {
74
+ devices: [],
75
+ };
76
+ const mgr = new LocalDeviceManager(config, mockLog);
77
+ expect(mgr).toBeDefined();
78
+ });
79
+
80
+ test('accepts local config with device list', () => {
81
+ const config: LocalConfig = {
82
+ devices: [
83
+ {
84
+ tuyaDeviceId: 'device1',
85
+ ip: '192.168.1.1',
86
+ tuyaKey: 'key123',
87
+ protocolVersion: '3.5',
88
+ },
89
+ ],
90
+ };
91
+ const mgr = new LocalDeviceManager(config, mockLog);
92
+ expect(mgr).toBeDefined();
93
+ });
94
+
95
+ test('accepts local config with per-device DP mappings', () => {
96
+ const config: LocalConfig = {
97
+ devices: [
98
+ {
99
+ tuyaDeviceId: 'device1',
100
+ ip: '192.168.1.1',
101
+ tuyaKey: 'key123',
102
+ protocolVersion: '3.5',
103
+ dpMapping: {
104
+ switch_1: 1,
105
+ bright_value: 2,
106
+ temp_value: 3,
107
+ },
108
+ },
109
+ ],
110
+ };
111
+ const mgr = new LocalDeviceManager(config, mockLog);
112
+ expect(mgr).toBeDefined();
113
+ });
114
+ });
115
+
116
+ describe('device discovery', () => {
117
+ test('initLocalDevices completes without error', async () => {
118
+ const config: LocalConfig = {
119
+ devices: [],
120
+ };
121
+ const mgr = new LocalDeviceManager(config, mockLog);
122
+
123
+ // Should not throw
124
+ await expect(mgr.initLocalDevices()).resolves.not.toThrow();
125
+ });
126
+ });
127
+
128
+ describe('error handling', () => {
129
+ test('handles missing local key gracefully', () => {
130
+ const config: LocalConfig = {
131
+ devices: [
132
+ {
133
+ tuyaDeviceId: 'device1',
134
+ ip: '192.168.1.1',
135
+ // Missing tuyaKey
136
+ protocolVersion: '3.5',
137
+ } as any,
138
+ ],
139
+ };
140
+
141
+ // Should create manager without crashing
142
+ const mgr = new LocalDeviceManager(config, mockLog);
143
+ expect(mgr).toBeDefined();
144
+ });
145
+
146
+ test('falls back when local command has no response after 10 seconds', async () => {
147
+ jest.useFakeTimers();
148
+ const mgr = new LocalDeviceManager({ devices: [] }, mockLog);
149
+ mgr['dpMaps'].set('device1', { switch_1: 1 });
150
+ mgr['localDevices'].push(new TuyaDevice({ id: 'device1', uuid: 'device1', name: 'Device 1', schema: [], status: [] }));
151
+
152
+ const conn = new (require('events').EventEmitter)();
153
+ conn.connected = true;
154
+ conn.update = jest.fn();
155
+ mgr['localConnections'].set('device1', conn);
156
+
157
+ const sendPromise = mgr.sendCommands('device1', [{ code: 'switch_1', value: true }]);
158
+ jest.advanceTimersByTime(10000);
159
+
160
+ await expect(sendPromise).rejects.toThrow('Local command response timeout');
161
+ jest.useRealTimers();
162
+ });
163
+
164
+ test('cancels older pending local responses when newer command supersedes same DP', async () => {
165
+ jest.useFakeTimers();
166
+ const mgr = new LocalDeviceManager({ devices: [] }, mockLog);
167
+ mgr['dpMaps'].set('device1', { switch_1: 1 });
168
+ mgr['localDevices'].push(new TuyaDevice({ id: 'device1', uuid: 'device1', name: 'Device 1', schema: [], status: [] }));
169
+
170
+ const conn = new (require('events').EventEmitter)();
171
+ conn.connected = true;
172
+ conn.update = jest.fn();
173
+ mgr['localConnections'].set('device1', conn);
174
+
175
+ const firstSend = mgr.sendCommands('device1', [{ code: 'switch_1', value: true }]);
176
+ const secondSend = mgr.sendCommands('device1', [{ code: 'switch_1', value: false }]);
177
+
178
+ await expect(firstSend).resolves.toBe(true);
179
+ jest.advanceTimersByTime(10000);
180
+ await expect(secondSend).rejects.toThrow('Local command response timeout');
181
+ jest.useRealTimers();
182
+ });
183
+
184
+ test('handles invalid IP address gracefully', async () => {
185
+ const config: LocalConfig = {
186
+ devices: [
187
+ {
188
+ tuyaDeviceId: 'device1',
189
+ ip: 'invalid-ip',
190
+ tuyaKey: 'key123',
191
+ protocolVersion: '3.5',
192
+ },
193
+ ],
194
+ };
195
+ const mgr = new LocalDeviceManager(config, mockLog);
196
+
197
+ // Should not throw during init
198
+ await expect(mgr.initLocalDevices()).resolves.not.toThrow();
199
+ });
200
+
201
+ test('handles invalid protocol version gracefully', () => {
202
+ const config: LocalConfig = {
203
+ devices: [
204
+ {
205
+ tuyaDeviceId: 'device1',
206
+ ip: '192.168.1.1',
207
+ tuyaKey: 'key123',
208
+ protocolVersion: '9.9' as any, // Invalid version
209
+ },
210
+ ],
211
+ };
212
+
213
+ // Should create manager without immediate error
214
+ const mgr = new LocalDeviceManager(config, mockLog);
215
+ expect(mgr).toBeDefined();
216
+ });
217
+
218
+ test('skips invalid local config entries without tuyaDeviceId', () => {
219
+ const config: LocalConfig = {
220
+ devices: [
221
+ {
222
+ // Missing tuyaDeviceId should be rejected
223
+ ip: '192.168.1.1',
224
+ tuyaKey: 'key123',
225
+ protocolVersion: '3.5',
226
+ name: 'Invalid Device',
227
+ } as any,
228
+ ],
229
+ };
230
+ const mgr = new LocalDeviceManager(config, mockLog);
231
+ (mgr as any)._registerDeviceConfig(config.devices![0]);
232
+
233
+ expect(mgr.devices.length).toBe(0);
234
+ expect(mockLog.warn).toHaveBeenCalledWith(
235
+ '[LocalDeviceManager] Skipping invalid local config entry for Invalid Device: missing tuyaDeviceId',
236
+ );
237
+ });
238
+ });
239
+
240
+ describe('DP mapping', () => {
241
+ test('uses default DP mapping when not provided', () => {
242
+ const config: LocalConfig = {
243
+ devices: [],
244
+ };
245
+ const mgr = new LocalDeviceManager(config, mockLog);
246
+ expect(mgr).toBeDefined();
247
+ // Default mappings should be applied internally
248
+ });
249
+
250
+ test('respects custom DP mappings', () => {
251
+ const customMapping = {
252
+ switch_1: 10,
253
+ bright_value: 11,
254
+ color_data: 12,
255
+ };
256
+ const config: LocalConfig = {
257
+ devices: [
258
+ {
259
+ tuyaDeviceId: 'device1',
260
+ ip: '192.168.1.1',
261
+ tuyaKey: 'key123',
262
+ protocolVersion: '3.5',
263
+ dpMapping: customMapping,
264
+ },
265
+ ],
266
+ };
267
+ const mgr = new LocalDeviceManager(config, mockLog);
268
+ expect(mgr).toBeDefined();
269
+ });
270
+ });
271
+
272
+ describe('logging', () => {
273
+ test('uses provided logger', () => {
274
+ const customLog: Logger = {
275
+ debug: jest.fn(),
276
+ info: jest.fn(),
277
+ warn: jest.fn(),
278
+ error: jest.fn(),
279
+ log: jest.fn(),
280
+ } as unknown as Logger;
281
+
282
+ const config: LocalConfig = {
283
+ devices: [],
284
+ };
285
+ const mgr = new LocalDeviceManager(config, customLog);
286
+ expect(mgr).toBeDefined();
287
+ });
288
+ });
289
+ });
290
+
291
+ describe('LocalDeviceManager Integration', () => {
292
+ test('multiple managers can coexist', () => {
293
+ const config1: LocalConfig = {
294
+ devices: [],
295
+ };
296
+ const config2: LocalConfig = {
297
+ devices: [
298
+ {
299
+ tuyaDeviceId: 'device1',
300
+ ip: '192.168.1.1',
301
+ tuyaKey: 'key123',
302
+ protocolVersion: '3.5',
303
+ dpMapping: { switch_1: 1 },
304
+ },
305
+ ],
306
+ };
307
+
308
+ const mgr1 = new LocalDeviceManager(config1, mockLog);
309
+ const mgr2 = new LocalDeviceManager(config2, mockLog);
310
+
311
+ expect(mgr1).toBeDefined();
312
+ expect(mgr2).toBeDefined();
313
+ expect(mgr1).not.toBe(mgr2);
314
+ });
315
+
316
+ test('manager cleanup on multiple inits', async () => {
317
+ const config: LocalConfig = {
318
+ devices: [],
319
+ };
320
+ const mgr = new LocalDeviceManager(config, mockLog);
321
+
322
+ await mgr.initLocalDevices();
323
+ await mgr.initLocalDevices(); // Should handle multiple inits
324
+
325
+ expect(mgr).toBeDefined();
326
+ });
327
+ });