homebridge-easy-mqtt 1.4.1-beta.0 → 1.5.0-beta.0

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 (154) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/README.md +102 -6
  3. package/config.schema.json +216 -7
  4. package/dist/accessory/abstract/base.d.ts +4 -6
  5. package/dist/accessory/abstract/base.js +17 -37
  6. package/dist/accessory/abstract/base.js.map +1 -1
  7. package/dist/accessory/abstract/common.d.ts +18 -4
  8. package/dist/accessory/abstract/common.js +165 -9
  9. package/dist/accessory/abstract/common.js.map +1 -1
  10. package/dist/accessory/abstract/group.d.ts +2 -4
  11. package/dist/accessory/abstract/group.js +11 -11
  12. package/dist/accessory/abstract/group.js.map +1 -1
  13. package/dist/accessory/abstract/helper.d.ts +3 -5
  14. package/dist/accessory/abstract/helper.js +34 -30
  15. package/dist/accessory/abstract/helper.js.map +1 -1
  16. package/dist/accessory/abstract/mqtt.d.ts +11 -8
  17. package/dist/accessory/abstract/mqtt.js +41 -33
  18. package/dist/accessory/abstract/mqtt.js.map +1 -1
  19. package/dist/accessory/addons/filter.d.ts +0 -1
  20. package/dist/accessory/addons/filter.js +6 -18
  21. package/dist/accessory/addons/filter.js.map +1 -1
  22. package/dist/accessory/button/button.d.ts +6 -0
  23. package/dist/accessory/{button.js → button/button.js} +6 -10
  24. package/dist/accessory/button/button.js.map +1 -0
  25. package/dist/accessory/button/doorbell.d.ts +7 -0
  26. package/dist/accessory/button/doorbell.js +25 -0
  27. package/dist/accessory/button/doorbell.js.map +1 -0
  28. package/dist/accessory/button/stateless.d.ts +6 -0
  29. package/dist/accessory/button/stateless.js +8 -0
  30. package/dist/accessory/button/stateless.js.map +1 -0
  31. package/dist/accessory/characteristic/characteristic.d.ts +3 -0
  32. package/dist/accessory/characteristic/characteristic.js +23 -0
  33. package/dist/accessory/characteristic/characteristic.js.map +1 -0
  34. package/dist/accessory/{abstract/customCharacteristic.d.ts → characteristic/custom.d.ts} +1 -0
  35. package/dist/accessory/{abstract/customCharacteristic.js → characteristic/custom.js} +4 -1
  36. package/dist/accessory/characteristic/custom.js.map +1 -0
  37. package/dist/accessory/characteristic/eve.d.ts +6 -0
  38. package/dist/accessory/characteristic/eve.js +24 -0
  39. package/dist/accessory/characteristic/eve.js.map +1 -0
  40. package/dist/accessory/climate/active.d.ts +2 -8
  41. package/dist/accessory/climate/active.js +9 -41
  42. package/dist/accessory/climate/active.js.map +1 -1
  43. package/dist/accessory/climate/fan2.d.ts +2 -15
  44. package/dist/accessory/climate/fan2.js +30 -109
  45. package/dist/accessory/climate/fan2.js.map +1 -1
  46. package/dist/accessory/climate/heaterCooler.d.ts +2 -14
  47. package/dist/accessory/climate/heaterCooler.js +32 -108
  48. package/dist/accessory/climate/heaterCooler.js.map +1 -1
  49. package/dist/accessory/climate/purifier.d.ts +2 -14
  50. package/dist/accessory/climate/purifier.js +27 -97
  51. package/dist/accessory/climate/purifier.js.map +1 -1
  52. package/dist/accessory/climate/temperatureControl.d.ts +5 -5
  53. package/dist/accessory/climate/temperatureControl.js +8 -8
  54. package/dist/accessory/climate/temperatureControl.js.map +1 -1
  55. package/dist/accessory/climate/thermostat.d.ts +2 -12
  56. package/dist/accessory/climate/thermostat.js +31 -84
  57. package/dist/accessory/climate/thermostat.js.map +1 -1
  58. package/dist/accessory/garage.d.ts +2 -12
  59. package/dist/accessory/garage.js +27 -93
  60. package/dist/accessory/garage.js.map +1 -1
  61. package/dist/accessory/lock.d.ts +2 -8
  62. package/dist/accessory/lock.js +28 -62
  63. package/dist/accessory/lock.js.map +1 -1
  64. package/dist/accessory/onoff/lightbulb.d.ts +2 -5
  65. package/dist/accessory/onoff/lightbulb.js +12 -18
  66. package/dist/accessory/onoff/lightbulb.js.map +1 -1
  67. package/dist/accessory/onoff/onoff.d.ts +4 -8
  68. package/dist/accessory/onoff/onoff.js +30 -34
  69. package/dist/accessory/onoff/onoff.js.map +1 -1
  70. package/dist/accessory/onoff/outlet.d.ts +2 -4
  71. package/dist/accessory/onoff/outlet.js +5 -5
  72. package/dist/accessory/onoff/outlet.js.map +1 -1
  73. package/dist/accessory/onoff/switch.d.ts +1 -4
  74. package/dist/accessory/onoff/switch.js +0 -3
  75. package/dist/accessory/onoff/switch.js.map +1 -1
  76. package/dist/accessory/position/blind.d.ts +2 -5
  77. package/dist/accessory/position/blind.js +7 -13
  78. package/dist/accessory/position/blind.js.map +1 -1
  79. package/dist/accessory/position/position.d.ts +2 -11
  80. package/dist/accessory/position/position.js +20 -71
  81. package/dist/accessory/position/position.js.map +1 -1
  82. package/dist/accessory/security.d.ts +4 -10
  83. package/dist/accessory/security.js +49 -81
  84. package/dist/accessory/security.js.map +1 -1
  85. package/dist/accessory/sensor/air.d.ts +2 -8
  86. package/dist/accessory/sensor/air.js +35 -67
  87. package/dist/accessory/sensor/air.js.map +1 -1
  88. package/dist/accessory/sensor/carbonDioxide.d.ts +2 -4
  89. package/dist/accessory/sensor/carbonDioxide.js +7 -7
  90. package/dist/accessory/sensor/carbonDioxide.js.map +1 -1
  91. package/dist/accessory/sensor/carbonMonoxide.d.ts +2 -4
  92. package/dist/accessory/sensor/carbonMonoxide.js +7 -7
  93. package/dist/accessory/sensor/carbonMonoxide.js.map +1 -1
  94. package/dist/accessory/sensor/contact.d.ts +2 -4
  95. package/dist/accessory/sensor/contact.js +20 -7
  96. package/dist/accessory/sensor/contact.js.map +1 -1
  97. package/dist/accessory/sensor/humidity.d.ts +2 -4
  98. package/dist/accessory/sensor/humidity.js +8 -5
  99. package/dist/accessory/sensor/humidity.js.map +1 -1
  100. package/dist/accessory/sensor/leak.d.ts +2 -4
  101. package/dist/accessory/sensor/leak.js +5 -5
  102. package/dist/accessory/sensor/leak.js.map +1 -1
  103. package/dist/accessory/sensor/light.d.ts +2 -4
  104. package/dist/accessory/sensor/light.js +5 -5
  105. package/dist/accessory/sensor/light.js.map +1 -1
  106. package/dist/accessory/sensor/motion.d.ts +2 -4
  107. package/dist/accessory/sensor/motion.js +8 -5
  108. package/dist/accessory/sensor/motion.js.map +1 -1
  109. package/dist/accessory/sensor/occupancy.d.ts +2 -4
  110. package/dist/accessory/sensor/occupancy.js +5 -5
  111. package/dist/accessory/sensor/occupancy.js.map +1 -1
  112. package/dist/accessory/sensor/sensor.d.ts +2 -6
  113. package/dist/accessory/sensor/sensor.js +5 -29
  114. package/dist/accessory/sensor/sensor.js.map +1 -1
  115. package/dist/accessory/sensor/smoke.d.ts +2 -4
  116. package/dist/accessory/sensor/smoke.js +5 -5
  117. package/dist/accessory/sensor/smoke.js.map +1 -1
  118. package/dist/accessory/sensor/temperature.d.ts +2 -4
  119. package/dist/accessory/sensor/temperature.js +8 -5
  120. package/dist/accessory/sensor/temperature.js.map +1 -1
  121. package/dist/accessory/valve.d.ts +2 -8
  122. package/dist/accessory/valve.js +10 -44
  123. package/dist/accessory/valve.js.map +1 -1
  124. package/dist/homebridge/platform.js +10 -4
  125. package/dist/homebridge/platform.js.map +1 -1
  126. package/dist/homebridge-ui/public/index.html +1 -1
  127. package/dist/homebridge-ui/public/ui.js +1 -1
  128. package/dist/i18n/en.d.ts +41 -5
  129. package/dist/i18n/en.js +43 -7
  130. package/dist/i18n/en.js.map +1 -1
  131. package/dist/i18n/fr.d.ts +41 -5
  132. package/dist/i18n/i18n.d.ts +41 -5
  133. package/dist/i18n/it.d.ts +41 -5
  134. package/dist/i18n/ro.d.ts +41 -5
  135. package/dist/i18n/template.d.ts +41 -5
  136. package/dist/i18n/vi.d.ts +41 -5
  137. package/dist/model/enums.d.ts +17 -2
  138. package/dist/model/enums.js +92 -77
  139. package/dist/model/enums.js.map +1 -1
  140. package/dist/model/history.d.ts +32 -0
  141. package/dist/model/history.js +128 -0
  142. package/dist/model/history.js.map +1 -0
  143. package/dist/model/mqtt.d.ts +1 -0
  144. package/dist/model/mqtt.js +37 -11
  145. package/dist/model/mqtt.js.map +1 -1
  146. package/dist/model/types.d.ts +39 -4
  147. package/dist/tools/log.d.ts +1 -1
  148. package/dist/tools/log.js.map +1 -1
  149. package/dist/tools/properties.js +1 -1
  150. package/dist/tools/properties.js.map +1 -1
  151. package/package.json +2 -1
  152. package/dist/accessory/abstract/customCharacteristic.js.map +0 -1
  153. package/dist/accessory/button.d.ts +0 -10
  154. package/dist/accessory/button.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -2,9 +2,17 @@
2
2
 
3
3
  All notable changes to homebridge-dummy will be documented in this file.
4
4
 
5
- ## 1.4.1-beta.0 (2025-10-10)
5
+ ## 1.5.0-beta.0 (2025-10-20)
6
6
 
7
7
  ### Added
8
+ - [Value Transformers](https://github.com/mpatfield/homebridge-easy-mqtt#history) (Thank you [@nehmeroumani](https://github.com/sponsors/nehmeroumani) for the code contribution!)
9
+ - `Doorbell` accessory type
10
+ - History and additional characteristics for for [Eve app](https://apps.apple.com/us/app/eve-for-matter-homekit/id917695792) users ([documentation](https://github.com/mpatfield/homebridge-easy-mqtt#history))
11
+ - Opened/closed history, and times opened count with option to reset for `ContactSensor`
12
+ - `MotionSensor` history
13
+ - Temperature history for `HeaterCooler`, `TemperatureSensor`, and `Thermostat`
14
+ - Humidity history for `HumiditySensor` and `Thermostat`
15
+ - On/off history and watts/amps/volts/kWh history for `Lightbulb`, `Outlet`, and `Switch`
8
16
  - Traduzioni in italiano. Grazie, [@Shikaban](https://github.com/sponsors/Shikaban)!
9
17
 
10
18
  ### Notes
package/README.md CHANGED
@@ -30,6 +30,7 @@ This plugin is designed to be a simple replacement for the fantastic [homebridge
30
30
  - `CarbonDioxideSensor`
31
31
  - `CarbonMonoxideSensor`
32
32
  - `ContactSensor`
33
+ - `Doorbell`
33
34
  - `Fanv2`
34
35
  - `GarageDoorOpener`
35
36
  - `HeaterCooler`
@@ -82,6 +83,11 @@ Using the Homebridge Config UI is the easiest way to set up this plugin. However
82
83
 
83
84
  ]
84
85
  },
86
+ "history": {
87
+ "enabled": true,
88
+ "disableRepeatLastData": false,
89
+ "size": 4032,
90
+ },
85
91
  "customCharacteristics": [
86
92
  {
87
93
  "uuid": "string",
@@ -134,7 +140,7 @@ Note that setting the this information in the JSON config will override the envi
134
140
 
135
141
  You will need to make sure to populate the appropriate topics based on the accessory type defined below.
136
142
 
137
- You may define topics using a JSONPath dot notation to assist the parser in finding the right value within the message. See [JSONPaths](#jsonpaths) below for more details.
143
+ You may define topics using a JSONPath dot notation to assist the parser in finding the right value within the message. You can also add a value transformer to alter the incoming or outgoing value. See [Advanced Topic Notation](#advanced-topic-notation) below for more details.
138
144
 
139
145
  As with topics, you will also need to populate the appropriate values based on the type. Note that while they are defined as strings, they will be auto-converted to the appropriate primitives (e.g. boolean or number) where appropriate.
140
146
 
@@ -163,18 +169,30 @@ These values are used for both determining current state and, where appropriate,
163
169
  - `topicSetHue` - For setting the lightbulb's current hue
164
170
  - `topicGetSaturation` - The current saturation setting of the lightbulb
165
171
  - `topicSetSaturation` - For setting the saturation setting of the lightbulb
172
+ - `topicGetCurrentConsumption` - Get the current power rate in watts ([Eve only](#eve-app-support))
173
+ - `topicGetElectricCurrent` - Get the electrical current in amps ([Eve only](#eve-app-support))
174
+ - `topicGetTotalConsumption` - Get the total energy use in kWh ([Eve only](#eve-app-support))
175
+ - `topicGetVoltage` - Get the current voltage ([Eve only](#eve-app-support))
166
176
 
167
177
  #### Outlet
168
178
  - `topicGetOn*` - The current state of the outlet, i.e. on/off
169
179
  - `topicSetOn*` - For setting the state of the outlet
180
+ - `topicGetOutletInUse` - Whether or not the outlet is
170
181
  - `valueOn*` - Turned on, e.g. "true", or "1", or "On"
171
182
  - `valueOff*` - Turned off, e.g. "false", or "0", or "Off"
172
- - `topicGetOutletInUse` - Whether or not the outlet is currently being used
173
183
  - `valueOutletInUse` - Currently being used, e.g. "true", or "1", or "On"
184
+ - `topicGetCurrentConsumption` - Get the current power rate in watts ([Eve only](#eve-app-support))
185
+ - `topicGetElectricCurrent` - Get the electrical current in amps ([Eve only](#eve-app-support))
186
+ - `topicGetTotalConsumption` - Get the total energy use in kWh ([Eve only](#eve-app-support))
187
+ - `topicGetVoltage` - Get the current voltage ([Eve only](#eve-app-support))
174
188
 
175
189
  #### Switch
176
190
  - `topicGetOn*` - The current state of the outlet, i.e. on/off
177
191
  - `topicSetOn*` - For setting the state of the outlet
192
+ - `topicGetCurrentConsumption` - Get the current power rate in watts ([Eve only](#eve-app-support))
193
+ - `topicGetElectricCurrent` - Get the electrical current in amps ([Eve only](#eve-app-support))
194
+ - `topicGetTotalConsumption` - Get the total energy use in kWh ([Eve only](#eve-app-support))
195
+ - `topicGetVoltage` - Get the current voltage ([Eve only](#eve-app-support))
178
196
  - `valueOn*` - Turned on, e.g. "true", or "1", or "On"
179
197
  - `valueOff*` - Turned off, e.g. "false", or "0", or "Off"
180
198
 
@@ -466,11 +484,27 @@ These values are used for both determining current state and, where appropriate,
466
484
  - `valueTampered` - Accessory has been tampered with
467
485
 
468
486
  #### StatelessProgrammableSwitch
469
- - `topicEventButtonPress` - Event for button press event
487
+ - `topicEventButtonPress*` - Event for button press event
470
488
  - `valueSinglePress` - Single press event
471
489
  - `valueDoublePress` - Double press event
472
490
  - `valueLongPress` - Long press event
473
491
 
492
+ ### Doorbell
493
+ - `maximumBrightness` - Set a maximum to use values (i.e. 1, 2, 3) rather than a percentage for brightness
494
+ - `maximumVolume` - Set a maximum to use values (i.e. 1, 2, 3) rather than a percentage for volume
495
+ - `topicEventButtonPress*` - Event for button press event
496
+ - `topicGetBrightness` - Get the brightness
497
+ - `topicSetBrightness` - Set the brightness
498
+ - `topicGetMuted` - Get whether or not the doorbell is muted
499
+ - `topicSetMuted` - Set whether or not the doorbell is muted
500
+ - `topicGetVolume` - Get the volume
501
+ - `topicSetVolume` - Set the volume
502
+ - `valueSinglePress` - Single press event
503
+ - `valueDoublePress` - Double press event
504
+ - `valueLongPress` - Long press event
505
+ - `valueMuted` - Doorbell muted
506
+ - `valueUnmuted` - Doorbell unmuted
507
+
474
508
  #### Valve
475
509
  - `valveType` - One of `GENERIC_VALVE` (default), `IRRIGATION`, `SHOWER_HEAD`, or `WATER_FAUCET`
476
510
  - `topicGetValveActive*` - For getting whether or not the valve is active
@@ -528,7 +562,9 @@ Each entry should have a topic and a message:
528
562
  ]
529
563
  ```
530
564
 
531
- ## JSONPaths
565
+ ## Advanced Topic Notation
566
+
567
+ ### JSONPaths
532
568
 
533
569
  For some devices, the desired values in the MQTT messages are embedded within a JSON object. For example, here is the MQTT message for my door lock that is received when the door is locked:
534
570
 
@@ -593,9 +629,69 @@ then you would use the topic
593
629
 
594
630
  `zwave/4/security/set$.target.mode.value`
595
631
 
596
- ## Custom Characteristics
632
+ ### Value Transformers
633
+
634
+ There are other situations where the value needs to be adjusted or altered entirely.
635
+
636
+ For example, you may have an Air Quality Sensor that measures Nitrogen Dioxide in ppm (parts per million) instead of µg/m³ (micrograms per cubic meter) which HomeKit expects. In this case, you need to multiply by the arbitrary number 1883 to get the correct result.
637
+
638
+ Using the pipe (`|`) notation, you may add a transformer:
639
+
640
+ `airquality/no2|value * 1883`
641
+
642
+ This will multiply the value by `1883` to get the desired result.
643
+
644
+ Note that `value` is a reserved keyword here to indicate the incoming value you'd like to transform.
645
+
646
+ You can also do the same thing on the publish side to transfer it back to ppm. In this case, you would need to divide by 1883.
647
+
648
+ `airquality/no2|value / 1883`
649
+
650
+ ### Both JSONPath + Transformer
651
+
652
+ You can also combine JSONPath and Transformer notation into a single entity
653
+
654
+ `airquality$.no2|value * 1883`
655
+
656
+ ## Eve App Support
657
+
658
+ If you use [Eve](https://apps.apple.com/us/app/eve-for-matter-homekit/id917695792), then there are some additional features available:
659
+ - Opened/closed history, and times opened count with option to reset for `ContactSensor`
660
+ - `MotionSensor` history
661
+ - Temperature history for `HeaterCooler`, `TemperatureSensor`, and `Thermostat`
662
+ - Humidity history for `HumiditySensor` and `Thermostat`
663
+ - On/off history for `Lightbulb`, `Outlet`, and `Switch`
664
+
665
+ You can also add get topics for watts/amps/volts/kWh for `Lightbulb`, `Outlet`, and `Switch`:
666
+ - `topicGetCurrentConsumption` - Get the current power rate in watts
667
+ - `topicGetElectricCurrent` - Get the electrical current in amps
668
+ - `topicGetTotalConsumption` - Get the total energy use in kWh
669
+ - `topicGetVoltage` - Get the current voltage
670
+
671
+ To enable history, choose the `History Enabled` option in the config UI.
672
+
673
+ There are a couple of advanced options if configuring via JSON:
674
+
675
+ ```json
676
+ {
677
+ "info": …
678
+ "mqtt": …
679
+ "history": {
680
+ "enabled": true,
681
+ "disableRepeatLastData": false,
682
+ "size": 4032,
683
+ },
684
+ … // Topic & Values
685
+ }
686
+ ```
687
+
688
+ - `enabled` — used to enable/disable history
689
+ - `disableRepeatLastData` — See [fakegato-history](https://github.com/simont77/fakegato-history?tab=readme-ov-file#fakegato-history) for info
690
+ - `size` - The maximum number of history entries. Default is 4032 (1 entry every 10 minutes for 28 days)
691
+
692
+ ### Custom Characteristics
597
693
 
598
- If you use a more advanced HomeKit app like [Eve](https://apps.apple.com/us/app/eve-for-matter-homekit/id917695792) or [Controller for Homekit](https://apps.apple.com/us/app/controller-for-homekit/id1198176727), you can add custom characteristics to display any arbitrary numeric information. Unfortunately, Apple currently doesn't offer a way to display this in the Home app.
694
+ Eve users can also add custom characteristics to display any arbitrary numeric information.
599
695
 
600
696
  <img src="https://raw.githubusercontent.com/mpatfield/homebridge-easy-mqtt/refs/heads/latest/img/screenshot_1.png">
601
697
 
@@ -21,8 +21,8 @@
21
21
  "type": {
22
22
  "type": "string",
23
23
  "title": "${config.title.type}",
24
- "enum": [ "AirPurifier", "AirQualitySensor", "CarbonMonoxideSensor", "CarbonDioxideSensor", "ContactSensor", "Fanv2", "GarageDoorOpener", "HeaterCooler", "HumiditySensor", "LeakSensor", "Lightbulb", "LightSensor", "LockMechanism", "MotionSensor", "OccupancySensor", "Outlet", "SecuritySystem", "SmokeSensor", "StatelessProgrammableSwitch", "Switch", "TemperatureSensor", "Thermostat", "Valve", "WindowCovering"],
25
- "enumNames": ["${config.enumNames.airPurifier}", "${config.enumNames.airQualitySensor}", "${config.enumNames.carbonMonoxideSensor}", "${config.enumNames.carbonDioxideSensor}", "${config.enumNames.contactSensor}", "${config.enumNames.fanv2}", "${config.enumNames.garageDoorOpener}", "${config.enumNames.heaterCooler}", "${config.enumNames.humiditySensor}", "${config.enumNames.leakSensor}", "${config.enumNames.lightbulb}", "${config.enumNames.lightSensor}", "${config.enumNames.lockMechanism}", "${config.enumNames.motionSensor}", "${config.enumNames.occupancySensor}", "${config.enumNames.outlet}", "${config.enumNames.securitySystem}", "${config.enumNames.smokeSensor}", "${config.enumNames.statelessSwitch}", "${config.enumNames.switch}", "${config.enumNames.temperatureSensor}", "${config.enumNames.thermostat}", "${config.enumNames.valve}", "${config.enumNames.windowCovering}"],
24
+ "enum": [ "AirPurifier", "AirQualitySensor", "CarbonMonoxideSensor", "CarbonDioxideSensor", "ContactSensor", "Doorbell", "Fanv2", "GarageDoorOpener", "HeaterCooler", "HumiditySensor", "LeakSensor", "Lightbulb", "LightSensor", "LockMechanism", "MotionSensor", "OccupancySensor", "Outlet", "SecuritySystem", "SmokeSensor", "StatelessProgrammableSwitch", "Switch", "TemperatureSensor", "Thermostat", "Valve", "WindowCovering"],
25
+ "enumNames": ["${config.enumNames.airPurifier}", "${config.enumNames.airQualitySensor}", "${config.enumNames.carbonMonoxideSensor}", "${config.enumNames.carbonDioxideSensor}", "${config.enumNames.contactSensor}", "${config.enumNames.doorbell}", "${config.enumNames.fanv2}", "${config.enumNames.garageDoorOpener}", "${config.enumNames.heaterCooler}", "${config.enumNames.humiditySensor}", "${config.enumNames.leakSensor}", "${config.enumNames.lightbulb}", "${config.enumNames.lightSensor}", "${config.enumNames.lockMechanism}", "${config.enumNames.motionSensor}", "${config.enumNames.occupancySensor}", "${config.enumNames.outlet}", "${config.enumNames.securitySystem}", "${config.enumNames.smokeSensor}", "${config.enumNames.statelessSwitch}", "${config.enumNames.switch}", "${config.enumNames.temperatureSensor}", "${config.enumNames.thermostat}", "${config.enumNames.valve}", "${config.enumNames.windowCovering}"],
26
26
  "required": true
27
27
  },
28
28
  "group": {
@@ -88,6 +88,15 @@
88
88
  }
89
89
  }
90
90
  },
91
+ "history": {
92
+ "type": "object",
93
+ "properties": {
94
+ "enabled": {
95
+ "type": "boolean",
96
+ "title": "${config.title.historyEnabled}"
97
+ }
98
+ }
99
+ },
91
100
  "customCharacteristic": {
92
101
  "type": "object",
93
102
  "properties": {
@@ -118,6 +127,7 @@
118
127
  "properties": {
119
128
  "info": { "$ref": "#/definitions/info" },
120
129
  "mqtt": { "$ref": "#/definitions/mqtt" },
130
+ "history": { "$ref": "#/definitions/history" },
121
131
  "customCharacteristics": {
122
132
  "type": "array",
123
133
  "items": { "$ref": "#/definitions/customCharacteristic" }
@@ -134,6 +144,10 @@
134
144
  "type": "integer",
135
145
  "title": "${config.title.maximum}"
136
146
  },
147
+ "maximumVolume": {
148
+ "type": "integer",
149
+ "title": "${config.title.maximum}"
150
+ },
137
151
  "temperatureUnits": {
138
152
  "type": "string",
139
153
  "title": "${config.title.sourceUnits}",
@@ -546,6 +560,38 @@
546
560
  "type": "string",
547
561
  "title": "${config.title.topicEventButtonPress}"
548
562
  },
563
+ "topicGetMuted": {
564
+ "type": "string",
565
+ "title": "${config.title.topicGetMuted}"
566
+ },
567
+ "topicGetVolume": {
568
+ "type": "string",
569
+ "title": "${config.title.topicGetVolume}"
570
+ },
571
+ "topicSetMuted": {
572
+ "type": "string",
573
+ "title": "${config.title.topicSetMuted}"
574
+ },
575
+ "topicSetVolume": {
576
+ "type": "string",
577
+ "title": "${config.title.topicSetVolume}"
578
+ },
579
+ "topicGetCurrentConsumption": {
580
+ "type": "string",
581
+ "title": "${config.title.topicGetCurrentConsumption}"
582
+ },
583
+ "topicGetElectricCurrent": {
584
+ "type": "string",
585
+ "title": "${config.title.topicGetElectricCurrent}"
586
+ },
587
+ "topicGetTotalConsumption": {
588
+ "type": "string",
589
+ "title": "${config.title.topicGetTotalConsumption}"
590
+ },
591
+ "topicGetVoltage": {
592
+ "type": "string",
593
+ "title": "${config.title.topicGetVoltage}"
594
+ },
549
595
  "valueBatteryLow": {
550
596
  "type": "string",
551
597
  "title": "${config.title.valueBatteryLow}"
@@ -814,6 +860,14 @@
814
860
  "type": "string",
815
861
  "title": "${config.title.valueLongPress}"
816
862
  },
863
+ "valueMuted": {
864
+ "type": "string",
865
+ "title": "${config.title.valueMuted}"
866
+ },
867
+ "valueUnmuted": {
868
+ "type": "string",
869
+ "title": "${config.title.valueUnmuted}"
870
+ },
817
871
  "resetOnRestart": {
818
872
  "type": "boolean",
819
873
  "title": "${config.title.resetOnRestart}"
@@ -1227,8 +1281,8 @@
1227
1281
  "info": {
1228
1282
  "properties": {
1229
1283
  "type" : {
1230
- "const": "StatelessProgrammableSwitch"
1231
- }
1284
+ "enum": ["Doorbell, StatelessProgrammableSwitch"]
1285
+ }
1232
1286
  }
1233
1287
  }
1234
1288
  }
@@ -1575,7 +1629,10 @@
1575
1629
  "required": ["topicGetObstructionDetected"]
1576
1630
  },
1577
1631
  "then": {
1578
- "required": ["valuePositionObstructed"]
1632
+ "anyOf": [
1633
+ { "required": ["valuePositionObstructed"] },
1634
+ { "required": ["valueDoorObstructed"] }
1635
+ ]
1579
1636
  }
1580
1637
  },
1581
1638
  {
@@ -1629,6 +1686,32 @@
1629
1686
  "then": {
1630
1687
  "required": ["topicGetCurrentVerticalTiltAngle"]
1631
1688
  }
1689
+ },
1690
+ {
1691
+ "if": {
1692
+ "properties": {
1693
+ "topicGetMuted": {
1694
+ "minLength": 1
1695
+ }
1696
+ },
1697
+ "required": ["topicGetMuted"]
1698
+ },
1699
+ "then": {
1700
+ "required": ["topicSetMuted", "valueMuted", "valueUnmuted"]
1701
+ }
1702
+ },
1703
+ {
1704
+ "if": {
1705
+ "properties": {
1706
+ "topicSetMuted": {
1707
+ "minLength": 1
1708
+ }
1709
+ },
1710
+ "required": ["topicSetMuted"]
1711
+ },
1712
+ "then": {
1713
+ "required": ["topicGetMuted"]
1714
+ }
1632
1715
  }
1633
1716
  ]
1634
1717
  },
@@ -1719,6 +1802,13 @@
1719
1802
  {
1720
1803
  "key": "accessories[].disableLogging",
1721
1804
  "flex": "0 0 25%"
1805
+ },
1806
+ {
1807
+ "key": "accessories[].history.enabled",
1808
+ "flex": "0 0 25%",
1809
+ "condition": {
1810
+ "functionBody": "return ['ContactSensor', 'HeaterCooler', 'HumiditySensor', 'Lightbulb', 'MotionSensor', 'Outlet', 'Switch', 'TemperatureSensor', 'Thermostat'].includes(model.accessories?.[arguments[1]]?.info?.type);"
1811
+ }
1722
1812
  }
1723
1813
  ]
1724
1814
  },
@@ -1837,7 +1927,7 @@
1837
1927
  "type": "fieldset",
1838
1928
  "notitle": true,
1839
1929
  "condition": {
1840
- "functionBody": "return model.accessories?.[arguments[1]]?.info?.type === 'StatelessProgrammableSwitch';"
1930
+ "functionBody": "return ['Doorbell', 'StatelessProgrammableSwitch'].includes(model.accessories?.[arguments[1]]?.info?.type);"
1841
1931
  },
1842
1932
  "items": [
1843
1933
  {
@@ -1853,6 +1943,68 @@
1853
1943
  }
1854
1944
  ]
1855
1945
  },
1946
+ {
1947
+ "type": "fieldset",
1948
+ "notitle": true,
1949
+ "condition": {
1950
+ "functionBody": "return model.accessories?.[arguments[1]]?.info?.type === 'Doorbell';"
1951
+ },
1952
+ "items": [
1953
+ {
1954
+ "type": "div",
1955
+ "displayFlex": true,
1956
+ "flex-direction": "row",
1957
+ "items": [
1958
+ {
1959
+ "key": "accessories[].topicGetBrightness",
1960
+ "flex": "0 0 40%"
1961
+ },
1962
+ {
1963
+ "key": "accessories[].topicSetBrightness",
1964
+ "flex": "0 0 40%"
1965
+ },
1966
+ {
1967
+ "key": "accessories[].maximumBrightness",
1968
+ "flex": "0 0 20%"
1969
+ }
1970
+ ]
1971
+ },
1972
+ {
1973
+ "type": "div",
1974
+ "displayFlex": true,
1975
+ "flex-direction": "row",
1976
+ "items": [
1977
+ {
1978
+ "key": "accessories[].topicGetVolume",
1979
+ "flex": "0 0 40%"
1980
+ },
1981
+ {
1982
+ "key": "accessories[].topicSetVolume",
1983
+ "flex": "0 0 40%"
1984
+ },
1985
+ {
1986
+ "key": "accessories[].maximumVolume",
1987
+ "flex": "0 0 20%"
1988
+ }
1989
+ ]
1990
+ },
1991
+ {
1992
+ "type": "div",
1993
+ "displayFlex": true,
1994
+ "flex-direction": "row",
1995
+ "items": [
1996
+ {
1997
+ "key": "accessories[].topicGetMuted",
1998
+ "flex": "0 0 50%"
1999
+ },
2000
+ {
2001
+ "key": "accessories[].topicSetMuted",
2002
+ "flex": "0 0 50%"
2003
+ }
2004
+ ]
2005
+ }
2006
+ ]
2007
+ },
1856
2008
  {
1857
2009
  "type": "fieldset",
1858
2010
  "notitle": true,
@@ -2057,6 +2209,45 @@
2057
2209
  }
2058
2210
  ]
2059
2211
  },
2212
+ {
2213
+ "type": "fieldset",
2214
+ "notitle": true,
2215
+ "condition": {
2216
+ "functionBody": "return ['Lightbulb', 'Outlet', 'Switch'].includes(model.accessories?.[arguments[1]]?.info?.type);"
2217
+ },
2218
+ "items": [
2219
+ {
2220
+ "type": "div",
2221
+ "displayFlex": true,
2222
+ "flex-direction": "row",
2223
+ "items": [
2224
+ {
2225
+ "key": "accessories[].topicGetCurrentConsumption",
2226
+ "flex": "0 0 50%"
2227
+ },
2228
+ {
2229
+ "key": "accessories[].topicGetTotalConsumption",
2230
+ "flex": "0 0 50%"
2231
+ }
2232
+ ]
2233
+ },
2234
+ {
2235
+ "type": "div",
2236
+ "displayFlex": true,
2237
+ "flex-direction": "row",
2238
+ "items": [
2239
+ {
2240
+ "key": "accessories[].topicGetElectricCurrent",
2241
+ "flex": "0 0 50%"
2242
+ },
2243
+ {
2244
+ "key": "accessories[].topicGetVoltage",
2245
+ "flex": "0 0 50%"
2246
+ }
2247
+ ]
2248
+ }
2249
+ ]
2250
+ },
2060
2251
  {
2061
2252
  "type": "fieldset",
2062
2253
  "notitle": true,
@@ -3247,7 +3438,7 @@
3247
3438
  "type": "fieldset",
3248
3439
  "notitle": true,
3249
3440
  "condition": {
3250
- "functionBody": "return model.accessories?.[arguments[1]]?.info?.type === 'StatelessProgrammableSwitch';"
3441
+ "functionBody": "return ['Doorbell', 'StatelessProgrammableSwitch'].includes(model.accessories?.[arguments[1]]?.info?.type);"
3251
3442
  },
3252
3443
  "items": [
3253
3444
  {
@@ -3271,6 +3462,24 @@
3271
3462
  }
3272
3463
  ]
3273
3464
  },
3465
+ {
3466
+ "type": "div",
3467
+ "displayFlex": true,
3468
+ "flex-direction": "row",
3469
+ "condition": {
3470
+ "functionBody": "return model.accessories?.[arguments[1]]?.info?.type === 'Doorbell';"
3471
+ },
3472
+ "items": [
3473
+ {
3474
+ "key": "accessories[].valueMuted",
3475
+ "flex": "0 0 25%"
3476
+ },
3477
+ {
3478
+ "key": "accessories[].valueUnmuted",
3479
+ "flex": "0 0 25%"
3480
+ }
3481
+ ]
3482
+ },
3274
3483
  {
3275
3484
  "type": "fieldset",
3276
3485
  "notitle": true,
@@ -1,9 +1,7 @@
1
- import { PlatformAccessory } from 'homebridge';
2
1
  import { MQTTAccessory } from './mqtt.js';
3
- import { CharacteristicType, BaseAccessoryConfig, ServiceType } from '../../model/types.js';
4
- import { Log } from '../../tools/log.js';
2
+ import { CharacteristicKey } from '../../model/enums.js';
3
+ import { BaseAccessoryConfig, MQTTAccessoryDependency } from '../../model/types.js';
5
4
  export declare abstract class BaseAccessory<C extends BaseAccessoryConfig = BaseAccessoryConfig> extends MQTTAccessory<C> {
6
- constructor(Service: ServiceType, Characteristic: CharacteristicType, accessory: PlatformAccessory, config: C, log: Log, isGrouped: boolean);
7
- private onBatteryLowUpdate;
8
- private onStatusActiveUpdate;
5
+ constructor(dependency: MQTTAccessoryDependency<C>);
6
+ isOptionalCharacteristic(key: CharacteristicKey): boolean;
9
7
  }
@@ -1,48 +1,28 @@
1
1
  import { MQTTAccessory } from './mqtt.js';
2
2
  import { PLATFORM_NAME } from '../../homebridge/settings.js';
3
+ import { isOptionalHKCharacteristic } from '../characteristic/characteristic.js';
3
4
  import { strings } from '../../i18n/i18n.js';
4
- import { CharacteristicKey } from '../../model/enums.js';
5
+ import { HKCharacteristicKey } from '../../model/enums.js';
5
6
  import { LogType } from '../../tools/log.js';
6
7
  import getVersion from '../../tools/version.js';
7
8
  export class BaseAccessory extends MQTTAccessory {
8
- constructor(Service, Characteristic, accessory, config, log, isGrouped) {
9
- super(Service, Characteristic, accessory, config, log, isGrouped);
10
- if (!isGrouped) {
11
- accessory.getService(Service.AccessoryInformation)
12
- .setCharacteristic(Characteristic.Name, config.info.name)
13
- .setCharacteristic(Characteristic.ConfiguredName, config.info.name)
14
- .setCharacteristic(Characteristic.Manufacturer, config.info.manufacturer ?? PLATFORM_NAME)
15
- .setCharacteristic(Characteristic.Model, config.info.model ?? config.info.type)
16
- .setCharacteristic(Characteristic.SerialNumber, config.info.serialNumber ?? this.identifier)
17
- .setCharacteristic(Characteristic.FirmwareRevision, config.info.version ?? getVersion());
9
+ constructor(dependency) {
10
+ super(dependency);
11
+ if (!dependency.isGrouped) {
12
+ this.platformAccessory.getService(dependency.Service.AccessoryInformation)
13
+ .setCharacteristic(dependency.Characteristic.Name, dependency.config.info.name)
14
+ .setCharacteristic(dependency.Characteristic.ConfiguredName, dependency.config.info.name)
15
+ .setCharacteristic(dependency.Characteristic.Manufacturer, dependency.config.info.manufacturer ?? PLATFORM_NAME)
16
+ .setCharacteristic(dependency.Characteristic.Model, dependency.config.info.model ?? dependency.config.info.type)
17
+ .setCharacteristic(dependency.Characteristic.SerialNumber, dependency.config.info.serialNumber ?? this.identifier)
18
+ .setCharacteristic(dependency.Characteristic.FirmwareRevision, dependency.config.info.version ?? getVersion());
18
19
  }
19
- this.setup(CharacteristicKey.BatteryLevel, 100, 'topicGetBatteryLevel', this.bindOnUpdateNumeric(CharacteristicKey.BatteryLevel, strings.accessory.batteryLevel), false);
20
- this.setup(CharacteristicKey.StatusLowBattery, Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL, 'topicGetBatteryLow', this.onBatteryLowUpdate.bind(this), false);
21
- this.setup(CharacteristicKey.StatusActive, true, 'topicGetStatusActive', this.onStatusActiveUpdate.bind(this), false);
20
+ this.setup(HKCharacteristicKey.BatteryLevel, 100, 'topicGetBatteryLevel', this.bindOnUpdateNumeric(HKCharacteristicKey.BatteryLevel, strings.accessory.batteryLevel), false);
21
+ this.setup(HKCharacteristicKey.StatusLowBattery, dependency.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL, 'topicGetBatteryLow', this.bindOnUpdateBooleanSingle(HKCharacteristicKey.StatusLowBattery, 'valueBatteryLow', strings.accessory.batteryLow, strings.accessory.batteryNotLow, LogType.WARNING), false);
22
+ this.setup(HKCharacteristicKey.StatusActive, true, 'topicGetStatusActive', this.bindOnUpdateBooleanSingle(HKCharacteristicKey.StatusActive, 'valueStatusActive', strings.accessory.statusActive, strings.accessory.statusInactive, LogType.ALWAYS, LogType.WARNING), false);
22
23
  }
23
- async onBatteryLowUpdate(topic, value) {
24
- const batteryLow = value === this.getPrimitiveValue('valueBatteryLow') ? 1 : 0;
25
- if (!this.onUpdate(CharacteristicKey.StatusLowBattery, batteryLow)) {
26
- return;
27
- }
28
- if (batteryLow) {
29
- this.logIfDesired(LogType.WARNING, strings.accessory.batteryLow);
30
- }
31
- else {
32
- this.logIfDesired(strings.accessory.batteryNotLow);
33
- }
34
- }
35
- async onStatusActiveUpdate(topic, value) {
36
- const statusActive = value === this.getPrimitiveValue('valueStatusActive');
37
- if (!this.onUpdate(CharacteristicKey.StatusActive, statusActive)) {
38
- return;
39
- }
40
- if (statusActive) {
41
- this.logIfDesired(strings.accessory.statusActive);
42
- }
43
- else {
44
- this.logIfDesired(LogType.WARNING, strings.accessory.statusInactive);
45
- }
24
+ isOptionalCharacteristic(key) {
25
+ return super.isOptionalCharacteristic(key) || isOptionalHKCharacteristic(key, this.config.info.type);
46
26
  }
47
27
  }
48
28
  //# sourceMappingURL=base.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/accessory/abstract/base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/accessory/abstract/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAEjF,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAqB,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,UAAU,MAAM,wBAAwB,CAAC;AAEhD,MAAM,OAAgB,aAAmE,SAAQ,aAAgB;IAE/G,YAAY,UAAsC;QAChD,KAAK,CAAC,UAAU,CAAC,CAAC;QAElB,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,oBAAoB,CAAE;iBACxE,iBAAiB,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;iBAC9E,iBAAiB,CAAC,UAAU,CAAC,cAAc,CAAC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;iBACxF,iBAAiB,CAAC,UAAU,CAAC,cAAc,CAAC,YAAY,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,IAAI,aAAa,CAAC;iBAC/G,iBAAiB,CAAC,UAAU,CAAC,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;iBAC/G,iBAAiB,CAAC,UAAU,CAAC,cAAc,CAAC,YAAY,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,UAAU,CAAC;iBACjH,iBAAiB,CAAC,UAAU,CAAC,cAAc,CAAC,gBAAgB,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,UAAU,EAAE,CAAC,CAAC;QACjH,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,YAAY,EAAE,GAAG,EAC9C,sBAAsB,EAAE,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,YAAY,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,CAAC;QAE7H,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,EAAE,UAAU,CAAC,cAAc,CAAC,gBAAgB,CAAC,oBAAoB,EAC9G,oBAAoB,EACpB,IAAI,CAAC,yBAAyB,CAAC,mBAAmB,CAAC,gBAAgB,EAAE,iBAAiB,EACpF,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,EACjF,KAAK,CACN,CAAC;QAEF,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,YAAY,EAAE,IAAI,EAC/C,sBAAsB,EACtB,IAAI,CAAC,yBAAyB,CAAC,mBAAmB,CAAC,YAAY,EAAE,mBAAmB,EAClF,OAAO,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,SAAS,CAAC,cAAc,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,EACpG,KAAK,CAAC,CAAC;IACX,CAAC;IAEQ,wBAAwB,CAAC,GAAsB;QACtD,OAAO,KAAK,CAAC,wBAAwB,CAAC,GAAG,CAAC,IAAI,0BAA0B,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvG,CAAC;CACF"}