really still wip
This commit is contained in:
1
.mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot
Normal file
1
.mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot
Normal file
File diff suppressed because one or more lines are too long
@@ -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
250
User/lib/adc/temperature.c
Normal 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
113
User/lib/adc/temperature.h
Normal 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
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
0
User/lib/telemetry/telemetry.c
Normal file
0
User/lib/telemetry/telemetry.c
Normal file
93
User/lib/telemetry/telemetry.h
Normal file
93
User/lib/telemetry/telemetry.h
Normal 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
|
||||
133
User/main.c
133
User/main.c
@@ -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,13 +79,21 @@ 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();
|
||||
//ed25519_create_keypair (persistent.pubkey, persistent.privkey, "vFt0FRugSOeqnkshImMCVfgHM5vBxz4");
|
||||
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");
|
||||
// persistent.nodeType = NODE_TYPE_CHAT_NODE;
|
||||
MESH_LOGD (TAG, "Task2 boot3");
|
||||
// persistent.nodeType = NODE_TYPE_CHAT_NODE;
|
||||
persistent.nodeType = NODE_TYPE_REPEATER;
|
||||
memset (persistent.password, 0, sizeof (persistent.password));
|
||||
strcpy (persistent.password, "hesielko");
|
||||
@@ -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();
|
||||
@@ -99,9 +152,9 @@ void task2_task (void *pvParameters) {
|
||||
plainTextMessage.timestamp = RTC_GetCounter();
|
||||
plainTextMessage.textType = 0;
|
||||
plainTextMessage.attempt = 0;
|
||||
snprintf(plainTextMessage.message, sizeof(plainTextMessage.message), "Sending message at SySTick is %d", xTaskGetTickCount());
|
||||
snprintf (plainTextMessage.message, sizeof (plainTextMessage.message), "Sending message at SySTick is %d", xTaskGetTickCount());
|
||||
printf ("Sending a direct message to the first node\n");
|
||||
sendEncryptedTextMessage(&(persistent.contacts[0]), &plainTextMessage);
|
||||
sendEncryptedTextMessage (&(persistent.contacts[0]), &plainTextMessage);
|
||||
}
|
||||
}
|
||||
vTaskDelay (pdMS_TO_TICKS (2000));
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
#include <ctype.h>
|
||||
#include "stdio.h"
|
||||
|
||||
void processFrame (FrameStruct frame);
|
||||
void processFrame (const FrameStruct * frame);
|
||||
|
||||
#endif
|
||||
@@ -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) {
|
||||
@@ -173,8 +408,8 @@ int encrypt_then_mac (const uint8_t *aes_key, const uint8_t keySize, const uint8
|
||||
|
||||
// prepare padded buffer
|
||||
uint8_t padded[padded_len];
|
||||
memset(padded, 0, padded_len); // zero padding
|
||||
memcpy(padded, plaintext, plen); // copy plaintext
|
||||
memset (padded, 0, padded_len); // zero padding
|
||||
memcpy (padded, plaintext, plen); // copy plaintext
|
||||
|
||||
// ciphertext will go right after HMAC
|
||||
uint8_t *ciphertext = output + HMAC_SIZE;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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, ×tamp, 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);
|
||||
}
|
||||
/*
|
||||
|
||||
if (dataFlags & ADVERTISEMENT_FLAG_RFU1) {
|
||||
memcpy(frame.payload + offset, &persistent.rfu1, sizeof(persistent.rfu1));
|
||||
offset += sizeof(persistent.rfu1);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
/* ---- send ---- */
|
||||
frame.payloadLen = offset;
|
||||
frame.path.pathLen = 0;
|
||||
sendFrame (frame);
|
||||
LoRaTransmit (&frame);
|
||||
}
|
||||
|
||||
AdvertisementPayload decodeAdvertisement (FrameStruct 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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -61,36 +62,103 @@ void sendAnonymousRequest (NodeEntry *targetNode, const uint8_t *password, uint3
|
||||
|
||||
// 5. Finalize and send
|
||||
frame.payloadLen = offset;
|
||||
memcpy(&(frame.path), &(targetNode->path), sizeof(frame.path));
|
||||
memcpy (&(frame.path), &(targetNode->path), sizeof (frame.path));
|
||||
|
||||
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,30 +172,39 @@ 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++] = 0; // legacy
|
||||
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;
|
||||
resp.data[index3++] = FIRMWARE_VER_LEVEL;
|
||||
resp.dataLen = index3;
|
||||
sendEncryptedResponse(foundNode, &resp);
|
||||
}
|
||||
|
||||
return anonReq;
|
||||
sendEncryptedResponse (foundNode, &resp);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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) {
|
||||
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);
|
||||
uint8_t pubKeyLen = (remainingLen > 8) ? sizeof (discResp.pubkey) : 8;
|
||||
discResp.pubkeyLen = pubKeyLen;
|
||||
memcpy (discResp.pubkey, &(frame->payload[index]), discResp.pubkeyLen);
|
||||
index += pubKeyLen;
|
||||
|
||||
printDiscoverResponse (&discResp);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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,22 +49,22 @@ 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];
|
||||
uint8_t index = 0;
|
||||
|
||||
uint8_t msgLen = strlen(msg->message) + 1;
|
||||
uint8_t msgLen = strlen (msg->message) + 1;
|
||||
buf[index++] = msg->timestamp;
|
||||
buf[index++] = msg->timestamp >> 8;
|
||||
buf[index++] = msg->timestamp >> 16;
|
||||
@@ -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);
|
||||
sendDiscreteAck(enc.payload, 5 + strlen((char *)&enc.payload[5]), remNode->pubKey);
|
||||
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();
|
||||
memcpy(resp.data, &stats, sizeof(stats));
|
||||
resp.dataLen = sizeof(stats);
|
||||
sendEncryptedResponse(enc.remNode, &resp);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -9,61 +9,64 @@
|
||||
|
||||
#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, ×tamp, 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) {
|
||||
GroupTextMessage msg;
|
||||
strcpy((char *) msg.text, persistent.nodeName);
|
||||
strcpy ((char *)msg.text, persistent.nodeName);
|
||||
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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#include "stats.h"
|
||||
|
||||
RepeaterStats stats;
|
||||
|
||||
uint32_t startupTime = 0;
|
||||
uint32_t tickAirtime = 0;
|
||||
@@ -4,4 +4,8 @@
|
||||
|
||||
extern RepeaterStats stats;
|
||||
|
||||
extern uint32_t startupTime;
|
||||
|
||||
extern uint32_t tickAirtime;
|
||||
|
||||
#endif
|
||||
138
User/sx1262.c
138
User/sx1262.c
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user