forked from home-assistant/core
Compare commits
97 Commits
2022.10.0b
...
2022.10.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bca322856 | ||
|
|
bd2ac57d55 | ||
|
|
f330745cdb | ||
|
|
5ac258378b | ||
|
|
5812d802ee | ||
|
|
c64b286f6e | ||
|
|
f5368cc359 | ||
|
|
b182305ff6 | ||
|
|
410479b212 | ||
|
|
fc4ffc748c | ||
|
|
1143ede4db | ||
|
|
81783fd52b | ||
|
|
316c5f8cc3 | ||
|
|
66d14ec1cc | ||
|
|
11b351f015 | ||
|
|
779d805b5a | ||
|
|
aabd681d7e | ||
|
|
570270b9ea | ||
|
|
aacae6b9bf | ||
|
|
35a69cb253 | ||
|
|
998d13499c | ||
|
|
3bd4d66b2e | ||
|
|
5f37742197 | ||
|
|
92afbf01e7 | ||
|
|
eb003f34f0 | ||
|
|
9f7f13ac87 | ||
|
|
7a1757a61f | ||
|
|
9938642800 | ||
|
|
7e57933164 | ||
|
|
20db8138d9 | ||
|
|
146520b437 | ||
|
|
20c61af5b7 | ||
|
|
e26f3de80b | ||
|
|
b4cb70cdeb | ||
|
|
895facdf72 | ||
|
|
ed7c93240c | ||
|
|
2c34190d82 | ||
|
|
98567b6f26 | ||
|
|
9302071527 | ||
|
|
af5f5542d2 | ||
|
|
f08fab9d7e | ||
|
|
1efa374c4e | ||
|
|
723d415966 | ||
|
|
09f1039f32 | ||
|
|
9ca179ddcb | ||
|
|
310dbe90a1 | ||
|
|
39be6ecd00 | ||
|
|
5957c6a185 | ||
|
|
04a2a041c3 | ||
|
|
7cfba93d50 | ||
|
|
e13c6a5264 | ||
|
|
572d15050f | ||
|
|
dd243e18e6 | ||
|
|
b1883609cf | ||
|
|
85c131ed43 | ||
|
|
a9f2119932 | ||
|
|
d32ab6ff8f | ||
|
|
d77afb0a79 | ||
|
|
736991af35 | ||
|
|
e513c4fafc | ||
|
|
b519bf5332 | ||
|
|
8f44c11677 | ||
|
|
3abd0877f7 | ||
|
|
68aa0856c3 | ||
|
|
ad1ed811e8 | ||
|
|
8c84efa842 | ||
|
|
12fc7f29d5 | ||
|
|
cc8267fb13 | ||
|
|
bcd9510733 | ||
|
|
43891f0baa | ||
|
|
70010c0115 | ||
|
|
c32e4d34f6 | ||
|
|
f8f3d96a74 | ||
|
|
412ef9d126 | ||
|
|
9bb75bb726 | ||
|
|
321da50a7e | ||
|
|
e410e298c4 | ||
|
|
d41d09aa7e | ||
|
|
590d47aad0 | ||
|
|
6c7060e0e2 | ||
|
|
2fed773b93 | ||
|
|
71e320fc96 | ||
|
|
de90358f2a | ||
|
|
2703bbc630 | ||
|
|
a3833a408b | ||
|
|
933b84050e | ||
|
|
046c3b4dd1 | ||
|
|
7e8905758b | ||
|
|
97f5670fdc | ||
|
|
b3c43b981a | ||
|
|
ebb213eb14 | ||
|
|
a0ba102492 | ||
|
|
be036914a6 | ||
|
|
ecb934ee6a | ||
|
|
783f514df3 | ||
|
|
2e2d8d1367 | ||
|
|
1836dc4a3b |
@@ -162,7 +162,7 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/brunt/ @eavanvalkenburg
|
||||
/homeassistant/components/bsblan/ @liudger
|
||||
/tests/components/bsblan/ @liudger
|
||||
/homeassistant/components/bt_smarthub/ @jxwolstenholme
|
||||
/homeassistant/components/bt_smarthub/ @typhoon2099
|
||||
/homeassistant/components/bthome/ @Ernst79
|
||||
/tests/components/bthome/ @Ernst79
|
||||
/homeassistant/components/buienradar/ @mjj4791 @ties @Robbie1221
|
||||
|
||||
5
homeassistant/brands/amazon.json
Normal file
5
homeassistant/brands/amazon.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "amazon",
|
||||
"name": "Amazon",
|
||||
"integrations": ["alexa", "amazon_polly", "aws", "route53"]
|
||||
}
|
||||
@@ -2,10 +2,11 @@
|
||||
"domain": "apple",
|
||||
"name": "Apple",
|
||||
"integrations": [
|
||||
"icloud",
|
||||
"ibeacon",
|
||||
"apple_tv",
|
||||
"homekit_controller",
|
||||
"homekit",
|
||||
"homekit_controller"
|
||||
"ibeacon",
|
||||
"icloud",
|
||||
"itunes"
|
||||
]
|
||||
}
|
||||
|
||||
5
homeassistant/brands/aruba.json
Normal file
5
homeassistant/brands/aruba.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "aruba",
|
||||
"name": "Aruba",
|
||||
"integrations": ["aruba", "cppm_tracker"]
|
||||
}
|
||||
5
homeassistant/brands/asterisk.json
Normal file
5
homeassistant/brands/asterisk.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "asterisk",
|
||||
"name": "Asterisk",
|
||||
"integrations": ["asterisk_cdr", "asterisk_mbox"]
|
||||
}
|
||||
5
homeassistant/brands/august.json
Normal file
5
homeassistant/brands/august.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "august",
|
||||
"name": "August Home",
|
||||
"integrations": ["august", "yalexs_ble"]
|
||||
}
|
||||
5
homeassistant/brands/cisco.json
Normal file
5
homeassistant/brands/cisco.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "cisco",
|
||||
"name": "Cisco",
|
||||
"integrations": ["cisco_ios", "cisco_mobility_express", "cisco_webex_teams"]
|
||||
}
|
||||
5
homeassistant/brands/clicksend.json
Normal file
5
homeassistant/brands/clicksend.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "clicksend",
|
||||
"name": "ClickSend",
|
||||
"integrations": ["clicksend", "clicksend_tts"]
|
||||
}
|
||||
5
homeassistant/brands/devolo.json
Normal file
5
homeassistant/brands/devolo.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "devolo",
|
||||
"name": "devolo",
|
||||
"integrations": ["devolo_home_control", "devolo_home_network"]
|
||||
}
|
||||
5
homeassistant/brands/dlna.json
Normal file
5
homeassistant/brands/dlna.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "dlna",
|
||||
"name": "DLNA",
|
||||
"integrations": ["dlna_dmr", "dlna_dms"]
|
||||
}
|
||||
5
homeassistant/brands/elgato.json
Normal file
5
homeassistant/brands/elgato.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "elgato",
|
||||
"name": "Elgato",
|
||||
"integrations": ["avea", "elgato"]
|
||||
}
|
||||
5
homeassistant/brands/emoncms.json
Normal file
5
homeassistant/brands/emoncms.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "emoncms",
|
||||
"name": "emoncms",
|
||||
"integrations": ["emoncms", "emoncms_history"]
|
||||
}
|
||||
5
homeassistant/brands/epson.json
Normal file
5
homeassistant/brands/epson.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "epson",
|
||||
"name": "Epson",
|
||||
"integrations": ["epson", "epsonworkforce"]
|
||||
}
|
||||
5
homeassistant/brands/eq3.json
Normal file
5
homeassistant/brands/eq3.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "eq3",
|
||||
"name": "eQ-3",
|
||||
"integrations": ["eq3btsmart", "maxcube"]
|
||||
}
|
||||
5
homeassistant/brands/ffmpeg.json
Normal file
5
homeassistant/brands/ffmpeg.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "ffmpeg",
|
||||
"name": "FFmpeg",
|
||||
"integrations": ["ffmpeg", "ffmpeg_motion", "ffmpeg_noise"]
|
||||
}
|
||||
5
homeassistant/brands/geonet.json
Normal file
5
homeassistant/brands/geonet.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "geonet",
|
||||
"name": "GeoNet",
|
||||
"integrations": ["geonetnz_quakes", "geonetnz_volcano"]
|
||||
}
|
||||
5
homeassistant/brands/globalcache.json
Normal file
5
homeassistant/brands/globalcache.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "globalcache",
|
||||
"name": "Global Caché",
|
||||
"integrations": ["gc100", "itach"]
|
||||
}
|
||||
5
homeassistant/brands/hikvision.json
Normal file
5
homeassistant/brands/hikvision.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "hikvision",
|
||||
"name": "Hikvision",
|
||||
"integrations": ["hikvision", "hikvisioncam"]
|
||||
}
|
||||
5
homeassistant/brands/homematic.json
Normal file
5
homeassistant/brands/homematic.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "homematic",
|
||||
"name": "Homematic",
|
||||
"integrations": ["homematic", "homematicip_cloud"]
|
||||
}
|
||||
5
homeassistant/brands/honeywell.json
Normal file
5
homeassistant/brands/honeywell.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "honeywell",
|
||||
"name": "Honeywell",
|
||||
"integrations": ["lyric", "evohome", "honeywell"]
|
||||
}
|
||||
5
homeassistant/brands/ibm.json
Normal file
5
homeassistant/brands/ibm.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "ibm",
|
||||
"name": "IBM",
|
||||
"integrations": ["watson_iot", "watson_tts"]
|
||||
}
|
||||
5
homeassistant/brands/inovelli.json
Normal file
5
homeassistant/brands/inovelli.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "inovelli",
|
||||
"name": "Inovelli",
|
||||
"iot_standards": ["zigbee", "zwave"]
|
||||
}
|
||||
5
homeassistant/brands/jasco.json
Normal file
5
homeassistant/brands/jasco.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "jasco",
|
||||
"name": "Jasco",
|
||||
"iot_standards": ["zwave"]
|
||||
}
|
||||
5
homeassistant/brands/lg.json
Normal file
5
homeassistant/brands/lg.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "lg",
|
||||
"name": "LG",
|
||||
"integrations": ["lg_netcast", "lg_soundbar", "webostv"]
|
||||
}
|
||||
5
homeassistant/brands/logitech.json
Normal file
5
homeassistant/brands/logitech.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "logitech",
|
||||
"name": "Logitech",
|
||||
"integrations": ["harmony", "ue_smart_radio", "squeezebox"]
|
||||
}
|
||||
5
homeassistant/brands/lutron.json
Normal file
5
homeassistant/brands/lutron.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "lutron",
|
||||
"name": "Lutron",
|
||||
"integrations": ["lutron", "lutron_caseta", "homeworks"]
|
||||
}
|
||||
5
homeassistant/brands/melnor.json
Normal file
5
homeassistant/brands/melnor.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "melnor",
|
||||
"name": "Melnor",
|
||||
"integrations": ["melnor", "raincloud"]
|
||||
}
|
||||
16
homeassistant/brands/microsoft.json
Normal file
16
homeassistant/brands/microsoft.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"domain": "microsoft",
|
||||
"name": "Microsoft",
|
||||
"integrations": [
|
||||
"azure_devops",
|
||||
"azure_event_hub",
|
||||
"azure_service_bus",
|
||||
"microsoft_face_detect",
|
||||
"microsoft_face_identify",
|
||||
"microsoft_face",
|
||||
"microsoft",
|
||||
"msteams",
|
||||
"xbox",
|
||||
"xbox_live"
|
||||
]
|
||||
}
|
||||
12
homeassistant/brands/mqtt.json
Normal file
12
homeassistant/brands/mqtt.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"domain": "mqtt",
|
||||
"name": "MQTT",
|
||||
"integrations": [
|
||||
"manual_mqtt",
|
||||
"mqtt",
|
||||
"mqtt_eventstream",
|
||||
"mqtt_json",
|
||||
"mqtt_room",
|
||||
"mqtt_statestream"
|
||||
]
|
||||
}
|
||||
5
homeassistant/brands/netgear.json
Normal file
5
homeassistant/brands/netgear.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "netgear",
|
||||
"name": "NETGEAR",
|
||||
"integrations": ["netgear", "netgear_lte"]
|
||||
}
|
||||
5
homeassistant/brands/openwrt.json
Normal file
5
homeassistant/brands/openwrt.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "openwrt",
|
||||
"name": "OpenWrt",
|
||||
"integrations": ["luci", "ubus"]
|
||||
}
|
||||
5
homeassistant/brands/panasonic.json
Normal file
5
homeassistant/brands/panasonic.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "panasonic",
|
||||
"name": "Panasonic",
|
||||
"integrations": ["panasonic_bluray", "panasonic_viera"]
|
||||
}
|
||||
5
homeassistant/brands/philips.json
Normal file
5
homeassistant/brands/philips.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "philips",
|
||||
"name": "Philips",
|
||||
"integrations": ["dynalite", "hue", "philips_js"]
|
||||
}
|
||||
5
homeassistant/brands/qnap.json
Normal file
5
homeassistant/brands/qnap.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "qnap",
|
||||
"name": "QNAP",
|
||||
"integrations": ["qnap", "qnap_qsw"]
|
||||
}
|
||||
5
homeassistant/brands/raspberry.json
Normal file
5
homeassistant/brands/raspberry.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "raspberry_pi",
|
||||
"name": "Raspberry Pi",
|
||||
"integrations": ["rpi_camera", "rpi_power", "remote_rpi_gpio"]
|
||||
}
|
||||
5
homeassistant/brands/russound.json
Normal file
5
homeassistant/brands/russound.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "russound",
|
||||
"name": "Russound",
|
||||
"integrations": ["russound_rio", "russound_rnet"]
|
||||
}
|
||||
5
homeassistant/brands/samsung.json
Normal file
5
homeassistant/brands/samsung.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "samsung",
|
||||
"name": "Samsung",
|
||||
"integrations": ["familyhub", "samsungtv", "syncthru"]
|
||||
}
|
||||
5
homeassistant/brands/solaredge.json
Normal file
5
homeassistant/brands/solaredge.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "solaredge",
|
||||
"name": "SolarEdge",
|
||||
"integrations": ["solaredge", "solaredge_local"]
|
||||
}
|
||||
5
homeassistant/brands/sony.json
Normal file
5
homeassistant/brands/sony.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "sony",
|
||||
"name": "Sony",
|
||||
"integrations": ["braviatv", "ps4", "sony_projector", "songpal"]
|
||||
}
|
||||
5
homeassistant/brands/synology.json
Normal file
5
homeassistant/brands/synology.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "synology",
|
||||
"name": "Synology",
|
||||
"integrations": ["synology_chat", "synology_dsm", "synology_srm"]
|
||||
}
|
||||
5
homeassistant/brands/telegram.json
Normal file
5
homeassistant/brands/telegram.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "telegram",
|
||||
"name": "Telegram",
|
||||
"integrations": ["telegram", "telegram_bot"]
|
||||
}
|
||||
5
homeassistant/brands/telldus.json
Normal file
5
homeassistant/brands/telldus.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "telldus",
|
||||
"name": "Telldus",
|
||||
"integrations": ["tellduslive", "tellstick"]
|
||||
}
|
||||
5
homeassistant/brands/tesla.json
Normal file
5
homeassistant/brands/tesla.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "tesla",
|
||||
"name": "Tesla",
|
||||
"integrations": ["powerwall", "tesla_wall_connector"]
|
||||
}
|
||||
9
homeassistant/brands/trafikverket.json
Normal file
9
homeassistant/brands/trafikverket.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"domain": "trafikverket",
|
||||
"name": "Trafikverket",
|
||||
"integrations": [
|
||||
"trafikverket_ferry",
|
||||
"trafikverket_train",
|
||||
"trafikverket_weatherstation"
|
||||
]
|
||||
}
|
||||
5
homeassistant/brands/twilio.json
Normal file
5
homeassistant/brands/twilio.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "twilio",
|
||||
"name": "Twilio",
|
||||
"integrations": ["twilio", "twilio_call", "twilio_sms"]
|
||||
}
|
||||
5
homeassistant/brands/u_tec.json
Normal file
5
homeassistant/brands/u_tec.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "u_tec",
|
||||
"name": "U-tec",
|
||||
"iot_standards": ["zwave"]
|
||||
}
|
||||
5
homeassistant/brands/vlc.json
Normal file
5
homeassistant/brands/vlc.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "vlc",
|
||||
"name": "VideoLAN",
|
||||
"integrations": ["vlc", "vlc_telnet"]
|
||||
}
|
||||
11
homeassistant/brands/xiaomi.json
Normal file
11
homeassistant/brands/xiaomi.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"domain": "xiaomi",
|
||||
"name": "Xiaomi",
|
||||
"integrations": [
|
||||
"xiaomi_aqara",
|
||||
"xiaomi_ble",
|
||||
"xiaomi_miio",
|
||||
"xiaomi_tv",
|
||||
"xiaomi"
|
||||
]
|
||||
}
|
||||
5
homeassistant/brands/yale.json
Normal file
5
homeassistant/brands/yale.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "yale",
|
||||
"name": "Yale",
|
||||
"integrations": ["august", "yale_smart_alarm", "yalexs_ble"]
|
||||
}
|
||||
5
homeassistant/brands/yandex.json
Normal file
5
homeassistant/brands/yandex.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "yandex",
|
||||
"name": "Yandex",
|
||||
"integrations": ["yandex_transport", "yandextts"]
|
||||
}
|
||||
5
homeassistant/brands/yeelight.json
Normal file
5
homeassistant/brands/yeelight.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "yeelight",
|
||||
"name": "Yeelight",
|
||||
"integrations": ["yeelight", "yeelightsunflower"]
|
||||
}
|
||||
5
homeassistant/brands/zooz.json
Normal file
5
homeassistant/brands/zooz.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"domain": "zooz",
|
||||
"name": "Zooz",
|
||||
"iot_standards": ["zwave"]
|
||||
}
|
||||
@@ -68,7 +68,7 @@ class AirlySensorEntityDescription(SensorEntityDescription):
|
||||
SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_CAQI,
|
||||
device_class=SensorDeviceClass.AQI,
|
||||
icon="mdi:air-filter",
|
||||
name=ATTR_API_CAQI,
|
||||
native_unit_of_measurement="CAQI",
|
||||
),
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Alarm Control Panel",
|
||||
"documentation": "https://www.home-assistant.io/integrations/alarm_control_panel",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -819,7 +819,9 @@ def temperature_from_object(hass, temp_obj, interval=False):
|
||||
# convert to Celsius if absolute temperature
|
||||
temp -= 273.15
|
||||
|
||||
return TemperatureConverter.convert(temp, from_unit, to_unit, interval=interval)
|
||||
if interval:
|
||||
return TemperatureConverter.convert_interval(temp, from_unit, to_unit)
|
||||
return TemperatureConverter.convert(temp, from_unit, to_unit)
|
||||
|
||||
|
||||
@HANDLERS.register(("Alexa.ThermostatController", "SetTargetTemperature"))
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/api",
|
||||
"dependencies": ["http"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/application_credentials",
|
||||
"dependencies": ["auth", "websocket_api"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/auth",
|
||||
"dependencies": ["http"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
"dependencies": ["blueprint", "trace"],
|
||||
"after_dependencies": ["device_automation", "webhook"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"requirements": ["securetar==2022.2.0"],
|
||||
"iot_class": "calculated",
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Binary Sensor",
|
||||
"documentation": "https://www.home-assistant.io/integrations/binary_sensor",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Blueprint",
|
||||
"documentation": "https://www.home-assistant.io/integrations/blueprint",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ from .models import (
|
||||
HaBluetoothConnector,
|
||||
ProcessAdvertisementCallback,
|
||||
)
|
||||
from .scanner import HaScanner, ScannerStartError, create_bleak_scanner
|
||||
from .scanner import HaScanner, ScannerStartError
|
||||
from .util import adapter_human_name, adapter_unique_name, async_default_adapter
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -400,13 +400,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
|
||||
passive = entry.options.get(CONF_PASSIVE)
|
||||
mode = BluetoothScanningMode.PASSIVE if passive else BluetoothScanningMode.ACTIVE
|
||||
scanner = HaScanner(hass, mode, adapter, address)
|
||||
try:
|
||||
bleak_scanner = create_bleak_scanner(mode, adapter)
|
||||
scanner.async_setup()
|
||||
except RuntimeError as err:
|
||||
raise ConfigEntryNotReady(
|
||||
f"{adapter_human_name(adapter, address)}: {err}"
|
||||
) from err
|
||||
scanner = HaScanner(hass, bleak_scanner, adapter, address)
|
||||
info_callback = async_get_advertisement_callback(hass)
|
||||
entry.async_on_unload(scanner.async_register_callback(info_callback))
|
||||
try:
|
||||
|
||||
@@ -3,7 +3,6 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Callable, Iterable
|
||||
from dataclasses import asdict
|
||||
from datetime import datetime, timedelta
|
||||
import itertools
|
||||
import logging
|
||||
@@ -185,11 +184,11 @@ class BluetoothManager:
|
||||
"adapters": self._adapters,
|
||||
"scanners": scanner_diagnostics,
|
||||
"connectable_history": [
|
||||
asdict(service_info)
|
||||
service_info.as_dict()
|
||||
for service_info in self._connectable_history.values()
|
||||
],
|
||||
"history": [
|
||||
asdict(service_info) for service_info in self._history.values()
|
||||
service_info.as_dict() for service_info in self._history.values()
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
"requirements": [
|
||||
"bleak==0.18.1",
|
||||
"bleak-retry-connector==2.1.3",
|
||||
"bluetooth-adapters==0.5.2",
|
||||
"bluetooth-adapters==0.6.0",
|
||||
"bluetooth-auto-recovery==0.3.3",
|
||||
"dbus-fast==1.17.0"
|
||||
"dbus-fast==1.24.0"
|
||||
],
|
||||
"codeowners": ["@bdraco"],
|
||||
"config_flow": true,
|
||||
|
||||
@@ -53,6 +53,25 @@ class BluetoothServiceInfoBleak(BluetoothServiceInfo):
|
||||
connectable: bool
|
||||
time: float
|
||||
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
"""Return as dict.
|
||||
|
||||
The dataclass asdict method is not used because
|
||||
it will try to deepcopy pyobjc data which will fail.
|
||||
"""
|
||||
return {
|
||||
"name": self.name,
|
||||
"address": self.address,
|
||||
"rssi": self.rssi,
|
||||
"manufacturer_data": self.manufacturer_data,
|
||||
"service_data": self.service_data,
|
||||
"service_uuids": self.service_uuids,
|
||||
"source": self.source,
|
||||
"advertisement": self.advertisement,
|
||||
"connectable": self.connectable,
|
||||
"time": self.time,
|
||||
}
|
||||
|
||||
|
||||
class BluetoothScanningMode(Enum):
|
||||
"""The mode of scanning for bluetooth devices."""
|
||||
|
||||
@@ -16,7 +16,7 @@ from bleak.assigned_numbers import AdvertisementDataType
|
||||
from bleak.backends.bluezdbus.advertisement_monitor import OrPattern
|
||||
from bleak.backends.bluezdbus.scanner import BlueZScannerArgs
|
||||
from bleak.backends.device import BLEDevice
|
||||
from bleak.backends.scanner import AdvertisementData
|
||||
from bleak.backends.scanner import AdvertisementData, AdvertisementDataCallback
|
||||
from bleak_retry_connector import get_device_by_adapter
|
||||
from dbus_fast import InvalidMessageError
|
||||
|
||||
@@ -86,11 +86,14 @@ class ScannerStartError(HomeAssistantError):
|
||||
|
||||
|
||||
def create_bleak_scanner(
|
||||
scanning_mode: BluetoothScanningMode, adapter: str | None
|
||||
detection_callback: AdvertisementDataCallback,
|
||||
scanning_mode: BluetoothScanningMode,
|
||||
adapter: str | None,
|
||||
) -> bleak.BleakScanner:
|
||||
"""Create a Bleak scanner."""
|
||||
scanner_kwargs: dict[str, Any] = {
|
||||
"scanning_mode": SCANNING_MODE_TO_BLEAK[scanning_mode]
|
||||
"detection_callback": detection_callback,
|
||||
"scanning_mode": SCANNING_MODE_TO_BLEAK[scanning_mode],
|
||||
}
|
||||
if platform.system() == "Linux":
|
||||
# Only Linux supports multiple adapters
|
||||
@@ -117,16 +120,18 @@ class HaScanner(BaseHaScanner):
|
||||
over ethernet, usb over ethernet, etc.
|
||||
"""
|
||||
|
||||
scanner: bleak.BleakScanner
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
scanner: bleak.BleakScanner,
|
||||
mode: BluetoothScanningMode,
|
||||
adapter: str,
|
||||
address: str,
|
||||
) -> None:
|
||||
"""Init bluetooth discovery."""
|
||||
self.hass = hass
|
||||
self.scanner = scanner
|
||||
self.mode = mode
|
||||
self.adapter = adapter
|
||||
self._start_stop_lock = asyncio.Lock()
|
||||
self._cancel_watchdog: CALLBACK_TYPE | None = None
|
||||
@@ -141,6 +146,13 @@ class HaScanner(BaseHaScanner):
|
||||
"""Return a list of discovered devices."""
|
||||
return self.scanner.discovered_devices
|
||||
|
||||
@hass_callback
|
||||
def async_setup(self) -> None:
|
||||
"""Set up the scanner."""
|
||||
self.scanner = create_bleak_scanner(
|
||||
self._async_detection_callback, self.mode, self.adapter
|
||||
)
|
||||
|
||||
async def async_get_device_by_address(self, address: str) -> BLEDevice | None:
|
||||
"""Get a device by address."""
|
||||
if platform.system() == "Linux":
|
||||
@@ -218,8 +230,6 @@ class HaScanner(BaseHaScanner):
|
||||
|
||||
async def async_start(self) -> None:
|
||||
"""Start bluetooth scanner."""
|
||||
self.scanner.register_detection_callback(self._async_detection_callback)
|
||||
|
||||
async with self._start_stop_lock:
|
||||
await self._async_start()
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"domain": "bt_smarthub",
|
||||
"name": "BT Smart Hub",
|
||||
"documentation": "https://www.home-assistant.io/integrations/bt_smarthub",
|
||||
"requirements": ["btsmarthub_devicelist==0.2.2"],
|
||||
"codeowners": ["@jxwolstenholme"],
|
||||
"requirements": ["btsmarthub_devicelist==0.2.3"],
|
||||
"codeowners": ["@typhoon2099"],
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["btsmarthub_devicelist"]
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Button",
|
||||
"documentation": "https://www.home-assistant.io/integrations/button",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/calendar",
|
||||
"dependencies": ["http"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
"requirements": ["PyTurboJPEG==1.6.7"],
|
||||
"after_dependencies": ["media_player"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Climate",
|
||||
"documentation": "https://www.home-assistant.io/integrations/climate",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/config",
|
||||
"dependencies": ["http"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Configurator",
|
||||
"documentation": "https://www.home-assistant.io/integrations/configurator",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
"dependencies": ["http"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal",
|
||||
"iot_class": "local_push"
|
||||
"iot_class": "local_push",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Cover",
|
||||
"documentation": "https://www.home-assistant.io/integrations/cover",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"name": "Daikin AC",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/daikin",
|
||||
"requirements": ["pydaikin==2.7.0"],
|
||||
"requirements": ["pydaikin==2.7.2"],
|
||||
"codeowners": ["@fredrike"],
|
||||
"zeroconf": ["_dkapi._tcp.local."],
|
||||
"quality_scale": "platinum",
|
||||
|
||||
@@ -41,5 +41,6 @@
|
||||
"zone"
|
||||
],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -295,7 +295,6 @@ async def _insert_statistics(hass: HomeAssistant) -> None:
|
||||
metadata: StatisticMetaData = {
|
||||
"source": DOMAIN,
|
||||
"name": "Outdoor temperature",
|
||||
"state_unit_of_measurement": TEMP_CELSIUS,
|
||||
"statistic_id": f"{DOMAIN}:temperature_outdoor",
|
||||
"unit_of_measurement": TEMP_CELSIUS,
|
||||
"has_mean": True,
|
||||
@@ -309,7 +308,6 @@ async def _insert_statistics(hass: HomeAssistant) -> None:
|
||||
metadata = {
|
||||
"source": DOMAIN,
|
||||
"name": "Energy consumption 1",
|
||||
"state_unit_of_measurement": ENERGY_KILO_WATT_HOUR,
|
||||
"statistic_id": f"{DOMAIN}:energy_consumption_kwh",
|
||||
"unit_of_measurement": ENERGY_KILO_WATT_HOUR,
|
||||
"has_mean": False,
|
||||
@@ -322,7 +320,6 @@ async def _insert_statistics(hass: HomeAssistant) -> None:
|
||||
metadata = {
|
||||
"source": DOMAIN,
|
||||
"name": "Energy consumption 2",
|
||||
"state_unit_of_measurement": ENERGY_MEGA_WATT_HOUR,
|
||||
"statistic_id": f"{DOMAIN}:energy_consumption_mwh",
|
||||
"unit_of_measurement": ENERGY_MEGA_WATT_HOUR,
|
||||
"has_mean": False,
|
||||
@@ -337,7 +334,6 @@ async def _insert_statistics(hass: HomeAssistant) -> None:
|
||||
metadata = {
|
||||
"source": DOMAIN,
|
||||
"name": "Gas consumption 1",
|
||||
"state_unit_of_measurement": VOLUME_CUBIC_METERS,
|
||||
"statistic_id": f"{DOMAIN}:gas_consumption_m3",
|
||||
"unit_of_measurement": VOLUME_CUBIC_METERS,
|
||||
"has_mean": False,
|
||||
@@ -352,7 +348,6 @@ async def _insert_statistics(hass: HomeAssistant) -> None:
|
||||
metadata = {
|
||||
"source": DOMAIN,
|
||||
"name": "Gas consumption 2",
|
||||
"state_unit_of_measurement": VOLUME_CUBIC_FEET,
|
||||
"statistic_id": f"{DOMAIN}:gas_consumption_ft3",
|
||||
"unit_of_measurement": VOLUME_CUBIC_FEET,
|
||||
"has_mean": False,
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Device Automation",
|
||||
"documentation": "https://www.home-assistant.io/integrations/device_automation",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
"dependencies": ["zone"],
|
||||
"after_dependencies": [],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
"codeowners": ["@bdraco"],
|
||||
"quality_scale": "internal",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aiodiscover", "dnspython", "pyroute2", "scapy"]
|
||||
"loggers": ["aiodiscover", "dnspython", "pyroute2", "scapy"],
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/diagnostics",
|
||||
"dependencies": ["http"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
"after_dependencies": ["zeroconf"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal",
|
||||
"loggers": ["netdisco"]
|
||||
"loggers": ["netdisco"],
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"iot_class": "calculated",
|
||||
"dependencies": ["websocket_api", "history", "recorder"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ from typing import Any, cast
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import recorder, websocket_api
|
||||
from homeassistant.const import ENERGY_KILO_WATT_HOUR
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.integration_platform import (
|
||||
async_process_integration_platforms,
|
||||
@@ -268,6 +269,7 @@ async def ws_get_fossil_energy_consumption(
|
||||
statistic_ids,
|
||||
"hour",
|
||||
True,
|
||||
{"energy": ENERGY_KILO_WATT_HOUR},
|
||||
)
|
||||
|
||||
def _combine_sum_statistics(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Bluetooth support for esphome."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
import logging
|
||||
|
||||
from aioesphomeapi import APIClient
|
||||
@@ -11,14 +12,8 @@ from homeassistant.components.bluetooth import (
|
||||
async_register_scanner,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import (
|
||||
CALLBACK_TYPE,
|
||||
HomeAssistant,
|
||||
async_get_hass,
|
||||
callback as hass_callback,
|
||||
)
|
||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback as hass_callback
|
||||
|
||||
from ..domain_data import DomainData
|
||||
from ..entry_data import RuntimeEntryData
|
||||
from .client import ESPHomeClient
|
||||
from .scanner import ESPHomeScanner
|
||||
@@ -27,18 +22,23 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@hass_callback
|
||||
def async_can_connect(source: str) -> bool:
|
||||
"""Check if a given source can make another connection."""
|
||||
domain_data = DomainData.get(async_get_hass())
|
||||
entry = domain_data.get_by_unique_id(source)
|
||||
entry_data = domain_data.get_entry_data(entry)
|
||||
_LOGGER.debug(
|
||||
"Checking if %s can connect, available=%s, ble_connections_free=%s",
|
||||
source,
|
||||
entry_data.available,
|
||||
entry_data.ble_connections_free,
|
||||
)
|
||||
return bool(entry_data.available and entry_data.ble_connections_free)
|
||||
def _async_can_connect_factory(
|
||||
entry_data: RuntimeEntryData, source: str
|
||||
) -> Callable[[], bool]:
|
||||
"""Create a can_connect function for a specific RuntimeEntryData instance."""
|
||||
|
||||
@hass_callback
|
||||
def _async_can_connect() -> bool:
|
||||
"""Check if a given source can make another connection."""
|
||||
_LOGGER.debug(
|
||||
"Checking if %s can connect, available=%s, ble_connections_free=%s",
|
||||
source,
|
||||
entry_data.available,
|
||||
entry_data.ble_connections_free,
|
||||
)
|
||||
return bool(entry_data.available and entry_data.ble_connections_free)
|
||||
|
||||
return _async_can_connect
|
||||
|
||||
|
||||
async def async_connect_scanner(
|
||||
@@ -63,7 +63,7 @@ async def async_connect_scanner(
|
||||
connector = HaBluetoothConnector(
|
||||
client=ESPHomeClient,
|
||||
source=source,
|
||||
can_connect=lambda: async_can_connect(source),
|
||||
can_connect=_async_can_connect_factory(entry_data, source),
|
||||
)
|
||||
scanner = ESPHomeScanner(hass, source, new_info_callback, connector, connectable)
|
||||
unload_callbacks = [
|
||||
|
||||
@@ -15,10 +15,9 @@ from bleak.backends.device import BLEDevice
|
||||
from bleak.backends.service import BleakGATTServiceCollection
|
||||
from bleak.exc import BleakError
|
||||
|
||||
from homeassistant.core import CALLBACK_TYPE, async_get_hass, callback as hass_callback
|
||||
from homeassistant.core import CALLBACK_TYPE, async_get_hass
|
||||
|
||||
from ..domain_data import DomainData
|
||||
from ..entry_data import RuntimeEntryData
|
||||
from .characteristic import BleakGATTCharacteristicESPHome
|
||||
from .descriptor import BleakGATTDescriptorESPHome
|
||||
from .service import BleakGATTServiceESPHome
|
||||
@@ -85,7 +84,9 @@ class ESPHomeClient(BaseBleakClient):
|
||||
assert self._ble_device.details is not None
|
||||
self._source = self._ble_device.details["source"]
|
||||
self.domain_data = DomainData.get(async_get_hass())
|
||||
self._client = self._async_get_entry_data().client
|
||||
config_entry = self.domain_data.get_by_unique_id(self._source)
|
||||
self.entry_data = self.domain_data.get_entry_data(config_entry)
|
||||
self._client = self.entry_data.client
|
||||
self._is_connected = False
|
||||
self._mtu: int | None = None
|
||||
self._cancel_connection_state: CALLBACK_TYPE | None = None
|
||||
@@ -108,12 +109,6 @@ class ESPHomeClient(BaseBleakClient):
|
||||
)
|
||||
self._cancel_connection_state = None
|
||||
|
||||
@hass_callback
|
||||
def _async_get_entry_data(self) -> RuntimeEntryData:
|
||||
"""Get the entry data."""
|
||||
config_entry = self.domain_data.get_by_unique_id(self._source)
|
||||
return self.domain_data.get_entry_data(config_entry)
|
||||
|
||||
def _async_ble_device_disconnected(self) -> None:
|
||||
"""Handle the BLE device disconnecting from the ESP."""
|
||||
_LOGGER.debug("%s: BLE device disconnected", self._source)
|
||||
@@ -125,8 +120,7 @@ class ESPHomeClient(BaseBleakClient):
|
||||
def _async_esp_disconnected(self) -> None:
|
||||
"""Handle the esp32 client disconnecting from hass."""
|
||||
_LOGGER.debug("%s: ESP device disconnected", self._source)
|
||||
entry_data = self._async_get_entry_data()
|
||||
entry_data.disconnect_callbacks.remove(self._async_esp_disconnected)
|
||||
self.entry_data.disconnect_callbacks.remove(self._async_esp_disconnected)
|
||||
self._async_ble_device_disconnected()
|
||||
|
||||
def _async_call_bleak_disconnected_callback(self) -> None:
|
||||
@@ -179,8 +173,7 @@ class ESPHomeClient(BaseBleakClient):
|
||||
connected_future.set_exception(BleakError("Disconnected"))
|
||||
return
|
||||
|
||||
entry_data = self._async_get_entry_data()
|
||||
entry_data.disconnect_callbacks.append(self._async_esp_disconnected)
|
||||
self.entry_data.disconnect_callbacks.append(self._async_esp_disconnected)
|
||||
connected_future.set_result(connected)
|
||||
|
||||
timeout = kwargs.get("timeout", self._timeout)
|
||||
@@ -203,14 +196,13 @@ class ESPHomeClient(BaseBleakClient):
|
||||
|
||||
async def _wait_for_free_connection_slot(self, timeout: float) -> None:
|
||||
"""Wait for a free connection slot."""
|
||||
entry_data = self._async_get_entry_data()
|
||||
if entry_data.ble_connections_free:
|
||||
if self.entry_data.ble_connections_free:
|
||||
return
|
||||
_LOGGER.debug(
|
||||
"%s: Out of connection slots, waiting for a free one", self._source
|
||||
)
|
||||
async with async_timeout.timeout(timeout):
|
||||
await entry_data.wait_for_ble_connections_free()
|
||||
await self.entry_data.wait_for_ble_connections_free()
|
||||
|
||||
@property
|
||||
def is_connected(self) -> bool:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"name": "ESPHome",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/esphome",
|
||||
"requirements": ["aioesphomeapi==11.0.0"],
|
||||
"requirements": ["aioesphomeapi==11.1.0"],
|
||||
"zeroconf": ["_esphomelib._tcp.local."],
|
||||
"dhcp": [{ "registered_devices": true }],
|
||||
"codeowners": ["@OttoWinter", "@jesserockz"],
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Fan",
|
||||
"documentation": "https://www.home-assistant.io/integrations/fan",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/file_upload",
|
||||
"dependencies": ["http"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -40,7 +40,10 @@ async def async_setup_entry(
|
||||
|
||||
flume_entity_list = []
|
||||
for device in flume_devices.device_list:
|
||||
if device[KEY_DEVICE_TYPE] != FLUME_TYPE_SENSOR:
|
||||
if (
|
||||
device[KEY_DEVICE_TYPE] != FLUME_TYPE_SENSOR
|
||||
or KEY_DEVICE_LOCATION not in device
|
||||
):
|
||||
continue
|
||||
|
||||
device_id = device[KEY_DEVICE_ID]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"domain": "frontend",
|
||||
"name": "Home Assistant Frontend",
|
||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||
"requirements": ["home-assistant-frontend==20220929.0"],
|
||||
"requirements": ["home-assistant-frontend==20221006.0"],
|
||||
"dependencies": [
|
||||
"api",
|
||||
"auth",
|
||||
@@ -19,5 +19,6 @@
|
||||
"websocket_api"
|
||||
],
|
||||
"codeowners": ["@home-assistant/frontend"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Geolocation",
|
||||
"documentation": "https://www.home-assistant.io/integrations/geo_location",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "entity"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import cast
|
||||
|
||||
import aiohttp
|
||||
from google.auth.exceptions import RefreshError
|
||||
@@ -105,12 +104,13 @@ async def async_setup_service(hass: HomeAssistant) -> None:
|
||||
|
||||
async def append_to_sheet(call: ServiceCall) -> None:
|
||||
"""Append new line of data to a Google Sheets document."""
|
||||
|
||||
entry = cast(
|
||||
ConfigEntry,
|
||||
hass.config_entries.async_get_entry(call.data[DATA_CONFIG_ENTRY]),
|
||||
entry: ConfigEntry | None = hass.config_entries.async_get_entry(
|
||||
call.data[DATA_CONFIG_ENTRY]
|
||||
)
|
||||
session: OAuth2Session = hass.data[DOMAIN][entry.entry_id]
|
||||
if not entry:
|
||||
raise ValueError(f"Invalid config entry: {call.data[DATA_CONFIG_ENTRY]}")
|
||||
if not (session := hass.data[DOMAIN].get(entry.entry_id)):
|
||||
raise ValueError(f"Config entry not loaded: {call.data[DATA_CONFIG_ENTRY]}")
|
||||
await session.async_ensure_token_valid()
|
||||
await hass.async_add_executor_job(_append_to_sheet, call, entry)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from typing import Any
|
||||
from google.oauth2.credentials import Credentials
|
||||
from gspread import Client, GSpreadException
|
||||
|
||||
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntry
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.helpers import config_entry_oauth2_flow
|
||||
@@ -25,6 +25,8 @@ class OAuth2FlowHandler(
|
||||
|
||||
DOMAIN = DOMAIN
|
||||
|
||||
reauth_entry: ConfigEntry | None = None
|
||||
|
||||
@property
|
||||
def logger(self) -> logging.Logger:
|
||||
"""Return logger."""
|
||||
@@ -42,6 +44,9 @@ class OAuth2FlowHandler(
|
||||
|
||||
async def async_step_reauth(self, entry_data: Mapping[str, Any]) -> FlowResult:
|
||||
"""Perform reauth upon an API authentication error."""
|
||||
self.reauth_entry = self.hass.config_entries.async_get_entry(
|
||||
self.context["entry_id"]
|
||||
)
|
||||
return await self.async_step_reauth_confirm()
|
||||
|
||||
async def async_step_reauth_confirm(
|
||||
@@ -52,40 +57,27 @@ class OAuth2FlowHandler(
|
||||
return self.async_show_form(step_id="reauth_confirm")
|
||||
return await self.async_step_user()
|
||||
|
||||
def _async_reauth_entry(self) -> ConfigEntry | None:
|
||||
"""Return existing entry for reauth."""
|
||||
if self.source != SOURCE_REAUTH or not (
|
||||
entry_id := self.context.get("entry_id")
|
||||
):
|
||||
return None
|
||||
return next(
|
||||
(
|
||||
entry
|
||||
for entry in self._async_current_entries()
|
||||
if entry.entry_id == entry_id
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
async def async_oauth_create_entry(self, data: dict[str, Any]) -> FlowResult:
|
||||
"""Create an entry for the flow, or update existing entry."""
|
||||
service = Client(Credentials(data[CONF_TOKEN][CONF_ACCESS_TOKEN]))
|
||||
|
||||
if entry := self._async_reauth_entry():
|
||||
if self.reauth_entry:
|
||||
_LOGGER.debug("service.open_by_key")
|
||||
try:
|
||||
await self.hass.async_add_executor_job(
|
||||
service.open_by_key,
|
||||
entry.unique_id,
|
||||
self.reauth_entry.unique_id,
|
||||
)
|
||||
except GSpreadException as err:
|
||||
_LOGGER.error(
|
||||
"Could not find spreadsheet '%s': %s", entry.unique_id, str(err)
|
||||
"Could not find spreadsheet '%s': %s",
|
||||
self.reauth_entry.unique_id,
|
||||
str(err),
|
||||
)
|
||||
return self.async_abort(reason="open_spreadsheet_failure")
|
||||
|
||||
self.hass.config_entries.async_update_entry(entry, data=data)
|
||||
await self.hass.config_entries.async_reload(entry.entry_id)
|
||||
self.hass.config_entries.async_update_entry(self.reauth_entry, data=data)
|
||||
await self.hass.config_entries.async_reload(self.reauth_entry.entry_id)
|
||||
return self.async_abort(reason="reauth_successful")
|
||||
|
||||
try:
|
||||
@@ -97,6 +89,7 @@ class OAuth2FlowHandler(
|
||||
return self.async_abort(reason="create_spreadsheet_failure")
|
||||
|
||||
await self.async_set_unique_id(doc.id)
|
||||
self._abort_if_unique_id_configured()
|
||||
return self.async_create_entry(
|
||||
title=DEFAULT_NAME, data=data, description_placeholders={"url": doc.url}
|
||||
)
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
},
|
||||
"auth": {
|
||||
"title": "Link Google Account"
|
||||
},
|
||||
"reauth_confirm": {
|
||||
"title": "[%key:common::config_flow::title::reauth%]",
|
||||
"description": "The Google Sheets integration needs to re-authenticate your account"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/hardware",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"quality_scale": "internal",
|
||||
"requirements": ["psutil-home-assistant==0.0.1"]
|
||||
"requirements": ["psutil-home-assistant==0.0.1"],
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
"after_dependencies": ["panel_custom"],
|
||||
"codeowners": ["@home-assistant/supervisor"],
|
||||
"iot_class": "local_polling",
|
||||
"quality_scale": "internal"
|
||||
"quality_scale": "internal",
|
||||
"integration_type": "system"
|
||||
}
|
||||
|
||||
@@ -219,7 +219,6 @@ class SupervisorOSUpdateEntity(HassioOSEntity, UpdateEntity):
|
||||
class SupervisorSupervisorUpdateEntity(HassioSupervisorEntity, UpdateEntity):
|
||||
"""Update entity to handle updates for the Home Assistant Supervisor."""
|
||||
|
||||
_attr_auto_update = True
|
||||
_attr_supported_features = UpdateEntityFeature.INSTALL
|
||||
_attr_title = "Home Assistant Supervisor"
|
||||
|
||||
@@ -233,6 +232,11 @@ class SupervisorSupervisorUpdateEntity(HassioSupervisorEntity, UpdateEntity):
|
||||
"""Return native value of entity."""
|
||||
return self.coordinator.data[DATA_KEY_SUPERVISOR][ATTR_VERSION]
|
||||
|
||||
@property
|
||||
def auto_update(self) -> bool:
|
||||
"""Return true if auto-update is enabled for supervisor."""
|
||||
return self.coordinator.data[DATA_KEY_SUPERVISOR][ATTR_AUTO_UPDATE]
|
||||
|
||||
@property
|
||||
def release_url(self) -> str | None:
|
||||
"""URL to the full release notes of the latest version available."""
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user