diff --git a/examples/knx-demo-smal-go/knx-demo.ino b/examples/knx-demo-smal-go/knx-demo.ino new file mode 100644 index 0000000..52fb386 --- /dev/null +++ b/examples/knx-demo-smal-go/knx-demo.ino @@ -0,0 +1,129 @@ +#include + +#ifdef ARDUINO_ARCH_ESP8266 +#include +#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(); +} \ No newline at end of file diff --git a/examples/knx-demo-smal-go/platformio.ini b/examples/knx-demo-smal-go/platformio.ini new file mode 100644 index 0000000..a919602 --- /dev/null +++ b/examples/knx-demo-smal-go/platformio.ini @@ -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 diff --git a/src/knx/bau_systemB_device.cpp b/src/knx/bau_systemB_device.cpp index 43d70f7..37289af 100644 --- a/src/knx/bau_systemB_device.cpp +++ b/src/knx/bau_systemB_device.cpp @@ -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() diff --git a/src/knx/config.h b/src/knx/config.h index 0b3ce64..a042ae3 100644 --- a/src/knx/config.h +++ b/src/knx/config.h @@ -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) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 2ed11d9..db92058 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -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) { diff --git a/src/knx/group_object.h b/src/knx/group_object.h index 7fdf5e6..6a07b5f 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -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 };