diff --git a/src/knx/application_layer.cpp b/src/knx/application_layer.cpp index 5e5f6b5..c496bff 100644 --- a/src/knx/application_layer.cpp +++ b/src/knx/application_layer.cpp @@ -623,10 +623,29 @@ void ApplicationLayer::propertyValueWriteRequest(AckType ack, Priority priority, startIndex, data, length); } +void ApplicationLayer::adcReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, + uint8_t channelNr, uint8_t readCount, int16_t value) +{ + CemiFrame frame(4); + APDU& apdu = frame.apdu(); + apdu.type(ADCResponse); + uint8_t* data = apdu.data(); + + data[0] |= (channelNr & 0b111111); + data[1] = readCount; + data[2] = value >> 8; + data[3] = value & 0xFF; + + if (asap == _connectedTsap) + dataConnectedRequest(asap, priority, apdu, secCtrl); + else + dataIndividualRequest(ack, hopType, priority, asap, apdu, secCtrl); +} + void ApplicationLayer::functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t* resultData, uint8_t resultLength) { - CemiFrame frame(3 + resultLength + 1); + CemiFrame frame(3 + resultLength); APDU& apdu = frame.apdu(); apdu.type(FunctionPropertyStateResponse); uint8_t* data = apdu.data() + 1; @@ -1033,10 +1052,10 @@ void ApplicationLayer::individualIndication(HopCountType hopType, Priority prior break; } case FunctionPropertyCommand: - _bau.functionPropertyCommandIndication(priority, hopType, tsap, secCtrl, data[1], data[2], &data[3], apdu.length() - 4); //TODO: check length + _bau.functionPropertyCommandIndication(priority, hopType, tsap, secCtrl, data[1], data[2], &data[3], apdu.length() - 3); //TODO: check length break; case FunctionPropertyState: - _bau.functionPropertyStateIndication(priority, hopType, tsap, secCtrl, data[1], data[2], &data[3], apdu.length() - 4); //TODO: check length + _bau.functionPropertyStateIndication(priority, hopType, tsap, secCtrl, data[1], data[2], &data[3], apdu.length() - 3); //TODO: check length break; case FunctionPropertyExtCommand: { @@ -1128,6 +1147,13 @@ void ApplicationLayer::individualIndication(HopCountType hopType, Priority prior case KeyResponse: _bau.keyWriteAppLayerConfirm(priority, hopType, tsap, secCtrl, data[1]); break; + case ADCRead: + { + //Since we don't have an adc for bus voltage, we just send zero as readCount + uint8_t channelNr = data[0] & 0b111111; + this->adcReadResponse(AckRequested, priority, hopType, tsap, secCtrl, channelNr, 0, 0); + break; + } default: print("Individual-indication: unhandled APDU-Type: "); println(apdu.type()); diff --git a/src/knx/application_layer.h b/src/knx/application_layer.h index 327aed1..56b0f60 100644 --- a/src/knx/application_layer.h +++ b/src/knx/application_layer.h @@ -114,6 +114,8 @@ class ApplicationLayer uint16_t objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t returnCode); void propertyValueWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length); + void adcReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, + uint8_t channelNr, uint8_t readCount, int16_t value); void functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t *resultData, uint8_t resultLength); void functionPropertyExtStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, diff --git a/src/knx/bau.cpp b/src/knx/bau.cpp index 24f8138..d54602f 100644 --- a/src/knx/bau.cpp +++ b/src/knx/bau.cpp @@ -347,3 +347,21 @@ BeforeRestartCallback BusAccessUnit::beforeRestartCallback() { return 0; } + +void BusAccessUnit::functionPropertyCallback(FunctionPropertyCallback func) +{ +} + +FunctionPropertyCallback BusAccessUnit::functionPropertyCallback() +{ + return 0; +} + +void BusAccessUnit::functionPropertyStateCallback(FunctionPropertyCallback func) +{ +} + +FunctionPropertyCallback BusAccessUnit::functionPropertyStateCallback() +{ + return 0; +} \ No newline at end of file diff --git a/src/knx/bau.h b/src/knx/bau.h index 1382446..0193893 100644 --- a/src/knx/bau.h +++ b/src/knx/bau.h @@ -4,6 +4,7 @@ #include "interface_object.h" typedef void (*BeforeRestartCallback)(void); +typedef void (*FunctionPropertyCallback)(uint8_t objectIndex, uint8_t propertyId, uint8_t length, uint8_t *data, uint8_t *resultData, uint8_t &resultLength); class BusAccessUnit { @@ -165,4 +166,8 @@ class BusAccessUnit uint8_t* data, uint32_t length); virtual void beforeRestartCallback(BeforeRestartCallback func); virtual BeforeRestartCallback beforeRestartCallback(); + virtual void functionPropertyCallback(FunctionPropertyCallback func); + virtual FunctionPropertyCallback functionPropertyCallback(); + virtual void functionPropertyStateCallback(FunctionPropertyCallback func); + virtual FunctionPropertyCallback functionPropertyStateCallback(); }; diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp index 572dd4a..d3ae078 100644 --- a/src/knx/bau_systemB.cpp +++ b/src/knx/bau_systemB.cpp @@ -312,7 +312,10 @@ void BauSystemB::functionPropertyCommandIndication(Priority priority, HopCountTy } else { - resultLength = 0; // We must not send a return code or any data fields + if(_functionProperty != 0) + _functionProperty(objectIndex, propertyId, length, data, resultData, resultLength); + else + resultLength = 0; } } @@ -334,7 +337,10 @@ void BauSystemB::functionPropertyStateIndication(Priority priority, HopCountType } else { - resultLength = 0; // We must not send a return code or any data fields + if(_functionPropertyState != 0) + _functionPropertyState(objectIndex, propertyId, length, data, resultData, resultLength); + else + resultLength = 0; } } @@ -638,3 +644,22 @@ BeforeRestartCallback BauSystemB::beforeRestartCallback() { return _beforeRestart; } + +void BauSystemB::functionPropertyCallback(FunctionPropertyCallback func) +{ + _functionProperty = func; +} + +FunctionPropertyCallback BauSystemB::functionPropertyCallback() +{ + return _functionProperty; +} +void BauSystemB::functionPropertyStateCallback(FunctionPropertyCallback func) +{ + _functionPropertyState = func; +} + +FunctionPropertyCallback BauSystemB::functionPropertyStateCallback() +{ + return _functionPropertyState; +} \ No newline at end of file diff --git a/src/knx/bau_systemB.h b/src/knx/bau_systemB.h index dfbced6..ad57e66 100644 --- a/src/knx/bau_systemB.h +++ b/src/knx/bau_systemB.h @@ -43,6 +43,10 @@ class BauSystemB : protected BusAccessUnit VersionCheckCallback versionCheckCallback(); void beforeRestartCallback(BeforeRestartCallback func); BeforeRestartCallback beforeRestartCallback(); + void functionPropertyCallback(FunctionPropertyCallback func); + FunctionPropertyCallback functionPropertyCallback(); + void functionPropertyStateCallback(FunctionPropertyCallback func); + FunctionPropertyCallback functionPropertyStateCallback(); protected: virtual ApplicationLayer& applicationLayer() = 0; @@ -113,4 +117,6 @@ class BauSystemB : protected BusAccessUnit SecurityControl _restartSecurity; uint32_t _restartDelay = 0; BeforeRestartCallback _beforeRestart = 0; + FunctionPropertyCallback _functionProperty = 0; + FunctionPropertyCallback _functionPropertyState = 0; }; diff --git a/src/knx/knx_types.h b/src/knx/knx_types.h index a97fca9..b0a2a95 100644 --- a/src/knx/knx_types.h +++ b/src/knx/knx_types.h @@ -159,6 +159,8 @@ enum ApduType // Application Layer Services on Point-to-point Connection-Oriented Communication Mode (mandatory) // Application Layer Services on Point-to-point Connectionless Communication Mode (either optional or mandatory) + ADCRead = 0x0180, + ADCResponse = 0x01C0, PropertyValueExtRead = 0x1CC, PropertyValueExtResponse = 0x1CD, PropertyValueExtWriteCon = 0x1CE,