Files
IoTManager/lib/MySensors/hal/transport/MyTransportHAL.cpp
Dmitry Borisenko cb50965c3b gatewayTransportSend
2022-12-01 02:10:06 +01:00

242 lines
6.9 KiB
C++

/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2019 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include "MyTransportHAL.h"
#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL)
#define TRANSPORT_HAL_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__) //!< debug
#else
#define TRANSPORT_HAL_DEBUG(x,...) //!< debug NULL
#endif
bool transportHALInit(void)
{
TRANSPORT_HAL_DEBUG(PSTR("THA:INIT\n"));
#if defined(MY_TRANSPORT_ENCRYPTION)
uint8_t transportPSK[16];
#if defined(MY_ENCRYPTION_SIMPLE_PASSWD)
(void)memset((void *)transportPSK, 0, sizeof(transportPSK));
(void)memcpy((void *)transportPSK, MY_ENCRYPTION_SIMPLE_PASSWD,
strnlen(MY_ENCRYPTION_SIMPLE_PASSWD, sizeof(transportPSK)));
#else
hwReadConfigBlock((void *)transportPSK, (void *)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS,
sizeof(transportPSK));
#endif
#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL)
hwDebugBuf2Str((const uint8_t *)transportPSK, sizeof(transportPSK));
TRANSPORT_HAL_DEBUG(PSTR("THA:INIT:PSK=%s\n"),hwDebugPrintStr);
#endif
#endif
bool result = transportInit();
#if defined(MY_TRANSPORT_ENCRYPTION)
#if defined(MY_RADIO_RFM69)
transportEncrypt((const char *)transportPSK);
#else
//set up AES-key
AES128CBCInit(transportPSK);
#endif
// Make sure it is purged from memory when set
(void)memset((void *)transportPSK, 0,
sizeof(transportPSK));
#endif
return result;
}
void transportHALSetAddress(const uint8_t address)
{
TRANSPORT_HAL_DEBUG(PSTR("THA:SAD:ADDR=%" PRIu8 "\n"), address);
transportSetAddress(address);
}
uint8_t transportHALGetAddress(void)
{
uint8_t result = transportGetAddress();
TRANSPORT_HAL_DEBUG(PSTR("THA:GAD:ADDR=%" PRIu8 "\n"), result);
return result;
}
bool transportHALDataAvailable(void)
{
bool result = transportDataAvailable();
#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL)
if (result) {
TRANSPORT_HAL_DEBUG(PSTR("THA:DATA:AVAIL\n"));
}
#endif
return result;
}
bool transportHALSanityCheck(void)
{
bool result = transportSanityCheck();
TRANSPORT_HAL_DEBUG(PSTR("THA:SAN:RES=%" PRIu8 "\n"), result);
return result;
}
bool transportHALReceive(MyMessage *inMsg, uint8_t *msgLength)
{
// set pointer to first byte of data structure
uint8_t *rx_data = &inMsg->last;
uint8_t payloadLength = transportReceive((void *)rx_data);
#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL)
hwDebugBuf2Str((const uint8_t *)rx_data, payloadLength);
TRANSPORT_HAL_DEBUG(PSTR("THA:RCV:MSG=%s\n"), hwDebugPrintStr);
#endif
#if defined(MY_TRANSPORT_ENCRYPTION) && !defined(MY_RADIO_RFM69)
TRANSPORT_HAL_DEBUG(PSTR("THA:RCV:DECRYPT\n"));
// has to be adjusted, WIP!
uint8_t IV[16] = { 0 };
// decrypt data
AES128CBCDecrypt(IV, (uint8_t *)rx_data, payloadLength);
#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL)
hwDebugBuf2Str((const uint8_t *)rx_data, payloadLength);
TRANSPORT_HAL_DEBUG(PSTR("THA:RCV:PLAIN=%s\n"), hwDebugPrintStr);
#endif
#endif
// Reject messages with incorrect protocol version
MyMessage tmp = *inMsg;
if (!tmp.isProtocolVersionValid()) {
setIndication(INDICATION_ERR_VERSION);
TRANSPORT_HAL_DEBUG(PSTR("!THA:RCV:PVER=%" PRIu8 "\n"),
tmp.getVersion()); // protocol version mismatch
return false;
}
*msgLength = tmp.getLength();
#if defined(MY_TRANSPORT_ENCRYPTION) && !defined(MY_RADIO_RFM69)
// payload length = a multiple of blocksize length for decrypted messages, i.e. cannot be used for payload length check
#else
// Reject payloads with incorrect length
const uint8_t expectedMessageLength = tmp.getExpectedMessageSize();
if (payloadLength != expectedMessageLength) {
setIndication(INDICATION_ERR_LENGTH);
TRANSPORT_HAL_DEBUG(PSTR("!THA:RCV:LEN=%" PRIu8 ",EXP=%" PRIu8 "\n"), payloadLength,
expectedMessageLength); // invalid payload length
return false;
}
#endif
TRANSPORT_HAL_DEBUG(PSTR("THA:RCV:MSG LEN=%" PRIu8 "\n"), payloadLength);
return true;
}
bool transportHALSend(const uint8_t nextRecipient, const MyMessage *outMsg, const uint8_t len,
const bool noACK)
{
if (outMsg == NULL) {
// nothing to send
return false;
}
#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL)
hwDebugBuf2Str((const uint8_t *)&outMsg->last, len);
TRANSPORT_HAL_DEBUG(PSTR("THA:SND:MSG=%s\n"), hwDebugPrintStr);
#endif
#if defined(MY_TRANSPORT_ENCRYPTION) && !defined(MY_RADIO_RFM69)
TRANSPORT_HAL_DEBUG(PSTR("THA:SND:ENCRYPT\n"));
uint8_t *tx_data[MAX_MESSAGE_SIZE];
// copy input data because it is read-only
(void)memcpy((void *)tx_data, (void *)&outMsg->last, len);
// We us IV vector filled with zeros but randomize unused bytes in encryption block
uint8_t IV[16] = { 0 };
const uint8_t finalLength = len > 16 ? 32 : 16;
// fill block with random data
for (uint8_t i = len; i < finalLength; i++) {
*((uint8_t *)tx_data + i) = random(256);
}
//encrypt data
AES128CBCEncrypt(IV, (uint8_t *)tx_data, finalLength);
#if defined(MY_DEBUG_VERBOSE_TRANSPORT_HAL)
hwDebugBuf2Str((const uint8_t *)tx_data, finalLength);
TRANSPORT_HAL_DEBUG(PSTR("THA:SND:CIP=%s\n"), hwDebugPrintStr);
#endif
#else
const uint8_t *tx_data = &outMsg->last;
const uint8_t finalLength = len;
#endif
bool result = transportSend(nextRecipient, (void *)tx_data, finalLength, noACK);
TRANSPORT_HAL_DEBUG(PSTR("THA:SND:MSG LEN=%" PRIu8 ",RES=%" PRIu8 "\n"), finalLength, result);
return result;
}
void transportHALPowerDown(void)
{
transportPowerDown();
}
void transportHALPowerUp(void)
{
transportPowerUp();
}
void transportHALSleep(void)
{
transportSleep();
}
void transportHALStandBy(void)
{
transportStandBy();
}
int16_t transportHALGetSendingRSSI(void)
{
int16_t result = transportGetSendingRSSI();
return result;
}
int16_t transportHALGetReceivingRSSI(void)
{
int16_t result = transportGetReceivingRSSI();
return result;
}
int16_t transportHALGetSendingSNR(void)
{
int16_t result = transportGetSendingSNR();
return result;
}
int16_t transportHALGetReceivingSNR(void)
{
int16_t result = transportGetReceivingSNR();
return result;
}
int16_t transportHALGetTxPowerPercent(void)
{
int16_t result = transportGetTxPowerPercent();
return result;
}
bool transportHALSetTxPowerPercent(const uint8_t powerPercent)
{
bool result = transportSetTxPowerPercent(powerPercent);
return result;
}
int16_t transportHALGetTxPowerLevel(void)
{
int16_t result = transportGetTxPowerLevel();
return result;
}