mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			345 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			345 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "group_object.h"
 | |
| 
 | |
| #include "datapoint_types.h"
 | |
| #include "../interface_object/group_object_table_object.h"
 | |
| #include "../bits.h"
 | |
| 
 | |
| #include <cstring>
 | |
| 
 | |
| #ifdef SMALL_GROUPOBJECT
 | |
|     GroupObjectUpdatedHandler GroupObject::_updateHandlerStatic = 0;
 | |
| #endif
 | |
| GroupObjectTableObject* GroupObject::_table = 0;
 | |
| 
 | |
| GroupObject::GroupObject()
 | |
| {
 | |
|     _data = 0;
 | |
|     _uninitialized = true;
 | |
|     _commFlag = Uninitialized;
 | |
|     _dataLength = 0;
 | |
| #ifndef SMALL_GROUPOBJECT
 | |
|     _updateHandler = 0;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| GroupObject::~GroupObject()
 | |
| {
 | |
|     if (_data)
 | |
|         delete[] _data;
 | |
| }
 | |
| 
 | |
| bool GroupObject::responseUpdateEnable()
 | |
| {
 | |
|     if (!_table)
 | |
|         return false;
 | |
| 
 | |
|     return bitRead(ntohs(_table->_tableData[_asap]), 15) > 0;
 | |
| }
 | |
| 
 | |
| bool GroupObject::transmitEnable()
 | |
| {
 | |
|     if (!_table)
 | |
|         return false;
 | |
| 
 | |
|     return bitRead(ntohs(_table->_tableData[_asap]), 14) > 0 ;
 | |
| }
 | |
| 
 | |
| bool GroupObject::valueReadOnInit()
 | |
| {
 | |
|     if (!_table)
 | |
|         return false;
 | |
| 
 | |
|     return bitRead(ntohs(_table->_tableData[_asap]), 13) > 0;
 | |
| }
 | |
| 
 | |
| bool GroupObject::writeEnable()
 | |
| {
 | |
|     if (!_table)
 | |
|         return false;
 | |
| 
 | |
|     return bitRead(ntohs(_table->_tableData[_asap]), 12) > 0 ;
 | |
| }
 | |
| 
 | |
| bool GroupObject::readEnable()
 | |
| {
 | |
|     if (!_table)
 | |
|         return false;
 | |
| 
 | |
|     // we forbid reading of new (uninitialized) go
 | |
|     if (_uninitialized)
 | |
|         return false;
 | |
| 
 | |
|     return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0;
 | |
| }
 | |
| 
 | |
| bool GroupObject::communicationEnable()
 | |
| {
 | |
|     if (!_table)
 | |
|         return false;
 | |
| 
 | |
|     return bitRead(ntohs(_table->_tableData[_asap]), 10) > 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| Priority GroupObject::priority()
 | |
| {
 | |
|     if (!_table)
 | |
|         return LowPriority;
 | |
| 
 | |
|     return (Priority)((ntohs(_table->_tableData[_asap]) >> 6) & (3 << 2)) ;
 | |
| }
 | |
| 
 | |
| uint8_t* GroupObject::valueRef()
 | |
| {
 | |
|     return _data;
 | |
| }
 | |
| 
 | |
| uint16_t GroupObject::asap()
 | |
| {
 | |
|     return _asap;
 | |
| }
 | |
| 
 | |
| size_t GroupObject::goSize()
 | |
| {
 | |
|     size_t size = sizeInTelegram();
 | |
| 
 | |
|     if (size == 0)
 | |
|         return 1;
 | |
| 
 | |
|     return size;
 | |
| }
 | |
| 
 | |
| // see knxspec 3.5.1 p. 178
 | |
| size_t GroupObject::asapValueSize(uint8_t code) const
 | |
| {
 | |
|     if (code < 7)
 | |
|         return 0;
 | |
| 
 | |
|     if (code < 8)
 | |
|         return 1;
 | |
| 
 | |
|     if (code < 11 || (code > 20 && code < 255))
 | |
|         return code - 6;
 | |
| 
 | |
|     switch (code)
 | |
|     {
 | |
|         case 11:
 | |
|             return 6;
 | |
| 
 | |
|         case 12:
 | |
|             return 8;
 | |
| 
 | |
|         case 13:
 | |
|             return 10;
 | |
| 
 | |
|         case 14:
 | |
|             return 14;
 | |
| 
 | |
|         case 15:
 | |
|             return 5;
 | |
| 
 | |
|         case 16:
 | |
|             return 7;
 | |
| 
 | |
|         case 17:
 | |
|             return 9;
 | |
| 
 | |
|         case 18:
 | |
|             return 11;
 | |
| 
 | |
|         case 19:
 | |
|             return 12;
 | |
| 
 | |
|         case 20:
 | |
|             return 13;
 | |
| 
 | |
|         case 255:
 | |
|             return 252;
 | |
|     }
 | |
| 
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| 
 | |
| ComFlag GroupObject::commFlag()
 | |
| {
 | |
|     return _commFlag;
 | |
| }
 | |
| 
 | |
| void GroupObject::commFlag(ComFlag value)
 | |
| {
 | |
|     _commFlag = value;
 | |
| 
 | |
|     if (value == WriteRequest || value == Updated || value == Ok)
 | |
|         _uninitialized = false;
 | |
| }
 | |
| 
 | |
| bool GroupObject::initialized()
 | |
| {
 | |
|     return !_uninitialized;
 | |
| }
 | |
| 
 | |
| void GroupObject::requestObjectRead()
 | |
| {
 | |
|     commFlag(ReadRequest);
 | |
| }
 | |
| 
 | |
| void GroupObject::objectWritten()
 | |
| {
 | |
|     commFlag(WriteRequest);
 | |
| }
 | |
| 
 | |
| size_t GroupObject::valueSize()
 | |
| {
 | |
|     return _dataLength;
 | |
| }
 | |
| 
 | |
| size_t GroupObject::sizeInTelegram()
 | |
| {
 | |
|     uint8_t code = lowByte(ntohs(_table->_tableData[_asap]));
 | |
|     return asapValueSize(code);
 | |
| }
 | |
| 
 | |
| size_t GroupObject::sizeInMemory() const
 | |
| {
 | |
|     uint8_t code = lowByte(ntohs(_table->_tableData[_asap]));
 | |
|     size_t result = asapValueSize(code);
 | |
| 
 | |
|     if (code == 0)
 | |
|         return 1;
 | |
| 
 | |
|     if (code == 14)
 | |
|         return 14 + 1;
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| #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;
 | |
| }
 | |
| 
 | |
| 
 | |
| GroupObjectUpdatedHandler GroupObject::callback()
 | |
| {
 | |
|     return _updateHandler;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void GroupObject::value(const KNXValue& value, const Dpt& type)
 | |
| {
 | |
|     valueNoSend(value, type);
 | |
|     objectWritten();
 | |
| }
 | |
| 
 | |
| 
 | |
| KNXValue GroupObject::value(const Dpt& type)
 | |
| {
 | |
|     KNXValue value = "";
 | |
|     KNX_Decode_Value(_data, _dataLength, type, value);
 | |
|     return value;
 | |
| }
 | |
| 
 | |
| 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;
 | |
| }
 | |
| 
 | |
| 
 | |
| Dpt GroupObject::dataPointType()
 | |
| {
 | |
|     return _datapointType;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool GroupObject::tryValue(KNXValue& value)
 | |
| {
 | |
|     return tryValue(value, _datapointType);
 | |
| }
 | |
| 
 | |
| 
 | |
| void GroupObject::value(const KNXValue& value)
 | |
| {
 | |
|     this->value(value, _datapointType);
 | |
| }
 | |
| 
 | |
| 
 | |
| KNXValue GroupObject::value()
 | |
| {
 | |
|     return value(_datapointType);
 | |
| }
 | |
| 
 | |
| 
 | |
| void GroupObject::valueNoSend(const KNXValue& value)
 | |
| {
 | |
|     valueNoSend(value, _datapointType);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type)
 | |
| {
 | |
|     if (_uninitialized)
 | |
|         commFlag(Ok);
 | |
| 
 | |
|     KNX_Encode_Value(value, _data, _dataLength, type);
 | |
| }
 | |
| 
 | |
| bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type)
 | |
| {
 | |
|     if (_uninitialized)
 | |
|     {
 | |
|         // always set first value
 | |
|         this->valueNoSend(value, type);
 | |
|         return true;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         // convert new value to given dtp
 | |
|         uint8_t newData[_dataLength];
 | |
|         memset(newData, 0, _dataLength);
 | |
|         KNX_Encode_Value(value, newData, _dataLength, type);
 | |
| 
 | |
|         // check for change in converted value / update value on change only
 | |
|         const bool dataChanged = memcmp(_data, newData, _dataLength);
 | |
| 
 | |
|         if (dataChanged)
 | |
|             memcpy(_data, newData, _dataLength);
 | |
| 
 | |
|         return dataChanged;
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool GroupObject::valueCompare(const KNXValue& value, const Dpt& type)
 | |
| {
 | |
|     if (valueNoSendCompare(value, type))
 | |
|     {
 | |
|         objectWritten();
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| } |