diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..fb1a42a
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,23 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "OpenKNXproducer Documentation",
+ "type": "shell",
+ "command": "~/bin/OpenKNXproducer.exe",
+ "args": [
+ "baggages",
+ "--DocFileName",
+ "doc/Applikationsbeschreibung-FunctionBlocks.md",
+ "--BaggagesDir",
+ "src/Baggages/Help_de",
+ "--Prefix",
+ "FCB"
+ ],
+ "problemMatcher": [],
+ "group": "test"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index cbd216f..51e126d 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,14 @@ Bei Bedarf können die FunktionsBlöcke mit Logiken ergänzen werden.
- AND mit 9 Eingängen
- OR mit 9 Eingängen
- Prioritätsschalter
+- Anzahl
+- Aggregation
+ - Summe
+ - Mittelwert
+ - Minimum
+ - Maximum
+ - Spannbreite (Maximum - Minimum)
+
## Planned Features
- Multiplexer
diff --git a/doc/Applikationsbeschreibung-FunctionBlocks.md b/doc/Applikationsbeschreibung-FunctionBlocks.md
index 4cdc29f..cae6951 100644
--- a/doc/Applikationsbeschreibung-FunctionBlocks.md
+++ b/doc/Applikationsbeschreibung-FunctionBlocks.md
@@ -5,6 +5,29 @@
Die Anwendung stellt je Kanal einen Funktionsblock bereit.
Folgende Funktionsblöcke stehen zur Auswahl:
+ * [UND](#und)
+ * [ODER](#oder)
+ * [Prioritätsschalter](#prioritätsschalter)
+ * [Beispielanwendungen](#beispielsanwendung)
+ * [Anzahl](#anzahl)
+ * [Statistische Aggregation](#statistische-aggregation)
+
+
+
+### ETS Konfiguration
+
+* **[Allgemein](#allgemein)**
+ * [Kanalauswahl](#kanalauswahl)
+* (n=1 bis 99) *Abhängig vomTyp*:
+ * [Kanal-Typ-unabhängige Einstellungen](#kanaleinstellungen)
+ * {[**UND**, **ODER**, **Anzahl**](#undoderanzahl-kanaleinstellungen)}
+ * [**Prioritätsschalter**](#prioritätsschalter-2)
+ * [**Aggregation**](#aggregation)
+
+
+
+# Blocktypen
+
## UND
@@ -38,7 +61,21 @@ Jedoch bietet der Taste die Möglichkeit verschiedene Prozentwerte mit verschied
So können z.B. für einen Jalousientaster Kommunikationswerte für Nachbetrieb, Beschattung aktiv, Windsperre auf Prozentwerte umgesetzt werden, die der Taster in verschiedene Farbwerte umsetzt.
-# Konfiguration
+
+## Anzahl
+
+Ein Anzahl-Funktionsblock verfügt über bis zu 9 Eingänge.
+Der Ausgang gibt aus, wie viele der (verwendeten) Eingänge den Wert EIN angenommen haben.
+Die Eingänge können vor Zählung invertiert werden.
+
+
+## Statistische Aggregation
+
+Ein Aggregations-Funktionsblock verfügt über bis zu 9 numerische Eingänge, gängiger DPTs.
+Der Ausgangswert wird basierend auf der gewählten Funktion (Summe, Mittelwert, Minimum, Maximum, Spannbreite) berechnet und kann in verschiedenen numerischen DPTs ausgegeben werden.
+Es kann beeinflusst werden, wie mit Werten umgegangen wird die vom Ausgatyp nicht dargestellt werden können.
+
+# ETS Konfiguration
## Allgemein
@@ -55,19 +92,25 @@ Die Einstellung dient lediglich dazu, die Seite der Basiseinstellungen kompakt a
Für jeden Kanal kann für einen Funktionsblock konfiguriert werden:
-#### UND
+- **UND**
+ Ein UND-Funktionsblock verfügt über bis zu 9 Eingänge.
+ Der Ausgang gibt EIN aus, wenn alle Eingänge EIN sind.
-Ein UND-Funktionsblock verfügt über bis zu 9 Eingänge.
-Der Ausgang gibt EIN aus, wenn alle Eingänge EIN sind.
+- **ODER**
+ Ein ODER-Funktionsblock verfügt über bis zu 9 Eingänge.
+ Der Ausgang gibt EIN aus, wenn mindestens ein Eingang EIN ist.
-#### ODER
+- **Prioritätsschalter**
+ Ein Prioritätsschalter hat bis zu 9 Eingänge vom Typ EIN/AUS.
+ Der Eingang mit der höchsten Priorität der EIN ist, bestimmt den Ausgangswert.
-Ein ODER-Funktionsblock verfügt über bis zu 9 Eingänge. Der Ausgang gibt EIN aus, wenn mindestens ein Eingang EIN ist.
+- **Anzahl**
+ Ein Anzahl-Funktionsblock hat bis zu 9 Eingänge vom Typ EIN/AUS.
+ Der Ausgang gibt die Anzahl der Eingänge mit dem Wert EIN aus.
-#### Prioritätsschalter
-
-Ein Prioritätsschalter hat bis zu 9 Eingänge vom Typ EIN/AUS.
-Der Eingang mit der höchsten Priorität der EIN ist, bestimmt den Ausgangswert.
+- **Statistische Aggregation**
+ Ein Aggregations-Funktionsblock hat bis zu 9 Eingänge mit numerischem Typ.
+ Es kann zwischen fünf Funktionen (Summe, Mittelwert, Minimum, Maximum, Spannbreite) zur Berechnung des Ausgangswertes gewählt werden.
## Kanaleinstellungen
@@ -76,8 +119,8 @@ Jeder Kanal bietet folgende Einstellungen:
### Bezeichnung
-Die Bezeichnung wird innerhalb der ETS für die Bennenung des Kanals und für die Bennenung der Funktionsblock Ein- und Ausgänge verwendet.
-Die Bezeichnung hat keinen Einfluss auf die Funktion des Funktionsblocks und kann jederzeit auch nachträglich angepasst werden.
+Die Bezeichnung wird innerhalb der ETS für die Benennung des Kanals und für die Benennung der Funktionsblock Ein- und Ausgänge verwendet.
+Die Bezeichnung hat keinen Einfluss auf das Verhalten des Funktionsblocks und kann jederzeit auch nachträglich angepasst werden.
### Kanal deaktivieren (zu Testzwecken)
@@ -86,12 +129,53 @@ Mit dieser Einstellung kann ein Kanal deaktiviert werden, ohne das die Konfigura
Ein deaktivierter Kanal sendet keine Telegramme auf dem KNX-Bus.
-## UND/ODER Kanaleinstellungen
+
+#### Kommentar
+
+Hier kann eine ausführlichere - auch mehrzeilige - Dokumention des Blocks erfolgen.
+Es wird empfohlen zentrale Annahmen die der Konfiguration des Blocks zugrunde liegen hier festzuhalten.
+Die Dokumentation hat keinen Einfluss auf das Geräteverhalten.
+
+Eine mehrzeilige Eingabe ist aufgrund von Beschränkungen der ETS nicht direkt möglich,
+kann jedoch durch Eingabe mit `\n` und Drücken des Buttons erzeugt werden.
+Anschließend kann der Text mehrzeilig bearbeitet werden.
+
+
+*Beispiel:*
+>
+> Der Text
+> ```
+> Ein Text\nmit mehreren\nZeilen!
+> ```
+> wird umgewandelt in
+> ```
+> Ein Text
+> mit mehreren
+> Zeilen!
+> ```
+
+
+
+### Sendeverhalten
+
+Zur Auswahl stehen:
+
+- **Bei jedem Eingangstelegram**
+ Wenn einer der Eingänge ein Telegramm empfängt, wird der Ausgangswert auf den Bus gesendet.
+ Diese Einstellung kann zu hintereinderfolgenden gleichen Ausgangswerten am Bus führen.
+
+- **Nur bei Änderung des Ausgangswertes**
+ Der Ausgang wird nur dann auf den Bus gesendet, wenn sich durch die berechnete Logikfunktion der Wert ändert.
+
+
+Unabhängig von der Einstellung wird der Ausgangswert auch nach der Initialisierungsphase inklusive eventueller Wartezeit für Leseanforderungs-Antworten einmalig auf den Bus gesendet.
+
+## UND/ODER/Anzahl Kanaleinstellungen
### Eingang 1-9
-Legt fest ob der Eingang verwendet wird und ob der Eingangswert normal oder invertiert verwendet wird.
+Legt fest, ob der Eingang verwendet wird, und falls ja, ob der Eingangswert **normal** oder **invertiert** verwendet wird.
### Initialisierung
@@ -113,26 +197,11 @@ Zur Auswahl stehen:
**Wichtig**: Die Vorbelegung erfolgt vor einer möglichen eingestellten Invertierung des Eingangswertes.
Das bedeutet das bei einer Vorbelegung von "AUS" und einer eingestellten Invertierung der Wert als EIN von der Logik interpretiert wird.
-
-### Invertiert
+### Invertiert (nur UND/ODER)
+
Legt fest, ob der Ausgangswert normal oder invertiert auf den Bus gesendet wird.
-
-### Sendeverhalten
-
-Zur Auswahl stehen:
-
-- **Bei jedem Eingangstelegram**
- Wenn einer der Eingänge ein Telegramm empfängt, wird der Ausgangswert auf den Bus gesendet.
- Diese Einstellung kann zu hintereinderfolgenden gleichen Ausgangswerten am Bus führen.
-
-- **Nur bei Änderung des Ausgangswertes**
- Der Ausgang wird nur dann auf den Bus gesendet, wenn sich durch die berechnete Logikfunktion der Wert ändert.
-
-
-Unabhängig von der Einstellung wird der Ausgangswert auch nach der Initialisierungsphase inklusive eventueller Wartezeit für Leseanforderungs-Antworten einmalig auf den Bus gesendet.
-
## Prioritätsschalter
@@ -145,22 +214,6 @@ Legt fest, welchen Werttype für den Ausgang verwendet wird
- **1 Byte (Ohne Vorzeichen)**
Ausgang ist byte (5.* 8 bit vorzeichenlos)
-
-
-### Sendeverhalten
-
-Zur Auswahl stehen:
-
-- **Bei jedem Eingangstelegram**
- Wenn einer der Eingänge ein Telegramm empfängt, wird der Ausgangswert auf den Bus gesendet.
- Diese Einstellung kann zu hintereinderfolgenden gleichen Ausgangswerten am Bus führen.
-
-- **Nur bei Änderung des Ausgangswertes**
- Der Ausgang wird nur dann auf den Bus gesendet, wenn sich durch die berechnete Logikfunktion der Wert ändert.
-
-
-Unabhängig von der Einstellung wird der Ausgangswert auch nach der Initialisierungsphase inklusive eventueller Wartezeit für Leseanforderungs-Antworten einmalig auf den Bus gesendet.
-
### Ausgangswert wenn alle Eingänge AUS
@@ -169,7 +222,7 @@ Legt den Wert für den Ausgang fest, wenn alle Eingänge AUS sind.
### Eingang 1-9
-Legt fest ob der Eingang verwendet wird und ob der Eingangswert normal oder invertiert verwendet wird.
+Legt fest, ob der Eingang verwendet wird und ob der Eingangswert normal oder invertiert verwendet wird.
Die Eingangsnummer 1-9 entspricht gleichzeitig der Priorität, wobei 1 die höchste und 9 die niedrigste darstellt.
@@ -197,4 +250,87 @@ Das bedeutet das bei einer Vorbelegung von "AUS" und einer eingestellten Inverti
### Ausgangswert
Legt den Wert fest, der auf den Bus gesendet wird, wenn dieser Eingang der Eingang mit der höchsten Nummer ist der auf EIN gesetzt ist.
+
+
+
+## Aggregation
+
+
+### Funktion
+
+Legt fest, wie der Ausgangswert aus den Werten der aktiven Eingänge berechnet wird:
+
+- **Summe**
+ Addiert die Eingangswerte.
+ Das Ergebnis kann außerhalb des Eingangs-Wertebereichs liegen!
+- **Mittelwert**
+ Summe dividiert durch die Anzahl der aktiven Eingänge.
+ Das Ergebnis ist i.d.R. nicht ganzzahlig, wird jedoch innerhalb des Eingangs-Wertebereichs liegen.
+- **Minimum**
+ Verwendet den kleinsten Eingangswert.
+- **Maximum**
+ Verwendet den größten Eingangswert.
+- **Spannbreite (Maximum - Minimum)**
+ Liefert ein einfaches Maß dafür, wie weit sich die Eingangs-Werte voneinander unterscheiden.
+ Das Ergebnis kann außerhalb des Eingangs-Wertebereichs liegen, wenn vorzeichenbehaftet ist!
+
+
+### Gewichtung der Eingänge
+
+
+> Nur für *Summe* und *Mittelwert*
+
+**Individuelle Gewichte** erlaubt eine Berechnung bei der die Eingänge unterschiedlich stark in der Ergebnis einfließen.
+Dazu kann je aktivem Eingang ein individuelles Gewicht (Standardwert 1) angegeben werden.
+Mindestens ein Gewicht muss von 0 abweichen, sonst wird kein Ergebnis ausgegeben!
+
+
+
+### Wertetyp / DPT (Eingänge)
+
+Definiert den DPT der Eingänge. Zur Auswahl stehen gängige numerische DPTs mit 1Byte, 2Bytes und 4Bytes.
+
+
+### Eingang 1-9
+
+Legt fest, ob der Eingang verwendet wird.
+
+
+### Gewicht Eingang 1-9
+
+Definiert wie stark dieser Eingang in das Ergebnis einfließt.
+
+Bei 0 hat dieser Eingang keinen Einfluss auf das Resultat der Berechnung,
+wird aber verhindern dass ein Ergebnis entsteht so lange der Eingang noch keinen Wert hat,
+oder kann abhängig vom Sendeverhalten ein Senden auf de Bus auslösen.
+
+Ein negativer Wert ändert das Vorzeichen des Eingangswertes. Bei der Gewichtssumme fließt der Betrag ein.
+
+
+### Wertetyp / DPT (Ausgang)
+
+Definiert den DPT des Ausgangs. Zur Auswahl stehen gängige numerische DPTs mit 1Byte, 2Bytes und 4Bytes.
+
+In der Standardeinstellung **Identisch mit Eingängen** wird der DPT der Eingänge übernommen.
+
+
+### Rundungsmodus
+
+> *Nur* einstellbar, wenn ein Ganzzahl-Wertetyp für den Ausgang gewählt wurde und das berechnete Ergebnis nicht zwingend ganzzahlig ist.
+
+- **Nachkommastellen verwerfen**
+ Kein besondere Behandlung.
+- **Runden (ab 0,5 aufrufen)**
+ Anwendung der üblichen Rundungsregeln.
+
+
+### Bei Überschreiten des Wertebereichs
+
+> *Nur* relevant, wenn der berechnete Ausgangswert durch den gewählten Ausgangs-DPT nicht mehr in jedem Fall abbildbar ist.
+
+- **KO nicht aktualisieren / nicht senden**
+ Ignoriert den Wert.
+- **Auf Bereichsrand setzen**
+ Ein zu kleiner Wert wird durch den Minimalwert des DPT ersetzt, ein zu großer Wert durch den Maximalwert.
+
\ No newline at end of file
diff --git a/library.json b/library.json
index de7e416..700df18 100644
--- a/library.json
+++ b/library.json
@@ -1,9 +1,6 @@
{
"name": "OFM-FunctionBlocks",
- "version": "0.1.0",
- "dependencies": {
- "bblanchon/ArduinoJson": "^7.0.4"
- },
+ "version": "0.2.0-DEV",
"description": "Function Blocks",
"homepage": "https://openknx.de",
"authors": {
@@ -14,6 +11,6 @@
},
"repository": {
"type": "git",
- "url": "https://github.com/mgeramb/OFM-FunctionBlocks"
+ "url": "https://github.com/OpenKNX/OFM-FunctionBlocks"
}
}
\ No newline at end of file
diff --git a/src/Baggages/Help_de/FCB-AggrEingang.md b/src/Baggages/Help_de/FCB-AggrEingang.md
new file mode 100644
index 0000000..815a10b
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-AggrEingang.md
@@ -0,0 +1,4 @@
+### Eingang 1-9
+
+Legt fest, ob der Eingang verwendet wird.
+
diff --git a/src/Baggages/Help_de/FCB-AggrEingangGewicht.md b/src/Baggages/Help_de/FCB-AggrEingangGewicht.md
new file mode 100644
index 0000000..d2ab99e
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-AggrEingangGewicht.md
@@ -0,0 +1,10 @@
+### Gewicht Eingang 1-9
+
+Definiert wie stark dieser Eingang in das Ergebnis einfließt.
+
+Bei 0 hat dieser Eingang keinen Einfluss auf das Resultat der Berechnung,
+wird aber verhindern dass ein Ergebnis entsteht so lange der Eingang noch keinen Wert hat,
+oder kann abhängig vom Sendeverhalten ein Senden auf de Bus auslösen.
+
+Ein negativer Wert ändert das Vorzeichen des Eingangswertes. Bei der Gewichtssumme fließt der Betrag ein.
+
diff --git a/src/Baggages/Help_de/FCB-AggrFunction.md b/src/Baggages/Help_de/FCB-AggrFunction.md
new file mode 100644
index 0000000..c167438
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-AggrFunction.md
@@ -0,0 +1,18 @@
+### Funktion
+
+Legt fest, wie der Ausgangswert aus den Werten der aktiven Eingänge berechnet wird:
+
+- **Summe**
+ Addiert die Eingangswerte.
+ Das Ergebnis kann außerhalb des Eingangs-Wertebereichs liegen!
+- **Mittelwert**
+ Summe dividiert durch die Anzahl der aktiven Eingänge.
+ Das Ergebnis ist i.d.R. nicht ganzzahlig, wird jedoch innerhalb des Eingangs-Wertebereichs liegen.
+- **Minimum**
+ Verwendet den kleinsten Eingangswert.
+- **Maximum**
+ Verwendet den größten Eingangswert.
+- **Spannbreite (Maximum - Minimum)**
+ Liefert ein einfaches Maß dafür, wie weit sich die Eingangs-Werte voneinander unterscheiden.
+ Das Ergebnis kann außerhalb des Eingangs-Wertebereichs liegen, wenn vorzeichenbehaftet ist!
+
diff --git a/src/Baggages/Help_de/FCB-Anzahl.md b/src/Baggages/Help_de/FCB-Anzahl.md
new file mode 100644
index 0000000..4829fea
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-Anzahl.md
@@ -0,0 +1,6 @@
+### Anzahl
+
+Ein Anzahl-Funktionsblock verfügt über bis zu 9 Eingänge.
+Der Ausgang gibt aus, wie viele der (verwendeten) Eingänge den Wert EIN angenommen haben.
+Die Eingänge können vor Zählung invertiert werden.
+
diff --git a/src/Baggages/Help_de/FCB-Bezeichnung.md b/src/Baggages/Help_de/FCB-Bezeichnung.md
index f9c94f4..0f43919 100644
--- a/src/Baggages/Help_de/FCB-Bezeichnung.md
+++ b/src/Baggages/Help_de/FCB-Bezeichnung.md
@@ -1,5 +1,5 @@
### Bezeichnung
-Die Bezeichnung wird innerhalb der ETS für die Bennenung des Kanals und für die Bennenung der Funktionsblock Ein- und Ausgänge verwendet.
-Die Bezeichnung hat keinen Einfluss auf die Funktion des Funktionsblocks und kann jederzeit auch nachträglich angepasst werden.
+Die Bezeichnung wird innerhalb der ETS für die Benennung des Kanals und für die Benennung der Funktionsblock Ein- und Ausgänge verwendet.
+Die Bezeichnung hat keinen Einfluss auf das Verhalten des Funktionsblocks und kann jederzeit auch nachträglich angepasst werden.
diff --git a/src/Baggages/Help_de/FCB-DptAusgang.md b/src/Baggages/Help_de/FCB-DptAusgang.md
new file mode 100644
index 0000000..0b8d294
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-DptAusgang.md
@@ -0,0 +1,6 @@
+### Wertetyp / DPT (Ausgang)
+
+Definiert den DPT des Ausgangs. Zur Auswahl stehen gängige numerische DPTs mit 1Byte, 2Bytes und 4Bytes.
+
+In der Standardeinstellung **Identisch mit Eingängen** wird der DPT der Eingänge übernommen.
+
diff --git a/src/Baggages/Help_de/FCB-DptEingang.md b/src/Baggages/Help_de/FCB-DptEingang.md
new file mode 100644
index 0000000..730911b
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-DptEingang.md
@@ -0,0 +1,4 @@
+### Wertetyp / DPT (Eingänge)
+
+Definiert den DPT der Eingänge. Zur Auswahl stehen gängige numerische DPTs mit 1Byte, 2Bytes und 4Bytes.
+
diff --git a/src/Baggages/Help_de/FCB-Gewichtung-der-Eingaenge.md b/src/Baggages/Help_de/FCB-Gewichtung-der-Eingaenge.md
new file mode 100644
index 0000000..d4e6b84
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-Gewichtung-der-Eingaenge.md
@@ -0,0 +1,7 @@
+### Gewichtung der Eingänge
+
+**Individuelle Gewichte** erlaubt eine Berechnung bei der die Eingänge unterschiedlich stark in der Ergebnis einfließen.
+Dazu kann je aktivem Eingang ein individuelles Gewicht (Standardwert 1) angegeben werden.
+Mindestens ein Gewicht muss von 0 abweichen, sonst wird kein Ergebnis ausgegeben!
+
+
diff --git a/src/Baggages/Help_de/FCB-Kanalauswahl.md b/src/Baggages/Help_de/FCB-Kanalauswahl.md
index a21f3bd..8d25d31 100644
--- a/src/Baggages/Help_de/FCB-Kanalauswahl.md
+++ b/src/Baggages/Help_de/FCB-Kanalauswahl.md
@@ -2,17 +2,23 @@
Für jeden Kanal kann für einen Funktionsblock konfiguriert werden:
-#### UND
+- **UND**
+ Ein UND-Funktionsblock verfügt über bis zu 9 Eingänge.
+ Der Ausgang gibt EIN aus, wenn alle Eingänge EIN sind.
-Ein UND-Funktionsblock verfügt über bis zu 9 Eingänge.
-Der Ausgang gibt EIN aus, wenn alle Eingänge EIN sind.
+- **ODER**
+ Ein ODER-Funktionsblock verfügt über bis zu 9 Eingänge.
+ Der Ausgang gibt EIN aus, wenn mindestens ein Eingang EIN ist.
-#### ODER
+- **Prioritätsschalter**
+ Ein Prioritätsschalter hat bis zu 9 Eingänge vom Typ EIN/AUS.
+ Der Eingang mit der höchsten Priorität der EIN ist, bestimmt den Ausgangswert.
-Ein ODER-Funktionsblock verfügt über bis zu 9 Eingänge. Der Ausgang gibt EIN aus, wenn mindestens ein Eingang EIN ist.
+- **Anzahl**
+ Ein Anzahl-Funktionsblock hat bis zu 9 Eingänge vom Typ EIN/AUS.
+ Der Ausgang gibt die Anzahl der Eingänge mit dem Wert EIN aus.
-#### Prioritätsschalter
-
-Ein Prioritätsschalter hat bis zu 9 Eingänge vom Typ EIN/AUS.
-Der Eingang mit der höchsten Priorität der EIN ist, bestimmt den Ausgangswert.
+- **Statistische Aggregation**
+ Ein Aggregations-Funktionsblock hat bis zu 9 Eingänge mit numerischem Typ.
+ Es kann zwischen fünf Funktionen (Summe, Mittelwert, Minimum, Maximum, Spannbreite) zur Berechnung des Ausgangswertes gewählt werden.
diff --git a/src/Baggages/Help_de/FCB-Kommentar.md b/src/Baggages/Help_de/FCB-Kommentar.md
new file mode 100644
index 0000000..b6a2f9c
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-Kommentar.md
@@ -0,0 +1,10 @@
+### Kommentar
+
+Hier kann eine ausführlichere - auch mehrzeilige - Dokumention des Blocks erfolgen.
+Es wird empfohlen zentrale Annahmen die der Konfiguration des Blocks zugrunde liegen hier festzuhalten.
+Die Dokumentation hat keinen Einfluss auf das Geräteverhalten.
+
+Eine mehrzeilige Eingabe ist aufgrund von Beschränkungen der ETS nicht direkt möglich,
+kann jedoch durch Eingabe mit `\n` und Drücken des Buttons erzeugt werden.
+Anschließend kann der Text mehrzeilig bearbeitet werden.
+
diff --git a/src/Baggages/Help_de/FCB-LogicEingang.md b/src/Baggages/Help_de/FCB-LogicEingang.md
index 226f4d5..852fefe 100644
--- a/src/Baggages/Help_de/FCB-LogicEingang.md
+++ b/src/Baggages/Help_de/FCB-LogicEingang.md
@@ -1,4 +1,4 @@
### Eingang 1-9
-Legt fest ob der Eingang verwendet wird und ob der Eingangswert normal oder invertiert verwendet wird.
+Legt fest, ob der Eingang verwendet wird, und falls ja, ob der Eingangswert **normal** oder **invertiert** verwendet wird.
diff --git a/src/Baggages/Help_de/FCB-OutOfRange.md b/src/Baggages/Help_de/FCB-OutOfRange.md
new file mode 100644
index 0000000..12aa0c5
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-OutOfRange.md
@@ -0,0 +1,9 @@
+### Bei Überschreiten des Wertebereichs
+
+> *Nur* relevant, wenn der berechnete Ausgangswert durch den gewählten Ausgangs-DPT nicht mehr in jedem Fall abbildbar ist.
+
+- **KO nicht aktualisieren / nicht senden**
+ Ignoriert den Wert.
+- **Auf Bereichsrand setzen**
+ Ein zu kleiner Wert wird durch den Minimalwert des DPT ersetzt, ein zu großer Wert durch den Maximalwert.
+
diff --git a/src/Baggages/Help_de/FCB-PrioEingang.md b/src/Baggages/Help_de/FCB-PrioEingang.md
index d9d4137..3a591af 100644
--- a/src/Baggages/Help_de/FCB-PrioEingang.md
+++ b/src/Baggages/Help_de/FCB-PrioEingang.md
@@ -1,5 +1,5 @@
### Eingang 1-9
-Legt fest ob der Eingang verwendet wird und ob der Eingangswert normal oder invertiert verwendet wird.
+Legt fest, ob der Eingang verwendet wird und ob der Eingangswert normal oder invertiert verwendet wird.
Die Eingangsnummer 1-9 entspricht gleichzeitig der Priorität, wobei 1 die höchste und 9 die niedrigste darstellt.
diff --git a/src/Baggages/Help_de/FCB-Rundungsmodus.md b/src/Baggages/Help_de/FCB-Rundungsmodus.md
new file mode 100644
index 0000000..387a213
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-Rundungsmodus.md
@@ -0,0 +1,9 @@
+### Rundungsmodus
+
+> *Nur* einstellbar, wenn ein Ganzzahl-Wertetyp für den Ausgang gewählt wurde und das berechnete Ergebnis nicht zwingend ganzzahlig ist.
+
+- **Nachkommastellen verwerfen**
+ Kein besondere Behandlung.
+- **Runden (ab 0,5 aufrufen)**
+ Anwendung der üblichen Rundungsregeln.
+
diff --git a/src/Baggages/Help_de/FCB-Statistische-Aggregation.md b/src/Baggages/Help_de/FCB-Statistische-Aggregation.md
new file mode 100644
index 0000000..55d3c89
--- /dev/null
+++ b/src/Baggages/Help_de/FCB-Statistische-Aggregation.md
@@ -0,0 +1,6 @@
+### Statistische Aggregation
+
+Ein Aggregations-Funktionsblock verfügt über bis zu 9 numerische Eingänge, gängiger DPTs.
+Der Ausgangswert wird basierend auf der gewählten Funktion (Summe, Mittelwert, Minimum, Maximum, Spannbreite) berechnet und kann in verschiedenen numerischen DPTs ausgegeben werden.
+Es kann beeinflusst werden, wie mit Werten umgegangen wird die vom Ausgatyp nicht dargestellt werden können.
+
diff --git a/src/Baggages/Icons/LICENSE b/src/Baggages/Icons/LICENSE
new file mode 100644
index 0000000..758ebbe
--- /dev/null
+++ b/src/Baggages/Icons/LICENSE
@@ -0,0 +1,17 @@
+Icons with "openknx" in filename were designed individually for this project.
+
+Others were created as custom export from Pictogrammers Material Design Icons Collection:
+
+> Pictogrammers Free License
+> --------------------------
+>
+> Last Updated: February 1st, 2023
+>
+> This package is released as free, open-source, and GPL friendly by
+> the [Pictogrammers](https://pictogrammers.com/). You may use it
+> for commercial projects, open-source projects, or anything really.
+>
+> # Icons: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
+> Some of the icons are redistributed under the Apache 2.0 license. All other
+> icons are either redistributed under their respective licenses or are
+> distributed under the Apache 2.0 license.
diff --git a/src/Baggages/Icons/set-merge.png b/src/Baggages/Icons/set-merge.png
new file mode 100644
index 0000000..91df06f
Binary files /dev/null and b/src/Baggages/Icons/set-merge.png differ
diff --git a/src/Baggages/Icons/tally-mark-5.png b/src/Baggages/Icons/tally-mark-5.png
new file mode 100644
index 0000000..ad65969
Binary files /dev/null and b/src/Baggages/Icons/tally-mark-5.png differ
diff --git a/src/FunctionBlocks.share.xml b/src/FunctionBlocks.share.xml
index 47f36cf..3eb5ca0 100644
--- a/src/FunctionBlocks.share.xml
+++ b/src/FunctionBlocks.share.xml
@@ -11,12 +11,69 @@
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -59,6 +116,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/FunctionBlocks.templ.xml b/src/FunctionBlocks.templ.xml
index 5541eed..36a36ee 100644
--- a/src/FunctionBlocks.templ.xml
+++ b/src/FunctionBlocks.templ.xml
@@ -10,6 +10,7 @@
+
@@ -21,7 +22,7 @@
-
+
@@ -73,7 +74,6 @@
-
@@ -168,6 +168,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -176,6 +233,8 @@
+
+
@@ -254,7 +313,7 @@
-
+
@@ -299,76 +358,228 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
@@ -392,10 +603,8 @@
-
-
-
-
+
+
@@ -407,19 +616,23 @@
-
-
-
-
+
+
-
+
+
+
+
+
+
+
@@ -537,19 +750,23 @@
-
-
-
-
+
+
-
+
+
+
+
+
+
+
@@ -667,19 +884,159 @@
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -917,6 +1274,295 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/FunctionBlocks/LogicFunctionBlock.cpp b/src/FunctionBlocks/LogicFunctionBlock.cpp
index 626ac57..2006dc5 100644
--- a/src/FunctionBlocks/LogicFunctionBlock.cpp
+++ b/src/FunctionBlocks/LogicFunctionBlock.cpp
@@ -2,7 +2,7 @@
#include "knxprod.h"
LogicFunctionBlock::LogicFunctionBlock(uint8_t channelIndex, LogicFunctionBlockType type)
- : FunctionBlock(channelIndex, type == LogicFunctionBlockType::LogicOR ? "OR" : "AND"),
+ : FunctionBlock(channelIndex, type == LogicFunctionBlockType::LogicOR ? "OR" : (type == LogicFunctionBlockType::LogicAND ? "AND" : "COUNT")),
_type(type)
{
}
@@ -131,6 +131,7 @@ void LogicFunctionBlock::handleKo(GroupObject& ko)
{
// Recalc the output
bool result = (_type == LogicFunctionBlockType::LogicAND ? true : false);
+ uint8_t count = 0;
for (uint8_t i = 0; i < 9; i++)
{
//
@@ -146,9 +147,10 @@ void LogicFunctionBlock::handleKo(GroupObject& ko)
}
auto& ko = getKo(i);
- auto inputValue = (bool)ko.value(DPT_Switch);
+ bool inputValue = ko.value(DPT_Switch);
if (inputKo == 2)
inputValue = !inputValue;
+
if (_type == LogicFunctionBlockType::LogicAND)
{
if (!inputValue)
@@ -157,7 +159,7 @@ void LogicFunctionBlock::handleKo(GroupObject& ko)
break;
}
}
- else
+ else if (_type == LogicFunctionBlockType::LogicOR)
{
if (inputValue)
{
@@ -165,15 +167,35 @@ void LogicFunctionBlock::handleKo(GroupObject& ko)
break;
}
}
+ else
+ {
+ if (inputValue)
+ {
+ count++;
+ }
+ }
+ }
+
+ if (_type == LogicFunctionBlockType::LogicCOUNT)
+ {
+ //
+ //
+ if (ParamFCB_CHLogicBehavOut)
+ KoFCB_CHKO9.valueCompare(count, DPT_Value_1_Ucount);
+ else
+ KoFCB_CHKO9.value(count, DPT_Value_1_Ucount);
}
- if (ParamFCB_CHLogicOutInv)
- result = !result;
-
- //
- //
- if (ParamFCB_CHLogicBehavOut && KoFCB_CHKO9.initialized())
- KoFCB_CHKO9.valueCompare(result, DPT_Switch);
else
- KoFCB_CHKO9.value(result, DPT_Switch);
+ {
+ if (ParamFCB_CHLogicOutInv)
+ result = !result;
+
+ //
+ //
+ if (ParamFCB_CHLogicBehavOut)
+ KoFCB_CHKO9.valueCompare(result, DPT_Switch);
+ else
+ KoFCB_CHKO9.value(result, DPT_Switch);
+ }
}
}
\ No newline at end of file
diff --git a/src/FunctionBlocks/LogicFunctionBlock.h b/src/FunctionBlocks/LogicFunctionBlock.h
index 9fa78d0..cde6784 100644
--- a/src/FunctionBlocks/LogicFunctionBlock.h
+++ b/src/FunctionBlocks/LogicFunctionBlock.h
@@ -5,6 +5,7 @@ enum class LogicFunctionBlockType
{
LogicAND,
LogicOR,
+ LogicCOUNT,
};
class LogicFunctionBlock : public FunctionBlock
diff --git a/src/FunctionBlocks/SimpleAggregationBlock.cpp b/src/FunctionBlocks/SimpleAggregationBlock.cpp
new file mode 100644
index 0000000..96b3ed7
--- /dev/null
+++ b/src/FunctionBlocks/SimpleAggregationBlock.cpp
@@ -0,0 +1,352 @@
+#include "SimpleAggregationBlock.h"
+#include "knxprod.h"
+
+#define TYPE2Str(type) \
+ type == SimpleAggregationBlockType::AggrSUM ? "SUM" : type == SimpleAggregationBlockType::AggrAVG ? "AVG" \
+ : type == SimpleAggregationBlockType::AggrMIN ? "MIN" \
+ : type == SimpleAggregationBlockType::AggrMAX ? "MAX" \
+ : "Range"
+ /*
+ : type == SimpleAggregationBlockType::AggrWidth ? "Width" \
+ : type == SimpleAggregationBlockType::AggrMedian ? "Median" \
+ : type == SimpleAggregationBlockType::AggrQ25 ? "Q25" \
+ : type == SimpleAggregationBlockType::AggrQ75 ? "Q75" \
+ : "STD"
+ */
+
+#define FCB_LIMIT(t, x, min, max) \
+ if (((t)(x)) < ((t)(min))) \
+ x = ((t)(min)); \
+ else if (((t)(x)) > ((t)(max))) \
+ x = ((t)(max));
+
+SimpleAggregationBlock::SimpleAggregationBlock(uint8_t channelIndex, SimpleAggregationBlockType type)
+ : FunctionBlock(channelIndex, TYPE2Str(type)),
+ _type(type)
+{
+}
+
+uint8_t SimpleAggregationBlock::getParamInput(uint8_t input)
+{
+ logDebugP("getParamInput(%d)", input);
+ switch (input)
+ {
+ case 0:
+ return ParamFCB_CHAggKo0D;
+ case 1:
+ return ParamFCB_CHAggKo1D;
+ case 2:
+ return ParamFCB_CHAggKo2D;
+ case 3:
+ return ParamFCB_CHAggKo3D;
+ case 4:
+ return ParamFCB_CHAggKo4D;
+ case 5:
+ return ParamFCB_CHAggKo5D;
+ case 6:
+ return ParamFCB_CHAggKo6D;
+ case 7:
+ return ParamFCB_CHAggKo7D;
+ case 8:
+ return ParamFCB_CHAggKo8D;
+ default:
+ openknx.hardware.fatalError(FATAL_SYSTEM, "Invalid input");
+ return 0;
+ }
+}
+
+int8_t SimpleAggregationBlock::getParamInputWeight(uint8_t input)
+{
+ if (ParamFCB_CHAggWeight == 0)
+ {
+ // no individual weight
+ return 1;
+ }
+ switch (input)
+ {
+ case 0:
+ return ParamFCB_CHAggKo0W;
+ case 1:
+ return ParamFCB_CHAggKo1W;
+ case 2:
+ return ParamFCB_CHAggKo2W;
+ case 3:
+ return ParamFCB_CHAggKo3W;
+ case 4:
+ return ParamFCB_CHAggKo4W;
+ case 5:
+ return ParamFCB_CHAggKo5W;
+ case 6:
+ return ParamFCB_CHAggKo6W;
+ case 7:
+ return ParamFCB_CHAggKo7W;
+ case 8:
+ return ParamFCB_CHAggKo8W;
+ default:
+ openknx.hardware.fatalError(FATAL_SYSTEM, "Invalid input");
+ return 0;
+ }
+}
+
+void SimpleAggregationBlock::readInputKos()
+{
+/*
+ for (uint8_t i = 0; i < 9; i++)
+ {
+ //
+ //
+ //
+ auto inputKo = getParamInput(i);
+ if (inputKo == 0)
+ continue;
+
+ auto& ko = getKo(i);
+ //
+ //
+ //
+ //
+ auto inputBehavior = getParamInputBehavior(i);
+ switch (inputBehavior)
+ {
+ case 0:
+ ko.value(false, DPT_Switch);
+ break;
+ case 1:
+ ko.value(true, DPT_Switch);
+ break;
+ case 2:
+ case 3:
+ ko.requestObjectRead();
+ break;
+ }
+ }
+*/
+}
+
+void SimpleAggregationBlock::initMissingInputValues()
+{
+/*
+ for (uint8_t i = 0; i < 9; i++)
+ {
+ //
+ //
+ //
+ auto inputKo = getParamInput(i);
+ if (inputKo == 0)
+ continue;
+
+ if (!hasValue(i))
+ {
+ auto& ko = getKo(i);
+ auto inputBehavior = getParamInputBehavior(i);
+ switch (inputBehavior)
+ {
+ case 2:
+ ko.value(false, DPT_Switch);
+ break;
+ case 3:
+ ko.value(true, DPT_Switch);
+ break;
+ }
+ }
+ }
+*/
+}
+
+Dpt SimpleAggregationBlock::_dptType(uint8_t typeParamValue)
+{
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ Dpt dptInput;
+ switch (typeParamValue)
+ {
+ case 50:
+ dptInput = DPT_Value_1_Ucount;
+ break;
+ case 51:
+ dptInput = DPT_Scaling;
+ break;
+ case 61:
+ dptInput = DPT_Value_1_Count;
+ break;
+ case 70:
+ dptInput = DPT_Value_2_Ucount;
+ break;
+ case 80:
+ dptInput = DPT_Value_2_Count;
+ break;
+ case 90:
+ dptInput = DPT_Value_Temp;
+ break;
+ case 120:
+ dptInput = DPT_Value_4_Ucount;
+ break;
+ case 130:
+ dptInput = DPT_Value_4_Count;
+ break;
+ case 140:
+ dptInput = DPT_Value_Amplitude;
+ break;
+ default:
+ dptInput = DPT_Switch;
+ break;
+ }
+ return dptInput;
+}
+
+void SimpleAggregationBlock::handleKo(GroupObject& ko)
+{
+ auto index = FCB_KoCalcIndex(ko.asap());
+ if (index >= FCB_KoCHKO0 && index <= FCB_KoCHKO8)
+ {
+ logDebugP("handleKo: %d; %d; %d", index, ParamFCB_CHAggInputDpt, ParamFCB_CHAggOutputDptEff);
+ _update();
+ }
+}
+
+void SimpleAggregationBlock::_update()
+{
+ const Dpt dptInput = _dptType(ParamFCB_CHAggInputDpt);
+
+ // Recalc the output
+ double min = std::numeric_limits::max();
+ double max = std::numeric_limits::min();
+ double sum = 0.0;
+ int16_t absWeightSum = 0.0;
+ uint8_t count = 0;
+ for (uint8_t i = 0; i < 9; i++)
+ {
+ //
+ //
+ if (getParamInput(i) == 0)
+ {
+ continue;
+ }
+
+ if (!hasValue(i))
+ {
+ // TODO handling of incomplete input values; current implementation requires all
+ logDebugP(" input(%d) NOT has value", i);
+ return;
+ }
+
+ const int8_t inputWeight = getParamInputWeight(i);
+ const double inputValue = getKo(i).value(dptInput);
+ min = MIN(min, inputValue);
+ max = MAX(max, inputValue);
+ sum += inputValue * inputWeight;
+ absWeightSum += abs(inputWeight);
+ count++;
+ }
+
+ logDebugP(" count %d", count);
+ if (count == 0)
+ {
+ return;
+ }
+
+ KNXValue result = 0.0;
+ switch (_type)
+ {
+ case SimpleAggregationBlockType::AggrSUM:
+ result = sum;
+ break;
+ case SimpleAggregationBlockType::AggrAVG:
+ result = sum / absWeightSum;
+ break;
+ case SimpleAggregationBlockType::AggrMIN:
+ result = min;
+ break;
+ case SimpleAggregationBlockType::AggrMAX:
+ result = max;
+ break;
+ case SimpleAggregationBlockType::AggrWidth:
+ result = max - min;
+ break;
+ default:
+ break;
+ }
+ _updateOutput(result);
+}
+
+void SimpleAggregationBlock::_updateOutput(KNXValue& result)
+{
+ logDebugP(" result %f (of type %d)", result, _type);
+
+ const Dpt dptOutput = _dptType(ParamFCB_CHAggOutputDptEff);
+
+ // rounding for integer outputs
+ if ((dptOutput.mainGroup != 9) && (dptOutput.mainGroup != 14))
+ {
+ if (ParamFCB_CHAggOutputRounding)
+ {
+ result = (int64_t)round((double)result);
+ }
+ else
+ {
+ // integer output
+ result = (int64_t)result;
+ }
+ }
+
+ if (ParamFCB_CHAggOutputOverflow == 1)
+ {
+ _limitToOutputDptRange(result);
+ }
+
+ //
+ //
+ if (ParamFCB_CHAggBehavOut)
+ {
+ KoFCB_CHKO9.valueCompare(result, dptOutput);
+ }
+ else
+ {
+ KoFCB_CHKO9.value(result, dptOutput);
+ }
+}
+
+void SimpleAggregationBlock::_limitToOutputDptRange(KNXValue& result)
+{
+ switch (ParamFCB_CHAggOutputDptEff)
+ {
+ case 50:
+ FCB_LIMIT(int64_t, result, 0, 255)
+ break;
+ case 51:
+ FCB_LIMIT(int64_t, result, 0, 100)
+ break;
+ case 61:
+ FCB_LIMIT(int64_t, result, -128, 128)
+ break;
+ case 70:
+ FCB_LIMIT(int64_t, result, 0, 65535)
+ break;
+ case 80:
+ FCB_LIMIT(int64_t, result, -32768, 32767)
+ break;
+ case 90:
+ // limit as defined in dptconvert
+ FCB_LIMIT(double, result, -671088.64, 670433.28)
+ break;
+ case 120:
+ FCB_LIMIT(int64_t, result, 0 ,4294967295)
+ break;
+ case 130:
+ FCB_LIMIT(int64_t, result, -2147483648, 2147483647)
+ break;
+ case 140:
+ // limit as defined in dptconvert
+ FCB_LIMIT(double, result, (-8388608.0 * pow(2, 255)), (8388607.0 * pow(2, 255)))
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/FunctionBlocks/SimpleAggregationBlock.h b/src/FunctionBlocks/SimpleAggregationBlock.h
new file mode 100644
index 0000000..b9f50e5
--- /dev/null
+++ b/src/FunctionBlocks/SimpleAggregationBlock.h
@@ -0,0 +1,40 @@
+#pragma once
+#include "FunctionBlock.h"
+
+enum class SimpleAggregationBlockType
+{
+ AggrSUM,
+ AggrAVG,
+ AggrMIN,
+ AggrMAX,
+ AggrWidth,
+ /*
+ AggrMedian,
+ AggrQ25,
+ AggrQ75,
+ AggrSTD,
+ */
+};
+
+class SimpleAggregationBlock : public FunctionBlock
+{
+ private:
+ const SimpleAggregationBlockType _type;
+ uint8_t getParamInput(uint8_t input);
+ int8_t getParamInputWeight(uint8_t input);
+
+ Dpt _dptType(uint8_t typeParamValue);
+ void _update();
+ void _updateOutput(KNXValue& result);
+ void _limitToOutputDptRange(KNXValue& result);
+
+ public:
+ SimpleAggregationBlock(uint8_t channelIndex, SimpleAggregationBlockType type);
+
+ // TODO remove here
+ void readInputKos() override;
+ // TODO remove here
+ void initMissingInputValues() override;
+
+ void handleKo(GroupObject &ko) override;
+};
\ No newline at end of file
diff --git a/src/FunctionBlocksModule.cpp b/src/FunctionBlocksModule.cpp
index 95a7358..dda7425 100644
--- a/src/FunctionBlocksModule.cpp
+++ b/src/FunctionBlocksModule.cpp
@@ -2,6 +2,7 @@
#include "knxprod.h"
#include "FunctionBlocks/LogicFunctionBlock.h"
#include "FunctionBlocks/PrioritySwitchFunctionBlock.h"
+#include "FunctionBlocks/SimpleAggregationBlock.h"
FunctionBlocksModule::FunctionBlocksModule()
{
@@ -49,27 +50,31 @@ OpenKNX::Channel* FunctionBlocksModule::createChannel(uint8_t _channelIndex)
logDebugP("Channel %d is disabled", _channelIndex);
return nullptr;
}
- //
- //
- //
- //
+ //
+ //
+ //
+ //
+ //
+ //
switch (ParamFCB_CHChannelType)
{
- case 0:
- logDebugP("Channel %d is deactivated", _channelIndex);
- return nullptr;
- case 1:
- return new LogicFunctionBlock(_channelIndex, LogicFunctionBlockType::LogicAND);
- break;
- case 2:
- return new LogicFunctionBlock(_channelIndex, LogicFunctionBlockType::LogicOR);
- break;
- case 3:
- return new PrioritySwitchFunctionBlock(_channelIndex);
- break;
+ case 0:
+ logDebugP("Channel %d is deactivated", _channelIndex);
+ return nullptr;
+ case 1:
+ return new LogicFunctionBlock(_channelIndex, LogicFunctionBlockType::LogicAND);
+ case 2:
+ return new LogicFunctionBlock(_channelIndex, LogicFunctionBlockType::LogicOR);
+ case 4:
+ return new LogicFunctionBlock(_channelIndex, LogicFunctionBlockType::LogicCOUNT);
+ case 3:
+ return new PrioritySwitchFunctionBlock(_channelIndex);
+ case 5:
+ return new SimpleAggregationBlock(_channelIndex, static_cast(ParamFCB_CHAggType));
+ default:
+ logErrorP("Unknown channel type %d", ParamFCB_CHChannelType);
+ return nullptr;
}
- logErrorP("Unknown channel type %d", ParamFCB_CHChannelType);
- return nullptr;
}
void FunctionBlocksModule::loop()