Skip to content

Commit 234b1f2

Browse files
committed
Update our custom component so that it actually works reliably
1 parent 752779e commit 234b1f2

File tree

3 files changed

+88
-57
lines changed

3 files changed

+88
-57
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ Install the Python module within your virtual environment:
1414
(venv) $ pip install zigpy-znp
1515
```
1616

17-
If you are using Home Assistant, copy `custom_components/custom_zha_radios.py` into your `custom_components` folder and create a new entry in your `configuration.yaml` file:
17+
If you are using Home Assistant, copy `custom_components/zha_custom_radios.py` into your `custom_components` folder and create a new entry in your `configuration.yaml` file:
1818

1919
```yaml
20-
custom_zha_radios:
20+
zha_custom_radios:
2121
znp:
2222
module: zigpy_znp.zigbee.application
2323
description: TI CC13x2, CC26x2, ZZH, and CC2531

custom_components/custom_zha_radios.py

Lines changed: 0 additions & 55 deletions
This file was deleted.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import os
2+
import logging
3+
import importlib
4+
5+
from homeassistant.core import HomeAssistant
6+
from homeassistant.config import load_yaml_config_file, YAML_CONFIG_FILE
7+
from homeassistant.__main__ import get_arguments
8+
9+
LOGGER = logging.getLogger(__name__)
10+
DOMAIN = "zha_custom_radios"
11+
12+
13+
def setup(hass, config):
14+
"""
15+
No-op. This code runs way too late to do anything useful.
16+
"""
17+
return True
18+
19+
20+
def inject_enum_member(target_enum, name, value):
21+
"""
22+
Hack to inject a new member into an enum.
23+
"""
24+
25+
member = target_enum._member_type_.__new__(target_enum)
26+
member._name_ = name
27+
member._value_ = value
28+
29+
if not isinstance(value, tuple):
30+
args = (value,)
31+
else:
32+
args = value
33+
34+
target_enum.__init__(member, *args)
35+
36+
target_enum._member_names_.append(name)
37+
target_enum._member_map_[name] = member
38+
target_enum._value2member_map_[value] = member
39+
type.__setattr__(target_enum, name, member)
40+
41+
42+
def get_ha_config():
43+
"""
44+
Duplicate enough of the HA startup sequence to extract the config *really* early.
45+
"""
46+
47+
args = get_arguments()
48+
49+
hass = HomeAssistant()
50+
hass.config.config_dir = os.path.abspath(os.path.join(os.getcwd(), args.config))
51+
52+
return load_yaml_config_file(hass.config.path(YAML_CONFIG_FILE))
53+
54+
55+
def inject(config):
56+
"""
57+
Injects new ZHA radio modules specified in the YAML config.
58+
"""
59+
60+
try:
61+
from homeassistant.components.zha.core.const import RadioType
62+
except ImportError:
63+
LOGGER.error(
64+
"It looks like HA has not finished setting up its dependencies yet "
65+
"on first launch. Restart Home Assistant once it finishes."
66+
)
67+
return
68+
69+
custom_names = list(config[DOMAIN].keys())
70+
original_names = list(RadioType._member_names_)
71+
72+
for name, obj in config[DOMAIN].items():
73+
module = importlib.import_module(obj["module"])
74+
app = module.ControllerApplication
75+
description = obj["description"]
76+
77+
LOGGER.warning("Injecting %s (%s) as a new radio type", name, obj)
78+
inject_enum_member(RadioType, name, (description, app))
79+
80+
# New keys are moved up top
81+
RadioType._member_names_ = custom_names + original_names
82+
83+
84+
# We are a purposefully a legacy integration so we can run this when we're imported.
85+
# This allows us to run way before anything else has even had a chance to load.
86+
inject(get_ha_config())

0 commit comments

Comments
 (0)