Skip to content

Added HACS parsing. Additional examples #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vs
130 changes: 129 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,23 @@ Variable | Description
-- | --
`states` | This is the same as with the rest of Home Assistant.
`custom_components` | Gives you a list of information about your custom_components
`hacs_components` | Gives you a list of information about HACS installed integrations, plugins, and themes

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

- `domain`
- `name`
- `documentation`
- `codeowner`

The information about HACS components are fetched from the storage hacs files, the folowing keys are available:

- `category`
- `name`
- `documentation`
- `authors`
- `description`

**Example usage of the `custom_components` variable:**

```
Expand All @@ -91,6 +100,125 @@ _{{custom_component_descriptions[integration.domain]}}_
{% endfor -%}
```

**Example usage of the `hacs_components` variable:**

```
### Integrations
{%- for component in hacs_components | selectattr('category', 'equalto', 'integration') | sort(attribute='name') %}
- [{{component.name}}]({{component.documentation}})
{%- endfor %}

### Lovelace
{%- for component in hacs_components | selectattr('category', 'equalto', 'plugin') | sort(attribute='name') %}
- [{{component.name}}]({{component.documentation}})
{%- endfor %}

### Themes
{%- for component in hacs_components | selectattr('category', 'equalto', 'theme') | sort(attribute='name') %}
- [{{component.name}}]({{component.documentation}})
{%- endfor %}
```

**Example usage for documenting Alexa smart home utterances**
```
{%- set alexa_configuration =
{
"domains": ["light", "camera", "vacuum", "fan"],
"entities": {
"included": ["climate.downstairs", "input_boolean.guest_mode", "input_boolean.assistant_notifications", "input_boolean.andrea_morning", "cover.garage_door"],
"excluded": ["light.kitchen_light_1", "light.kitchen_light_2", "light.cabinet_split", "light.cabinet_large", "light.test_sensor_led", "camera.doorbell"]
}
}
-%}
{%- macro sentence_case(text) -%}
{{ text[0]|upper}}{{text[1:] }}
{%- endmacro -%}
{% set data = namespace(domains=[]) %}
{%- for state in states %}
{%- 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) %}
{%- if state.domain not in data.domains %}
{%- set data.domains = data.domains + [state.domain] %}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- for domain in data.domains %}
### {{ sentence_case(domain) }}
{%- if domain == 'climate' %}
Control a thermostat temperature, run mode, etc...

Climate Mode | Accepted words
-- | --
AUTO | "auto", "automatic"
COOL | "cool", "cooling"
HEAT | "heat", "heating"
ECO | "eco", "economical"
OFF | "off"

**What you say:**

_"Alexa, set thermostat to 70."_
_"Alexa, set the AC to 70."_
_"Alexa, make it warmer in here."_
_"Alexa, make it cooler in here."_
_"Alexa, set `DEVICE NAME` to `CLIMATE MODE`."_
_"Alexa, turn on the `CLIMATE MODE`."_
_"Alexa, turn off the `DEVICE NAME`."_
{% endif %}
**Device Names:**
{%- for state in states[domain] %}
{%- 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) %}
{%- if state.entity_id not in alexa_configuration.entities.excluded %}
- {{state.name}}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- endfor %}
```

### Sensors

Create a long-lived access token in Home Assistant

```yaml
sensor:
- platform: version
- platform: rest
name: Addons
resource: 'https://your-ha-url/api/hassio/supervisor/info'
headers:
Authorization: 'Bearer yourlonglivedaccesstoken'
json_attributes_path: "$.data"
json_attributes:
- addons
- addons_repositories
value_template: '{{ value_json.data.addons | count}}'
```

**Example usage of Home Assistant version badge**
```
[![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}})
```

**Example usage of listing addon repositories**
```
{% for repository in states.sensor.addons.attributes.addons_repositories | sort -%}
- {{ repository }}
{% endfor %}
```

**Example usage of listing addons**
```
{%- set addon_docs =
{
"core_samba": "https://github.com/home-assistant/hassio-addons/tree/master/samba",
"core_mariadb": "https://github.com/home-assistant/hassio-addons/tree/master/mariadb"
}
-%}
{% for addon in states.sensor.addons.attributes.addons | sort(attribute='name') -%}
- [{{ addon.name }}]({{addon_docs[addon.slug]}})
{% endfor %}
```

If you only use this integration the output of that will be:

```
Expand Down
51 changes: 50 additions & 1 deletion custom_components/readme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,12 @@ async def service_generate(call):
if ReadmeConfiguration.convert_lovelace:
convert_lovelace(hass)
custom_components = get_custom_components(hass)
variables = {"custom_components": custom_components, "states": AllStates(hass)}
hacs_components = get_hacs_components(hass)
variables = {
"custom_components": custom_components,
"states": AllStates(hass),
"hacs_components": hacs_components
}

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

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

def get_hacs_components(hass):
base = hass.config.path()
keys = []
hacs_components = []

for file in os.listdir(f"{base}/.storage/hacs"):
if file.endswith(".hacs"):
keys.append(os.path.splitext(file)[0])

if os.path.exists(f"{base}/.storage/hacs.repositories"):
with open(f"{base}/.storage/hacs.repositories", "r") as repositories:
content = repositories.read()
content = json.loads(content)

for key in keys:
repository = content["data"][key]

hacs_components.append(
{
"category": repository["category"],
"name": get_repository_name(repository),
"description": repository["description"],
"authors": repository["authors"],
"documentation": "https://github.com/"+repository["full_name"]
}
)

return hacs_components

def get_repository_name(repository) -> str:
"""Return the name of the repository for use in the frontend."""
name = None
if repository["repository_manifest"]:
name = repository["repository_manifest"]["name"]
else:
name = repository["full_name"].split("/")[-1]

if name.isupper():
return name

return (name.replace("-", " ")
.replace("_", " ")
.replace("homeassistant", "")
.title().strip())

def get_custom_components(hass):
"""Return a list with custom_component info."""
Expand Down