Hallo zusammen,
gleich vorweg: ich habe das bis jetzt noch nicht produktiv getestet, aber der erzeugte Code wird zumindest fehlerfrei kompiliert.
Ich wollte es so früh wie möglich vorstellen, um Feedback zu Fehlern oder gewünschten Ergänzungen zu bekommen.
Ich habe eine Tabelle in LibreOffice erstellt, welche den Inhalt für das XML erzeugt. Das XML übergibt man an ein Powershell-Skript, welches ein komplettes Code-Gerüst erzeugt.
Konnekting Template Generator 005.ods - LibreOffice Calc.png
Zuerst setzt man auf dem Tab "Manufacturer&Device" die gwünschten Werte. Danach den Rest in "Parameters". Die Struktur entspricht weitgehend dem XML.
In der Tabelle gibt es zusätzliche Einträge, welche vom Skript benötigt werden.
Zur Demonstartion habe ich die Tabelle mit den Werten für das Beispiel "DemoSensor_Temp_RH.ino" gefüllt. In Spalte N steht das XML. Die Spalte markieren und den Inhalt per Copy&Paste in einen beliebigen Texteditor packen und als "*.xml" speichern. NICHT als ".kdevice.xml".
Wegen der zusätzlichen Einträge kann die erzeugte Datei noch nicht mit der Suite geöffnet werden (auch nach Anpassung der XSD im .jar nicht. XML Notepad gibt mit der XSD keine Fehler mehr aus).
Die zusätzlichen Einträge:
Das Skript "create-KonnektingCode.ps1" erwartet den Namen der XML-Datei als Parameter:
Es speichert ohne Nachfrage zwei Dateien. Das Code-Gerüst als "<name>.ino" und eine bereinigte Version als "<name>.kdevice.xml", welche mit der Suite geöffnet werden kann.
Das vollständige Code-Gerüst:
IMHO spart man eine ganze Menge lästiger und fehleranfälliger Tipperei damit. Jetzt muß sich nur noch zeigen, ob es sich in der Praxis bewährt.
Bei knxEvents() inkrementiere ich den Index um 1, um ihn den Indexen der definierten ComObjekte anzupassen.
Das Powershell-Skript lädt die Datei "Konnekting_Code_Skeleton.ino" ein und ersetzt bestimmte Schlüsselwörter durch neuen Text (z.B. "[KNXComObjects]", "[ParamSizeList]").
Die Datei kann jeder für sich ändern, wenn er andere Vorlieben hat.
Das Skript muß vorher noch umbenannt werden.
Um das Powershell-Skript starten zu können, muß man die Execution Policy ändern.
Entweder dauerhaft durch: Set-ExecutionPolicy Unrestricted
oder nur für die aktuelle PS-Session: Set-ExecutionPolicy Unrestricted -Scope Process
KonnektingCodeSkeleton.zip
Todos:
gleich vorweg: ich habe das bis jetzt noch nicht produktiv getestet, aber der erzeugte Code wird zumindest fehlerfrei kompiliert.
Ich wollte es so früh wie möglich vorstellen, um Feedback zu Fehlern oder gewünschten Ergänzungen zu bekommen.
Ich habe eine Tabelle in LibreOffice erstellt, welche den Inhalt für das XML erzeugt. Das XML übergibt man an ein Powershell-Skript, welches ein komplettes Code-Gerüst erzeugt.
Konnekting Template Generator 005.ods - LibreOffice Calc.png
Zuerst setzt man auf dem Tab "Manufacturer&Device" die gwünschten Werte. Danach den Rest in "Parameters". Die Struktur entspricht weitgehend dem XML.
In der Tabelle gibt es zusätzliche Einträge, welche vom Skript benötigt werden.
Zur Demonstartion habe ich die Tabelle mit den Werten für das Beispiel "DemoSensor_Temp_RH.ino" gefüllt. In Spalte N steht das XML. Die Spalte markieren und den Inhalt per Copy&Paste in einen beliebigen Texteditor packen und als "*.xml" speichern. NICHT als ".kdevice.xml".
Wegen der zusätzlichen Einträge kann die erzeugte Datei noch nicht mit der Suite geöffnet werden (auch nach Anpassung der XSD im .jar nicht. XML Notepad gibt mit der XSD keine Fehler mehr aus).
Die zusätzlichen Einträge:
- VarName: der im Skript zu nutzende Variablenname. Im Code-Gerüst wird sowas daraus:
typeTemp = Tools.getUINT8Param(1); // Aktualisierung senden - CO_Name: Name für das ComObject. Es werden #define mit dem Namen und dem korrekten Index erzeugt.
Alt: limitReached(currentTemp, limitTempMin, limitTempMax, 2, 3, valueTempMin, valueTempMax);
Neu:
#define CO_limitTempMin 2
#define CO_limitTempMax 3
limitReached(currentTemp, limitTempMin, limitTempMax, CO_limitTempMin, CO_limitTempMax, valueTempMin, valueTempMax);
oder:
KNX.write(CO_limitTempMin ,1) - ObjectType: wird für die _comObjectsList benötigt:
KnxComObject(KNX_DPT_9_001 , COM_OBJ_SENSOR ),
Das Skript "create-KonnektingCode.ps1" erwartet den Namen der XML-Datei als Parameter:
Code:
PS D:\PowerShell\PowerShellSkripte\KNX\Konnekting> .\create-KonnektingCode.ps1 .\DemoSensor_Temp_RH.xml ManufacturerName : DemoManufacturer ManufacturerId : 57005 DeviceName : DemoDevice DeviceId : 255 Revision : 255 Groups Group: Allgemein Paramters 0 Geräteanlaufzeit [0..255sek] Group: Temperatur Paramters 1 Aktualisierung senden 2 Zyklus [s] 3 Temperaturänderung 4 Wert senden bei der Unterschreitung 5 Untere Grenze [°] 6 Wert senden bei der Überschreitung 7 Obere Grenze [°] Group: Relative Luftfeuchtigkeit Paramters 8 Aktualisierung senden 9 Zyklus [s] 10 Luftfeuchtigkeitsänderung 11 Wert senden bei der Unterschreitung 12 Untere Grenze [%] 13 Wert senden bei der Überschreitung 14 Obere Grenze [%] CommObjects 0 Temperatur 1 Temperatur 2 Temperatur 3 Relative Luftfeuchtigkeit 4 Relative Luftfeuchtigkeit 5 Relative Luftfeuchtigkeit
Das vollständige Code-Gerüst:
PHP-Code:
// comment following line to disable DEBUG mode
#define DEBUG debugSerial
// no need to comment, you can leave it as it is as long you do not change the "#define DEBUG debugSerial" line
#ifdef DEBUG
#include <SoftwareSerial.h>
SoftwareSerial debugSerial(10, 11); // RX, TX
#endif
// include KnxDevice library
#include <KnxDevice.h>
// defaults to on-board LED for AVR Arduinos
#define PROG_LED_PIN 8
// define programming-button PIN
#define PROG_BUTTON_PIN 3
// Define KONNEKTING Device related IDs
#define MANUFACTURER DemoManufacturer
#define DEVICENAME DemoDevice
#define MANUFACTURER_ID 57005
#define DEVICE_ID 255
#define REVISION 255
#define CO_currentTemp 1
#define CO_limitTempMin 2
#define CO_limitTempMax 3
#define CO_currentHumd 4
#define CO_limitHumdMin 5
#define CO_limitHumdMax 6
// define KNX Transceiver serial port
#ifdef __AVR_ATmega328P__
#define KNX_SERIAL Serial // Nano/ProMini etc. use Serial
#else
#define KNX_SERIAL Serial1 // Leonardo/Micro etc. use Serial1
#endif
// Definition of the Communication Objects attached to the device
KnxComObject KnxDevice::_comObjectsList[] = {
/* don't change this */ Tools.createProgComObject(),
// Currently, Sketch Index and Suite Index differ for ComObjects :-(
KnxComObject(KNX_DPT_9_001 , COM_OBJ_SENSOR ), // Sketch-Index 1, Suite-Index 0
KnxComObject(KNX_DPT_1_001 , COM_OBJ_SENSOR ), // Sketch-Index 2, Suite-Index 1
KnxComObject(KNX_DPT_1_001 , COM_OBJ_SENSOR ), // Sketch-Index 3, Suite-Index 2
KnxComObject(KNX_DPT_9_007 , COM_OBJ_SENSOR ), // Sketch-Index 4, Suite-Index 3
KnxComObject(KNX_DPT_1_001 , COM_OBJ_SENSOR ), // Sketch-Index 5, Suite-Index 4
KnxComObject(KNX_DPT_1_001 , COM_OBJ_SENSOR ), // Sketch-Index 6, Suite-Index 5
};
const byte KnxDevice::_numberOfComObjects = sizeof (_comObjectsList) / sizeof (KnxComObject); // do no change this code
// Definition of parameter size
byte KnxTools::_paramSizeList[] = {
// For params, the index in Sketch and Suite is equal
// Group: Allgemein
PARAM_UINT8 , // Param Index 0 - Geräteanlaufzeit [0..255sek]
// Group: Temperatur
PARAM_UINT8 , // Param Index 1 - Aktualisierung senden
PARAM_UINT32 , // Param Index 2 - Zyklus [s]
PARAM_UINT8 , // Param Index 3 - Temperaturänderung
PARAM_UINT8 , // Param Index 4 - Wert senden bei der Unterschreitung
PARAM_INT16 , // Param Index 5 - Untere Grenze [°]
PARAM_UINT8 , // Param Index 6 - Wert senden bei der Überschreitung
PARAM_INT16 , // Param Index 7 - Obere Grenze [°]
// Group: Relative Luftfeuchtigkeit
PARAM_UINT8 , // Param Index 8 - Aktualisierung senden
PARAM_UINT32 , // Param Index 9 - Zyklus [s]
PARAM_UINT8 , // Param Index 10 - Luftfeuchtigkeitsänderung
PARAM_UINT8 , // Param Index 11 - Wert senden bei der Unterschreitung
PARAM_INT16 , // Param Index 12 - Untere Grenze [%]
PARAM_UINT8 , // Param Index 13 - Wert senden bei der Überschreitung
PARAM_INT16 , // Param Index 14 - Obere Grenze [%]
};
const byte KnxTools::_numberOfParams = sizeof (_paramSizeList); // do no change this code
// Group: Allgemein
uint8_t startDelay;
// Group: Temperatur
uint8_t typeTemp;
uint32_t intervalTempUser;
uint8_t diffTempUser;
uint8_t valueTempMin;
int16_t limitTempMin;
uint8_t valueTempMax;
int16_t limitTempMax;
// Group: Relative Luftfeuchtigkeit
uint8_t typeHumd;
uint32_t intervalHumdUser;
uint8_t diffHumdUser;
uint8_t valueHumdMin;
int16_t limitHumdMin;
uint8_t valueHumdMax;
int16_t limitHumdMax;
// Callback function to handle com objects updates
void knxEvents(byte index) {
index++ ;
switch (index) {
case CO_currentTemp : // we arrive here when object index 0 has been updated
// code to treat index 0 object update
break;
case CO_limitTempMin : // we arrive here when object index 1 has been updated
// code to treat index 0 object update
break;
case CO_limitTempMax : // we arrive here when object index 2 has been updated
// code to treat index 0 object update
break;
case CO_currentHumd : // we arrive here when object index 3 has been updated
// code to treat index 0 object update
break;
case CO_limitHumdMin : // we arrive here when object index 4 has been updated
// code to treat index 0 object update
break;
case CO_limitHumdMax : // we arrive here when object index 5 has been updated
// code to treat index 0 object update
break;
default:
// code to treat remaining objects updates
break;
}
};
void setup() {
// if debug mode is enabled, setup serial port with 9600 baud
#ifdef DEBUG
DEBUG.begin(9600);
#endif
// Initialize KNX enabled Arduino Board
Tools.init(KNX_SERIAL, PROG_BUTTON_PIN, PROG_LED_PIN, MANUFACTURER_ID, DEVICE_ID, REVISION);
#ifdef DEBUG
DEBUG.println("Start");
#endif
// Group: Allgemein
startDelay = Tools.getUINT8Param(0); // Geräteanlaufzeit [0..255sek]
// Group: Temperatur
typeTemp = Tools.getUINT8Param(1); // Aktualisierung senden
intervalTempUser = Tools.getUINT32Param(2); // Zyklus [s]
diffTempUser = Tools.getUINT8Param(3); // Temperaturänderung
valueTempMin = Tools.getUINT8Param(4); // Wert senden bei der Unterschreitung
limitTempMin = Tools.getINT16Param(5); // Untere Grenze [°]
valueTempMax = Tools.getUINT8Param(6); // Wert senden bei der Überschreitung
limitTempMax = Tools.getINT16Param(7); // Obere Grenze [°]
// Group: Relative Luftfeuchtigkeit
typeHumd = Tools.getUINT8Param(8); // Aktualisierung senden
intervalHumdUser = Tools.getUINT32Param(9); // Zyklus [s]
diffHumdUser = Tools.getUINT8Param(10); // Luftfeuchtigkeitsänderung
valueHumdMin = Tools.getUINT8Param(11); // Wert senden bei der Unterschreitung
limitHumdMin = Tools.getINT16Param(12); // Untere Grenze [%]
valueHumdMax = Tools.getUINT8Param(13); // Wert senden bei der Überschreitung
limitHumdMax = Tools.getINT16Param(14); // Obere Grenze [%]
}
void loop() {
Knx.task();
// only do measurements and other sketch related stuff if not in programming mode
if (!Tools.getProgState()) {
}
}
Bei knxEvents() inkrementiere ich den Index um 1, um ihn den Indexen der definierten ComObjekte anzupassen.
Das Powershell-Skript lädt die Datei "Konnekting_Code_Skeleton.ino" ein und ersetzt bestimmte Schlüsselwörter durch neuen Text (z.B. "[KNXComObjects]", "[ParamSizeList]").
Die Datei kann jeder für sich ändern, wenn er andere Vorlieben hat.
Das Skript muß vorher noch umbenannt werden.
Um das Powershell-Skript starten zu können, muß man die Execution Policy ändern.
Entweder dauerhaft durch: Set-ExecutionPolicy Unrestricted
oder nur für die aktuelle PS-Session: Set-ExecutionPolicy Unrestricted -Scope Process
KonnektingCodeSkeleton.zip
Todos:
- Mehr Prüfungen für die XML-Datei. Bis jetzt wird nur geprüft, ob die IDs bei 0 beginnen und jeweils um 1 größer werden. Im Fehlerfall werden keine Dateien gespeichert
- MIN/MAX auf HEX und gerade Anzahl Zeichen prüfen
- MIN<=Default<=MAX
- einen Schönheitsfehler habe ich gerade gesehen. Bei KnxEvents() steht überall eine 0: "// code to treat index 0 object update". Ändere ich und lade dann später eine neue Version hoch.
Kommentar