Skip to content

Commit c5a17b1

Browse files
authored
Merge pull request #35 from senyo888/senyo888-patch-1
2 parents 1c6e81d + 9ef3241 commit c5a17b1

20 files changed

Lines changed: 4391 additions & 28 deletions

File tree

.github/pull_request_template.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,9 @@
2323
## UI Gallery submissions
2424

2525
- [ ] Uses `/ui-gallery/<card-id>/`.
26-
- [ ] Includes `README.md`, YAML, and `preview.png`.
26+
- [ ] Includes `README.md`, `preview.png`, and `card.yaml` or `dashboard.yaml`.
27+
- [ ] Top-level `ui-gallery/README.md` is updated.
28+
- [ ] Example follows `ui-gallery/reference.txt` format.
29+
- [ ] Required custom cards are documented.
2730
- [ ] Preserves canonical Humidity Intelligence backend entities/helpers.
31+
- [ ] Screenshots and YAML contain no private entity IDs, secrets, addresses, device IDs, tokens, internal URLs, or personal data.

.github/workflows/hacs.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ on:
77
- cron: "0 0 * * *"
88
workflow_dispatch:
99

10-
permissions:
11-
contents: read
10+
permissions: {}
1211

1312
concurrency:
1413
group: ${{ github.workflow }}-${{ github.ref }}

.github/workflows/hassfest.yaml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: Validate with hassfest
2+
3+
on:
4+
push:
5+
pull_request:
6+
schedule:
7+
- cron: "0 0 * * *"
8+
9+
jobs:
10+
validate:
11+
runs-on: "ubuntu-latest"
12+
steps:
13+
- uses: "actions/checkout@v3"
14+
15+
- name: Stage custom component layout
16+
shell: bash
17+
run: |
18+
set -euo pipefail
19+
mkdir -p custom_components/humidity_intelligence
20+
rsync -a \
21+
__init__.py \
22+
binary_sensor.py \
23+
config_flow.py \
24+
const.py \
25+
manifest.json \
26+
migration.py \
27+
sensor.py \
28+
services.py \
29+
services.yaml \
30+
strings.json \
31+
switch.py \
32+
translations \
33+
automations \
34+
helpers \
35+
sensors \
36+
ui \
37+
custom_components/humidity_intelligence/
38+
rm -f manifest.json
39+
40+
- name: Normalize staged Hassfest metadata
41+
shell: bash
42+
run: |
43+
set -euo pipefail
44+
python3 - <<'PY'
45+
import json
46+
from pathlib import Path
47+
48+
base = Path("custom_components/humidity_intelligence")
49+
50+
manifest_path = base / "manifest.json"
51+
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
52+
ordered_manifest = {
53+
"domain": manifest.pop("domain"),
54+
"name": manifest.pop("name"),
55+
}
56+
for key in sorted(manifest):
57+
ordered_manifest[key] = manifest[key]
58+
manifest_path.write_text(
59+
json.dumps(ordered_manifest, indent=2, ensure_ascii=False) + "\n",
60+
encoding="utf-8",
61+
)
62+
63+
for rel_path in ("strings.json", "translations/en.json"):
64+
path = base / rel_path
65+
data = json.loads(path.read_text(encoding="utf-8"))
66+
for section in ("config", "options"):
67+
root = data.setdefault(section, {})
68+
shared_errors = dict(root.get("error", {}))
69+
for step in root.get("step", {}).values():
70+
if isinstance(step, dict):
71+
shared_errors.update(step.pop("errors", {}) or {})
72+
if shared_errors:
73+
root["error"] = shared_errors
74+
75+
text = json.dumps(data, indent=2, ensure_ascii=False)
76+
text = text.replace(
77+
"humidity_intelligence_cards_<layout>.yaml",
78+
"humidity_intelligence_cards_layout.yaml",
79+
)
80+
path.write_text(text + "\n", encoding="utf-8")
81+
PY
82+
83+
- name: Verify staged Hassfest metadata
84+
shell: bash
85+
run: |
86+
set -euo pipefail
87+
python3 - <<'PY'
88+
import json
89+
from pathlib import Path
90+
91+
base = Path("custom_components/humidity_intelligence")
92+
manifest = json.loads((base / "manifest.json").read_text(encoding="utf-8"))
93+
keys = list(manifest)
94+
expected = ["domain", "name"] + sorted(keys[2:])
95+
if keys != expected:
96+
raise SystemExit(f"Manifest keys are not sorted for Hassfest: {keys}")
97+
98+
for rel_path in ("strings.json", "translations/en.json"):
99+
path = base / rel_path
100+
text = path.read_text(encoding="utf-8")
101+
data = json.loads(text)
102+
if "<layout>" in text:
103+
raise SystemExit(f"{rel_path} still contains <layout>")
104+
for section in ("config", "options"):
105+
for step_name, step in data.get(section, {}).get("step", {}).items():
106+
if isinstance(step, dict) and "errors" in step:
107+
raise SystemExit(f"{rel_path} has nested errors at {section}.{step_name}")
108+
print("Staged Hassfest metadata is normalized.")
109+
PY
110+
111+
- uses: home-assistant/actions/hassfest@master

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ This project follows a practical changelog format for Home Assistant and HACS us
88

99
- Added GitHub community health files, issue forms, validation workflows, and contributor guidance.
1010
- Added CI SAST/security checks, Bandit configuration, broader diagnostics redaction, and cleanup error logging.
11+
- Added Hassfest validation workflow for Home Assistant custom integration checks.
12+
- Updated Hassfest compatibility by staging the root-content HACS layout as `custom_components/humidity_intelligence`, aligning manifest keys, shared flow errors, and Lovelace after-dependency metadata.
13+
- Added pre-Hassfest staged metadata normalization and verification so CI validates the generated custom component tree, not stale root metadata.
14+
- Added a V2 UI Gallery with default mobile, tablet, and legacy mobile examples plus contributor/reference documentation.
1115

1216
## 2.0.3
1317

CONTRIBUTING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ Each Gallery submission should include:
3939
- `card.yaml` or `dashboard.yaml`
4040
- `preview.png`
4141

42-
Gallery examples must preserve canonical Humidity Intelligence backend entities/helpers. Do not publish private entity IDs, secrets, addresses, personal data, or screenshots that reveal sensitive home information.
42+
Use [ui-gallery/CONTRIBUTING.md](ui-gallery/CONTRIBUTING.md) and [ui-gallery/reference.txt](ui-gallery/reference.txt) for the required gallery format.
43+
44+
Gallery examples must preserve canonical Humidity Intelligence backend entities/helpers. Do not publish private entity IDs, secrets, addresses, personal data, or screenshots that reveal sensitive home information. Add or update the matching entry in [ui-gallery/README.md](ui-gallery/README.md) when adding a gallery example.
4345

4446
## Privacy and redaction
4547

README.md

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
[![Latest Release](https://img.shields.io/github/v/release/senyo888/Humidity-Intelligence?display_name=tag&sort=semver)](https://github.com/senyo888/Humidity-Intelligence/releases)
1010
[![HACS](https://img.shields.io/badge/HACS-Custom%20Integration-orange)](https://hacs.xyz)
11-
[![Home Assistant](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsenyo888%2FHumidity-Intelligence%2Fmain%2Fmanifest.json&query=%24.homeassistant&prefix=%3E%3D&label=Home%20Assistant&color=blue)](https://www.home-assistant.io/)
11+
[![Home Assistant](https://img.shields.io/badge/Home%20Assistant-2026.4.3%2B-blue)](https://www.home-assistant.io/)
1212
[![License](https://img.shields.io/github/license/senyo888/Humidity-Intelligence)](LICENSE)
1313

1414
<details>
@@ -21,28 +21,19 @@
2121
</details>
2222

2323
<details>
24-
<summary><strong>V2 UI Gallery (PNG)</strong></summary>
24+
<summary><strong>V2 UI Examples (PNG)</strong></summary>
2525

2626
<br>
2727

2828
<img src="assets/v2_ui_gallery/IMG_5665.png" width="320" alt="V2 UI gallery image 1">
29-
3029
<img src="assets/v2_ui_gallery/IMG_5672.png" width="320" alt="V2 UI gallery image 2">
31-
3230
<img src="assets/v2_ui_gallery/IMG_5673.png" width="320" alt="V2 UI gallery image 3">
33-
3431
<img src="assets/v2_ui_gallery/IMG_5674.png" width="320" alt="V2 UI gallery image 4">
35-
3632
<img src="assets/v2_ui_gallery/IMG_0323.png" width="320" alt="V2 UI gallery image 5">
37-
3833
<img src="assets/v2_ui_gallery/IMG_0324.png" width="320" alt="V2 UI gallery image 6">
39-
4034
<img src="assets/v2_ui_gallery/IMG_5675.png" width="320" alt="V2 UI gallery image 7">
41-
4235
<img src="assets/v2_ui_gallery/ui_v1_mobile.png" width="320" alt="V2 UI gallery image 8">
43-
4436
<img src="assets/v2_ui_gallery/ui_v2_mobile_aq.png" width="320" alt="V2 UI gallery image 9">
45-
4637
<img src="assets/v2_ui_gallery/ui_v2_tablet_zone_2.png" width="320" alt="V2 UI gallery image 10">
4738

4839
</details>
@@ -60,6 +51,7 @@
6051
- [Migration Guide - v1 to v2](#migration-guide---v1-to-v2)
6152
- [Full Configuration Flow](#full-configuration-flow)
6253
- [Configuration Screenshots (Visual Guide)](#configuration-screenshots-visual-guide)
54+
- [UI Gallery](#ui-gallery)
6355
- [Post-Configuration Workflow](#post-configuration-workflow)
6456
- [How to Use Services](#how-to-use-services)
6557
- [Release Notes](#release-notes)
@@ -135,7 +127,7 @@ V2 models that instability structurally.
135127

136128
`56%` is not always "high."
137129

138-
Humidity Intelligence v2 evaluates humidity **relative to the active target profile**:
130+
Humidity Intelligence v2.0.3 evaluates humidity **relative to the active target profile**:
139131

140132
- Winter defaults to a lower comfort band than summer
141133
- Spring and autumn use intermediate bands
@@ -217,7 +209,7 @@ The UI renders.
217209
- dependency status lines now include direct upstream repository links for fast install/verification
218210
- options menu order updated to prioritize setup sequence: Dependencies -> Sensors -> Global Gates
219211
- README dependency guidance expanded and clarified for HACS-first UI setup
220-
- top badges updated for clearer positioning (`Custom Integration`) and auto-synced Home Assistant compatibility from `manifest.json`
212+
- top badges updated for clearer positioning (`Custom Integration`) and Home Assistant compatibility
221213

222214
Upgrade note: **v2.0.3 focuses on dependency clarity, UI onboarding accuracy, and metadata consistency.**
223215
No breaking schema changes are introduced.
@@ -629,6 +621,20 @@ Example service usage:
629621

630622
---
631623

624+
## UI Gallery
625+
626+
Reusable default UI examples live in [ui-gallery](ui-gallery/README.md).
627+
628+
Included examples:
629+
630+
- [Default V2 Mobile AQ](ui-gallery/default-v2-mobile-aq/README.md)
631+
- [Default V2 Tablet Zone 2](ui-gallery/default-v2-tablet-zone-2/README.md)
632+
- [Default V1 Mobile](ui-gallery/default-v1-mobile/README.md)
633+
634+
For new gallery submissions, follow [ui-gallery/CONTRIBUTING.md](ui-gallery/CONTRIBUTING.md).
635+
636+
---
637+
632638
## Post-Configuration Workflow
633639

634640
When modifying options:
@@ -796,12 +802,13 @@ Safety guidance:
796802

797803
### v2.0.3
798804

799-
- updated minimum Home Assistant version to `2026.4.3` in `manifest.json`
805+
- bumped integration version to `2.0.3`
806+
- documented minimum Home Assistant version as `2026.4.3`
800807
- dependency status output now includes direct repository links (`card-mod`, `button-card`, `mod-card`, `apexcharts-card`, `HACS`)
801808
- added post-configuration Dependencies options step so dependency checks are accessible after initial setup
802809
- reordered options menu for setup flow clarity (`Dependencies`, then `Sensors`, then `Global Gates`)
803810
- refreshed README dependency section with clearer HACS-first install guidance and acknowledgements
804-
- updated top badges: HACS badge wording now `Custom Integration`, and Home Assistant badge now auto-reads compatibility from `manifest.json`
811+
- updated top badges: HACS badge wording now `Custom Integration`, and Home Assistant compatibility is shown directly
805812

806813
### v2.0.2
807814

@@ -811,7 +818,7 @@ Safety guidance:
811818
- humidifier telemetry reason expanded with lane scope, trigger condition, measured values vs thresholds, and recovery logic
812819
- runtime debug logs added for active target profile, seasonal adjustments, humidity badge classification, and humidifier trigger/stop events
813820

814-
### v2.0.1
821+
### v2.0.1 fixes
815822

816823
- fixed Fahrenheit telemetry normalization by converting all internal temperature math to Celsius before averages, spreads, deltas, and thresholds
817824
- fixed aggregate behavior so IAQ/AQ averages ignore `unknown`, `unavailable`, and non-numeric states and only return unknown when no valid values exist

__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import logging
66
from homeassistant.config_entries import ConfigEntry
77
from homeassistant.core import HomeAssistant
8+
from homeassistant.helpers import config_validation as cv
89

910
from .const import DOMAIN
1011
from .services import async_register_services, async_unregister_services
@@ -15,6 +16,8 @@
1516

1617
_LOGGER = logging.getLogger(__name__)
1718

19+
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
20+
1821

1922
async def async_setup(hass: HomeAssistant, config: dict) -> bool:
2023
"""Set up the Humidity Intelligence integration via YAML."""

manifest.json

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
{
22
"domain": "humidity_intelligence",
33
"name": "Humidity Intelligence",
4-
"icon": "mdi:water-percent",
5-
"version": "2.0.3",
6-
"documentation": "https://github.com/senyo888/humidity-intelligence",
7-
"issue_tracker": "https://github.com/senyo888/humidity-intelligence/issues",
8-
"config_flow": true,
9-
"homeassistant": "2026.4.3",
10-
"requirements": [],
4+
"after_dependencies": ["lovelace"],
115
"codeowners": ["@senyo888"],
6+
"config_flow": true,
7+
"documentation": "https://github.com/senyo888/Humidity-Intelligence",
8+
"import_executor": true,
129
"iot_class": "calculated",
13-
"import_executor": true
10+
"issue_tracker": "https://github.com/senyo888/Humidity-Intelligence/issues",
11+
"requirements": [],
12+
"version": "2.0.3"
1413
}

0 commit comments

Comments
 (0)