v0.16.3
This commit is contained in:
1 parent
f376f0a7b6
commit
8059e16d12
36 files changed
+1140
-193
No files matched your search
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Static release checks for the two-node Simple day/night heating Flows.
|
||||
|
||||
Does not replace `cargo test` or hardware verification.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PROFILE_DIR = ROOT / "flows" / "simple-heating"
|
||||
ROOMS = {
|
||||
"sypialnia": ("9a0bb37d-0306-4f87-9b14-fabf3b4c6164", 20.5, 10),
|
||||
"jan-pieczara": ("7feae66a-747e-4205-8cff-91cc0b7924f6", 20.8, 8),
|
||||
"igor": ("dd451f3e-4fc0-4189-b1cf-0c814b65cefc", 20.8, 10),
|
||||
}
|
||||
TRANSLATIONS = [
|
||||
"flow.node.simpleHeat", "flow.simpleHeatDay", "flow.simpleHeatNight",
|
||||
"flow.simpleHeatMinimum", "flow.simpleHeatBoostMinutes",
|
||||
"flow.simpleHeatOffMinutes", "flow.simpleHeatHint", "zones.flowDayOff", "zones.flowDayPendingOff",
|
||||
"flow.constantDescription", "flow.constantHelp", "flow.simpleHeatDescription", "flow.simpleHeatHowItWorks",
|
||||
"flow.simpleHeatHelpIntro", "flow.simpleHeatHelpNightTitle", "flow.simpleHeatHelpNightSleep",
|
||||
"flow.simpleHeatHelpNightBrake", "flow.simpleHeatHelpNightGentle", "flow.simpleHeatHelpNightBoost",
|
||||
"flow.simpleHeatHelpDayTitle", "flow.simpleHeatHelpDayOff", "flow.simpleHeatHelpDayHeat",
|
||||
"flow.simpleHeatHelpDayStop", "flow.simpleHeatHelpSensors", "flow.simpleHeatHelpSchedule",
|
||||
"flow.simpleHeatHelpControl", "flow.simpleHeatDayTip", "flow.simpleHeatNightTip",
|
||||
"flow.simpleHeatMinimumTip", "flow.simpleHeatBoostTip", "flow.simpleHeatOffTip",
|
||||
]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
version = tomllib.loads((ROOT / "Cargo.toml").read_text())["package"]["version"]
|
||||
for name, (zone_id, target, boost) in ROOMS.items():
|
||||
path = PROFILE_DIR / f"{name}-simple-heat-v5.flow.json"
|
||||
doc = json.loads(path.read_text())
|
||||
assert doc["format"] == "gree-controller-flow" and doc["version"] == 1, name
|
||||
graph = doc["flow"]
|
||||
assert graph["enabled"] and not graph["draft"], name
|
||||
assert len(graph["nodes"]) == 2 and len(graph["edges"]) == 1, name
|
||||
conditions = [node for node in graph["nodes"] if node["kind"] == "constant"]
|
||||
actions = [node for node in graph["nodes"] if node["kind"] == "zone_heat_cycle"]
|
||||
assert len(conditions) == len(actions) == 1, name
|
||||
assert conditions[0]["config"]["value"] is True, name
|
||||
assert graph["edges"][0]["from"] == conditions[0]["id"], name
|
||||
assert graph["edges"][0]["to"] == actions[0]["id"], name
|
||||
conf = actions[0]["config"]
|
||||
assert conf["zone_id"] == zone_id, name
|
||||
assert conf["night_target"] == target, name
|
||||
assert conf["day_target"] == 20 and conf["day_min"] == 19.7, name
|
||||
assert conf["boost_after_minutes"] == boost, name
|
||||
assert conf["day_off_after_minutes"] == 30, name
|
||||
assert "Wymaga wersji aplikacji 0.16.2" in graph["description"], name
|
||||
|
||||
for lang in ("pl", "en"):
|
||||
translations = json.loads((ROOT / "lang" / f"{lang}.json").read_text())["translations"]
|
||||
assert all(translations.get(key) for key in TRANSLATIONS), lang
|
||||
|
||||
# Validate every distributable JSON input, not only the three new Flow exports.
|
||||
json_files = list(ROOT.rglob("*.json"))
|
||||
for path in json_files:
|
||||
json.loads(path.read_text())
|
||||
assert len(json_files) > 30, len(json_files)
|
||||
|
||||
js_files = list((ROOT / "web").rglob("*.js"))
|
||||
for path in js_files:
|
||||
subprocess.run(["node", "--check", str(path)], check=True, capture_output=True, text=True)
|
||||
|
||||
rust = (ROOT / "src" / "api" / "flows.rs").read_text()
|
||||
engine = (ROOT / "src" / "engine" / "zone_control.rs").read_text()
|
||||
auto = (ROOT / "src" / "engine" / "automations.rs").read_text()
|
||||
status = (ROOT / "web" / "js-dynamic" / "entities.js").read_text()
|
||||
ui = (ROOT / "web" / "js-dynamic" / "flows.js").read_text()
|
||||
html = (ROOT / "web" / "index.html").read_text()
|
||||
for value in ("zone_heat_cycle", "boost_after_minutes", "day_off_after_minutes"):
|
||||
assert value in rust and value in ui, value
|
||||
assert "simple_heat_step(" in engine and "action_zone_simple_heat" in auto
|
||||
assert "zone.simple_heat" in engine and "enabled_heat_actions" in engine
|
||||
assert "automation.flow" in status and "zones.flowDayOff" in status
|
||||
assert 'data-flow-add="zone_heat_cycle"' in html
|
||||
assert "day_target_20_starts_at_21_then_boosts_to_22" in (ROOT / "src" / "engine" / "simple_heat.rs").read_text()
|
||||
|
||||
lock = (ROOT / "Cargo.lock").read_text()
|
||||
assert f'name = "gree-controller"\nversion = "{version}"' in lock
|
||||
for manifest in [
|
||||
ROOT / "ha-addon" / "repository" / "gree-controller" / "config.yaml",
|
||||
ROOT / "ha-addon" / "home-assistant" / "custom_components" / "gree_controller" / "manifest.json",
|
||||
]:
|
||||
assert version in manifest.read_text(), manifest
|
||||
assert json.loads((ROOT / "docs" / "openapi.json").read_text())["info"]["version"] == version
|
||||
|
||||
print(f"OK: {len(ROOMS)} Flow imports, {len(json_files)} JSON files, {len(js_files)} JS scripts, translations, linked controller source, version {version}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except (AssertionError, subprocess.CalledProcessError) as exc:
|
||||
print(f"FAIL: {exc}", file=sys.stderr)
|
||||
raise
|
||||
Reference in new issue
Block a user