Add support for Function Properties

This commit is contained in:
Nanosonde 2020-06-08 11:04:00 +02:00
parent cc1fc7d5fb
commit 86c8f359e3
12 changed files with 198 additions and 5 deletions

View File

@ -494,6 +494,25 @@ void ApplicationLayer::propertyValueWriteRequest(AckType ack, Priority priority,
startIndex, data, length); 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, void ApplicationLayer::propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex) 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); startIndex, data + 5, apdu.length() - 5);
break; 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: case PropertyDescriptionRead:
_bau.propertyDescriptionReadIndication(priority, hopType, tsap, data[1], data[2], data[3]); _bau.propertyDescriptionReadIndication(priority, hopType, tsap, data[1], data[2], data[3]);
break; break;
@ -919,4 +944,4 @@ void ApplicationLayer::individualSend(AckType ack, HopCountType hopType, Priorit
bool ApplicationLayer::isConnected() bool ApplicationLayer::isConnected()
{ {
return (_connectedTsap >= 0); return (_connectedTsap >= 0);
} }

View File

@ -105,6 +105,8 @@ class ApplicationLayer
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length); 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, 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); 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, void propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex); uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex);
void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,

View File

@ -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) 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)
{ {
} }

View File

@ -48,6 +48,10 @@ class BusAccessUnit
uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, bool status); 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, virtual void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex); 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, 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); 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, virtual void propertyValueReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,

View File

@ -240,6 +240,32 @@ void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hop
startIndex, data, size); 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) void BauSystemB::individualAddressReadIndication(HopCountType hopType)
{ {
if (_deviceObj.progMode()) if (_deviceObj.progMode())
@ -433,4 +459,4 @@ void BauSystemB::propertyValueWrite(ObjectType objectType, uint8_t objectInstanc
Memory& BauSystemB::memory() Memory& BauSystemB::memory()
{ {
return _memory; return _memory;
} }

View File

@ -56,6 +56,10 @@ class BauSystemB : protected BusAccessUnit
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length) override; 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, void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) override; 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 individualAddressReadIndication(HopCountType hopType) override;
void individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress) override; void individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress) override;
void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType,
@ -97,4 +101,4 @@ class BauSystemB : protected BusAccessUnit
bool _configured = true; bool _configured = true;
RestartState _restartState = Idle; RestartState _restartState = Idle;
uint32_t _restartDelay = 0; uint32_t _restartDelay = 0;
}; };

View File

@ -0,0 +1,51 @@
#pragma once
#include "property.h"
class InterfaceObject;
template <class T> 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;
};

View File

@ -137,6 +137,30 @@ uint8_t InterfaceObject::propertySize(PropertyID id)
return prop->ElementSize(); 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() uint8_t InterfaceObject::propertyDescriptionCount()
{ {
return 0; return 0;

View File

@ -98,6 +98,34 @@ class InterfaceObject : public SaveRestore
* @returns the size in byte or 0 if the interface object does not have the property * @returns the size in byte or 0 if the interface object does not have the property
*/ */
virtual uint8_t propertySize(PropertyID id); 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. * 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; Property** _properties = nullptr;
uint8_t _propertyCount = 0; uint8_t _propertyCount = 0;
}; };

View File

@ -138,6 +138,9 @@ enum ApduType
UserMemoryWrite = 0x2C2, UserMemoryWrite = 0x2C2,
UserManufacturerInfoRead = 0x2C5, UserManufacturerInfoRead = 0x2C5,
UserManufacturerInfoResponse = 0x2C6, UserManufacturerInfoResponse = 0x2C6,
FunctionPropertyCommand = 0x2C7,
FunctionPropertyState = 0x2C8,
FunctionPropertyStateResponse = 0x2C9,
DeviceDescriptorRead = 0x300, DeviceDescriptorRead = 0x300,
DeviceDescriptorResponse = 0x340, DeviceDescriptorResponse = 0x340,
Restart = 0x380, Restart = 0x380,

View File

@ -203,3 +203,19 @@ uint8_t Property::write(uint16_t position, uint16_t value)
pushWord(value, data); pushWord(value, data);
return write(position, 1, 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;
}

View File

@ -238,6 +238,8 @@ class Property : public SaveRestore
uint8_t ElementSize() const; uint8_t ElementSize() const;
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const = 0; 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 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(uint8_t& value) const;
uint8_t read(uint16_t& value) const; uint8_t read(uint16_t& value) const;
uint8_t read(uint32_t& value) const; uint8_t read(uint32_t& value) const;
@ -253,4 +255,4 @@ class Property : public SaveRestore
PropertyDataType _type; PropertyDataType _type;
uint16_t _maxElements; uint16_t _maxElements;
uint8_t _access; uint8_t _access;
}; };