mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Integrations v2.1: Virtual integrations (#80613)
This commit is contained in:
parent
6c23de94e1
commit
bb287dd0ed
6
homeassistant/components/3_day_blinds/manifest.json
Normal file
6
homeassistant/components/3_day_blinds/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "3_day_blinds",
|
||||
"name": "3 Day Blinds",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/amp_motorization/manifest.json
Normal file
6
homeassistant/components/amp_motorization/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "amp_motorization",
|
||||
"name": "AMP Motorization",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/august_ble/manifest.json
Normal file
6
homeassistant/components/august_ble/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "august_ble",
|
||||
"name": "August Bluetooth",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "yalexs_ble"
|
||||
}
|
6
homeassistant/components/bliss_automation/manifest.json
Normal file
6
homeassistant/components/bliss_automation/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "bliss_automation",
|
||||
"name": "Bliss Automation",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/bloc_blinds/manifest.json
Normal file
6
homeassistant/components/bloc_blinds/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "bloc_blinds",
|
||||
"name": "Bloc Blinds",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/brel_home/manifest.json
Normal file
6
homeassistant/components/brel_home/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "brel_home",
|
||||
"name": "Brel Home",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/bswitch/manifest.json
Normal file
6
homeassistant/components/bswitch/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "bswitch",
|
||||
"name": "BSwitch",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "switchbee"
|
||||
}
|
6
homeassistant/components/bticino/manifest.json
Normal file
6
homeassistant/components/bticino/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "bticino",
|
||||
"name": "BTicino",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "netatmo"
|
||||
}
|
6
homeassistant/components/bubendorff/manifest.json
Normal file
6
homeassistant/components/bubendorff/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "bubendorff",
|
||||
"name": "Bubendorff",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "netatmo"
|
||||
}
|
6
homeassistant/components/cozytouch/manifest.json
Normal file
6
homeassistant/components/cozytouch/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "cozytouch",
|
||||
"name": "Atlantic Cozytouch",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "overkiz"
|
||||
}
|
6
homeassistant/components/dacia/manifest.json
Normal file
6
homeassistant/components/dacia/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "dacia",
|
||||
"name": "Dacia",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "renault"
|
||||
}
|
@ -56,8 +56,5 @@
|
||||
}
|
||||
],
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["denonavr"],
|
||||
"supported_brands": {
|
||||
"marantz": "Marantz"
|
||||
}
|
||||
"loggers": ["denonavr"]
|
||||
}
|
||||
|
6
homeassistant/components/diaz/manifest.json
Normal file
6
homeassistant/components/diaz/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "diaz",
|
||||
"name": "Diaz",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/digital_loggers/manifest.json
Normal file
6
homeassistant/components/digital_loggers/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "digital_loggers",
|
||||
"name": "Digital Loggers",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "wemo"
|
||||
}
|
6
homeassistant/components/dooya/manifest.json
Normal file
6
homeassistant/components/dooya/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "dooya",
|
||||
"name": "Dooya",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/flexom/manifest.json
Normal file
6
homeassistant/components/flexom/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "flexom",
|
||||
"name": "Bouygues Flexom",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "overkiz"
|
||||
}
|
6
homeassistant/components/gaviota/manifest.json
Normal file
6
homeassistant/components/gaviota/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "gaviota",
|
||||
"name": "Gaviota",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
@ -7,8 +7,5 @@
|
||||
"dependencies": ["network"],
|
||||
"codeowners": ["@cmroche"],
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["greeclimate"],
|
||||
"supported_brands": {
|
||||
"heiwa": "Heiwa"
|
||||
}
|
||||
"loggers": ["greeclimate"]
|
||||
}
|
||||
|
6
homeassistant/components/havana_shade/manifest.json
Normal file
6
homeassistant/components/havana_shade/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "havana_shade",
|
||||
"name": "Havana Shade",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/heiwa/manifest.json
Normal file
6
homeassistant/components/heiwa/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "heiwa",
|
||||
"name": "Heiwa",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "gree"
|
||||
}
|
6
homeassistant/components/hi_kumo/manifest.json
Normal file
6
homeassistant/components/hi_kumo/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "hi_kumo",
|
||||
"name": "Hitachi Hi Kumo",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "overkiz"
|
||||
}
|
@ -17,8 +17,5 @@
|
||||
],
|
||||
"zeroconf": ["_powerview._tcp.local."],
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["aiopvapi"],
|
||||
"supported_brands": {
|
||||
"luxaflex": "Luxaflex"
|
||||
}
|
||||
"loggers": ["aiopvapi"]
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "hurrican_shutters_wholesale",
|
||||
"name": "Hurrican Shutters Wholesale",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
@ -13,8 +13,5 @@
|
||||
"requirements": ["inkbird-ble==0.5.5"],
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"iot_class": "local_push",
|
||||
"supported_brands": {
|
||||
"nutrichef": "Nutrichef"
|
||||
}
|
||||
"iot_class": "local_push"
|
||||
}
|
||||
|
6
homeassistant/components/inspired_shades/manifest.json
Normal file
6
homeassistant/components/inspired_shades/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "inspired_shades",
|
||||
"name": "Inspired Shades",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/ismartwindow/manifest.json
Normal file
6
homeassistant/components/ismartwindow/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "ismartwindow",
|
||||
"name": "iSmartWindow",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/legrand/manifest.json
Normal file
6
homeassistant/components/legrand/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "legrand",
|
||||
"name": "Legrand",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "netatmo"
|
||||
}
|
6
homeassistant/components/luxaflex/manifest.json
Normal file
6
homeassistant/components/luxaflex/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "luxaflex",
|
||||
"name": "Luxaflex",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "hunterdouglas_powerview"
|
||||
}
|
6
homeassistant/components/marantz/manifest.json
Normal file
6
homeassistant/components/marantz/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "marantz",
|
||||
"name": "Marantz",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "denonavr"
|
||||
}
|
6
homeassistant/components/martec/manifest.json
Normal file
6
homeassistant/components/martec/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "martec",
|
||||
"name": "Martec",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
@ -19,25 +19,5 @@
|
||||
],
|
||||
"codeowners": ["@starkillerOG"],
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["motionblinds"],
|
||||
"supported_brands": {
|
||||
"amp_motorization": "AMP Motorization",
|
||||
"bliss_automation": "Bliss Automation",
|
||||
"bloc_blinds": "Bloc Blinds",
|
||||
"brel_home": "Brel Home",
|
||||
"3_day_blinds": "3 Day Blinds",
|
||||
"diaz": "Diaz",
|
||||
"dooya": "Dooya",
|
||||
"gaviota": "Gaviota",
|
||||
"havana_shade": "Havana Shade",
|
||||
"hurrican_shutters_wholesale": "Hurrican Shutters Wholesale",
|
||||
"inspired_shades": "Inspired Shades",
|
||||
"ismartwindow": "iSmartWindow",
|
||||
"martec": "Martec",
|
||||
"raven_rock_mfg": "Raven Rock MFG",
|
||||
"screenaway": "ScreenAway",
|
||||
"smart_blinds": "Smart Blinds",
|
||||
"smart_home": "Smart Home",
|
||||
"uprise_smart_shades": "Uprise Smart Shades"
|
||||
}
|
||||
"loggers": ["motionblinds"]
|
||||
}
|
||||
|
@ -11,11 +11,5 @@
|
||||
"models": ["Healty Home Coach", "Netatmo Relay", "Presence", "Welcome"]
|
||||
},
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["pyatmo"],
|
||||
"supported_brands": {
|
||||
"legrand": "Legrand",
|
||||
"bubendorff": "Bubendorff",
|
||||
"smarther": "Smarther",
|
||||
"bticino": "BTicino"
|
||||
}
|
||||
"loggers": ["pyatmo"]
|
||||
}
|
||||
|
6
homeassistant/components/nexity/manifest.json
Normal file
6
homeassistant/components/nexity/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "nexity",
|
||||
"name": "Nexity Eugénie",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "overkiz"
|
||||
}
|
6
homeassistant/components/nutrichef/manifest.json
Normal file
6
homeassistant/components/nutrichef/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "nutrichef",
|
||||
"name": "Nutrichef",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "inkbird"
|
||||
}
|
@ -18,13 +18,5 @@
|
||||
],
|
||||
"codeowners": ["@imicknl", "@vlebourl", "@tetienne"],
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["boto3", "botocore", "pyhumps", "pyoverkiz", "s3transfer"],
|
||||
"supported_brands": {
|
||||
"cozytouch": "Atlantic Cozytouch",
|
||||
"flexom": "Bouygues Flexom",
|
||||
"hi_kumo": "Hitachi Hi Kumo",
|
||||
"nexity": "Nexity Eugénie",
|
||||
"rexel": "Rexel Energeasy Connect",
|
||||
"somfy": "Somfy"
|
||||
}
|
||||
"loggers": ["boto3", "botocore", "pyhumps", "pyoverkiz", "s3transfer"]
|
||||
}
|
||||
|
6
homeassistant/components/pcs_lighting/manifest.json
Normal file
6
homeassistant/components/pcs_lighting/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "pcs_lighting",
|
||||
"name": "PCS Lighting",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "upb"
|
||||
}
|
6
homeassistant/components/raven_rock_mfg/manifest.json
Normal file
6
homeassistant/components/raven_rock_mfg/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "raven_rock_mfg",
|
||||
"name": "Raven Rock MFG",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
@ -6,6 +6,5 @@
|
||||
"requirements": ["renault-api==0.1.11"],
|
||||
"codeowners": ["@epenet"],
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["renault_api"],
|
||||
"supported_brands": { "dacia": "Dacia" }
|
||||
"loggers": ["renault_api"]
|
||||
}
|
||||
|
6
homeassistant/components/rexel/manifest.json
Normal file
6
homeassistant/components/rexel/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "rexel",
|
||||
"name": "Rexel Energeasy Connect",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "overkiz"
|
||||
}
|
6
homeassistant/components/roborock/manifest.json
Normal file
6
homeassistant/components/roborock/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "roborock",
|
||||
"name": "Roborock",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "xiaomi_miio"
|
||||
}
|
6
homeassistant/components/screenaway/manifest.json
Normal file
6
homeassistant/components/screenaway/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "screenaway",
|
||||
"name": "ScreenAway",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/sensorblue/manifest.json
Normal file
6
homeassistant/components/sensorblue/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "sensorblue",
|
||||
"name": "SensorBlue",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "thermobeacon"
|
||||
}
|
6
homeassistant/components/simply_automated/manifest.json
Normal file
6
homeassistant/components/simply_automated/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "simply_automated",
|
||||
"name": "Simply Automated",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "upb"
|
||||
}
|
6
homeassistant/components/smart_blinds/manifest.json
Normal file
6
homeassistant/components/smart_blinds/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "smart_blinds",
|
||||
"name": "Smart Blinds",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/smart_home/manifest.json
Normal file
6
homeassistant/components/smart_home/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "smart_home",
|
||||
"name": "Smart Home",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
6
homeassistant/components/smarther/manifest.json
Normal file
6
homeassistant/components/smarther/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "smarther",
|
||||
"name": "Smarther",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "netatmo"
|
||||
}
|
6
homeassistant/components/somfy/manifest.json
Normal file
6
homeassistant/components/somfy/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "somfy",
|
||||
"name": "Somfy",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "overkiz"
|
||||
}
|
@ -5,8 +5,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/switchbee",
|
||||
"requirements": ["pyswitchbee==1.5.5"],
|
||||
"codeowners": ["@jafar-atili"],
|
||||
"iot_class": "local_polling",
|
||||
"supported_brands": {
|
||||
"bswitch": "BSwitch"
|
||||
}
|
||||
"iot_class": "local_polling"
|
||||
}
|
||||
|
@ -27,9 +27,5 @@
|
||||
"requirements": ["thermobeacon-ble==0.3.2"],
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"iot_class": "local_push",
|
||||
"supported_brands": {
|
||||
"thermoplus": "ThermoPlus",
|
||||
"sensorblue": "SensorBlue"
|
||||
}
|
||||
"iot_class": "local_push"
|
||||
}
|
||||
|
6
homeassistant/components/thermoplus/manifest.json
Normal file
6
homeassistant/components/thermoplus/manifest.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "thermoplus",
|
||||
"name": "ThermoPlus",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "thermobeacon"
|
||||
}
|
@ -6,9 +6,5 @@
|
||||
"codeowners": ["@gwww"],
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["upb_lib"],
|
||||
"supported_brands": {
|
||||
"pcs_lighting": "PCS Lighting",
|
||||
"simply_automated": "Simply Automated"
|
||||
}
|
||||
"loggers": ["upb_lib"]
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "uprise_smart_shades",
|
||||
"name": "Uprise Smart Shades",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "motion_blinds"
|
||||
}
|
@ -21,7 +21,6 @@ from homeassistant.exceptions import (
|
||||
TemplateError,
|
||||
Unauthorized,
|
||||
)
|
||||
from homeassistant.generated import supported_brands
|
||||
from homeassistant.helpers import config_validation as cv, entity, template
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.event import (
|
||||
@ -74,7 +73,6 @@ def async_register_commands(
|
||||
async_reg(hass, handle_unsubscribe_events)
|
||||
async_reg(hass, handle_validate_config)
|
||||
async_reg(hass, handle_subscribe_entities)
|
||||
async_reg(hass, handle_supported_brands)
|
||||
async_reg(hass, handle_supported_features)
|
||||
async_reg(hass, handle_integration_descriptions)
|
||||
|
||||
@ -705,31 +703,6 @@ async def handle_validate_config(
|
||||
connection.send_result(msg["id"], result)
|
||||
|
||||
|
||||
@decorators.websocket_command(
|
||||
{
|
||||
vol.Required("type"): "supported_brands",
|
||||
}
|
||||
)
|
||||
@decorators.async_response
|
||||
async def handle_supported_brands(
|
||||
hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]
|
||||
) -> None:
|
||||
"""Handle supported brands command."""
|
||||
data = {}
|
||||
|
||||
ints_or_excs = await async_get_integrations(
|
||||
hass, supported_brands.HAS_SUPPORTED_BRANDS
|
||||
)
|
||||
for int_or_exc in ints_or_excs.values():
|
||||
if isinstance(int_or_exc, Exception):
|
||||
raise int_or_exc
|
||||
# Happens if a custom component without supported brands overrides a built-in one with supported brands
|
||||
if "supported_brands" not in int_or_exc.manifest:
|
||||
continue
|
||||
data[int_or_exc.domain] = int_or_exc.manifest["supported_brands"]
|
||||
connection.send_result(msg["id"], data)
|
||||
|
||||
|
||||
@callback
|
||||
@decorators.websocket_command(
|
||||
{
|
||||
|
@ -14,8 +14,5 @@
|
||||
},
|
||||
"codeowners": ["@esev"],
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["pywemo"],
|
||||
"supported_brands": {
|
||||
"digital_loggers": "Digital Loggers"
|
||||
}
|
||||
"loggers": ["pywemo"]
|
||||
}
|
||||
|
@ -7,8 +7,5 @@
|
||||
"codeowners": ["@rytilahti", "@syssi", "@starkillerOG", "@bieniu"],
|
||||
"zeroconf": ["_miio._udp.local."],
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["micloud", "miio"],
|
||||
"supported_brands": {
|
||||
"roborock": "Roborock"
|
||||
}
|
||||
"loggers": ["micloud", "miio"]
|
||||
}
|
||||
|
@ -12,8 +12,5 @@
|
||||
"service_uuid": "0000fe24-0000-1000-8000-00805f9b34fb"
|
||||
}
|
||||
],
|
||||
"iot_class": "local_push",
|
||||
"supported_brands": {
|
||||
"august_ble": "August Bluetooth"
|
||||
}
|
||||
"iot_class": "local_push"
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,21 +0,0 @@
|
||||
"""Automatically generated by hassfest.
|
||||
|
||||
To update, run python3 -m script.hassfest
|
||||
"""
|
||||
|
||||
HAS_SUPPORTED_BRANDS = [
|
||||
"denonavr",
|
||||
"gree",
|
||||
"hunterdouglas_powerview",
|
||||
"inkbird",
|
||||
"motion_blinds",
|
||||
"netatmo",
|
||||
"overkiz",
|
||||
"renault",
|
||||
"switchbee",
|
||||
"thermobeacon",
|
||||
"upb",
|
||||
"wemo",
|
||||
"xiaomi_miio",
|
||||
"yalexs_ble",
|
||||
]
|
@ -152,7 +152,6 @@ class Manifest(TypedDict, total=False):
|
||||
version: str
|
||||
codeowners: list[str]
|
||||
loggers: list[str]
|
||||
supported_brands: dict[str, str]
|
||||
|
||||
|
||||
def manifest_from_legacy_module(domain: str, module: ModuleType) -> Manifest:
|
||||
|
@ -20,7 +20,6 @@ from . import (
|
||||
requirements,
|
||||
services,
|
||||
ssdp,
|
||||
supported_brands,
|
||||
translations,
|
||||
usb,
|
||||
zeroconf,
|
||||
@ -39,7 +38,6 @@ INTEGRATION_PLUGINS = [
|
||||
requirements,
|
||||
services,
|
||||
ssdp,
|
||||
supported_brands,
|
||||
translations,
|
||||
usb,
|
||||
zeroconf,
|
||||
|
@ -47,7 +47,10 @@ def generate_and_validate(integrations: dict[str, Integration], config: Config):
|
||||
for domain in sorted(integrations):
|
||||
integration = integrations[domain]
|
||||
|
||||
if not integration.manifest:
|
||||
if (
|
||||
not integration.manifest
|
||||
or integration.manifest.get("integration_type") == "virtual"
|
||||
):
|
||||
continue
|
||||
|
||||
codeowners = integration.manifest["codeowners"]
|
||||
|
@ -171,14 +171,24 @@ def _generate_integrations(
|
||||
integration = integrations[domain]
|
||||
if integration.integration_type in ("entity", "system"):
|
||||
continue
|
||||
metadata["config_flow"] = integration.config_flow
|
||||
metadata["iot_class"] = integration.iot_class
|
||||
metadata["integration_type"] = integration.integration_type
|
||||
|
||||
if integration.translated_name:
|
||||
result["translated_name"].add(domain)
|
||||
else:
|
||||
metadata["name"] = integration.name
|
||||
|
||||
metadata["integration_type"] = integration.integration_type
|
||||
|
||||
if integration.integration_type == "virtual":
|
||||
if integration.supported_by:
|
||||
metadata["supported_by"] = integration.supported_by
|
||||
if integration.iot_standard:
|
||||
metadata["iot_standard"] = integration.iot_standard
|
||||
else:
|
||||
metadata["config_flow"] = integration.config_flow
|
||||
if integration.iot_class:
|
||||
metadata["iot_class"] = integration.iot_class
|
||||
|
||||
if integration.integration_type == "helper":
|
||||
result["helper"][domain] = metadata
|
||||
else:
|
||||
|
@ -2,6 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from awesomeversion import (
|
||||
@ -158,7 +159,7 @@ def verify_wildcard(value: str):
|
||||
return value
|
||||
|
||||
|
||||
MANIFEST_SCHEMA = vol.Schema(
|
||||
INTEGRATION_MANIFEST_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("domain"): str,
|
||||
vol.Required("name"): str,
|
||||
@ -254,14 +255,32 @@ MANIFEST_SCHEMA = vol.Schema(
|
||||
vol.Optional("loggers"): [str],
|
||||
vol.Optional("disabled"): str,
|
||||
vol.Optional("iot_class"): vol.In(SUPPORTED_IOT_CLASSES),
|
||||
vol.Optional("supported_brands"): vol.Schema({str: str}),
|
||||
}
|
||||
)
|
||||
|
||||
CUSTOM_INTEGRATION_MANIFEST_SCHEMA = MANIFEST_SCHEMA.extend(
|
||||
VIRTUAL_INTEGRATION_MANIFEST_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("domain"): str,
|
||||
vol.Required("name"): str,
|
||||
vol.Required("integration_type"): "virtual",
|
||||
vol.Exclusive("iot_standard", "virtual_integration"): vol.Any(
|
||||
"homekit", "zigbee", "zwave"
|
||||
),
|
||||
vol.Exclusive("supported_by", "virtual_integration"): str,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def manifest_schema(value: dict[str, Any]) -> vol.Schema:
|
||||
"""Validate integration manifest."""
|
||||
if value.get("integration_type") == "virtual":
|
||||
return VIRTUAL_INTEGRATION_MANIFEST_SCHEMA(value)
|
||||
return INTEGRATION_MANIFEST_SCHEMA(value)
|
||||
|
||||
|
||||
CUSTOM_INTEGRATION_MANIFEST_SCHEMA = INTEGRATION_MANIFEST_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional("version"): vol.All(str, verify_version),
|
||||
vol.Remove("supported_brands"): dict,
|
||||
}
|
||||
)
|
||||
|
||||
@ -284,7 +303,7 @@ def validate_manifest(integration: Integration, core_components_dir: Path) -> No
|
||||
|
||||
try:
|
||||
if integration.core:
|
||||
MANIFEST_SCHEMA(integration.manifest)
|
||||
manifest_schema(integration.manifest)
|
||||
else:
|
||||
CUSTOM_INTEGRATION_MANIFEST_SCHEMA(integration.manifest)
|
||||
except vol.Invalid as err:
|
||||
@ -312,15 +331,19 @@ def validate_manifest(integration: Integration, core_components_dir: Path) -> No
|
||||
if (
|
||||
integration.manifest["domain"] not in NO_IOT_CLASS
|
||||
and "iot_class" not in integration.manifest
|
||||
and integration.manifest.get("integration_type") != "virtual"
|
||||
):
|
||||
integration.add_error("manifest", "Domain is missing an IoT Class")
|
||||
|
||||
for domain, _name in integration.manifest.get("supported_brands", {}).items():
|
||||
if (core_components_dir / domain).exists():
|
||||
integration.add_warning(
|
||||
"manifest",
|
||||
f"Supported brand domain {domain} collides with built-in core integration",
|
||||
)
|
||||
if (
|
||||
integration.manifest.get("integration_type") == "virtual"
|
||||
and (supported_by := integration.manifest.get("supported_by"))
|
||||
and not (core_components_dir / supported_by).exists()
|
||||
):
|
||||
integration.add_error(
|
||||
"manifest",
|
||||
"Virtual integration points to non-existing supported_by integration",
|
||||
)
|
||||
|
||||
if not integration.core:
|
||||
validate_version(integration)
|
||||
|
@ -109,11 +109,12 @@ class Integration:
|
||||
continue
|
||||
|
||||
init = fil / "__init__.py"
|
||||
if not init.exists():
|
||||
manifest = fil / "manifest.json"
|
||||
if not init.exists() and not manifest.exists():
|
||||
print(
|
||||
f"Warning: {init} missing, skipping directory. "
|
||||
"If this is your development environment, "
|
||||
"you can safely delete this folder."
|
||||
f"Warning: {init} and manifest.json missing, "
|
||||
"skipping directory. If this is your development "
|
||||
"environment, you can safely delete this folder."
|
||||
)
|
||||
continue
|
||||
|
||||
@ -170,9 +171,9 @@ class Integration:
|
||||
return self.manifest.get("dependencies", [])
|
||||
|
||||
@property
|
||||
def supported_brands(self) -> dict[str]:
|
||||
"""Return dict of supported brands."""
|
||||
return self.manifest.get("supported_brands", {})
|
||||
def supported_by(self) -> str:
|
||||
"""Return the integration supported by this virtual integration."""
|
||||
return self.manifest.get("supported_by", {})
|
||||
|
||||
@property
|
||||
def integration_type(self) -> str:
|
||||
@ -184,6 +185,11 @@ class Integration:
|
||||
"""Return the integration IoT Class."""
|
||||
return self.manifest.get("iot_class")
|
||||
|
||||
@property
|
||||
def iot_standard(self) -> str:
|
||||
"""Return the IoT standard supported by this virtual integration."""
|
||||
return self.manifest.get("iot_standard", {})
|
||||
|
||||
def add_error(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""Add an error."""
|
||||
self.errors.append(Error(*args, **kwargs))
|
||||
|
@ -1,54 +0,0 @@
|
||||
"""Generate supported_brands data."""
|
||||
from __future__ import annotations
|
||||
|
||||
import black
|
||||
|
||||
from .model import Config, Integration
|
||||
from .serializer import to_string
|
||||
|
||||
BASE = """
|
||||
\"\"\"Automatically generated by hassfest.
|
||||
|
||||
To update, run python3 -m script.hassfest
|
||||
\"\"\"
|
||||
|
||||
HAS_SUPPORTED_BRANDS = {}
|
||||
""".strip()
|
||||
|
||||
|
||||
def generate_and_validate(integrations: dict[str, Integration], config: Config) -> str:
|
||||
"""Validate and generate supported_brands data."""
|
||||
|
||||
brands = [
|
||||
domain
|
||||
for domain, integration in sorted(integrations.items())
|
||||
if integration.supported_brands
|
||||
]
|
||||
|
||||
return black.format_str(BASE.format(to_string(brands)), mode=black.Mode())
|
||||
|
||||
|
||||
def validate(integrations: dict[str, Integration], config: Config) -> None:
|
||||
"""Validate supported_brands data."""
|
||||
supported_brands_path = config.root / "homeassistant/generated/supported_brands.py"
|
||||
config.cache["supported_brands"] = content = generate_and_validate(
|
||||
integrations, config
|
||||
)
|
||||
|
||||
if config.specific_integrations:
|
||||
return
|
||||
|
||||
if supported_brands_path.read_text(encoding="utf-8") != content:
|
||||
config.add_error(
|
||||
"supported_brands",
|
||||
"File supported_brands.py is not up to date. Run python3 -m script.hassfest",
|
||||
fixable=True,
|
||||
)
|
||||
|
||||
|
||||
def generate(integrations: dict[str, Integration], config: Config):
|
||||
"""Generate supported_brands data."""
|
||||
supported_brands_path = config.root / "homeassistant/generated/supported_brands.py"
|
||||
supported_brands_path.write_text(
|
||||
f"{config.cache['supported_brands']}", encoding="utf-8"
|
||||
)
|
@ -23,13 +23,7 @@ from homeassistant.helpers.json import json_loads
|
||||
from homeassistant.loader import async_get_integration
|
||||
from homeassistant.setup import DATA_SETUP_TIME, async_setup_component
|
||||
|
||||
from tests.common import (
|
||||
MockEntity,
|
||||
MockEntityPlatform,
|
||||
MockModule,
|
||||
async_mock_service,
|
||||
mock_integration,
|
||||
)
|
||||
from tests.common import MockEntity, MockEntityPlatform, async_mock_service
|
||||
|
||||
STATE_KEY_SHORT_NAMES = {
|
||||
"entity_id": "e",
|
||||
@ -1794,45 +1788,6 @@ async def test_validate_config_invalid(websocket_client, key, config, error):
|
||||
assert msg["result"] == {key: {"valid": False, "error": error}}
|
||||
|
||||
|
||||
async def test_supported_brands(hass, websocket_client):
|
||||
"""Test supported brands."""
|
||||
# Custom components without supported brands that override a built-in component with
|
||||
# supported brand will still be listed in HAS_SUPPORTED_BRANDS and should be ignored.
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule("override_without_brands"),
|
||||
)
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule("test", partial_manifest={"supported_brands": {"hello": "World"}}),
|
||||
)
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule(
|
||||
"abcd", partial_manifest={"supported_brands": {"something": "Something"}}
|
||||
),
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.generated.supported_brands.HAS_SUPPORTED_BRANDS",
|
||||
("abcd", "test", "override_without_brands"),
|
||||
):
|
||||
await websocket_client.send_json({"id": 7, "type": "supported_brands"})
|
||||
msg = await websocket_client.receive_json()
|
||||
|
||||
assert msg["id"] == 7
|
||||
assert msg["type"] == const.TYPE_RESULT
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {
|
||||
"abcd": {
|
||||
"something": "Something",
|
||||
},
|
||||
"test": {
|
||||
"hello": "World",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
async def test_message_coalescing(hass, websocket_client, hass_admin_user):
|
||||
"""Test enabling message coalescing."""
|
||||
await websocket_client.send_json(
|
||||
|
Loading…
x
Reference in New Issue
Block a user