mirror of
https://github.com/NickoScope/nickol-knx-mcp.git
synced 2026-09-30 03:41:58 +02:00
fix(handover): read domain names from GroupRanges, not mislabeled GARecord.main_name
Main/middle range names now resolve correctly (e.g. [1] Освещение 1 этаж, [5] Климат) instead of a middle-group name leaking into the main. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
a621ced701
commit
2f2b8b1f91
@@ -26,6 +26,12 @@ Zennio project (a 3646-GA multi-vendor villa, 5× larger, no ETS Functions).
|
|||||||
`Все шторы - Стоп`) surface as INFO `central_macro_no_status` instead of a
|
`Все шторы - Стоп`) surface as INFO `central_macro_no_status` instead of a
|
||||||
`missing_status_address` warning, since a fan-out broadcast has no single state to read back.
|
`missing_status_address` warning, since a fan-out broadcast has no single state to read back.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Handover domain names** — the group-address map now reads main/middle range names straight
|
||||||
|
from the project's `GroupRanges` instead of `GARecord.main_name`, which the parser could
|
||||||
|
mislabel (a middle range's name leaking into the main). Domains now render correctly
|
||||||
|
(e.g. `[1] Освещение 1 этаж`, `[5] Климат`) instead of a middle-group name.
|
||||||
|
|
||||||
## [0.2.0] — 2026-06-30
|
## [0.2.0] — 2026-06-30
|
||||||
|
|
||||||
**Colour/climate entity assembly and GA-intent noise reduction.** Two feature tracks
|
**Colour/climate entity assembly and GA-intent noise reduction.** Two feature tracks
|
||||||
|
|||||||
@@ -25,23 +25,41 @@ from .intent import INTENT_FUNCTIONAL
|
|||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
# Structure helpers
|
# Structure helpers
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
|
def _range_names(project: LoadedProject) -> tuple[dict[int, str], dict[tuple[int, int], str]]:
|
||||||
|
"""Authoritative main/middle names from the project's GroupRanges.
|
||||||
|
|
||||||
|
``GARecord.main_name`` from the parser can mislabel (it may carry a middle
|
||||||
|
range's name), so the domain map reads names straight from ``group_ranges``.
|
||||||
|
"""
|
||||||
|
main_names: dict[int, str] = {}
|
||||||
|
mid_names: dict[tuple[int, int], str] = {}
|
||||||
|
for mkey, mrange in (project.raw.get("group_ranges") or {}).items():
|
||||||
|
head = str(mkey).split("/")[0]
|
||||||
|
if not head.isdigit():
|
||||||
|
continue
|
||||||
|
mi = int(head)
|
||||||
|
main_names[mi] = mrange.get("name") or ""
|
||||||
|
for skey, srange in (mrange.get("group_ranges") or {}).items():
|
||||||
|
parts = str(skey).split("/")
|
||||||
|
if len(parts) >= 2 and parts[1].isdigit():
|
||||||
|
mid_names[(mi, int(parts[1]))] = srange.get("name") or ""
|
||||||
|
return main_names, mid_names
|
||||||
|
|
||||||
|
|
||||||
def _domain_map(project: LoadedProject) -> dict[int, dict[str, Any]]:
|
def _domain_map(project: LoadedProject) -> dict[int, dict[str, Any]]:
|
||||||
"""main -> {name, count, middles: {middle -> {name, count}}}, sorted-ready."""
|
"""main -> {name, count, middles: {middle -> {name, count}}}, sorted-ready."""
|
||||||
|
main_names, mid_names = _range_names(project)
|
||||||
mains: dict[int, dict[str, Any]] = {}
|
mains: dict[int, dict[str, Any]] = {}
|
||||||
for ga in project.gas.values():
|
for ga in project.gas.values():
|
||||||
if ga.main is None:
|
if ga.main is None:
|
||||||
continue
|
continue
|
||||||
m = mains.setdefault(ga.main, {"name": ga.main_name or "", "count": 0, "middles": {}})
|
m = mains.setdefault(
|
||||||
|
ga.main, {"name": main_names.get(ga.main, ""), "count": 0, "middles": {}})
|
||||||
m["count"] += 1
|
m["count"] += 1
|
||||||
if not m["name"] and ga.main_name:
|
midkey = ga.middle if ga.middle is not None else -1
|
||||||
m["name"] = ga.main_name
|
|
||||||
mid = m["middles"].setdefault(
|
mid = m["middles"].setdefault(
|
||||||
ga.middle if ga.middle is not None else -1,
|
midkey, {"name": mid_names.get((ga.main, midkey), ""), "count": 0})
|
||||||
{"name": ga.middle_name or "", "count": 0},
|
|
||||||
)
|
|
||||||
mid["count"] += 1
|
mid["count"] += 1
|
||||||
if not mid["name"] and ga.middle_name:
|
|
||||||
mid["name"] = ga.middle_name
|
|
||||||
return mains
|
return mains
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user