barback32/main/lorcomm.c

174 lines
4.4 KiB
C

#include <string.h>
#include "esp_log.h"
#include "esp32-lora.h"
#include "lorcomm.h"
#include "main.h"
#define TAG "lorcomm"
#define MSG_ID_TRACK (16)
typedef struct {
uint8_t mac[3];
uint8_t ids[MSG_ID_TRACK];
} id_cache_t;
uint8_t mac[6] = {0};
static uint8_t msg_id = 1;
id_cache_t id_cache[MSG_ID_TRACK] = { 0 };
uint8_t acmp(uint8_t a[], uint8_t b[], uint8_t len) {
for(uint8_t i = 0; i < len; i++) {
if(a[i] != b[i]) return 0;
}
return 1;
}
void lorcomm_handle_receive(uint8_t size) {
printf("packet size: %d\n", size);
uint8_t *buf = malloc(size);
lora_packet *packet = malloc(sizeof(lora_packet));
// get data from the lora driver
lora32_read_data(&lora, buf);
// copy buffer onto message headers
memcpy(packet, buf, LORA_PACKET_HEADER_SIZE);
ESP_LOGI(TAG, "[%02X:%02X:%02X] id: %02d type: %02X", packet->src[0], packet->src[1], packet->src[2], packet->id, packet->type);
for(uint8_t i = 0; i < MSG_ID_TRACK; i++) {
if(id_cache[i].mac[0]+id_cache[i].mac[1]+id_cache[i].mac[2] == 0) {
memcpy(id_cache[i].mac, &packet->src, 3);
// this is assumed to be empty
id_cache[i].ids[0] = packet->id;
ESP_LOGI(TAG, "adding new tracking entity");
break;
}
for(uint8_t j = 0; j < MSG_ID_TRACK; j++) {
if(id_cache[i].ids[j] == packet->id) {
ESP_LOGI(TAG, "already seen packet, not relaying");
goto receive_cleanup;
} else if(id_cache[i].ids[j] == 0) {
ESP_LOGI(TAG, "adding id to tracking");
// add id to array
id_cache[i].ids[i] = packet->id;
// set next in queue to zero, rolling over as needed
id_cache[i].ids[(i + 1) % MSG_ID_TRACK] = 0;
goto break_outer;
}
}
}
break_outer:
// update local msg id to incoming +1
// this will give a rolling local area id
if(packet->id < msg_id) {
msg_id = packet->id + 1;
// 0 is an invalid id
if(msg_id == 0) msg_id = 1;
}
if(memcmp(packet->src, &mac[3], 3) == 0) {
ESP_LOGI(TAG, "received own packet, done");
goto receive_cleanup;
}
if(packet->type == TEXT) {
lora_msg *msg = malloc(sizeof(lora_msg));
memcpy(msg, buf + LORA_PACKET_HEADER_SIZE, LORA_MSG_HEADER_SIZE);
// allocate memory for message payload
msg->msg = malloc(msg->length);
memcpy(msg->msg, buf + LORA_PACKET_HEADER_SIZE + LORA_MSG_HEADER_SIZE, msg->length);
// if the msg doesnt end in NULL it's probably already corrupt
// just go ahead and terminate it
//if(msg->msg[msg->length] != '\0')
//msg->msg[msg->length] = '\0';
ESP_LOGI(TAG, "msg (len: %d): %s", msg->length, msg->msg);
free(msg->msg);
msg->msg = NULL;
free(msg);
} else if(packet->type == ROUTING) {
// future stuff
} else {
ESP_LOGW(TAG, "Unknown packet type: %02X", packet->type);
ESP_LOGW(TAG, "msg: %s", (char*)packet);
goto receive_cleanup;
}
vTaskDelay(3000/portTICK_PERIOD_MS);
ESP_LOGI(TAG, "relaying message");
lora32_send(&lora, buf, size);
receive_cleanup:
free(buf);
lora32_enable_continuous_rx(&lora);
}
void lorcomm_send_message(lora32_cfg_t *lora, char *text) {
// allocate and zero out packet and msg payload
uint8_t len = strlen(text) + 1;
lora_packet packet = { 0 };
lora_msg msg = { 0 };
// set packet tracking id
packet.id = msg_id;
msg_id = msg_id + 1;
if(msg_id == 0) msg_id = 1;
// set src and dest (broadcast) addresses
memcpy(packet.src, &mac[3], 3);
memset(packet.dst, 0xFF, 3);
// indicate message payload
packet.type = TEXT;
packet.payload = malloc(LORA_PACKET_HEADER_SIZE + len);
msg.length = len;
msg.msg = malloc(LORA_MSG_HEADER_SIZE + len);
memcpy(msg.msg, text, len);
uint8_t buf_len = LORA_PACKET_HEADER_SIZE + LORA_MSG_HEADER_SIZE + len;
uint8_t *send_buf = malloc(buf_len);
ESP_LOGI(TAG, "packet length: %d", buf_len);
// set src, dst, length
memcpy(send_buf, (uint8_t*)&packet, LORA_PACKET_HEADER_SIZE);
memcpy((uint8_t*)(send_buf + LORA_PACKET_HEADER_SIZE), (void*)&msg, LORA_MSG_HEADER_SIZE);
memcpy((uint8_t*)(send_buf + LORA_PACKET_HEADER_SIZE + LORA_MSG_HEADER_SIZE), (void*)msg.msg, len);
ESP_LOGI(TAG, "id: %02d", packet.id);
ESP_LOGI(TAG, "src: [%02X:%02X:%02X]", packet.src[0], packet.src[1], packet.src[2]);
ESP_LOGI(TAG, "dst: [%02X:%02X:%02X]", packet.dst[0], packet.dst[1], packet.dst[2]);
lora32_send(lora, send_buf, buf_len);
free(packet.payload);
packet.payload = NULL;
free(msg.msg);
msg.msg = NULL;
free(send_buf);
}