@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
@@ -5,6 +5,391 @@
5
5
  "headerDisplay": "<p align='center'><img height='60px' src='https://user-images.githubusercontent.com/3979615/78354049-dc7ff780-75f6-11ea-8026-2f8bf81d8331.png'></p>",
6
6
  "footerDisplay": "",
7
7
  "customUi": false,
8
+ "layout": [
9
+ {
10
+ "type": "radiobuttons",
11
+ "key": "mode",
12
+ "style": { "selected": "btn-secondary", "unselected": "btn-outline-secondary" }
13
+ },
14
+ {
15
+ "type": "fieldset",
16
+ "items": [
17
+ {
18
+ "type": "tabs",
19
+ "tabs": [
20
+ {
21
+ "type": "fieldset",
22
+ "title": "Local Settings",
23
+ "notitle": true,
24
+ "items": [
25
+ {
26
+ "type": "help",
27
+ "labelHtmlClass": "alert-link alert-warning",
28
+ "helpvalue": "⚠These settings are currently inactive because Cloud mode is enabled.",
29
+ "condition": { "functionBody": "return (model.mode === 'cloud')" }
30
+ },
31
+ "local.autoDiscoverDevices",
32
+ "local.discoverTimeout",
33
+ "local.rediscoverInterval",
34
+ {
35
+ "key": "local.devices",
36
+ "add": "Add Manual Device",
37
+ "title": "{{ 'Add New Device' }}",
38
+ "type": "tabarray",
39
+ "notitle": true,
40
+ "items": [
41
+ {
42
+ "type": "div",
43
+ "displayFlex": false,
44
+ "notitle": true,
45
+ "title": "{{ value.name || value.tuyaDeviceId || 'New Device' }}",
46
+ "items": [
47
+ "local.devices[].category",
48
+ "local.devices[].name",
49
+ "local.devices[].tuyaDeviceId",
50
+ "local.devices[].tuyaKey",
51
+ "local.devices[].ip",
52
+ "local.devices[].protocolVersion",
53
+ "local.devices[].dpMapping",
54
+ "local.devices[].outletCount",
55
+ {
56
+ "type": "help",
57
+ "labelHtmlClass": "alert-link alert-warning",
58
+ "helpvalue": "Set up the camera streaming in the Common Settings > RTSP Camera Settings.",
59
+ "condition": { "functionBody": "return (model.local?.devices?.[arrayIndices[0]].category === 'sp')" }
60
+ },
61
+ {
62
+ "type": "fieldset",
63
+ "items": [
64
+ "local.devices[].dpMapping.add_ele",
65
+ "local.devices[].dpMapping.air_quality",
66
+ "local.devices[].dpMapping.alarm_message",
67
+ "local.devices[].dpMapping.alarm_propel_switch",
68
+ "local.devices[].dpMapping.battery_percentage",
69
+ "local.devices[].dpMapping.bright_value",
70
+ "local.devices[].dpMapping.bright_value_v2",
71
+ "local.devices[].dpMapping.child_lock",
72
+ "local.devices[].dpMapping.co2_state",
73
+ "local.devices[].dpMapping.co2_value",
74
+ "local.devices[].dpMapping.co_status",
75
+ "local.devices[].dpMapping.co_value",
76
+ "local.devices[].dpMapping.colour_data",
77
+ "local.devices[].dpMapping.colour_data_v2",
78
+ "local.devices[].dpMapping.control",
79
+ "local.devices[].dpMapping.cur_current",
80
+ "local.devices[].dpMapping.cur_power",
81
+ "local.devices[].dpMapping.cur_voltage",
82
+ "local.devices[].dpMapping.dehumidify_set_value",
83
+ "local.devices[].dpMapping.doorbell_call",
84
+ "local.devices[].dpMapping.doorbell_pic",
85
+ "local.devices[].dpMapping.doorbell_ring_exist",
86
+ "local.devices[].dpMapping.doorbell_volume_value",
87
+ "local.devices[].dpMapping.doorcontact_state",
88
+ "local.devices[].dpMapping.fan_direction",
89
+ "local.devices[].dpMapping.fan_speed",
90
+ "local.devices[].dpMapping.fan_speed_enum",
91
+ "local.devices[].dpMapping.feed_report",
92
+ "local.devices[].dpMapping.feed_state",
93
+ "local.devices[].dpMapping.floodlight_lightness",
94
+ "local.devices[].dpMapping.floodlight_switch",
95
+ "local.devices[].dpMapping.gas_sensor_status",
96
+ "local.devices[].dpMapping.humidity_current",
97
+ "local.devices[].dpMapping.humidity_indoor",
98
+ "local.devices[].dpMapping.humidity_set",
99
+ "local.devices[].dpMapping.level",
100
+ "local.devices[].dpMapping.light",
101
+ "local.devices[].dpMapping.lock",
102
+ "local.devices[].dpMapping.lock_motor_state",
103
+ "local.devices[].dpMapping.manual_feed",
104
+ "local.devices[].dpMapping.master_mode",
105
+ "local.devices[].dpMapping.meal_plan",
106
+ "local.devices[].dpMapping.mode",
107
+ "local.devices[].dpMapping.motion_switch",
108
+ "local.devices[].dpMapping.movement_detect_pic",
109
+ "local.devices[].dpMapping.open_close",
110
+ "local.devices[].dpMapping.percent_control",
111
+ "local.devices[].dpMapping.percent_state",
112
+ "local.devices[].dpMapping.pir",
113
+ "local.devices[].dpMapping.pir_state",
114
+ "local.devices[].dpMapping.pm10_value",
115
+ "local.devices[].dpMapping.pm25",
116
+ "local.devices[].dpMapping.pm25_value",
117
+ "local.devices[].dpMapping.position",
118
+ "local.devices[].dpMapping.presence_state",
119
+ "local.devices[].dpMapping.quick_feed",
120
+ "local.devices[].dpMapping.shake",
121
+ "local.devices[].dpMapping.shock_state",
122
+ "local.devices[].dpMapping.slow_feed",
123
+ "local.devices[].dpMapping.smoke_sensor_status",
124
+ "local.devices[].dpMapping.sos_state",
125
+ "local.devices[].dpMapping.speed",
126
+ "local.devices[].dpMapping.swing",
127
+ "local.devices[].dpMapping.switch",
128
+ "local.devices[].dpMapping.switch_1",
129
+ "local.devices[].dpMapping.switch_fan",
130
+ "local.devices[].dpMapping.switch_horizontal",
131
+ "local.devices[].dpMapping.switch_inching",
132
+ "local.devices[].dpMapping.switch_led",
133
+ "local.devices[].dpMapping.switch_mode1",
134
+ "local.devices[].dpMapping.switch_music",
135
+ "local.devices[].dpMapping.switch_pir",
136
+ "local.devices[].dpMapping.switch_sound",
137
+ "local.devices[].dpMapping.switch_spray",
138
+ "local.devices[].dpMapping.temp_current",
139
+ "local.devices[].dpMapping.temp_indoor",
140
+ "local.devices[].dpMapping.temp_set",
141
+ "local.devices[].dpMapping.temp_unit_convert",
142
+ "local.devices[].dpMapping.temp_value",
143
+ "local.devices[].dpMapping.temp_value_v2",
144
+ "local.devices[].dpMapping.tvoc",
145
+ "local.devices[].dpMapping.va_humidity",
146
+ "local.devices[].dpMapping.va_temperature",
147
+ "local.devices[].dpMapping.voc_value",
148
+ "local.devices[].dpMapping.work_mode",
149
+ "local.devices[].dpMapping.work_state",
150
+ "local.devices[].dpMapping.work_status"
151
+ ]
152
+ },
153
+ {
154
+ "key": "local.devices[].dpMappingArray",
155
+ "type": "array",
156
+ "listItems": 3,
157
+ "items": [
158
+ {
159
+ "type": "div",
160
+ "displayFlex": true,
161
+ "flex-direction": "row",
162
+ "items": [
163
+ {
164
+ "key": "local.devices[].dpMappingArray[].dpCode",
165
+ "placeholder": "switch"
166
+ },
167
+ {
168
+ "key": "local.devices[].dpMappingArray[].dpID",
169
+ "placeholder": "1"
170
+ }
171
+ ]
172
+ }
173
+ ]
174
+ }
175
+ ]
176
+ }
177
+ ]
178
+ }
179
+ ]
180
+ },
181
+ {
182
+ "type": "fieldset",
183
+ "title": "Cloud Settings",
184
+ "notitle": true,
185
+ "items": [
186
+ {
187
+ "type": "help",
188
+ "labelHtmlClass": "alert-link alert-warning",
189
+ "helpvalue": "⚠These settings are currently inactive because Local mode is enabled.",
190
+ "condition": { "functionBody": "return (model.mode === 'local')" }
191
+ },
192
+ {
193
+ "type": "fieldset",
194
+ "title": "Tuya Cloud Account Info",
195
+ "expandable": true,
196
+ "expanded": true,
197
+ "items": [
198
+ "options.projectType",
199
+ "options.endpoint",
200
+ "options.accessId",
201
+ "options.accessKey",
202
+ "options.countryCode",
203
+ "options.username",
204
+ "options.password",
205
+ "options.appSchema"
206
+ ]
207
+ },
208
+ {
209
+ "type": "fieldset",
210
+ "title": "Tuya Home Settings",
211
+ "expandable": true,
212
+ "expanded": false,
213
+ "items": [
214
+ {
215
+ "key": "options.homeWhitelist",
216
+ "add": "Add Another Home ID",
217
+ "type": "tabarray",
218
+ "items": [
219
+ {
220
+ "type": "div",
221
+ "title": "{{ value }}",
222
+ "items": [ "options.homeWhitelist[]" ]
223
+ }
224
+ ]
225
+ }
226
+ ]
227
+ },
228
+ {
229
+ "type": "fieldset",
230
+ "title": "Advance Settings",
231
+ "expandable": true,
232
+ "expanded": false,
233
+ "items": [
234
+ "options.generateWeatherAccessory",
235
+ "options.weatherAPI",
236
+ "options.forceIPv4"
237
+ ]
238
+ }
239
+ ]
240
+ },
241
+ {
242
+ "type": "fieldset",
243
+ "title": "Common Settings",
244
+ "notitle": true,
245
+ "items": [
246
+ {
247
+ "type": "fieldset",
248
+ "title": "Tuya Device Settings",
249
+ "expandable": true,
250
+ "expanded": true,
251
+ "items": [
252
+ {
253
+ "key": "options.deviceOverrides",
254
+ "add": "Add Another Device Override",
255
+ "title": "{{ value.id || 'New Device Override' }}",
256
+ "type": "tabarray",
257
+ "default": [],
258
+ "items": [
259
+ {
260
+ "type": "div",
261
+ "items": [
262
+ "options.deviceOverrides[].id",
263
+ "options.deviceOverrides[].category",
264
+ "options.deviceOverrides[].unbridged",
265
+ "options.deviceOverrides[].adaptiveLighting",
266
+ "options.deviceOverrides[].configFor",
267
+ {
268
+ "key": "options.deviceOverrides[].schema",
269
+ "add": "Add New Schema",
270
+ "title": "{{ value.code }}",
271
+ "type": "tabarray",
272
+ "items": [
273
+ {
274
+ "type": "div",
275
+ "items": [
276
+ "options.deviceOverrides[].schema[].code",
277
+ "options.deviceOverrides[].schema[].newCode",
278
+ "options.deviceOverrides[].schema[].hidden",
279
+ "options.deviceOverrides[].schema[].type",
280
+ "options.deviceOverrides[].schema[].onGet",
281
+ "options.deviceOverrides[].schema[].onSet",
282
+ {
283
+ "key": "options.deviceOverrides[].schema[].property",
284
+ "items": [
285
+ "options.deviceOverrides[].schema[].property.min",
286
+ "options.deviceOverrides[].schema[].property.max",
287
+ "options.deviceOverrides[].schema[].property.scale",
288
+ "options.deviceOverrides[].schema[].property.step",
289
+ {
290
+ "key": "options.deviceOverrides[].schema[].property.range",
291
+ "add": "Add Range",
292
+ "title": "{{ value }}",
293
+ "type": "tabarray",
294
+ "items": [
295
+ {
296
+ "type": "div",
297
+ "items": [ "options.deviceOverrides[].schema[].property.range[]" ]
298
+ }
299
+ ]
300
+ }
301
+ ]
302
+ }
303
+ ]
304
+ }
305
+ ]
306
+ }
307
+ ]
308
+ }
309
+ ]
310
+ }
311
+ ]
312
+ },
313
+ {
314
+ "type": "fieldset",
315
+ "title": "Accessory Service Informations",
316
+ "expandable": true,
317
+ "expanded": false,
318
+ "notitle": false,
319
+ "items": [
320
+ {
321
+ "key": "options.serviceInformationOverrides",
322
+ "add": "Add Another Service Information Override",
323
+ "title": "{{ 'New Service Information Override' }}",
324
+ "type": "tabarray",
325
+ "default": [],
326
+ "items": [
327
+ {
328
+ "type": "div",
329
+ "title": "{{ value.configuredName || value.device_id }}",
330
+ "items": [
331
+ "options.serviceInformationOverrides[].device_id",
332
+ "options.serviceInformationOverrides[].index",
333
+ "options.serviceInformationOverrides[].manifacturer",
334
+ "options.serviceInformationOverrides[].model",
335
+ "options.serviceInformationOverrides[].firmwareRevision",
336
+ "options.serviceInformationOverrides[].configuredName"
337
+ ]
338
+ }
339
+ ]
340
+ }
341
+ ]
342
+ },
343
+ {
344
+ "type": "fieldset",
345
+ "title": "RTSP Camera Settings",
346
+ "expandable": true,
347
+ "expanded": false,
348
+ "notitle": false,
349
+ "items": [
350
+ {
351
+ "key": "cameras",
352
+ "add": "Add Camera",
353
+ "title": "{{ 'New Camera' }}",
354
+ "type": "tabarray",
355
+ "notitle": true,
356
+ "items": [
357
+ {
358
+ "type": "div",
359
+ "displayFlex": false,
360
+ "flex-direction": "row",
361
+ "notitle": true,
362
+ "title": "{{ value.deviceName }}",
363
+ "items": [
364
+ "cameras[].deviceId",
365
+ "cameras[].deviceName",
366
+ "cameras[].rtspUrl",
367
+ "cameras[].username",
368
+ "cameras[].password"
369
+ ]
370
+ }
371
+ ]
372
+ }
373
+ ]
374
+ },
375
+ {
376
+ "type": "fieldset",
377
+ "title": "Debug Settings",
378
+ "expandable": true,
379
+ "expanded": false,
380
+ "notitle": false,
381
+ "items": [
382
+ "common.debug",
383
+ "common.debugLevel"
384
+ ]
385
+ }
386
+ ]
387
+ }
388
+ ]
389
+ }
390
+ ]
391
+ }
392
+ ],
8
393
  "schema": {
9
394
  "type": "object",
10
395
  "required": ["mode"],
@@ -20,18 +405,15 @@
20
405
  "type": "string",
21
406
  "default": "cloud",
22
407
  "oneOf": [
23
- { "title": "Cloud (Tuya OpenAPI)", "enum": ["cloud"] },
24
408
  { "title": "Local (LAN / direct TCP)", "enum": ["local"] },
409
+ { "title": "Cloud (Tuya OpenAPI)", "enum": ["cloud"] },
25
410
  { "title": "Both (Cloud + Local)", "enum": ["both"] }
26
411
  ]
27
412
  },
28
413
  "local": {
29
414
  "title": "Local Settings",
30
- "description": "Configure local LAN devices. For help getting local keys, see the <a href='#' onClick='alert(\"Visit: wiki/Get-Local-Keys-for-Your-Devices.md\")'>Local Keys Setup Guide</a>.",
415
+ "description": "Configure local LAN devices. For help getting local keys, see the <a href='#' onClick='alert(\"Visit: docs/Get-Local-Keys-for-Your-Devices.md\")'>Local Keys Setup Guide</a>.",
31
416
  "type": "object",
32
- "condition": {
33
- "functionBody": "return (model.mode === 'local' || model.mode === 'both');"
34
- },
35
417
  "properties": {
36
418
  "autoDiscoverDevices": {
37
419
  "title": "Auto-Discover Devices",
@@ -62,6 +444,7 @@
62
444
  "default": [],
63
445
  "items": {
64
446
  "type": "object",
447
+ "required": ["category"],
65
448
  "properties": {
66
449
  "category": {
67
450
  "title": "Type",
@@ -76,27 +459,42 @@
76
459
  { "title": "Smart Outlet / Power Strip", "enum": ["cz"] },
77
460
  { "title": "Wireless Remote Switch", "enum": ["wxkg"] },
78
461
  { "title": "Scene Switch", "enum": ["cjkg"] },
462
+ { "title": "WhiteNoiseLight", "enum": ["bzyd"] },
79
463
  { "title": "Air Conditioner", "enum": ["kt"] },
80
464
  { "title": "Heater / Convector", "enum": ["qn"] },
81
465
  { "title": "Air Purifier", "enum": ["kj"] },
82
- { "title": "Humidifier / Diffuser", "enum": ["xxj"] },
466
+ { "title": "Diffuser", "enum": ["xxj"] },
83
467
  { "title": "Garage Door", "enum": ["ckmkzq"] },
84
- { "title": "Window Covering / Blind", "enum": ["cl"] },
85
- { "title": "Smart Lock", "enum": ["ms"] },
468
+ { "title": "Blind", "enum": ["mg"] },
469
+ { "title": "Window Covering", "enum": ["cl"] },
470
+ { "title": "Pet Feeder", "enum": ["cwwsq"] },
86
471
  { "title": "Window / Door Sensor", "enum": ["mc"] },
87
- { "title": "Contact Sensor", "enum": ["hj"] },
88
- { "title": "Leak Sensor", "enum": ["yc"] },
89
- { "title": "Motion Sensor", "enum": ["pir"] },
90
- { "title": "Smoke Sensor", "enum": ["yw"] },
91
- { "title": "Temperature/Humidity Sensor", "enum": ["wsdcz"] },
92
- { "title": "Light Sensor", "enum": ["gd"] },
93
- { "title": "Air Quality Sensor", "enum": ["kqbj"] },
94
472
  { "title": "Thermostat", "enum": ["wk"] },
95
473
  { "title": "Towel Rack / Warmer", "enum": ["mjj"] },
474
+ { "title": "Valve", "enum": ["ggq"] },
475
+ { "title": "Humidifier", "enum": ["jsq"] },
476
+ { "title": "Dehumidifier", "enum": ["cs"] },
96
477
  { "title": "Fan", "enum": ["fs"] },
97
- { "title": "Doorbell / Camera", "enum": ["mb"] },
98
- { "title": "Pet Feeder", "enum": ["cwwsq"] },
99
- { "title": "Security System", "enum": ["aq"] },
478
+ { "title": "ExtractionHood", "enum": ["yyj"] },
479
+ { "title": "Camera", "enum": ["sp"] },
480
+ { "title": "Smoke Sensor", "enum": ["ywbj"] },
481
+ { "title": "Contact Sensor", "enum": ["mcs"] },
482
+ { "title": "Vibration Sensor", "enum": ["zd"] },
483
+ { "title": "Leak Sensor", "enum": ["rqbj"] },
484
+ { "title": "CarbonMonoxide Sensor", "enum": ["cobj"] },
485
+ { "title": "CarbonDioxide Sensor", "enum": ["co2bj"] },
486
+ { "title": "Temperature/Humidity Sensor", "enum": ["wsdcg"] },
487
+ { "title": "Light Sensor", "enum": ["ldcg"] },
488
+ { "title": "Motion Sensor", "enum": ["pir"] },
489
+ { "title": "Air Quality Sensor", "enum": ["pm25"] },
490
+ { "title": "HumanPresence Sensor", "enum": ["hps"] },
491
+ { "title": "Smart Lock", "enum": ["ms"] },
492
+ { "title": "Security System", "enum": ["mal"] },
493
+ { "title": "Doorbell", "enum": ["wxml"] },
494
+ { "title": "WeatherStation", "enum": ["qxj"] },
495
+ { "title": "IRControlHub", "enum": ["wnykq"] },
496
+ { "title": "IRControlHubSub", "enum": ["qt"] },
497
+ { "title": "IRGeneric", "enum": ["infrared_"] },
100
498
  { "title": "Custom / Other", "enum": ["other"] }
101
499
  ]
102
500
  },
@@ -104,517 +502,737 @@
104
502
  "title": "Device ID",
105
503
  "description": "The Tuya device ID (same as the cloud device ID).",
106
504
  "type": "string",
107
- "condition": {
108
- "functionBody": "return model.local && model.local.devices && model.local.devices[arrayIndices[0]] && model.local.devices[arrayIndices[0]].category !== '';"
109
- }
505
+ "condition": { "functionBody": "return !!model.local?.devices?.[arrayIndices[0]]?.category;" }
110
506
  },
111
507
  "tuyaKey": {
112
508
  "title": "Local Key",
113
509
  "description": "The 16-character AES local key for direct communication.",
114
510
  "type": "string",
115
- "condition": {
116
- "functionBody": "return model.local && model.local.devices && model.local.devices[arrayIndices[0]] && model.local.devices[arrayIndices[0]].category !== '';"
117
- }
511
+ "condition": { "functionBody": "return !!model.local?.devices?.[arrayIndices[0]]?.category;" }
118
512
  },
119
513
  "ip": {
120
514
  "title": "IP Address",
121
515
  "description": "Fixed IP address. Leave blank to use auto-discovery.",
122
516
  "type": "string",
123
- "condition": {
124
- "functionBody": "return model.local && model.local.devices && model.local.devices[arrayIndices[0]] && model.local.devices[arrayIndices[0]].category !== '';"
125
- }
517
+ "condition": { "functionBody": "return !!model.local?.devices?.[arrayIndices[0]]?.category;" }
126
518
  },
127
519
  "name": {
128
520
  "title": "Name",
129
521
  "description": "Anything you'd like to use to identify this device.",
130
522
  "type": "string",
131
- "condition": {
132
- "functionBody": "return model.local && model.local.devices && model.local.devices[arrayIndices[0]] && model.local.devices[arrayIndices[0]].category !== '';"
133
- }
523
+ "condition": { "functionBody": "return !!model.local?.devices?.[arrayIndices[0]]?.category;" }
134
524
  },
135
525
  "protocolVersion": {
136
526
  "title": "Protocol Version",
137
527
  "description": "Tuya local protocol version. Leave blank to auto-detect.",
138
528
  "type": "string",
139
- "condition": {
140
- "functionBody": "return model.local && model.local.devices && model.local.devices[arrayIndices[0]] && model.local.devices[arrayIndices[0]].category !== '';"
141
- }
529
+ "condition": { "functionBody": "return !!model.local?.devices?.[arrayIndices[0]]?.category;" }
142
530
  },
143
- "dpMapping": {
531
+ "dpMappingArray": {
144
532
  "title": "Custom DP Mapping (Advanced)",
145
- "description": "Override default DP-to-function mappings as JSON. Example: {\"switch_1\": 1, \"bright_value\": 2, \"temp_value\": 3}",
146
- "type": "object",
147
- "additionalProperties": {
148
- "type": "integer"
149
- },
150
- "condition": {
151
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) && ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) !== '';"
152
- }
153
- },
154
- "outletCount": {
155
- "type": "integer",
156
- "title": "Outlet Count",
157
- "placeholder": 5,
158
- "condition": {
159
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz';"
160
- }
161
- },
162
- "isZigbeeGateway": {
163
- "title": "Zigbee Gateway",
164
- "description": "Mark this device as a Zigbee gateway. Usually auto-detected if other devices reference this device as their parent.",
165
- "type": "boolean",
166
- "default": false
167
- },
168
- "parentDeviceId": {
169
- "title": "Parent Gateway Device ID",
170
- "description": "For Zigbee sub-devices: the Tuya device ID of the parent gateway. Commands are routed through the parent's TCP connection using the Zigbee CID.",
171
- "type": "string"
172
- },
173
- "zigbeeChildId": {
174
- "title": "Zigbee Child ID (CID)",
175
- "description": "For Zigbee sub-devices: the 16-character hex node ID assigned by the gateway (e.g. '0011223344556601'). Required when parentDeviceId is set.",
176
- "type": "string",
177
- "pattern": "^[0-9a-fA-F]{16}$"
178
- },
179
- "childDpMapping": {
180
- "title": "Child DP Mapping (Override)",
181
- "description": "For Zigbee sub-devices: optional DP mapping override. If provided, replaces the parent's DP mapping for this child device. Useful when child DPs differ from the gateway.",
182
- "type": "object",
183
- "additionalProperties": {
184
- "type": "integer"
185
- },
186
- "condition": {
187
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].parentDeviceId : undefined) !== undefined && ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].parentDeviceId : undefined) !== '';"
188
- }
189
- },
190
- "childCategory": {
191
- "title": "Child Category Override",
192
- "description": "For Zigbee sub-devices: optional category override. If provided, replaces the parent's category for this child device. Useful when child is a different device type than the gateway.",
193
- "type": "string",
194
- "condition": {
195
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].parentDeviceId : undefined) !== undefined && ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].parentDeviceId : undefined) !== '';"
196
- }
197
- },
198
- "outlets": {
533
+ "description": "Override default DP-to-function mappings as JSON.",
199
534
  "type": "array",
200
- "title": "Outlets",
201
- "orderable": false,
202
535
  "items": {
203
536
  "type": "object",
537
+ "required": ["dpCode", "dpID"],
204
538
  "properties": {
205
- "name": {
206
- "type": "string"
539
+ "dpCode": {
540
+ "type": "string",
541
+ "title": "DP Code"
207
542
  },
208
- "dp": {
209
- "type": "integer"
543
+ "dpID": {
544
+ "type": "integer",
545
+ "title": "DP ID"
210
546
  }
211
547
  }
212
548
  },
213
549
  "condition": {
214
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz';"
215
- }
216
- },
217
- "dpPower": {
218
- "type": "integer",
219
- "title": "Power DP",
220
- "placeholder": 1,
221
- "condition": {
222
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg';"
223
- }
224
- },
225
- "dpBrightness": {
226
- "type": "integer",
227
- "title": "Brightness DP",
228
- "placeholder": 2,
229
- "condition": {
230
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
231
- }
232
- },
233
- "dpColorTemperature": {
234
- "type": "integer",
235
- "title": "Color Temperature DP",
236
- "placeholder": 3,
237
- "condition": {
238
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
239
- }
240
- },
241
- "minWhiteColor": {
242
- "type": "integer",
243
- "title": "Min White Color",
244
- "placeholder": 140,
245
- "condition": {
246
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg';"
247
- }
248
- },
249
- "maxWhiteColor": {
250
- "type": "integer",
251
- "title": "Max White Color",
252
- "placeholder": 400,
253
- "condition": {
254
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg';"
255
- }
256
- },
257
- "dpMode": {
258
- "type": "integer",
259
- "title": "Mode DP",
260
- "placeholder": 2,
261
- "condition": {
262
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg';"
263
- }
264
- },
265
- "dpColor": {
266
- "type": "integer",
267
- "title": "Color DP",
268
- "placeholder": 5,
269
- "condition": {
270
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg';"
271
- }
272
- },
273
- "colorFunction": {
274
- "type": "string",
275
- "title": "Color Function",
276
- "placeholder": "HEXHSB",
277
- "condition": {
278
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg';"
550
+ "functionBody": "return ['wnykq', 'qt', 'infrared_', 'other'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
279
551
  }
280
552
  },
281
- "scaleBrightness": {
282
- "type": "integer",
283
- "title": "Scale Brightness",
284
- "placeholder": 255,
285
- "condition": {
286
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
287
- }
288
- },
289
- "scaleWhiteColor": {
290
- "type": "integer",
291
- "title": "Scale White Color",
292
- "placeholder": 255,
293
- "condition": {
294
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dj' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'dsd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'xdd' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'tgkg';"
295
- }
296
- },
297
- "voltsId": {
298
- "type": "integer",
299
- "title": "Voltage DP",
300
- "placeholder": 9,
301
- "condition": {
302
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz';"
303
- }
304
- },
305
- "ampsId": {
306
- "type": "integer",
307
- "title": "Amperage DP",
308
- "placeholder": 8,
309
- "condition": {
310
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz';"
311
- }
312
- },
313
- "wattsId": {
314
- "type": "integer",
315
- "title": "Power DP",
316
- "placeholder": 7,
317
- "condition": {
318
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz';"
319
- }
320
- },
321
- "voltsDivisor": {
322
- "type": "integer",
323
- "title": "Voltage Divisor",
324
- "placeholder": 10,
325
- "condition": {
326
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz';"
327
- }
328
- },
329
- "ampsDivisor": {
330
- "type": "integer",
331
- "title": "Amperage Divisor",
332
- "placeholder": 1000,
333
- "condition": {
334
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz';"
335
- }
336
- },
337
- "wattsDivisor": {
338
- "type": "integer",
339
- "title": "Power Divisor",
340
- "placeholder": 10,
341
- "condition": {
342
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz';"
343
- }
344
- },
345
- "noCool": {
346
- "type": "boolean",
347
- "title": "No Cool Mode",
348
- "condition": {
349
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'kt' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ktkzq';"
350
- }
351
- },
352
- "noHeat": {
353
- "type": "boolean",
354
- "title": "No Heat Mode",
355
- "condition": {
356
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'kt' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ktkzq';"
357
- }
358
- },
359
- "cmdCool": {
360
- "type": "string",
361
- "title": "Cool Command",
362
- "placeholder": "COOL",
363
- "condition": {
364
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'kt' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ktkzq';"
365
- }
366
- },
367
- "cmdHeat": {
368
- "type": "string",
369
- "title": "Heat Command",
370
- "placeholder": "HEAT",
371
- "condition": {
372
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'kt' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ktkzq';"
373
- }
374
- },
375
- "noSwing": {
376
- "type": "boolean",
377
- "title": "No Swing Mode",
378
- "condition": {
379
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'kt' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ktkzq';"
380
- }
381
- },
382
- "minTemperature": {
383
- "type": "integer",
384
- "title": "Min Temperature",
385
- "placeholder": 15,
386
- "condition": {
387
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'kt' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ktkzq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
388
- }
389
- },
390
- "maxTemperature": {
391
- "type": "integer",
392
- "title": "Max Temperature",
393
- "placeholder": 40,
394
- "condition": {
395
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'kt' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ktkzq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
396
- }
397
- },
398
- "minTemperatureSteps": {
399
- "type": "integer",
400
- "title": "Min Temperature Steps",
401
- "placeholder": 1,
402
- "condition": {
403
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'kt' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ktkzq';"
404
- }
405
- },
406
- "dpActive": {
407
- "type": "integer",
408
- "title": "Active DP",
409
- "placeholder": 7,
410
- "condition": {
411
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
412
- }
413
- },
414
- "dpDesiredTemperature": {
415
- "type": "integer",
416
- "title": "Desired Temperature DP",
417
- "placeholder": 2,
418
- "condition": {
419
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
420
- }
421
- },
422
- "dpCurrentTemperature": {
423
- "type": "integer",
424
- "title": "Current Temperature DP",
425
- "placeholder": 3,
426
- "condition": {
427
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
428
- }
429
- },
430
- "dpAction": {
431
- "type": "integer",
432
- "title": "Action DP",
433
- "placeholder": 1,
434
- "condition": {
435
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ckmkzq';"
436
- }
437
- },
438
- "dpStatus": {
439
- "type": "integer",
440
- "title": "Status DP",
441
- "placeholder": 2,
442
- "condition": {
443
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ckmkzq';"
444
- }
445
- },
446
- "flipState": {
447
- "type": "boolean",
448
- "title": "Flip State",
449
- "condition": {
450
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'ckmkzq' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cl' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'clkg';"
451
- }
452
- },
453
- "timeToOpen": {
454
- "type": "integer",
455
- "title": "Time to Open (seconds)",
456
- "placeholder": 45,
457
- "condition": {
458
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cl' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'clkg';"
459
- }
460
- },
461
- "timeToTighten": {
462
- "type": "integer",
463
- "title": "Time to Tighten (seconds)",
464
- "placeholder": 0,
465
- "condition": {
466
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cl' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'clkg';"
467
- }
468
- },
469
- "timeToClose": {
470
- "type": "integer",
471
- "title": "Time to Close (seconds)",
472
- "placeholder": 30,
473
- "description": "Time in seconds for blinds to fully open or close",
474
- "condition": {
475
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cl' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'clkg';"
476
- }
477
- },
478
- "dpLight": {
479
- "type": "integer",
480
- "title": "Light DP",
481
- "placeholder": 1,
482
- "condition": {
483
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cz' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'pc' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'wkcz';"
484
- }
485
- },
486
- "dpBlindType": {
487
- "type": "integer",
488
- "title": "Blind Type DP",
489
- "placeholder": 1,
490
- "condition": {
491
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'cl' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'clkg';"
492
- }
493
- },
494
- "dpLightOn": {
495
- "type": "integer",
496
- "title": "Light On DP",
497
- "placeholder": 9,
498
- "condition": {
499
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
500
- }
501
- },
502
- "dpFanOn": {
503
- "type": "integer",
504
- "title": "Fan On DP",
505
- "placeholder": 1,
506
- "condition": {
507
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
508
- }
509
- },
510
- "dpRotationSpeed": {
511
- "type": "integer",
512
- "title": "Rotation Speed DP",
513
- "placeholder": 4,
514
- "condition": {
515
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn' || ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
516
- }
517
- },
518
- "dpRotationDirection": {
519
- "type": "integer",
520
- "title": "Rotation Direction DP",
521
- "placeholder": 63,
522
- "condition": {
523
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
524
- }
525
- },
526
- "maxSpeed": {
527
- "type": "integer",
528
- "title": "Max Speed",
529
- "placeholder": 3,
530
- "condition": {
531
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
553
+ "dpMapping": {
554
+ "title": "DP Mapping (Advanced)",
555
+ "description": "Override default DP-to-function mappings as JSON. Example: {\"switch_1\": 1, \"bright_value\": 2, \"temp_value\": 3}",
556
+ "type": "object",
557
+ "condition": { "functionBody": "return !['other', '', undefined].includes(model.local?.devices?.[arrayIndices[0]]?.category);" },
558
+ "properties": {
559
+ "add_ele": {
560
+ "type": "integer",
561
+ "title": "add_ele",
562
+ "condition": {
563
+ "functionBody": "return ['cz', 'dlq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
564
+ }
565
+ },
566
+ "air_quality": {
567
+ "type": "integer",
568
+ "title": "air_quality",
569
+ "condition": {
570
+ "functionBody": "return ['kj', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
571
+ }
572
+ },
573
+ "alarm_message": {
574
+ "type": "integer",
575
+ "title": "alarm_message",
576
+ "condition": {
577
+ "functionBody": "return ['sp', 'wxml'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
578
+ }
579
+ },
580
+ "alarm_propel_switch": {
581
+ "type": "integer",
582
+ "title": "alarm_propel_switch",
583
+ "condition": {
584
+ "functionBody": "return ['wxml'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
585
+ }
586
+ },
587
+ "battery_percentage": {
588
+ "type": "integer",
589
+ "title": "battery_percentage",
590
+ "condition": {
591
+ "functionBody": "return ['cwwsq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
592
+ }
593
+ },
594
+ "bright_value": {
595
+ "type": "integer",
596
+ "title": "bright_value",
597
+ "condition": {
598
+ "functionBody": "return ['dj', 'fs', 'jsq', 'ldcg', 'tgq', 'wnykq', 'xxj', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
599
+ }
600
+ },
601
+ "bright_value_v2": {
602
+ "type": "integer",
603
+ "title": "bright_value_v2",
604
+ "condition": {
605
+ "functionBody": "return ['dj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
606
+ }
607
+ },
608
+ "child_lock": {
609
+ "type": "integer",
610
+ "title": "child_lock",
611
+ "condition": {
612
+ "functionBody": "return ['cs', 'fs'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
613
+ }
614
+ },
615
+ "co2_state": {
616
+ "type": "integer",
617
+ "title": "co2_state",
618
+ "condition": {
619
+ "functionBody": "return ['co2bj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
620
+ }
621
+ },
622
+ "co2_value": {
623
+ "type": "integer",
624
+ "title": "co2_value",
625
+ "condition": {
626
+ "functionBody": "return ['co2bj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
627
+ }
628
+ },
629
+ "co_status": {
630
+ "type": "integer",
631
+ "title": "co_status",
632
+ "condition": {
633
+ "functionBody": "return ['cobj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
634
+ }
635
+ },
636
+ "co_value": {
637
+ "type": "integer",
638
+ "title": "co_value",
639
+ "condition": {
640
+ "functionBody": "return ['cobj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
641
+ }
642
+ },
643
+ "colour_data": {
644
+ "type": "integer",
645
+ "title": "colour_data",
646
+ "condition": {
647
+ "functionBody": "return ['bzyd', 'dj', 'fs', 'jsq', 'xxj', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
648
+ }
649
+ },
650
+ "colour_data_v2": {
651
+ "type": "integer",
652
+ "title": "colour_data_v2",
653
+ "condition": {
654
+ "functionBody": "return ['dj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
655
+ }
656
+ },
657
+ "control": {
658
+ "type": "integer",
659
+ "title": "control",
660
+ "condition": {
661
+ "functionBody": "return ['mg'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
662
+ }
663
+ },
664
+ "cur_current": {
665
+ "type": "integer",
666
+ "title": "cur_current",
667
+ "condition": {
668
+ "functionBody": "return ['cz', 'dlq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
669
+ }
670
+ },
671
+ "cur_power": {
672
+ "type": "integer",
673
+ "title": "cur_power",
674
+ "condition": {
675
+ "functionBody": "return ['cz', 'dlq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
676
+ }
677
+ },
678
+ "cur_voltage": {
679
+ "type": "integer",
680
+ "title": "cur_voltage",
681
+ "condition": {
682
+ "functionBody": "return ['cz', 'dlq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
683
+ }
684
+ },
685
+ "dehumidify_set_value": {
686
+ "type": "integer",
687
+ "title": "dehumidify_set_value",
688
+ "condition": {
689
+ "functionBody": "return ['cs'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
690
+ }
691
+ },
692
+ "doorbell_call": {
693
+ "type": "integer",
694
+ "title": "doorbell_call",
695
+ "condition": {
696
+ "functionBody": "return ['wxml'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
697
+ }
698
+ },
699
+ "doorbell_pic": {
700
+ "type": "integer",
701
+ "title": "doorbell_pic",
702
+ "condition": {
703
+ "functionBody": "return ['sp'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
704
+ }
705
+ },
706
+ "doorbell_ring_exist": {
707
+ "type": "integer",
708
+ "title": "doorbell_ring_exist",
709
+ "condition": {
710
+ "functionBody": "return ['sp'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
711
+ }
712
+ },
713
+ "doorbell_volume_value": {
714
+ "type": "integer",
715
+ "title": "doorbell_volume_value",
716
+ "condition": {
717
+ "functionBody": "return ['wxml'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
718
+ }
719
+ },
720
+ "doorcontact_state": {
721
+ "type": "integer",
722
+ "title": "doorcontact_state",
723
+ "condition": {
724
+ "functionBody": "return ['ckmkzq', 'mcs'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
725
+ }
726
+ },
727
+ "fan_direction": {
728
+ "type": "integer",
729
+ "title": "fan_direction",
730
+ "condition": {
731
+ "functionBody": "return ['fs'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
732
+ }
733
+ },
734
+ "fan_speed": {
735
+ "type": "integer",
736
+ "title": "fan_speed",
737
+ "condition": {
738
+ "functionBody": "return ['fs'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
739
+ }
740
+ },
741
+ "fan_speed_enum": {
742
+ "type": "integer",
743
+ "title": "fan_speed_enum",
744
+ "condition": {
745
+ "functionBody": "return ['cs', 'fs', 'kj', 'kt', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
746
+ }
747
+ },
748
+ "feed_report": {
749
+ "type": "integer",
750
+ "title": "feed_report",
751
+ "condition": {
752
+ "functionBody": "return ['cwwsq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
753
+ }
754
+ },
755
+ "feed_state": {
756
+ "type": "integer",
757
+ "title": "feed_state",
758
+ "condition": {
759
+ "functionBody": "return ['cwwsq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
760
+ }
761
+ },
762
+ "floodlight_lightness": {
763
+ "type": "integer",
764
+ "title": "floodlight_lightness",
765
+ "condition": {
766
+ "functionBody": "return ['sp'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
767
+ }
768
+ },
769
+ "floodlight_switch": {
770
+ "type": "integer",
771
+ "title": "floodlight_switch",
772
+ "condition": {
773
+ "functionBody": "return ['sp'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
774
+ }
775
+ },
776
+ "gas_sensor_status": {
777
+ "type": "integer",
778
+ "title": "gas_sensor_status",
779
+ "condition": {
780
+ "functionBody": "return ['rqbj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
781
+ }
782
+ },
783
+ "humidity_current": {
784
+ "type": "integer",
785
+ "title": "humidity_current",
786
+ "condition": {
787
+ "functionBody": "return ['jsq', 'kt'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
788
+ }
789
+ },
790
+ "humidity_indoor": {
791
+ "type": "integer",
792
+ "title": "humidity_indoor",
793
+ "condition": {
794
+ "functionBody": "return ['cs'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
795
+ }
796
+ },
797
+ "humidity_set": {
798
+ "type": "integer",
799
+ "title": "humidity_set",
800
+ "condition": {
801
+ "functionBody": "return ['jsq', 'kt'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
802
+ }
803
+ },
804
+ "level": {
805
+ "type": "integer",
806
+ "title": "level",
807
+ "condition": {
808
+ "functionBody": "return ['xxj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
809
+ }
810
+ },
811
+ "light": {
812
+ "type": "integer",
813
+ "title": "light",
814
+ "condition": {
815
+ "functionBody": "return ['cwwsq', 'fs', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
816
+ }
817
+ },
818
+ "lock": {
819
+ "type": "integer",
820
+ "title": "lock",
821
+ "condition": {
822
+ "functionBody": "return ['kj', 'kt', 'qn', 'qn_old', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
823
+ }
824
+ },
825
+ "lock_motor_state": {
826
+ "type": "integer",
827
+ "title": "lock_motor_state",
828
+ "condition": {
829
+ "functionBody": "return ['ms'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
830
+ }
831
+ },
832
+ "manual_feed": {
833
+ "type": "integer",
834
+ "title": "manual_feed",
835
+ "condition": {
836
+ "functionBody": "return ['cwwsq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
837
+ }
838
+ },
839
+ "master_mode": {
840
+ "type": "integer",
841
+ "title": "master_mode",
842
+ "condition": {
843
+ "functionBody": "return ['mal'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
844
+ }
845
+ },
846
+ "meal_plan": {
847
+ "type": "integer",
848
+ "title": "meal_plan",
849
+ "condition": {
850
+ "functionBody": "return ['cwwsq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
851
+ }
852
+ },
853
+ "mode": {
854
+ "type": "integer",
855
+ "title": "mode",
856
+ "condition": {
857
+ "functionBody": "return ['kj', 'kt', 'mjj', 'wk', 'xxj', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
858
+ }
859
+ },
860
+ "motion_switch": {
861
+ "type": "integer",
862
+ "title": "motion_switch",
863
+ "condition": {
864
+ "functionBody": "return ['sp'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
865
+ }
866
+ },
867
+ "movement_detect_pic": {
868
+ "type": "integer",
869
+ "title": "movement_detect_pic",
870
+ "condition": {
871
+ "functionBody": "return ['sp'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
872
+ }
873
+ },
874
+ "open_close": {
875
+ "type": "integer",
876
+ "title": "open_close",
877
+ "condition": {
878
+ "functionBody": "return ['ms'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
879
+ }
880
+ },
881
+ "percent_control": {
882
+ "type": "integer",
883
+ "title": "percent_control",
884
+ "condition": {
885
+ "functionBody": "return ['mg'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
886
+ }
887
+ },
888
+ "percent_state": {
889
+ "type": "integer",
890
+ "title": "percent_state",
891
+ "condition": {
892
+ "functionBody": "return ['mg'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
893
+ }
894
+ },
895
+ "pir": {
896
+ "type": "integer",
897
+ "title": "pir",
898
+ "condition": {
899
+ "functionBody": "return ['pir'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
900
+ }
901
+ },
902
+ "pir_state": {
903
+ "type": "integer",
904
+ "title": "pir_state",
905
+ "condition": {
906
+ "functionBody": "return ['dj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
907
+ }
908
+ },
909
+ "pm10_value": {
910
+ "type": "integer",
911
+ "title": "pm10_value",
912
+ "condition": {
913
+ "functionBody": "return ['pm25'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
914
+ }
915
+ },
916
+ "pm25": {
917
+ "type": "integer",
918
+ "title": "pm25",
919
+ "condition": {
920
+ "functionBody": "return ['kj', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
921
+ }
922
+ },
923
+ "pm25_value": {
924
+ "type": "integer",
925
+ "title": "pm25_value",
926
+ "condition": {
927
+ "functionBody": "return ['pm25'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
928
+ }
929
+ },
930
+ "position": {
931
+ "type": "integer",
932
+ "title": "position",
933
+ "condition": {
934
+ "functionBody": "return ['mg'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
935
+ }
936
+ },
937
+ "presence_state": {
938
+ "type": "integer",
939
+ "title": "presence_state",
940
+ "condition": {
941
+ "functionBody": "return ['hps'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
942
+ }
943
+ },
944
+ "quick_feed": {
945
+ "type": "integer",
946
+ "title": "quick_feed",
947
+ "condition": {
948
+ "functionBody": "return ['cwwsq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
949
+ }
950
+ },
951
+ "shake": {
952
+ "type": "integer",
953
+ "title": "shake",
954
+ "condition": {
955
+ "functionBody": "return ['qn', 'qn_old'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
956
+ }
957
+ },
958
+ "shock_state": {
959
+ "type": "integer",
960
+ "title": "shock_state",
961
+ "condition": {
962
+ "functionBody": "return ['zd'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
963
+ }
964
+ },
965
+ "slow_feed": {
966
+ "type": "integer",
967
+ "title": "slow_feed",
968
+ "condition": {
969
+ "functionBody": "return ['cwwsq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
970
+ }
971
+ },
972
+ "smoke_sensor_status": {
973
+ "type": "integer",
974
+ "title": "smoke_sensor_status",
975
+ "condition": {
976
+ "functionBody": "return ['ywbj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
977
+ }
978
+ },
979
+ "sos_state": {
980
+ "type": "integer",
981
+ "title": "sos_state",
982
+ "condition": {
983
+ "functionBody": "return ['mal'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
984
+ }
985
+ },
986
+ "speed": {
987
+ "type": "integer",
988
+ "title": "speed",
989
+ "condition": {
990
+ "functionBody": "return ['kj', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
991
+ }
992
+ },
993
+ "swing": {
994
+ "type": "integer",
995
+ "title": "swing",
996
+ "condition": {
997
+ "functionBody": "return ['cs'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
998
+ }
999
+ },
1000
+ "switch": {
1001
+ "type": "integer",
1002
+ "title": "switch",
1003
+ "condition": {
1004
+ "functionBody": "return ['cs', 'cwwsq', 'cz', 'dj', 'dlq', 'ggq', 'jsq', 'kj', 'kt', 'mjj', 'qn', 'qn_old', 'tgq', 'wk', 'xxj', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1005
+ }
1006
+ },
1007
+ "switch_1": {
1008
+ "type": "integer",
1009
+ "title": "switch_1",
1010
+ "condition": {
1011
+ "functionBody": "return ['ckmkzq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1012
+ }
1013
+ },
1014
+ "switch_fan": {
1015
+ "type": "integer",
1016
+ "title": "switch_fan",
1017
+ "condition": {
1018
+ "functionBody": "return ['fs'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1019
+ }
1020
+ },
1021
+ "switch_horizontal": {
1022
+ "type": "integer",
1023
+ "title": "switch_horizontal",
1024
+ "condition": {
1025
+ "functionBody": "return ['fs', 'kt'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1026
+ }
1027
+ },
1028
+ "switch_inching": {
1029
+ "type": "integer",
1030
+ "title": "switch_inching",
1031
+ "condition": {
1032
+ "functionBody": "return ['cz', 'dlq'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1033
+ }
1034
+ },
1035
+ "switch_led": {
1036
+ "type": "integer",
1037
+ "title": "switch_led",
1038
+ "condition": {
1039
+ "functionBody": "return ['bzyd', 'dj', 'jsq', 'xxj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1040
+ }
1041
+ },
1042
+ "switch_mode1": {
1043
+ "type": "integer",
1044
+ "title": "switch_mode1",
1045
+ "condition": {
1046
+ "functionBody": "return ['wxkg'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1047
+ }
1048
+ },
1049
+ "switch_music": {
1050
+ "type": "integer",
1051
+ "title": "switch_music",
1052
+ "condition": {
1053
+ "functionBody": "return ['bzyd'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1054
+ }
1055
+ },
1056
+ "switch_pir": {
1057
+ "type": "integer",
1058
+ "title": "switch_pir",
1059
+ "condition": {
1060
+ "functionBody": "return ['dj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1061
+ }
1062
+ },
1063
+ "switch_sound": {
1064
+ "type": "integer",
1065
+ "title": "switch_sound",
1066
+ "condition": {
1067
+ "functionBody": "return ['xxj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1068
+ }
1069
+ },
1070
+ "switch_spray": {
1071
+ "type": "integer",
1072
+ "title": "switch_spray",
1073
+ "condition": {
1074
+ "functionBody": "return ['xxj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1075
+ }
1076
+ },
1077
+ "temp_current": {
1078
+ "type": "integer",
1079
+ "title": "temp_current",
1080
+ "condition": {
1081
+ "functionBody": "return ['jsq', 'kt', 'mjj', 'qn', 'qn_old', 'wk'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1082
+ }
1083
+ },
1084
+ "temp_indoor": {
1085
+ "type": "integer",
1086
+ "title": "temp_indoor",
1087
+ "condition": {
1088
+ "functionBody": "return ['cs'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1089
+ }
1090
+ },
1091
+ "temp_set": {
1092
+ "type": "integer",
1093
+ "title": "temp_set",
1094
+ "condition": {
1095
+ "functionBody": "return ['kt', 'mjj', 'qn', 'qn_old', 'wk'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1096
+ }
1097
+ },
1098
+ "temp_unit_convert": {
1099
+ "type": "integer",
1100
+ "title": "temp_unit_convert",
1101
+ "condition": {
1102
+ "functionBody": "return ['kt', 'mjj', 'qn', 'qn_old', 'wk'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1103
+ }
1104
+ },
1105
+ "temp_value": {
1106
+ "type": "integer",
1107
+ "title": "temp_value",
1108
+ "condition": {
1109
+ "functionBody": "return ['dj', 'fs', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1110
+ }
1111
+ },
1112
+ "temp_value_v2": {
1113
+ "type": "integer",
1114
+ "title": "temp_value_v2",
1115
+ "condition": {
1116
+ "functionBody": "return ['dj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1117
+ }
1118
+ },
1119
+ "tvoc": {
1120
+ "type": "integer",
1121
+ "title": "tvoc",
1122
+ "condition": {
1123
+ "functionBody": "return ['kj', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1124
+ }
1125
+ },
1126
+ "va_humidity": {
1127
+ "type": "integer",
1128
+ "title": "va_humidity",
1129
+ "condition": {
1130
+ "functionBody": "return ['cz', 'dlq', 'pm25', 'wnykq', 'wsdcg'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1131
+ }
1132
+ },
1133
+ "va_temperature": {
1134
+ "type": "integer",
1135
+ "title": "va_temperature",
1136
+ "condition": {
1137
+ "functionBody": "return ['cz', 'dlq', 'pm25', 'wnykq', 'wsdcg'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1138
+ }
1139
+ },
1140
+ "voc_value": {
1141
+ "type": "integer",
1142
+ "title": "voc_value",
1143
+ "condition": {
1144
+ "functionBody": "return ['pm25'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1145
+ }
1146
+ },
1147
+ "work_mode": {
1148
+ "type": "integer",
1149
+ "title": "work_mode",
1150
+ "condition": {
1151
+ "functionBody": "return ['dj', 'fs', 'jsq', 'xxj', 'yyj'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1152
+ }
1153
+ },
1154
+ "work_state": {
1155
+ "type": "integer",
1156
+ "title": "work_state",
1157
+ "condition": {
1158
+ "functionBody": "return ['mjj', 'qn', 'qn_old', 'wk'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1159
+ }
1160
+ },
1161
+ "work_status": {
1162
+ "type": "integer",
1163
+ "title": "work_status",
1164
+ "condition": {
1165
+ "functionBody": "return ['kt'].includes(model.local?.devices?.[arrayIndices[0]]?.category);"
1166
+ }
1167
+ }
532
1168
  }
533
1169
  },
534
- "fanDefaultSpeed": {
1170
+ "outletCount": {
535
1171
  "type": "integer",
536
- "title": "Fan Default Speed",
537
- "placeholder": 1,
538
- "condition": {
539
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
540
- }
1172
+ "title": "Outlet Count",
1173
+ "placeholder": 5,
1174
+ "condition": { "functionBody": "return ['cz', 'pc', 'wkcz'].includes(model.local?.devices?.[arrayIndices[0]]?.category);" }
541
1175
  },
542
- "useStrings": {
1176
+ "isZigbeeGateway": {
1177
+ "title": "Zigbee Gateway",
1178
+ "description": "Mark this device as a Zigbee gateway. Usually auto-detected if other devices reference this device as their parent.",
543
1179
  "type": "boolean",
544
- "title": "Use Strings",
545
- "placeholder": true,
546
- "condition": {
547
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'fs';"
548
- }
549
- },
550
- "dpChildLock": {
551
- "type": "integer",
552
- "title": "Child Lock DP",
553
- "placeholder": 6,
554
- "condition": {
555
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
556
- }
557
- },
558
- "dpTemperatureDisplayUnits": {
559
- "type": "integer",
560
- "title": "Temperature Display Units DP",
561
- "placeholder": 19,
562
- "condition": {
563
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
564
- }
1180
+ "default": false
565
1181
  },
566
- "cmdLow": {
567
- "type": "string",
568
- "title": "Low Command",
569
- "placeholder": "Low",
570
- "condition": {
571
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
572
- }
1182
+ "parentDeviceId": {
1183
+ "title": "Parent Gateway Device ID",
1184
+ "description": "For Zigbee sub-devices: the Tuya device ID of the parent gateway. Commands are routed through the parent's TCP connection using the Zigbee CID.",
1185
+ "type": "string"
573
1186
  },
574
- "cmdHigh": {
1187
+ "zigbeeChildId": {
1188
+ "title": "Zigbee Child ID (CID)",
1189
+ "description": "For Zigbee sub-devices: the 16-character hex node ID assigned by the gateway (e.g. '0011223344556601'). Required when parentDeviceId is set.",
575
1190
  "type": "string",
576
- "title": "High Command",
577
- "placeholder": "High",
578
- "condition": {
579
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
580
- }
581
- },
582
- "noChildLock": {
583
- "type": "boolean",
584
- "title": "No Child Lock",
585
- "condition": {
586
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
587
- }
588
- },
589
- "noTemperatureUnit": {
590
- "type": "boolean",
591
- "title": "No Temperature Unit",
592
- "condition": {
593
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
594
- }
1191
+ "pattern": "^[0-9a-fA-F]{16}$"
595
1192
  },
596
- "temperatureDivisor": {
597
- "type": "integer",
598
- "title": "Temperature Divisor",
599
- "placeholder": 1,
1193
+ "childDpMapping": {
1194
+ "title": "Child DP Mapping (Override)",
1195
+ "description": "For Zigbee sub-devices: optional DP mapping override. If provided, replaces the parent's DP mapping for this child device. Useful when child DPs differ from the gateway.",
1196
+ "type": "object",
1197
+ "additionalProperties": {
1198
+ "type": "integer"
1199
+ },
600
1200
  "condition": {
601
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
1201
+ "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].parentDeviceId : undefined) !== undefined && ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].parentDeviceId : undefined) !== '';"
602
1202
  }
603
1203
  },
604
- "thresholdTemperatureDivisor": {
605
- "type": "integer",
606
- "title": "Threshold Temperature Divisor",
607
- "placeholder": 1,
1204
+ "childCategory": {
1205
+ "title": "Child Category Override",
1206
+ "description": "For Zigbee sub-devices: optional category override. If provided, replaces the parent's category for this child device. Useful when child is a different device type than the gateway.",
1207
+ "type": "string",
608
1208
  "condition": {
609
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
1209
+ "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].parentDeviceId : undefined) !== undefined && ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].parentDeviceId : undefined) !== '';"
610
1210
  }
611
1211
  },
612
- "temperatureOffset": {
613
- "type": "integer",
614
- "title": "Temperature Offset",
615
- "placeholder": 0,
616
- "condition": {
617
- "functionBody": "return ((model.local && model.local.devices && model.local.devices[arrayIndices[0]]) ? model.local.devices[arrayIndices[0]].category : undefined) === 'qn';"
1212
+ "remote_keys": {
1213
+ "title": "IR Keys",
1214
+ "description": "",
1215
+ "type": "object",
1216
+ "condition": { "functionBody": "return !['other', '', undefined].includes(model.local?.devices?.[arrayIndices[0]]?.category);" },
1217
+ "properties": {
1218
+ "key_list": {
1219
+ "title": "IR Learning Code",
1220
+ "type": "array",
1221
+ "items": {
1222
+ "type": "object",
1223
+ "required": ["id"],
1224
+ "properties": {
1225
+ "key_name": {
1226
+ "title": "Display Name",
1227
+ "type": "string"
1228
+ },
1229
+ "learning_code": {
1230
+ "title": "Learning Code",
1231
+ "type": "string"
1232
+ }
1233
+ }
1234
+ }
1235
+ }
618
1236
  }
619
1237
  }
620
1238
  }
@@ -625,48 +1243,26 @@
625
1243
  "options": {
626
1244
  "title": "Cloud Account Info",
627
1245
  "type": "object",
628
- "condition": {
629
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
630
- },
631
1246
  "properties": {
632
1247
  "projectType": {
633
1248
  "title": "Project Type (Development Method)",
634
1249
  "description": "Required for Cloud mode.",
635
1250
  "type": "string",
636
1251
  "default": "2",
637
- "condition": {
638
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
639
- },
640
1252
  "oneOf": [
641
- {
642
- "title": "Custom",
643
- "enum": [
644
- "1"
645
- ]
646
- },
647
- {
648
- "title": "Smart Home",
649
- "enum": [
650
- "2"
651
- ]
652
- }
1253
+ { "title": "Custom", "enum": [ "1" ] },
1254
+ { "title": "Smart Home", "enum": [ "2" ] }
653
1255
  ]
654
1256
  },
655
1257
  "endpoint": {
656
1258
  "title": "Endpoint URL",
657
1259
  "type": "string",
658
- "format": "url",
659
- "condition": {
660
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
661
- }
1260
+ "format": "url"
662
1261
  },
663
1262
  "accessId": {
664
1263
  "title": "Access ID",
665
1264
  "description": "Required for Cloud mode.",
666
- "type": "string",
667
- "condition": {
668
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
669
- }
1265
+ "type": "string"
670
1266
  },
671
1267
  "accessKey": {
672
1268
  "description": "Required for Cloud mode.",
@@ -674,9 +1270,6 @@
674
1270
  "type": "string",
675
1271
  "x-schema-form": {
676
1272
  "type": "password"
677
- },
678
- "condition": {
679
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
680
1273
  }
681
1274
  },
682
1275
  "countryCode": {
@@ -934,18 +1527,8 @@
934
1527
  "type": "string",
935
1528
  "default": "tuyaSmart",
936
1529
  "oneOf": [
937
- {
938
- "title": "Tuya Smart",
939
- "enum": [
940
- "tuyaSmart"
941
- ]
942
- },
943
- {
944
- "title": "Smart Life",
945
- "enum": [
946
- "smartlife"
947
- ]
948
- }
1530
+ { "title": "Tuya Smart", "enum": [ "tuyaSmart" ] },
1531
+ { "title": "Smart Life", "enum": [ "smartlife" ] }
949
1532
  ],
950
1533
  "condition": {
951
1534
  "functionBody": "return model.options.projectType === '2';"
@@ -966,9 +1549,6 @@
966
1549
  "deviceOverrides": {
967
1550
  "title": "Device Overriding Configs",
968
1551
  "type": "array",
969
- "condition": {
970
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
971
- },
972
1552
  "items": {
973
1553
  "type": "object",
974
1554
  "required": ["id"],
@@ -983,7 +1563,7 @@
983
1563
  "description": "Category Code or `hidden`",
984
1564
  "type": "string",
985
1565
  "condition": {
986
- "functionBody": "return (model.options && model.options.deviceOverrides);"
1566
+ "functionBody": "return (model.options?.deviceOverrides);"
987
1567
  }
988
1568
  },
989
1569
  "unbridged": {
@@ -991,7 +1571,35 @@
991
1571
  "description": "Would you like to make this device be an external device?",
992
1572
  "type": "boolean",
993
1573
  "condition": {
994
- "functionBody": "return (model.options && model.options.deviceOverrides);"
1574
+ "functionBody": "return (model.options?.deviceOverrides);"
1575
+ }
1576
+ },
1577
+ "adaptiveLighting": {
1578
+ "title": "Adaptive Lighting",
1579
+ "description": "Enable if your device supports intelligently adjusting the brightness and color of your lights",
1580
+ "type": "boolean",
1581
+ "condition": {
1582
+ "functionBody": "return (['bzyd', 'cwwsq', 'dj', 'dsd', 'xdd', 'fwd', 'dc', 'dd', 'gyd', 'tyndj', 'sxd', 'jsq', 'fs', 'fsd', 'fskg', 'yyj', 'xxj', 'sp'].includes(model?.options?.deviceOverrides?.[arrayIndices[0]]?.category));"
1583
+ }
1584
+ },
1585
+ "configFor": {
1586
+ "title": "When to apply the configuration",
1587
+ "description": "Whether the setting is for devices on Cloud, devices on Local, or used by both.",
1588
+ "type": "string",
1589
+ "required": true,
1590
+ "default": "cloud",
1591
+ "oneOf": [
1592
+ { "title": "Cloud", "enum": [ "cloud" ] },
1593
+ { "title": "Local", "enum": [ "local" ] },
1594
+ { "title": "Both", "enum": [ "both" ] }
1595
+ ]
1596
+ },
1597
+ "garageDoorUseContactSensorForState": {
1598
+ "title": "Use Contact Sensor For Garage Door State",
1599
+ "description": "For garage door controllers only. Derive CurrentDoorState and TargetDoorState reads from doorcontact_state instead of switch_1.",
1600
+ "type": "boolean",
1601
+ "condition": {
1602
+ "functionBody": "return (model.options?.deviceOverrides);"
995
1603
  }
996
1604
  },
997
1605
  "schema": {
@@ -1005,14 +1613,14 @@
1005
1613
  "title": "DP Code",
1006
1614
  "type": "string",
1007
1615
  "condition": {
1008
- "functionBody": "return (model.options && model.options.deviceOverrides);"
1616
+ "functionBody": "return (model.options?.deviceOverrides);"
1009
1617
  }
1010
1618
  },
1011
1619
  "newCode": {
1012
1620
  "title": "New DP Code",
1013
1621
  "type": "string",
1014
1622
  "condition": {
1015
- "functionBody": "return (model.options && model.options.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].code && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1623
+ "functionBody": "return (model.options?.deviceOverrides?.[arrayIndices[0]]?.schema?.[arrayIndices[1]]?.code && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1016
1624
  }
1017
1625
  },
1018
1626
  "type": {
@@ -1020,45 +1628,15 @@
1020
1628
  "type": "string",
1021
1629
  "default": "",
1022
1630
  "oneOf": [
1023
- {
1024
- "title": "Boolean",
1025
- "enum": [
1026
- "Boolean"
1027
- ]
1028
- },
1029
- {
1030
- "title": "Integer",
1031
- "enum": [
1032
- "Integer"
1033
- ]
1034
- },
1035
- {
1036
- "title": "Enum",
1037
- "enum": [
1038
- "Enum"
1039
- ]
1040
- },
1041
- {
1042
- "title": "String",
1043
- "enum": [
1044
- "String"
1045
- ]
1046
- },
1047
- {
1048
- "title": "Json",
1049
- "enum": [
1050
- "Json"
1051
- ]
1052
- },
1053
- {
1054
- "title": "Raw",
1055
- "enum": [
1056
- "Raw"
1057
- ]
1058
- }
1631
+ { "title": "Boolean", "enum": [ "Boolean" ] },
1632
+ { "title": "Integer", "enum": [ "Integer" ] },
1633
+ { "title": "Enum", "enum": [ "Enum" ] },
1634
+ { "title": "String", "enum": [ "String" ] },
1635
+ { "title": "Json", "enum": [ "Json" ] },
1636
+ { "title": "Raw", "enum": [ "Raw" ] }
1059
1637
  ],
1060
1638
  "condition": {
1061
- "functionBody": "return (model.options && model.options.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].code && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1639
+ "functionBody": "return (model.options?.deviceOverrides?.[arrayIndices[0]]?.schema?.[arrayIndices[1]]?.code && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1062
1640
  }
1063
1641
  },
1064
1642
  "property": {
@@ -1069,28 +1647,28 @@
1069
1647
  "title": "min",
1070
1648
  "type": "integer",
1071
1649
  "condition": {
1072
- "functionBody": "return (model.options && model.options.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Integer' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1650
+ "functionBody": "return (model.options?.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Integer' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1073
1651
  }
1074
1652
  },
1075
1653
  "max": {
1076
1654
  "title": "max",
1077
1655
  "type": "integer",
1078
1656
  "condition": {
1079
- "functionBody": "return (model.options && model.options.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Integer' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1657
+ "functionBody": "return (model.options?.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Integer' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1080
1658
  }
1081
1659
  },
1082
1660
  "scale": {
1083
1661
  "title": "scale",
1084
1662
  "type": "integer",
1085
1663
  "condition": {
1086
- "functionBody": "return (model.options && model.options.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Integer' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1664
+ "functionBody": "return (model.options?.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Integer' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1087
1665
  }
1088
1666
  },
1089
1667
  "step": {
1090
1668
  "title": "step",
1091
1669
  "type": "integer",
1092
1670
  "condition": {
1093
- "functionBody": "return (model.options && model.options.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Integer' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1671
+ "functionBody": "return (model.options?.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Integer' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1094
1672
  }
1095
1673
  },
1096
1674
  "range": {
@@ -1101,25 +1679,43 @@
1101
1679
  "type": "string"
1102
1680
  },
1103
1681
  "condition": {
1104
- "functionBody": "return (model.options && model.options.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Enum' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1682
+ "functionBody": "return (model.options?.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].type === 'Enum' && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1105
1683
  }
1106
1684
  }
1107
1685
  },
1108
1686
  "condition": {
1109
- "functionBody": "return (model.options && model.options.deviceOverrides && model.options.deviceOverrides[arrayIndices[0]].schema && model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].code && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1687
+ "functionBody": "return (model.options?.deviceOverrides?.[arrayIndices[0]]?.schema?.[arrayIndices[1]]?.code && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1110
1688
  }
1111
1689
  },
1112
1690
  "hidden": {
1113
1691
  "title": "Hidden",
1114
1692
  "type": "boolean",
1115
1693
  "condition": {
1116
- "functionBody": "return (model.options && model.options.deviceOverrides);"
1694
+ "functionBody": "return (model.options?.deviceOverrides);"
1695
+ }
1696
+ },
1697
+ "onGet": {
1698
+ "title": "onGet",
1699
+ "type": "string",
1700
+ "description": "Optional. A one-line JavaScript code to convert the old value to the new value. The function is called with two arguments: device and value. Examples: https://github.com/homebridge-plugins/homebridge-tuya/blob/latest/ADVANCED_OPTIONS.md#examples",
1701
+ "placeholder": "value",
1702
+ "condition": {
1703
+ "functionBody": "return (model.options?.deviceOverrides?.[arrayIndices[0]]?.schema?.[arrayIndices[1]]?.code && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1704
+ }
1705
+ },
1706
+ "onSet": {
1707
+ "title": "onSet",
1708
+ "type": "string",
1709
+ "description": "Optional. A one-line JavaScript code to convert the new value to the old value. The function is called with two arguments: device and value. Returning undefined means to skip sending the command. Examples: https://github.com/homebridge-plugins/homebridge-tuya/blob/latest/ADVANCED_OPTIONS.md#examples",
1710
+ "placeholder": "value",
1711
+ "condition": {
1712
+ "functionBody": "return (model.options?.deviceOverrides?.[arrayIndices[0]]?.schema?.[arrayIndices[1]]?.code && !model.options.deviceOverrides[arrayIndices[0]].schema[arrayIndices[1]].hidden);"
1117
1713
  }
1118
1714
  }
1119
1715
  }
1120
1716
  },
1121
1717
  "condition": {
1122
- "functionBody": "return (model.options && model.options.deviceOverrides);"
1718
+ "functionBody": "return (model.options?.deviceOverrides);"
1123
1719
  }
1124
1720
  }
1125
1721
  }
@@ -1129,9 +1725,6 @@
1129
1725
  "title": "Accessory Service Informations ",
1130
1726
  "description": "Accessory Service Information Configs",
1131
1727
  "type": "array",
1132
- "condition": {
1133
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
1134
- },
1135
1728
  "items": {
1136
1729
  "type": "object",
1137
1730
  "required": ["device_id", "index"],
@@ -1180,12 +1773,23 @@
1180
1773
  "title": "Weather API",
1181
1774
  "description": "Open-Meteo : For non-commercial use. [Weather data by Open-Meteo.com](https://open-meteo.com/)<br>Tuya : Requires authorization for Weather Service.",
1182
1775
  "type": "string",
1183
- "enum": ["Open-Meteo", "Tuya"],
1776
+ "enum": [ "Open-Meteo", "Tuya" ],
1184
1777
  "default": "Open-Meteo",
1185
1778
  "condition": {
1186
1779
  "functionBody": "return (model.options && model.options.generateWeatherAccessory);"
1187
1780
  }
1188
1781
  },
1782
+ "forceIPv4": {
1783
+ "title": "Forcing IPv4 connection",
1784
+ "type": "boolean",
1785
+ "default": false
1786
+ }
1787
+ }
1788
+ },
1789
+ "common": {
1790
+ "title": "Common Settings",
1791
+ "type": "object",
1792
+ "properties": {
1189
1793
  "debug": {
1190
1794
  "title": "Enable Debug Logging",
1191
1795
  "type": "boolean",
@@ -1196,326 +1800,50 @@
1196
1800
  "description": "An optional list of strings seperated with comma `,`. `api` represents for API and MQTT log, device ID represents for specific device log. If blank, all logs are outputed.",
1197
1801
  "type": "string",
1198
1802
  "condition": {
1199
- "functionBody": "return (model.options && model.options.debug);"
1803
+ "functionBody": "return (model.common.debug);"
1200
1804
  }
1201
1805
  }
1202
1806
  }
1203
- }
1204
- }
1205
- },
1206
- "layout": [
1207
- "mode",
1208
- {
1209
- "type": "fieldset",
1210
- "title": "Local Settings",
1211
- "expandable": true,
1212
- "expanded": true,
1213
- "condition": {
1214
- "functionBody": "return (model.mode === 'local' || model.mode === 'both');"
1215
- },
1216
- "items": [
1217
- "local.autoDiscoverDevices",
1218
- "local.discoverTimeout",
1219
- "local.rediscoverInterval",
1220
- {
1221
- "key": "local.devices",
1222
- "add": "Add Manual Device",
1223
- "title": "{{ 'Add New Device' }}",
1224
- "type": "tabarray",
1225
- "notitle": true,
1226
- "items": [
1227
- {
1228
- "type": "div",
1229
- "displayFlex": false,
1230
- "notitle": true,
1231
- "title": "{{ value.name || value.tuyaDeviceId || 'New Device' }}",
1232
- "items": [
1233
- { "key": "local.devices[].category" },
1234
- { "key": "local.devices[].name" },
1235
- { "key": "local.devices[].tuyaDeviceId" },
1236
- { "key": "local.devices[].tuyaKey" },
1237
- { "key": "local.devices[].ip" },
1238
- { "key": "local.devices[].protocolVersion" },
1239
- { "key": "local.devices[].dpMapping" },
1240
- { "key": "local.devices[].outletCount" },
1241
- { "key": "local.devices[].outlets" },
1242
- { "key": "local.devices[].dpPower" },
1243
- { "key": "local.devices[].dpBrightness" },
1244
- { "key": "local.devices[].dpColorTemperature" },
1245
- { "key": "local.devices[].minWhiteColor" },
1246
- { "key": "local.devices[].maxWhiteColor" },
1247
- { "key": "local.devices[].dpMode" },
1248
- { "key": "local.devices[].dpColor" },
1249
- { "key": "local.devices[].colorFunction" },
1250
- { "key": "local.devices[].scaleBrightness" },
1251
- { "key": "local.devices[].scaleWhiteColor" },
1252
- { "key": "local.devices[].voltsId" },
1253
- { "key": "local.devices[].ampsId" },
1254
- { "key": "local.devices[].wattsId" },
1255
- { "key": "local.devices[].voltsDivisor" },
1256
- { "key": "local.devices[].ampsDivisor" },
1257
- { "key": "local.devices[].wattsDivisor" },
1258
- { "key": "local.devices[].noCool" },
1259
- { "key": "local.devices[].noHeat" },
1260
- { "key": "local.devices[].cmdCool" },
1261
- { "key": "local.devices[].cmdHeat" },
1262
- { "key": "local.devices[].noSwing" },
1263
- { "key": "local.devices[].minTemperature" },
1264
- { "key": "local.devices[].maxTemperature" },
1265
- { "key": "local.devices[].minTemperatureSteps" },
1266
- { "key": "local.devices[].dpActive" },
1267
- { "key": "local.devices[].dpDesiredTemperature" },
1268
- { "key": "local.devices[].dpCurrentTemperature" },
1269
- { "key": "local.devices[].dpAction" },
1270
- { "key": "local.devices[].dpStatus" },
1271
- { "key": "local.devices[].flipState" },
1272
- { "key": "local.devices[].timeToOpen" },
1273
- { "key": "local.devices[].timeToTighten" },
1274
- { "key": "local.devices[].timeToClose" },
1275
- { "key": "local.devices[].dpLight" },
1276
- { "key": "local.devices[].dpBlindType" },
1277
- { "key": "local.devices[].dpLightOn" },
1278
- { "key": "local.devices[].dpFanOn" },
1279
- { "key": "local.devices[].dpRotationSpeed" },
1280
- { "key": "local.devices[].dpRotationDirection" },
1281
- { "key": "local.devices[].maxSpeed" },
1282
- { "key": "local.devices[].fanDefaultSpeed" },
1283
- { "key": "local.devices[].useStrings" },
1284
- { "key": "local.devices[].dpChildLock" },
1285
- { "key": "local.devices[].dpTemperatureDisplayUnits" },
1286
- { "key": "local.devices[].cmdLow" },
1287
- { "key": "local.devices[].cmdHigh" },
1288
- { "key": "local.devices[].noChildLock" },
1289
- { "key": "local.devices[].noTemperatureUnit" },
1290
- { "key": "local.devices[].temperatureDivisor" },
1291
- { "key": "local.devices[].thresholdTemperatureDivisor" },
1292
- { "key": "local.devices[].temperatureOffset" }
1293
- ]
1294
- }
1295
- ]
1296
- }
1297
- ]
1298
- },
1299
- {
1300
- "type": "fieldset",
1301
- "title": "Tuya Cloud Account Info",
1302
- "expandable": true,
1303
- "expanded": false,
1304
- "condition": {
1305
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
1306
- },
1307
- "items": [
1308
- "options.projectType",
1309
- "options.endpoint",
1310
- "options.accessId",
1311
- "options.accessKey",
1312
- "options.countryCode",
1313
- "options.username",
1314
- "options.password",
1315
- "options.appSchema"
1316
- ]
1317
- },
1318
- {
1319
- "type": "fieldset",
1320
- "title": "Tuya Home Settings",
1321
- "expandable": true,
1322
- "expanded": false,
1323
- "notitle": false,
1324
- "condition": {
1325
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
1326
- },
1327
- "items": [
1328
- {
1329
- "key": "options.homeWhitelist",
1330
- "add": "Add Another Home ID",
1331
- "title": "{{ 'New Whitelisted Home' }}",
1332
- "type": "tabarray",
1333
- "notitle": true,
1334
- "items": [
1335
- {
1336
- "type": "div",
1337
- "displayFlex": true,
1338
- "flex-direction": "row",
1339
- "notitle": true,
1340
- "title": "{{ value }}",
1341
- "items": [
1342
- {
1343
- "key": "options.homeWhitelist[]",
1344
- "placeholder": "Home ID"
1345
- }
1346
- ]
1347
- }
1348
- ]
1349
- }
1350
- ]
1351
- },
1352
- {
1353
- "type": "fieldset",
1354
- "title": "Tuya Device Settings",
1355
- "expandable": true,
1356
- "expanded": true,
1357
- "notitle": false,
1358
- "condition": {
1359
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
1360
- },
1361
- "items": [
1362
- {
1363
- "key": "options.deviceOverrides",
1364
- "add": "Add Another Device Override",
1365
- "title": "{{ 'New Device Override' }}",
1366
- "type": "tabarray",
1367
- "notitle": true,
1368
- "default": [],
1369
- "items": [
1370
- {
1371
- "type": "div",
1372
- "displayFlex": false,
1373
- "flex-direction": "row",
1374
- "notitle": true,
1375
- "title": "{{ value.id || 'New Device Override' }}",
1376
- "items": [
1377
- {
1378
- "key": "options.deviceOverrides[].id"
1379
- },
1380
- {
1381
- "key": "options.deviceOverrides[].category"
1382
- },
1383
- {
1384
- "key": "options.deviceOverrides[].unbridged"
1385
- },
1386
- {
1387
- "key": "options.deviceOverrides[].schema",
1388
- "add": "Add New Schema",
1389
- "title": "{{ 'New Schema' }}",
1390
- "type": "tabarray",
1391
- "notitle": true,
1392
- "items": [
1393
- {
1394
- "type": "div",
1395
- "displayFlex": true,
1396
- "title": "{{ value.code }}",
1397
- "flex-direction": "column",
1398
- "notitle": false,
1399
- "items": [
1400
- {
1401
- "key": "options.deviceOverrides[].schema[].code"
1402
- },
1403
- {
1404
- "key": "options.deviceOverrides[].schema[].newCode"
1405
- },
1406
- {
1407
- "key": "options.deviceOverrides[].schema[].hidden"
1408
- },
1409
- {
1410
- "key": "options.deviceOverrides[].schema[].type"
1411
- },
1412
- {
1413
- "key": "options.deviceOverrides[].schema[].property",
1414
- "notitle": false,
1415
- "items": [
1416
- "options.deviceOverrides[].schema[].property.min",
1417
- "options.deviceOverrides[].schema[].property.max",
1418
- "options.deviceOverrides[].schema[].property.scale",
1419
- "options.deviceOverrides[].schema[].property.step",
1420
- {
1421
- "key": "options.deviceOverrides[].schema[].property.range",
1422
- "add": "Add Range",
1423
- "title": "{{ 'New Range' }}",
1424
- "type": "tabarray",
1425
- "notitle": true,
1426
- "items": [
1427
- {
1428
- "type": "div",
1429
- "displayFlex": true,
1430
- "flex-direction": "row",
1431
- "notitle": true,
1432
- "title": "{{ value }}",
1433
- "items": [
1434
- {
1435
- "key": "options.deviceOverrides[].schema[].property.range[]",
1436
- "placeholder": "Range"
1437
- }
1438
- ]
1439
- }
1440
- ]
1441
- }
1442
- ]
1443
- }
1444
- ]
1445
- }
1446
- ]
1447
- }
1448
- ]
1449
- }
1450
- ]
1451
- }
1452
- ]
1453
- },
1454
-
1455
- {
1456
- "type": "fieldset",
1457
- "title": "Accessory Service Informations",
1458
- "expandable": true,
1459
- "expanded": false,
1460
- "notitle": false,
1461
- "condition": {
1462
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
1463
1807
  },
1464
- "items": [
1465
- {
1466
- "key": "options.serviceInformationOverrides",
1467
- "add": "Add Another Service Information Override",
1468
- "title": "{{ 'New Service Information Override' }}",
1469
- "type": "tabarray",
1470
- "notitle": true,
1471
- "default": [],
1472
- "items": [
1473
- {
1474
- "type": "div",
1475
- "displayFlex": false,
1476
- "flex-direction": "row",
1477
- "notitle": true,
1478
- "title": "{{ value.device_id }}",
1479
- "items": [
1480
- {
1481
- "key": "options.serviceInformationOverrides[].device_id"
1482
- },
1483
- {
1484
- "key": "options.serviceInformationOverrides[].index"
1485
- },
1486
- {
1487
- "key": "options.serviceInformationOverrides[].manifacturer"
1488
- },
1489
- {
1490
- "key": "options.serviceInformationOverrides[].model"
1491
- },
1492
- {
1493
- "key": "options.serviceInformationOverrides[].firmwareRevision"
1494
- },
1495
- {
1496
- "key": "options.serviceInformationOverrides[].configuredName"
1497
- }
1498
- ]
1808
+ "cameras": {
1809
+ "title": "RTSP Camera",
1810
+ "description": "Specifying a local IP address causes the communication to be routed within the local network (LAN).",
1811
+ "type": "array",
1812
+ "items": {
1813
+ "type": "object",
1814
+ "required": ["rtspUrl"],
1815
+ "properties": {
1816
+ "deviceId": {
1817
+ "title": "DeviceID",
1818
+ "description": "Device ID. If the device is not a Tuya camera, you don’t need to enter anything.",
1819
+ "type": "string"
1820
+ },
1821
+ "deviceName": {
1822
+ "title": "Device Name",
1823
+ "description": "Display Name",
1824
+ "type": "string"
1825
+ },
1826
+ "rtspUrl": {
1827
+ "title": "RTSP URL",
1828
+ "description": "RTSP URLs (starting with rtsp://) for real-time video/audio streaming.",
1829
+ "type": "string"
1830
+ },
1831
+ "username": {
1832
+ "title": "username",
1833
+ "description": "The authentication username for accessing the RTSP stream. If authentication is not required, please leave it empty.",
1834
+ "type": "string"
1835
+ },
1836
+ "password": {
1837
+ "title": "password",
1838
+ "description": "The authentication password for accessing the RTSP stream. If authentication is not required, please leave it empty.",
1839
+ "type": "string",
1840
+ "x-schema-form": {
1841
+ "type": "password"
1842
+ }
1499
1843
  }
1500
- ]
1844
+ }
1501
1845
  }
1502
- ]
1503
- },
1504
- {
1505
- "type": "fieldset",
1506
- "title": "Advance Settings",
1507
- "expandable": true,
1508
- "expanded": false,
1509
- "notitle": false,
1510
- "condition": {
1511
- "functionBody": "return (model.mode === 'cloud' || model.mode === 'both');"
1512
- },
1513
- "items": [
1514
- "options.generateWeatherAccessory",
1515
- "options.weatherAPI",
1516
- "options.debug",
1517
- "options.debugLevel"
1518
- ]
1846
+ }
1519
1847
  }
1520
- ]
1848
+ }
1521
1849
  }