iobroker.iot 3.6.0 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/README.md +8 -4
  2. package/admin/assets/index-5zouxn2w.js +680 -0
  3. package/admin/index_m.html +1 -1
  4. package/admin/rules/assets/{index-BRdNnGcA.js → index-DwYdaT5M.js} +80 -81
  5. package/admin/rules/customRuleBlocks.js +2 -2
  6. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/AlexaResponse.js +101 -95
  7. package/build-backend/lib/AlexaSmartHomeV3/Alexa/AlexaResponse.js.map +1 -0
  8. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Capabilities/Base.js +22 -36
  9. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/Base.js.map +1 -0
  10. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/BrightnessController.js +19 -0
  11. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/BrightnessController.js.map +1 -0
  12. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorController.js +14 -0
  13. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorController.js.map +1 -0
  14. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorTemperatureController.js +19 -0
  15. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorTemperatureController.js.map +1 -0
  16. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ContactSensor.js +16 -0
  17. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ContactSensor.js.map +1 -0
  18. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/LockController.js +14 -0
  19. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/LockController.js.map +1 -0
  20. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Capabilities/ModeController.js +27 -28
  21. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ModeController.js.map +1 -0
  22. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/MotionSensor.js +14 -0
  23. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/MotionSensor.js.map +1 -0
  24. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/PercentageController.js +14 -0
  25. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/PercentageController.js.map +1 -0
  26. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/PowerController.js +19 -0
  27. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/PowerController.js.map +1 -0
  28. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/Speaker.js +25 -0
  29. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/Speaker.js.map +1 -0
  30. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/TemperatureSensor.js +14 -0
  31. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/TemperatureSensor.js.map +1 -0
  32. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ThermostatController.js +37 -0
  33. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/ThermostatController.js.map +1 -0
  34. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/index.js +32 -0
  35. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Capabilities/index.js.map +1 -0
  36. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/Base.js +29 -0
  37. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/Base.js.map +1 -0
  38. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Directives/ChangeReport.js +34 -27
  39. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/ChangeReport.js.map +1 -0
  40. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/Discovery.js +39 -0
  41. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/Discovery.js.map +1 -0
  42. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Directives/ReportState.js +19 -22
  43. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/ReportState.js.map +1 -0
  44. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/index.js +14 -0
  45. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Directives/index.js.map +1 -0
  46. package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Base.js +36 -0
  47. package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Base.js.map +1 -0
  48. package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Closed.js +57 -0
  49. package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Closed.js.map +1 -0
  50. package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Open.js +57 -0
  51. package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/Open.js.map +1 -0
  52. package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/index.js +12 -0
  53. package/build-backend/lib/AlexaSmartHomeV3/Alexa/ModeValues/index.js.map +1 -0
  54. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/AdjustableProperty.js +16 -0
  55. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/AdjustableProperty.js.map +1 -0
  56. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Base.js +127 -0
  57. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Base.js.map +1 -0
  58. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Brightness.js +18 -0
  59. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Brightness.js.map +1 -0
  60. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Color.js +38 -0
  61. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Color.js.map +1 -0
  62. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Properties/ColorTemperatureInKelvin.js +20 -29
  63. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/ColorTemperatureInKelvin.js.map +1 -0
  64. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/DetectionState.js +23 -0
  65. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/DetectionState.js.map +1 -0
  66. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Properties/LockState.js +9 -12
  67. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/LockState.js.map +1 -0
  68. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Mode.js +34 -0
  69. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Mode.js.map +1 -0
  70. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Muted.js +19 -0
  71. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Muted.js.map +1 -0
  72. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Percentage.js +18 -0
  73. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Percentage.js.map +1 -0
  74. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Alexa/Properties/PowerState.js +9 -9
  75. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/PowerState.js.map +1 -0
  76. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/TargetSetpoint.js +31 -0
  77. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/TargetSetpoint.js.map +1 -0
  78. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Temperature.js +22 -0
  79. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Temperature.js.map +1 -0
  80. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/ThermostatMode.js +49 -0
  81. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/ThermostatMode.js.map +1 -0
  82. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Volume.js +21 -0
  83. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/Volume.js.map +1 -0
  84. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/index.js +38 -0
  85. package/build-backend/lib/AlexaSmartHomeV3/Alexa/Properties/index.js.map +1 -0
  86. package/build-backend/lib/AlexaSmartHomeV3/Controls/AdjustableControl.js +20 -0
  87. package/build-backend/lib/AlexaSmartHomeV3/Controls/AdjustableControl.js.map +1 -0
  88. package/build-backend/lib/AlexaSmartHomeV3/Controls/AdjustablePercentageControl.js +26 -0
  89. package/build-backend/lib/AlexaSmartHomeV3/Controls/AdjustablePercentageControl.js.map +1 -0
  90. package/build-backend/lib/AlexaSmartHomeV3/Controls/AirCondition.js +148 -0
  91. package/build-backend/lib/AlexaSmartHomeV3/Controls/AirCondition.js.map +1 -0
  92. package/build-backend/lib/AlexaSmartHomeV3/Controls/Blind.js +13 -0
  93. package/build-backend/lib/AlexaSmartHomeV3/Controls/Blind.js.map +1 -0
  94. package/build-backend/lib/AlexaSmartHomeV3/Controls/ContactSensor.js +17 -0
  95. package/build-backend/lib/AlexaSmartHomeV3/Controls/ContactSensor.js.map +1 -0
  96. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Controls/Control.js +73 -104
  97. package/build-backend/lib/AlexaSmartHomeV3/Controls/Control.js.map +1 -0
  98. package/build-backend/lib/AlexaSmartHomeV3/Controls/Ct.js +182 -0
  99. package/build-backend/lib/AlexaSmartHomeV3/Controls/Ct.js.map +1 -0
  100. package/build-backend/lib/AlexaSmartHomeV3/Controls/Dimmer.js +127 -0
  101. package/build-backend/lib/AlexaSmartHomeV3/Controls/Dimmer.js.map +1 -0
  102. package/build-backend/lib/AlexaSmartHomeV3/Controls/Door.js +10 -0
  103. package/build-backend/lib/AlexaSmartHomeV3/Controls/Door.js.map +1 -0
  104. package/build-backend/lib/AlexaSmartHomeV3/Controls/Gate.js +38 -0
  105. package/build-backend/lib/AlexaSmartHomeV3/Controls/Gate.js.map +1 -0
  106. package/build-backend/lib/AlexaSmartHomeV3/Controls/Hue.js +208 -0
  107. package/build-backend/lib/AlexaSmartHomeV3/Controls/Hue.js.map +1 -0
  108. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Controls/Light.js +15 -22
  109. package/build-backend/lib/AlexaSmartHomeV3/Controls/Light.js.map +1 -0
  110. package/build-backend/lib/AlexaSmartHomeV3/Controls/Lock.js +35 -0
  111. package/build-backend/lib/AlexaSmartHomeV3/Controls/Lock.js.map +1 -0
  112. package/build-backend/lib/AlexaSmartHomeV3/Controls/Motion.js +17 -0
  113. package/build-backend/lib/AlexaSmartHomeV3/Controls/Motion.js.map +1 -0
  114. package/build-backend/lib/AlexaSmartHomeV3/Controls/ReadOnlyDetector.js +26 -0
  115. package/build-backend/lib/AlexaSmartHomeV3/Controls/ReadOnlyDetector.js.map +1 -0
  116. package/build-backend/lib/AlexaSmartHomeV3/Controls/Slider.js +10 -0
  117. package/build-backend/lib/AlexaSmartHomeV3/Controls/Slider.js.map +1 -0
  118. package/build-backend/lib/AlexaSmartHomeV3/Controls/Socket.js +21 -0
  119. package/build-backend/lib/AlexaSmartHomeV3/Controls/Socket.js.map +1 -0
  120. package/build-backend/lib/AlexaSmartHomeV3/Controls/Temperature.js +21 -0
  121. package/build-backend/lib/AlexaSmartHomeV3/Controls/Temperature.js.map +1 -0
  122. package/build-backend/lib/AlexaSmartHomeV3/Controls/Thermostat.js +85 -0
  123. package/build-backend/lib/AlexaSmartHomeV3/Controls/Thermostat.js.map +1 -0
  124. package/build-backend/lib/AlexaSmartHomeV3/Controls/VacuumCleaner.js +27 -0
  125. package/build-backend/lib/AlexaSmartHomeV3/Controls/VacuumCleaner.js.map +1 -0
  126. package/build-backend/lib/AlexaSmartHomeV3/Controls/Volume.js +116 -0
  127. package/build-backend/lib/AlexaSmartHomeV3/Controls/Volume.js.map +1 -0
  128. package/build-backend/lib/AlexaSmartHomeV3/Controls/VolumeGroup.js +10 -0
  129. package/build-backend/lib/AlexaSmartHomeV3/Controls/VolumeGroup.js.map +1 -0
  130. package/build-backend/lib/AlexaSmartHomeV3/Controls/Window.js +10 -0
  131. package/build-backend/lib/AlexaSmartHomeV3/Controls/Window.js.map +1 -0
  132. package/build-backend/lib/AlexaSmartHomeV3/Controls/index.js +121 -0
  133. package/build-backend/lib/AlexaSmartHomeV3/Controls/index.js.map +1 -0
  134. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Device.js +29 -30
  135. package/build-backend/lib/AlexaSmartHomeV3/Device.js.map +1 -0
  136. package/build-backend/lib/AlexaSmartHomeV3/DeviceManager.js +392 -0
  137. package/build-backend/lib/AlexaSmartHomeV3/DeviceManager.js.map +1 -0
  138. package/build-backend/lib/AlexaSmartHomeV3/Exceptions/AlexaV3Exception.js +10 -0
  139. package/build-backend/lib/AlexaSmartHomeV3/Exceptions/AlexaV3Exception.js.map +1 -0
  140. package/build-backend/lib/AlexaSmartHomeV3/Exceptions/HourlyDeviceRateLimitExceeded.js +10 -0
  141. package/build-backend/lib/AlexaSmartHomeV3/Exceptions/HourlyDeviceRateLimitExceeded.js.map +1 -0
  142. package/build-backend/lib/AlexaSmartHomeV3/Exceptions/OverallDailyRateLimitExceeded.js +10 -0
  143. package/build-backend/lib/AlexaSmartHomeV3/Exceptions/OverallDailyRateLimitExceeded.js.map +1 -0
  144. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Helpers/AdapterProvider.js +12 -21
  145. package/build-backend/lib/AlexaSmartHomeV3/Helpers/AdapterProvider.js.map +1 -0
  146. package/build-backend/lib/AlexaSmartHomeV3/Helpers/FileHelper.js +53 -0
  147. package/build-backend/lib/AlexaSmartHomeV3/Helpers/FileHelper.js.map +1 -0
  148. package/{lib → build-backend/lib}/AlexaSmartHomeV3/Helpers/IotProxy.js +9 -26
  149. package/build-backend/lib/AlexaSmartHomeV3/Helpers/IotProxy.js.map +1 -0
  150. package/build-backend/lib/AlexaSmartHomeV3/Helpers/Logger.js +93 -0
  151. package/build-backend/lib/AlexaSmartHomeV3/Helpers/Logger.js.map +1 -0
  152. package/build-backend/lib/AlexaSmartHomeV3/Helpers/RateLimiter.js +112 -0
  153. package/build-backend/lib/AlexaSmartHomeV3/Helpers/RateLimiter.js.map +1 -0
  154. package/build-backend/lib/AlexaSmartHomeV3/Helpers/Utils.js +625 -0
  155. package/build-backend/lib/AlexaSmartHomeV3/Helpers/Utils.js.map +1 -0
  156. package/build-backend/lib/Utils.js +96 -0
  157. package/build-backend/lib/Utils.js.map +1 -0
  158. package/build-backend/lib/adminCommonSocket.js +715 -0
  159. package/build-backend/lib/adminCommonSocket.js.map +1 -0
  160. package/build-backend/lib/alexaCustom.js +542 -0
  161. package/build-backend/lib/alexaCustom.js.map +1 -0
  162. package/{lib → build-backend/lib}/alexaSmartHomeV2.js +4 -8
  163. package/{lib → build-backend/lib}/alexaSmartHomeV3.js +25 -45
  164. package/build-backend/lib/alexaSmartHomeV3.js.map +1 -0
  165. package/{lib → build-backend/lib}/alisa.js +41 -44
  166. package/{lib → build-backend/lib}/devices.js +11 -8
  167. package/build-backend/lib/devices.js.map +1 -0
  168. package/{lib → build-backend/lib}/functions.js +11 -8
  169. package/build-backend/lib/functions.js.map +1 -0
  170. package/{lib → build-backend/lib}/googleHome.js +25 -26
  171. package/{lib → build-backend/lib}/notifications.js +15 -22
  172. package/build-backend/lib/notifications.js.map +1 -0
  173. package/{lib → build-backend/lib}/remote.js +615 -636
  174. package/build-backend/lib/remote.js.map +1 -0
  175. package/{lib → build-backend/lib}/rooms.js +11 -8
  176. package/build-backend/lib/rooms.js.map +1 -0
  177. package/{lib → build-backend/lib}/texts.js +6 -4
  178. package/build-backend/lib/texts.js.map +1 -0
  179. package/build-backend/lib/translate.js +21 -0
  180. package/build-backend/lib/translate.js.map +1 -0
  181. package/{lib → build-backend/lib}/visuApp.js +45 -65
  182. package/build-backend/lib/visuApp.js.map +1 -0
  183. package/build-backend/main.js +1361 -0
  184. package/build-backend/main.js.map +1 -0
  185. package/io-package.json +14 -14
  186. package/package.json +18 -15
  187. package/admin/assets/index-DCbOB3g_.js +0 -681
  188. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/BrightnessController.js +0 -15
  189. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorController.js +0 -10
  190. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ColorTemperatureController.js +0 -15
  191. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ContactSensor.js +0 -10
  192. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/LockController.js +0 -10
  193. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/MotionSensor.js +0 -10
  194. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/PercentageController.js +0 -10
  195. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/PowerController.js +0 -15
  196. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/Speaker.js +0 -20
  197. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/TemperatureSensor.js +0 -10
  198. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/ThermostatController.js +0 -34
  199. package/lib/AlexaSmartHomeV3/Alexa/Capabilities/index.js +0 -14
  200. package/lib/AlexaSmartHomeV3/Alexa/Directives/Base.js +0 -27
  201. package/lib/AlexaSmartHomeV3/Alexa/Directives/Discovery.js +0 -39
  202. package/lib/AlexaSmartHomeV3/Alexa/Directives/index.js +0 -13
  203. package/lib/AlexaSmartHomeV3/Alexa/ModeValues/Base.js +0 -38
  204. package/lib/AlexaSmartHomeV3/Alexa/ModeValues/Closed.js +0 -55
  205. package/lib/AlexaSmartHomeV3/Alexa/ModeValues/Open.js +0 -56
  206. package/lib/AlexaSmartHomeV3/Alexa/ModeValues/index.js +0 -14
  207. package/lib/AlexaSmartHomeV3/Alexa/Properties/AdjustableProperty.js +0 -11
  208. package/lib/AlexaSmartHomeV3/Alexa/Properties/Base.js +0 -108
  209. package/lib/AlexaSmartHomeV3/Alexa/Properties/Brightness.js +0 -14
  210. package/lib/AlexaSmartHomeV3/Alexa/Properties/Color.js +0 -40
  211. package/lib/AlexaSmartHomeV3/Alexa/Properties/DetectionState.js +0 -22
  212. package/lib/AlexaSmartHomeV3/Alexa/Properties/Mode.js +0 -32
  213. package/lib/AlexaSmartHomeV3/Alexa/Properties/Muted.js +0 -17
  214. package/lib/AlexaSmartHomeV3/Alexa/Properties/Percentage.js +0 -14
  215. package/lib/AlexaSmartHomeV3/Alexa/Properties/TargetSetpoint.js +0 -28
  216. package/lib/AlexaSmartHomeV3/Alexa/Properties/Temperature.js +0 -20
  217. package/lib/AlexaSmartHomeV3/Alexa/Properties/ThermostatMode.js +0 -52
  218. package/lib/AlexaSmartHomeV3/Alexa/Properties/Volume.js +0 -19
  219. package/lib/AlexaSmartHomeV3/Alexa/Properties/index.js +0 -14
  220. package/lib/AlexaSmartHomeV3/Controls/AdjustableControl.js +0 -22
  221. package/lib/AlexaSmartHomeV3/Controls/AdjustablePercentageControl.js +0 -28
  222. package/lib/AlexaSmartHomeV3/Controls/AirCondition.js +0 -144
  223. package/lib/AlexaSmartHomeV3/Controls/Blind.js +0 -12
  224. package/lib/AlexaSmartHomeV3/Controls/ContactSensor.js +0 -17
  225. package/lib/AlexaSmartHomeV3/Controls/Ct.js +0 -172
  226. package/lib/AlexaSmartHomeV3/Controls/Dimmer.js +0 -124
  227. package/lib/AlexaSmartHomeV3/Controls/Door.js +0 -9
  228. package/lib/AlexaSmartHomeV3/Controls/Gate.js +0 -42
  229. package/lib/AlexaSmartHomeV3/Controls/Hue.js +0 -207
  230. package/lib/AlexaSmartHomeV3/Controls/Lock.js +0 -36
  231. package/lib/AlexaSmartHomeV3/Controls/Motion.js +0 -17
  232. package/lib/AlexaSmartHomeV3/Controls/ReadOnlyDetector.js +0 -25
  233. package/lib/AlexaSmartHomeV3/Controls/Slider.js +0 -10
  234. package/lib/AlexaSmartHomeV3/Controls/Socket.js +0 -21
  235. package/lib/AlexaSmartHomeV3/Controls/Temperature.js +0 -22
  236. package/lib/AlexaSmartHomeV3/Controls/Thermostat.js +0 -86
  237. package/lib/AlexaSmartHomeV3/Controls/VacuumCleaner.js +0 -28
  238. package/lib/AlexaSmartHomeV3/Controls/Volume.js +0 -109
  239. package/lib/AlexaSmartHomeV3/Controls/VolumeGroup.js +0 -9
  240. package/lib/AlexaSmartHomeV3/Controls/Window.js +0 -9
  241. package/lib/AlexaSmartHomeV3/Controls/index.js +0 -14
  242. package/lib/AlexaSmartHomeV3/DeviceManager.js +0 -415
  243. package/lib/AlexaSmartHomeV3/Exceptions/AlexaV3Exception.js +0 -8
  244. package/lib/AlexaSmartHomeV3/Exceptions/HourlyDeviceRateLimitExceeded.js +0 -5
  245. package/lib/AlexaSmartHomeV3/Exceptions/OverallDailyRateLimitExceeded.js +0 -5
  246. package/lib/AlexaSmartHomeV3/Helpers/FileHelper.js +0 -70
  247. package/lib/AlexaSmartHomeV3/Helpers/Logger.js +0 -95
  248. package/lib/AlexaSmartHomeV3/Helpers/RateLimiter.js +0 -82
  249. package/lib/AlexaSmartHomeV3/Helpers/Utils.js +0 -583
  250. package/lib/Utils.js +0 -608
  251. package/lib/adminCommonSocket.js +0 -781
  252. package/lib/alexaCustom.js +0 -622
  253. package/lib/translate.js +0 -19
  254. package/main.js +0 -1454
@@ -0,0 +1,1361 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.IotAdapter = void 0;
7
+ const aws_iot_device_sdk_1 = require("aws-iot-device-sdk");
8
+ const adapter_core_1 = require("@iobroker/adapter-core"); // Get common adapter utils
9
+ const node_fs_1 = require("node:fs");
10
+ const axios_1 = __importDefault(require("axios"));
11
+ const node_zlib_1 = require("node:zlib");
12
+ // @ts-expect-error no types
13
+ const alexaSmartHomeV2_1 = __importDefault(require("./lib/alexaSmartHomeV2"));
14
+ const alexaSmartHomeV3_1 = __importDefault(require("./lib/alexaSmartHomeV3"));
15
+ const alexaCustom_1 = __importDefault(require("./lib/alexaCustom"));
16
+ // @ts-expect-error no types
17
+ const googleHome_1 = __importDefault(require("./lib/googleHome"));
18
+ // @ts-expect-error no types
19
+ const alisa_1 = __importDefault(require("./lib/alisa"));
20
+ const remote_1 = __importDefault(require("./lib/remote"));
21
+ const visuApp_1 = require("./lib/visuApp");
22
+ const notifications_1 = require("./lib/notifications");
23
+ const NONE = '___none___';
24
+ const MAX_IOT_MESSAGE_LENGTH = 127 * 1024;
25
+ const SPECIAL_ADAPTERS = ['netatmo'];
26
+ const ALLOWED_SERVICES = SPECIAL_ADAPTERS.concat(['text2command']);
27
+ class IotAdapter extends adapter_core_1.Adapter {
28
+ recalcTimeout = null;
29
+ lang = 'de';
30
+ translate = false;
31
+ alexaSH2 = null;
32
+ alexaSH3 = null;
33
+ googleHome = null;
34
+ alexaCustom = null;
35
+ yandexAlisa = null;
36
+ remote = null;
37
+ device = null;
38
+ urlKey = null;
39
+ connectedOwn = false;
40
+ secret = '';
41
+ connectStarted = 0;
42
+ constructor(options = {}) {
43
+ super({
44
+ ...options,
45
+ name: 'iot',
46
+ objectChange: (id, obj) => {
47
+ if (id === 'system.config' && obj && !this.translate) {
48
+ const systemObj = obj;
49
+ this.lang = systemObj.common.language;
50
+ if (this.lang !== 'en' && this.lang !== 'de' && this.lang !== 'ru') {
51
+ this.lang = 'en';
52
+ }
53
+ this.alexaSH2?.setLanguage(this.lang);
54
+ this.alexaSH3?.setLanguage(this.lang);
55
+ this.yandexAlisa?.setLanguage(this.lang);
56
+ this.alexaCustom?.setLanguage(this.lang);
57
+ this.googleHome?.setLanguage(this.lang);
58
+ this.remote?.setLanguage(this.lang);
59
+ }
60
+ // if it is an instance
61
+ if (id.startsWith('system.adapter.')) {
62
+ // try to find it in special adapters
63
+ const adpr = SPECIAL_ADAPTERS.find(a => id.startsWith(`system.adapter.${a}.`));
64
+ // if found and it is really instance
65
+ if (adpr && id.match(/\.\d+$/)) {
66
+ // update state
67
+ setTimeout(async () => await this.createStateForAdapter(adpr), 1000);
68
+ }
69
+ return;
70
+ }
71
+ void this.alexaSH3?.handleObjectChange(id, obj);
72
+ if (id) {
73
+ this.remote?.updateObject(id, obj);
74
+ }
75
+ },
76
+ stateChange: async (id, state) => {
77
+ if (id === `${this.namespace}.app.message` && state && !state.ack) {
78
+ try {
79
+ await this.sendMessageToApp(state.val);
80
+ }
81
+ catch (e) {
82
+ this.log.error(`Cannot send message to app: ${e}`);
83
+ }
84
+ }
85
+ if (state) {
86
+ if (this.config.googleHome) {
87
+ void this.googleHome?.updateState(id, state);
88
+ }
89
+ if (this.config.amazonAlexa) {
90
+ void this.alexaSH3?.handleStateUpdate(id, state);
91
+ }
92
+ if (this.config.yandexAlisa) {
93
+ void this.yandexAlisa?.updateState?.(id, state);
94
+ }
95
+ }
96
+ if (id) {
97
+ this.remote?.updateState(id, state);
98
+ }
99
+ if (id === `${this.namespace}.smart.lastResponse` && state && !state.ack) {
100
+ this.alexaCustom?.setResponse(state.val);
101
+ }
102
+ },
103
+ unload: async (callback) => {
104
+ try {
105
+ if (this.device) {
106
+ this.device.end();
107
+ this.device = null;
108
+ }
109
+ if (this.remote) {
110
+ this.remote.destroy();
111
+ this.remote = null;
112
+ }
113
+ if (this.alexaSH3) {
114
+ await this.alexaSH3.destroy();
115
+ }
116
+ }
117
+ catch {
118
+ // ignore
119
+ }
120
+ callback();
121
+ },
122
+ message: async (obj) => {
123
+ if (obj) {
124
+ switch (obj.command) {
125
+ case 'update':
126
+ if (this.recalcTimeout) {
127
+ clearTimeout(this.recalcTimeout);
128
+ }
129
+ this.recalcTimeout = setTimeout(async () => {
130
+ this.recalcTimeout = null;
131
+ this.alexaSH2?.updateDevices(obj.message, async (analyseAddedId) => {
132
+ await this.setStateAsync('smart.updatesResult', analyseAddedId || '', true);
133
+ this.log.debug('Devices updated!');
134
+ await this.setStateAsync('smart.updates', true, true);
135
+ });
136
+ // this.alexaSH3 && this.alexaSH3.updateDevices(obj.message, async analyseAddedId => {
137
+ // await this.setStateAsync('smart.updatesResult', analyseAddedId || '', true);
138
+ // await this.setStateAsync('smart.updates3', true, true);
139
+ // });
140
+ if (this.alexaSH3) {
141
+ await this.alexaSH3.updateDevices();
142
+ await this.setStateAsync('smart.updates3', true, true);
143
+ }
144
+ this.googleHome?.updateDevices(async (analyseAddedId) => {
145
+ await this.setStateAsync('smart.updatesResult', analyseAddedId || '', true);
146
+ this.log.debug('GH Devices updated!');
147
+ await this.setStateAsync('smart.updatesGH', true, true);
148
+ });
149
+ }, 1000);
150
+ break;
151
+ case 'browse':
152
+ if (obj.callback) {
153
+ this.log.info('Request devices');
154
+ if (this.alexaSH2) {
155
+ this.alexaSH2.updateDevices(() => {
156
+ this.sendTo(obj.from, obj.command, this.alexaSH2.getDevices(), obj.callback);
157
+ void this.setState('smart.updates', false, true);
158
+ });
159
+ }
160
+ else {
161
+ this.sendTo(obj.from, obj.command, { error: 'not activated' }, obj.callback);
162
+ }
163
+ }
164
+ break;
165
+ case 'browse3':
166
+ if (obj.callback) {
167
+ this.log.info('Request V3 devices');
168
+ if (this.alexaSH3) {
169
+ const devices = await this.alexaSH3.getDevices();
170
+ this.sendTo(obj.from, obj.command, devices, obj.callback);
171
+ await this.setStateAsync('smart.updates3', false, true);
172
+ }
173
+ else {
174
+ this.sendTo(obj.from, obj.command, { error: 'not activated' }, obj.callback);
175
+ }
176
+ }
177
+ break;
178
+ case 'browseGH':
179
+ if (obj.callback) {
180
+ this.log.info('Request google home devices');
181
+ if (this.googleHome) {
182
+ this.googleHome.updateDevices(() => {
183
+ this.sendTo(obj.from, obj.command, this.googleHome.getDevices(), obj.callback);
184
+ void this.setStateAsync('smart.updatesGH', false, true);
185
+ });
186
+ }
187
+ else {
188
+ this.sendTo(obj.from, obj.command, { error: 'not activated' }, obj.callback);
189
+ }
190
+ }
191
+ break;
192
+ case 'browseAlisa':
193
+ if (obj.callback) {
194
+ this.log.info('Request Yandex Alice devices');
195
+ if (this.yandexAlisa) {
196
+ this.yandexAlisa.updateDevices(() => {
197
+ this.sendTo(obj.from, obj.command, this.yandexAlisa.getDevices(), obj.callback);
198
+ void this.setStateAsync('smart.updatesYA', false, true);
199
+ });
200
+ }
201
+ else {
202
+ this.sendTo(obj.from, obj.command, { error: 'not activated' }, obj.callback);
203
+ }
204
+ }
205
+ break;
206
+ case 'alexaCustomKnownDevices':
207
+ // Admin UI can request the known/discoveredAlexa devices used via Custom skill
208
+ // Allow setting the rooms of the devices and store in adapter config
209
+ // Restart adapter after change - or we also add a set message to the config
210
+ if (obj.callback) {
211
+ this.log.info('Request Alexa Custom known devices');
212
+ if (this.alexaCustom) {
213
+ const devices = this.alexaCustom.getKnownDevices();
214
+ this.sendTo(obj.from, obj.command, devices, obj.callback);
215
+ }
216
+ else {
217
+ this.sendTo(obj.from, obj.command, { error: 'not activated' }, obj.callback);
218
+ }
219
+ }
220
+ break;
221
+ case 'alexaCustomKnownUsers':
222
+ // Admin UI can request the known/discoveredAlexa users used via Custom skill
223
+ // Allow setting the names of the users and store in adapter config
224
+ // Restart adapter after change - or we also add a set message to the config
225
+ if (obj.callback) {
226
+ this.log.info('Request Alexa Custom known users');
227
+ if (this.alexaCustom) {
228
+ const users = this.alexaCustom.getKnownUsers();
229
+ this.sendTo(obj.from, obj.command, users, obj.callback);
230
+ }
231
+ else {
232
+ this.sendTo(obj.from, obj.command, { error: 'not activated' }, obj.callback);
233
+ }
234
+ }
235
+ break;
236
+ case 'private': {
237
+ if (typeof obj.message !== 'object') {
238
+ try {
239
+ obj.message = JSON.parse(obj.message);
240
+ }
241
+ catch (e) {
242
+ this.log.error(`Cannot parse object: ${e}`);
243
+ obj.callback &&
244
+ this.sendTo(obj.from, obj.command, { error: 'Invalid message format: cannot parse object' }, obj.callback);
245
+ return;
246
+ }
247
+ }
248
+ const response = await this.processMessage(obj.message.type, obj.message.request);
249
+ if (obj.callback) {
250
+ this.sendTo(obj.from, obj.command, response, obj.callback);
251
+ }
252
+ break;
253
+ }
254
+ case 'ifttt':
255
+ this.sendDataToIFTTT(obj.message);
256
+ break;
257
+ case 'alexaCustomResponse':
258
+ this.alexaCustom?.setResponse(obj.message);
259
+ break;
260
+ case 'debug':
261
+ this.alexaSH2?.getDebug((data) => this.sendTo(obj.from, obj.command, data, obj.callback));
262
+ break;
263
+ case 'getServiceEndpoint':
264
+ if (obj.callback) {
265
+ if (!this.urlKey) {
266
+ try {
267
+ this.urlKey = await this.readUrlKey();
268
+ }
269
+ catch {
270
+ try {
271
+ this.urlKey = await this.createUrlKey(this.config.login, this.config.pass);
272
+ }
273
+ catch (err) {
274
+ return (obj.callback &&
275
+ this.sendTo(obj.from, obj.command, { error: `Cannot get urlKey: ${err.toString()}` }, obj.callback));
276
+ }
277
+ }
278
+ }
279
+ const result = {
280
+ url: `https://service.iobroker.in/v1/iotService?key=${this.urlKey.key}&user=${encodeURIComponent(this.config.login)}`,
281
+ };
282
+ const serviceName = typeof obj.message === 'string' ? obj.message : obj.message?.serviceName;
283
+ if (serviceName) {
284
+ result.url += `&service=${encodeURIComponent(serviceName)}`;
285
+ result.stateID = `${this.namespace}.services.${serviceName}`;
286
+ }
287
+ if (obj.message?.data) {
288
+ result.data += `&data=${typeof obj.message.data === 'object' ? JSON.stringify(obj.message.data) : obj.message.data}`;
289
+ }
290
+ // check if the service name is in the white list
291
+ if (serviceName &&
292
+ this.config.allowedServices[0] !== '*' &&
293
+ !this.config.allowedServices.includes(serviceName.replace(/^custom_/, '')) &&
294
+ !ALLOWED_SERVICES.includes(serviceName)) {
295
+ result.warning = 'Service name is not in white list';
296
+ this.log.warn(`Service "${serviceName}" is not in allowed services list`);
297
+ }
298
+ if (obj.callback) {
299
+ this.sendTo(obj.from, obj.command, result, obj.callback);
300
+ }
301
+ }
302
+ break;
303
+ case 'sendNotification':
304
+ try {
305
+ const { message, title } = (0, notifications_1.buildMessageFromNotification)(obj.message);
306
+ await this.sendMessageToApp(JSON.stringify({ message, title }));
307
+ if (obj.callback) {
308
+ this.sendTo(obj.from, 'sendNotification', { sent: true }, obj.callback);
309
+ }
310
+ }
311
+ catch {
312
+ if (obj.callback) {
313
+ this.sendTo(obj.from, 'sendNotification', { sent: false }, obj.callback);
314
+ }
315
+ }
316
+ break;
317
+ default:
318
+ this.log.warn(`Unknown command: ${obj.command}`);
319
+ break;
320
+ }
321
+ }
322
+ },
323
+ ready: () => this.main()
324
+ .then(() => { })
325
+ .catch(error => {
326
+ this.log.error(`Error in main: ${error.toString()}`);
327
+ }),
328
+ });
329
+ // warning: `this.log = obj => console.log(obj)` does not implemented. Only this.on('log', obj => console.log(obj))
330
+ this.on('log', obj => this.remote?.onLog(obj));
331
+ }
332
+ sendDataToIFTTT(obj) {
333
+ if (!obj) {
334
+ this.log.warn('No data to send to IFTTT');
335
+ return;
336
+ }
337
+ if (!this.config.iftttKey && (typeof obj !== 'object' || !obj.key)) {
338
+ this.log.warn('No IFTTT key is defined');
339
+ return;
340
+ }
341
+ let url;
342
+ let data;
343
+ if (typeof obj !== 'object') {
344
+ url = `https://maker.ifttt.com/trigger/state/with/key/${this.config.iftttKey}`;
345
+ data = {
346
+ value1: `${this.namespace}.services.ifttt`,
347
+ value2: obj,
348
+ };
349
+ }
350
+ else if (obj.event) {
351
+ const event = obj.event;
352
+ const key = obj.key;
353
+ delete obj.event;
354
+ delete obj.key;
355
+ url = `https://maker.ifttt.com/trigger/${event}/with/key/${key || this.config.iftttKey}`;
356
+ data = obj;
357
+ }
358
+ else if (obj.val === undefined) {
359
+ return this.log.warn('No value is defined');
360
+ }
361
+ else {
362
+ obj.id = obj.id || `${this.namespace}.services.ifttt`;
363
+ url = `https://maker.ifttt.com/trigger/state/with/key/${this.config.iftttKey}`;
364
+ data = {
365
+ value1: obj.id,
366
+ value2: obj.val,
367
+ value3: obj.ack,
368
+ };
369
+ }
370
+ if (url) {
371
+ axios_1.default
372
+ .post(url, data, {
373
+ timeout: 15000,
374
+ validateStatus: status => status < 400,
375
+ })
376
+ .then(response => this.log.debug(`Response from IFTTT: ${JSON.stringify(response.data)}`))
377
+ .catch(error => {
378
+ if (error.response) {
379
+ this.log.warn(`Response from IFTTT: ${error.response.data ? JSON.stringify(error.response.data) : error.response.status}`);
380
+ }
381
+ else {
382
+ this.log.warn(`Response from IFTTT: ${error.code}`);
383
+ }
384
+ });
385
+ }
386
+ else {
387
+ this.log.warn(`Invalid request to IFTTT: ${JSON.stringify(obj)}`);
388
+ }
389
+ }
390
+ /**
391
+ * Send a message to the ioBroker Visu App by using the app-message endpoint (which then forwards it to the app via FCM)
392
+ *
393
+ * @param message either a json string or the message itself, if the message itself the other props will be taken from the adapter states
394
+ */
395
+ async sendMessageToApp(message) {
396
+ if (!message) {
397
+ throw new Error('Empty message');
398
+ }
399
+ const trimmedMessage = message.toString().trim();
400
+ let json;
401
+ if (trimmedMessage.startsWith('{') && trimmedMessage.endsWith('}')) {
402
+ try {
403
+ json = JSON.parse(trimmedMessage);
404
+ }
405
+ catch {
406
+ this.log.warn(`Cannot parse message: ${trimmedMessage}`);
407
+ json = null;
408
+ }
409
+ }
410
+ else {
411
+ json = null;
412
+ }
413
+ if (!json) {
414
+ // take expires
415
+ const ttlSecondsState = await this.getStateAsync(`${this.namespace}.app.expire`);
416
+ const priorityState = await this.getStateAsync(`${this.namespace}.app.priority`);
417
+ const titleState = await this.getStateAsync(`${this.namespace}.app.title`);
418
+ const priorityVal = priorityState?.val;
419
+ json = {
420
+ message: message.toString(),
421
+ priority: priorityVal === '1' || priorityVal === 'high' || priorityVal === true ? 'high' : undefined,
422
+ ttlSeconds: parseInt(ttlSecondsState?.val, 0) || undefined,
423
+ title: (titleState?.val || 'ioBroker').toString(),
424
+ };
425
+ }
426
+ else {
427
+ if (json.expire) {
428
+ json.ttlSeconds = json.expire;
429
+ delete json.expire;
430
+ }
431
+ }
432
+ json.ttlSeconds = parseInt(json.ttlSeconds, 0) || undefined;
433
+ if (json.ttlSeconds && json.ttlSeconds > 3_600 * 48) {
434
+ json.ttlSeconds = 3_600 * 48;
435
+ }
436
+ if (!json.message) {
437
+ throw new Error('Empty message');
438
+ }
439
+ const response = await axios_1.default.post('https://app-message.iobroker.in/', json, {
440
+ headers: {
441
+ 'Content-Type': 'application/json',
442
+ Authorization: `Bearer ${Buffer.from(`${this.config.login}:${this.config.pass}`).toString('base64')}`,
443
+ },
444
+ timeout: 5_000,
445
+ validateStatus: status => status < 400,
446
+ });
447
+ await this.setState('app.message', message, true);
448
+ this.log.debug(`Message sent: ${JSON.stringify(response.data)}`);
449
+ }
450
+ async controlState(id, data) {
451
+ id ||= 'services.ifttt';
452
+ if (typeof data === 'object') {
453
+ if (data.id) {
454
+ if (data.id === `${this.namespace}.services.ifttt`) {
455
+ data.ack = true;
456
+ }
457
+ if (data.val === undefined) {
458
+ throw new Error('No value set');
459
+ }
460
+ const obj = await this.getForeignObjectAsync(data.id);
461
+ if (!obj || !obj.common) {
462
+ throw new Error(`Unknown ID: ${data.id}`);
463
+ }
464
+ else {
465
+ if (typeof data.val === 'string') {
466
+ data.val = data.val.replace(/^@ifttt\s?/, '');
467
+ }
468
+ if (obj.common.type === 'boolean') {
469
+ data.val =
470
+ data.val === true ||
471
+ data.val === 'true' ||
472
+ data.val === 'on' ||
473
+ data.val === 'ON' ||
474
+ data.val === 1 ||
475
+ data.val === '1';
476
+ }
477
+ else if (obj.common.type === 'number') {
478
+ data.val = parseFloat(data.val);
479
+ }
480
+ await this.setForeignStateAsync(data.id, data.val, data.ack);
481
+ }
482
+ }
483
+ else if (data.val !== undefined) {
484
+ if (typeof data.val === 'string') {
485
+ data.val = data.val.replace(/^@ifttt\s?/, '');
486
+ }
487
+ await this.setStateAsync(id, data.val, data.ack !== undefined ? data.ack : true);
488
+ }
489
+ else {
490
+ await this.setStateAsync(id, JSON.stringify(data), true);
491
+ }
492
+ }
493
+ else {
494
+ if (typeof data === 'string') {
495
+ data = data.replace(/^@ifttt\s?/, '');
496
+ }
497
+ await this.setStateAsync(id, data, true);
498
+ }
499
+ }
500
+ async processIfttt(data) {
501
+ this.log.debug(`Received IFTTT object: ${JSON.stringify(data)}`);
502
+ let id;
503
+ let dataObj = null;
504
+ // >If data is object with id and data property
505
+ if (typeof data === 'object' && data.id && data.data !== undefined) {
506
+ id = data.id;
507
+ if (typeof data.data === 'string' && data.data[0] === '{') {
508
+ try {
509
+ dataObj = JSON.parse(data.data);
510
+ }
511
+ catch {
512
+ this.log.debug(`Cannot parse: ${data.data}`);
513
+ dataObj = data;
514
+ }
515
+ }
516
+ else {
517
+ dataObj = data.data;
518
+ }
519
+ }
520
+ else if (typeof data === 'string' && data[0] === '{') {
521
+ // If data is string and starts with {
522
+ try {
523
+ dataObj = JSON.parse(data);
524
+ if (typeof dataObj.id === 'string') {
525
+ id = dataObj.id;
526
+ if (dataObj.data) {
527
+ dataObj = dataObj.data;
528
+ }
529
+ }
530
+ }
531
+ catch {
532
+ this.log.debug(`Cannot parse: ${JSON.stringify(data)}`);
533
+ }
534
+ }
535
+ else {
536
+ dataObj = data;
537
+ }
538
+ if (id) {
539
+ let obj = await this.getForeignObjectAsync(id);
540
+ if (!obj) {
541
+ const newId = `${this.namespace}.services.${id}`;
542
+ obj = await this.getForeignObjectAsync(newId);
543
+ if (!obj) {
544
+ // create state
545
+ await this.setObjectNotExistsAsync(`services.${id}`, {
546
+ type: 'state',
547
+ common: {
548
+ name: 'IFTTT value',
549
+ write: false,
550
+ role: 'state',
551
+ read: true,
552
+ type: 'mixed',
553
+ desc: 'Custom state',
554
+ },
555
+ native: {},
556
+ });
557
+ id = newId;
558
+ }
559
+ }
560
+ }
561
+ await this.controlState(id || null, dataObj || data);
562
+ }
563
+ onDisconnect(event) {
564
+ const now = Date.now();
565
+ if (now - this.connectStarted < 500) {
566
+ this.log.warn('Looks like your connection certificates are invalid. Please renew them via configuration dialog.');
567
+ }
568
+ if (typeof event === 'string') {
569
+ if (event.toLowerCase().includes('duplicate')) {
570
+ // disable adapter
571
+ this.log.error(`Two devices are trying to connect with the same iot account. This is not allowed. Stopping`);
572
+ void this.getForeignObjectAsync(`system.adapter.${this.namespace}`).then(obj => {
573
+ if (obj) {
574
+ obj.common.enabled = false;
575
+ return this.setForeignObjectAsync(obj._id, obj);
576
+ }
577
+ });
578
+ }
579
+ this.log.info(`Connection changed: ${event}`);
580
+ }
581
+ else {
582
+ this.log.info('Connection changed: disconnect');
583
+ }
584
+ if (this.connectedOwn) {
585
+ this.log.info('Connection lost');
586
+ this.connectedOwn = false;
587
+ void this.setState('info.connection', false, true);
588
+ }
589
+ this.remote?.onCloudDisconnect();
590
+ }
591
+ onConnect(clientId) {
592
+ if (!this.connectedOwn) {
593
+ this.log.info(`Connection changed: connect "${clientId}"`);
594
+ this.connectedOwn = true;
595
+ void this.setState('info.connection', this.connectedOwn, true);
596
+ // setTimeout(() => {
597
+ // device.publish(`response/${clientId}/stateChange`, JSON.stringify({alive: true}), {qos: 0}, (error, result) => {
598
+ // console.log(`Published alive: ${result}, ${error}`);
599
+ // });
600
+ // }, 2000);
601
+ }
602
+ else {
603
+ this.log.info('Connection not changed: was connected');
604
+ }
605
+ }
606
+ encryptOwn(secret, value) {
607
+ let result = '';
608
+ for (let i = 0; i < value.length; i++) {
609
+ result += String.fromCharCode(secret[i % secret.length].charCodeAt(0) ^ value.charCodeAt(i));
610
+ }
611
+ return `base64:${Buffer.from(result).toString('base64')}`;
612
+ }
613
+ decryptOwn(secret, value) {
614
+ if (value.startsWith('base64:')) {
615
+ try {
616
+ value = Buffer.from(value.substring(7), 'base64').toString('ascii');
617
+ }
618
+ catch (e) {
619
+ this.log.error(`Cannot decrypt key: ${e}`);
620
+ }
621
+ }
622
+ let result = '';
623
+ for (let i = 0; i < value.length; i++) {
624
+ result += String.fromCharCode(secret[i % secret.length].charCodeAt(0) ^ value.charCodeAt(i));
625
+ }
626
+ return result;
627
+ }
628
+ async readUrlKey() {
629
+ const key = await this.getStateAsync('certs.urlKey');
630
+ if (!key?.val) {
631
+ throw new Error('Not exists');
632
+ }
633
+ else {
634
+ return { key: key.val };
635
+ }
636
+ }
637
+ async createUrlKey(login, pass) {
638
+ this.log.debug('Fetching URL key...');
639
+ let response;
640
+ try {
641
+ response = await axios_1.default.get(`https://generate-key.iobroker.in/v1/generateUrlKey?user=${encodeURIComponent(login)}&pass=${encodeURIComponent(pass)}&version=${this.version}`, {
642
+ timeout: 15000,
643
+ validateStatus: status => status < 400,
644
+ });
645
+ }
646
+ catch (error) {
647
+ if (error.response) {
648
+ if (error.response.status === 401) {
649
+ this.log.error(`Cannot create URL key because of invalid user or password`);
650
+ }
651
+ throw new Error(error.response.data);
652
+ }
653
+ else {
654
+ throw error;
655
+ }
656
+ }
657
+ if (response.data && response.data.error) {
658
+ this.log.error(`Cannot fetch URL key: ${JSON.stringify(response.data.error)}`);
659
+ throw new Error(response.data);
660
+ }
661
+ else if (response.data && response.data.key) {
662
+ await this.setStateAsync('certs.urlKey', response.data.key, true);
663
+ return { key: response.data.key };
664
+ }
665
+ else {
666
+ this.log.error(`Cannot fetch URL key: ${JSON.stringify(response.data)}`);
667
+ throw new Error(response.data);
668
+ }
669
+ }
670
+ async readCertificates() {
671
+ let privateKey;
672
+ let certificate;
673
+ try {
674
+ privateKey = await this.getStateAsync('certs.private');
675
+ certificate = await this.getStateAsync('certs.certificate');
676
+ }
677
+ catch {
678
+ throw new Error('Not exists');
679
+ }
680
+ if (!certificate?.val || !privateKey?.val) {
681
+ throw new Error('Not exists');
682
+ }
683
+ else {
684
+ return {
685
+ private: this.decryptOwn(this.secret, privateKey.val),
686
+ certificate: this.decryptOwn(this.secret, certificate.val),
687
+ };
688
+ }
689
+ }
690
+ async writeKeys(data) {
691
+ await this.setStateAsync('certs.private', this.encryptOwn(this.secret, data.keyPair.PrivateKey), true);
692
+ await this.setStateAsync('certs.public', this.encryptOwn(this.secret, data.keyPair.PublicKey), true);
693
+ await this.setStateAsync('certs.certificate', this.encryptOwn(this.secret, data.certificatePem), true);
694
+ await this.setStateAsync('certs.id', data.certificateId, true);
695
+ }
696
+ async fetchCertificates(login, pass, _forceUserCreation) {
697
+ const state = await this.getStateAsync('certs.forceUserCreate');
698
+ const forceUserCreation = state?.val;
699
+ if (forceUserCreation) {
700
+ await this.setStateAsync('certs.forceUserCreate', false, true);
701
+ }
702
+ this.log.debug('Fetching certificates...');
703
+ let response;
704
+ try {
705
+ response = await axios_1.default.get(`https://create-user.iobroker.in/v1/createUser?user=${encodeURIComponent(login)}&pass=${encodeURIComponent(pass)}&forceRecreate=${forceUserCreation}&version=${this.version}`, {
706
+ timeout: 15000,
707
+ validateStatus: status => status < 400,
708
+ });
709
+ }
710
+ catch (error) {
711
+ if (error.response) {
712
+ if (error.response.status === 401) {
713
+ this.log.error(`Cannot fetch connection certificates because of invalid user or password`);
714
+ }
715
+ else {
716
+ this.log.error(`Cannot fetch connection certificates: ${JSON.stringify(error.response.data)}`);
717
+ }
718
+ throw new Error(error.response.data);
719
+ }
720
+ else {
721
+ this.log.error(`Cannot fetch connection certificates: ${JSON.stringify(error.code)}`);
722
+ throw error;
723
+ }
724
+ }
725
+ if (response?.data?.certificates) {
726
+ const awsCertificates = response.data.certificates;
727
+ await this.writeKeys(awsCertificates);
728
+ return {
729
+ private: awsCertificates.keyPair.PrivateKey,
730
+ certificate: awsCertificates.certificatePem,
731
+ };
732
+ }
733
+ this.log.error(`Cannot fetch connection certificates: ${JSON.stringify(response.data)}`);
734
+ throw new Error(response.data);
735
+ }
736
+ async processMessage(type, request) {
737
+ if (request instanceof Buffer) {
738
+ request = request.toString();
739
+ }
740
+ this.log.debug(`Data: ${JSON.stringify(request)}`);
741
+ if (!request || !type) {
742
+ return { error: 'invalid request' };
743
+ }
744
+ if (type.startsWith('remote')) {
745
+ const start = Date.now();
746
+ if (this.remote) {
747
+ return this.remote
748
+ .process(request, type)
749
+ .then(response => {
750
+ if (response !== NONE) {
751
+ this.log.debug(`[REMOTE] Response in: ${Date.now() - start}ms (Length: ${Array.isArray(response) ? `A ${response.length}` : JSON.stringify(response).length}) for ${request}`);
752
+ }
753
+ return response;
754
+ })
755
+ .catch(err => {
756
+ this.log.error(`Error in processing of remote request: ${err.toString()}`);
757
+ return NONE;
758
+ });
759
+ }
760
+ this.log.error(`Received command, but remote already closed.`);
761
+ }
762
+ else if (type.startsWith('nightscout')) {
763
+ if (this.config.nightscout) {
764
+ const state = await this.getForeignStateAsync(`system.adapter.nightscout.${this.config.nightscout}.alive`);
765
+ if (state?.val) {
766
+ return this.sendToAsync(`nightscout.${this.config.nightscout}`, 'send', request);
767
+ }
768
+ return { error: `nightscout.${this.config.nightscout} is offline` };
769
+ }
770
+ return { error: 'Service is disabled' };
771
+ }
772
+ else if (type.startsWith('alexa')) {
773
+ if (typeof request === 'string') {
774
+ try {
775
+ request = JSON.parse(request);
776
+ }
777
+ catch {
778
+ this.log.error(`Cannot parse request: ${JSON.stringify(request)}`);
779
+ return { error: 'Cannot parse request' };
780
+ }
781
+ }
782
+ this.log.debug(`${Date.now()} ALEXA: ${JSON.stringify(request)}`);
783
+ if (request?.directive) {
784
+ if (this.alexaSH3) {
785
+ try {
786
+ const response = await this.alexaSH3.process(request);
787
+ if (request.directive.header.messageId != response.event.header.messageId) {
788
+ throw new Error('Incoming and outgoing header message IDs are not equal!');
789
+ }
790
+ return response;
791
+ }
792
+ catch {
793
+ this.log.error(`Cannot parse request: ${request}`);
794
+ }
795
+ }
796
+ return { error: 'Service is disabled' };
797
+ }
798
+ else if (request?.error) {
799
+ // answer from alexa3 events cloud actually just show it in log
800
+ if (request.error.includes('You have no iobroker.iot license')) {
801
+ // pause for 30 minutes send of the events
802
+ this.alexaSH3?.pauseEvents();
803
+ }
804
+ this.log.error(`Error from Alexa events cloud: ${request.error}`);
805
+ }
806
+ else if (request && !request.header) {
807
+ if (this.alexaCustom) {
808
+ return this.alexaCustom.process(request, this.config.amazonAlexa);
809
+ }
810
+ return { error: 'Service is disabled' };
811
+ }
812
+ else {
813
+ if (this.alexaSH2) {
814
+ return this.alexaSH2.process(request, this.config.amazonAlexa);
815
+ }
816
+ return { error: 'Service is disabled' };
817
+ }
818
+ }
819
+ else if (type.startsWith('ifttt')) {
820
+ try {
821
+ if (typeof request === 'object') {
822
+ request = JSON.stringify(request);
823
+ }
824
+ else {
825
+ request = request.toString();
826
+ }
827
+ }
828
+ catch {
829
+ this.log.error(`Cannot parse request: ${request}`);
830
+ return { error: 'Cannot parse request' };
831
+ }
832
+ await this.processIfttt(request);
833
+ return NONE;
834
+ }
835
+ else if (type.startsWith('ghome')) {
836
+ if (typeof request === 'string') {
837
+ try {
838
+ request = JSON.parse(request);
839
+ }
840
+ catch {
841
+ this.log.error(`Cannot parse request: ${request}`);
842
+ return { error: 'Cannot parse request' };
843
+ }
844
+ }
845
+ if (this.googleHome) {
846
+ return this.googleHome.process(request, this.config.googleHome);
847
+ }
848
+ return { error: 'Service is disabled' };
849
+ }
850
+ else if (type.startsWith('alisa')) {
851
+ if (typeof request === 'string') {
852
+ try {
853
+ request = JSON.parse(request);
854
+ }
855
+ catch {
856
+ this.log.error(`Cannot parse request: ${request}`);
857
+ return { error: 'Cannot parse request' };
858
+ }
859
+ }
860
+ this.log.debug(`${Date.now()} ALISA: ${JSON.stringify(request)}`);
861
+ if (this.yandexAlisa) {
862
+ return this.yandexAlisa.process(request, this.config.yandexAlisa);
863
+ }
864
+ return { error: 'Service is disabled' };
865
+ }
866
+ else {
867
+ let isCustom = false;
868
+ let _type = type;
869
+ if (_type.match(/^custom_/)) {
870
+ _type = _type.substring(7);
871
+ isCustom = true;
872
+ }
873
+ if (_type === 'visu') {
874
+ this.log.debug(`Received visu command: ${JSON.stringify(request)}`);
875
+ if (typeof request === 'object') {
876
+ request = JSON.stringify(request);
877
+ }
878
+ else {
879
+ request = request.toString();
880
+ }
881
+ try {
882
+ const visuData = JSON.parse(request);
883
+ if (visuData.presence) {
884
+ await (0, visuApp_1.handleGeofenceData)(visuData, this);
885
+ }
886
+ if (visuData.devices) {
887
+ await (0, visuApp_1.handleDevicesData)(visuData, this);
888
+ }
889
+ if (visuData.command === 'getInstances') {
890
+ const res = await (0, visuApp_1.handleGetInstances)(visuData, this);
891
+ return { result: 'Ok', ...res };
892
+ }
893
+ if (visuData.command === 'sendToAdapter') {
894
+ return await (0, visuApp_1.handleSendToAdapter)(visuData, this);
895
+ }
896
+ }
897
+ catch (e) {
898
+ this.log.error(`Could not handle data "${request}" by Visu App: ${e.message}`);
899
+ return { error: e.message };
900
+ }
901
+ return { result: 'Ok' };
902
+ }
903
+ else if (this.config.allowedServices[0] === '*' ||
904
+ this.config.allowedServices.includes(_type) ||
905
+ ALLOWED_SERVICES.includes(_type)) {
906
+ if (typeof request === 'object') {
907
+ request = JSON.stringify(request);
908
+ }
909
+ else {
910
+ request = request.toString();
911
+ }
912
+ if (SPECIAL_ADAPTERS.includes(_type)) {
913
+ try {
914
+ await this.setStateAsync(`services.${_type}`, request, true);
915
+ }
916
+ catch (err) {
917
+ return { result: err };
918
+ }
919
+ return { result: 'Ok' };
920
+ }
921
+ else if (type.startsWith('text2command')) {
922
+ if (this.config.text2command !== undefined && this.config.text2command !== '') {
923
+ try {
924
+ await this.setForeignStateAsync(`text2command.${this.config.text2command}.text`, request);
925
+ }
926
+ catch (err) {
927
+ return { result: err };
928
+ }
929
+ return { result: 'Ok' };
930
+ }
931
+ this.log.warn('Received service text2command, but instance is not defined');
932
+ return { result: 'but instance is not defined' };
933
+ }
934
+ else if (type.startsWith('simpleApi')) {
935
+ return { result: 'not implemented' };
936
+ }
937
+ else if (isCustom) {
938
+ let obj;
939
+ try {
940
+ obj = await this.getObjectAsync(`services.custom_${_type}`);
941
+ }
942
+ catch (e) {
943
+ this.log.error(`Cannot get object services.custom_${_type}: ${e}`);
944
+ }
945
+ if (!obj) {
946
+ try {
947
+ await this.setObjectNotExistsAsync(`services.custom_${_type}`, {
948
+ _id: `${this.namespace}.services.custom_${_type}`,
949
+ type: 'state',
950
+ common: {
951
+ name: `Service for ${_type}`,
952
+ write: false,
953
+ read: true,
954
+ type: 'mixed',
955
+ role: 'value',
956
+ },
957
+ native: {},
958
+ });
959
+ await this.setStateAsync(`services.custom_${_type}`, request, true);
960
+ }
961
+ catch (err) {
962
+ this.log.error(`Cannot control .services.custom_${_type}: ${JSON.stringify(err)}`);
963
+ return { error: err };
964
+ }
965
+ }
966
+ else {
967
+ await this.setStateAsync(`services.custom_${_type}`, request, true);
968
+ return { result: 'Ok' };
969
+ }
970
+ }
971
+ else {
972
+ this.log.warn(`Received service "${type}", but it is not allowed`);
973
+ return { error: 'not allowed' };
974
+ }
975
+ }
976
+ else {
977
+ this.log.warn(`Received service "${type}", but it is not found in whitelist`);
978
+ return { error: 'Unknown service' };
979
+ }
980
+ }
981
+ this.log.warn(`Received message of unknown type: ${type}`);
982
+ return { error: 'Unknown message type' };
983
+ }
984
+ closeDevice() {
985
+ return new Promise(resolve => {
986
+ if (this.device) {
987
+ try {
988
+ this.device.end(true, () => {
989
+ this.device = null;
990
+ resolve();
991
+ });
992
+ }
993
+ catch {
994
+ this.device = null;
995
+ resolve();
996
+ }
997
+ }
998
+ else {
999
+ resolve();
1000
+ }
1001
+ });
1002
+ }
1003
+ async startDevice(clientId, login, password, retry) {
1004
+ retry ||= 0;
1005
+ let certs;
1006
+ try {
1007
+ certs = await this.readCertificates();
1008
+ }
1009
+ catch (error) {
1010
+ if (error.message === 'Not exists') {
1011
+ try {
1012
+ certs = await this.fetchCertificates(login, password);
1013
+ }
1014
+ catch {
1015
+ // ignore
1016
+ }
1017
+ }
1018
+ else {
1019
+ throw error;
1020
+ }
1021
+ }
1022
+ // destroy the old device
1023
+ await this.closeDevice();
1024
+ if (!certs) {
1025
+ return this.log.error(`Cannot read connection certificates`);
1026
+ }
1027
+ try {
1028
+ this.connectStarted = Date.now();
1029
+ this.device = new aws_iot_device_sdk_1.device({
1030
+ privateKey: Buffer.from(certs.private),
1031
+ clientCert: Buffer.from(certs.certificate),
1032
+ caCert: (0, node_fs_1.readFileSync)(`${__dirname}/../keys/root-CA.crt`),
1033
+ clientId,
1034
+ username: 'ioBroker',
1035
+ host: this.config.cloudUrl,
1036
+ debug: !!this.config.debug,
1037
+ baseReconnectTimeMs: 5000,
1038
+ keepalive: 60,
1039
+ });
1040
+ this.remote?.registerDevice(this.device);
1041
+ this.device.subscribe(`command/${clientId}/#`);
1042
+ this.device.on('connect', () => this.onConnect(clientId));
1043
+ this.device.on('close', () => this.onDisconnect());
1044
+ this.device.on('reconnect', () => this.log.debug('reconnect'));
1045
+ this.device.on('offline', () => this.log.debug('offline'));
1046
+ this.device.on('error', error => {
1047
+ const errorTxt = (error?.message && JSON.stringify(error.message)) || JSON.stringify(error);
1048
+ this.log.error(`Error by device connection: ${errorTxt}`);
1049
+ // restart the iot device if DNS cannot be resolved
1050
+ if (errorTxt.includes('EAI_AGAIN')) {
1051
+ this.log.error(`DNS name of ${this.config.cloudUrl} cannot be resolved: connection will be retried in 10 seconds.`);
1052
+ setTimeout(() => this.startDevice(clientId, login, password), 10000);
1053
+ }
1054
+ });
1055
+ this.device.on('message', async (topic, request) => {
1056
+ this.log.debug(`Request ${topic}`);
1057
+ if (topic.startsWith(`command/${clientId}/`)) {
1058
+ const type = topic.substring(clientId.length + 9); // 9 === 'command//'.length
1059
+ try {
1060
+ const response = await this.processMessage(type, request);
1061
+ if (this.common.loglevel === 'debug' && !type.startsWith('remote')) {
1062
+ this.log.debug(`Response: ${JSON.stringify(response)}`);
1063
+ }
1064
+ if (this.device && response !== NONE) {
1065
+ // It is a big file - send in trunks
1066
+ if (Array.isArray(response)) {
1067
+ try {
1068
+ for (let m = 0; m < response.length; m++) {
1069
+ const trunk = response[m];
1070
+ await new Promise((resolve, reject) => this.device.publish(`response/${clientId}/${type}`, typeof trunk !== 'string' ? JSON.stringify(trunk) : trunk, { qos: 1 }, error => {
1071
+ if (error) {
1072
+ reject(error);
1073
+ }
1074
+ else {
1075
+ resolve();
1076
+ }
1077
+ }));
1078
+ }
1079
+ }
1080
+ catch (err) {
1081
+ this.log.error(`[REMOTE] Cannot send packet: ${err}`);
1082
+ }
1083
+ }
1084
+ else {
1085
+ this.log.debug(`[REMOTE] Send response to 'response/${clientId}/${type}: ${JSON.stringify(response)}`);
1086
+ const msg = JSON.stringify(response);
1087
+ if (msg && msg.length > MAX_IOT_MESSAGE_LENGTH) {
1088
+ const packed = (0, node_zlib_1.deflateSync)(msg).toString('base64');
1089
+ this.log.debug(`[REMOTE] Content was packed from ${msg.length} bytes to ${packed.length} bytes`);
1090
+ if (packed.length > MAX_IOT_MESSAGE_LENGTH) {
1091
+ this.log.warn(`[REMOTE] Content was packed to ${packed.length} bytes which is still near/over the message limit!`);
1092
+ }
1093
+ this.device.publish(`response/${clientId}/${type}`, packed);
1094
+ }
1095
+ else {
1096
+ // console.log(`Publish to "response/${clientId}/${type}": ${msg}`);
1097
+ this.device.publish(`response/${clientId}/${type}`, msg);
1098
+ }
1099
+ }
1100
+ }
1101
+ }
1102
+ catch (error) {
1103
+ this.log.debug(`Error processing request ${topic}`);
1104
+ this.log.debug(`${error}`);
1105
+ }
1106
+ }
1107
+ });
1108
+ }
1109
+ catch (error) {
1110
+ if (error && typeof error === 'object' && error.message) {
1111
+ this.log.error(`Cannot read connection certificates: ${error.message}`);
1112
+ }
1113
+ else {
1114
+ this.log.error(`Cannot read connection certificates: ${JSON.stringify(error)} / ${error && error.toString()}`);
1115
+ }
1116
+ if ((error === 'timeout' || error.message?.includes('timeout')) && retry < 10) {
1117
+ setTimeout(() => this.startDevice(clientId, login, password, retry + 1), 10000);
1118
+ }
1119
+ }
1120
+ }
1121
+ async updateNightscoutSecret() {
1122
+ if (!this.config.nightscout) {
1123
+ return;
1124
+ }
1125
+ const email = this.config.login.replace(/[^\w\d-_]/g, '_');
1126
+ const secret = this.config.nightscoutPass;
1127
+ const apiSecret = email + (secret ? `-${secret}` : '');
1128
+ const URL = `https://generate-key.iobroker.in/v1/generateUrlKey?user=${encodeURIComponent(this.config.login)}&pass=${encodeURIComponent(this.config.pass)}&apisecret=${encodeURIComponent(apiSecret)}`;
1129
+ let response;
1130
+ try {
1131
+ response = await axios_1.default.get(URL, {
1132
+ timeout: 15000,
1133
+ validateStatus: status => status < 400,
1134
+ });
1135
+ if (response.data.error) {
1136
+ this.log.error(`Api-Secret cannot be updated: ${response.data.error}`);
1137
+ }
1138
+ else {
1139
+ this.log.debug(`Api-Secret updated: ${JSON.stringify(response.data)}`);
1140
+ }
1141
+ }
1142
+ catch (error) {
1143
+ if (error.response) {
1144
+ this.log.warn(`Cannot update api-secret: ${error.response.data ? JSON.stringify(error.response.data) : error.response.status}`);
1145
+ }
1146
+ else {
1147
+ this.log.warn(`Cannot update api-secret: ${error.code}`);
1148
+ }
1149
+ }
1150
+ }
1151
+ async createStateForAdapter(adapterName) {
1152
+ // find any instance of this adapter
1153
+ const instances = await this.getObjectViewAsync('system', 'instance', {
1154
+ startkey: `system.adapter.${adapterName}.`,
1155
+ endkey: `system.adapter.${adapterName}.\u9999`,
1156
+ });
1157
+ if (instances?.rows?.length) {
1158
+ let obj;
1159
+ try {
1160
+ obj = await this.getObjectAsync(`service.${adapterName}`);
1161
+ }
1162
+ catch {
1163
+ // ignore
1164
+ }
1165
+ if (!obj) {
1166
+ try {
1167
+ await this.setForeignObjectAsync(`${this.namespace}.services.${adapterName}`, {
1168
+ type: 'state',
1169
+ common: {
1170
+ name: `Service for ${adapterName}`,
1171
+ write: false,
1172
+ read: true,
1173
+ type: 'mixed',
1174
+ role: 'value',
1175
+ },
1176
+ native: {},
1177
+ });
1178
+ }
1179
+ catch {
1180
+ // ignore
1181
+ }
1182
+ }
1183
+ }
1184
+ else {
1185
+ try {
1186
+ // delete if object exists
1187
+ const obj = await this.getObjectAsync(`service.${adapterName}`);
1188
+ if (obj) {
1189
+ await this.delObjectAsync(`service.${adapterName}`);
1190
+ }
1191
+ }
1192
+ catch {
1193
+ // ignore
1194
+ }
1195
+ }
1196
+ }
1197
+ async main() {
1198
+ if (this.config.googleHome === undefined) {
1199
+ this.config.googleHome = false;
1200
+ }
1201
+ if (this.config.amazonAlexa === undefined) {
1202
+ this.config.amazonAlexa = true;
1203
+ }
1204
+ if (this.config.yandexAlisa === undefined) {
1205
+ this.config.yandexAlisa = false;
1206
+ }
1207
+ this.config.pingTimeout = parseInt(this.config.pingTimeout, 10) || 5000;
1208
+ if (this.config.pingTimeout < 3000) {
1209
+ this.config.pingTimeout = 3000;
1210
+ }
1211
+ if (this.config.deviceOffLevel === undefined) {
1212
+ this.config.deviceOffLevel = 30;
1213
+ }
1214
+ if (this.config.login !== (this.config.login || '').trim().toLowerCase()) {
1215
+ this.log.error('Please write your login only in lowercase!');
1216
+ }
1217
+ if (!this.config.login || !this.config.pass) {
1218
+ return this.log.error('No cloud credentials found. Please get one on https://iobroker.pro');
1219
+ }
1220
+ let systemConfig = await this.getForeignObjectAsync('system.config');
1221
+ if (!systemConfig) {
1222
+ this.log.warn('Object system.config not found. Please check your installation!');
1223
+ systemConfig = { common: {} };
1224
+ }
1225
+ // create service state for netatmo if any instance exists
1226
+ for (let a = 0; a < SPECIAL_ADAPTERS.length; a++) {
1227
+ await this.createStateForAdapter(SPECIAL_ADAPTERS[a]);
1228
+ }
1229
+ this.secret = systemConfig?.native?.secret || 'Zgfr56gFe87jJOM';
1230
+ this.config.pass = this.decryptOwn(this.secret, this.config.pass);
1231
+ this.config.deviceOffLevel = parseFloat(this.config.deviceOffLevel) || 0;
1232
+ this.config.concatWord = (this.config.concatWord || '').toString().trim();
1233
+ this.config.apikey = (this.config.apikey || '').trim();
1234
+ this.config.replaces = this.config.replaces ? this.config.replaces.split(',') : null;
1235
+ this.config.cloudUrl = (this.config.cloudUrl || '').toString();
1236
+ this.config.nightscout = this.config.nightscout || '';
1237
+ if (this.config.replaces) {
1238
+ const text = [];
1239
+ for (let r = 0; r < this.config.replaces.length; r++) {
1240
+ text.push(`"${this.config.replaces[r]}"`);
1241
+ }
1242
+ this.log.debug(`Following strings will be replaced in names: ${text.join(', ')}`);
1243
+ }
1244
+ if (this.config.amazonAlexa) {
1245
+ this.alexaSH2 = new alexaSmartHomeV2_1.default(this);
1246
+ this.alexaCustom = new alexaCustom_1.default(this);
1247
+ }
1248
+ if (this.config.yandexAlisa) {
1249
+ this.yandexAlisa = new alisa_1.default(this);
1250
+ }
1251
+ this.remote = new remote_1.default(this, this.config.login.replace(/[^-_:a-zA-Z1-9]/g, '_'));
1252
+ this.config.allowedServices = (this.config.allowedServices || '')
1253
+ .split(/[,\s]+/)
1254
+ .map(s => s.trim())
1255
+ .filter(s => s);
1256
+ await this.setStateAsync('info.connection', false, true);
1257
+ this.config.cloudUrl = this.config.cloudUrl || 'a18wym7vjdl22g.iot.eu-west-1.amazonaws.com';
1258
+ if (!this.config.login || !this.config.pass) {
1259
+ return this.log.error('No cloud credentials found. Please get one on https://iobroker.pro');
1260
+ }
1261
+ if (this.config.iftttKey) {
1262
+ await this.subscribeStatesAsync('services.ifttt');
1263
+ // create ifttt object
1264
+ const iftttObj = await this.getObjectAsync('.services.ifttt');
1265
+ if (!iftttObj) {
1266
+ await this.setObjectNotExistsAsync('services.ifttt', {
1267
+ _id: `${this.namespace}.services.ifttt`,
1268
+ type: 'state',
1269
+ common: {
1270
+ name: 'IFTTT value',
1271
+ write: true,
1272
+ role: 'state',
1273
+ read: true,
1274
+ type: 'mixed',
1275
+ desc: 'All written data will be sent to IFTTT. If no state specified all requests from IFTTT will be saved here',
1276
+ },
1277
+ native: {},
1278
+ });
1279
+ }
1280
+ }
1281
+ // detect netatmo creation
1282
+ await this.subscribeForeignObjectsAsync('system.adapter.*');
1283
+ await this.subscribeStatesAsync('smart.*');
1284
+ this.log.info(`Connecting with ${this.config.cloudUrl}`);
1285
+ if (this.config.language) {
1286
+ this.translate = true;
1287
+ this.lang = this.config.language;
1288
+ }
1289
+ else {
1290
+ this.lang = systemConfig.common.language;
1291
+ }
1292
+ if (this.lang !== 'en' && this.lang !== 'de' && this.lang !== 'ru') {
1293
+ this.lang = 'en';
1294
+ }
1295
+ if (this.alexaSH2) {
1296
+ this.alexaSH2.setLanguage(this.lang, this.translate);
1297
+ this.alexaSH2.updateDevices();
1298
+ }
1299
+ this.alexaCustom?.setLanguage(this.lang);
1300
+ this.remote?.setLanguage(this.lang);
1301
+ // check password
1302
+ if (this.config.pass.length < 8 ||
1303
+ !this.config.pass.match(/[a-z]/) ||
1304
+ !this.config.pass.match(/[A-Z]/) ||
1305
+ !this.config.pass.match(/\d/)) {
1306
+ return this.log.error('The password must be at least 8 characters long and have numbers, upper and lower case letters. Please change the password in the profile https://iobroker.pro/accountProfile.');
1307
+ }
1308
+ await this.updateNightscoutSecret();
1309
+ const iotClientId = this.config.login.replace(/[^-_:a-zA-Z1-9]/g, '_');
1310
+ // user will be created here
1311
+ await this.startDevice(iotClientId, this.config.login, this.config.pass);
1312
+ // after the user created, we can try to generate URL key
1313
+ // read URL keys from server
1314
+ try {
1315
+ this.urlKey = await this.readUrlKey();
1316
+ }
1317
+ catch {
1318
+ if (this.config.googleHome ||
1319
+ this.config.yandexAlisa ||
1320
+ this.config.allowedServices.length ||
1321
+ this.config.iftttKey) {
1322
+ try {
1323
+ this.urlKey = await this.createUrlKey(this.config.login, this.config.pass);
1324
+ }
1325
+ catch (err) {
1326
+ return this.log.error(`Cannot read URL key: ${typeof err === 'object' ? JSON.stringify(err) : err}`);
1327
+ }
1328
+ }
1329
+ }
1330
+ if (this.config.amazonAlexaV3) {
1331
+ this.alexaSH3 = new alexaSmartHomeV3_1.default({
1332
+ adapter: this,
1333
+ iotClientId,
1334
+ iotDevice: this.device,
1335
+ });
1336
+ this.alexaSH3.setLanguage(this.lang);
1337
+ await this.alexaSH3.updateDevices();
1338
+ }
1339
+ if (this.config.googleHome) {
1340
+ this.googleHome = new googleHome_1.default(this, this.urlKey);
1341
+ } // no else
1342
+ if (this.config.yandexAlisa) {
1343
+ this.yandexAlisa = new alisa_1.default(this, this.urlKey);
1344
+ }
1345
+ this.googleHome?.setLanguage(this.lang);
1346
+ this.googleHome?.updateDevices();
1347
+ this.yandexAlisa?.setLanguage(this.lang);
1348
+ this.yandexAlisa?.updateDevices();
1349
+ await this.subscribeStatesAsync('app.message');
1350
+ }
1351
+ }
1352
+ exports.IotAdapter = IotAdapter;
1353
+ if (require.main !== module) {
1354
+ // Export the constructor in compact mode
1355
+ module.exports = (options) => new IotAdapter(options);
1356
+ }
1357
+ else {
1358
+ // otherwise start the instance directly
1359
+ (() => new IotAdapter())();
1360
+ }
1361
+ //# sourceMappingURL=main.js.map