really still wip

This commit is contained in:
2025-12-28 12:23:11 +01:00
parent a48ef9d5e0
commit 31dda62474
33 changed files with 1721 additions and 589 deletions

View File

File diff suppressed because one or more lines are too long

View File

@@ -90,26 +90,28 @@
#define configMTIME_BASE_ADDRESS ( 0 )
#define configMTIMECMP_BASE_ADDRESS ( 0 )
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ SystemCoreClock
#define configTICK_RATE_HZ ( ( TickType_t ) 500 )
#define configMAX_PRIORITIES ( 15 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 1024 ) /* Can be as low as 60 but some of the demo tasks that use this constant require it to be higher. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024 ) )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 512 ) /* Can be as low as 60 but some of the demo tasks that use this constant require it to be higher. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 24* 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 1
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
/* Co-routine definitions. */
@@ -139,6 +141,7 @@ to exclude the API function. */
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_xSemaphoreGetMutexHolder 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
@@ -147,5 +150,7 @@ header file. */
/* Map to the platform printf function. */
#define configPRINT_STRING( pcString ) printf( pcString )
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue()
#endif /* FREERTOS_CONFIG_H */

250
User/lib/adc/temperature.c Normal file
View File

@@ -0,0 +1,250 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : temperature.c
* Author : WCH
* Version : V1.0.0
* Date : 2023/11/17
* Description : Temperature program body.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*
*@Note
*Internal temperature sensor routine:
*Through the ADC channel 16, the output voltage value and temperature value of the internal
*temperature sensor are collected.
*
*/
#include "debug.h"
#include "lib/telemetry/telemetry.h"
/* Global Variable */
s16 Calibrattion_Val = 0;
/*********************************************************************
* @fn ADC_Function_Init
*
* @brief Initializes ADC collection.
*
* @return none
*/
void ADC_Function_Init(void)
{
ADC_InitTypeDef ADC_InitStructure={0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
ADC_BufferCmd(ADC1, DISABLE); //disable buffer
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
Calibrattion_Val = Get_CalibrationValue(ADC1);
ADC_BufferCmd(ADC1, ENABLE); //enable buffer
ADC_TempSensorVrefintCmd(ENABLE);
}
/*********************************************************************
* @fn Get_ADC_Val
*
* @brief Returns ADCx conversion result data.
*
* @param ch - ADC channel.
* ADC_Channel_0 - ADC Channel0 selected.
* ADC_Channel_1 - ADC Channel1 selected.
* ADC_Channel_2 - ADC Channel2 selected.
* ADC_Channel_3 - ADC Channel3 selected.
* ADC_Channel_4 - ADC Channel4 selected.
* ADC_Channel_5 - ADC Channel5 selected.
* ADC_Channel_6 - ADC Channel6 selected.
* ADC_Channel_7 - ADC Channel7 selected.
* ADC_Channel_8 - ADC Channel8 selected.
* ADC_Channel_9 - ADC Channel9 selected.
* ADC_Channel_10 - ADC Channel10 selected.
* ADC_Channel_11 - ADC Channel11 selected.
* ADC_Channel_12 - ADC Channel12 selected.
* ADC_Channel_13 - ADC Channel13 selected.
* ADC_Channel_14 - ADC Channel14 selected.
* ADC_Channel_15 - ADC Channel15 selected.
* ADC_Channel_16 - ADC Channel16 selected.
* ADC_Channel_17 - ADC Channel17 selected.
*
* @return none
*/
u16 Get_ADC_Val(u8 ch)
{
u16 val;
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
val = ADC_GetConversionValue(ADC1);
return val;
}
/*********************************************************************
* @fn Get_ADC_Average
*
* @brief Returns ADCx conversion result average data.
*
* @param ch - ADC channel.
* ADC_Channel_0 - ADC Channel0 selected.
* ADC_Channel_1 - ADC Channel1 selected.
* ADC_Channel_2 - ADC Channel2 selected.
* ADC_Channel_3 - ADC Channel3 selected.
* ADC_Channel_4 - ADC Channel4 selected.
* ADC_Channel_5 - ADC Channel5 selected.
* ADC_Channel_6 - ADC Channel6 selected.
* ADC_Channel_7 - ADC Channel7 selected.
* ADC_Channel_8 - ADC Channel8 selected.
* ADC_Channel_9 - ADC Channel9 selected.
* ADC_Channel_10 - ADC Channel10 selected.
* ADC_Channel_11 - ADC Channel11 selected.
* ADC_Channel_12 - ADC Channel12 selected.
* ADC_Channel_13 - ADC Channel13 selected.
* ADC_Channel_14 - ADC Channel14 selected.
* ADC_Channel_15 - ADC Channel15 selected.
* ADC_Channel_16 - ADC Channel16 selected.
* ADC_Channel_17 - ADC Channel17 selected.
*
* @return val - The Data conversion value.
*/
u16 Get_ADC_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
u16 val;
for(t=0;t<times;t++)
{
temp_val+=Get_ADC_Val(ch);
Delay_Ms(5);
}
val = temp_val/times;
return val;
}
/*********************************************************************
* @fn Get_ConversionVal
*
* @brief Get Conversion Value.
*
* @param val - Sampling value
*
* @return val+Calibrattion_Val - Conversion Value.
*/
u16 Get_ConversionVal(s16 val)
{
if((val+Calibrattion_Val)<0|| val==0) return 0;
if((Calibrattion_Val+val)>4095||val==4095) return 4095;
return (val+Calibrattion_Val);
}
s32 TempSensor_Volt_To_Temper_x10(s32 Value)
{
s32 Temper_x10;
s32 Refer_Volt, Refer_Temper;
s32 k = 43; // slope in mV/¡ãC
// Read factory calibration values
Refer_Volt = (s32)((*(u32 *)0x1FFFF720) & 0x0000FFFF); // mV at reference temp
Refer_Temper = (s32)(((*(u32 *)0x1FFFF720) >> 16) & 0x0000FFFF); // ¡ãC
// Compute temperature in decicelsius
// Formula: T_x10 = Tref*10 - ((V - Vref)*100 + k/2) / k
// Multiply (V - Vref) by 100 to get tenths of ¡ãC
Temper_x10 = Refer_Temper * 10 - ((Value - Refer_Volt) * 100 + (k / 2)) / k;
return Temper_x10;
}
s32 getTemperature(void)
{
u16 ADC_val;
s32 val_mv;
ADC_val = Get_ADC_Average( ADC_Channel_TempSensor, 10 );
ADC_val = Get_ConversionVal(ADC_val);
val_mv = (ADC_val*3300/4096);
return TempSensor_Volt_To_Temper(val_mv);
}
s16 getDeciTemperature(void)
{
u16 ADC_val;
s32 val_mv;
ADC_val = Get_ADC_Average( ADC_Channel_TempSensor, 10 );
ADC_val = Get_ConversionVal(ADC_val);
val_mv = (ADC_val*3300/4096);
s32 temp_x10 = TempSensor_Volt_To_Temper_x10(val_mv);
int16_t temp16 = (int16_t)temp_x10; // store in 2 bytes
return temp16;
}
s32 getVoltage(void)
{
u16 ADC_val;
s32 val_mv;
ADC_val = Get_ADC_Average( ADC_Channel_0, 10 );
ADC_val = Get_ConversionVal(ADC_val);
val_mv = (ADC_val*3300/4096);
return val_mv;
}
// Helper: convert signed 24-bit int to 3 bytes (big-endian)
void int24_to_bytes(int32_t value, uint8_t *bytes) {
if (value < 0) value += 0x1000000; // 2's complement for 24-bit
bytes[0] = (value >> 16) & 0xFF;
bytes[1] = (value >> 8) & 0xFF;
bytes[2] = value & 0xFF;
}
// Encode GPS into CayenneLPP payload
void encode_gps(uint8_t channel, float lat, float lon, float alt, uint8_t *payload) {
payload[0] = channel;
payload[1] = LPP_GPS; // GPS type
int32_t latInt = lat * 10000;
int32_t lonInt = lon * 10000;
int32_t altInt = alt * 100;
int24_to_bytes(latInt, &payload[2]);
int24_to_bytes(lonInt, &payload[5]);
int24_to_bytes(altInt, &payload[8]);
}

113
User/lib/adc/temperature.h Normal file
View File

@@ -0,0 +1,113 @@
#ifndef TEMPERATURE_HEADER
#define TEMPERATURE_HEADER
/********************************** (C) COPYRIGHT *******************************
* File Name : temperature.c
* Author : WCH
* Version : V1.0.0
* Date : 2023/11/17
* Description : Temperature program body.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*
*@Note
*Internal temperature sensor routine:
*Through the ADC channel 16, the output voltage value and temperature value of the internal
*temperature sensor are collected.
*
*/
/* Global Variable */
extern s16 Calibrattion_Val;
/*********************************************************************
* @fn ADC_Function_Init
*
* @brief Initializes ADC collection.
*
* @return none
*/
void ADC_Function_Init(void);
/*********************************************************************
* @fn Get_ADC_Val
*
* @brief Returns ADCx conversion result data.
*
* @param ch - ADC channel.
* ADC_Channel_0 - ADC Channel0 selected.
* ADC_Channel_1 - ADC Channel1 selected.
* ADC_Channel_2 - ADC Channel2 selected.
* ADC_Channel_3 - ADC Channel3 selected.
* ADC_Channel_4 - ADC Channel4 selected.
* ADC_Channel_5 - ADC Channel5 selected.
* ADC_Channel_6 - ADC Channel6 selected.
* ADC_Channel_7 - ADC Channel7 selected.
* ADC_Channel_8 - ADC Channel8 selected.
* ADC_Channel_9 - ADC Channel9 selected.
* ADC_Channel_10 - ADC Channel10 selected.
* ADC_Channel_11 - ADC Channel11 selected.
* ADC_Channel_12 - ADC Channel12 selected.
* ADC_Channel_13 - ADC Channel13 selected.
* ADC_Channel_14 - ADC Channel14 selected.
* ADC_Channel_15 - ADC Channel15 selected.
* ADC_Channel_16 - ADC Channel16 selected.
* ADC_Channel_17 - ADC Channel17 selected.
*
* @return none
*/
u16 Get_ADC_Val(u8 ch);
/*********************************************************************
* @fn Get_ADC_Average
*
* @brief Returns ADCx conversion result average data.
*
* @param ch - ADC channel.
* ADC_Channel_0 - ADC Channel0 selected.
* ADC_Channel_1 - ADC Channel1 selected.
* ADC_Channel_2 - ADC Channel2 selected.
* ADC_Channel_3 - ADC Channel3 selected.
* ADC_Channel_4 - ADC Channel4 selected.
* ADC_Channel_5 - ADC Channel5 selected.
* ADC_Channel_6 - ADC Channel6 selected.
* ADC_Channel_7 - ADC Channel7 selected.
* ADC_Channel_8 - ADC Channel8 selected.
* ADC_Channel_9 - ADC Channel9 selected.
* ADC_Channel_10 - ADC Channel10 selected.
* ADC_Channel_11 - ADC Channel11 selected.
* ADC_Channel_12 - ADC Channel12 selected.
* ADC_Channel_13 - ADC Channel13 selected.
* ADC_Channel_14 - ADC Channel14 selected.
* ADC_Channel_15 - ADC Channel15 selected.
* ADC_Channel_16 - ADC Channel16 selected.
* ADC_Channel_17 - ADC Channel17 selected.
*
* @return val - The Data conversion value.
*/
u16 Get_ADC_Average(u8 ch,u8 times);
/*********************************************************************
* @fn Get_ConversionVal
*
* @brief Get Conversion Value.
*
* @param val - Sampling value
*
* @return val+Calibrattion_Val - Conversion Value.
*/
u16 Get_ConversionVal(s16 val);
s32 getTemperature(void);
s16 getDeciTemperature(void);
s32 getVoltage(void);
void encode_gps(uint8_t channel, float lat, float lon, float alt, uint8_t *payload);
#endif

View File

@@ -9,32 +9,23 @@
#define AESKeyCount 8
#define CONTACT_COUNT 100
typedef struct {
char name[32];
unsigned char pubKey[32];
unsigned char secret[32];
int32_t gps_latitude;
int32_t gps_longitude;
Path path;
uint8_t flags;
uint8_t type;
uint8_t authenticated;
uint32_t last_seen_rt; //remote timestamp
uint32_t last_seen_lt; //local timestamp
uint32_t sync_timestamp;
} NodeEntry;
typedef struct {
uint32_t magic; // e.g. 0xDEADBEEF
uint8_t privkey[32]; // Ed25519 private
uint8_t pubkey[32]; // Ed25519 public
uint8_t nodeType;
int32_t latitude;
int32_t longitude;
int32_t altitude;
int8_t txPowerInDbm;
uint32_t frequencyInHz;
uint8_t spreadingFactor;
uint8_t bandwidth;
uint8_t codingRate;
uint16_t preambleLength;
float tcxoVoltage;
uint8_t aesKeys[AESKeyCount][17];
uint8_t password[16];
char nodeName[32];

View File

@@ -4,34 +4,21 @@
// Nightcracker's Ed25519 - https://github.com/orlp/ed25519
#include <stddef.h>
#if defined(_WIN32)
#if defined(ED25519_BUILD_DLL)
#define ED25519_DECLSPEC __declspec(dllexport)
#elif defined(ED25519_DLL)
#define ED25519_DECLSPEC __declspec(dllimport)
#else
#define ED25519_DECLSPEC
#endif
#else
#define ED25519_DECLSPEC
#endif
#include "meshcore/packetstructs.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ED25519_NO_SEED
int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed);
#endif
void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
void ED25519_DECLSPEC ed25519_derive_pub(unsigned char *public_key, const unsigned char *private_key);
void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key);
void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
void ed25519_derive_pub(unsigned char *public_key, const unsigned char *private_key);
void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
void ed25519_sign_ad(FrameStruct *frame);
int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key);
int ed25519_verify_ad(const FrameStruct *frame);
void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
#ifdef __cplusplus

View File

@@ -1,40 +0,0 @@
#include "ed_25519.h"
#ifndef ED25519_NO_SEED
#ifdef _WIN32
#include <windows.h>
#include <wincrypt.h>
#else
#include <stdio.h>
#endif
int ed25519_create_seed(unsigned char *seed) {
#ifdef _WIN32
HCRYPTPROV prov;
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
return 1;
}
if (!CryptGenRandom(prov, 32, seed)) {
CryptReleaseContext(prov, 0);
return 1;
}
CryptReleaseContext(prov, 0);
#else
FILE *f = fopen("/dev/urandom", "rb");
if (f == NULL) {
return 1;
}
fread(seed, 1, 32, f);
fclose(f);
#endif
return 0;
}
#endif

View File

@@ -1,4 +1,5 @@
#include "ed_25519.h"
#include "lib/config.h"
#include "sha512.h"
#include "ge.h"
#include "sc.h"
@@ -29,3 +30,35 @@ void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t
sc_reduce(hram);
sc_muladd(signature + 32, hram, private_key, r);
}
void ed25519_sign_ad(FrameStruct *frame) {
sha512_context hash;
unsigned char hram[64];
unsigned char r[64];
ge_p3 R;
unsigned char *signature = &(frame->payload[36]);
sha512_init(&hash);
sha512_update(&hash, persistent.privkey + 32, 32);
sha512_update(&hash, frame->payload, 32);
sha512_update(&hash, frame->payload, 36); // pubkey and timestamp combined (32 bytes pubkey, 4 bytes timestamp)
sha512_update(&hash, &(frame->payload[100]), frame->payloadLen - 100);
sha512_final(&hash, r);
sc_reduce(r);
ge_scalarmult_base(&R, r);
ge_p3_tobytes(signature, &R);
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, frame->payload, 32);
sha512_update(&hash, frame->payload, 36); // pubkey and timestamp combined (32 bytes pubkey, 4 bytes timestamp)
sha512_update(&hash, &(frame->payload[100]), frame->payloadLen - 100);
sha512_final(&hash, hram);
sc_reduce(hram);
sc_muladd(signature + 32, hram, persistent.privkey, r);
}

View File

@@ -75,3 +75,38 @@ int ed25519_verify(const unsigned char *signature, const unsigned char *message,
return 1;
}
int ed25519_verify_ad(const FrameStruct *frame) {
unsigned char h[64];
unsigned char checker[32];
sha512_context hash;
ge_p3 A;
ge_p2 R;
const unsigned char *signature = &(frame->payload[36]);
if (signature[63] & 224) {
return 0;
}
if (ge_frombytes_negate_vartime(&A, frame->payload) != 0) { //pubkey is at start
return 0;
}
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, frame->payload, 32);
sha512_update(&hash, frame->payload, 36); // pubkey and timestamp combined (32 bytes pubkey, 4 bytes timestamp)
sha512_update(&hash, &(frame->payload[100]), frame->payloadLen - 100);
sha512_final(&hash, h);
sc_reduce(h);
ge_double_scalarmult_vartime(&R, h, &A, signature + 32);
ge_tobytes(checker, &R);
if (!consttime_equal(checker, signature)) {
return 0;
}
return 1;
}

View File

View File

@@ -0,0 +1,93 @@
#ifndef TELEMETRY_HEADER
#define TELEMETRY_HEADER
#define TELEM_CHANNEL_SELF 1 // LPP data channel for 'self' device
#define LPP_DIGITAL_INPUT 0 // 1 byte
#define LPP_DIGITAL_OUTPUT 1 // 1 byte
#define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed
#define LPP_ANALOG_OUTPUT 3 // 2 bytes, 0.01 signed
#define LPP_GENERIC_SENSOR 100 // 4 bytes, unsigned
#define LPP_LUMINOSITY 101 // 2 bytes, 1 lux unsigned
#define LPP_PRESENCE 102 // 1 byte, bool
#define LPP_TEMPERATURE 103 // 2 bytes, 0.1¡ãC signed
#define LPP_RELATIVE_HUMIDITY 104 // 1 byte, 0.5% unsigned
#define LPP_ACCELEROMETER 113 // 2 bytes per axis, 0.001G
#define LPP_BAROMETRIC_PRESSURE 115 // 2 bytes 0.1hPa unsigned
#define LPP_VOLTAGE 116 // 2 bytes 0.01V unsigned
#define LPP_CURRENT 117 // 2 bytes 0.001A unsigned
#define LPP_FREQUENCY 118 // 4 bytes 1Hz unsigned
#define LPP_PERCENTAGE 120 // 1 byte 1-100% unsigned
#define LPP_ALTITUDE 121 // 2 byte 1m signed
#define LPP_CONCENTRATION 125 // 2 bytes, 1 ppm unsigned
#define LPP_POWER 128 // 2 byte, 1W, unsigned
#define LPP_DISTANCE 130 // 4 byte, 0.001m, unsigned
#define LPP_ENERGY 131 // 4 byte, 0.001kWh, unsigned
#define LPP_DIRECTION 132 // 2 bytes, 1deg, unsigned
#define LPP_UNIXTIME 133 // 4 bytes, unsigned
#define LPP_GYROMETER 134 // 2 bytes per axis, 0.01 ¡ã/s
#define LPP_COLOUR 135 // 1 byte per RGB Color
#define LPP_GPS 136 // 3 byte lon/lat 0.0001 ¡ã, 3 bytes alt 0.01 meter
#define LPP_SWITCH 142 // 1 byte, 0/1
#define LPP_POLYLINE 240 // 1 byte size, 1 byte delta factor, 3 byte lon/lat 0.0001¡ã * factor, n (size-8) bytes deltas
// Only Data Size
#define LPP_DIGITAL_INPUT_SIZE 1
#define LPP_DIGITAL_OUTPUT_SIZE 1
#define LPP_ANALOG_INPUT_SIZE 2
#define LPP_ANALOG_OUTPUT_SIZE 2
#define LPP_GENERIC_SENSOR_SIZE 4
#define LPP_LUMINOSITY_SIZE 2
#define LPP_PRESENCE_SIZE 1
#define LPP_TEMPERATURE_SIZE 2
#define LPP_RELATIVE_HUMIDITY_SIZE 1
#define LPP_ACCELEROMETER_SIZE 6
#define LPP_BAROMETRIC_PRESSURE_SIZE 2
#define LPP_VOLTAGE_SIZE 2
#define LPP_CURRENT_SIZE 2
#define LPP_FREQUENCY_SIZE 4
#define LPP_PERCENTAGE_SIZE 1
#define LPP_ALTITUDE_SIZE 2
#define LPP_POWER_SIZE 2
#define LPP_DISTANCE_SIZE 4
#define LPP_ENERGY_SIZE 4
#define LPP_DIRECTION_SIZE 2
#define LPP_UNIXTIME_SIZE 4
#define LPP_GYROMETER_SIZE 6
#define LPP_GPS_SIZE 9
#define LPP_SWITCH_SIZE 1
#define LPP_CONCENTRATION_SIZE 2
#define LPP_COLOUR_SIZE 3
#define LPP_MIN_POLYLINE_SIZE 8
// Multipliers
#define LPP_DIGITAL_INPUT_MULT 1
#define LPP_DIGITAL_OUTPUT_MULT 1
#define LPP_ANALOG_INPUT_MULT 100
#define LPP_ANALOG_OUTPUT_MULT 100
#define LPP_GENERIC_SENSOR_MULT 1
#define LPP_LUMINOSITY_MULT 1
#define LPP_PRESENCE_MULT 1
#define LPP_TEMPERATURE_MULT 10
#define LPP_RELATIVE_HUMIDITY_MULT 2
#define LPP_ACCELEROMETER_MULT 1000
#define LPP_BAROMETRIC_PRESSURE_MULT 10
#define LPP_VOLTAGE_MULT 100
#define LPP_CURRENT_MULT 1000
#define LPP_FREQUENCY_MULT 1
#define LPP_PERCENTAGE_MULT 1
#define LPP_ALTITUDE_MULT 1
#define LPP_POWER_MULT 1
#define LPP_DISTANCE_MULT 1000
#define LPP_ENERGY_MULT 1000
#define LPP_DIRECTION_MULT 1
#define LPP_UNIXTIME_MULT 1
#define LPP_GYROMETER_MULT 100
#define LPP_GPS_LAT_LON_MULT 10000
#define LPP_GPS_ALT_MULT 100
#define LPP_SWITCH_MULT 1
#define LPP_CONCENTRATION_MULT 1
#define LPP_COLOUR_MULT 1
#endif

View File

@@ -18,24 +18,52 @@
#include "FreeRTOS.h"
#include "meshcore/meshframing.h"
#include "meshcore/packets/advert.h"
#include "meshcore/packets/control.h"
#include "meshcore/packets/encrypted.h"
#include "meshcore/packets/group.h"
#include "task.h"
#include "meshcore/packetstructs.h"
#include "sx1262.h"
#include "util/hexdump.h"
#include "util/log.h"
#include "string.h"
#include "meshcore/meshcore.h"
#include "lib/config.h"
#include "lib/rtc/rtc.h"
#include "lib/ed25519/ed_25519.h"
#include "meshcore/stats.h"
#include "lib/adc/temperature.h"
#define TAG "MeshCore"
static TIM_TypeDef *runtimeTIM = TIM2; // use TIM2 for example
void vConfigureTimerForRunTimeStats (void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// Reset the timer
TIM_DeInit (runtimeTIM);
// Set timer for max period, upcounting
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // Assuming 72 MHz clock -> 1 MHz timer tick (1 ?s)
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // Max 16-bit value
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit (runtimeTIM, &TIM_TimeBaseStructure);
TIM_Cmd (runtimeTIM, ENABLE);
}
uint32_t ulGetRunTimeCounterValue (void) {
return TIM_GetCounter (runtimeTIM);
}
/* Global define */
#define TASK1_TASK_PRIO 5
#define TASK1_STK_SIZE 2048
#define TASK1_STK_SIZE 1024
/* Global Variable */
TaskHandle_t Task1Task_Handler;
@@ -51,12 +79,20 @@ TaskHandle_t Task2Task_Handler;
* @return none
*/
uint8_t bufIn[256];
// uint8_t bufIn[260];
void task2_task (void *pvParameters) {
MESH_LOGD (TAG, "Task2 boot0");
RTC_Init();
startupTime = RTC_GetCounter();
memset (&stats, 0, sizeof (stats));
MESH_LOGD (TAG, "Task2 boot1");
ADC_Function_Init();
MESH_LOGD (TAG, "Task2 boot2");
// ed25519_create_keypair (persistent.pubkey, persistent.privkey, "vFt0FRugSOeqnkshImMCVfgHM5vBxz4");
ed25519_create_keypair (persistent.pubkey, persistent.privkey, "vFt0FRugSOeqnkshImMCVfgHM5vBxz3");
MESH_LOGD (TAG, "Task2 boot3");
// persistent.nodeType = NODE_TYPE_CHAT_NODE;
persistent.nodeType = NODE_TYPE_REPEATER;
memset (persistent.password, 0, sizeof (persistent.password));
@@ -75,21 +111,38 @@ void task2_task (void *pvParameters) {
memcpy (persistent.aesKeys, aesKeysDefault, sizeof (persistent.aesKeys));
sendAdvert();
// sendAdvert();
DiscoverRequestPayload discReq;
discReq.prefixOnly = 0;
discReq.since = 0;
discReq.tag = RTC_GetCounter();
discReq.typeFilter = 0xFF;
sendDiscoverRequest (&discReq);
persistent.latitude = 48190900;
persistent.longitude = 17030300;
persistent.altitude = 23400;
char x;
MESH_LOGD (TAG, "Task2 boot");
while (1) {
if (USART_GetFlagStatus (USART1, USART_FLAG_RXNE) == SET) {
x = USART_ReceiveData (USART1);
if (x == 'M') {
printf ("Sending message\n");
MESH_LOGI (TAG, "Sending message\n");
char tempBuf[180];
snprintf (tempBuf, 180, "SySTick is %d", xTaskGetTickCount());
makeSendGroupMessage (tempBuf, 1);
}
if (x == 'A') {
printf ("Sending advert\n");
sendAdvert();
if (x == '0') {
MESH_LOGI (TAG, "Sending zero hop advert\n");
sendAdvert (0);
}
if (x == 'F') {
MESH_LOGI (TAG, "Sending flood advert\n");
sendAdvert (1);
}
if (x == 'N') {
printNodeDB();
@@ -113,30 +166,31 @@ void task1_task (void *pvParameters) {
const int64_t interval_ms = 10; // 10 ms
int64_t start_time, end_time, elapsed;
ESP_LOGW (TAG, "LoraInit");
MESH_LOGW (TAG, "LoraInit");
LoRaInit();
int8_t txPowerInDbm = 20;
uint32_t frequencyInHz = 869554000;
ESP_LOGW (TAG, "Enable TCXO");
uint8_t spreadingFactor = 8;
uint8_t bandwidth = SX126X_LORA_BW_62_5;
uint8_t codingRate = SX126X_LORA_CR_4_8;
uint16_t preambleLength = 16;
float tcxoVoltage = 2.2; // ebyte
// float tcxoVoltage = 1.8; // heltec
MESH_LOGW (TAG, "Enable TCXO");
char useRegulatorLDO = 1;
LoRaDebugPrint (0);
ESP_LOGW (TAG, "Starting lora");
MESH_LOGW (TAG, "Starting lora");
uint16_t loraBeginStat = LoRaBegin (frequencyInHz, txPowerInDbm, tcxoVoltage, useRegulatorLDO);
if (loraBeginStat != 0) {
ESP_LOGE (TAG, "Does not recognize the module");
MESH_LOGE (TAG, "Does not recognize the module");
while (1) {
vTaskDelay (pdMS_TO_TICKS (1000));
}
}
uint8_t spreadingFactor = 8;
uint8_t bandwidth = SX126X_LORA_BW_62_5;
uint8_t codingRate = SX126X_LORA_CR_4_8;
uint16_t preambleLength = 16;
char crcOn = 1;
char invertIrq = 0;
@@ -146,22 +200,25 @@ void task1_task (void *pvParameters) {
while (1) {
start_time = xTaskGetTickCount();
uint8_t rxLen = LoRaReceive (bufIn, sizeof (bufIn));
if (rxLen > 0) {
// ESP_LOGI (TAG, "%d byte packet received", rxLen);
int8_t rssi, snr;
GetPacketStatus (&rssi, &snr);
ESP_LOGI (TAG, "rssi=%d[dBm] snr=%d[dB]", rssi, snr);
int8_t rssi, snr, rawsnr;
FrameStruct frame;
frame = decodeFrame (bufIn, rxLen);
processFrame (frame);
if (ReadFrame (&frame, &rssi, &snr, &rawsnr)) {
hexdump ("Whole frame", frame.payload, frame.payloadLen);
stats.lastSNR = rawsnr;
// stats.lastSNR = snr; //TODO figure out which to use
stats.lastRSSI = rssi;
MESH_LOGI (TAG, "rssi=%d[dBm] snr=%d[dB] rawsnr=%d[quarter dB]", rssi, snr, rawsnr);
// frame = decodeFrame (bufIn, rxLen);
MESH_LOGD (TAG, "Free stack before processFrame: %u bytes", uxTaskGetStackHighWaterMark (NULL) * 4);
processFrame (&frame);
MESH_LOGD (TAG, "Free stack before retransmitFrame: %u bytes", uxTaskGetStackHighWaterMark (NULL) * 4);
retransmitFrame (&frame);
memset (&frame, 0, sizeof (FrameStruct)); // prepare for the next round
}
int lost = GetPacketLost();
if (lost != 0) {
ESP_LOGW (TAG, "%d packets lost", lost);
MESH_LOGW (TAG, "%d packets lost", lost);
}
end_time = xTaskGetTickCount();
@@ -174,7 +231,9 @@ void task1_task (void *pvParameters) {
}
void vApplicationStackOverflowHook (TaskHandle_t xTask, char *pcTaskName) {
printf ("stackoverflow");
UBaseType_t minFree = uxTaskGetStackHighWaterMark (xTask);
MESH_LOGE (TAG, "Stack overflow in task '%s' (%p)! Minimum free stack: %u words (%u bytes)",
pcTaskName, xTask, minFree, minFree * 4);
}
/*********************************************************************
@@ -218,9 +277,9 @@ int main (void) {
USART_Cmd (USART1, ENABLE);
printf ("SystemClk:%d\r\n", SystemCoreClock);
printf ("ChipID:%08x\r\n", DBGMCU_GetCHIPID());
printf ("FreeRTOS Kernel Version:%s\r\n", tskKERNEL_VERSION_NUMBER);
MESH_LOGD (TAG, "SystemClk:%d\r\n", SystemCoreClock);
MESH_LOGD (TAG, "ChipID:%08x\r\n", DBGMCU_GetCHIPID());
MESH_LOGD (TAG, "FreeRTOS Kernel Version:%s\r\n", tskKERNEL_VERSION_NUMBER);
xTaskCreate ((TaskFunction_t)task1_task,
(const char *)"task1",
@@ -231,7 +290,7 @@ int main (void) {
xTaskCreate ((TaskFunction_t)task2_task,
(const char *)"task2",
(uint16_t)1024,
(uint16_t)TASK1_STK_SIZE,
(void *)NULL,
(UBaseType_t)TASK1_TASK_PRIO,
(TaskHandle_t *)&Task2Task_Handler);
@@ -240,6 +299,6 @@ int main (void) {
vTaskStartScheduler();
while (1) {
printf ("shouldn't run at here!!\n");
MESH_LOGE (TAG, "shouldn't run at here!!\n");
}
}

View File

@@ -6,6 +6,7 @@
#include "meshcore/packets/control.h"
#include "meshcore/packets/encrypted.h"
#include "meshcore/packets/group.h"
#include "meshcore/stats.h"
#include "task.h"
#include "lib/base64.h"
#include "lib/cifra/aes.h"
@@ -13,52 +14,54 @@
#include "lib/cifra/hmac.h"
#include "lib/config.h"
#include "meshframing.h"
#include "meshcore/packetstructs.h"
#define TAG "MeshCore"
// requires at least a 256 byte data
void processFrame (FrameStruct frame) {
void processFrame (const FrameStruct *frame) {
printFrameHeader (frame);
if (frame.header & PAYLOAD_VERSION_3) { // more than the version 0
ESP_LOGW (TAG, "Frame too new, got version %d instead of 0", (frame.header & PAYLOAD_VERSION_3) >> 6);
if (frame->header & PAYLOAD_VERSION_3) { // more than the version 0
MESH_LOGW (TAG, "Frame too new, got version %d instead of 0", (frame->header & PAYLOAD_VERSION_3) >> 6);
}
unsigned char checkSumBuf[10];
AdvertisementPayload advert;
GroupTextMessage msg;
unsigned char frameType = frame.header & PAYLOAD_TYPE_MASK;
unsigned char frameType = frame->header & PAYLOAD_TYPE_MASK;
unsigned char index = 0;
stats.packetsReceivedCount++;
if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD ||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
stats.receivedFloodCount++;
}
if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_DIRECT ||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT) {
stats.receivedDirectCount++;
}
if (frameType == PAYLOAD_TYPE_ANON_REQ) {
decodeAnonReq (frame);
} else if (frameType == PAYLOAD_TYPE_PATH || frameType == PAYLOAD_TYPE_REQ || frameType == PAYLOAD_TYPE_RESPONSE || frameType == PAYLOAD_TYPE_TXT_MSG) {
printf (" Typexd: 0x%02X\n", frameType);
EncryptedPayloadStruct enc = decodeEncryptedPayload (frame);
printf (" Typexdd: 0x%02X\n", enc.type);
if (enc.payloadLen > 0) {
parseEncryptedPayload (enc);
}
decodeEncryptedPayload (frame);
} else if (frameType == PAYLOAD_TYPE_ACK) {
memset (checkSumBuf, 0, sizeof (checkSumBuf));
base64_encode (frame.payload, 4, checkSumBuf);
printf ("Checksum: %s\n", checkSumBuf);
} else if (frameType == PAYLOAD_TYPE_ACK) {
uint32_t checkSum = frame.payload[index++];
checkSum |= frame.payload[index++] << 8;
checkSum |= frame.payload[index++] << 16;
checkSum |= frame.payload[index++] << 24;
uint32_t checkSum = frame->payload[index++];
checkSum |= frame->payload[index++] << 8;
checkSum |= frame->payload[index++] << 16;
checkSum |= frame->payload[index++] << 24;
// TODO add checking
} else if (frameType == PAYLOAD_TYPE_ADVERT) {
advert = decodeAdvertisement (frame);
printAdvertisement (advert);
decodeAdvertisement (frame);
} else if (frameType == PAYLOAD_TYPE_GRP_TXT || frameType == PAYLOAD_TYPE_GRP_DATA) {
msg = decodeGroupMessage (frame);
printGroupMessage (msg);
decodeGroupMessage (frame);
} else if (frameType == PAYLOAD_TYPE_TRACE) {
} else if (frameType == PAYLOAD_TYPE_MULTIPART) {
@@ -68,7 +71,8 @@ void processFrame (FrameStruct frame) {
} else if (frameType == PAYLOAD_TYPE_RAW_CUSTOM) {
// not implemented
} else {
stats.packetsReceivedCount--;
}
retransmitFrame (frame);
MESH_LOGD(TAG, "Processed frame");
}

View File

@@ -11,6 +11,6 @@
#include <ctype.h>
#include "stdio.h"
void processFrame (FrameStruct frame);
void processFrame (const FrameStruct * frame);
#endif

View File

@@ -1,12 +1,110 @@
#include "meshframing.h"
#include "ch32v30x_gpio.h"
#include "lib/config.h"
#include "meshcore/stats.h"
#include "string.h"
#include "stdio.h"
#include "sx1262.h"
#include "util/hexdump.h"
#include "util/log.h"
#include "FreeRTOS.h"
#include "task.h"
#include "lib/cifra/sha2.h"
#define TAG "Meshframing"
int ReadFrame (FrameStruct *frame, int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr) {
uint16_t irqRegs = GetIrqStatus();
// uint8_t status = GetStatus();
if (irqRegs & SX126X_IRQ_RX_DONE) {
// ClearIrqStatus(SX126X_IRQ_RX_DONE);
ClearIrqStatus (SX126X_IRQ_ALL);
uint8_t offset = 0;
uint8_t payloadLength = 0;
GetRxBufferStatus (&payloadLength, &offset);
if (payloadLength == 0) {
return 0;
}
GetPacketStatus (rssiPacket, snrPacket, rawSnr);
memset (frame, 0, sizeof (FrameStruct));
WaitForIdle (BUSY_WAIT, "start ReadBuffer", 1);
uint8_t cmd[3] = {SX126X_CMD_READ_BUFFER, offset, SX126X_CMD_NOP};
GPIO_WriteBit (GPIOA, GPIO_Pin_4, 0);
uint16_t curPayloadIndex = 0;
uint8_t pathIndex = 0;
uint8_t transportIndex = 0;
uint8_t state = 0; // 0=header, 1=transport, 2=pathLen, 3=path, 4=payload
for (uint16_t i = 0; i < payloadLength + sizeof (cmd); i++) {
uint8_t out = (i < sizeof (cmd)) ? cmd[i] : 0xFF;
// Wait TX ready
while (!SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_TXE));
SPI_I2S_SendData (SPI1, out);
// Wait RX ready
while (!SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_RXNE));
uint8_t in = (uint8_t)SPI_I2S_ReceiveData (SPI1);
// Only process payload bytes
if (i >= sizeof (cmd)) {
switch (state) {
case 0: // header
frame->header = in;
state = ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD)
? 1
: 2;
break;
case 1: // transportCodes[4]
frame->transportCodes[transportIndex++] = in;
if (transportIndex >= 4)
state = 2;
break;
case 2: // pathLen
frame->path.pathLen = in;
if (frame->path.pathLen > 64) {
frame->path.pathLen = 64;
}
pathIndex = 0;
state = (frame->path.pathLen > 0) ? 3 : 4;
break;
case 3: // path
frame->path.path[pathIndex++] = in;
if (pathIndex >= frame->path.pathLen)
state = 4;
break;
case 4: // payload
frame->payload[curPayloadIndex++] = in;
break;
}
}
}
frame->payloadLen = curPayloadIndex;
GPIO_WriteBit (GPIOA, GPIO_Pin_4, 1);
WaitForIdle (BUSY_WAIT, "end ReadBuffer", 0);
return payloadLength;
}
return 0;
}
/*
FrameStruct decodeFrame (unsigned char *data, unsigned char dataLen) {
hexdump ("RxDump", data, dataLen);
FrameStruct frame;
memset (&frame, 0, sizeof (frame));
unsigned char index = 0;
@@ -25,9 +123,9 @@ FrameStruct decodeFrame (unsigned char *data, unsigned char dataLen) {
return frame;
}
void printFrameHeader (FrameStruct frame) {
switch (frame.header & ROUTE_TYPE_MASK) {
*/
void printFrameHeader (const FrameStruct *frame) {
switch (frame->header & ROUTE_TYPE_MASK) {
case ROUTE_TYPE_TRANSPORT_FLOOD:
printf ("transport flood");
break;
@@ -47,7 +145,7 @@ void printFrameHeader (FrameStruct frame) {
printf (", payload type is ");
switch (frame.header & PAYLOAD_TYPE_MASK) {
switch (frame->header & PAYLOAD_TYPE_MASK) {
case PAYLOAD_TYPE_REQ:
printf ("request");
break;
@@ -101,68 +199,205 @@ void printFrameHeader (FrameStruct frame) {
break;
}
char version[2];
version[0] = (frame.header >> 6) + '0';
version[0] = (frame->header >> 6) + '0';
version[1] = 0;
printf (", payload version is %s ", version);
if ((frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
(frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
printf ("Transport codes: %d %d\n", *((uint16_t *)frame.transportCodes),
*((uint16_t *)&(frame.transportCodes[2])));
if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
printf ("Transport codes: %d %d\n", *((uint16_t *)frame->transportCodes),
*((uint16_t *)&(frame->transportCodes[2])));
}
printf ("Path is %d nodes long", frame.path.pathLen);
printf ("Path is %d nodes long", frame->path.pathLen);
for (uint8_t pathIndex = 0; pathIndex < frame.path.pathLen; pathIndex++) {
printf ("node %d - %02X, ", pathIndex, frame.path.path[pathIndex]);
for (uint8_t pathIndex = 0; pathIndex < frame->path.pathLen; pathIndex++) {
printf ("node %d - %02X, ", pathIndex, frame->path.path[pathIndex]);
}
putchar ('\n');
}
void sendFrame (FrameStruct frame) {
void LoRaTransmit (const FrameStruct *frame) {
uint8_t len = 2; // header + path_len
if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
len += 4;
}
len += frame->path.pathLen;
len += frame->payloadLen;
uint16_t irqStatus;
char rv = 0;
if (txActive == 0) {
txActive = 1;
if (PacketParams[2] == 0x00) { // explicit header, variable length
PacketParams[3] = len;
}
WriteCommand (SX126X_CMD_SET_PACKET_PARAMS, PacketParams, 6);
ClearIrqStatus (SX126X_IRQ_ALL);
WaitForIdle (BUSY_WAIT, "start WriteBuffer", 1);
uint8_t cmdBuf[2] = {SX126X_CMD_WRITE_BUFFER, 0x00};
uint8_t cmdLen = sizeof (cmdBuf);
GPIO_WriteBit (GPIOA, GPIO_Pin_4, 0);
uint16_t payloadIndex = 0;
uint8_t state = 0;
uint8_t pathIndex = 0;
uint8_t transportIndex = 0;
for (uint16_t i = 0; i < len + cmdLen; i++) {
uint8_t out = 0xFF;
if (i < cmdLen) {
out = cmdBuf[i];
} else {
switch (state) {
case 0: // header
out = frame->header;
state = ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD)
? 1
: 2;
break;
case 1: // transport codes
out = frame->transportCodes[transportIndex++];
if (transportIndex >= 4)
state = 2;
break;
case 2: // path length
out = frame->path.pathLen;
pathIndex = 0;
state = (frame->path.pathLen > 0) ? 3 : 4;
break;
case 3: // path
out = frame->path.path[pathIndex++];
if (pathIndex >= frame->path.pathLen)
state = 4;
break;
case 4: // payload
out = frame->payload[payloadIndex++];
break;
}
}
while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData (SPI1, out);
while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_RXNE) == RESET);
(void)SPI_I2S_ReceiveData (SPI1); // discard
}
GPIO_WriteBit (GPIOA, GPIO_Pin_4, 1);
WaitForIdle (BUSY_WAIT, "end WriteBuffer", 0);
SetTx (5000);
irqStatus = GetIrqStatus();
while (!(irqStatus & (SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT))) {
vTaskDelay (1);
irqStatus = GetIrqStatus();
}
txActive = 0;
SetRx (0xFFFFFF);
if (irqStatus & SX126X_IRQ_TX_DONE) {
rv = 1;
}
}
if (rv == 0) {
txLost++;
}
}
/*
void sendFrame (const FrameStruct *frame) {
uint8_t txBuf[256];
size_t offset = 0;
txBuf[offset++] = frame.header;
txBuf[offset++] = frame->header;
if ((frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
(frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
memcpy (txBuf + offset, frame.transportCodes, 4);
if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT ||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
memcpy (txBuf + offset, frame->transportCodes, 4);
offset += 4;
}
if (frame.path.pathLen > 64) {
frame.path.pathLen = 64;
if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD ||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
stats.sentFloodCount++;
}
txBuf[offset++] = frame.path.pathLen;
if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_DIRECT ||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT) {
stats.sentDirectCount++;
}
memcpy (txBuf + offset, frame.path.path, frame.path.pathLen);
offset += frame.path.pathLen;
stats.packetsSentCount++;
uint8_t pathLen = frame->path.pathLen;
if (pathLen > 64) {
pathLen = 64;
}
txBuf[offset++] = pathLen;
memcpy (txBuf + offset, frame->path.path, pathLen);
hexdump ("TxDump Path", frame->path.path, frame->path.pathLen);
offset += pathLen;
uint16_t maxPayloadLen = 256 - offset;
uint16_t payloadLen = frame.payloadLen > maxPayloadLen ? maxPayloadLen : frame.payloadLen;
uint16_t payloadLen = frame->payloadLen > maxPayloadLen ? maxPayloadLen : frame->payloadLen;
memcpy (txBuf + offset, frame.payload, payloadLen);
memcpy (txBuf + offset, frame->payload, payloadLen);
offset += payloadLen;
hexdump ("TxDump", txBuf, offset);
hexdump ("TxDumpPayload", frame->payload, frame->payloadLen);
TickType_t start, end;
start = xTaskGetTickCount();
LoRaSend (txBuf, offset, SX126x_TXMODE_SYNC);
end = xTaskGetTickCount();
tickAirtime += end - start;
}
*/
void retransmitFrame (FrameStruct frame) {
if (frame.header & ROUTE_TYPE_FLOOD || frame.header & ROUTE_TYPE_TRANSPORT_FLOOD) {
if (frame.header != DONT_RETRANSMIT_HEADER && frame.path.pathLen + 1 < MAX_FLOOD_TTL) {
frame.path.path[frame.path.pathLen++] = persistent.pubkey[0];
void retransmitFrame (FrameStruct *frame) {
MESH_LOGD (TAG, "Going to check ReTx");
if (frame->header & ROUTE_TYPE_FLOOD || frame->header & ROUTE_TYPE_TRANSPORT_FLOOD) {
MESH_LOGD (TAG, "Header is flood");
if (frame->header != DONT_RETRANSMIT_HEADER && frame->path.pathLen + 1 < MAX_FLOOD_TTL) {
MESH_LOGD (TAG, "Writing pubkey");
frame->path.path[frame->path.pathLen++] = persistent.pubkey[0];
MESH_LOGD (TAG, "Flooding");
vTaskDelay (10);
LoRaTransmit (frame); // TODO check if correct
MESH_LOGD (TAG, "Flooded");
}
}
if (frame.header & ROUTE_TYPE_DIRECT || frame.header & ROUTE_TYPE_TRANSPORT_DIRECT) {
if (frame->header & ROUTE_TYPE_DIRECT || frame->header & ROUTE_TYPE_TRANSPORT_DIRECT) {
}
}
// Verify MAC + Decrypt
int encrypt_then_mac (const uint8_t *aes_key, const uint8_t keySize, const uint8_t *plaintext, size_t plen, uint8_t *output, size_t *olen) {
@@ -202,7 +437,8 @@ int mac_then_decrypt (const uint8_t *aes_key, const uint8_t keySize, const uint8
const uint8_t *ciphertext = input + HMAC_SIZE;
size_t clen = ilen - HMAC_SIZE;
if (clen % 16 != 0) return -2; // must be multiple of block size
if (clen % 16 != 0)
return -2; // must be multiple of block size
uint8_t calc_mac[32]; // full SHA-256
hmac_sha256 (aes_key, keySize, ciphertext, clen, calc_mac);
@@ -212,3 +448,25 @@ int mac_then_decrypt (const uint8_t *aes_key, const uint8_t keySize, const uint8
return aes_decrypt_ecb (aes_key, 16, ciphertext, clen, plaintext);
}
uint16_t getTransportCode (const FrameStruct *frame) {
uint16_t code;
/*
// compute HMAC over ciphertext
uint8_t mac[32]; // full SHA-256
cf_hmac_ctx ctx;
cf_hmac_init (&ctx, &cf_sha256, key, sizeof(key));
cf_hmac_update (&ctx, &(frame->header), sizeof (frame->header));
cf_hmac_update (&ctx, frame->payload, frame->payloadLen);
cf_hmac_finish (&ctx, mac);
// copy only HMAC_SIZE bytes of MAC
memcpy (&code, mac, HMAC_SIZE);
*/
if (code == 0) { // reserve codes 0000 and FFFF
code++;
} else if (code == 0xFFFF) {
code--;
}
return code;
}

View File

@@ -12,13 +12,20 @@
#define HMAC_SIZE 2 // meshcore size
#define MAX_FLOOD_TTL 64
int ReadFrame(FrameStruct *frame, int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr);
void LoRaTransmit (const FrameStruct *frame);
/*
FrameStruct decodeFrame (unsigned char *data, unsigned char dataLen);
void printFrameHeader (FrameStruct frame) ;
void sendFrame (const FrameStruct * frame);
*/
void sendFrame (FrameStruct frame);
void printFrameHeader (const FrameStruct * frame) ;
void retransmitFrame (FrameStruct frame) ;
//CALL LAST, PATH GETS MODIFIED
void retransmitFrame (FrameStruct * frame) ;
// Verify MAC + Decrypt
@@ -26,4 +33,5 @@ int encrypt_then_mac (const uint8_t *aes_key, const uint8_t keySize, const uint8
int mac_then_decrypt (const uint8_t *aes_key, const uint8_t keySize, const uint8_t *input, size_t ilen, uint8_t *plaintext);
#endif

View File

@@ -8,6 +8,7 @@
void sendDiscreteAck (uint8_t *data, const uint8_t len, uint8_t *senderPubKey) {
FrameStruct frame;
frame.path.pathLen = 0;
memset (&frame, 0, sizeof (frame));
// 1. Header
@@ -38,5 +39,5 @@ void sendDiscreteAck (uint8_t *data, const uint8_t len, uint8_t *senderPubKey) {
frame.payloadLen = 4;
sendFrame (frame);
LoRaTransmit (&frame);
}

View File

@@ -7,186 +7,202 @@
#include "advert.h"
#include "util/hexdump.h"
#include "lib/base64.h"
#include "util/log.h"
#include "FreeRTOS.h"
#include "task.h"
#define TAG "Advert"
void sendAdvert() {
AdvertisementPayload ad;
memcpy (ad.pubKey, persistent.pubkey, sizeof (ad.pubKey));
ad.dataFlags = ADVERTISEMENT_FLAG_HAS_NAME;
if (persistent.nodeType == NODE_TYPE_CHAT_NODE) {
ad.dataFlags |= ADVERTISEMENT_FLAG_IS_CHAT_NODE;
} else if (persistent.nodeType == NODE_TYPE_REPEATER) {
ad.dataFlags |= ADVERTISEMENT_FLAG_IS_REAPEATER;
} else if (persistent.nodeType == NODE_TYPE_ROOM_SERVER) {
ad.dataFlags |= ADVERTISEMENT_FLAG_IS_ROOM_SERVER;
} else if (persistent.nodeType == NODE_TYPE_SENSOR) {
ad.dataFlags |= ADVERTISEMENT_FLAG_IS_SENSOR;
}
strcpy (ad.nodeName, persistent.nodeName);
ad.timestamp = RTC_GetCounter();
uint8_t app_data[40];
size_t app_len = 0;
app_data[app_len++] = ad.dataFlags;
if (ad.dataFlags & ADVERTISEMENT_FLAG_HAS_LOCATION) {
memcpy (app_data + app_len, &ad.latitude, sizeof (ad.latitude));
app_len += sizeof (ad.latitude);
memcpy (app_data + app_len, &ad.longitude, sizeof (ad.longitude));
app_len += sizeof (ad.longitude);
}
if (ad.dataFlags & ADVERTISEMENT_FLAG_RFU1) {
memcpy (app_data + app_len, &ad.rfu1, sizeof (ad.rfu1));
app_len += sizeof (ad.rfu1);
}
if (ad.dataFlags & ADVERTISEMENT_FLAG_RFU2) {
memcpy (app_data + app_len, &ad.rfu2, sizeof (ad.rfu2));
app_len += sizeof (ad.rfu2);
}
if (ad.dataFlags & ADVERTISEMENT_FLAG_HAS_NAME) {
size_t nodenameLen = strlen (ad.nodeName);
memcpy (app_data + app_len, ad.nodeName, nodenameLen);
app_len += nodenameLen;
}
// 2. Reserve frame and build payload header
void sendAdvert (uint8_t shouldFlood) {
printf ("High-water mark before preparing advert: %u\n", uxTaskGetStackHighWaterMark (NULL));
FrameStruct frame;
frame.header = ROUTE_TYPE_FLOOD | PAYLOAD_TYPE_ADVERT | PAYLOAD_VERSION_0;
size_t offset = 0;
memcpy (frame.payload + offset, ad.pubKey, sizeof (ad.pubKey));
offset += sizeof (ad.pubKey);
memcpy (frame.payload + offset, &ad.timestamp, sizeof (ad.timestamp));
offset += sizeof (ad.timestamp);
frame.header = (shouldFlood ? ROUTE_TYPE_FLOOD : ROUTE_TYPE_DIRECT) | PAYLOAD_TYPE_ADVERT | PAYLOAD_VERSION_0;
// reserve signature space
/* ---- public key ---- */
memcpy (frame.payload + offset, persistent.pubkey, 32);
offset += 32;
/* ---- timestamp ---- */
uint32_t timestamp = RTC_GetCounter();
memcpy (frame.payload + offset, &timestamp, sizeof (timestamp));
offset += sizeof (timestamp);
/* ---- reserve signature ---- */
uint8_t *signature_pos = frame.payload + offset;
offset += 64;
// append app_data after signature
memcpy (frame.payload + offset, app_data, app_len);
offset += app_len;
/* ---- build app data directly into payload ---- */
size_t app_start = offset;
// 3. Sign pubKey + timestamp + app_data
uint8_t message[76];
size_t msg_len = 0;
memcpy (message + msg_len, ad.pubKey, sizeof (ad.pubKey));
msg_len += sizeof (ad.pubKey);
memcpy (message + msg_len, &ad.timestamp, sizeof (ad.timestamp));
msg_len += sizeof (ad.timestamp);
memcpy (message + msg_len, app_data, app_len);
msg_len += app_len;
uint8_t dataFlags = ADVERTISEMENT_FLAG_HAS_NAME;
if (persistent.nodeType == NODE_TYPE_CHAT_NODE)
dataFlags |= ADVERTISEMENT_FLAG_IS_CHAT_NODE;
else if (persistent.nodeType == NODE_TYPE_REPEATER)
dataFlags |= ADVERTISEMENT_FLAG_IS_REAPEATER;
else if (persistent.nodeType == NODE_TYPE_ROOM_SERVER)
dataFlags |= ADVERTISEMENT_FLAG_IS_ROOM_SERVER;
else if (persistent.nodeType == NODE_TYPE_SENSOR)
dataFlags |= ADVERTISEMENT_FLAG_IS_SENSOR;
ed25519_sign (signature_pos, message, msg_len, persistent.pubkey, persistent.privkey);
frame.payload[offset++] = dataFlags;
hexdump ("Complete advert", frame.payload, offset);
if (dataFlags & ADVERTISEMENT_FLAG_HAS_LOCATION) {
memcpy (frame.payload + offset, &persistent.latitude, sizeof (persistent.latitude));
offset += sizeof (persistent.latitude);
hexdump ("Public key", ad.pubKey, 32);
memcpy (frame.payload + offset, &persistent.longitude, sizeof (persistent.longitude));
offset += sizeof (persistent.longitude);
}
/*
hexdump ("Signature", signature_pos, 64);
printf ("Timestamp is %d\n", ad.timestamp);
printf ("NodeName %s\n", ad.nodeName);
hexdump ("Appdata", app_data, app_len);
// 5. Set payload length and send
frame.payloadLen = offset;
frame.path.pathLen = 0;
sendFrame (frame);
if (dataFlags & ADVERTISEMENT_FLAG_RFU1) {
memcpy(frame.payload + offset, &persistent.rfu1, sizeof(persistent.rfu1));
offset += sizeof(persistent.rfu1);
}
AdvertisementPayload decodeAdvertisement (FrameStruct frame) {
if (dataFlags & ADVERTISEMENT_FLAG_RFU2) {
memcpy(frame.payload + offset, &persistent.rfu2, sizeof(persistent.rfu2));
offset += sizeof(persistent.rfu2);
}
*/
if (dataFlags & ADVERTISEMENT_FLAG_HAS_NAME) {
size_t nameLen = strlen (persistent.nodeName);
memcpy (frame.payload + offset, persistent.nodeName, nameLen);
offset += nameLen;
}
size_t app_len = offset - app_start;
frame.payloadLen = offset;
/* ---- sign directly over payload ---- */
printf ("High-water mark before signing: %u\n", uxTaskGetStackHighWaterMark (NULL));
ed25519_sign_ad (&frame);
printf ("High-water mark after signing: %u\n", uxTaskGetStackHighWaterMark (NULL));
/* ---- debug ---- */
hexdump ("Public key", frame.payload, 32);
hexdump ("Signature", signature_pos, 64);
hexdump ("Appdata", frame.payload + app_start, app_len);
printf ("Timestamp is %lu\n", timestamp);
printf ("NodeName %s\n", persistent.nodeName);
/* ---- send ---- */
frame.payloadLen = offset;
frame.path.pathLen = 0;
LoRaTransmit (&frame);
}
void decodeAdvertisement (const FrameStruct *frame) {
AdvertisementPayload advert;
memset (&advert, 0, sizeof (advert));
if ((frame.header & PAYLOAD_TYPE_MASK) != PAYLOAD_TYPE_ADVERT) {
return advert;
advert.valid = 0;
if (frame->payloadLen < 101) {
MESH_LOGW (TAG, "Advertisement frame too short (%d < 101)", frame->payloadLen);
return;
}
if (ed25519_verify_ad (frame) != 1) {
MESH_LOGW (TAG, "Incorrect signature");
return;
}
advert.valid = 1;
unsigned char index = 0;
memcpy (advert.pubKey, frame.payload + index, 32);
memcpy (advert.pubKey, frame->payload + index, 32);
index += 32;
memcpy (&advert.timestamp, frame.payload + index, 4);
memcpy (&advert.timestamp, frame->payload + index, 4);
index += 4;
memcpy (advert.signature, frame.payload + index, 64);
memcpy (advert.signature, frame->payload + index, 64);
index += 64;
advert.dataFlags = frame.payload[index++];
advert.dataFlags = frame->payload[index++];
uint8_t expectedLen = 101;
if (advert.dataFlags & ADVERTISEMENT_FLAG_HAS_LOCATION) {
memcpy (&advert.latitude, frame.payload + index, 4);
expectedLen += 8;
}
if (advert.dataFlags & ADVERTISEMENT_FLAG_RFU1) {
expectedLen += 2;
}
if (advert.dataFlags & ADVERTISEMENT_FLAG_RFU2) {
expectedLen += 2;
}
if (frame->payloadLen < expectedLen) {
MESH_LOGW (TAG, "Advertisement frame with data too short (%d < %d)", frame->payloadLen, expectedLen);
return;
}
if (advert.dataFlags & ADVERTISEMENT_FLAG_HAS_LOCATION) {
memcpy (&advert.latitude, frame->payload + index, 4);
index += 4;
memcpy (&advert.longitude, frame.payload + index, 4);
memcpy (&advert.longitude, frame->payload + index, 4);
index += 4;
}
if (advert.dataFlags & ADVERTISEMENT_FLAG_RFU1) {
memcpy (&advert.rfu1, frame.payload + index, 2);
memcpy (&advert.rfu1, frame->payload + index, 2);
index += 2;
}
if (advert.dataFlags & ADVERTISEMENT_FLAG_RFU2) {
memcpy (&advert.rfu2, frame.payload + index, 2);
memcpy (&advert.rfu2, frame->payload + index, 2);
index += 2;
}
unsigned char nameLen = frame.payloadLen - index;
if (nameLen > 32) {
nameLen = 32;
unsigned char nameLen = frame->payloadLen - index;
if (nameLen > 31) {
nameLen = 31; // leave space for null
}
memcpy (advert.nodeName, frame.payload + index, nameLen);
advert.nodeName[frame.payloadLen - index] = 0;
memcpy (advert.nodeName, frame->payload + index, nameLen);
advert.nodeName[nameLen] = 0;
NodeEntry *node = getNode (advert.pubKey[0]);
printAdvertisement (&advert);
saveAdvert (&advert);
}
void saveAdvert (const AdvertisementPayload *advert) {
NodeEntry *node = getNode (advert->pubKey[0]);
if (node == NULL) {
node = getNextNode();
memset (node, 0, sizeof (NodeEntry));
}
memcpy (node->name, advert.nodeName, sizeof (node->name));
memcpy (node->pubKey, advert.pubKey, sizeof (node->pubKey));
ed25519_key_exchange ((unsigned char *)node->secret, advert.pubKey, persistent.privkey);
node->gps_latitude = advert.latitude;
node->gps_longitude = advert.longitude;
memcpy (node->name, advert->nodeName, sizeof (node->name));
memcpy (node->pubKey, advert->pubKey, sizeof (node->pubKey));
ed25519_key_exchange ((unsigned char *)node->secret, advert->pubKey, persistent.privkey);
node->gps_latitude = advert->latitude;
node->gps_longitude = advert->longitude;
// ADD PATH
node->type = advert.dataFlags & 0x0F;
node->type = advert->dataFlags & 0x0F;
node->last_seen_lt = RTC_GetCounter();
node->last_seen_rt = advert.timestamp;
return advert;
node->last_seen_rt = advert->timestamp;
}
void printAdvertisement (AdvertisementPayload advert) {
unsigned char keyBuf[50];
unsigned char sigBuf[90];
memset (keyBuf, 0, sizeof (keyBuf));
memset (sigBuf, 0, sizeof (sigBuf));
base64_encode (advert.pubKey, 32, keyBuf);
base64_encode (advert.signature, 64, sigBuf);
printf ("%s on %ld with type %s on %s location %ld %ld, public key %s and "
"signature %s\n",
advert.dataFlags & ADVERTISEMENT_FLAG_HAS_NAME ? advert.nodeName
void printAdvertisement (const AdvertisementPayload *advert) {
printf (
"%s on %ld with type %s on %s location %ld %ld\n",
advert->dataFlags & ADVERTISEMENT_FLAG_HAS_NAME
? advert->nodeName
: "nameless node",
advert.timestamp,
(advert.dataFlags & 0x07) == 0x04
? "sensor"
: ((advert.dataFlags & 0x07) == 0x03
? "room server"
: ((advert.dataFlags & 0x07) == 0x02 ? "repeater"
: "chat node")),
advert.dataFlags & 0x80 ? "known" : "unknown", advert.latitude,
advert.longitude, keyBuf, sigBuf);
advert->timestamp,
(advert->dataFlags & 0x07) == 0x04 ? "sensor"
: (advert->dataFlags & 0x07) == 0x03 ? "room server"
: (advert->dataFlags & 0x07) == 0x02 ? "repeater"
: "chat node",
advert->dataFlags & 0x80 ? "known" : "unknown",
advert->latitude,
advert->longitude);
hexdump ("Public key", advert->pubKey, 32);
hexdump ("Signature", advert->signature, 64);
}

View File

@@ -3,10 +3,12 @@
#include "meshcore/packetstructs.h"
void sendAdvert();
void sendAdvert (uint8_t shouldFlood);
AdvertisementPayload decodeAdvertisement (FrameStruct frame);
void decodeAdvertisement (const FrameStruct * frame);
void printAdvertisement (AdvertisementPayload advert);
void printAdvertisement (const AdvertisementPayload * advert);
void saveAdvert(const AdvertisementPayload * advert);
#endif

View File

@@ -10,9 +10,10 @@
#define TAG "Anonymous"
void sendAnonymousRequest (NodeEntry *targetNode, const uint8_t *password, uint32_t sync) {
void sendAnonymousRequest (const NodeEntry *targetNode, const uint8_t *password, uint32_t sync) {
uint8_t passwordLen = strlen ((const char *)password);
FrameStruct frame;
frame.path.pathLen = 0;
uint8_t offset = 0;
// 1. Frame header
@@ -65,32 +66,99 @@ void sendAnonymousRequest (NodeEntry *targetNode, const uint8_t *password, uint3
hexdump ("Anon payload", frame.payload, frame.payloadLen);
sendFrame (frame);
LoRaTransmit (&frame);
}
AnonymousRequestPayload decodeAnonReq (FrameStruct frame) {
void printAnonRequest (const AnonymousRequestPayload *req, int isRoomServer) {
if (!req)
return;
printf ("AnonymousRequestPayload at %p\n", (void *)req);
printf (" destination hash: 0x%02X\n", req->destinationHash);
printf (" sender pubKey: ");
for (int i = 0; i < sizeof (req->pubKey); i++) {
printf ("%02X", req->pubKey[i]);
}
printf ("\n");
printf (" cipher MAC: 0x%04X\n", req->cipherMAC);
printf (" decrypted payload (%u bytes):\n", req->payloadLen);
uint8_t index = 0;
// timestamp (first 4 bytes)
if (req->payloadLen >= 4) {
uint32_t timestamp = req->payload[index++];
timestamp |= req->payload[index++] << 8;
timestamp |= req->payload[index++] << 16;
timestamp |= req->payload[index++] << 24;
printf (" timestamp: %u\n", timestamp);
}
// room server sync timestamp
if (isRoomServer && req->payloadLen >= index + 4) {
uint32_t syncTimestamp = req->payload[index++];
syncTimestamp |= req->payload[index++] << 8;
syncTimestamp |= req->payload[index++] << 16;
syncTimestamp |= req->payload[index++] << 24;
printf (" sync timestamp: %u\n", syncTimestamp);
}
// remaining bytes = password
if (index < req->payloadLen) {
uint8_t passwordLen = req->payloadLen - index;
if (passwordLen > 16)
passwordLen = 16;
passwordLen = strnlen (&(req->payload[index]), passwordLen);
printf (" password: ");
for (uint8_t i = 0; i < passwordLen; i++) {
printf ("%c", req->payload[i + index]);
}
printf ("\n");
}
}
size_t strnlen (const char *s, size_t maxLen) {
size_t len = 0;
while (len < maxLen && s[len] != '\0') {
len++;
}
return len;
}
void decodeAnonReq (const FrameStruct *frame) {
uint8_t index = 0;
AnonymousRequestPayload anonReq;
anonReq.destinationHash = frame.payload[index++];
memcpy (anonReq.pubKey, &(frame.payload[index]), sizeof (anonReq.pubKey));
anonReq.destinationHash = frame->payload[index++];
memcpy (anonReq.pubKey, &(frame->payload[index]), sizeof (anonReq.pubKey));
index += sizeof (anonReq.pubKey);
anonReq.cipherMAC = frame.payload[index];
anonReq.cipherMAC |= frame.payload[index + 1] << 8;
anonReq.cipherMAC = frame->payload[index];
anonReq.cipherMAC |= frame->payload[index + 1] << 8;
NodeEntry *foundNode = getNode (anonReq.pubKey[0]);
if (foundNode == NULL) {
foundNode = getNextNode();
strcpy (foundNode->name, "Anonymous node");
memcpy (foundNode->pubKey, anonReq.pubKey, sizeof (foundNode->pubKey));
ed25519_key_exchange ((unsigned char *)foundNode->secret, anonReq.pubKey, persistent.privkey);
foundNode->gps_latitude = 0;
foundNode->gps_longitude = 0;
// ADD PATH
foundNode->type = 0;
foundNode->last_seen_lt = RTC_GetCounter();
MESH_LOGI (TAG, "New anonymous node created: %s", foundNode->name);
} else {
MESH_LOGD (TAG, "Existing node found for pubKey[0]=0x%02X", anonReq.pubKey[0]);
}
mac_then_decrypt (foundNode->secret, 32, &(frame.payload[index]), frame.payloadLen - index, anonReq.payload);
anonReq.payloadLen = frame.payloadLen - index - 2;
mac_then_decrypt (foundNode->secret, 32, &(frame->payload[index]), frame->payloadLen - index, anonReq.payload);
anonReq.payloadLen = frame->payloadLen - index - 2;
hexdump ("AnonReq payload", anonReq.payload, anonReq.payloadLen);
uint8_t index2 = 0;
foundNode->last_seen_rt = anonReq.payload[index2++];
foundNode->last_seen_rt |= anonReq.payload[index2++] << 8;
@@ -104,23 +172,35 @@ AnonymousRequestPayload decodeAnonReq (FrameStruct frame) {
foundNode->sync_timestamp |= anonReq.payload[index2++] << 24;
}
printAnonRequest (&anonReq, persistent.nodeType == NODE_TYPE_ROOM_SERVER);
uint8_t passwordLen = anonReq.payloadLen - index2;
if (passwordLen > 16) {
if (passwordLen > 16)
passwordLen = 16;
}
passwordLen = strnlen (&(anonReq.payload[index2]), passwordLen);
MESH_LOGI (TAG, "Password len is %d.", passwordLen);
uint8_t passwordBuf[16];
memcpy (passwordBuf, &(anonReq.payload[index2]), passwordLen);
if (memcmp (passwordBuf, persistent.password, sizeof (persistent.password)) == 0) {
if (memcmp (passwordBuf, persistent.password, passwordLen) == 0) {
foundNode->authenticated = 1;
MESH_LOGI (TAG, "Password correct, node %s authenticated.", foundNode->name);
MESH_LOGI (TAG, "Login response sent to node %s.", foundNode->name);
} else {
MESH_LOGW (TAG, "Password incorrect for node %s.", foundNode->name);
}
Response resp;
resp.tag = RTC_GetCounter();
uint8_t index3 = 0;
uint32_t randOut = rand();
resp.data[index3++] = RESP_SERVER_LOGIN_OK;
resp.data[index3++] = 0; // legacy
resp.data[index3++] = 1;//isadmin
resp.data[index3++] = PERM_ACL_ADMIN;//permissions
resp.data[index3++] = randOut & 0xFF;//rng
resp.data[index3++] = foundNode->authenticated; // isadmin
resp.data[index3++] = foundNode->authenticated ? PERM_ACL_ADMIN : PERM_ACL_GUEST; // permissions
resp.data[index3++] = randOut & 0xFF;
resp.data[index3++] = (randOut >> 8) & 0xFF;
resp.data[index3++] = (randOut >> 16) & 0xFF;
resp.data[index3++] = (randOut >> 24) & 0xFF;
@@ -128,6 +208,3 @@ AnonymousRequestPayload decodeAnonReq (FrameStruct frame) {
resp.dataLen = index3;
sendEncryptedResponse (foundNode, &resp);
}
return anonReq;
}

View File

@@ -4,8 +4,8 @@
#include "meshcore/packetstructs.h"
#include "lib/config.h"
AnonymousRequestPayload decodeAnonReq (FrameStruct frame);
void decodeAnonReq (const FrameStruct * frame);
void sendAnonymousRequest (NodeEntry *targetNode, const uint8_t *password, uint32_t sync);
void sendAnonymousRequest (const NodeEntry *targetNode, const uint8_t *password, uint32_t sync);
#endif

View File

@@ -1,13 +1,19 @@
#include "lib/config.h"
#include "meshcore/meshframing.h"
#include "meshcore/packetstructs.h"
#include "control.h"
#include "meshcore/stats.h"
#include "string.h"
#include "util/hexdump.h"
#include "util/log.h"
#include <stdio.h>
#define TAG "Control"
void sendDiscoverRequest (const DiscoverRequestPayload *discReq) {
FrameStruct frame;
frame.path.pathLen = 0;
uint8_t offset = 0;
// Build payload
@@ -30,47 +36,110 @@ void sendDiscoverRequest(const DiscoverRequestPayload *discReq) {
frame.payloadLen = offset;
sendFrame(frame);
LoRaTransmit (&frame);
}
void sendDiscoverResponse (const DiscoverResponsePayload *discResp) {
FrameStruct frame;
frame.path.pathLen = 0;
uint8_t offset = 0;
void decodeControlFrame(FrameStruct frame) {
/* Control type + node type (lower nibble) */
frame.payload[offset++] =
(discResp->nodeType & 0x0F) |
CONTROL_DATA_FLAG_DISCOVER_RESP;
/* SNR */
frame.payload[offset++] = (uint8_t)discResp->snr;
/* Tag (LE) */
frame.payload[offset++] = (discResp->tag >> 0) & 0xFF;
frame.payload[offset++] = (discResp->tag >> 8) & 0xFF;
frame.payload[offset++] = (discResp->tag >> 16) & 0xFF;
frame.payload[offset++] = (discResp->tag >> 24) & 0xFF;
/* Pubkey */
if (discResp->pubkeyLen > 0) {
memcpy (&frame.payload[offset],
discResp->pubkey,
discResp->pubkeyLen);
offset += discResp->pubkeyLen;
}
frame.payloadLen = offset;
LoRaTransmit (&frame);
}
void printDiscoverRequest (const DiscoverRequestPayload *p) {
printf ("=== Discover Request ===\n");
printf ("prefixOnly : %u\n", p->prefixOnly);
printf ("typeFilter : 0x%02X\n", p->typeFilter);
printf ("tag : 0x%08lX\n", (unsigned long)p->tag);
printf ("since : 0x%08lX\n", (unsigned long)p->since);
}
void printDiscoverResponse (const DiscoverResponsePayload *p) {
printf ("=== Discover Response ===\n");
printf ("nodeType : %u\n", p->nodeType);
printf ("snr : %u\n", p->snr);
printf ("tag : 0x%08lX\n", (unsigned long)p->tag);
hexdump ("pubkey : ", p->pubkey, p->pubkeyLen);
printf ("\n");
}
void decodeControlFrame (const FrameStruct * frame) {
uint8_t index = 0;
uint8_t type = frame.payload[index] & 0xF0;
uint8_t type = frame->payload[index] & 0xF0;
if (type == CONTROL_DATA_FLAG_TYPE_NODE_DISCOVER_REQ) {
DiscoverRequestPayload discReq;
discReq.prefixOnly = frame.payload[index++] & 0x01;
discReq.prefixOnly = frame->payload[index++] & 0x01;
discReq.typeFilter = frame.payload[index++];
discReq.typeFilter = frame->payload[index++];
discReq.tag = frame.payload[index++];
discReq.tag |= frame.payload[index++] << 8;
discReq.tag |= frame.payload[index++] << 16;
discReq.tag |= frame.payload[index++] << 24;
discReq.tag = frame->payload[index++];
discReq.tag |= frame->payload[index++] << 8;
discReq.tag |= frame->payload[index++] << 16;
discReq.tag |= frame->payload[index++] << 24;
if (index < frame.payloadLen) {
discReq.since = frame.payload[index++];
discReq.since |= frame.payload[index++] << 8;
discReq.since |= frame.payload[index++] << 16;
discReq.since |= frame.payload[index++] << 24;
if (index < frame->payloadLen) {
discReq.since = frame->payload[index++];
discReq.since |= frame->payload[index++] << 8;
discReq.since |= frame->payload[index++] << 16;
discReq.since |= frame->payload[index++] << 24;
}
printDiscoverRequest (&discReq);
if ((discReq.typeFilter >> 2) & persistent.nodeType) {
DiscoverResponsePayload discResp;
discResp.tag = discReq.tag;
discResp.nodeType = persistent.nodeType;
discResp.pubkeyLen = sizeof (persistent.pubkey);
memcpy (discResp.pubkey, persistent.pubkey, discResp.pubkeyLen);
discResp.snr = stats.lastSNR; // hopefully the correct one
sendDiscoverResponse (&discResp);
MESH_LOGD(TAG, "Replying to a discover request with tag %d", discResp.tag);
}
} else if (type == CONTROL_DATA_FLAG_DISCOVER_RESP) {
DiscoverResponsePayload discResp;
discResp.nodeType = frame.payload[index++] & 0x0F;
discResp.nodeType = frame->payload[index++] & 0x0F;
discResp.snr = frame.payload[index++];
discResp.snr = frame->payload[index++];
discResp.tag = frame.payload[index++];
discResp.tag |= frame.payload[index++] << 8;
discResp.tag |= frame.payload[index++] << 16;
discResp.tag |= frame.payload[index++] << 24;
discResp.tag = frame->payload[index++];
discResp.tag |= frame->payload[index++] << 8;
discResp.tag |= frame->payload[index++] << 16;
discResp.tag |= frame->payload[index++] << 24;
uint8_t remainingLen = frame.payloadLen - index;
uint8_t remainingLen = frame->payloadLen - index;
uint8_t pubKeyLen = (remainingLen > 8) ? sizeof (discResp.pubkey) : 8;
memcpy(discResp.pubkey, &(frame.payload[index]), pubKeyLen);
discResp.pubkeyLen = pubKeyLen;
memcpy (discResp.pubkey, &(frame->payload[index]), discResp.pubkeyLen);
index += pubKeyLen;
printDiscoverResponse (&discResp);
}
}

View File

@@ -3,6 +3,14 @@
#include "meshcore/packetstructs.h"
void decodeControlFrame(FrameStruct frame);
void sendDiscoverRequest(const DiscoverRequestPayload *discReq);
void sendDiscoverResponse(const DiscoverResponsePayload *discResp);
void printDiscoverRequest(const DiscoverRequestPayload *p);
void printDiscoverResponse(const DiscoverResponsePayload *p);
void decodeControlFrame(const FrameStruct * frame);
#endif

View File

@@ -1,4 +1,5 @@
#include "lib/config.h"
#include "lib/telemetry/telemetry.h"
#include "meshcore/meshframing.h"
#include "meshcore/packets/ack.h"
#include "meshcore/packetstructs.h"
@@ -10,6 +11,9 @@
#include "encrypted.h"
#include "FreeRTOS.h"
#include "task.h"
#include "lib/adc/temperature.h"
#define TICKS_TO_MS(xTicks) (((uint32_t)(xTicks)*1000U) / (uint32_t)configTICK_RATE_HZ)
#define TAG "EncryptedMessage"
@@ -20,7 +24,7 @@ void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8
// 1. Header
frame.header =
ROUTE_TYPE_FLOOD | //currently flood
(targetNode->path.pathLen > 0 ? ROUTE_TYPE_DIRECT : ROUTE_TYPE_FLOOD) | // currently flood
payloadType |
PAYLOAD_VERSION_0;
@@ -45,16 +49,16 @@ void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8
memcpy (&frame.path, &targetNode->path, sizeof (frame.path));
hexdump ("Encrypted frame", frame.payload, frame.payloadLen);
sendFrame (frame);
LoRaTransmit (&frame);
}
void sendEncryptedTextMessage (NodeEntry *targetNode, const PlainTextMessagePayload *msg) {
if (targetNode == NULL) {
ESP_LOGW(TAG, "Node is null");
MESH_LOGW (TAG, "Node is null");
return;
}
if (targetNode->last_seen_lt == 0) {
ESP_LOGW(TAG, "Node is not populated");
MESH_LOGW (TAG, "Node is not populated");
return;
}
uint8_t buf[256];
@@ -80,12 +84,13 @@ void sendEncryptedResponse (NodeEntry *targetNode, const Response *resp) {
uint8_t buf[256];
uint8_t index = 0;
buf[index++] = resp->tag;
buf[index++] = resp->tag >> 8;
buf[index++] = resp->tag >> 16;
buf[index++] = resp->tag >> 24;
buf[index++] = (resp->tag) & 0xFF;
buf[index++] = (resp->tag >> 8) & 0xFF;
buf[index++] = (resp->tag >> 16) & 0xFF;
buf[index++] = (resp->tag >> 24) & 0xFF;
memcpy (&buf[index], resp->data, resp->dataLen);
memcpy (&(buf[index]), resp->data, resp->dataLen);
index += resp->dataLen;
sendEncryptedFrame (
targetNode,
@@ -104,7 +109,8 @@ void sendEncryptedRequest (NodeEntry *targetNode, const Request *req) {
buf[index++] = req->timestamp >> 24;
buf[index++] = req->requestType;
memcpy (&buf[index], req->data, req->dataLen);
memcpy (&(buf[index]), req->data, req->dataLen);
index += req->dataLen;
sendEncryptedFrame (
targetNode,
@@ -123,7 +129,7 @@ void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload
buf[index++] = path->extra.type;
memcpy (&buf[index], path->extra.data,
sizeof (path->extra.data));
path->extra.dataLen);
sendEncryptedFrame (
targetNode,
@@ -137,20 +143,14 @@ void printRequest (const Request *req) {
printf (" Timestamp: %u\n", req->timestamp);
printf (" Type: 0x%02X\n", req->requestType);
printf (" Data: ");
for (int i = 0; i < req->dataLen; i++) {
printf ("%02X ", req->data[i]);
}
printf ("\n");
hexdump (" Data", req->data, req->dataLen);
}
void printResponse (const Response *resp) {
printf ("Response:\n");
printf (" Tag: %u\n", resp->tag);
printf (" Data: ");
for (int i = 0; i < resp->dataLen; i++) {
printf ("%02X ", resp->data[i]);
}
printf ("\n");
hexdump (" Data", resp->data, resp->dataLen);
}
void printPlainTextMessage (const PlainTextMessagePayload *msg) {
@@ -165,16 +165,10 @@ void printReturnedPathPayload (const ReturnedPathPayload *path) {
printf ("ReturnedPathPayload:\n");
printf (" Path Length: %u\n", path->path.pathLen);
printf (" Path: ");
for (int i = 0; i < path->path.pathLen; i++) {
printf ("%02X ", path->path.path[i]);
}
printf ("\n");
hexdump (" Path:", path->path.path, path->path.pathLen);
printf (" Extra Type: %u\n", path->extra.type);
printf (" Extra Data: ");
for (int i = 0; i < sizeof (path->extra.data); i++) {
printf ("%02X ", path->extra.data[i]);
}
printf ("\n");
hexdump (" Extra data:", path->extra.data, path->extra.dataLen);
}
void printEncryptedPayload (const EncryptedPayloadStruct *enc) {
@@ -191,22 +185,22 @@ void printEncryptedPayload (const EncryptedPayloadStruct *enc) {
printf ("\n");
}
EncryptedPayloadStruct decodeEncryptedPayload (FrameStruct frame) {
void decodeEncryptedPayload (const FrameStruct *frame) {
EncryptedPayloadStruct enc;
memset (&enc, 0, sizeof (enc));
enc.type = frame.header & PAYLOAD_TYPE_MASK;
enc.type = frame->header & PAYLOAD_TYPE_MASK;
unsigned char index = 0;
enc.destinationHash = frame.payload[index++];
enc.sourceHash = frame.payload[index++];
enc.cipherMAC = frame.payload[index];
enc.cipherMAC |= frame.payload[index + 1] << 8;
enc.destinationHash = frame->payload[index++];
enc.sourceHash = frame->payload[index++];
enc.cipherMAC = frame->payload[index];
enc.cipherMAC |= frame->payload[index + 1] << 8;
if (enc.destinationHash != persistent.pubkey[0]) {
return enc;
return;
}
ESP_LOGI(TAG, "Finding remote node, sourceHash is %d", enc.sourceHash);
MESH_LOGI (TAG, "Finding remote node, sourceHash is %d", enc.sourceHash);
NodeEntry *remNode = getNode (enc.sourceHash);
@@ -214,96 +208,152 @@ EncryptedPayloadStruct decodeEncryptedPayload (FrameStruct frame) {
if (remNode == NULL) {
ESP_LOGW(TAG, "Node not in DB");
return enc;
MESH_LOGW (TAG, "Node not in DB");
return;
}
ESP_LOGI(TAG, "Found node with index %d", remNode - persistent.contacts);
MESH_LOGI (TAG, "Found node with index %d", remNode - persistent.contacts);
if (mac_then_decrypt (remNode->secret, 32, &(frame.payload[index]), frame.payloadLen - index, enc.payload) != 0) {
ESP_LOGW (TAG, "HMAC failed on encrypted message %s", remNode->name);
if (mac_then_decrypt (remNode->secret, 32, &(frame->payload[index]), frame->payloadLen - index, enc.payload) != 0) {
MESH_LOGW (TAG, "HMAC failed on encrypted message %s", remNode->name);
} else {
enc.payloadLen = frame.payloadLen - HMAC_SIZE;
ESP_LOGI(TAG, "HMAC success from %s, %u bytes long", remNode->name, enc.payloadLen);
enc.payloadLen = frame->payloadLen - HMAC_SIZE;
MESH_LOGI (TAG, "HMAC success from %s, %u bytes long", remNode->name, enc.payloadLen);
sendDiscreteAck (enc.payload, 5 + strlen ((char *)&enc.payload[5]), remNode->pubKey);
}
return enc;
printf (" Typexdd: 0x%02X\n", enc.type);
if (enc.payloadLen > 0) {
parseEncryptedPayload (&enc);
}
}
void parseEncryptedPayload (EncryptedPayloadStruct enc) {
void parseEncryptedPayload (const EncryptedPayloadStruct *enc) {
// printEncryptedPayload(&enc);
printf ("EncryptedPayload:\n");
printf (" Type: 0x%02X\n", enc.type);
printf (" DestinationHash: 0x%02X\n", enc.destinationHash);
printf (" SourceHash: 0x%02X\n", enc.sourceHash);
printf (" CipherMAC: 0x%04X\n", enc.cipherMAC);
printf (" PayloadLen: %u\n", enc.payloadLen);
printf (" Payload: ");
hexdump("Full payload buffer", enc.payload, sizeof(enc.payload));
printf (" Type: 0x%02X\n", enc->type);
printf (" DestinationHash: 0x%02X\n", enc->destinationHash);
printf (" SourceHash: 0x%02X\n", enc->sourceHash);
printf (" CipherMAC: 0x%04X\n", enc->cipherMAC);
printf (" PayloadLen: %u\n", enc->payloadLen);
hexdump (" Payload: ", enc->payload, enc->payloadLen);
printf ("\n");
uint8_t index = 0;
if (enc.type == PAYLOAD_TYPE_PATH) {
if (enc->type == PAYLOAD_TYPE_PATH) {
ReturnedPathPayload retPath;
retPath.path.pathLen = enc.payload[index++];
retPath.path.pathLen = enc->payload[index++];
if (retPath.path.pathLen > 64) {
ESP_LOGW (TAG, "Path too long\n");
MESH_LOGW (TAG, "Path too long\n");
return;
}
memcpy (retPath.path.path, &(enc.payload[index]), retPath.path.pathLen);
memcpy (retPath.path.path, &(enc->payload[index]), retPath.path.pathLen);
index += retPath.path.pathLen;
retPath.extra.type = enc.payload[index++];
memcpy (retPath.extra.data, &(enc.payload[index]), enc.payloadLen - index);
retPath.extra.type = enc->payload[index++];
retPath.extra.dataLen = enc->payloadLen - index;
memcpy (retPath.extra.data, &(enc->payload[index]), retPath.extra.dataLen);
} else if (enc.type == PAYLOAD_TYPE_REQ) {
} else if (enc->type == PAYLOAD_TYPE_REQ) {
Request req;
req.timestamp = enc.payload[index++];
req.timestamp |= enc.payload[index++] << 8;
req.timestamp |= enc.payload[index++] << 16;
req.timestamp |= enc.payload[index++] << 24;
req.requestType = enc.payload[index++];
req.dataLen = enc.payloadLen - index;
memcpy (req.data, &(enc.payload[index]), req.dataLen);
req.timestamp = enc->payload[index++];
req.timestamp |= enc->payload[index++] << 8;
req.timestamp |= enc->payload[index++] << 16;
req.timestamp |= enc->payload[index++] << 24;
req.requestType = enc->payload[index++];
req.dataLen = enc->payloadLen - index;
memcpy (req.data, &(enc->payload[index]), req.dataLen);
printRequest (&req);
switch (req.requestType) {
case REQUEST_GET_STATS: {
Response resp;
resp.tag = RTC_GetCounter();
stats.totalUpTimeSeconds = RTC_GetCounter() - startupTime;
stats.totalAirTimeSeconds = TICKS_TO_MS (tickAirtime / 1000);
memcpy (resp.data, &stats, sizeof (stats));
resp.dataLen = sizeof (stats);
sendEncryptedResponse(enc.remNode, &resp);
sendEncryptedResponse (enc->remNode, &resp);
break;
}
case REQUEST_KEEPALIVE:
break;
case REQUEST_GET_TELEMETRY_DATA:
case REQUEST_GET_TELEMETRY_DATA: {
Response resp;
resp.tag = req.timestamp;
uint8_t index2 = 0;
resp.data[index2++] = TELEM_CHANNEL_SELF;
resp.data[index2++] = LPP_TEMPERATURE;
int16_t dataTemp = getDeciTemperature();
printf ("The temperature is %d decicelsius\n", dataTemp);
resp.data[index2++] = (dataTemp >> 8) & 0xFF;
resp.data[index2++] = dataTemp & 0xFF;
resp.data[index2++] = TELEM_CHANNEL_SELF;
resp.data[index2++] = LPP_VOLTAGE;
int16_t dataVolt = stats.millivolts / 10;
resp.data[index2++] = (dataVolt >> 8) & 0xFF;
resp.data[index2++] = dataVolt & 0xFF;
if (enc->remNode->authenticated) {
encode_gps (TELEM_CHANNEL_SELF, persistent.latitude / 1000000.0f, persistent.longitude / 1000000.0f, persistent.altitude / 100.0f, &(resp.data[index2]));
// encode_gps(TELEM_CHANNEL_SELF, 48.1909f, 17.0303f, 234.0f, &(resp.data[index2]));
index2 += LPP_GPS_SIZE;
}
if (enc->remNode->authenticated) {
resp.data[index2++] = 2;
resp.data[index2++] = LPP_TEMPERATURE;
int16_t jokeTemp = 6942;
resp.data[index2++] = (jokeTemp >> 8) & 0xFF;
resp.data[index2++] = jokeTemp & 0xFF;
resp.dataLen = index2;
}
sendEncryptedResponse (enc->remNode, &resp);
break;
}
case REQUEST_GET_MIN_MAX_AVG:
break;
case REQUEST_GET_ACCESS_LIST:
break;
}
} else if (enc.type == PAYLOAD_TYPE_RESPONSE) {
} else if (enc->type == PAYLOAD_TYPE_RESPONSE) {
Response resp;
resp.tag = enc.payload[index++];
resp.tag |= enc.payload[index++] << 8;
resp.tag |= enc.payload[index++] << 16;
resp.tag |= enc.payload[index++] << 24;
resp.dataLen = enc.payloadLen - index;
memcpy (resp.data, &(enc.payload[index]), resp.dataLen);
resp.tag = enc->payload[index++];
resp.tag |= enc->payload[index++] << 8;
resp.tag |= enc->payload[index++] << 16;
resp.tag |= enc->payload[index++] << 24;
resp.dataLen = enc->payloadLen - index;
memcpy (resp.data, &(enc->payload[index]), resp.dataLen);
printResponse (&resp);
} else if (enc.type == PAYLOAD_TYPE_TXT_MSG) {
} else if (enc->type == PAYLOAD_TYPE_TXT_MSG) {
PlainTextMessagePayload plaintext;
plaintext.timestamp = enc.payload[index++];
plaintext.timestamp |= enc.payload[index++] << 8;
plaintext.timestamp |= enc.payload[index++] << 16;
plaintext.timestamp |= enc.payload[index++] << 24;
plaintext.attempt = enc.payload[index] & 0x03;
plaintext.textType = enc.payload[index++] >> 2;
memcpy (plaintext.message, &(enc.payload[index]), enc.payloadLen - index);
plaintext.timestamp = enc->payload[index++];
plaintext.timestamp |= enc->payload[index++] << 8;
plaintext.timestamp |= enc->payload[index++] << 16;
plaintext.timestamp |= enc->payload[index++] << 24;
plaintext.attempt = enc->payload[index] & 0x03;
plaintext.textType = enc->payload[index++] >> 2;
memcpy (plaintext.message, &(enc->payload[index]), enc->payloadLen - index);
printPlainTextMessage (&plaintext);
}
}

View File

@@ -18,8 +18,8 @@ void sendEncryptedRequest (NodeEntry *targetNode, const Request *req);
void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload *path);
EncryptedPayloadStruct decodeEncryptedPayload (FrameStruct frame);
void decodeEncryptedPayload (const FrameStruct *frame);
void parseEncryptedPayload (EncryptedPayloadStruct enc);
void parseEncryptedPayload (const EncryptedPayloadStruct * enc);
#endif

View File

@@ -9,40 +9,43 @@
#define TAG "GroupMessage"
void sendGroupMessage (GroupTextMessage msg) {
msg.channelHash = persistent.aesKeys[msg.keyIndex][0];
msg.flags = 0;
msg.timestamp = RTC_GetCounter();
void sendGroupMessage (const GroupTextMessage *msg) {
// Prepare values locally instead of modifying msg
uint8_t channelHash = persistent.aesKeys[msg->keyIndex][0];
uint8_t flags = 0;
int32_t timestamp = RTC_GetCounter();
FrameStruct frame;
frame.header = ROUTE_TYPE_FLOOD | PAYLOAD_TYPE_GRP_TXT | PAYLOAD_VERSION_0;
frame.path.pathLen = 0;
size_t offset = 0;
memset (frame.payload, 0, sizeof (frame.payload));
frame.payload[offset++] = msg.channelHash;
frame.payload[offset++] = channelHash;
uint8_t cipherBuf[176];
size_t offset2 = 0;
memcpy (cipherBuf, (const void *)&(msg.timestamp), 4);
offset2 += 4;
cipherBuf[offset2++] = msg.flags;
size_t textSize = offset2 + strlen ((const char *)msg.text);
if (textSize > 175) {
textSize = 175;
// Build encryption buffer directly on stack (no extra large buffer)
uint8_t buf[180]; // enough for timestamp + flags + text
size_t buf_offset = 0;
memcpy (buf + buf_offset, &timestamp, sizeof (timestamp));
buf_offset += sizeof (timestamp);
buf[buf_offset++] = flags;
size_t textLen = strlen ((const char *)msg->text);
if (buf_offset + textLen > sizeof (buf)) {
textLen = sizeof (buf) - buf_offset;
}
memcpy (cipherBuf + offset2, msg.text, textSize);
offset2 += textSize;
memcpy (buf + buf_offset, msg->text, textLen);
buf_offset += textLen;
hexdump ("TxDumpDec", buf, buf_offset);
// Encrypt and MAC directly into frame payload after channelHash
size_t olen = 0;
hexdump ("TxDumpDec", cipherBuf, offset2);
encrypt_then_mac (&(persistent.aesKeys[msg.keyIndex][1]), 16, cipherBuf, offset2, &(frame.payload[offset]), &olen);
encrypt_then_mac (&persistent.aesKeys[msg->keyIndex][1], 16, buf, buf_offset, &frame.payload[offset], &olen);
frame.payloadLen = olen + 1;
frame.payloadLen = olen + 1; // +1 for channelHash
sendFrame (frame);
return;
LoRaTransmit (&frame);
}
void makeSendGroupMessage (char *txt, uint8_t keyIndex) {
@@ -51,19 +54,19 @@ void makeSendGroupMessage (char *txt, uint8_t keyIndex) {
strcat ((char *)msg.text, ": ");
strcat ((char *)msg.text, txt);
msg.keyIndex = keyIndex;
sendGroupMessage (msg);
sendGroupMessage (&msg);
return;
}
GroupTextMessage decodeGroupMessage (FrameStruct frame) {
void decodeGroupMessage (const FrameStruct *frame) {
GroupTextMessage msg;
memset (&msg, 0, sizeof (msg));
if ((frame.header & PAYLOAD_TYPE_MASK) != PAYLOAD_TYPE_GRP_TXT) {
ESP_LOGW (TAG, "Not a group text");
return msg;
if ((frame->header & PAYLOAD_TYPE_MASK) != PAYLOAD_TYPE_GRP_TXT) {
MESH_LOGW (TAG, "Not a group text");
return;
}
unsigned char index = 0;
msg.channelHash = frame.payload[index++];
msg.channelHash = frame->payload[index++];
unsigned char tmp[184];
@@ -71,27 +74,27 @@ GroupTextMessage decodeGroupMessage (FrameStruct frame) {
for (unsigned char i = 0; i < AESKeyCount; i++) {
if (msg.channelHash != persistent.aesKeys[i][0]) {
ESP_LOGW (TAG, "Hash %d does not equal %d", persistent.aesKeys[i][0], msg.channelHash);
MESH_LOGW (TAG, "Hash %d does not equal %d", persistent.aesKeys[i][0], msg.channelHash);
continue;
}
ESP_LOGW (TAG, "Hash does equal %d", msg.channelHash);
MESH_LOGW (TAG, "Hash does equal %d", msg.channelHash);
if (mac_then_decrypt (persistent.aesKeys[i] + 1, 16, frame.payload + index, frame.payloadLen - index, tmp) != 0) {
ESP_LOGW (TAG, "HMAC failed on grouphash key %d not matching %d", persistent.aesKeys[i][0], msg.channelHash);
if (mac_then_decrypt (persistent.aesKeys[i] + 1, 16, frame->payload + index, frame->payloadLen - index, tmp) != 0) {
MESH_LOGW (TAG, "HMAC failed on grouphash key %d not matching %d", persistent.aesKeys[i][0], msg.channelHash);
continue;
}
hexdump ("RxDumpDec", tmp, frame.payloadLen - index);
hexdump ("RxDumpDec", tmp, frame->payloadLen - index);
decrypted = 1;
break;
}
if (!decrypted) {
return msg;
return;
}
unsigned char plaintextLen = frame.payloadLen - index;
unsigned char plaintextLen = frame->payloadLen - index;
index = 0;
memcpy (&msg.timestamp, tmp + index, 4);
@@ -99,10 +102,11 @@ GroupTextMessage decodeGroupMessage (FrameStruct frame) {
msg.flags = tmp[index++];
memcpy (msg.text, tmp + index, plaintextLen - index);
return msg;
printGroupMessage (&msg);
}
void printGroupMessage (GroupTextMessage msg) {
printf ("Message with channel hash %d, flags %d: %s\n", msg.channelHash,
msg.flags, msg.text);
void printGroupMessage (const GroupTextMessage *msg) {
printf ("Message with channel hash %d, flags %d: %s\n", msg->channelHash,
msg->flags, msg->text);
}

View File

@@ -4,12 +4,12 @@
#include "stdint.h"
#include "meshcore/packetstructs.h"
void sendGroupMessage (GroupTextMessage msg);
void sendGroupMessage (const GroupTextMessage * msg);
void makeSendGroupMessage (char *txt, uint8_t keyIndex);
GroupTextMessage decodeGroupMessage (FrameStruct frame);
void decodeGroupMessage (const FrameStruct * frame);
void printGroupMessage (GroupTextMessage msg);
void printGroupMessage (const GroupTextMessage * msg);
#endif

View File

@@ -56,6 +56,7 @@ typedef struct DiscoverResponsePayload {
int8_t snr;
uint32_t tag;
uint8_t pubkey[32];
uint8_t pubkeyLen;
} DiscoverResponsePayload;
typedef struct AnonymousRequestPayload {
@@ -116,6 +117,27 @@ typedef struct Node {
char flags;
} Node;
typedef struct {
char name[32];
unsigned char pubKey[32];
unsigned char secret[32];
int32_t gps_latitude;
int32_t gps_longitude;
Path path;
uint8_t flags;
uint8_t type;
uint8_t authenticated;
uint32_t last_seen_rt; //remote timestamp
uint32_t last_seen_lt; //local timestamp
uint32_t sync_timestamp;
} NodeEntry;
typedef struct EncryptedPayloadStruct {
uint8_t destinationHash;
uint8_t sourceHash;
@@ -153,6 +175,7 @@ typedef struct AdvertisementPayload {
uint8_t pubKey[32];
int32_t timestamp;
uint8_t signature[64];
uint8_t valid;
uint8_t dataFlags;
int32_t latitude;
int32_t longitude;
@@ -164,6 +187,7 @@ typedef struct AdvertisementPayload {
typedef struct Extra {
uint8_t type;
uint8_t dataLen;
uint8_t data[180]; // hopefully long enough
} Extra;
@@ -204,4 +228,8 @@ typedef struct RepeaterStats {
uint32_t total_rx_air_time_secs;
} RepeaterStats;
typedef struct Channel {
} Channel;
#endif

View File

@@ -1,3 +1,6 @@
#include "stats.h"
RepeaterStats stats;
uint32_t startupTime = 0;
uint32_t tickAirtime = 0;

View File

@@ -4,4 +4,8 @@
extern RepeaterStats stats;
extern uint32_t startupTime;
extern uint32_t tickAirtime;
#endif

View File

@@ -11,9 +11,9 @@
#define TAG "SX1262"
// Global Stuff
static uint8_t PacketParams[6];
static char txActive;
static int txLost = 0;
uint8_t PacketParams[6];
char txActive;
int txLost = 0;
static char debugPrint;
// Arduino compatible macros
@@ -22,7 +22,7 @@ static char debugPrint;
void LoRaError (int error) {
if (debugPrint) {
ESP_LOGE (TAG, "LoRaErrorDefault=%d", error);
MESH_LOGE (TAG, "LoRaErrorDefault=%d", error);
}
while (1) {
vTaskDelay (1);
@@ -112,7 +112,7 @@ void spi_read_byte (uint8_t *rx, const uint8_t *tx, size_t len) {
// Wait TX ready
while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_TXE) == RESET);
if (debugPrint) {
printf ("Sent %02X over spi.\n", out);
MESH_LOGV (TAG, "Sent %02X over spi.\n", out);
}
SPI_I2S_SendData (SPI1, out);
// Wait RX ready
@@ -121,7 +121,7 @@ void spi_read_byte (uint8_t *rx, const uint8_t *tx, size_t len) {
uint8_t in = (uint8_t)SPI_I2S_ReceiveData (SPI1);
if (debugPrint) {
printf ("Got %02X over spi.\n", in);
MESH_LOGV (TAG, "Got %02X over spi.\n", in);
}
if (rx)
rx[i] = in;
@@ -129,6 +129,36 @@ void spi_read_byte (uint8_t *rx, const uint8_t *tx, size_t len) {
GPIO_WriteBit (GPIOA, GPIO_Pin_4, 1);
}
// Full-duplex transfer: TX and RX buffers
void spi_read_byte_offs (uint8_t *rx, const uint8_t *tx, size_t len, uint8_t off) {
GPIO_WriteBit (GPIOA, GPIO_Pin_4, 0);
for (size_t i = 0; i < len; i++) {
uint8_t out = 0xFF;
if (i < off) {
out = tx ? tx[i] : 0xFF;
}
// Wait TX ready
while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_TXE) == RESET);
if (debugPrint) {
MESH_LOGV (TAG, "Sent %02X over spi.\n", out);
}
SPI_I2S_SendData (SPI1, out);
// Wait RX ready
while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_RXNE) == RESET);
uint8_t in = (uint8_t)SPI_I2S_ReceiveData (SPI1);
if (debugPrint) {
MESH_LOGV (TAG, "Got %02X over spi.\n", in);
}
if (rx && i >= off) {
rx[i - off] = in;
}
}
GPIO_WriteBit (GPIOA, GPIO_Pin_4, 1);
}
int16_t LoRaBegin (uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltage, char useRegulatorLDO) {
if (txPowerInDbm > 22) {
txPowerInDbm = 22;
@@ -142,17 +172,17 @@ int16_t LoRaBegin (uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltag
uint8_t wk[2];
ReadRegister (SX126X_REG_LORA_SYNC_WORD_MSB, wk, 2); // 0x0740
uint16_t syncWord = (wk[0] << 8) + wk[1];
ESP_LOGI (TAG, "syncWord=0x%x", syncWord);
MESH_LOGI (TAG, "syncWord=0x%x", syncWord);
if (syncWord != SX126X_SYNC_WORD_PUBLIC && syncWord != SX126X_SYNC_WORD_PRIVATE) {
ESP_LOGE (TAG, "SX126x error, maybe no SPI connection");
MESH_LOGE (TAG, "SX126x error, maybe no SPI connection");
return ERR_INVALID_MODE;
}
ESP_LOGI (TAG, "SX126x installed");
MESH_LOGI (TAG, "SX126x installed");
SetStandby (SX126X_STANDBY_RC);
SetDio2AsRfSwitchCtrl (1);
ESP_LOGI (TAG, "tcxoVoltage=%f", tcxoVoltage);
MESH_LOGI (TAG, "tcxoVoltage=%f", tcxoVoltage);
// set TCXO control, if requested
if (tcxoVoltage > 0.0) {
SetDio3AsTcxoCtrl (tcxoVoltage, RADIO_TCXO_SETUP_TIME); // Configure the radio to use a TCXO controlled by DIO3
@@ -160,7 +190,7 @@ int16_t LoRaBegin (uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltag
Calibrate (SX126X_CALIBRATE_IMAGE_ON | SX126X_CALIBRATE_ADC_BULK_P_ON | SX126X_CALIBRATE_ADC_BULK_N_ON | SX126X_CALIBRATE_ADC_PULSE_ON | SX126X_CALIBRATE_PLL_ON | SX126X_CALIBRATE_RC13M_ON | SX126X_CALIBRATE_RC64K_ON);
ESP_LOGI (TAG, "useRegulatorLDO=%d", useRegulatorLDO);
MESH_LOGI (TAG, "useRegulatorLDO=%d", useRegulatorLDO);
if (useRegulatorLDO) {
SetRegulatorMode (SX126X_REGULATOR_LDO); // set regulator mode: LDO
} else {
@@ -239,7 +269,7 @@ void LoRaConfig (uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate,
);
ESP_LOGI (TAG, "Almost done setting LoRa");
MESH_LOGI (TAG, "Almost done setting LoRa");
// Receive state no receive timeoout
SetRx (0xFFFFFF);
}
@@ -286,12 +316,12 @@ char LoRaSend (uint8_t *pData, int16_t len, uint8_t mode) {
irqStatus = GetIrqStatus();
}
if (debugPrint) {
ESP_LOGI (TAG, "irqStatus=0x%x", irqStatus);
MESH_LOGI (TAG, "irqStatus=0x%x", irqStatus);
if (irqStatus & SX126X_IRQ_TX_DONE) {
ESP_LOGI (TAG, "SX126X_IRQ_TX_DONE");
MESH_LOGI (TAG, "SX126X_IRQ_TX_DONE");
}
if (irqStatus & SX126X_IRQ_TIMEOUT) {
ESP_LOGI (TAG, "SX126X_IRQ_TIMEOUT");
MESH_LOGI (TAG, "SX126X_IRQ_TIMEOUT");
}
}
txActive = 0;
@@ -306,7 +336,7 @@ char LoRaSend (uint8_t *pData, int16_t len, uint8_t mode) {
}
}
if (debugPrint) {
ESP_LOGI (TAG, "Send rv=0x%x", rv);
MESH_LOGI (TAG, "Send rv=0x%x", rv);
}
if (rv == 0)
txLost++;
@@ -331,11 +361,12 @@ char ReceiveMode (void) {
return rv;
}
void GetPacketStatus (int8_t *rssiPacket, int8_t *snrPacket) {
void GetPacketStatus (int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr) {
uint8_t buf[4];
ReadCommand (SX126X_CMD_GET_PACKET_STATUS, buf, 4); // 0x14
*rssiPacket = (buf[3] >> 1) * -1;
(buf[2] < 128) ? (*snrPacket = buf[2] >> 2) : (*snrPacket = ((buf[2] - 256) >> 2));
*rawSnr = buf[2];
}
void SetTxPower (int8_t txPowerInDbm) {
@@ -347,7 +378,7 @@ void ResetLora (void) {
GPIO_WriteBit (GPIOE, GPIO_Pin_3, 0);
vTaskDelay (pdMS_TO_TICKS (20));
GPIO_WriteBit (GPIOE, GPIO_Pin_3, 1);
ESP_LOGW (TAG, "Waiting for idle");
MESH_LOGW (TAG, "Waiting for idle");
vTaskDelay (pdMS_TO_TICKS (10));
// ensure BUSY is low (state meachine ready)
WaitForIdle (BUSY_WAIT, "Reset", 1);
@@ -512,7 +543,7 @@ void SetDioIrqParams (uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, ui
}
void SetStopRxTimerOnPreambleDetect (char enable) {
ESP_LOGI (TAG, "SetStopRxTimerOnPreambleDetect enable=%d", enable);
MESH_LOGI (TAG, "SetStopRxTimerOnPreambleDetect enable=%d", enable);
// uint8_t data = (uint8_t)enable;
uint8_t data = 0;
if (enable)
@@ -573,7 +604,7 @@ void ClearIrqStatus (uint16_t irq) {
void SetRx (uint32_t timeout) {
if (debugPrint) {
ESP_LOGI (TAG, "----- SetRx timeout=%d", timeout);
MESH_LOGI (TAG, "----- SetRx timeout=%d", timeout);
}
SetStandby (SX126X_STANDBY_RC);
uint8_t buf[3];
@@ -588,14 +619,14 @@ void SetRx (uint32_t timeout) {
vTaskDelay (pdMS_TO_TICKS (1));
}
if ((GetStatus() & 0x70) != 0x50) {
ESP_LOGE (TAG, "SetRx Illegal Status");
MESH_LOGE (TAG, "SetRx Illegal Status");
LoRaError (ERR_INVALID_SETRX_STATE);
}
}
void SetTx (uint32_t timeoutInMs) {
if (debugPrint) {
ESP_LOGI (TAG, "----- SetTx timeoutInMs=%d", timeoutInMs);
MESH_LOGI (TAG, "----- SetTx timeoutInMs=%d", timeoutInMs);
}
SetStandby (SX126X_STANDBY_RC);
uint8_t buf[3];
@@ -605,7 +636,9 @@ void SetTx (uint32_t timeoutInMs) {
tout = (uint32_t)(timeoutInUs / 0.015625);
}
if (debugPrint) {
ESP_LOGI (TAG, "SetTx timeoutInMs=%d" " tout=%d", timeoutInMs, tout);
MESH_LOGI (TAG, "SetTx timeoutInMs=%d"
" tout=%d",
timeoutInMs, tout);
}
buf[0] = (uint8_t)((tout >> 16) & 0xFF);
buf[1] = (uint8_t)((tout >> 8) & 0xFF);
@@ -618,7 +651,7 @@ void SetTx (uint32_t timeoutInMs) {
vTaskDelay (1);
}
if ((GetStatus() & 0x70) != 0x60) {
ESP_LOGE (TAG, "SetTx Illegal Status");
MESH_LOGE (TAG, "SetTx Illegal Status");
LoRaError (ERR_INVALID_SETTX_STATE);
}
}
@@ -649,7 +682,7 @@ void WaitForIdleBegin (unsigned long timeout, char *text) {
char ret = WaitForIdle (BUSY_WAIT, text, stop);
if (ret == 1)
break;
ESP_LOGW (TAG, "WaitForIdle fail retry=%d", retry);
MESH_LOGW (TAG, "WaitForIdle fail retry=%d", retry);
vTaskDelay (pdMS_TO_TICKS (10));
}
}
@@ -666,22 +699,23 @@ char WaitForIdle (unsigned long timeout, char *text, char stop) {
if (GPIO_ReadInputDataBit (GPIOE, GPIO_Pin_1)) {
if (stop) {
ESP_LOGE (TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%d", text, timeout, start);
MESH_LOGE (TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%d", text, timeout, start);
LoRaError (ERR_IDLE_TIMEOUT);
} else {
ESP_LOGW (TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%d", text, timeout, start);
MESH_LOGW (TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%d", text, timeout, start);
ret = 0;
}
}
return ret;
}
/*
uint8_t ReadBuffer (uint8_t *rxData, int16_t rxDataLen) {
uint8_t offset = 0;
uint8_t payloadLength = 0;
GetRxBufferStatus (&payloadLength, &offset);
if (payloadLength > rxDataLen) {
ESP_LOGW (TAG, "ReadBuffer rxDataLen too small. payloadLength=%d rxDataLen=%d", payloadLength, rxDataLen);
MESH_LOGW (TAG, "ReadBuffer rxDataLen too small. payloadLength=%d rxDataLen=%d", payloadLength, rxDataLen);
return 0;
}
@@ -700,13 +734,35 @@ uint8_t ReadBuffer (uint8_t *rxData, int16_t rxDataLen) {
memcpy (rxData, &buf[3], payloadLength);
free (buf);
} else {
ESP_LOGE (TAG, "ReadBuffer malloc fail");
MESH_LOGE (TAG, "ReadBuffer malloc fail");
payloadLength = 0;
}
// wait for BUSY to go low
WaitForIdle (BUSY_WAIT, "end ReadBuffer", 0);
return payloadLength;
}*/
uint8_t ReadBuffer (uint8_t *rxData, int16_t rxDataLen) {
uint8_t offset = 0;
uint8_t payloadLength = 0;
GetRxBufferStatus (&payloadLength, &offset);
if (payloadLength > rxDataLen) {
MESH_LOGW (TAG, "ReadBuffer rxDataLen too small. payloadLength=%d rxDataLen=%d", payloadLength, rxDataLen);
return 0;
}
WaitForIdle (BUSY_WAIT, "start ReadBuffer", 1);
uint8_t cmd[3] = {SX126X_CMD_READ_BUFFER, offset, SX126X_CMD_NOP};
spi_read_byte_offs (rxData, cmd, rxDataLen, sizeof (cmd));
WaitForIdle (BUSY_WAIT, "end ReadBuffer", 0);
return payloadLength;
}
@@ -724,7 +780,7 @@ void WriteBuffer (uint8_t *txData, int16_t txDataLen) {
spi_write_byte (buf, txDataLen + 2);
free (buf);
} else {
ESP_LOGE (TAG, "WriteBuffer malloc fail");
MESH_LOGE (TAG, "WriteBuffer malloc fail");
}
// wait for BUSY to go low
@@ -736,9 +792,9 @@ void WriteRegister (uint16_t reg, uint8_t *data, uint8_t numBytes) {
WaitForIdle (BUSY_WAIT, "start WriteRegister", 1);
if (debugPrint) {
ESP_LOGI (TAG, "WriteRegister: REG=0x%02x", reg);
MESH_LOGI (TAG, "WriteRegister: REG=0x%02x", reg);
for (uint8_t n = 0; n < numBytes; n++) {
ESP_LOGI (TAG, "DataOut:%02x ", data[n]);
MESH_LOGI (TAG, "DataOut:%02x ", data[n]);
}
}
@@ -759,7 +815,7 @@ void ReadRegister (uint16_t reg, uint8_t *data, uint8_t numBytes) {
WaitForIdle (BUSY_WAIT, "start ReadRegister", 1);
if (debugPrint) {
ESP_LOGI (TAG, "ReadRegister: REG=0x%02x", reg);
MESH_LOGI (TAG, "ReadRegister: REG=0x%02x", reg);
}
// start transfer
@@ -771,15 +827,15 @@ void ReadRegister (uint16_t reg, uint8_t *data, uint8_t numBytes) {
buf[1] = (reg & 0xFF00) >> 8;
buf[2] = reg & 0xff;
if (debugPrint) {
ESP_LOGI (TAG, "Reading bytes");
MESH_LOGI (TAG, "Reading bytes");
}
spi_read_byte (buf2, buf, 4 + numBytes);
ESP_LOGI (TAG, "read a byte");
MESH_LOGI (TAG, "read a byte");
memcpy (data, &buf2[4], numBytes);
if (debugPrint) {
for (uint8_t n = 0; n < numBytes; n++) {
ESP_LOGI (TAG, "DataIn:%02x ", data[n]);
MESH_LOGI (TAG, "DataIn:%02x ", data[n]);
}
}
@@ -793,14 +849,14 @@ void WriteCommand (uint8_t cmd, uint8_t *data, uint8_t numBytes) {
for (int retry = 1; retry < 10; retry++) {
status = WriteCommand2 (cmd, data, numBytes);
if (debugPrint) {
ESP_LOGD (TAG, "status=%02x", status);
MESH_LOGD (TAG, "status=%02x", status);
}
if (status == 0)
break;
ESP_LOGW (TAG, "WriteCommand2 status=%02x retry=%d", status, retry);
MESH_LOGW (TAG, "WriteCommand2 status=%02x retry=%d", status, retry);
}
if (status != 0) {
ESP_LOGE (TAG, "SPI Transaction error:0x%02x", status);
MESH_LOGE (TAG, "SPI Transaction error:0x%02x", status);
LoRaError (ERR_SPI_TRANSACTION);
}
}
@@ -810,7 +866,7 @@ uint8_t WriteCommand2 (uint8_t cmd, uint8_t *data, uint8_t numBytes) {
WaitForIdle (BUSY_WAIT, "start WriteCommand2", 1);
if (debugPrint) {
ESP_LOGI (TAG, "WriteCommand: CMD=0x%02x", cmd);
MESH_LOGI (TAG, "WriteCommand: CMD=0x%02x", cmd);
}
// start transfer
@@ -846,7 +902,7 @@ void ReadCommand (uint8_t cmd, uint8_t *data, uint8_t numBytes) {
WaitForIdleBegin (BUSY_WAIT, "start ReadCommand");
if (debugPrint) {
ESP_LOGI (TAG, "ReadCommand: CMD=0x%02x", cmd);
MESH_LOGI (TAG, "ReadCommand: CMD=0x%02x", cmd);
}
// start transfer

View File

@@ -381,10 +381,11 @@ void LoRaDebugPrint(char enable);
// Private function
void spi_write_byte(uint8_t* Dataout, size_t DataLength );
void spi_read_byte(uint8_t *rx, const uint8_t *tx, size_t len);
void spi_read_byte_offs (uint8_t *rx, const uint8_t *tx, size_t len, uint8_t off);
uint8_t spi_transfer(uint8_t address);
char ReceiveMode(void);
void GetPacketStatus(int8_t *rssiPacket, int8_t *snrPacket);
void GetPacketStatus (int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr);
void SetTxPower(int8_t txPowerInDbm);
void FixInvertedIQ(uint8_t iqConfig);
@@ -429,5 +430,8 @@ void ReadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes);
void SPItransfer(uint8_t cmd, char write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, char waitForBusy);
void LoRaError(int error);
extern uint8_t PacketParams[6];
extern char txActive;
extern int txLost;
#endif

View File

@@ -1,20 +1,33 @@
#ifndef LOGGER_HEADER
#define LOGGER_HEADER
// Define log levels
#define LOG_ERROR "E"
#define LOG_WARN "W"
#define LOG_INFO "I"
#define LOG_DEBUG "D"
#include <stdio.h>
// Define a generic log macro
#define LOG_PRINT(level, tag, fmt, ...) \
printf("[%s] %s: " fmt "\r\n", level, tag, ##__VA_ARGS__)
// Log levels as integers for easy comparison
#define LOG_LEVEL_ERROR 0
#define LOG_LEVEL_WARN 1
#define LOG_LEVEL_INFO 2
#define LOG_LEVEL_DEBUG 3
#define LOG_LEVEL_VERBOSE 4
// Define ESP-like shortcuts
#define ESP_LOGE(tag, fmt, ...) LOG_PRINT(LOG_ERROR, tag, fmt, ##__VA_ARGS__)
#define ESP_LOGW(tag, fmt, ...) LOG_PRINT(LOG_WARN, tag, fmt, ##__VA_ARGS__)
#define ESP_LOGI(tag, fmt, ...) LOG_PRINT(LOG_INFO, tag, fmt, ##__VA_ARGS__)
#define ESP_LOGD(tag, fmt, ...) LOG_PRINT(LOG_DEBUG, tag, fmt, ##__VA_ARGS__)
// Current log level (change at runtime or compile-time)
#ifndef CURRENT_LOG_LEVEL
#define CURRENT_LOG_LEVEL LOG_LEVEL_DEBUG
#endif
// Internal macro to check log level
#define LOG_PRINT_IF(level, levelStr, tag, fmt, ...) \
do { \
if ((level) <= CURRENT_LOG_LEVEL) { \
printf("[%s] %s: " fmt "\r\n", levelStr, tag, ##__VA_ARGS__); \
} \
} while(0)
// ESP-like shortcuts
#define MESH_LOGE(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_ERROR, "E", tag, fmt, ##__VA_ARGS__)
#define MESH_LOGW(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_WARN, "W", tag, fmt, ##__VA_ARGS__)
#define MESH_LOGI(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_INFO, "I", tag, fmt, ##__VA_ARGS__)
#define MESH_LOGD(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_DEBUG, "D", tag, fmt, ##__VA_ARGS__)
#define MESH_LOGV(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_VERBOSE, "V", tag, fmt, ##__VA_ARGS__)
#endif