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.
- package/CHANGELOG.md +9 -1
- package/README.md +102 -6
- package/config.schema.json +216 -7
- package/dist/accessory/abstract/base.d.ts +4 -6
- package/dist/accessory/abstract/base.js +17 -37
- package/dist/accessory/abstract/base.js.map +1 -1
- package/dist/accessory/abstract/common.d.ts +18 -4
- package/dist/accessory/abstract/common.js +165 -9
- package/dist/accessory/abstract/common.js.map +1 -1
- package/dist/accessory/abstract/group.d.ts +2 -4
- package/dist/accessory/abstract/group.js +11 -11
- package/dist/accessory/abstract/group.js.map +1 -1
- package/dist/accessory/abstract/helper.d.ts +3 -5
- package/dist/accessory/abstract/helper.js +34 -30
- package/dist/accessory/abstract/helper.js.map +1 -1
- package/dist/accessory/abstract/mqtt.d.ts +11 -8
- package/dist/accessory/abstract/mqtt.js +41 -33
- package/dist/accessory/abstract/mqtt.js.map +1 -1
- package/dist/accessory/addons/filter.d.ts +0 -1
- package/dist/accessory/addons/filter.js +6 -18
- package/dist/accessory/addons/filter.js.map +1 -1
- package/dist/accessory/button/button.d.ts +6 -0
- package/dist/accessory/{button.js → button/button.js} +6 -10
- package/dist/accessory/button/button.js.map +1 -0
- package/dist/accessory/button/doorbell.d.ts +7 -0
- package/dist/accessory/button/doorbell.js +25 -0
- package/dist/accessory/button/doorbell.js.map +1 -0
- package/dist/accessory/button/stateless.d.ts +6 -0
- package/dist/accessory/button/stateless.js +8 -0
- package/dist/accessory/button/stateless.js.map +1 -0
- package/dist/accessory/characteristic/characteristic.d.ts +3 -0
- package/dist/accessory/characteristic/characteristic.js +23 -0
- package/dist/accessory/characteristic/characteristic.js.map +1 -0
- package/dist/accessory/{abstract/customCharacteristic.d.ts → characteristic/custom.d.ts} +1 -0
- package/dist/accessory/{abstract/customCharacteristic.js → characteristic/custom.js} +4 -1
- package/dist/accessory/characteristic/custom.js.map +1 -0
- package/dist/accessory/characteristic/eve.d.ts +6 -0
- package/dist/accessory/characteristic/eve.js +24 -0
- package/dist/accessory/characteristic/eve.js.map +1 -0
- package/dist/accessory/climate/active.d.ts +2 -8
- package/dist/accessory/climate/active.js +9 -41
- package/dist/accessory/climate/active.js.map +1 -1
- package/dist/accessory/climate/fan2.d.ts +2 -15
- package/dist/accessory/climate/fan2.js +30 -109
- package/dist/accessory/climate/fan2.js.map +1 -1
- package/dist/accessory/climate/heaterCooler.d.ts +2 -14
- package/dist/accessory/climate/heaterCooler.js +32 -108
- package/dist/accessory/climate/heaterCooler.js.map +1 -1
- package/dist/accessory/climate/purifier.d.ts +2 -14
- package/dist/accessory/climate/purifier.js +27 -97
- package/dist/accessory/climate/purifier.js.map +1 -1
- package/dist/accessory/climate/temperatureControl.d.ts +5 -5
- package/dist/accessory/climate/temperatureControl.js +8 -8
- package/dist/accessory/climate/temperatureControl.js.map +1 -1
- package/dist/accessory/climate/thermostat.d.ts +2 -12
- package/dist/accessory/climate/thermostat.js +31 -84
- package/dist/accessory/climate/thermostat.js.map +1 -1
- package/dist/accessory/garage.d.ts +2 -12
- package/dist/accessory/garage.js +27 -93
- package/dist/accessory/garage.js.map +1 -1
- package/dist/accessory/lock.d.ts +2 -8
- package/dist/accessory/lock.js +28 -62
- package/dist/accessory/lock.js.map +1 -1
- package/dist/accessory/onoff/lightbulb.d.ts +2 -5
- package/dist/accessory/onoff/lightbulb.js +12 -18
- package/dist/accessory/onoff/lightbulb.js.map +1 -1
- package/dist/accessory/onoff/onoff.d.ts +4 -8
- package/dist/accessory/onoff/onoff.js +30 -34
- package/dist/accessory/onoff/onoff.js.map +1 -1
- package/dist/accessory/onoff/outlet.d.ts +2 -4
- package/dist/accessory/onoff/outlet.js +5 -5
- package/dist/accessory/onoff/outlet.js.map +1 -1
- package/dist/accessory/onoff/switch.d.ts +1 -4
- package/dist/accessory/onoff/switch.js +0 -3
- package/dist/accessory/onoff/switch.js.map +1 -1
- package/dist/accessory/position/blind.d.ts +2 -5
- package/dist/accessory/position/blind.js +7 -13
- package/dist/accessory/position/blind.js.map +1 -1
- package/dist/accessory/position/position.d.ts +2 -11
- package/dist/accessory/position/position.js +20 -71
- package/dist/accessory/position/position.js.map +1 -1
- package/dist/accessory/security.d.ts +4 -10
- package/dist/accessory/security.js +49 -81
- package/dist/accessory/security.js.map +1 -1
- package/dist/accessory/sensor/air.d.ts +2 -8
- package/dist/accessory/sensor/air.js +35 -67
- package/dist/accessory/sensor/air.js.map +1 -1
- package/dist/accessory/sensor/carbonDioxide.d.ts +2 -4
- package/dist/accessory/sensor/carbonDioxide.js +7 -7
- package/dist/accessory/sensor/carbonDioxide.js.map +1 -1
- package/dist/accessory/sensor/carbonMonoxide.d.ts +2 -4
- package/dist/accessory/sensor/carbonMonoxide.js +7 -7
- package/dist/accessory/sensor/carbonMonoxide.js.map +1 -1
- package/dist/accessory/sensor/contact.d.ts +2 -4
- package/dist/accessory/sensor/contact.js +20 -7
- package/dist/accessory/sensor/contact.js.map +1 -1
- package/dist/accessory/sensor/humidity.d.ts +2 -4
- package/dist/accessory/sensor/humidity.js +8 -5
- package/dist/accessory/sensor/humidity.js.map +1 -1
- package/dist/accessory/sensor/leak.d.ts +2 -4
- package/dist/accessory/sensor/leak.js +5 -5
- package/dist/accessory/sensor/leak.js.map +1 -1
- package/dist/accessory/sensor/light.d.ts +2 -4
- package/dist/accessory/sensor/light.js +5 -5
- package/dist/accessory/sensor/light.js.map +1 -1
- package/dist/accessory/sensor/motion.d.ts +2 -4
- package/dist/accessory/sensor/motion.js +8 -5
- package/dist/accessory/sensor/motion.js.map +1 -1
- package/dist/accessory/sensor/occupancy.d.ts +2 -4
- package/dist/accessory/sensor/occupancy.js +5 -5
- package/dist/accessory/sensor/occupancy.js.map +1 -1
- package/dist/accessory/sensor/sensor.d.ts +2 -6
- package/dist/accessory/sensor/sensor.js +5 -29
- package/dist/accessory/sensor/sensor.js.map +1 -1
- package/dist/accessory/sensor/smoke.d.ts +2 -4
- package/dist/accessory/sensor/smoke.js +5 -5
- package/dist/accessory/sensor/smoke.js.map +1 -1
- package/dist/accessory/sensor/temperature.d.ts +2 -4
- package/dist/accessory/sensor/temperature.js +8 -5
- package/dist/accessory/sensor/temperature.js.map +1 -1
- package/dist/accessory/valve.d.ts +2 -8
- package/dist/accessory/valve.js +10 -44
- package/dist/accessory/valve.js.map +1 -1
- package/dist/homebridge/platform.js +10 -4
- package/dist/homebridge/platform.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +1 -1
- package/dist/homebridge-ui/public/ui.js +1 -1
- package/dist/i18n/en.d.ts +41 -5
- package/dist/i18n/en.js +43 -7
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/fr.d.ts +41 -5
- package/dist/i18n/i18n.d.ts +41 -5
- package/dist/i18n/it.d.ts +41 -5
- package/dist/i18n/ro.d.ts +41 -5
- package/dist/i18n/template.d.ts +41 -5
- package/dist/i18n/vi.d.ts +41 -5
- package/dist/model/enums.d.ts +17 -2
- package/dist/model/enums.js +92 -77
- package/dist/model/enums.js.map +1 -1
- package/dist/model/history.d.ts +32 -0
- package/dist/model/history.js +128 -0
- package/dist/model/history.js.map +1 -0
- package/dist/model/mqtt.d.ts +1 -0
- package/dist/model/mqtt.js +37 -11
- package/dist/model/mqtt.js.map +1 -1
- package/dist/model/types.d.ts +39 -4
- package/dist/tools/log.d.ts +1 -1
- package/dist/tools/log.js.map +1 -1
- package/dist/tools/properties.js +1 -1
- package/dist/tools/properties.js.map +1 -1
- package/package.json +2 -1
- package/dist/accessory/abstract/customCharacteristic.js.map +0 -1
- package/dist/accessory/button.d.ts +0 -10
- 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.
|
|
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 [
|
|
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
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
package/config.schema.json
CHANGED
|
@@ -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
|
-
"
|
|
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
|
-
"
|
|
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
|
|
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
|
|
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 {
|
|
4
|
-
import {
|
|
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(
|
|
7
|
-
|
|
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 {
|
|
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(
|
|
9
|
-
super(
|
|
10
|
-
if (!isGrouped) {
|
|
11
|
-
|
|
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(
|
|
20
|
-
this.setup(
|
|
21
|
-
this.setup(
|
|
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
|
-
|
|
24
|
-
|
|
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":"
|
|
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"}
|