From 31319a690b08813556c00b314cf02c63ac9eb486 Mon Sep 17 00:00:00 2001 From: nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Thu, 7 May 2020 19:35:10 +0200 Subject: [PATCH 1/9] Fix travis build (#56) * Disable knx-usb example * Update python to 3.8 * Enable knx-usb example * Update to Arduino 1.8.11 * Pin to version 1.8.11 * Use python 3.7 * Use python 3.8 and fix path * Fix paths and remove obsolete stuff * Add lib Wire to deps. * Use Adafruit TinyUSB lib version 0.7.1 --- .travis.yml | 19 ++++++++++--------- examples/knx-usb/platformio-ci.ini | 4 ++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8452609..93834a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,6 @@ - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" cache: directories: - - ~/arduino_ide - - ~/.arduino15/packages/ git: depth: false quiet: true @@ -36,6 +34,7 @@ - language: cpp os: linux env: + - ARDUINO_IDE_VERSION="1.8.11" cache: directories: - ~/arduino_ide @@ -52,13 +51,15 @@ - sed -i 's#compiler.warning_level=all#compiler.warning_level=default#' ~/.arduino15/preferences.txt # changes for bsec lib # samd - - sed -ri 's#(recipe.c.combine.pattern=[^$]*\{archive_file\}")( -Wl,--end-group)#\1 {compiler.libraries.ldflags}\2#' ~/.arduino15/packages/arduino/hardware/samd/1.8.4/platform.txt - - sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/arduino/hardware/samd/1.8.4/platform.txt + - ls -l ~/.arduino15/packages/arduino/hardware/samd + - sed -ri 's#(recipe.c.combine.pattern=[^$]*\{archive_file\}")( -Wl,--end-group)#\1 {compiler.libraries.ldflags}\2#' ~/.arduino15/packages/arduino/hardware/samd/1.8.6/platform.txt + - sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/arduino/hardware/samd/1.8.6/platform.txt # esp8266 - - sed -ri 's#(recipe.c.combine.pattern=[^$]*\{compiler.c.elf.libs\})( -Wl,--end-group "-L\{build.path\}")#\1 {compiler.libraries.ldflags}\2#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/platform.txt - - sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/platform.txt - - sed -i '/^.*libalgobsec.*$/d' ~/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/sdk/ld/eagle.app.v6.common.ld.h - - sed -ri 's#(\*libwps\.a:\(\.literal\.\* \.text\.\*\))#\1\n *libalgobsec.a:(.literal.* .text.*)#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/sdk/ld/eagle.app.v6.common.ld.h + - ls -l ~/.arduino15/packages/esp8266/hardware/esp8266 + - sed -ri 's#(recipe.c.combine.pattern=[^$]*\{compiler.c.elf.libs\})( -Wl,--end-group "-L\{build.path\}")#\1 {compiler.libraries.ldflags}\2#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.0/platform.txt + - sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.0/platform.txt + - sed -i '/^.*libalgobsec.*$/d' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.0/tools/sdk/ld/eagle.app.v6.common.ld.h + - sed -ri 's#(\*libwps\.a:\(\.literal\.\* \.text\.\*\))#\1\n *libalgobsec.a:(.literal.* .text.*)#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.0/tools/sdk/ld/eagle.app.v6.common.ld.h # the HDC100X lib is not properly set up in githup so move things around a bit - rm -rf $HOME/arduino_ide/libraries/HDC100X_Arduino_Library-master @@ -79,7 +80,7 @@ # Test build for PlatformIO based projects - language: python python: - - "2.7" + - "3.8" cache: directories: - "~/.platformio" diff --git a/examples/knx-usb/platformio-ci.ini b/examples/knx-usb/platformio-ci.ini index aaaa387..0dd3625 100644 --- a/examples/knx-usb/platformio-ci.ini +++ b/examples/knx-usb/platformio-ci.ini @@ -19,10 +19,10 @@ board_build.usb_product="KNX RF - USB Interface" lib_deps = SPI - Adafruit TinyUSB Library + Adafruit TinyUSB Library@0.7.1 https://github.com/thelsing/FlashStorage.git knx - + build_flags = -DMEDIUM_TYPE=2 -DUSE_USB From c97bcc29f344367e90b176264f319ec1884cfb47 Mon Sep 17 00:00:00 2001 From: Thomas Kunze Date: Thu, 7 May 2020 20:15:15 +0200 Subject: [PATCH 2/9] comment some debugging code --- src/knx/memory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/knx/memory.cpp b/src/knx/memory.cpp index 0611b29..058c3d1 100644 --- a/src/knx/memory.cpp +++ b/src/knx/memory.cpp @@ -95,7 +95,7 @@ void Memory::writeMemory() { println(_data - buffer); println("."); - println((int)_saveRestores[i], HEX); + //println((long)_saveRestores[i], HEX); buffer = _saveRestores[i]->save(buffer); } @@ -105,7 +105,7 @@ void Memory::writeMemory() { println(_data - buffer); println("."); - println((int)_tableObjects[i], HEX); + //println((long)_tableObjects[i], HEX); buffer = _tableObjects[i]->save(buffer); //save to size of the memoryblock for tableobject too, so that we can rebuild the usedList and freeList From 5f4f86dcbdbfe216024073617963cc478546f601 Mon Sep 17 00:00:00 2001 From: Thomas Kunze Date: Fri, 8 May 2020 01:50:50 +0200 Subject: [PATCH 3/9] add platformio file and fix compiling without IP --- .vscode/extensions.json | 7 ++++++ platformio.ini | 27 +++++++++++++++++++++++ src/knx/knx_ip_device_information_dib.cpp | 2 ++ src/knx/knx_ip_frame.cpp | 2 +- src/knx/knx_ip_search_response.cpp | 3 +-- src/knx/knx_ip_supported_service_dib.cpp | 2 ++ src/knx/knx_value.cpp | 2 +- 7 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 platformio.ini diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..e80666b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..23ac4f9 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,27 @@ +; 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] +src_dir = examples/knx-demo + + +[env] +platform = atmelsam +board = zeroUSB +framework = arduino +build_type = debug +monitor_speed = 115200 +lib_ldf_mode = deep+ +lib_extra_dirs = + ${sysenv.USERPROFILE}/Documents/PlatformIO/Projects +build_flags = + -Wno-unknown-pragmas + +[env:build] diff --git a/src/knx/knx_ip_device_information_dib.cpp b/src/knx/knx_ip_device_information_dib.cpp index 8d5cf95..c6a5aa5 100644 --- a/src/knx/knx_ip_device_information_dib.cpp +++ b/src/knx/knx_ip_device_information_dib.cpp @@ -1,6 +1,7 @@ #include "knx_ip_device_information_dib.h" #include "bits.h" +#ifdef USE_IP KnxIpDeviceInformationDIB::KnxIpDeviceInformationDIB(uint8_t* data) : KnxIpDIB(data) {} @@ -98,3 +99,4 @@ void KnxIpDeviceInformationDIB::friendlyName(const uint8_t* value) { pushByteArray(value, LEN_FRIENDLY_NAME, _data + 24); } +#endif \ No newline at end of file diff --git a/src/knx/knx_ip_frame.cpp b/src/knx/knx_ip_frame.cpp index fad20ac..9cf1ce2 100644 --- a/src/knx/knx_ip_frame.cpp +++ b/src/knx/knx_ip_frame.cpp @@ -54,7 +54,6 @@ void KnxIpFrame::totalLength(uint16_t length) { pushWord(length, _data + 4); } -#endif uint8_t* KnxIpFrame::data() { @@ -79,3 +78,4 @@ KnxIpFrame::KnxIpFrame(uint16_t length) protocolVersion(KnxIp1_0); totalLength(length); } +#endif \ No newline at end of file diff --git a/src/knx/knx_ip_search_response.cpp b/src/knx/knx_ip_search_response.cpp index 8f436a4..ba3968e 100644 --- a/src/knx/knx_ip_search_response.cpp +++ b/src/knx/knx_ip_search_response.cpp @@ -1,8 +1,6 @@ #include "knx_ip_search_response.h" #ifdef USE_IP -#endif - #define SERVICE_FAMILIES 2 KnxIpSearchResponse::KnxIpSearchResponse(IpParameterObject& parameters, DeviceObject& deviceObject) @@ -61,3 +59,4 @@ KnxIpSupportedServiceDIB& KnxIpSearchResponse::supportedServices() { return _supportedServices; } +#endif \ No newline at end of file diff --git a/src/knx/knx_ip_supported_service_dib.cpp b/src/knx/knx_ip_supported_service_dib.cpp index 2e73d69..a4afbd4 100644 --- a/src/knx/knx_ip_supported_service_dib.cpp +++ b/src/knx/knx_ip_supported_service_dib.cpp @@ -1,5 +1,6 @@ #include "knx_ip_supported_service_dib.h" +#ifdef USE_IP KnxIpSupportedServiceDIB::KnxIpSupportedServiceDIB(uint8_t* data) : KnxIpDIB(data) {} @@ -39,3 +40,4 @@ void KnxIpSupportedServiceDIB::serviceVersion(ServiceFamily family, uint8_t ver } } } +#endif \ No newline at end of file diff --git a/src/knx/knx_value.cpp b/src/knx/knx_value.cpp index 7b6f93a..22d3e85 100644 --- a/src/knx/knx_value.cpp +++ b/src/knx/knx_value.cpp @@ -526,7 +526,7 @@ struct tm KNXValue::timeValue() const return *timePtr; } } - struct tm tmp; + struct tm tmp = {0}; return tmp; } From c31053a7fd88345547fe8233b5171278578ccc29 Mon Sep 17 00:00:00 2001 From: Thomas Kunze Date: Fri, 8 May 2020 02:06:23 +0200 Subject: [PATCH 4/9] add pio ignores to gitignore --- .gitignore | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5208146..c2a029f 100644 --- a/.gitignore +++ b/.gitignore @@ -269,4 +269,10 @@ __pycache__/ **/CodeDB **/VisualGDBCache -doc/build \ No newline at end of file +doc/build + +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch \ No newline at end of file From cc1fc7d5fb5050309937e99b9e0b346f2132292f Mon Sep 17 00:00:00 2001 From: thelsing Date: Fri, 8 May 2020 02:33:53 +0200 Subject: [PATCH 5/9] Update .travis.yml --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 93834a7..4d20c55 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,10 +56,10 @@ - sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/arduino/hardware/samd/1.8.6/platform.txt # esp8266 - ls -l ~/.arduino15/packages/esp8266/hardware/esp8266 - - sed -ri 's#(recipe.c.combine.pattern=[^$]*\{compiler.c.elf.libs\})( -Wl,--end-group "-L\{build.path\}")#\1 {compiler.libraries.ldflags}\2#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.0/platform.txt - - sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.0/platform.txt - - sed -i '/^.*libalgobsec.*$/d' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.0/tools/sdk/ld/eagle.app.v6.common.ld.h - - sed -ri 's#(\*libwps\.a:\(\.literal\.\* \.text\.\*\))#\1\n *libalgobsec.a:(.literal.* .text.*)#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.0/tools/sdk/ld/eagle.app.v6.common.ld.h + - sed -ri 's#(recipe.c.combine.pattern=[^$]*\{compiler.c.elf.libs\})( -Wl,--end-group "-L\{build.path\}")#\1 {compiler.libraries.ldflags}\2#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.1/platform.txt + - sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.1/platform.txt + - sed -i '/^.*libalgobsec.*$/d' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.1/tools/sdk/ld/eagle.app.v6.common.ld.h + - sed -ri 's#(\*libwps\.a:\(\.literal\.\* \.text\.\*\))#\1\n *libalgobsec.a:(.literal.* .text.*)#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.7.1/tools/sdk/ld/eagle.app.v6.common.ld.h # the HDC100X lib is not properly set up in githup so move things around a bit - rm -rf $HOME/arduino_ide/libraries/HDC100X_Arduino_Library-master From 86c8f359e352c21944ddcac83eea2c7292e53295 Mon Sep 17 00:00:00 2001 From: Nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Mon, 8 Jun 2020 11:04:00 +0200 Subject: [PATCH 6/9] Add support for Function Properties --- src/knx/application_layer.cpp | 27 ++++++++++++++++++- src/knx/application_layer.h | 2 ++ src/knx/bau.cpp | 8 ++++++ src/knx/bau.h | 4 +++ src/knx/bau_systemB.cpp | 28 ++++++++++++++++++- src/knx/bau_systemB.h | 6 ++++- src/knx/function_property.h | 51 +++++++++++++++++++++++++++++++++++ src/knx/interface_object.cpp | 24 +++++++++++++++++ src/knx/interface_object.h | 30 ++++++++++++++++++++- src/knx/knx_types.h | 3 +++ src/knx/property.cpp | 16 +++++++++++ src/knx/property.h | 4 ++- 12 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 src/knx/function_property.h diff --git a/src/knx/application_layer.cpp b/src/knx/application_layer.cpp index 74f99d8..cbf5afa 100644 --- a/src/knx/application_layer.cpp +++ b/src/knx/application_layer.cpp @@ -494,6 +494,25 @@ void ApplicationLayer::propertyValueWriteRequest(AckType ack, Priority priority, startIndex, data, length); } +void ApplicationLayer::functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, + uint8_t objectIndex, uint8_t propertyId, uint8_t* resultData, uint8_t resultLength) +{ + CemiFrame frame(3 + resultLength + 1); + APDU& apdu = frame.apdu(); + apdu.type(FunctionPropertyStateResponse); + uint8_t* data = apdu.data() + 1; + + data[0] = objectIndex; + data[1] = propertyId; + if (resultLength > 0) + memcpy(&data[2], resultData, resultLength); + + if (asap == _connectedTsap) + dataConnectedRequest(asap, priority, apdu); + else + dataIndividualRequest(ack, hopType, priority, asap, apdu); +} + void ApplicationLayer::propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex) { @@ -751,6 +770,12 @@ void ApplicationLayer::individualIndication(HopCountType hopType, Priority prior startIndex, data + 5, apdu.length() - 5); break; } + case FunctionPropertyCommand: + _bau.functionPropertyCommandIndication(priority, hopType, tsap, data[1], data[2], &data[3], apdu.length() - 4); //TODO: check length + break; + case FunctionPropertyState: + _bau.functionPropertyStateIndication(priority, hopType, tsap, data[1], data[2], &data[3], apdu.length() - 4); //TODO: check length + break; case PropertyDescriptionRead: _bau.propertyDescriptionReadIndication(priority, hopType, tsap, data[1], data[2], data[3]); break; @@ -919,4 +944,4 @@ void ApplicationLayer::individualSend(AckType ack, HopCountType hopType, Priorit bool ApplicationLayer::isConnected() { return (_connectedTsap >= 0); -} \ No newline at end of file +} diff --git a/src/knx/application_layer.h b/src/knx/application_layer.h index 401a653..c2de79c 100644 --- a/src/knx/application_layer.h +++ b/src/knx/application_layer.h @@ -105,6 +105,8 @@ class ApplicationLayer uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length); void propertyValueWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length); + void functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, + uint8_t objectIndex, uint8_t propertyId, uint8_t *resultData, uint8_t resultLength); void propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex); void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, diff --git a/src/knx/bau.cpp b/src/knx/bau.cpp index e2b1a9d..f28c94f 100644 --- a/src/knx/bau.cpp +++ b/src/knx/bau.cpp @@ -106,6 +106,14 @@ void BusAccessUnit::propertyValueReadIndication(Priority priority, HopCountType { } +void BusAccessUnit::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t* data, uint8_t length) +{ +} + +void BusAccessUnit::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t* data, uint8_t length) +{ +} + void BusAccessUnit::propertyValueReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status) { } diff --git a/src/knx/bau.h b/src/knx/bau.h index a0e567c..444c61f 100644 --- a/src/knx/bau.h +++ b/src/knx/bau.h @@ -48,6 +48,10 @@ class BusAccessUnit uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, bool status); virtual void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex); + virtual void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, + uint8_t propertyId, uint8_t* data, uint8_t length); + virtual void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, + uint8_t propertyId, uint8_t* data, uint8_t length); virtual void propertyValueReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status); virtual void propertyValueReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp index 8f44ef1..f3cc234 100644 --- a/src/knx/bau_systemB.cpp +++ b/src/knx/bau_systemB.cpp @@ -240,6 +240,32 @@ void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hop startIndex, data, size); } +void BauSystemB::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, + uint8_t propertyId, uint8_t* data, uint8_t length) +{ + uint8_t resultLength = 0; + uint8_t resultData[32]; + + InterfaceObject* obj = getInterfaceObject(objectIndex); + if(obj) + obj->command((PropertyID)propertyId, data, length, resultData, resultLength); + + _appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, resultData, resultLength); +} + +void BauSystemB::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, + uint8_t propertyId, uint8_t* data, uint8_t length) +{ + uint8_t resultLength = 0; + uint8_t resultData[32]; + + InterfaceObject* obj = getInterfaceObject(objectIndex); + if(obj) + obj->state((PropertyID)propertyId, data, length, resultData, resultLength); + + _appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, resultData, resultLength); +} + void BauSystemB::individualAddressReadIndication(HopCountType hopType) { if (_deviceObj.progMode()) @@ -433,4 +459,4 @@ void BauSystemB::propertyValueWrite(ObjectType objectType, uint8_t objectInstanc Memory& BauSystemB::memory() { return _memory; -} \ No newline at end of file +} diff --git a/src/knx/bau_systemB.h b/src/knx/bau_systemB.h index b651150..2dce5e7 100644 --- a/src/knx/bau_systemB.h +++ b/src/knx/bau_systemB.h @@ -56,6 +56,10 @@ class BauSystemB : protected BusAccessUnit uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length) override; void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) override; + void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, + uint8_t propertyId, uint8_t* data, uint8_t length); + void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, + uint8_t propertyId, uint8_t* data, uint8_t length); void individualAddressReadIndication(HopCountType hopType) override; void individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress) override; void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, @@ -97,4 +101,4 @@ class BauSystemB : protected BusAccessUnit bool _configured = true; RestartState _restartState = Idle; uint32_t _restartDelay = 0; -}; \ No newline at end of file +}; diff --git a/src/knx/function_property.h b/src/knx/function_property.h new file mode 100644 index 0000000..b43df9f --- /dev/null +++ b/src/knx/function_property.h @@ -0,0 +1,51 @@ +#pragma once + +#include "property.h" + +class InterfaceObject; + +template class FunctionProperty : public Property +{ + public: + FunctionProperty(T* io, PropertyID id, uint8_t access, + void (*commandCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&), + void (*stateCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&)) + : Property(id, false, PDT_FUNCTION, 1, access), _interfaceObject(io), _commandCallback(commandCallback), _stateCallback(stateCallback) + /* max_elements is set to 1, see 3.3.7 Application Layer p.68 */ + {} + + virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const override + { + return 0; + } + + virtual uint8_t write(uint16_t start, uint8_t count, const uint8_t* data) override + { + return 0; + } + + virtual void command(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) override + { + if (length == 0 || _commandCallback == nullptr ) + { + resultLength = 0; + return; + } + _commandCallback(_interfaceObject, data, length, resultData, resultLength); + } + + virtual void state(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) override + { + if (length == 0 || _stateCallback == nullptr ) + { + resultLength = 0; + return; + } + _stateCallback(_interfaceObject, data, length, resultData, resultLength); + } + + private: + T* _interfaceObject = nullptr; + void (*_commandCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&) = nullptr; + void (*_stateCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&) = nullptr; +}; diff --git a/src/knx/interface_object.cpp b/src/knx/interface_object.cpp index 20276f6..19396ac 100644 --- a/src/knx/interface_object.cpp +++ b/src/knx/interface_object.cpp @@ -137,6 +137,30 @@ uint8_t InterfaceObject::propertySize(PropertyID id) return prop->ElementSize(); } +void InterfaceObject::command(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) +{ + Property* prop = property(id); + if (prop == nullptr) + { + resultLength = 0; + return;; + } + + prop->command(data, length, resultData, resultLength); +} + +void InterfaceObject::state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t resultLength) +{ + Property* prop = property(id); + if (prop == nullptr) + { + resultLength = 0; + return;; + } + + prop->state(data, length, resultData, resultLength); +} + uint8_t InterfaceObject::propertyDescriptionCount() { return 0; diff --git a/src/knx/interface_object.h b/src/knx/interface_object.h index 03f93e9..0b92633 100644 --- a/src/knx/interface_object.h +++ b/src/knx/interface_object.h @@ -98,6 +98,34 @@ class InterfaceObject : public SaveRestore * @returns the size in byte or 0 if the interface object does not have the property */ virtual uint8_t propertySize(PropertyID id); + /** + * Call command of a function property of the interface object. Property type must be PDT_FUNCTION + * + * @param id id of the property to call + * + * @param[in] length The size of the data buffer + * + * @param[in] data The argument data for the function + * + * @param[out] resultLength The size of the result data buffer + * + * @param[out] resultData The result data for the function + */ + virtual void command(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t &resultLength); + /** + * Get state of a function property of the interface object. Property type must be PDT_FUNCTION + * + * @param id id of the property to call + * + * @param[in] length The size of the data buffer + * + * @param[in] data The argument data for the function + * + * @param[out] resultLength The size of the result data buffer + * + * @param[out] resultData The result data for the function + */ + virtual void state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t resultLength); /** * Read the Description of a property of the interface object. The output parameters are only valid if nuberOfElements is not zero. * @@ -170,4 +198,4 @@ class InterfaceObject : public SaveRestore Property** _properties = nullptr; uint8_t _propertyCount = 0; -}; \ No newline at end of file +}; diff --git a/src/knx/knx_types.h b/src/knx/knx_types.h index 046a4b3..a84b224 100644 --- a/src/knx/knx_types.h +++ b/src/knx/knx_types.h @@ -138,6 +138,9 @@ enum ApduType UserMemoryWrite = 0x2C2, UserManufacturerInfoRead = 0x2C5, UserManufacturerInfoResponse = 0x2C6, + FunctionPropertyCommand = 0x2C7, + FunctionPropertyState = 0x2C8, + FunctionPropertyStateResponse = 0x2C9, DeviceDescriptorRead = 0x300, DeviceDescriptorResponse = 0x340, Restart = 0x380, diff --git a/src/knx/property.cpp b/src/knx/property.cpp index a5077dd..a42989f 100644 --- a/src/knx/property.cpp +++ b/src/knx/property.cpp @@ -203,3 +203,19 @@ uint8_t Property::write(uint16_t position, uint16_t value) pushWord(value, data); return write(position, 1, data); } + +void Property::command(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) +{ + (void)data; + (void)length; + (void)resultData; + resultLength = 0; +} + +void Property::state(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t &resultLength) +{ + (void)data; + (void)length; + (void)resultData; + resultLength = 0; +} diff --git a/src/knx/property.h b/src/knx/property.h index 11ac4ef..7c3ea93 100644 --- a/src/knx/property.h +++ b/src/knx/property.h @@ -238,6 +238,8 @@ class Property : public SaveRestore uint8_t ElementSize() const; virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const = 0; virtual uint8_t write(uint16_t start, uint8_t count, const uint8_t* data) = 0; + virtual void command(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength); + virtual void state(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength); uint8_t read(uint8_t& value) const; uint8_t read(uint16_t& value) const; uint8_t read(uint32_t& value) const; @@ -253,4 +255,4 @@ class Property : public SaveRestore PropertyDataType _type; uint16_t _maxElements; uint8_t _access; -}; \ No newline at end of file +}; From 918d3f37c4a96f26989d4ac19fa694e946e9e453 Mon Sep 17 00:00:00 2001 From: Nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Mon, 8 Jun 2020 11:14:56 +0200 Subject: [PATCH 7/9] Fix compilation. --- src/knx/application_layer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/knx/application_layer.cpp b/src/knx/application_layer.cpp index cbf5afa..c6f6245 100644 --- a/src/knx/application_layer.cpp +++ b/src/knx/application_layer.cpp @@ -508,9 +508,9 @@ void ApplicationLayer::functionPropertyStateResponse(AckType ack, Priority prior memcpy(&data[2], resultData, resultLength); if (asap == _connectedTsap) - dataConnectedRequest(asap, priority, apdu); + _transportLayer->dataConnectedRequest(asap, priority, apdu); else - dataIndividualRequest(ack, hopType, priority, asap, apdu); + _transportLayer->dataIndividualRequest(ack, hopType, priority, asap, apdu); } void ApplicationLayer::propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, From d1701db1d1b7497b0b7bcdfdc80541855d445e39 Mon Sep 17 00:00:00 2001 From: nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Mon, 8 Jun 2020 11:43:06 +0200 Subject: [PATCH 8/9] Disable Travis-CI 8266 Arduino test --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4d20c55..1eeb901 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,7 +75,7 @@ # - buildExampleSketch knx-bme680 # - buildExampleSketch knx-hdc1008 - build_platform zero - - build_platform esp8266 + # - build_platform esp8266 # Test build for PlatformIO based projects - language: python From cadc6c61246d1b4634fae1ed15fc265cefc29746 Mon Sep 17 00:00:00 2001 From: nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Tue, 9 Jun 2020 21:06:13 +0200 Subject: [PATCH 9/9] Refactor broadcast/systembroadcast (#62) * Add missing source files * Fix comment * Refactor Broadcast/SystemBroadcast * Add empty confirm methods * Remove unclean solution to suppress warning about unsed var * Restore old structure * Fix issues * Add more missing source files * Make sure that services from SystemBroadcast are also available from Broadcast on closed media * Make sure that sent broadcast/systembroadcast frames are always marked as broadcast frames on closed media --- examples/knx-linux/CMakeLists.txt | 38 +++++++++++++------ src/knx/application_layer.cpp | 61 ++++++++++++++++++++++++++++++- src/knx/bau.cpp | 14 +++++++ src/knx/bau.h | 8 ++++ src/knx/bau27B0.cpp | 12 +++++- src/knx/bau27B0.h | 5 ++- src/knx/bau_systemB.cpp | 5 +++ src/knx/bau_systemB.h | 2 + src/knx/data_link_layer.cpp | 5 +++ src/knx/network_layer.cpp | 1 - 10 files changed, 135 insertions(+), 16 deletions(-) diff --git a/examples/knx-linux/CMakeLists.txt b/examples/knx-linux/CMakeLists.txt index 9660b58..f654713 100644 --- a/examples/knx-linux/CMakeLists.txt +++ b/examples/knx-linux/CMakeLists.txt @@ -28,8 +28,11 @@ add_executable(knx-linux ../../src/knx/cemi_frame.cpp ../../src/knx/cemi_frame.h ../../src/knx/cemi_server.cpp - ../../src/knx/cemi_server_object.cpp - ../../src/knx/data_link_layer.cpp + ../../src/knx/cemi_server.h + ../../src/knx/cemi_server_object.cpp + ../../src/knx/cemi_server_object.h + ../../src/knx/config.h + ../../src/knx/data_link_layer.cpp ../../src/knx/data_link_layer.h ../../src/knx/data_property.cpp ../../src/knx/data_property.h @@ -50,14 +53,23 @@ add_executable(knx-linux ../../src/knx/ip_parameter_object.cpp ../../src/knx/ip_parameter_object.h ../../src/knx/knx_ip_device_information_dib.cpp - ../../src/knx/knx_ip_dib.cpp - ../../src/knx/knx_ip_frame.cpp - ../../src/knx/knx_ip_routing_indication.cpp - ../../src/knx/knx_ip_search_request.cpp - ../../src/knx/knx_ip_search_response.cpp - ../../src/knx/knx_ip_supported_service_dib.cpp - ../../src/knx/ip_host_protocol_address_information.cpp - ../../src/knx/knx_value.cpp + ../../src/knx/knx_ip_device_information_dib.h + ../../src/knx/knx_ip_dib.cpp + ../../src/knx/knx_ip_dib.h + ../../src/knx/knx_ip_frame.cpp + ../../src/knx/knx_ip_frame.h + ../../src/knx/knx_ip_routing_indication.cpp + ../../src/knx/knx_ip_routing_indication.h + ../../src/knx/knx_ip_search_request.cpp + ../../src/knx/knx_ip_search_request.h + ../../src/knx/knx_ip_search_response.cpp + ../../src/knx/knx_ip_search_response.h + ../../src/knx/knx_ip_supported_service_dib.cpp + ../../src/knx/knx_ip_supported_service_dib.h + ../../src/knx/ip_host_protocol_address_information.cpp + ../../src/knx/ip_host_protocol_address_information.h + ../../src/knx/knx_types.h + ../../src/knx/knx_value.cpp ../../src/knx/knx_value.h ../../src/knx/memory.cpp ../../src/knx/memory.h @@ -65,7 +77,7 @@ add_executable(knx-linux ../../src/knx/network_layer.h ../../src/knx/npdu.cpp ../../src/knx/npdu.h - ../../src/knx/platform.cpp + ../../src/knx/platform.cpp ../../src/knx/platform.h ../../src/knx/property.cpp ../../src/knx/property.h @@ -75,6 +87,7 @@ add_executable(knx-linux ../../src/knx/rf_medium_object.h ../../src/knx/rf_physical_layer.cpp ../../src/knx/rf_physical_layer.h + ../../src/knx/save_restore.h ../../src/knx/table_object.cpp ../../src/knx/table_object.h ../../src/knx/tpdu.cpp @@ -84,7 +97,8 @@ add_executable(knx-linux ../../src/knx/transport_layer.cpp ../../src/knx/transport_layer.h ../../src/knx/usb_tunnel_interface.cpp - ../../src/knx_facade.cpp + ../../src/knx/usb_tunnel_interface.h + ../../src/knx_facade.cpp ../../src/knx_facade.h ../../src/linux_platform.cpp ../../src/linux_platform.h diff --git a/src/knx/application_layer.cpp b/src/knx/application_layer.cpp index c6f6245..421a8f2 100644 --- a/src/knx/application_layer.cpp +++ b/src/knx/application_layer.cpp @@ -118,8 +118,15 @@ void ApplicationLayer::dataBroadcastIndication(HopCountType hopType, Priority pr break; } default: +#if (MEDIUM_TYPE == 5)||(MEDIUM_TYPE == 0) + // Make sure we also check if it is a service normally available only on SystemBroadcast on open media + dataSystemBroadcastIndication(hopType, priority, source, apdu); +#else print("Broadcast-indication: unhandled APDU-Type: "); println(apdu.type()); + +#endif + break; } } @@ -159,8 +166,15 @@ void ApplicationLayer::dataBroadcastConfirm(AckType ack, HopCountType hopType, P break; } default: +#if (MEDIUM_TYPE == 5)||(MEDIUM_TYPE == 0) + // Make sure we also check if it is a service normally available only on SystemBroadcast on open media + dataSystemBroadcastConfirm(hopType, priority, apdu, status); +#else print("Broadcast-confirm: unhandled APDU-Type: "); println(apdu.type()); + +#endif + break; } } @@ -198,13 +212,58 @@ void ApplicationLayer::dataSystemBroadcastIndication(HopCountType hopType, Prior break; } default: +#if (MEDIUM_TYPE == 5)||(MEDIUM_TYPE == 0) + print("Broadcast-indication: unhandled APDU-Type: "); +#else + print("SystemBroadcast-indication: unhandled APDU-Type: "); +#endif + println(apdu.type()); break; } } void ApplicationLayer::dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status) { - + const uint8_t* data = apdu.data(); + switch (apdu.type()) + { + // TODO: testInfo could be of any length + case SystemNetworkParameterRead: + { + uint16_t objectType; + uint16_t propertyId; + uint8_t testInfo[2]; + popWord(objectType, data + 1); + popWord(propertyId, data + 3); + popByte(testInfo[0], data + 4); + popByte(testInfo[1], data + 5); + propertyId = (propertyId >> 4) & 0x0FFF;; + testInfo[0] &= 0x0F; + _bau.systemNetworkParameterReadLocalConfirm(priority, hopType, objectType, propertyId, testInfo, sizeof(testInfo), status); + break; + } + case DomainAddressSerialNumberWrite: + { + const uint8_t* knxSerialNumber = &data[1]; + const uint8_t* domainAddress = &data[7]; + _bau.domainAddressSerialNumberWriteLocalConfirm(priority, hopType, domainAddress, knxSerialNumber, status); + break; + } + case DomainAddressSerialNumberRead: + { + const uint8_t* knxSerialNumber = &data[1]; + _bau.domainAddressSerialNumberReadLocalConfirm(priority, hopType, knxSerialNumber, status); + break; + } + default: +#if (MEDIUM_TYPE == 5)||(MEDIUM_TYPE == 0) + print("Broadcast-confirm: unhandled APDU-Type: "); +#else + print("SystemBroadcast-confirm: unhandled APDU-Type: "); +#endif + println(apdu.type()); + break; + } } void ApplicationLayer::dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu) diff --git a/src/knx/bau.cpp b/src/knx/bau.cpp index f28c94f..b09f513 100644 --- a/src/knx/bau.cpp +++ b/src/knx/bau.cpp @@ -264,6 +264,20 @@ void BusAccessUnit::domainAddressSerialNumberReadIndication(Priority priority, H { } +void BusAccessUnit::systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, uint16_t objectType, + uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, bool status) +{ +} + +void BusAccessUnit::domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* rfDoA, + const uint8_t* knxSerialNumber, bool status) +{ +} + +void BusAccessUnit::domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber, bool status) +{ +} + void BusAccessUnit::propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t& numberOfElements, uint16_t startIndex, uint8_t** data, uint32_t& length) diff --git a/src/knx/bau.h b/src/knx/bau.h index 444c61f..d2d9c80 100644 --- a/src/knx/bau.h +++ b/src/knx/bau.h @@ -123,6 +123,14 @@ class BusAccessUnit virtual void domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber); + virtual void systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, uint16_t objectType, + uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, bool status); + + virtual void domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* rfDoA, + const uint8_t* knxSerialNumber, bool status); + + virtual void domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber, bool status); + virtual void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t& numberOfElements, uint16_t startIndex, uint8_t** data, uint32_t& length); diff --git a/src/knx/bau27B0.cpp b/src/knx/bau27B0.cpp index c9cf495..a938dba 100644 --- a/src/knx/bau27B0.cpp +++ b/src/knx/bau27B0.cpp @@ -150,4 +150,14 @@ void Bau27B0::individualAddressSerialNumberReadIndication(Priority priority, Hop _appLayer.IndividualAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber); } -#endif // #if MEDIUM_TYPE == 2 +void Bau27B0::domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* rfDoA, + const uint8_t* knxSerialNumber, bool status) +{ +} + +void Bau27B0::domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber, bool status) +{ +} + + +#endif // #ifdef USE_RF diff --git a/src/knx/bau27B0.h b/src/knx/bau27B0.h index 8b270b6..678a659 100644 --- a/src/knx/bau27B0.h +++ b/src/knx/bau27B0.h @@ -34,5 +34,8 @@ class Bau27B0 : public BauSystemB void individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint16_t newIndividualAddress, uint8_t* knxSerialNumber) override; void individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber) override; + void domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* rfDoA, + const uint8_t* knxSerialNumber, bool status) override; + void domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber, bool status) override; }; -#endif \ No newline at end of file +#endif diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp index f3cc234..1a80920 100644 --- a/src/knx/bau_systemB.cpp +++ b/src/knx/bau_systemB.cpp @@ -419,6 +419,11 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun } } +void BauSystemB::systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, uint16_t objectType, + uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, bool status) +{ +} + void BauSystemB::propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t &numberOfElements, uint16_t startIndex, uint8_t **data, uint32_t &length) diff --git a/src/knx/bau_systemB.h b/src/knx/bau_systemB.h index 2dce5e7..b618fa6 100644 --- a/src/knx/bau_systemB.h +++ b/src/knx/bau_systemB.h @@ -72,6 +72,8 @@ class BauSystemB : protected BusAccessUnit uint8_t* data, uint8_t dataLength) override; void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType, uint16_t propertyId, uint8_t* testInfo, uint16_t testinfoLength) override; + void systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, uint16_t objectType, + uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, bool status) override; void connectConfirm(uint16_t tsap) override; virtual InterfaceObject* getInterfaceObject(uint8_t idx) = 0; diff --git a/src/knx/data_link_layer.cpp b/src/knx/data_link_layer.cpp index a8421e8..877783d 100644 --- a/src/knx/data_link_layer.cpp +++ b/src/knx/data_link_layer.cpp @@ -140,7 +140,12 @@ bool DataLinkLayer::sendTelegram(NPDU & npdu, AckType ack, uint16_t destinationA frame.addressType(addrType); frame.priority(priority); frame.repetition(RepititionAllowed); +#if (MEDIUM_TYPE == 5)||(MEDIUM_TYPE == 0) + // Make sure to always send as normal Broadcast on closed media (TP and IP) + frame.systemBroadcast(Broadcast); +#else frame.systemBroadcast(systemBroadcast); +#endif if (npdu.octetCount() <= 15) frame.frameType(StandardFrame); diff --git a/src/knx/network_layer.cpp b/src/knx/network_layer.cpp index ffea9d3..869c4fc 100644 --- a/src/knx/network_layer.cpp +++ b/src/knx/network_layer.cpp @@ -45,7 +45,6 @@ void NetworkLayer::dataIndication(AckType ack, AddressType addrType, uint16_t de } // destination == 0 _transportLayer.dataBroadcastIndication(hopType, priority, source, npdu.tpdu()); - } void NetworkLayer::dataConfirm(AckType ack, AddressType addressType, uint16_t destination, FrameFormat format, Priority priority, uint16_t source, NPDU& npdu, bool status)