@smarthome.exchange/integrations 1.0.0 → 3.0.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 +84 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/core/classes.configstore.d.ts +2 -0
- package/dist_ts/core/classes.configstore.js +84 -27
- package/dist_ts/core/classes.nativehomeadmission.d.ts +19 -0
- package/dist_ts/core/classes.nativehomeadmission.js +84 -0
- package/dist_ts/core/classes.nativeintegrationowner.d.ts +81 -0
- package/dist_ts/core/classes.nativeintegrationowner.js +273 -0
- package/dist_ts/core/classes.runtimemanager.d.ts +2 -0
- package/dist_ts/core/classes.runtimemanager.js +11 -3
- package/dist_ts/core/index.d.ts +2 -0
- package/dist_ts/core/index.js +3 -1
- package/dist_ts/core/types.d.ts +16 -0
- package/dist_ts/integrations/braviatv/braviatv.classes.client.d.ts +23 -72
- package/dist_ts/integrations/braviatv/braviatv.classes.client.js +265 -625
- package/dist_ts/integrations/braviatv/braviatv.classes.configflow.d.ts +7 -7
- package/dist_ts/integrations/braviatv/braviatv.classes.configflow.js +51 -68
- package/dist_ts/integrations/braviatv/braviatv.classes.integration.d.ts +8 -11
- package/dist_ts/integrations/braviatv/braviatv.classes.integration.js +186 -135
- package/dist_ts/integrations/braviatv/braviatv.discovery.js +12 -11
- package/dist_ts/integrations/braviatv/braviatv.mapper.d.ts +6 -14
- package/dist_ts/integrations/braviatv/braviatv.mapper.js +37 -131
- package/dist_ts/integrations/braviatv/braviatv.types.d.ts +55 -133
- package/dist_ts/integrations/braviatv/braviatv.validation.d.ts +7 -0
- package/dist_ts/integrations/braviatv/braviatv.validation.js +72 -0
- package/dist_ts/integrations/broadlink/broadlink.actions.d.ts +2 -0
- package/dist_ts/integrations/broadlink/broadlink.actions.js +36 -0
- package/dist_ts/integrations/broadlink/broadlink.classes.client.d.ts +21 -19
- package/dist_ts/integrations/broadlink/broadlink.classes.client.js +185 -124
- package/dist_ts/integrations/broadlink/broadlink.classes.configflow.d.ts +5 -4
- package/dist_ts/integrations/broadlink/broadlink.classes.configflow.js +64 -83
- package/dist_ts/integrations/broadlink/broadlink.classes.integration.d.ts +16 -19
- package/dist_ts/integrations/broadlink/broadlink.classes.integration.js +114 -59
- package/dist_ts/integrations/broadlink/broadlink.mapper.d.ts +3 -2
- package/dist_ts/integrations/broadlink/broadlink.mapper.js +2 -1
- package/dist_ts/integrations/broadlink/broadlink.selected.mapper.d.ts +10 -0
- package/dist_ts/integrations/broadlink/broadlink.selected.mapper.js +41 -0
- package/dist_ts/integrations/broadlink/broadlink.types.d.ts +43 -7
- package/dist_ts/integrations/broadlink/broadlink.validation.d.ts +7 -0
- package/dist_ts/integrations/broadlink/broadlink.validation.js +63 -0
- package/dist_ts/integrations/daikin/daikin.classes.client.d.ts +10 -52
- package/dist_ts/integrations/daikin/daikin.classes.client.js +55 -614
- package/dist_ts/integrations/daikin/daikin.classes.configflow.d.ts +8 -12
- package/dist_ts/integrations/daikin/daikin.classes.configflow.js +77 -138
- package/dist_ts/integrations/daikin/daikin.classes.integration.d.ts +7 -24
- package/dist_ts/integrations/daikin/daikin.classes.integration.js +175 -67
- package/dist_ts/integrations/daikin/daikin.discovery.d.ts +11 -24
- package/dist_ts/integrations/daikin/daikin.discovery.js +98 -305
- package/dist_ts/integrations/daikin/daikin.mapper.d.ts +6 -7
- package/dist_ts/integrations/daikin/daikin.mapper.js +95 -155
- package/dist_ts/integrations/daikin/daikin.types.d.ts +24 -44
- package/dist_ts/integrations/daikin/daikin.types.js +1 -1
- package/dist_ts/integrations/daikin/daikin.validation.d.ts +5 -0
- package/dist_ts/integrations/daikin/daikin.validation.js +53 -0
- package/dist_ts/integrations/deconz/deconz.classes.client.d.ts +37 -29
- package/dist_ts/integrations/deconz/deconz.classes.client.js +521 -294
- package/dist_ts/integrations/deconz/deconz.classes.configflow.d.ts +6 -1
- package/dist_ts/integrations/deconz/deconz.classes.configflow.js +63 -33
- package/dist_ts/integrations/deconz/deconz.classes.integration.d.ts +4 -3
- package/dist_ts/integrations/deconz/deconz.classes.integration.js +85 -40
- package/dist_ts/integrations/deconz/deconz.mapper.d.ts +1 -0
- package/dist_ts/integrations/deconz/deconz.mapper.js +24 -6
- package/dist_ts/integrations/deconz/deconz.types.d.ts +43 -6
- package/dist_ts/integrations/deconz/deconz.validation.d.ts +7 -1
- package/dist_ts/integrations/deconz/deconz.validation.js +215 -4
- package/dist_ts/integrations/denonavr/denonavr.classes.client.d.ts +31 -40
- package/dist_ts/integrations/denonavr/denonavr.classes.client.js +149 -404
- package/dist_ts/integrations/denonavr/denonavr.classes.configflow.d.ts +7 -2
- package/dist_ts/integrations/denonavr/denonavr.classes.configflow.js +44 -36
- package/dist_ts/integrations/denonavr/denonavr.classes.integration.d.ts +6 -11
- package/dist_ts/integrations/denonavr/denonavr.classes.integration.js +192 -113
- package/dist_ts/integrations/denonavr/denonavr.discovery.d.ts +10 -18
- package/dist_ts/integrations/denonavr/denonavr.discovery.js +71 -193
- package/dist_ts/integrations/denonavr/denonavr.mapper.d.ts +5 -13
- package/dist_ts/integrations/denonavr/denonavr.mapper.js +35 -159
- package/dist_ts/integrations/denonavr/denonavr.types.d.ts +55 -90
- package/dist_ts/integrations/denonavr/denonavr.validation.d.ts +10 -0
- package/dist_ts/integrations/denonavr/denonavr.validation.js +86 -0
- package/dist_ts/integrations/esphome/esphome.classes.client.d.ts +19 -7
- package/dist_ts/integrations/esphome/esphome.classes.client.js +183 -89
- package/dist_ts/integrations/esphome/esphome.classes.configflow.d.ts +5 -2
- package/dist_ts/integrations/esphome/esphome.classes.configflow.js +43 -33
- package/dist_ts/integrations/esphome/esphome.classes.integration.d.ts +8 -6
- package/dist_ts/integrations/esphome/esphome.classes.integration.js +71 -43
- package/dist_ts/integrations/esphome/esphome.discovery.js +4 -12
- package/dist_ts/integrations/esphome/esphome.mapper.d.ts +2 -2
- package/dist_ts/integrations/esphome/esphome.mapper.js +6 -4
- package/dist_ts/integrations/esphome/esphome.types.d.ts +31 -6
- package/dist_ts/integrations/esphome/esphome.types.js +1 -1
- package/dist_ts/integrations/esphome/esphome.validation.d.ts +7 -0
- package/dist_ts/integrations/esphome/esphome.validation.js +66 -0
- package/dist_ts/integrations/homeassistant/homeassistant.classes.client.d.ts +32 -4
- package/dist_ts/integrations/homeassistant/homeassistant.classes.client.js +345 -116
- package/dist_ts/integrations/homeassistant/homeassistant.classes.integration.d.ts +8 -5
- package/dist_ts/integrations/homeassistant/homeassistant.classes.integration.js +34 -8
- package/dist_ts/integrations/homeassistant/homeassistant.classes.runtime.d.ts +7 -4
- package/dist_ts/integrations/homeassistant/homeassistant.classes.runtime.js +44 -56
- package/dist_ts/integrations/homeassistant/homeassistant.types.d.ts +12 -1
- package/dist_ts/integrations/hue/hue.classes.client.d.ts +6 -1
- package/dist_ts/integrations/hue/hue.classes.client.js +120 -45
- package/dist_ts/integrations/hue/hue.classes.configflow.js +16 -7
- package/dist_ts/integrations/hue/hue.classes.integration.d.ts +2 -0
- package/dist_ts/integrations/hue/hue.classes.integration.js +103 -30
- package/dist_ts/integrations/hue/hue.validation.d.ts +1 -0
- package/dist_ts/integrations/hue/hue.validation.js +14 -4
- package/dist_ts/integrations/kodi/kodi.classes.client.d.ts +11 -45
- package/dist_ts/integrations/kodi/kodi.classes.client.js +84 -310
- package/dist_ts/integrations/kodi/kodi.classes.configflow.d.ts +9 -8
- package/dist_ts/integrations/kodi/kodi.classes.configflow.js +53 -48
- package/dist_ts/integrations/kodi/kodi.classes.integration.d.ts +11 -11
- package/dist_ts/integrations/kodi/kodi.classes.integration.js +114 -171
- package/dist_ts/integrations/kodi/kodi.discovery.js +53 -29
- package/dist_ts/integrations/kodi/kodi.mapper.d.ts +7 -2
- package/dist_ts/integrations/kodi/kodi.mapper.js +48 -10
- package/dist_ts/integrations/kodi/kodi.types.d.ts +32 -28
- package/dist_ts/integrations/kodi/kodi.validation.d.ts +9 -0
- package/dist_ts/integrations/kodi/kodi.validation.js +62 -0
- package/dist_ts/integrations/modbus/modbus.classes.client.d.ts +15 -61
- package/dist_ts/integrations/modbus/modbus.classes.client.js +117 -776
- package/dist_ts/integrations/modbus/modbus.classes.configflow.d.ts +9 -5
- package/dist_ts/integrations/modbus/modbus.classes.configflow.js +70 -38
- package/dist_ts/integrations/modbus/modbus.classes.integration.d.ts +6 -17
- package/dist_ts/integrations/modbus/modbus.classes.integration.js +133 -57
- package/dist_ts/integrations/modbus/modbus.discovery.d.ts +5 -8
- package/dist_ts/integrations/modbus/modbus.discovery.js +38 -93
- package/dist_ts/integrations/modbus/modbus.mapper.d.ts +8 -32
- package/dist_ts/integrations/modbus/modbus.mapper.js +71 -431
- package/dist_ts/integrations/modbus/modbus.types.d.ts +82 -332
- package/dist_ts/integrations/modbus/modbus.validation.d.ts +10 -0
- package/dist_ts/integrations/modbus/modbus.validation.js +128 -0
- package/dist_ts/integrations/mqtt/mqtt.classes.client.d.ts +15 -2
- package/dist_ts/integrations/mqtt/mqtt.classes.client.js +173 -23
- package/dist_ts/integrations/mqtt/mqtt.classes.configflow.d.ts +5 -1
- package/dist_ts/integrations/mqtt/mqtt.classes.configflow.js +53 -33
- package/dist_ts/integrations/mqtt/mqtt.classes.integration.d.ts +4 -1
- package/dist_ts/integrations/mqtt/mqtt.classes.integration.js +127 -56
- package/dist_ts/integrations/mqtt/mqtt.classes.session.d.ts +13 -0
- package/dist_ts/integrations/mqtt/mqtt.classes.session.js +130 -0
- package/dist_ts/integrations/mqtt/mqtt.mapper.d.ts +3 -0
- package/dist_ts/integrations/mqtt/mqtt.mapper.js +44 -1
- package/dist_ts/integrations/mqtt/mqtt.types.d.ts +46 -0
- package/dist_ts/integrations/mqtt/mqtt.validation.d.ts +7 -0
- package/dist_ts/integrations/mqtt/mqtt.validation.js +180 -0
- package/dist_ts/integrations/nanoleaf/nanoleaf.classes.client.d.ts +12 -34
- package/dist_ts/integrations/nanoleaf/nanoleaf.classes.client.js +143 -231
- package/dist_ts/integrations/nanoleaf/nanoleaf.classes.configflow.d.ts +6 -1
- package/dist_ts/integrations/nanoleaf/nanoleaf.classes.configflow.js +105 -18
- package/dist_ts/integrations/nanoleaf/nanoleaf.classes.integration.d.ts +8 -8
- package/dist_ts/integrations/nanoleaf/nanoleaf.classes.integration.js +141 -155
- package/dist_ts/integrations/nanoleaf/nanoleaf.credentials.d.ts +9 -0
- package/dist_ts/integrations/nanoleaf/nanoleaf.credentials.js +35 -0
- package/dist_ts/integrations/nanoleaf/nanoleaf.mapper.d.ts +6 -18
- package/dist_ts/integrations/nanoleaf/nanoleaf.mapper.js +45 -220
- package/dist_ts/integrations/nanoleaf/nanoleaf.types.d.ts +33 -147
- package/dist_ts/integrations/nanoleaf/nanoleaf.validation.d.ts +6 -0
- package/dist_ts/integrations/nanoleaf/nanoleaf.validation.js +82 -0
- package/dist_ts/integrations/onkyo/onkyo.classes.client.d.ts +15 -20
- package/dist_ts/integrations/onkyo/onkyo.classes.client.js +161 -404
- package/dist_ts/integrations/onkyo/onkyo.classes.configflow.d.ts +9 -4
- package/dist_ts/integrations/onkyo/onkyo.classes.configflow.js +51 -6
- package/dist_ts/integrations/onkyo/onkyo.classes.integration.d.ts +22 -6
- package/dist_ts/integrations/onkyo/onkyo.classes.integration.js +144 -11
- package/dist_ts/integrations/onkyo/onkyo.discovery.d.ts +6 -1
- package/dist_ts/integrations/onkyo/onkyo.discovery.js +40 -4
- package/dist_ts/integrations/onkyo/onkyo.mapper.d.ts +7 -8
- package/dist_ts/integrations/onkyo/onkyo.mapper.js +45 -12
- package/dist_ts/integrations/onkyo/onkyo.types.d.ts +58 -8
- package/dist_ts/integrations/onkyo/onkyo.types.js +13 -102
- package/dist_ts/integrations/onkyo/onkyo.validation.d.ts +16 -0
- package/dist_ts/integrations/onkyo/onkyo.validation.js +77 -0
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.client.d.ts +25 -25
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.client.js +116 -360
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.d.ts +11 -3
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.js +76 -6
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.integration.d.ts +26 -4
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.integration.js +142 -9
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.discovery.d.ts +2 -1
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.discovery.js +31 -4
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.mapper.d.ts +9 -9
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.mapper.js +31 -149
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.types.d.ts +51 -11
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.types.js +22 -87
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.validation.d.ts +6 -0
- package/dist_ts/integrations/panasonic_viera/panasonic_viera.validation.js +56 -0
- package/dist_ts/integrations/pioneer/pioneer.classes.client.d.ts +31 -16
- package/dist_ts/integrations/pioneer/pioneer.classes.client.js +167 -409
- package/dist_ts/integrations/pioneer/pioneer.classes.configflow.d.ts +10 -3
- package/dist_ts/integrations/pioneer/pioneer.classes.configflow.js +66 -6
- package/dist_ts/integrations/pioneer/pioneer.classes.integration.d.ts +13 -5
- package/dist_ts/integrations/pioneer/pioneer.classes.integration.js +239 -11
- package/dist_ts/integrations/pioneer/pioneer.discovery.d.ts +14 -1
- package/dist_ts/integrations/pioneer/pioneer.discovery.js +51 -4
- package/dist_ts/integrations/pioneer/pioneer.mapper.d.ts +14 -8
- package/dist_ts/integrations/pioneer/pioneer.mapper.js +54 -12
- package/dist_ts/integrations/pioneer/pioneer.types.d.ts +79 -12
- package/dist_ts/integrations/pioneer/pioneer.types.js +12 -76
- package/dist_ts/integrations/pioneer/pioneer.validation.d.ts +10 -0
- package/dist_ts/integrations/pioneer/pioneer.validation.js +85 -0
- package/dist_ts/integrations/samsungtv/samsungtv.classes.client.d.ts +4 -2
- package/dist_ts/integrations/samsungtv/samsungtv.classes.client.js +41 -16
- package/dist_ts/integrations/samsungtv/samsungtv.classes.configflow.d.ts +5 -0
- package/dist_ts/integrations/samsungtv/samsungtv.classes.configflow.js +20 -7
- package/dist_ts/integrations/samsungtv/samsungtv.classes.integration.d.ts +1 -0
- package/dist_ts/integrations/samsungtv/samsungtv.classes.integration.js +53 -50
- package/dist_ts/integrations/samsungtv/samsungtv.types.d.ts +4 -1
- package/dist_ts/integrations/shelly/shelly.classes.client.d.ts +26 -30
- package/dist_ts/integrations/shelly/shelly.classes.client.js +504 -276
- package/dist_ts/integrations/shelly/shelly.classes.configflow.d.ts +8 -3
- package/dist_ts/integrations/shelly/shelly.classes.configflow.js +43 -38
- package/dist_ts/integrations/shelly/shelly.classes.integration.d.ts +6 -6
- package/dist_ts/integrations/shelly/shelly.classes.integration.js +103 -101
- package/dist_ts/integrations/shelly/shelly.classes.subscription.d.ts +4 -0
- package/dist_ts/integrations/shelly/shelly.classes.subscription.js +24 -2
- package/dist_ts/integrations/shelly/shelly.mapper.d.ts +1 -2
- package/dist_ts/integrations/shelly/shelly.mapper.js +21 -20
- package/dist_ts/integrations/shelly/shelly.rpc.js +4 -1
- package/dist_ts/integrations/shelly/shelly.types.d.ts +42 -2
- package/dist_ts/integrations/shelly/shelly.types.js +11 -2
- package/dist_ts/integrations/shelly/shelly.validation.d.ts +7 -0
- package/dist_ts/integrations/shelly/shelly.validation.js +79 -0
- package/dist_ts/integrations/sonos/sonos.classes.client.d.ts +79 -22
- package/dist_ts/integrations/sonos/sonos.classes.client.js +427 -139
- package/dist_ts/integrations/sonos/sonos.classes.configflow.d.ts +9 -2
- package/dist_ts/integrations/sonos/sonos.classes.configflow.js +26 -28
- package/dist_ts/integrations/sonos/sonos.classes.integration.d.ts +7 -6
- package/dist_ts/integrations/sonos/sonos.classes.integration.js +289 -224
- package/dist_ts/integrations/sonos/sonos.config.d.ts +6 -1
- package/dist_ts/integrations/sonos/sonos.config.js +23 -2
- package/dist_ts/integrations/sonos/sonos.mapper.d.ts +1 -1
- package/dist_ts/integrations/sonos/sonos.mapper.js +14 -9
- package/dist_ts/integrations/sonos/sonos.matchers.js +3 -3
- package/dist_ts/integrations/sonos/sonos.types.d.ts +26 -1
- package/dist_ts/integrations/soundtouch/soundtouch.classes.client.d.ts +13 -36
- package/dist_ts/integrations/soundtouch/soundtouch.classes.client.js +179 -502
- package/dist_ts/integrations/soundtouch/soundtouch.classes.configflow.d.ts +6 -1
- package/dist_ts/integrations/soundtouch/soundtouch.classes.configflow.js +50 -40
- package/dist_ts/integrations/soundtouch/soundtouch.classes.integration.d.ts +14 -15
- package/dist_ts/integrations/soundtouch/soundtouch.classes.integration.js +108 -128
- package/dist_ts/integrations/soundtouch/soundtouch.discovery.d.ts +2 -20
- package/dist_ts/integrations/soundtouch/soundtouch.discovery.js +23 -113
- package/dist_ts/integrations/soundtouch/soundtouch.mapper.d.ts +3 -12
- package/dist_ts/integrations/soundtouch/soundtouch.mapper.js +35 -189
- package/dist_ts/integrations/soundtouch/soundtouch.types.d.ts +57 -142
- package/dist_ts/integrations/soundtouch/soundtouch.types.js +18 -3
- package/dist_ts/integrations/soundtouch/soundtouch.validation.d.ts +22 -0
- package/dist_ts/integrations/soundtouch/soundtouch.validation.js +65 -0
- package/dist_ts/integrations/tasmota/tasmota.classes.integration.d.ts +5 -0
- package/dist_ts/integrations/tasmota/tasmota.classes.integration.js +23 -7
- package/dist_ts/integrations/tasmota/tasmota.classes.runtime.d.ts +19 -5
- package/dist_ts/integrations/tasmota/tasmota.classes.runtime.js +115 -41
- package/dist_ts/integrations/tasmota/tasmota.config.js +23 -1
- package/dist_ts/integrations/tasmota/tasmota.credentials.d.ts +11 -0
- package/dist_ts/integrations/tasmota/tasmota.credentials.js +97 -0
- package/dist_ts/integrations/tasmota/tasmota.discovery.d.ts +7 -1
- package/dist_ts/integrations/tasmota/tasmota.discovery.js +108 -30
- package/dist_ts/integrations/tasmota/tasmota.mapper.d.ts +2 -2
- package/dist_ts/integrations/tasmota/tasmota.mapper.js +7 -7
- package/dist_ts/integrations/tasmota/tasmota.types.d.ts +41 -2
- package/dist_ts/integrations/tuya/tuya.classes.integration.d.ts +4 -1
- package/dist_ts/integrations/tuya/tuya.classes.integration.js +79 -110
- package/dist_ts/integrations/tuya/tuya.classes.runtime.d.ts +5 -2
- package/dist_ts/integrations/tuya/tuya.classes.runtime.js +73 -26
- package/dist_ts/integrations/tuya/tuya.mapper.js +2 -2
- package/dist_ts/integrations/tuya/tuya.types.d.ts +3 -0
- package/dist_ts/integrations/tuya/tuya.validation.d.ts +2 -2
- package/dist_ts/integrations/tuya/tuya.validation.js +6 -11
- package/dist_ts/integrations/webostv/webostv.classes.client.d.ts +6 -5
- package/dist_ts/integrations/webostv/webostv.classes.client.js +147 -76
- package/dist_ts/integrations/webostv/webostv.classes.configflow.d.ts +7 -2
- package/dist_ts/integrations/webostv/webostv.classes.configflow.js +36 -20
- package/dist_ts/integrations/webostv/webostv.classes.integration.d.ts +4 -4
- package/dist_ts/integrations/webostv/webostv.classes.integration.js +46 -54
- package/dist_ts/integrations/webostv/webostv.mapper.js +5 -5
- package/dist_ts/integrations/webostv/webostv.types.d.ts +16 -3
- package/dist_ts/integrations/webostv/webostv.types.js +1 -1
- package/dist_ts/integrations/webostv/webostv.validation.d.ts +3 -1
- package/dist_ts/integrations/webostv/webostv.validation.js +23 -1
- package/dist_ts/integrations/wiz/index.d.ts +1 -0
- package/dist_ts/integrations/wiz/index.js +2 -1
- package/dist_ts/integrations/wiz/wiz.classes.client.d.ts +14 -28
- package/dist_ts/integrations/wiz/wiz.classes.client.js +93 -229
- package/dist_ts/integrations/wiz/wiz.classes.configflow.d.ts +6 -4
- package/dist_ts/integrations/wiz/wiz.classes.configflow.js +38 -67
- package/dist_ts/integrations/wiz/wiz.classes.integration.d.ts +10 -21
- package/dist_ts/integrations/wiz/wiz.classes.integration.js +204 -44
- package/dist_ts/integrations/wiz/wiz.discovery.d.ts +10 -31
- package/dist_ts/integrations/wiz/wiz.discovery.js +48 -249
- package/dist_ts/integrations/wiz/wiz.mapper.d.ts +7 -51
- package/dist_ts/integrations/wiz/wiz.mapper.js +82 -668
- package/dist_ts/integrations/wiz/wiz.types.d.ts +34 -208
- package/dist_ts/integrations/wiz/wiz.validation.d.ts +8 -0
- package/dist_ts/integrations/wiz/wiz.validation.js +72 -0
- package/dist_ts/integrations/yamaha/index.d.ts +1 -0
- package/dist_ts/integrations/yamaha/index.js +2 -1
- package/dist_ts/integrations/yamaha/yamaha.classes.client.d.ts +30 -4
- package/dist_ts/integrations/yamaha/yamaha.classes.client.js +162 -6
- package/dist_ts/integrations/yamaha/yamaha.classes.configflow.d.ts +10 -3
- package/dist_ts/integrations/yamaha/yamaha.classes.configflow.js +106 -6
- package/dist_ts/integrations/yamaha/yamaha.classes.integration.d.ts +22 -4
- package/dist_ts/integrations/yamaha/yamaha.classes.integration.js +243 -8
- package/dist_ts/integrations/yamaha/yamaha.discovery.d.ts +13 -1
- package/dist_ts/integrations/yamaha/yamaha.discovery.js +57 -4
- package/dist_ts/integrations/yamaha/yamaha.mapper.d.ts +16 -8
- package/dist_ts/integrations/yamaha/yamaha.mapper.js +58 -12
- package/dist_ts/integrations/yamaha/yamaha.types.d.ts +73 -6
- package/dist_ts/integrations/yamaha/yamaha.types.js +8 -94
- package/dist_ts/integrations/yamaha/yamaha.validation.d.ts +12 -0
- package/dist_ts/integrations/yamaha/yamaha.validation.js +89 -0
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.configflow.d.ts +6 -1
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.configflow.js +18 -8
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.integration.d.ts +4 -1
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.integration.js +54 -6
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.runtime.d.ts +12 -6
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.runtime.js +73 -59
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.mapper.d.ts +3 -2
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.mapper.js +17 -12
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.types.d.ts +31 -2
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.validation.d.ts +9 -1
- package/dist_ts/integrations/zigbee2mqtt/zigbee2mqtt.validation.js +57 -7
- package/dist_ts/integrations/zwave_js/zwave_js.classes.client.d.ts +10 -4
- package/dist_ts/integrations/zwave_js/zwave_js.classes.client.js +167 -31
- package/dist_ts/integrations/zwave_js/zwave_js.classes.configflow.d.ts +6 -1
- package/dist_ts/integrations/zwave_js/zwave_js.classes.configflow.js +57 -35
- package/dist_ts/integrations/zwave_js/zwave_js.classes.integration.d.ts +3 -1
- package/dist_ts/integrations/zwave_js/zwave_js.classes.integration.js +59 -37
- package/dist_ts/integrations/zwave_js/zwave_js.discovery.js +3 -3
- package/dist_ts/integrations/zwave_js/zwave_js.mapper.js +41 -24
- package/dist_ts/integrations/zwave_js/zwave_js.types.d.ts +25 -3
- package/dist_ts/integrations/zwave_js/zwave_js.validation.d.ts +6 -2
- package/dist_ts/integrations/zwave_js/zwave_js.validation.js +52 -17
- package/dist_ts/plugins.d.ts +2 -1
- package/dist_ts/plugins.js +3 -2
- package/package.json +9 -9
- package/readme.md +539 -8
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/core/classes.configstore.ts +84 -27
- package/ts/core/classes.nativehomeadmission.ts +96 -0
- package/ts/core/classes.nativeintegrationowner.ts +302 -0
- package/ts/core/classes.runtimemanager.ts +11 -2
- package/ts/core/index.ts +2 -0
- package/ts/core/types.ts +18 -0
- package/ts/integrations/braviatv/braviatv.classes.client.ts +245 -709
- package/ts/integrations/braviatv/braviatv.classes.configflow.ts +47 -76
- package/ts/integrations/braviatv/braviatv.classes.integration.ts +167 -147
- package/ts/integrations/braviatv/braviatv.discovery.ts +11 -10
- package/ts/integrations/braviatv/braviatv.mapper.ts +39 -142
- package/ts/integrations/braviatv/braviatv.types.ts +53 -173
- package/ts/integrations/braviatv/braviatv.validation.ts +68 -0
- package/ts/integrations/broadlink/broadlink.actions.ts +31 -0
- package/ts/integrations/broadlink/broadlink.classes.client.ts +170 -144
- package/ts/integrations/broadlink/broadlink.classes.configflow.ts +59 -89
- package/ts/integrations/broadlink/broadlink.classes.integration.ts +110 -64
- package/ts/integrations/broadlink/broadlink.mapper.ts +5 -4
- package/ts/integrations/broadlink/broadlink.selected.mapper.ts +46 -0
- package/ts/integrations/broadlink/broadlink.types.ts +48 -8
- package/ts/integrations/broadlink/broadlink.validation.ts +66 -0
- package/ts/integrations/daikin/daikin.classes.client.ts +52 -661
- package/ts/integrations/daikin/daikin.classes.configflow.ts +72 -152
- package/ts/integrations/daikin/daikin.classes.integration.ts +166 -71
- package/ts/integrations/daikin/daikin.discovery.ts +94 -346
- package/ts/integrations/daikin/daikin.mapper.ts +83 -166
- package/ts/integrations/daikin/daikin.types.ts +27 -48
- package/ts/integrations/daikin/daikin.validation.ts +51 -0
- package/ts/integrations/daikin/readme.md +83 -0
- package/ts/integrations/deconz/deconz.classes.client.ts +348 -252
- package/ts/integrations/deconz/deconz.classes.configflow.ts +57 -29
- package/ts/integrations/deconz/deconz.classes.integration.ts +69 -37
- package/ts/integrations/deconz/deconz.mapper.ts +22 -5
- package/ts/integrations/deconz/deconz.types.ts +49 -6
- package/ts/integrations/deconz/deconz.validation.ts +177 -4
- package/ts/integrations/deconz/readme.md +15 -1
- package/ts/integrations/denonavr/denonavr.classes.client.ts +132 -421
- package/ts/integrations/denonavr/denonavr.classes.configflow.ts +44 -37
- package/ts/integrations/denonavr/denonavr.classes.integration.ts +171 -117
- package/ts/integrations/denonavr/denonavr.discovery.ts +67 -220
- package/ts/integrations/denonavr/denonavr.mapper.ts +36 -182
- package/ts/integrations/denonavr/denonavr.types.ts +48 -111
- package/ts/integrations/denonavr/denonavr.validation.ts +87 -0
- package/ts/integrations/esphome/esphome.classes.client.ts +179 -94
- package/ts/integrations/esphome/esphome.classes.configflow.ts +40 -33
- package/ts/integrations/esphome/esphome.classes.integration.ts +63 -36
- package/ts/integrations/esphome/esphome.discovery.ts +3 -12
- package/ts/integrations/esphome/esphome.mapper.ts +9 -7
- package/ts/integrations/esphome/esphome.types.ts +35 -6
- package/ts/integrations/esphome/esphome.validation.ts +66 -0
- package/ts/integrations/esphome/readme.md +20 -6
- package/ts/integrations/homeassistant/homeassistant.classes.client.ts +353 -125
- package/ts/integrations/homeassistant/homeassistant.classes.integration.ts +35 -18
- package/ts/integrations/homeassistant/homeassistant.classes.runtime.ts +50 -63
- package/ts/integrations/homeassistant/homeassistant.types.ts +17 -1
- package/ts/integrations/homeassistant/readme.md +22 -6
- package/ts/integrations/hue/hue.classes.client.ts +110 -41
- package/ts/integrations/hue/hue.classes.configflow.ts +12 -6
- package/ts/integrations/hue/hue.classes.integration.ts +92 -26
- package/ts/integrations/hue/hue.validation.ts +13 -3
- package/ts/integrations/hue/readme.md +3 -3
- package/ts/integrations/kodi/kodi.classes.client.ts +72 -352
- package/ts/integrations/kodi/kodi.classes.configflow.ts +52 -55
- package/ts/integrations/kodi/kodi.classes.integration.ts +97 -178
- package/ts/integrations/kodi/kodi.discovery.ts +49 -28
- package/ts/integrations/kodi/kodi.mapper.ts +52 -10
- package/ts/integrations/kodi/kodi.types.ts +33 -58
- package/ts/integrations/kodi/kodi.validation.ts +60 -0
- package/ts/integrations/modbus/modbus.classes.client.ts +100 -842
- package/ts/integrations/modbus/modbus.classes.configflow.ts +70 -41
- package/ts/integrations/modbus/modbus.classes.integration.ts +115 -60
- package/ts/integrations/modbus/modbus.discovery.ts +38 -106
- package/ts/integrations/modbus/modbus.mapper.ts +64 -467
- package/ts/integrations/modbus/modbus.types.ts +64 -381
- package/ts/integrations/modbus/modbus.validation.ts +119 -0
- package/ts/integrations/mqtt/mqtt.classes.client.ts +136 -19
- package/ts/integrations/mqtt/mqtt.classes.configflow.ts +45 -32
- package/ts/integrations/mqtt/mqtt.classes.integration.ts +99 -38
- package/ts/integrations/mqtt/mqtt.classes.session.ts +118 -0
- package/ts/integrations/mqtt/mqtt.mapper.ts +43 -1
- package/ts/integrations/mqtt/mqtt.types.ts +52 -0
- package/ts/integrations/mqtt/mqtt.validation.ts +157 -0
- package/ts/integrations/mqtt/readme.md +12 -3
- package/ts/integrations/nanoleaf/nanoleaf.classes.client.ts +115 -249
- package/ts/integrations/nanoleaf/nanoleaf.classes.configflow.ts +90 -19
- package/ts/integrations/nanoleaf/nanoleaf.classes.integration.ts +130 -181
- package/ts/integrations/nanoleaf/nanoleaf.credentials.ts +39 -0
- package/ts/integrations/nanoleaf/nanoleaf.mapper.ts +47 -260
- package/ts/integrations/nanoleaf/nanoleaf.types.ts +29 -147
- package/ts/integrations/nanoleaf/nanoleaf.validation.ts +77 -0
- package/ts/integrations/onkyo/onkyo.classes.client.ts +148 -457
- package/ts/integrations/onkyo/onkyo.classes.configflow.ts +52 -6
- package/ts/integrations/onkyo/onkyo.classes.integration.ts +121 -12
- package/ts/integrations/onkyo/onkyo.discovery.ts +41 -3
- package/ts/integrations/onkyo/onkyo.mapper.ts +46 -19
- package/ts/integrations/onkyo/onkyo.types.ts +55 -110
- package/ts/integrations/onkyo/onkyo.validation.ts +85 -0
- package/ts/integrations/onkyo/readme.md +126 -0
- package/ts/integrations/panasonic_viera/panasonic_viera.classes.client.ts +101 -398
- package/ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.ts +69 -5
- package/ts/integrations/panasonic_viera/panasonic_viera.classes.integration.ts +141 -9
- package/ts/integrations/panasonic_viera/panasonic_viera.discovery.ts +32 -3
- package/ts/integrations/panasonic_viera/panasonic_viera.mapper.ts +34 -161
- package/ts/integrations/panasonic_viera/panasonic_viera.types.ts +52 -96
- package/ts/integrations/panasonic_viera/panasonic_viera.validation.ts +56 -0
- package/ts/integrations/pioneer/pioneer.classes.client.ts +132 -428
- package/ts/integrations/pioneer/pioneer.classes.configflow.ts +67 -5
- package/ts/integrations/pioneer/pioneer.classes.integration.ts +225 -11
- package/ts/integrations/pioneer/pioneer.discovery.ts +45 -3
- package/ts/integrations/pioneer/pioneer.mapper.ts +57 -13
- package/ts/integrations/pioneer/pioneer.types.ts +87 -85
- package/ts/integrations/pioneer/pioneer.validation.ts +84 -0
- package/ts/integrations/samsungtv/readme.md +11 -5
- package/ts/integrations/samsungtv/samsungtv.classes.client.ts +40 -15
- package/ts/integrations/samsungtv/samsungtv.classes.configflow.ts +21 -6
- package/ts/integrations/samsungtv/samsungtv.classes.integration.ts +53 -38
- package/ts/integrations/samsungtv/samsungtv.types.ts +4 -1
- package/ts/integrations/shelly/readme.md +22 -7
- package/ts/integrations/shelly/shelly.classes.client.ts +386 -269
- package/ts/integrations/shelly/shelly.classes.configflow.ts +43 -38
- package/ts/integrations/shelly/shelly.classes.integration.ts +92 -111
- package/ts/integrations/shelly/shelly.classes.subscription.ts +24 -1
- package/ts/integrations/shelly/shelly.mapper.ts +19 -20
- package/ts/integrations/shelly/shelly.rpc.ts +2 -0
- package/ts/integrations/shelly/shelly.types.ts +50 -2
- package/ts/integrations/shelly/shelly.validation.ts +76 -0
- package/ts/integrations/sonos/readme.md +117 -38
- package/ts/integrations/sonos/sonos.classes.client.ts +392 -123
- package/ts/integrations/sonos/sonos.classes.configflow.ts +25 -28
- package/ts/integrations/sonos/sonos.classes.integration.ts +211 -186
- package/ts/integrations/sonos/sonos.config.ts +24 -2
- package/ts/integrations/sonos/sonos.mapper.ts +13 -8
- package/ts/integrations/sonos/sonos.matchers.ts +2 -2
- package/ts/integrations/sonos/sonos.types.ts +30 -1
- package/ts/integrations/soundtouch/soundtouch.classes.client.ts +152 -571
- package/ts/integrations/soundtouch/soundtouch.classes.configflow.ts +47 -42
- package/ts/integrations/soundtouch/soundtouch.classes.integration.ts +95 -150
- package/ts/integrations/soundtouch/soundtouch.discovery.ts +21 -133
- package/ts/integrations/soundtouch/soundtouch.mapper.ts +36 -207
- package/ts/integrations/soundtouch/soundtouch.types.ts +50 -195
- package/ts/integrations/soundtouch/soundtouch.validation.ts +60 -0
- package/ts/integrations/tasmota/readme.md +16 -5
- package/ts/integrations/tasmota/tasmota.classes.integration.ts +24 -6
- package/ts/integrations/tasmota/tasmota.classes.runtime.ts +112 -43
- package/ts/integrations/tasmota/tasmota.config.ts +17 -0
- package/ts/integrations/tasmota/tasmota.credentials.ts +92 -0
- package/ts/integrations/tasmota/tasmota.discovery.ts +87 -24
- package/ts/integrations/tasmota/tasmota.mapper.ts +6 -6
- package/ts/integrations/tasmota/tasmota.types.ts +43 -2
- package/ts/integrations/tuya/readme.md +52 -10
- package/ts/integrations/tuya/tuya.classes.integration.ts +69 -98
- package/ts/integrations/tuya/tuya.classes.runtime.ts +70 -24
- package/ts/integrations/tuya/tuya.mapper.ts +1 -1
- package/ts/integrations/tuya/tuya.types.ts +4 -0
- package/ts/integrations/tuya/tuya.validation.ts +5 -8
- package/ts/integrations/webostv/readme.md +115 -22
- package/ts/integrations/webostv/webostv.classes.client.ts +123 -50
- package/ts/integrations/webostv/webostv.classes.configflow.ts +35 -15
- package/ts/integrations/webostv/webostv.classes.integration.ts +44 -37
- package/ts/integrations/webostv/webostv.mapper.ts +4 -4
- package/ts/integrations/webostv/webostv.types.ts +18 -3
- package/ts/integrations/webostv/webostv.validation.ts +22 -1
- package/ts/integrations/wiz/index.ts +1 -0
- package/ts/integrations/wiz/wiz.classes.client.ts +84 -254
- package/ts/integrations/wiz/wiz.classes.configflow.ts +39 -70
- package/ts/integrations/wiz/wiz.classes.integration.ts +189 -45
- package/ts/integrations/wiz/wiz.discovery.ts +48 -291
- package/ts/integrations/wiz/wiz.mapper.ts +81 -754
- package/ts/integrations/wiz/wiz.types.ts +24 -224
- package/ts/integrations/wiz/wiz.validation.ts +73 -0
- package/ts/integrations/yamaha/index.ts +1 -0
- package/ts/integrations/yamaha/yamaha.classes.client.ts +150 -6
- package/ts/integrations/yamaha/yamaha.classes.configflow.ts +100 -5
- package/ts/integrations/yamaha/yamaha.classes.integration.ts +236 -8
- package/ts/integrations/yamaha/yamaha.discovery.ts +52 -3
- package/ts/integrations/yamaha/yamaha.mapper.ts +65 -13
- package/ts/integrations/yamaha/yamaha.types.ts +77 -97
- package/ts/integrations/yamaha/yamaha.validation.ts +86 -0
- package/ts/integrations/zigbee2mqtt/readme.md +22 -27
- package/ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.configflow.ts +16 -7
- package/ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.integration.ts +53 -6
- package/ts/integrations/zigbee2mqtt/zigbee2mqtt.classes.runtime.ts +62 -49
- package/ts/integrations/zigbee2mqtt/zigbee2mqtt.mapper.ts +17 -11
- package/ts/integrations/zigbee2mqtt/zigbee2mqtt.types.ts +35 -2
- package/ts/integrations/zigbee2mqtt/zigbee2mqtt.validation.ts +53 -7
- package/ts/integrations/zwave_js/readme.md +42 -9
- package/ts/integrations/zwave_js/zwave_js.classes.client.ts +155 -31
- package/ts/integrations/zwave_js/zwave_js.classes.configflow.ts +55 -31
- package/ts/integrations/zwave_js/zwave_js.classes.integration.ts +57 -35
- package/ts/integrations/zwave_js/zwave_js.discovery.ts +2 -2
- package/ts/integrations/zwave_js/zwave_js.mapper.ts +37 -23
- package/ts/integrations/zwave_js/zwave_js.types.ts +26 -3
- package/ts/integrations/zwave_js/zwave_js.validation.ts +52 -18
- package/ts/plugins.ts +2 -1
|
@@ -1,216 +1,135 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
2
|
import { BaseIntegration } from '../../core/classes.baseintegration.js';
|
|
3
|
-
import
|
|
3
|
+
import { NativeIntegrationOwner, type INativeSetupLease } from '../../core/classes.nativeintegrationowner.js';
|
|
4
|
+
import type { IDeviceFeatureWriteRequest, IIntegrationEntity, IIntegrationRuntime, IServiceCallRequest, IServiceCallResult } from '../../core/types.js';
|
|
4
5
|
import { KodiClient } from './kodi.classes.client.js';
|
|
5
6
|
import { KodiConfigFlow } from './kodi.classes.configflow.js';
|
|
6
7
|
import { createKodiDiscoveryDescriptor } from './kodi.discovery.js';
|
|
7
8
|
import { KodiMapper } from './kodi.mapper.js';
|
|
8
|
-
import type { IKodiConfig,
|
|
9
|
+
import type { IKodiConfig, IKodiIntegrationOptions, IKodiNativeSnapshot, IKodiSetupContext } from './kodi.types.js';
|
|
10
|
+
import { kodiBoolean, kodiInteger, kodiKeys, kodiRecord, kodiSignal, normalizeKodiConfig } from './kodi.validation.js';
|
|
9
11
|
|
|
10
12
|
export class KodiIntegration extends BaseIntegration<IKodiConfig> {
|
|
11
13
|
public readonly domain = 'kodi';
|
|
12
14
|
public readonly displayName = 'Kodi';
|
|
13
15
|
public readonly status = 'control-runtime' as const;
|
|
14
16
|
public readonly discoveryDescriptor = createKodiDiscoveryDescriptor();
|
|
15
|
-
public readonly configFlow
|
|
17
|
+
public readonly configFlow: KodiConfigFlow;
|
|
16
18
|
public readonly metadata = {
|
|
17
|
-
source: '
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
iotClass: 'local_push',
|
|
22
|
-
requirements: ['pykodi==0.2.7'],
|
|
23
|
-
dependencies: [],
|
|
24
|
-
afterDependencies: ['media_source'],
|
|
25
|
-
codeowners: ['@OnFreund'],
|
|
26
|
-
configFlow: true,
|
|
27
|
-
documentation: 'https://www.home-assistant.io/integrations/kodi',
|
|
19
|
+
source: 'native-typescript', integrationType: 'device', iotClass: 'local_poll',
|
|
20
|
+
localApi: { status: 'Selected Kodi HTTP JSON-RPC API13 through devicemanager.',
|
|
21
|
+
implemented: ['fresh application observation', 'read-only default', 'explicit owner-trusted absolute volume and boolean mute', 'home-scoped endpoint targets', 'joined terminal lifetime'],
|
|
22
|
+
explicitUnsupported: ['unique or cryptographic server identity', 'arbitrary JSON-RPC', 'media transport', 'library and power operations', 'toggle or increment', 'notification transport', 'retry or replay', 'Home Assistant bridge'] },
|
|
28
23
|
};
|
|
24
|
+
readonly #owner: NativeIntegrationOwner;
|
|
25
|
+
#getBasicCredentials?: IKodiIntegrationOptions['getBasicCredentials'];
|
|
26
|
+
#closePromise?: Promise<void>;
|
|
29
27
|
|
|
30
|
-
public
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
public constructor(options: IKodiIntegrationOptions = {}) {
|
|
29
|
+
super();
|
|
30
|
+
const value = kodiRecord(options, 'integration options');
|
|
31
|
+
kodiKeys(value, ['homeId', 'getBasicCredentials']);
|
|
32
|
+
if (value.getBasicCredentials !== undefined && typeof value.getBasicCredentials !== 'function') throw new TypeError('Kodi Basic provider must be a function.');
|
|
33
|
+
this.#owner = new NativeIntegrationOwner('kodi', { homeId: value.homeId as string | undefined });
|
|
34
|
+
this.#getBasicCredentials = value.getBasicCredentials as IKodiIntegrationOptions['getBasicCredentials'];
|
|
35
|
+
this.configFlow = new KodiConfigFlow(this.#owner);
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
public
|
|
38
|
+
public setup(config: IKodiConfig, context: IKodiSetupContext): Promise<IIntegrationRuntime> {
|
|
39
|
+
try {
|
|
40
|
+
const captured = normalizeKodiConfig(config);
|
|
41
|
+
return this.#owner.runSetup(context, captured.homeId, async (lease) => {
|
|
42
|
+
const client = new KodiClient(captured, { ...lease.context, abortSignal: lease.signal }, { getBasicCredentials: this.#getBasicCredentials });
|
|
43
|
+
lease.own(() => client.destroy());
|
|
44
|
+
const initial = await client.getSnapshot();
|
|
45
|
+
lease.assertOpen();
|
|
46
|
+
const runtime = new KodiRuntime(client, initial, lease);
|
|
47
|
+
lease.promoteToRuntime();
|
|
48
|
+
return runtime;
|
|
49
|
+
});
|
|
50
|
+
} catch (error) { return Promise.reject(error); }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public destroy(): Promise<void> {
|
|
54
|
+
if (!this.#closePromise) {
|
|
55
|
+
this.#closePromise = Promise.resolve().then(async () => {
|
|
56
|
+
try { await this.#owner.close(); }
|
|
57
|
+
finally { this.#getBasicCredentials = undefined; }
|
|
58
|
+
});
|
|
59
|
+
// Install the facade memo before synchronously closing admission or dispatching abort.
|
|
60
|
+
void this.#owner.close().catch(() => undefined);
|
|
61
|
+
}
|
|
62
|
+
return this.#closePromise;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public retryCleanup(): Promise<void> { return this.#owner.retryCleanup(); }
|
|
36
66
|
}
|
|
37
67
|
|
|
38
68
|
export class HomeAssistantKodiIntegration extends KodiIntegration {}
|
|
39
69
|
|
|
40
70
|
class KodiRuntime implements IIntegrationRuntime {
|
|
41
|
-
public domain = 'kodi';
|
|
42
|
-
|
|
43
|
-
|
|
71
|
+
public readonly domain = 'kodi';
|
|
72
|
+
readonly #deviceId: string;
|
|
73
|
+
readonly #entityId: string;
|
|
44
74
|
|
|
45
|
-
public
|
|
46
|
-
|
|
75
|
+
public constructor(private readonly client: KodiClient, initial: IKodiNativeSnapshot, private readonly lease: INativeSetupLease) {
|
|
76
|
+
this.#deviceId = KodiMapper.deviceId(initial);
|
|
77
|
+
this.#entityId = KodiMapper.entityId(initial);
|
|
47
78
|
}
|
|
48
79
|
|
|
49
|
-
public
|
|
50
|
-
|
|
51
|
-
}
|
|
80
|
+
public isHealthy(): boolean { return this.client.isHealthy(); }
|
|
81
|
+
public async devices(signal?: AbortSignal): Promise<plugins.shxInterfaces.data.IDeviceDefinition[]> { return KodiMapper.toNativeDevices(await this.client.getSnapshot(signal)); }
|
|
82
|
+
public async entities(): Promise<IIntegrationEntity[]> { return KodiMapper.toNativeEntities(await this.client.getSnapshot()); }
|
|
52
83
|
|
|
53
|
-
public async callService(
|
|
84
|
+
public async callService(input: IServiceCallRequest): Promise<IServiceCallResult> {
|
|
54
85
|
try {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
86
|
+
const request = kodiRecord(input, 'service request');
|
|
87
|
+
kodiKeys(request, ['domain', 'service', 'target', 'data']);
|
|
88
|
+
this.assertTarget(request.target);
|
|
89
|
+
const data = request.data === undefined ? {} : kodiRecord(request.data, 'service data');
|
|
90
|
+
if (request.domain === 'kodi' && request.service === 'snapshot') {
|
|
91
|
+
kodiKeys(data, []); return { success: true, data: await this.client.getSnapshot() };
|
|
60
92
|
}
|
|
61
|
-
if (
|
|
62
|
-
return await this.
|
|
93
|
+
if (request.domain === 'kodi' && request.service === 'set_volume') {
|
|
94
|
+
kodiKeys(data, ['volume']); return { success: true, data: await this.client.setVolume(kodiInteger(data.volume, 0, 100, 'absolute volume')) };
|
|
63
95
|
}
|
|
64
|
-
if (
|
|
65
|
-
return await this.
|
|
96
|
+
if ((request.domain === 'kodi' && request.service === 'set_muted') || (request.domain === 'media_player' && request.service === 'volume_mute')) {
|
|
97
|
+
kodiKeys(data, ['muted']); return { success: true, data: await this.client.setMuted(kodiBoolean(data.muted)) };
|
|
66
98
|
}
|
|
67
|
-
|
|
68
|
-
} catch (
|
|
69
|
-
return { success: false, error: errorArg instanceof Error ? errorArg.message : String(errorArg) };
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
public async destroy(): Promise<void> {
|
|
74
|
-
await this.client.destroy();
|
|
99
|
+
throw new TypeError('Kodi service is unsupported; only snapshot, absolute volume and explicit mute are admitted.');
|
|
100
|
+
} catch (error) { return kodiFailure(error); }
|
|
75
101
|
}
|
|
76
102
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
await this.client.
|
|
87
|
-
return { success: true };
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
await this.client.pause();
|
|
91
|
-
return { success: true };
|
|
92
|
-
}
|
|
93
|
-
if (requestArg.service === 'play_pause' || requestArg.service === 'media_play_pause') {
|
|
94
|
-
await this.client.playPause();
|
|
95
|
-
return { success: true };
|
|
96
|
-
}
|
|
97
|
-
if (requestArg.service === 'stop' || requestArg.service === 'media_stop') {
|
|
98
|
-
await this.client.stop();
|
|
99
|
-
return { success: true };
|
|
100
|
-
}
|
|
101
|
-
if (requestArg.service === 'next_track' || requestArg.service === 'media_next_track') {
|
|
102
|
-
await this.client.nextTrack();
|
|
103
|
-
return { success: true };
|
|
104
|
-
}
|
|
105
|
-
if (requestArg.service === 'previous_track' || requestArg.service === 'media_previous_track') {
|
|
106
|
-
await this.client.previousTrack();
|
|
107
|
-
return { success: true };
|
|
108
|
-
}
|
|
109
|
-
if (requestArg.service === 'seek' || requestArg.service === 'media_seek') {
|
|
110
|
-
const position = requestArg.data?.seek_position ?? requestArg.data?.position;
|
|
111
|
-
if (typeof position !== 'number') {
|
|
112
|
-
return { success: false, error: 'Kodi seek requires data.seek_position.' };
|
|
113
|
-
}
|
|
114
|
-
await this.client.seek(position);
|
|
115
|
-
return { success: true };
|
|
116
|
-
}
|
|
117
|
-
if (requestArg.service === 'volume_set') {
|
|
118
|
-
const level = requestArg.data?.volume_level;
|
|
119
|
-
if (typeof level !== 'number') {
|
|
120
|
-
return { success: false, error: 'Kodi volume_set requires data.volume_level.' };
|
|
121
|
-
}
|
|
122
|
-
await this.client.setVolumeLevel(level);
|
|
123
|
-
return { success: true };
|
|
124
|
-
}
|
|
125
|
-
if (requestArg.service === 'volume_up' || requestArg.service === 'volume_down') {
|
|
126
|
-
await this.client.stepVolume(requestArg.service === 'volume_up' ? 'increment' : 'decrement');
|
|
127
|
-
return { success: true };
|
|
128
|
-
}
|
|
129
|
-
if (requestArg.service === 'volume_mute') {
|
|
130
|
-
const muted = requestArg.data?.is_volume_muted ?? requestArg.data?.muted;
|
|
131
|
-
if (typeof muted !== 'boolean') {
|
|
132
|
-
return { success: false, error: 'Kodi volume_mute requires data.is_volume_muted.' };
|
|
133
|
-
}
|
|
134
|
-
await this.client.setMuted(muted);
|
|
135
|
-
return { success: true };
|
|
136
|
-
}
|
|
137
|
-
if (requestArg.service === 'play_media') {
|
|
138
|
-
const mediaId = requestArg.data?.media_content_id ?? requestArg.data?.uri;
|
|
139
|
-
const mediaType = requestArg.data?.media_content_type ?? requestArg.data?.media_type ?? 'file';
|
|
140
|
-
if ((typeof mediaId !== 'string' && typeof mediaId !== 'number') || mediaId === '') {
|
|
141
|
-
return { success: false, error: 'Kodi play_media requires data.media_content_id or data.uri.' };
|
|
142
|
-
}
|
|
143
|
-
await this.client.playMedia(typeof mediaType === 'string' ? mediaType : 'file', mediaId);
|
|
144
|
-
return { success: true };
|
|
145
|
-
}
|
|
146
|
-
return { success: false, error: `Unsupported Kodi media_player service: ${requestArg.service}` };
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
private async callKodiService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
|
|
150
|
-
if (requestArg.service === 'call_method') {
|
|
151
|
-
const method = requestArg.data?.method;
|
|
152
|
-
if (typeof method !== 'string' || !method) {
|
|
153
|
-
return { success: false, error: 'Kodi call_method requires data.method.' };
|
|
154
|
-
}
|
|
155
|
-
const params = this.callMethodParams(requestArg);
|
|
156
|
-
return { success: true, data: await this.client.callMethod(method, params) };
|
|
157
|
-
}
|
|
158
|
-
if (requestArg.service === 'add_to_playlist') {
|
|
159
|
-
const mediaType = requestArg.data?.media_type;
|
|
160
|
-
const mediaId = requestArg.data?.media_id;
|
|
161
|
-
if (typeof mediaType !== 'string' || (typeof mediaId !== 'string' && typeof mediaId !== 'number')) {
|
|
162
|
-
return { success: false, error: 'Kodi add_to_playlist requires data.media_type and data.media_id.' };
|
|
163
|
-
}
|
|
164
|
-
await this.client.addToPlaylist(mediaType as TKodiMediaType, mediaId);
|
|
165
|
-
return { success: true };
|
|
166
|
-
}
|
|
167
|
-
if (requestArg.service === 'show_notification') {
|
|
168
|
-
return this.callNotifyService(requestArg);
|
|
169
|
-
}
|
|
170
|
-
return { success: false, error: `Unsupported Kodi service: ${requestArg.service}` };
|
|
103
|
+
public async writeFeature(input: IDeviceFeatureWriteRequest, signal?: AbortSignal): Promise<IServiceCallResult> {
|
|
104
|
+
try {
|
|
105
|
+
kodiSignal(signal);
|
|
106
|
+
const request = kodiRecord(input, 'feature write');
|
|
107
|
+
kodiKeys(request, ['device', 'feature', 'value']);
|
|
108
|
+
const device = kodiRecord(request.device, 'feature device');
|
|
109
|
+
const feature = kodiRecord(request.feature, 'feature');
|
|
110
|
+
if (device.id !== this.#deviceId || device.integrationDomain !== 'kodi') throw new TypeError('Kodi feature target is outside this home and selected endpoint.');
|
|
111
|
+
if (feature.capability !== 'media') throw new TypeError('Kodi feature capability differs from the canonical feature.');
|
|
112
|
+
if (feature.id === 'volume') return { success: true, data: await this.client.setVolume(kodiInteger(request.value, 0, 100, 'absolute volume'), signal) };
|
|
113
|
+
if (feature.id === 'muted') return { success: true, data: await this.client.setMuted(kodiBoolean(request.value), signal) };
|
|
114
|
+
throw new TypeError('Kodi feature is not writable.');
|
|
115
|
+
} catch (error) { return kodiFailure(error); }
|
|
171
116
|
}
|
|
172
117
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if (typeof message !== 'string') {
|
|
176
|
-
return { success: false, error: 'Kodi notification requires data.message.' };
|
|
177
|
-
}
|
|
178
|
-
const title = typeof requestArg.data?.title === 'string' ? requestArg.data.title : 'Home Assistant';
|
|
179
|
-
const icon = typeof requestArg.data?.icon === 'string' ? requestArg.data.icon : 'info';
|
|
180
|
-
const displayTime = typeof requestArg.data?.displaytime === 'number' ? requestArg.data.displaytime : 10000;
|
|
181
|
-
await this.client.showNotification(title, message, icon, displayTime);
|
|
182
|
-
return { success: true };
|
|
118
|
+
public destroy(): Promise<void> {
|
|
119
|
+
return this.lease.close();
|
|
183
120
|
}
|
|
184
121
|
|
|
185
|
-
private
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (!commands.length) {
|
|
192
|
-
return { success: false, error: 'Kodi remote.send_command requires data.command.' };
|
|
193
|
-
}
|
|
194
|
-
for (const item of commands) {
|
|
195
|
-
await this.client.input(item);
|
|
196
|
-
}
|
|
197
|
-
return { success: true };
|
|
122
|
+
private assertTarget(input: unknown): void {
|
|
123
|
+
const target = kodiRecord(input, 'service target');
|
|
124
|
+
kodiKeys(target, ['deviceId', 'entityId']);
|
|
125
|
+
if (target.deviceId === undefined && target.entityId === undefined ||
|
|
126
|
+
target.deviceId !== undefined && target.deviceId !== this.#deviceId ||
|
|
127
|
+
target.entityId !== undefined && target.entityId !== this.#entityId) throw new TypeError('Kodi requires an exact owned device or entity target.');
|
|
198
128
|
}
|
|
129
|
+
}
|
|
199
130
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
if (explicitParams && typeof explicitParams === 'object') {
|
|
206
|
-
return explicitParams as Record<string, unknown>;
|
|
207
|
-
}
|
|
208
|
-
const params: Record<string, unknown> = {};
|
|
209
|
-
for (const [key, value] of Object.entries(requestArg.data || {})) {
|
|
210
|
-
if (key !== 'method') {
|
|
211
|
-
params[key] = value;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return Object.keys(params).length ? params : undefined;
|
|
215
|
-
}
|
|
131
|
+
function kodiFailure(error: unknown): IServiceCallResult {
|
|
132
|
+
const protocolError = error instanceof plugins.ecobridgeDeviceManager.KodiProtocolError ? error : undefined;
|
|
133
|
+
return { success: false, error: protocolError?.message ?? 'Kodi operation was refused or failed.',
|
|
134
|
+
data: { code: protocolError?.code ?? 'invalid-operation', effectOutcome: protocolError?.effectOutcome ?? 'not-sent', ...(protocolError?.rpcErrorCode === undefined ? {} : { rpcErrorCode: protocolError.rpcErrorCode }) } };
|
|
216
135
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
1
2
|
import { DiscoveryDescriptor } from '../../core/classes.discoverydescriptor.js';
|
|
2
3
|
import type { IDiscoveryCandidate, IDiscoveryMatch, IDiscoveryMatcher, IDiscoveryValidator } from '../../core/types.js';
|
|
3
4
|
import type { IKodiManualEntry, IKodiMdnsRecord } from './kodi.types.js';
|
|
4
5
|
|
|
5
6
|
const defaultPort = 8080;
|
|
6
|
-
const defaultWsPort = 9090;
|
|
7
7
|
const kodiMdnsType = '_xbmc-jsonrpc-h._tcp.local';
|
|
8
8
|
|
|
9
9
|
export class KodiMdnsMatcher implements IDiscoveryMatcher<IKodiMdnsRecord> {
|
|
@@ -20,25 +20,33 @@ export class KodiMdnsMatcher implements IDiscoveryMatcher<IKodiMdnsRecord> {
|
|
|
20
20
|
if (!matched) {
|
|
21
21
|
return { matched: false, confidence: 'low', reason: 'mDNS record is not a Kodi JSON-RPC advertisement.' };
|
|
22
22
|
}
|
|
23
|
+
let endpoint = kodiEndpoint(recordArg.host, recordArg.port);
|
|
24
|
+
for (const address of recordArg.addresses || []) {
|
|
25
|
+
if (endpoint) break;
|
|
26
|
+
endpoint = kodiEndpoint(address, recordArg.port);
|
|
27
|
+
}
|
|
28
|
+
if (!endpoint) {
|
|
29
|
+
return { matched: false, confidence: 'low', reason: 'Kodi advertisement does not contain a supported numeric HTTP endpoint.' };
|
|
30
|
+
}
|
|
23
31
|
return {
|
|
24
32
|
matched: true,
|
|
25
|
-
confidence:
|
|
26
|
-
reason: 'mDNS record
|
|
27
|
-
normalizedDeviceId: uuid,
|
|
33
|
+
confidence: 'high',
|
|
34
|
+
reason: 'mDNS record is a Kodi endpoint hint; application selection still requires a live observation.',
|
|
28
35
|
candidate: {
|
|
29
36
|
source: 'mdns',
|
|
30
37
|
integrationDomain: 'kodi',
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
port: recordArg.port || defaultPort,
|
|
38
|
+
host: endpoint.host,
|
|
39
|
+
port: endpoint.port,
|
|
34
40
|
name,
|
|
35
41
|
manufacturer: 'Kodi',
|
|
36
42
|
model: valueForKey(properties, 'version') ? 'Kodi Media Center' : undefined,
|
|
37
43
|
metadata: {
|
|
38
44
|
mdnsName: recordArg.name,
|
|
39
45
|
mdnsType: recordArg.type,
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
mdnsHost: recordArg.host,
|
|
47
|
+
advertisedId: uuid,
|
|
48
|
+
advertisedVersion: valueForKey(properties, 'version'),
|
|
49
|
+
selectionVerified: false,
|
|
42
50
|
},
|
|
43
51
|
},
|
|
44
52
|
};
|
|
@@ -51,30 +59,24 @@ export class KodiManualMatcher implements IDiscoveryMatcher<IKodiManualEntry> {
|
|
|
51
59
|
public description = 'Recognize manual Kodi setup entries.';
|
|
52
60
|
|
|
53
61
|
public async matches(inputArg: IKodiManualEntry): Promise<IDiscoveryMatch> {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return { matched: false, confidence: 'low', reason: 'Manual entry does not contain Kodi setup hints.' };
|
|
62
|
+
const endpoint = kodiEndpoint(inputArg.host, inputArg.port);
|
|
63
|
+
if (!endpoint) {
|
|
64
|
+
return { matched: false, confidence: 'low', reason: 'Manual Kodi setup requires a supported numeric HTTP endpoint.' };
|
|
58
65
|
}
|
|
59
|
-
const id = inputArg.uuid || inputArg.id;
|
|
60
66
|
return {
|
|
61
67
|
matched: true,
|
|
62
|
-
confidence:
|
|
68
|
+
confidence: 'high',
|
|
63
69
|
reason: 'Manual entry can start Kodi setup.',
|
|
64
|
-
normalizedDeviceId: id,
|
|
65
70
|
candidate: {
|
|
66
71
|
source: 'manual',
|
|
67
72
|
integrationDomain: 'kodi',
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
port: inputArg.port || defaultPort,
|
|
73
|
+
host: endpoint.host,
|
|
74
|
+
port: endpoint.port,
|
|
71
75
|
name: inputArg.name,
|
|
72
76
|
manufacturer: inputArg.manufacturer || 'Kodi',
|
|
73
77
|
model: inputArg.model,
|
|
74
78
|
metadata: {
|
|
75
|
-
|
|
76
|
-
wsPort: inputArg.wsPort || defaultWsPort,
|
|
77
|
-
ssl: inputArg.ssl,
|
|
79
|
+
selectionVerified: false,
|
|
78
80
|
},
|
|
79
81
|
},
|
|
80
82
|
};
|
|
@@ -89,19 +91,25 @@ export class KodiCandidateValidator implements IDiscoveryValidator {
|
|
|
89
91
|
const manufacturer = candidateArg.manufacturer?.toLowerCase() || '';
|
|
90
92
|
const model = candidateArg.model?.toLowerCase() || '';
|
|
91
93
|
const name = candidateArg.name?.toLowerCase() || '';
|
|
92
|
-
const
|
|
94
|
+
const recognized = candidateArg.integrationDomain === 'kodi'
|
|
93
95
|
|| manufacturer.includes('kodi')
|
|
94
96
|
|| manufacturer.includes('xbmc')
|
|
95
97
|
|| model.includes('kodi')
|
|
96
98
|
|| model.includes('xbmc')
|
|
97
99
|
|| name.includes('kodi')
|
|
98
100
|
|| Boolean(candidateArg.metadata?.kodi);
|
|
101
|
+
if (!recognized) {
|
|
102
|
+
return { matched: false, confidence: 'low', reason: 'Candidate is not Kodi.' };
|
|
103
|
+
}
|
|
104
|
+
const endpoint = kodiEndpoint(candidateArg.host, candidateArg.port);
|
|
105
|
+
if (!endpoint) {
|
|
106
|
+
return { matched: false, confidence: 'low', reason: 'Kodi candidate does not contain a supported numeric HTTP endpoint.' };
|
|
107
|
+
}
|
|
99
108
|
return {
|
|
100
|
-
matched,
|
|
101
|
-
confidence:
|
|
102
|
-
reason:
|
|
103
|
-
candidate:
|
|
104
|
-
normalizedDeviceId: candidateArg.id,
|
|
109
|
+
matched: true,
|
|
110
|
+
confidence: 'high',
|
|
111
|
+
reason: 'Candidate has Kodi metadata and a numeric endpoint hint; application selection still requires a live observation.',
|
|
112
|
+
candidate: { ...candidateArg, host: endpoint.host, port: endpoint.port },
|
|
105
113
|
};
|
|
106
114
|
}
|
|
107
115
|
}
|
|
@@ -113,6 +121,19 @@ export const createKodiDiscoveryDescriptor = (): DiscoveryDescriptor => {
|
|
|
113
121
|
.addValidator(new KodiCandidateValidator());
|
|
114
122
|
};
|
|
115
123
|
|
|
124
|
+
/** Select only supplied endpoints; the public foundation owns origin policy. */
|
|
125
|
+
const kodiEndpoint = (hostArg: string | undefined, portArg: number | undefined): { host: string; port: number } | undefined => {
|
|
126
|
+
const port = portArg === undefined ? defaultPort : portArg;
|
|
127
|
+
if (typeof hostArg !== 'string' || typeof port !== 'number' || !Number.isSafeInteger(port)) return undefined;
|
|
128
|
+
try {
|
|
129
|
+
const origin = plugins.ecobridgeDeviceManager.validateKodiOrigin(`http://${hostArg}:${port}`);
|
|
130
|
+
return { host: new URL(origin).hostname, port };
|
|
131
|
+
} catch (error) {
|
|
132
|
+
if (error instanceof plugins.ecobridgeDeviceManager.KodiProtocolError && error.code === 'invalid-options') return undefined;
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
116
137
|
const normalizeType = (valueArg?: string): string => {
|
|
117
138
|
return (valueArg || '').toLowerCase().replace(/\.$/, '');
|
|
118
139
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
import type { IIntegrationEntity } from '../../core/types.js';
|
|
3
|
-
import type { IKodiMediaItem, IKodiSnapshot, IKodiTime } from './kodi.types.js';
|
|
3
|
+
import type { IKodiMediaItem, IKodiNativeSnapshot, IKodiSnapshot, IKodiTime } from './kodi.types.js';
|
|
4
4
|
|
|
5
5
|
const kodiMediaTypes: Record<string, string> = {
|
|
6
6
|
music: 'music',
|
|
@@ -19,24 +19,64 @@ const kodiMediaTypes: Record<string, string> = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
export class KodiMapper {
|
|
22
|
+
public static deviceId(snapshot: Pick<IKodiNativeSnapshot, 'homeId' | 'origin'>): string {
|
|
23
|
+
return `kodi:${encodeURIComponent(snapshot.homeId)}:${encodeURIComponent(snapshot.origin)}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public static entityId(snapshot: Pick<IKodiNativeSnapshot, 'homeId' | 'origin'>): string {
|
|
27
|
+
return `media_player.${this.deviceId(snapshot)}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public static toNativeDevices(snapshot: IKodiNativeSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
|
|
31
|
+
return [{
|
|
32
|
+
id: this.deviceId(snapshot), integrationDomain: 'kodi', name: snapshot.name, protocol: 'http',
|
|
33
|
+
manufacturer: 'Kodi', model: snapshot.applicationName, online: snapshot.online,
|
|
34
|
+
features: [
|
|
35
|
+
{ id: 'volume', capability: 'media', name: 'Application volume', readable: true, writable: snapshot.capabilities.canSetVolume, unit: '%' },
|
|
36
|
+
{ id: 'muted', capability: 'media', name: 'Application muted', readable: true, writable: snapshot.capabilities.canSetMuted },
|
|
37
|
+
],
|
|
38
|
+
state: [
|
|
39
|
+
{ featureId: 'volume', value: snapshot.volume, updatedAt: snapshot.observedAt },
|
|
40
|
+
{ featureId: 'muted', value: snapshot.muted, updatedAt: snapshot.observedAt },
|
|
41
|
+
],
|
|
42
|
+
metadata: {
|
|
43
|
+
homeId: snapshot.homeId, origin: snapshot.origin, applicationVersion: snapshot.applicationVersion,
|
|
44
|
+
apiVersion: snapshot.apiVersion, selection: snapshot.selection, uniqueDeviceIdentityVerified: false,
|
|
45
|
+
cryptographicServerIdentityVerified: false, volumeRange: snapshot.capabilities.volumeRange,
|
|
46
|
+
runtimeAuthority: 'native-observation', playbackObserved: false,
|
|
47
|
+
},
|
|
48
|
+
}];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public static toNativeEntities(snapshot: IKodiNativeSnapshot): IIntegrationEntity[] {
|
|
52
|
+
return [{
|
|
53
|
+
id: this.entityId(snapshot), uniqueId: this.deviceId(snapshot), integrationDomain: 'kodi',
|
|
54
|
+
deviceId: this.deviceId(snapshot), platform: 'media_player', name: snapshot.name, state: 'unknown', available: snapshot.online,
|
|
55
|
+
attributes: { applicationVolume: snapshot.volume, isVolumeMuted: snapshot.muted, playbackObserved: false,
|
|
56
|
+
applicationName: snapshot.applicationName, applicationVersion: snapshot.applicationVersion, apiVersion: snapshot.apiVersion,
|
|
57
|
+
selection: snapshot.selection, uniqueDeviceIdentityVerified: false, cryptographicServerIdentityVerified: false,
|
|
58
|
+
capabilities: snapshot.capabilities, observedAt: snapshot.observedAt },
|
|
59
|
+
}];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Converts offline imported data without granting runtime availability or writes. */
|
|
22
63
|
public static toDevices(snapshotArg: IKodiSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
|
|
23
64
|
const updatedAt = snapshotArg.updatedAt || new Date().toISOString();
|
|
24
65
|
const application = snapshotArg.application;
|
|
25
66
|
return [{
|
|
26
|
-
id: this.
|
|
67
|
+
id: this.offlineDeviceId(snapshotArg),
|
|
27
68
|
integrationDomain: 'kodi',
|
|
28
69
|
name: this.deviceName(snapshotArg),
|
|
29
70
|
protocol: 'http',
|
|
30
71
|
manufacturer: snapshotArg.deviceInfo.manufacturer || 'Kodi',
|
|
31
72
|
model: snapshotArg.deviceInfo.model || application?.name,
|
|
32
|
-
online:
|
|
73
|
+
online: false,
|
|
33
74
|
features: [
|
|
34
|
-
{ id: 'playback', capability: 'media', name: 'Playback', readable: true, writable:
|
|
35
|
-
{ id: 'volume', capability: 'media', name: 'Volume', readable: true, writable:
|
|
36
|
-
{ id: 'muted', capability: 'media', name: 'Muted', readable: true, writable:
|
|
75
|
+
{ id: 'playback', capability: 'media', name: 'Playback', readable: true, writable: false },
|
|
76
|
+
{ id: 'volume', capability: 'media', name: 'Volume', readable: true, writable: false, unit: '%' },
|
|
77
|
+
{ id: 'muted', capability: 'media', name: 'Muted', readable: true, writable: false },
|
|
37
78
|
{ id: 'active_player', capability: 'media', name: 'Active player', readable: true, writable: false },
|
|
38
79
|
{ id: 'current_title', capability: 'media', name: 'Current title', readable: true, writable: false },
|
|
39
|
-
{ id: 'notification', capability: 'media', name: 'Notification', readable: false, writable: true },
|
|
40
80
|
],
|
|
41
81
|
state: [
|
|
42
82
|
{ featureId: 'playback', value: this.mediaState(snapshotArg), updatedAt },
|
|
@@ -46,6 +86,7 @@ export class KodiMapper {
|
|
|
46
86
|
{ featureId: 'current_title', value: this.mediaTitle(snapshotArg.item) || null, updatedAt },
|
|
47
87
|
],
|
|
48
88
|
metadata: {
|
|
89
|
+
runtimeAuthority: 'offline-import', uniqueDeviceIdentityVerified: false,
|
|
49
90
|
uuid: snapshotArg.deviceInfo.uuid,
|
|
50
91
|
host: snapshotArg.deviceInfo.host,
|
|
51
92
|
port: snapshotArg.deviceInfo.port,
|
|
@@ -62,11 +103,12 @@ export class KodiMapper {
|
|
|
62
103
|
id: `media_player.${this.slug(this.deviceName(snapshotArg))}`,
|
|
63
104
|
uniqueId: `kodi_${this.uniqueBase(snapshotArg)}`,
|
|
64
105
|
integrationDomain: 'kodi',
|
|
65
|
-
deviceId: this.
|
|
106
|
+
deviceId: this.offlineDeviceId(snapshotArg),
|
|
66
107
|
platform: 'media_player',
|
|
67
108
|
name: this.deviceName(snapshotArg),
|
|
68
109
|
state: this.mediaState(snapshotArg),
|
|
69
110
|
attributes: {
|
|
111
|
+
runtimeAuthority: 'offline-import', uniqueDeviceIdentityVerified: false,
|
|
70
112
|
volumeLevel: typeof snapshotArg.application?.volume === 'number' ? snapshotArg.application.volume / 100 : undefined,
|
|
71
113
|
isVolumeMuted: snapshotArg.application?.muted,
|
|
72
114
|
mediaContentId: this.mediaContentId(item),
|
|
@@ -86,7 +128,7 @@ export class KodiMapper {
|
|
|
86
128
|
live: snapshotArg.playerProperties?.live,
|
|
87
129
|
dynamicRange: this.dynamicRange(item),
|
|
88
130
|
},
|
|
89
|
-
available:
|
|
131
|
+
available: false,
|
|
90
132
|
}];
|
|
91
133
|
}
|
|
92
134
|
|
|
@@ -151,7 +193,7 @@ export class KodiMapper {
|
|
|
151
193
|
return Array.isArray(valueArg) ? valueArg[0] : valueArg;
|
|
152
194
|
}
|
|
153
195
|
|
|
154
|
-
private static
|
|
196
|
+
private static offlineDeviceId(snapshotArg: IKodiSnapshot): string {
|
|
155
197
|
return `kodi.device.${this.uniqueBase(snapshotArg)}`;
|
|
156
198
|
}
|
|
157
199
|
|