diff --git a/home-assistant-skill/ARCHITECTURE.md b/home-assistant-skill/ARCHITECTURE.md new file mode 100644 index 0000000..1807cc9 --- /dev/null +++ b/home-assistant-skill/ARCHITECTURE.md @@ -0,0 +1,72 @@ + +--- + +## Architektur (Refactoring) + +Der Code ist jetzt auf mehrere Dateien aufgeteilt, damit neue Sensoren/Geraete +nur noch wenige Zeilen Config statt eines kompletten Handlers brauchen: + +``` +home-assistant-skill/ ++-- index.js # Nur noch Config: ruft die Factories mit den echten +| # Entity-IDs auf und registriert die Handler ++-- factories.js # makeApplianceIntent, makeSimpleSensorIntent, +| # makeSlotSensorIntent, PERIOD_PHRASES ++-- ha-client.js # getHaState() - HA REST API Client ++-- static-handlers.js # Launch/Help/Cancel/Fallback/Error (Pflicht-Handler) ++-- package.json ++-- .env.example +``` + +Neuer einfacher Sensor (kein Slot), z.B. Luftfeuchtigkeit: + +```js +const GetHumidityIntentHandler = makeSimpleSensorIntent({ + intentName: 'GetHumidityIntent', + entityId: 'sensor.wohnzimmer_luftfeuchtigkeit', + template: (value, unit) => `Die Luftfeuchtigkeit betraegt ${value} ${unit}.`, +}); +``` + +Neues Geraet mit Status/Fortschritt/Endzeit, z.B. Geschirrspueler ohne +Fortschritt (nur Status, mit individueller Formulierung ueber +`customStatusTemplate`): + +```js +const GetDishwasherIntentHandler = makeApplianceIntent({ + intentName: 'GetDishwasherIntent', + deviceName: 'Der Geschirrspueler', + statusEntity: 'sensor.geschirrspueler_betriebszustand', + customStatusTemplate: (state) => `Der Geschirrspueler laeuft im Programm ${state}.`, +}); +``` + +Neue Kostengruppe mit Zeitraum-Slot (Tag/Woche/Monat), nutzt denselben +`PeriodList` Slot Type wie `GetEnergyCostIntent`: + +```js +const GetXyzEnergyCostIntentHandler = makeSlotSensorIntent({ + intentName: 'GetXyzEnergyCostIntent', + slotName: 'Period', + idToEntityMap: { + tag: 'sensor.xyz_kosten_tag', + woche: 'sensor.xyz_kosten_woche', + monat: 'sensor.xyz_kosten_monat', + }, + transformValue: (v) => parseFloat(v).toFixed(2).replace('.', ','), + template: (value, unit, periodSpoken, periodId) => + `Die Stromkosten fuer ${PERIOD_PHRASES[periodId] || periodSpoken} betragen ${value} ${unit}.`, +}); +``` + +In jedem Fall bleibt bestehen: Der zugehoerige **Intent mit Sample Utterances** +muss weiterhin in der Alexa Developer Console angelegt werden - das laesst +sich unabhaengig vom Code-Aufbau nicht vermeiden. + +`PERIOD_PHRASES` sorgt fuer korrekte deutsche Grammatik ("diese Woche" statt +"diesen Woche"), da `periodId` (die feste Slot-ID) statt des roh gesprochenen +Texts fuer die Formulierung verwendet wird. + +Aktuell zusaetzlich vorhanden: `GetPowerKammerUsageIntent` (Leistung +Kammer-Serverschrank) und `GetEnergyCostKammerIntent` (Stromkosten +Kammer-Serverschrank nach Tag/Woche/Monat) - gleiches Muster wie oben.