mirror of
https://github.com/NickoScope/nickol-knx-mcp.git
synced 2026-09-30 03:41:58 +02:00
Completes the roadmap. The tool now validates, repairs, generates (HA/ETS/handover/IoT), diffs, grades and drafts acceptance protocols — all design-time & read-only. B-tier: - B2 climate-correctness review note (controller/operation modes, setpoint shift cmd+state, mode-without-state flag) in generate_ha.py - B3 semantic project diff (diffproj.py; diff_projects / diff_loaded) - B4 per-function acceptance test protocol (advanced.py; generate_test_protocol) - B5 Matter readiness (advanced.py; check_matter) - B6 metering/energy DPT check + PV/battery/EVSE scaffold (advanced.py; check_energy) C-tier: - C1 KNX IoT Turtle/RDF export (iot.py; generate_knx_iot) - C2 naming-hygiene suggestions (advanced.py; suggest_names) - C3 as-built completeness grader (advanced.py; grade_completeness) A-tier quick wins: - A5 Areas/voice UI-only note; A6 time/date DPT-19.001 expose block (generate_ha.py) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
60 lines
2.5 KiB
Python
60 lines
2.5 KiB
Python
"""C1 — KNX IoT semantic export (Turtle / RDF).
|
|
|
|
KNX IoT is the IP-native future: an installation is described by a *semantic* model
|
|
(functions, datapoints, DPTs) rather than only classic group addresses. This module
|
|
emits a Turtle/RDF view of the project's functional group addresses from the same graph
|
|
we already build for the GA XML — one source of truth, two exports. Read-only file
|
|
generation; no bus.
|
|
|
|
The output is a pragmatic semantic skeleton (datapoint per functional GA with its DPT,
|
|
name, role and 3-level address). It is not the full certified KNX IoT ontology, and says
|
|
so — a starting point for an IoT-native description, reviewed before use.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from .project import LoadedProject
|
|
from .intent import INTENT_FUNCTIONAL
|
|
|
|
|
|
def _esc(s: str) -> str:
|
|
return (s or "").replace("\\", "\\\\").replace('"', '\\"').replace("\n", " ")
|
|
|
|
|
|
def generate_knx_iot_turtle(project: LoadedProject) -> str:
|
|
"""Emit a Turtle/RDF semantic view of the project's functional datapoints."""
|
|
lines = [
|
|
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .",
|
|
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .",
|
|
"@prefix knx: <https://ns.knx.org/> .",
|
|
"@prefix dpt: <https://ns.knx.org/dpt/> .",
|
|
"@prefix proj: <urn:nickol-knx:project#> .",
|
|
"",
|
|
"# KNX IoT semantic view — generated read-only from the .knxproj.",
|
|
"# Pragmatic skeleton (datapoint per functional group address), NOT the full",
|
|
"# certified KNX IoT ontology. Review before use.",
|
|
"",
|
|
f'proj:project a knx:Installation ;',
|
|
f' rdfs:label "{_esc(project.info.get("name","KNX project"))}" ;',
|
|
f' knx:groupAddressStyle "{_esc(project.info.get("group_address_style","ThreeLevel"))}" .',
|
|
"",
|
|
]
|
|
n = 0
|
|
for ga in project.gas.values():
|
|
if ga.intent != INTENT_FUNCTIONAL or ga.dpt_main is None:
|
|
continue
|
|
n += 1
|
|
node = "proj:ga_" + ga.address.replace("/", "_")
|
|
lines += [
|
|
f"{node} a knx:Datapoint ;",
|
|
f' knx:groupAddress "{ga.address}" ;',
|
|
f' rdfs:label "{_esc(ga.name)}" ;',
|
|
f" knx:datapointType dpt:{(ga.dpt or '').replace('.', '-') or 'unknown'} ;",
|
|
f' knx:role "{ga.kind}" ;',
|
|
f' knx:function "{_esc(ga.category)}" ;',
|
|
f" knx:secure {'true' if ga.data_secure else 'false'} .",
|
|
"",
|
|
]
|
|
lines.insert(len(lines), f"# {n} functional datapoints exported.")
|
|
return "\n".join(lines)
|