/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2023 Martin Preuss, all rights reserved. * * The license for this file can be found in the file COPYING which you * should have received along with this file. ****************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include "aqhome/msg_p.h" #include #include #include #include GWEN_LIST_FUNCTIONS(AQH_MSG, AQH_Msg) static uint8_t _calcChecksum(const uint8_t *ptr, uint8_t len); AQH_MSG *AQH_Msg_new() { AQH_MSG *msg; GWEN_NEW_OBJECT(AQH_MSG, msg); GWEN_LIST_INIT(AQH_MSG, msg); return msg; } void AQH_Msg_free(AQH_MSG *msg) { if (msg) { GWEN_LIST_FINI(AQH_MSG, msg); GWEN_FREE_OBJECT(msg); } } AQH_MSG *AQH_Msg_dup(const AQH_MSG *srcMsg) { AQH_MSG *msg; msg=AQH_Msg_new(); memmove(msg->buffer, srcMsg->buffer, AQH_MAXMSGSIZE); msg->bytesInBuffer=srcMsg->bytesInBuffer; msg->currentPos=srcMsg->currentPos; return msg; } uint8_t *AQH_Msg_GetBuffer(AQH_MSG *msg) { if (msg) return msg->buffer; return NULL; } const uint8_t *AQH_Msg_GetConstBuffer(const AQH_MSG *msg) { if (msg) return msg->buffer; return NULL; } uint8_t AQH_Msg_GetBytesInBuffer(const AQH_MSG *msg) { if (msg) return msg->bytesInBuffer; else return 0; } uint8_t AQH_Msg_GetCurrentPos(const AQH_MSG *msg) { if (msg) return msg->currentPos; else return 0; } int AQH_Msg_AddByte(AQH_MSG *msg, uint8_t b) { if (msg) { if ((msg->bytesInBuffercurrentPosbuffer[(msg->currentPos)++]=b; msg->bytesInBuffer++; return 0; } } return GWEN_ERROR_MEMORY_FULL; } int AQH_Msg_ReadNextByte(AQH_MSG *msg) { if (msg) { if ((msg->currentPoscurrentPosbytesInBuffer)) { return ((int)(msg->buffer[(msg->currentPos)++])) & 0xff; } } return GWEN_ERROR_EOF; } int AQH_Msg_IncCurrentPos(AQH_MSG *msg, uint8_t i) { if (msg) { if (((msg->currentPos+i)currentPos+i)bytesInBuffer)) { msg->currentPos+=i; return 0; } } return GWEN_ERROR_EOF; } int AQH_Msg_RewindCurrentPos(AQH_MSG *msg) { if (msg) { msg->currentPos=0; return 0; } return GWEN_ERROR_EOF; } int AQH_Msg_GetRemainingBytes(const AQH_MSG *msg) { if (msg) return msg->bytesInBuffer-msg->currentPos; return 0; } uint8_t AQH_Msg_GetDestAddress(const AQH_MSG *msg) { if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_DEST_ADDRESS) return msg->buffer[AQH_MSG_OFFS_ALL_DEST_ADDRESS]; return 0; } uint8_t AQH_Msg_GetMsgType(const AQH_MSG *msg) { if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_MSG_TYPE) return msg->buffer[AQH_MSG_OFFS_ALL_MSG_TYPE]; return 0; } uint8_t AQH_Msg_GetSourceAddress(const AQH_MSG *msg) { if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_SRC_ADDRESS) return msg->buffer[AQH_MSG_OFFS_ALL_SRC_ADDRESS]; return 0; } uint8_t AQH_Msg_GetMsgPayloadLen(const AQH_MSG *msg) { if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_PAYLOAD_LEN) return msg->buffer[AQH_MSG_OFFS_ALL_PAYLOAD_LEN]; return 0; } int AQH_Msg_IsMsgComplete(const AQH_MSG *msg) { if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_PAYLOAD_LEN) { uint8_t len; len=msg->buffer[AQH_MSG_OFFS_ALL_PAYLOAD_LEN]+AQH_MSG_OFFS_ALL_PAYLOAD_BEGIN+1; if (len>AQH_MAXMSGSIZE) return -1; else if (msg->bytesInBuffer>=len) return 1; } return 0; } int AQH_Msg_IsChecksumValid(const AQH_MSG *msg) { if (msg && AQH_Msg_IsMsgComplete(msg)) return (_calcChecksum(msg->buffer, msg->bytesInBuffer)==0)?1:0; return 0; } int AQH_Msg_AddChecksum(AQH_MSG *msg) { if (msg) { int rv; rv=AQH_Msg_AddByte(msg, _calcChecksum(msg->buffer, msg->bytesInBuffer)); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; } return 0; } return GWEN_ERROR_GENERIC; } void AQH_Msg_DumpToBuffer(const AQH_MSG *msg, GWEN_BUFFER *dbuf, const char *sText) { GWEN_Buffer_AppendArgs(dbuf, "0x%02x->0x%02x: %d %s\n", AQH_Msg_GetSourceAddress(msg), AQH_Msg_GetDestAddress(msg), AQH_Msg_GetMsgType(msg), sText); } uint8_t _calcChecksum(const uint8_t *ptr, uint8_t len) { int i; uint8_t x=0; for (i=0; i