added alternative GroupObject with less mangagement footprint (#125)

* corrected float with DPT9

* Switch Programming-LED also via Bus/ETS

* Again: Prog-LED switchable from bus/ETS

* DPT16 (to bus) implemented

* - added SMALL_GROUPOBJECT

* - added knx-demo-small-go example
- added config.h option (commented)
- changed platformio-ci.ini with -DSMALL_GROUPOBJECT
- changed plantformio.ini with tested -DSMALL_GROUPOBJECT

* - removed duplicate files

Co-authored-by: Waldemar Porscha <waldemar@porscha.eu>
Co-authored-by: Waldemar Porscha <waldemar.porscha@sap.com>
This commit is contained in:
mumpf 2021-02-18 09:40:35 +01:00 committed by GitHub
parent 21a05ae9b3
commit 164bf59166
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 332 additions and 25 deletions

View File

@ -0,0 +1,129 @@
#include <knx.h>
#ifdef ARDUINO_ARCH_ESP8266
#include <WiFiManager.h>
#endif
/*****************************************
* changes necessary for SMALL_GROUPOBJECT
* are commented with //**
* This project can be used with any
* of the knxprod files of the original
* knx-demo project.
*****************************************/
// create named references for easy access to group objects
#define goCurrent knx.getGroupObject(1)
#define goMax knx.getGroupObject(2)
#define goMin knx.getGroupObject(3)
#define goReset knx.getGroupObject(4)
float currentValue = 0;
float maxValue = 0;
float minValue = RAND_MAX;
long lastsend = 0;
void measureTemp()
{
long now = millis();
if ((now - lastsend) < 2000)
return;
lastsend = now;
int r = rand();
currentValue = (r * 1.0) / (RAND_MAX * 1.0);
currentValue *= 100 * 100;
// write new value to groupobject
goCurrent.value(currentValue, DPT_Value_Temp); //** each value access needs to done with according DPT parameter
if (currentValue > maxValue)
{
maxValue = currentValue;
goMax.value(maxValue, DPT_Value_Temp); //** each value access needs to done with according DPT parameter
}
if (currentValue < minValue)
{
minValue = currentValue;
goMin.value(minValue, DPT_Value_Temp); //** each value access needs to done with according DPT parameter
}
}
// callback from reset-GO
void resetCallback(GroupObject& go)
{
//** callbacks are now handled in the class, not per instance,
//** this means, we have to check, which GroupObject is calling back
if (go.asap() == goReset.asap())
{
if (go.value(DPT_Trigger)) //** each value access needs to done with according DPT parameter
{
maxValue = 0;
minValue = 10000;
}
}
}
void setup()
{
Serial.begin(115200);
ArduinoPlatform::SerialDebug = &Serial;
randomSeed(millis());
#ifdef ARDUINO_ARCH_ESP8266
WiFiManager wifiManager;
wifiManager.autoConnect("knx-demo");
#endif
// read adress table, association table, groupobject table and parameters from eeprom
knx.readMemory();
// print values of parameters if device is already configured
if (knx.configured())
{
// register callback for reset GO
GroupObject::classCallback(resetCallback); //** callbacks are now handled per class, not per instance
//** there is no global assignment of DPT for GroupObjects
// goReset.dataPointType(DPT_Trigger);
// goCurrent.dataPointType(DPT_Value_Temp);
// goMin.dataPointType(DPT_Value_Temp);
// goMax.dataPointType(DPT_Value_Temp);
Serial.print("Timeout: ");
Serial.println(knx.paramByte(0));
Serial.print("Zykl. senden: ");
Serial.println(knx.paramByte(1));
Serial.print("Min/Max senden: ");
Serial.println(knx.paramByte(2));
Serial.print("Aenderung senden: ");
Serial.println(knx.paramByte(3));
Serial.print("Abgleich: ");
Serial.println(knx.paramByte(4));
}
// pin or GPIO the programming led is connected to. Default is LED_BUILTIN
// knx.ledPin(LED_BUILTIN);
// is the led active on HIGH or low? Default is LOW
// knx.ledPinActiveOn(HIGH);
// pin or GPIO programming button is connected to. Default is 0
// knx.buttonPin(0);
// Is the interrup created in RISING or FALLING signal? Default is RISING
// knx.buttonPinInterruptOn(FALLING);
// start the framework.
knx.start();
}
void loop()
{
// don't delay here to much. Otherwise you might lose packages or mess up the timing with ETS
knx.loop();
// only run the application code if the device was configured with ETS
if (!knx.configured())
return;
measureTemp();
}

View File

@ -0,0 +1,120 @@
;PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[platformio]
; We have to keep libdeps dir out the project directory otherwise,
; library scanner seems to have issues so compilation fails
libdeps_dir = /tmp/libdeps
src_dir = .
;--- SAMD --------------------------------------------------
; SMALL_GROUPOBJECT just tested with TP on SAMD, but should work also in other environments
[env:zeroUSB]
platform = atmelsam
board = zeroUSB
framework = arduino
; We consider that the this projects is opened within its project directory
; while working with VS Code.
lib_extra_dirs = ../../../
lib_deps =
SPI
https://github.com/thelsing/FlashStorage.git
knx
build_flags =
-DMASK_VERSION=0x07B0
-DSMALL_GROUPOBJECT
-Wno-unknown-pragmas
; [env:adafruit_feather_m0_rf]
; platform = atmelsam
; board = adafruit_feather_m0
; framework = arduino
; ; We consider that the this projects is opened within its project directory
; ; while working with VS Code.
; lib_extra_dirs = ../../../
; lib_deps =
; SPI
; https://github.com/thelsing/FlashStorage.git
; knx
; build_flags =
; -DMASK_VERSION=0x27B0
; -Wno-unknown-pragmas
;-----------------------------------------------------------
;--- ESP8266 -----------------------------------------------
#[env:nodemcuv2_ip]
#platform = espressif8266
#board = nodemcuv2
#framework = arduino
; We consider that the this projects is opened within its project directory
; while working with VS Code.
#lib_extra_dirs = ../../../
#lib_deps =
# WifiManager
# knx
#build_flags =
# -DMASK_VERSION=0x57B0
# -Wno-unknown-pragmas
; [env:nodemcuv2_tp]
; platform = espressif8266
; board = nodemcuv2
; framework = arduino
; ; We consider that the this projects is opened within its project directory
; ; while working with VS Code.
; lib_extra_dirs = ../../../
; lib_deps =
; WifiManager
; knx
; build_flags =
; -DMASK_VERSION=0x07B0
; -Wno-unknown-pragmas
;---------------------------------------------------------
;--- ESP32 -----------------------------------------------
; [env:esp32dev_ip]
; platform = espressif32
; board = esp32dev
; framework = arduino
; ; We consider that the this projects is opened within its project directory
; ; while working with VS Code.
; lib_extra_dirs = ../../../
; lib_deps =
; knx
; build_flags =
; -DMASK_VERSION=0x57B0
; -Wno-unknown-pragmas
; [env:esp32dev_tp]
; platform = espressif32
; board = esp32dev
; framework = arduino
; ; We consider that the this projects is opened within its project directory
; ; while working with VS Code.
; lib_extra_dirs = ../../../
; lib_deps =
; knx
; build_flags =
; -DMASK_VERSION=0x07B0
; -Wno-unknown-pragmas

View File

@ -114,9 +114,13 @@ void BauSystemBDevice::updateGroupObject(GroupObject & go, uint8_t * data, uint8
memcpy(goData, data, length);
go.commFlag(Updated);
#ifdef SMALL_GROUPOBJECT
GroupObject::processClassCallback(go);
#else
GroupObjectUpdatedHandler handler = go.callback();
if (handler)
handler(go);
#endif
}
bool BauSystemBDevice::configured()

View File

@ -60,6 +60,12 @@
// Define via a compiler -D flag if required
// #define USE_DATASECURE
// option to have GroupObjects (KO in German) use 8 bytes mangement information RAM instead of 19 bytes
// see knx-demo-small-go for example
// this option might be also set via compiler flag -DSMALL_GROUPOBJECT if required
//#define SMALL_GROUPOBJECT
#endif
#if !defined(MASK_VERSION)

View File

@ -4,23 +4,30 @@
#include "datapoint_types.h"
#include "group_object_table_object.h"
#ifdef SMALL_GROUPOBJECT
GroupObjectUpdatedHandler GroupObject::_updateHandlerStatic = 0;
#endif
GroupObjectTableObject* GroupObject::_table = 0;
GroupObject::GroupObject()
{
_data = 0;
_commFlag = Ok;
_table = 0;
_dataLength = 0;
#ifndef SMALL_GROUPOBJECT
_updateHandler = 0;
#endif
}
GroupObject::GroupObject(const GroupObject& other)
{
_data = new uint8_t[other._dataLength];
_commFlag = other._commFlag;
_table = other._table;
_dataLength = other._dataLength;
_asap = other._asap;
#ifndef SMALL_GROUPOBJECT
_updateHandler = other._updateHandler;
#endif
memcpy(_data, other._data, _dataLength);
}
@ -175,6 +182,24 @@ size_t GroupObject::sizeInTelegram()
return asapValueSize(code);
}
#ifdef SMALL_GROUPOBJECT
GroupObjectUpdatedHandler GroupObject::classCallback()
{
return _updateHandlerStatic;
}
void GroupObject::classCallback(GroupObjectUpdatedHandler handler)
{
_updateHandlerStatic = handler;
}
void GroupObject::processClassCallback(GroupObject& ko)
{
if (_updateHandlerStatic != 0)
_updateHandlerStatic(ko);
}
#else
void GroupObject::callback(GroupObjectUpdatedHandler handler)
{
_updateHandler = handler;
@ -185,6 +210,7 @@ GroupObjectUpdatedHandler GroupObject::callback()
{
return _updateHandler;
}
#endif
void GroupObject::value(const KNXValue& value, const Dpt& type)
{
@ -205,7 +231,7 @@ bool GroupObject::tryValue(KNXValue& value, const Dpt& type)
return KNX_Decode_Value(_data, _dataLength, type, value);
}
#ifndef SMALL_GROUPOBJECT
void GroupObject::dataPointType(Dpt value)
{
_datapointType = value;
@ -240,7 +266,7 @@ void GroupObject::valueNoSend(const KNXValue& value)
{
valueNoSend(value, _datapointType);
}
#endif
void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type)
{

View File

@ -133,6 +133,8 @@ class GroupObject
* (in german "KO-Nr")
*/
uint16_t asap();
#ifndef SMALL_GROUPOBJECT
/**
* register a callback for this group object. The registered callback will be called if the group object was changed from the bus.
*/
@ -141,16 +143,12 @@ class GroupObject
* returns the registered callback
*/
GroupObjectUpdatedHandler callback();
#endif
/**
* return the current value of the group object.
* @param type the datapoint type used for the conversion. If this doesn't fit to the group object the returned value is invalid.
*/
KNXValue value(const Dpt& type);
/**
* return the current value of the group object. The datapoint type must be set with dataPointType(). Otherwise the returned
* value is invalid.
*/
KNXValue value();
/**
* set the current value of the group object and changes the state of the group object to ::WriteRequest.
* @param value the value the group object is set to
@ -159,13 +157,6 @@ class GroupObject
* The parameters must fit the group object. Otherwise it will stay unchanged.
*/
void value(const KNXValue& value, const Dpt& type);
/**
* set the current value of the group object and changes the state of the group object to ::WriteRequest.
* @param value the value the group object is set to
*
* The parameters must fit the group object and dhe datapoint type must be set with dataPointType(). Otherwise it will stay unchanged.
*/
void value(const KNXValue& value);
/**
* set the current value of the group object.
* @param value the value the group object is set to
@ -174,13 +165,6 @@ class GroupObject
* The parameters must fit the group object. Otherwise it will stay unchanged.
*/
void valueNoSend(const KNXValue& value, const Dpt& type);
/**
* set the current value of the group object.
* @param value the value the group object is set to
*
* The parameters must fit the group object and dhe datapoint type must be set with dataPointType(). Otherwise it will stay unchanged.
*/
void valueNoSend(const KNXValue& value);
/**
* set the current value of the group object.
* @param value the value the group object is set to
@ -191,6 +175,27 @@ class GroupObject
* @returns true if the value of the group object was changed successfully.
*/
bool tryValue(KNXValue& value, const Dpt& type);
#ifndef SMALL_GROUPOBJECT
/**
* return the current value of the group object. The datapoint type must be set with dataPointType(). Otherwise the returned
* value is invalid.
*/
KNXValue value();
/**
* set the current value of the group object and changes the state of the group object to ::WriteRequest.
* @param value the value the group object is set to
*
* The parameters must fit the group object and dhe datapoint type must be set with dataPointType(). Otherwise it will stay unchanged.
*/
void value(const KNXValue& value);
/**
* set the current value of the group object.
* @param value the value the group object is set to
*
* The parameters must fit the group object and dhe datapoint type must be set with dataPointType(). Otherwise it will stay unchanged.
*/
void valueNoSend(const KNXValue& value);
/**
* set the current value of the group object.
* @param value the value the group object is set to
@ -209,15 +214,32 @@ class GroupObject
* sets the datapoint type of the group object.
*/
void dataPointType(Dpt value);
#else
/**
* Alternative callback processing: register one global callback for all group object.
* The registered callback will be called if any group object was changed from the bus.
* The callback method has to dispatch to the correct handler for this group object.
*/
static GroupObjectUpdatedHandler classCallback();
static void classCallback(GroupObjectUpdatedHandler handler);
static void processClassCallback(GroupObject& ko);
#endif
private:
// class members
static GroupObjectTableObject* _table;
#ifdef SMALL_GROUPOBJECT
static GroupObjectUpdatedHandler _updateHandlerStatic;
#endif
size_t asapValueSize(uint8_t code);
GroupObjectUpdatedHandler _updateHandler;
size_t goSize();
uint16_t _asap = 0;
ComFlag _commFlag = Ok;
uint8_t* _data = 0;
uint8_t _dataLength = 0;
GroupObjectTableObject* _table = 0;
#ifndef SMALL_GROUPOBJECT
GroupObjectUpdatedHandler _updateHandler;
Dpt _datapointType;
#endif
};