Finish refactoring of IpParameterObject

This commit is contained in:
Thomas Kunze 2019-12-12 19:34:29 +01:00
parent e128debabb
commit 4cc8b2bb36
9 changed files with 224 additions and 202 deletions

View File

@ -18,7 +18,7 @@ template <class T> class CallbackProperty : public Property
: Property(id, writeEnable, type, maxElements, access), _interfaceObject(io), _readCallback(readCallback)
{}
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) override
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const override
{
if (count == 0 || _readCallback == nullptr || start > _maxElements || start + count > _maxElements + 1)
return 0;

View File

@ -3,7 +3,7 @@
#include <cstring>
uint8_t DataProperty::read(uint16_t start, uint8_t count, uint8_t* data)
uint8_t DataProperty::read(uint16_t start, uint8_t count, uint8_t* data) const
{
if (count == 0 || _currentElements == 0 || start > _currentElements || count > _currentElements - start + 1)
return 0;
@ -94,3 +94,65 @@ DataProperty::DataProperty(PropertyID id, bool writeEnable, PropertyDataType typ
write(1, 1, data);
}
}
DataProperty::DataProperty(PropertyID id, bool writeEnable, PropertyDataType type,
uint16_t maxElements, uint8_t access, uint32_t value)
: Property(id, writeEnable, type, maxElements, access)
{
uint8_t elementSize = ElementSize();
if (elementSize == 4)
{
uint8_t data[elementSize];
pushInt(value, data);
write(1, 1, data);
}
}
DataProperty::DataProperty(PropertyID id, bool writeEnable, PropertyDataType type,
uint16_t maxElements, uint8_t access, uint8_t value)
: Property(id, writeEnable, type, maxElements, access)
{
uint8_t elementSize = ElementSize();
if (elementSize == 1)
{
uint8_t data[elementSize];
data[0] = value;
write(1, 1, data);
}
}
uint16_t DataProperty::saveSize()
{
return sizeof(_currentElements) + _maxElements * ElementSize();
}
uint8_t* DataProperty::restore(uint8_t* buffer)
{
uint16_t elements = 0;
buffer = popWord(elements, buffer);
if (elements != _currentElements)
{
if (_data != nullptr)
delete[] _data;
_data = new uint8_t[elements * ElementSize()];
_currentElements = elements;
}
if (elements > 0)
buffer = popByteArray(_data, elements * ElementSize(), buffer);
return buffer;
}
uint8_t* DataProperty::save(uint8_t* buffer)
{
buffer = pushWord(_currentElements, buffer);
if (_currentElements > 0)
buffer = pushByteArray(_data, _currentElements, buffer);
return buffer;
}

View File

@ -6,10 +6,16 @@ class DataProperty : public Property
{
public:
DataProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access);
DataProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access, uint8_t value);
DataProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access, uint16_t value);
DataProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access, uint32_t value);
virtual ~DataProperty() override;
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) override;
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const override;
virtual uint8_t write(uint16_t start, uint8_t count, uint8_t* data) override;
virtual uint8_t* save(uint8_t* buffer) override;
virtual uint8_t* restore(uint8_t* buffer) override;
virtual uint16_t saveSize() override;
private:
uint16_t _currentElements = 0;
uint8_t* _data = nullptr;

View File

@ -15,7 +15,7 @@ void InterfaceObject::readPropertyDescription(uint8_t& propertyId, uint8_t& prop
numberOfElements = 0;
if (descriptions == nullptr || count == 0)
return;
return readPropertyDescription2(propertyId, propertyIndex, writeEnable, type, numberOfElements, access);
PropertyDescription* desc = nullptr;
@ -52,6 +52,53 @@ void InterfaceObject::readPropertyDescription(uint8_t& propertyId, uint8_t& prop
numberOfElements = desc->MaxElements;
access = desc->Access;
}
else
return readPropertyDescription2(propertyId, propertyIndex, writeEnable, type, numberOfElements, access);
}
void InterfaceObject::readPropertyDescription2(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access)
{
uint8_t count = _propertyCount;
numberOfElements = 0;
if (_properties == nullptr || count == 0)
return;
Property* prop = nullptr;
// from KNX spec. 03.03.07 Application Layer (page 56) - 3.4.3.3 A_PropertyDescription_Read-service
// Summary: either propertyId OR propertyIndex, but not both at the same time
if (propertyId != 0)
{
for (uint8_t i = 0; i < count; i++)
{
Property* p = _properties[i];
if (p->Id() != propertyId)
continue;
prop = p;
propertyIndex = i;
break;
}
}
else
{
// If propertyId is zero, propertyIndex shall be used.
// Response: propertyIndex of received A_PropertyDescription_Read
if (propertyIndex < count)
{
prop = _properties[propertyIndex];
}
}
if (prop != nullptr)
{
propertyId = prop->Id();
writeEnable = prop->WriteEnable();
type = prop->Type();
numberOfElements = prop->MaxElements();
access = prop->Access();
}
}
void InterfaceObject::readProperty(PropertyID id, uint16_t start, uint8_t& count, uint8_t* data)
@ -160,3 +207,13 @@ uint16_t InterfaceObject::saveSize()
}
return size;
}
const Property* InterfaceObject::property(PropertyID id) const
{
for (int i = 0; i < _propertyCount; i++)
if (_properties[i]->Id() == id)
return _properties[i];
return nullptr;
}

View File

@ -116,9 +116,9 @@ class InterfaceObject : public SaveRestore
*
* @param[out] access the ::AccessLevel necessary to read/write the property.
*/
// TODO: remove first version after complete property refactoring
void readPropertyDescription(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access);
void readPropertyDescription2(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access);
/**
* Gets object type.
*
@ -131,6 +131,11 @@ class InterfaceObject : public SaveRestore
*/
Property* property(PropertyID id);
/**
* Gets const property with PropertyID id if it exists and nullptr otherwise.
*/
const Property* property(PropertyID id) const;
virtual uint8_t* save(uint8_t* buffer) override;
virtual uint8_t* restore(uint8_t* buffer) override;
virtual uint16_t saveSize() override;

View File

@ -13,11 +13,14 @@ IpParameterObject::IpParameterObject(DeviceObject& deviceObject, Platform& platf
{
Property* properties[] =
{
new DataProperty(PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, OT_IP_PARAMETER),
new DataProperty(PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t)OT_IP_PARAMETER),
new DataProperty(PID_PROJECT_INSTALLATION_ID, true, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv3),
new CallbackProperty<IpParameterObject>(this, PID_KNX_INDIVIDUAL_ADDRESS, true, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv3,
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
{
if(start == 0)
return 1;
// TODO: get property of deviceobject and use it
pushWord(io->_deviceObject.induvidualAddress(), data);
return 1;
},
@ -26,195 +29,84 @@ IpParameterObject::IpParameterObject(DeviceObject& deviceObject, Platform& platf
io->_deviceObject.induvidualAddress(getWord(data));
return 1;
}),
//55 PID_IP_ASSIGNMENT_METHOD 3 / 3
//56 PID_IP_CAPABILITIES 3 / 1
//57 PID_CURRENT_IP_ADDRESS 3 / x
//58 PID_CURRENT_SUBNET_MASK 3 / x
//59 PID_CURRENT_DEFAULT_GATEWAY 3 / x
//60 PID_IP_ADDRESS 3 / 3
//61 PID_SUBNET_MASK 3 / 3
//62 PID_DEFAULT_GATEWAY 3 / 3
//64 PID_MAC_ADDRESS 3 / x
//65 PID_SYSTEM_SETUP_MULTICAST_ADDRESS 3 / x
//66 PID_ROUTING_MULTICAST_ADDRESS 3 / 3
//67 PID_TTL 3 / 3
//68 PID_KNXNETIP_DEVICE_CAPABILITIES 3 / x
//76 PID_FRIENDLY_NAME 3 / 3
new DataProperty(PID_IP_ASSIGNMENT_METHOD, true, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv3),
new DataProperty(PID_IP_CAPABILITIES, true, PDT_BITSET8, 1, ReadLv3 | WriteLv1),
new CallbackProperty<IpParameterObject>(this, PID_CURRENT_IP_ADDRESS, false, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv0,
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
if(start == 0)
return 1;
pushInt(io->_platform.currentIpAddress(), data);
return 1;
}),
new CallbackProperty<IpParameterObject>(this, PID_CURRENT_SUBNET_MASK, false, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv0,
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
if(start == 0)
return 1;
pushInt(io->_platform.currentSubnetMask(), data);
return 1;
}),
new CallbackProperty<IpParameterObject>(this, PID_CURRENT_DEFAULT_GATEWAY, false, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv0,
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
if(start == 0)
return 1;
pushInt(io->_platform.currentDefaultGateway(), data);
return 1;
}),
new DataProperty(PID_IP_ADDRESS, true, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv3),
new DataProperty(PID_SUBNET_MASK, true, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv3),
new DataProperty(PID_DEFAULT_GATEWAY, true, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv3),
new CallbackProperty<IpParameterObject>(this, PID_MAC_ADDRESS, false, PDT_GENERIC_06, 1, ReadLv3 | WriteLv0,
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
if(start == 0)
return 1;
io->_platform.macAddress(data);
return 1;
}),
new CallbackProperty<IpParameterObject>(this, PID_SYSTEM_SETUP_MULTICAST_ADDRESS, false, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv0,
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
if(start == 0)
return 1;
pushInt(DEFAULT_MULTICAST_ADDR, data);
return 1;
}),
new DataProperty(PID_ROUTING_MULTICAST_ADDRESS, true, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv3, DEFAULT_MULTICAST_ADDR),
new DataProperty(PID_TTL, true, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv3, (uint8_t)16),
new CallbackProperty<IpParameterObject>(this, PID_KNXNETIP_DEVICE_CAPABILITIES, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0,
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
if(start == 0)
return 1;
pushWord(0x1, data);
return 1;
}),
new DataProperty(PID_FRIENDLY_NAME, true, PDT_UNSIGNED_CHAR, 30, ReadLv3 | WriteLv3)
};
initializeProperties(sizeof(properties), properties);
}
void IpParameterObject::readProperty(PropertyID propertyId, uint16_t start, uint8_t& count, uint8_t* data)
{
switch (propertyId)
{
case PID_IP_ASSIGNMENT_METHOD:
data[0] = _ipAssignmentMethod;
break;
case PID_IP_CAPABILITIES:
data[0] = _ipCapabilities;
break;
case PID_CURRENT_IP_ADDRESS:
pushInt(_platform.currentIpAddress(), data);
break;
case PID_CURRENT_SUBNET_MASK:
pushInt(_platform.currentSubnetMask(), data);
break;
case PID_CURRENT_DEFAULT_GATEWAY:
pushInt(_platform.currentDefaultGateway(), data);
break;
case PID_IP_ADDRESS:
pushInt(_ipAddress, data);
break;
case PID_SUBNET_MASK:
pushInt(_subnetMask, data);
break;
case PID_DEFAULT_GATEWAY:
pushInt(_defaultGateway, data);
break;
case PID_MAC_ADDRESS:
{
uint8_t macAddr[6] = { 0, 0, 0, 0, 0, 0 };
_platform.macAddress(macAddr);
pushByteArray(macAddr, 6, data);
break;
}
case PID_SYSTEM_SETUP_MULTICAST_ADDRESS:
pushInt(DEFAULT_MULTICAST_ADDR, data);
break;
case PID_ROUTING_MULTICAST_ADDRESS:
pushInt(_multicastAddress, data);
break;
case PID_TTL:
data[0] = ttl();
break;
case PID_KNXNETIP_DEVICE_CAPABILITIES:
data[0] = 0x1;
break;
case PID_FRIENDLY_NAME:
for (uint8_t i = start; i < start + count; i++)
data[i-start] = _friendlyName[i-1];
break;
default:
InterfaceObject::readProperty(propertyId, start, count, data);
break;
}
}
void IpParameterObject::writeProperty(PropertyID id, uint16_t start, uint8_t* data, uint8_t& count)
{
switch (id)
{
case PID_IP_ASSIGNMENT_METHOD:
_ipAssignmentMethod = data[0];
break;
case PID_IP_ADDRESS:
_ipAddress = getInt(data);
break;
case PID_SUBNET_MASK:
_subnetMask = getInt(data);
break;
case PID_DEFAULT_GATEWAY:
_defaultGateway = getInt(data);
break;
case PID_ROUTING_MULTICAST_ADDRESS:
_multicastAddress = getInt(data);
break;
case PID_TTL:
_ttl = data[0];
break;
case PID_FRIENDLY_NAME:
for (uint8_t i = start; i < start + count; i++)
_friendlyName[i-1] = data[i - start];
break;
default:
InterfaceObject::writeProperty(id, start, data, count);
break;
}
}
uint8_t IpParameterObject::propertySize(PropertyID id)
{
switch (id)
{
case PID_IP_ASSIGNMENT_METHOD:
case PID_LOAD_STATE_CONTROL:
case PID_IP_CAPABILITIES:
case PID_TTL:
case PID_KNXNETIP_DEVICE_CAPABILITIES:
case PID_FRIENDLY_NAME:
return 1;
case PID_KNX_INDIVIDUAL_ADDRESS:
return 2;
case PID_CURRENT_IP_ADDRESS:
case PID_CURRENT_SUBNET_MASK:
case PID_CURRENT_DEFAULT_GATEWAY:
case PID_IP_ADDRESS:
case PID_SUBNET_MASK:
case PID_DEFAULT_GATEWAY:
case PID_SYSTEM_SETUP_MULTICAST_ADDRESS:
case PID_ROUTING_MULTICAST_ADDRESS:
return 4;
case PID_MAC_ADDRESS:
return 6;
}
return InterfaceObject::propertySize(id);
}
uint8_t* IpParameterObject::save(uint8_t* buffer)
{
buffer = pushWord(_projectInstallationId, buffer);
buffer = pushByte(_ipAssignmentMethod, buffer);
buffer = pushByte(_ipCapabilities, buffer);
buffer = pushInt(_ipAddress, buffer);
buffer = pushInt(_subnetMask, buffer);
buffer = pushInt(_defaultGateway, buffer);
buffer = pushInt(_multicastAddress, buffer);
buffer = pushByte(_ttl, buffer);
buffer = pushByteArray((uint8_t*)_friendlyName, 30, buffer);
return buffer;
}
uint8_t* IpParameterObject::restore(uint8_t* buffer)
{
buffer = popWord(_projectInstallationId, buffer);
buffer = popByte(_ipAssignmentMethod, buffer);
buffer = popByte(_ipCapabilities, buffer);
buffer = popInt(_ipAddress, buffer);
buffer = popInt(_subnetMask, buffer);
buffer = popInt(_defaultGateway, buffer);
buffer = popInt(_multicastAddress, buffer);
buffer = popByte(_ttl, buffer);
buffer = popByteArray((uint8_t*)_friendlyName, 30, buffer);
return buffer;
}
uint32_t IpParameterObject::multicastAddress() const
{
if (_multicastAddress == 0)
return DEFAULT_MULTICAST_ADDR;
const Property* prop = property(PID_ROUTING_MULTICAST_ADDRESS);
return _multicastAddress;
}
uint8_t data[4];
uint8_t count = prop->read(1, 1, data);
static PropertyDescription _propertyDescriptions[] =
{
{ PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 },
{ PID_PROJECT_INSTALLATION_ID, true, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv3 },
};
static uint8_t _propertyDescriptionCount = sizeof(_propertyDescriptions) / sizeof(PropertyDescription);
uint32_t value = DEFAULT_MULTICAST_ADDR;
if (count == 1)
popInt(value, data);
uint8_t IpParameterObject::propertyDescriptionCount()
{
return _propertyDescriptionCount;
}
PropertyDescription* IpParameterObject::propertyDescriptions()
{
return _propertyDescriptions;
return value;
}
uint16_t IpParameterObject::saveSize()

View File

@ -3,32 +3,32 @@
#include <cstring>
PropertyID Property::Id()
PropertyID Property::Id() const
{
return _id;
}
bool Property::WriteEnable()
bool Property::WriteEnable() const
{
return _writeEnable;
}
PropertyDataType Property::Type()
PropertyDataType Property::Type() const
{
return _type;
}
uint16_t Property::MaxElements()
uint16_t Property::MaxElements() const
{
return _maxElements;
}
uint8_t Property::Access()
uint8_t Property::Access() const
{
return _access;
}
uint8_t Property::ElementSize()
uint8_t Property::ElementSize() const
{
switch (_type)
{

View File

@ -230,13 +230,13 @@ class Property : public SaveRestore
public:
Property(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access);
virtual ~Property();
PropertyID Id();
bool WriteEnable();
PropertyDataType Type();
uint16_t MaxElements();
uint8_t Access();
uint8_t ElementSize();
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) = 0;
PropertyID Id() const;
bool WriteEnable() const;
PropertyDataType Type() const;
uint16_t MaxElements() const;
uint8_t Access() const;
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, uint8_t* data) = 0;
protected:
PropertyID _id;

View File

@ -34,7 +34,7 @@ class SaveRestore
}
/**
* @return The number of byte the object needs to save its state.
* @return The maximum number of bytes the object needs to save its state.
*/
virtual uint16_t saveSize()
{