Skip to content

Commit 7141c74

Browse files
authored
Added HACS parsing. Additional examples (#4)
* Some additional examples Added some additional examples that I am currently using in my implementation of this custom component. * Forgot macro * Added parsing of hacs files. * Updated readme for new changes.
1 parent ea7dc42 commit 7141c74

File tree

3 files changed

+180
-2
lines changed

3 files changed

+180
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.vs

README.md

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,23 @@ Variable | Description
7171
-- | --
7272
`states` | This is the same as with the rest of Home Assistant.
7373
`custom_components` | Gives you a list of information about your custom_components
74+
`hacs_components` | Gives you a list of information about HACS installed integrations, plugins, and themes
7475

75-
The information about custom components are fetched from the integrations manifest.json file, the folowing keys are aviable:
76+
The information about custom components are fetched from the integrations manifest.json file, the folowing keys are available:
7677

7778
- `domain`
7879
- `name`
7980
- `documentation`
8081
- `codeowner`
8182

83+
The information about HACS components are fetched from the storage hacs files, the folowing keys are available:
84+
85+
- `category`
86+
- `name`
87+
- `documentation`
88+
- `authors`
89+
- `description`
90+
8291
**Example usage of the `custom_components` variable:**
8392

8493
```
@@ -91,6 +100,125 @@ _{{custom_component_descriptions[integration.domain]}}_
91100
{% endfor -%}
92101
```
93102
103+
**Example usage of the `hacs_components` variable:**
104+
105+
```
106+
### Integrations
107+
{%- for component in hacs_components | selectattr('category', 'equalto', 'integration') | sort(attribute='name') %}
108+
- [{{component.name}}]({{component.documentation}})
109+
{%- endfor %}
110+
111+
### Lovelace
112+
{%- for component in hacs_components | selectattr('category', 'equalto', 'plugin') | sort(attribute='name') %}
113+
- [{{component.name}}]({{component.documentation}})
114+
{%- endfor %}
115+
116+
### Themes
117+
{%- for component in hacs_components | selectattr('category', 'equalto', 'theme') | sort(attribute='name') %}
118+
- [{{component.name}}]({{component.documentation}})
119+
{%- endfor %}
120+
```
121+
122+
**Example usage for documenting Alexa smart home utterances**
123+
```
124+
{%- set alexa_configuration =
125+
{
126+
"domains": ["light", "camera", "vacuum", "fan"],
127+
"entities": {
128+
"included": ["climate.downstairs", "input_boolean.guest_mode", "input_boolean.assistant_notifications", "input_boolean.andrea_morning", "cover.garage_door"],
129+
"excluded": ["light.kitchen_light_1", "light.kitchen_light_2", "light.cabinet_split", "light.cabinet_large", "light.test_sensor_led", "camera.doorbell"]
130+
}
131+
}
132+
-%}
133+
{%- macro sentence_case(text) -%}
134+
{{ text[0]|upper}}{{text[1:] }}
135+
{%- endmacro -%}
136+
{% set data = namespace(domains=[]) %}
137+
{%- for state in states %}
138+
{%- if (state.entity_id in alexa_configuration.entities.included) or (state.entity_id not in alexa_configuration.entities.included and state.domain in alexa_configuration.domains) %}
139+
{%- if state.domain not in data.domains %}
140+
{%- set data.domains = data.domains + [state.domain] %}
141+
{%- endif %}
142+
{%- endif %}
143+
{%- endfor %}
144+
{%- for domain in data.domains %}
145+
### {{ sentence_case(domain) }}
146+
{%- if domain == 'climate' %}
147+
Control a thermostat temperature, run mode, etc...
148+
149+
Climate Mode | Accepted words
150+
-- | --
151+
AUTO | "auto", "automatic"
152+
COOL | "cool", "cooling"
153+
HEAT | "heat", "heating"
154+
ECO | "eco", "economical"
155+
OFF | "off"
156+
157+
**What you say:**
158+
159+
_"Alexa, set thermostat to 70."_
160+
_"Alexa, set the AC to 70."_
161+
_"Alexa, make it warmer in here."_
162+
_"Alexa, make it cooler in here."_
163+
_"Alexa, set `DEVICE NAME` to `CLIMATE MODE`."_
164+
_"Alexa, turn on the `CLIMATE MODE`."_
165+
_"Alexa, turn off the `DEVICE NAME`."_
166+
{% endif %}
167+
**Device Names:**
168+
{%- for state in states[domain] %}
169+
{%- if (state.entity_id in alexa_configuration.entities.included) or (state.entity_id not in alexa_configuration.entities.included and state.domain in alexa_configuration.domains) %}
170+
{%- if state.entity_id not in alexa_configuration.entities.excluded %}
171+
- {{state.name}}
172+
{%- endif %}
173+
{%- endif %}
174+
{%- endfor %}
175+
{%- endfor %}
176+
```
177+
178+
### Sensors
179+
180+
Create a long-lived access token in Home Assistant
181+
182+
```yaml
183+
sensor:
184+
- platform: version
185+
- platform: rest
186+
name: Addons
187+
resource: 'https://your-ha-url/api/hassio/supervisor/info'
188+
headers:
189+
Authorization: 'Bearer yourlonglivedaccesstoken'
190+
json_attributes_path: "$.data"
191+
json_attributes:
192+
- addons
193+
- addons_repositories
194+
value_template: '{{ value_json.data.addons | count}}'
195+
```
196+
197+
**Example usage of Home Assistant version badge**
198+
```
199+
[![HA Version](https://img.shields.io/badge/Home%20Assistant-{{states.sensor.current_version.state}}-brightgreen)](https://github.com/home-assistant/home-assistant/releases/{{states.sensor.current_version.state}})
200+
```
201+
202+
**Example usage of listing addon repositories**
203+
```
204+
{% for repository in states.sensor.addons.attributes.addons_repositories | sort -%}
205+
- {{ repository }}
206+
{% endfor %}
207+
```
208+
209+
**Example usage of listing addons**
210+
```
211+
{%- set addon_docs =
212+
{
213+
"core_samba": "https://github.com/home-assistant/hassio-addons/tree/master/samba",
214+
"core_mariadb": "https://github.com/home-assistant/hassio-addons/tree/master/mariadb"
215+
}
216+
-%}
217+
{% for addon in states.sensor.addons.attributes.addons | sort(attribute='name') -%}
218+
- [{{ addon.name }}]({{addon_docs[addon.slug]}})
219+
{% endfor %}
220+
```
221+
94222
If you only use this integration the output of that will be:
95223

96224
```

custom_components/readme/__init__.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,12 @@ async def service_generate(call):
165165
if ReadmeConfiguration.convert_lovelace:
166166
convert_lovelace(hass)
167167
custom_components = get_custom_components(hass)
168-
variables = {"custom_components": custom_components, "states": AllStates(hass)}
168+
hacs_components = get_hacs_components(hass)
169+
variables = {
170+
"custom_components": custom_components,
171+
"states": AllStates(hass),
172+
"hacs_components": hacs_components
173+
}
169174

170175
with open(f"{base}/templates/README.j2", "r") as readme:
171176
content = readme.read()
@@ -180,6 +185,50 @@ async def service_generate(call):
180185

181186
hass.services.async_register(DOMAIN, "generate", service_generate)
182187

188+
def get_hacs_components(hass):
189+
base = hass.config.path()
190+
keys = []
191+
hacs_components = []
192+
193+
for file in os.listdir(f"{base}/.storage/hacs"):
194+
if file.endswith(".hacs"):
195+
keys.append(os.path.splitext(file)[0])
196+
197+
if os.path.exists(f"{base}/.storage/hacs.repositories"):
198+
with open(f"{base}/.storage/hacs.repositories", "r") as repositories:
199+
content = repositories.read()
200+
content = json.loads(content)
201+
202+
for key in keys:
203+
repository = content["data"][key]
204+
205+
hacs_components.append(
206+
{
207+
"category": repository["category"],
208+
"name": get_repository_name(repository),
209+
"description": repository["description"],
210+
"authors": repository["authors"],
211+
"documentation": "https://github.com/"+repository["full_name"]
212+
}
213+
)
214+
215+
return hacs_components
216+
217+
def get_repository_name(repository) -> str:
218+
"""Return the name of the repository for use in the frontend."""
219+
name = None
220+
if repository["repository_manifest"]:
221+
name = repository["repository_manifest"]["name"]
222+
else:
223+
name = repository["full_name"].split("/")[-1]
224+
225+
if name.isupper():
226+
return name
227+
228+
return (name.replace("-", " ")
229+
.replace("_", " ")
230+
.replace("homeassistant", "")
231+
.title().strip())
183232

184233
def get_custom_components(hass):
185234
"""Return a list with custom_component info."""

0 commit comments

Comments
 (0)