mirror of
https://github.com/manuelbl/ttn-esp32.git
synced 2025-06-15 12:24:27 +02:00
RF parameter monitoring
This commit is contained in:
parent
2a31ef0096
commit
9489f34542
8
examples/monitoring/CMakeLists.txt
Normal file
8
examples/monitoring/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
|
||||||
|
# Update the below line to match the path to the ttn-esp32 library,
|
||||||
|
# e.g. list(APPEND EXTRA_COMPONENT_DIRS "/Users/me/Documents/ttn-esp32")
|
||||||
|
list(APPEND EXTRA_COMPONENT_DIRS "../..")
|
||||||
|
|
||||||
|
project(monitoring)
|
5
examples/monitoring/Makefile
Normal file
5
examples/monitoring/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
PROJECT_NAME := monitoring
|
||||||
|
|
||||||
|
EXTRA_COMPONENT_DIRS := $(abspath ../..)
|
||||||
|
|
||||||
|
include $(IDF_PATH)/make/project.mk
|
4
examples/monitoring/main/CMakeLists.txt
Normal file
4
examples/monitoring/main/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
idf_component_register(
|
||||||
|
SRCS "main.cpp"
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
REQUIRES ttn-esp32)
|
0
examples/monitoring/main/component.mk
Normal file
0
examples/monitoring/main/component.mk
Normal file
140
examples/monitoring/main/main.cpp
Normal file
140
examples/monitoring/main/main.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* ttn-esp32 - The Things Network device library for ESP-IDF / SX127x
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Manuel Bleichenbacher
|
||||||
|
*
|
||||||
|
* Licensed under MIT License
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*
|
||||||
|
* Sample program showing how to send and receive messages.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
#include "TheThingsNetwork.h"
|
||||||
|
|
||||||
|
// NOTE:
|
||||||
|
// The LoRaWAN frequency and the radio chip must be configured by running 'make menuconfig'.
|
||||||
|
// Go to Components / The Things Network, select the appropriate values and save.
|
||||||
|
|
||||||
|
// Copy the below hex string from the "Device EUI" field
|
||||||
|
// on your device's overview page in the TTN console.
|
||||||
|
const char *devEui = "????????????????";
|
||||||
|
|
||||||
|
// Copy the below two lines from bottom of the same page
|
||||||
|
const char *appEui = "????????????????";
|
||||||
|
const char *appKey = "????????????????????????????????";
|
||||||
|
|
||||||
|
// Pins and other resources
|
||||||
|
#define TTN_SPI_HOST HSPI_HOST
|
||||||
|
#define TTN_SPI_DMA_CHAN 1
|
||||||
|
#define TTN_PIN_SPI_SCLK 5
|
||||||
|
#define TTN_PIN_SPI_MOSI 27
|
||||||
|
#define TTN_PIN_SPI_MISO 19
|
||||||
|
#define TTN_PIN_NSS 18
|
||||||
|
#define TTN_PIN_RXTX TTN_NOT_CONNECTED
|
||||||
|
#define TTN_PIN_RST 14
|
||||||
|
#define TTN_PIN_DIO0 26
|
||||||
|
#define TTN_PIN_DIO1 35
|
||||||
|
|
||||||
|
static TheThingsNetwork ttn;
|
||||||
|
|
||||||
|
const unsigned TX_INTERVAL = 30;
|
||||||
|
static uint8_t msgData[] = "Hello, world";
|
||||||
|
|
||||||
|
|
||||||
|
void printRFSettings(const char* window, const TTNRFSettings& settings)
|
||||||
|
{
|
||||||
|
int bw = (1 << (static_cast<int>(settings.bandwidth) - 1)) * 125;
|
||||||
|
int sf = static_cast<int>(settings.spreadingFactor) + 5;
|
||||||
|
|
||||||
|
if (settings.spreadingFactor == kTTNSFNone)
|
||||||
|
{
|
||||||
|
printf("%s: not used\n", window);
|
||||||
|
}
|
||||||
|
else if (settings.spreadingFactor == kTTNFSK)
|
||||||
|
{
|
||||||
|
printf("%s: FSK, BW %dkHz, %d.%d MHz\n",
|
||||||
|
window, bw, settings.frequency / 1000000, (settings.frequency % 1000000 + 50000) / 100000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%s: SF%d, BW %dkHz, %d.%d MHz\n",
|
||||||
|
window, sf, bw, settings.frequency / 1000000, (settings.frequency % 1000000 + 50000) / 100000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printAllRFSettings()
|
||||||
|
{
|
||||||
|
printRFSettings("TX ", ttn.txSettings());
|
||||||
|
printRFSettings("RX1", ttn.rx1Settings());
|
||||||
|
printRFSettings("RX2", ttn.rx2Settings());
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMessages(void* pvParameter)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
printf("Sending message...\n");
|
||||||
|
TTNResponseCode res = ttn.transmitMessage(msgData, sizeof(msgData) - 1);
|
||||||
|
printf(res == kTTNSuccessfulTransmission ? "Message sent.\n" : "Transmission failed.\n");
|
||||||
|
printAllRFSettings();
|
||||||
|
|
||||||
|
vTaskDelay(TX_INTERVAL * pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void messageReceived(const uint8_t* message, size_t length, port_t port)
|
||||||
|
{
|
||||||
|
printf("Message of %d bytes received on port %d:", length, port);
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
printf(" %02x", message[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void app_main(void)
|
||||||
|
{
|
||||||
|
esp_err_t err;
|
||||||
|
// Initialize the GPIO ISR handler service
|
||||||
|
err = gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
|
// Initialize the NVS (non-volatile storage) for saving and restoring the keys
|
||||||
|
err = nvs_flash_init();
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
|
// Initialize SPI bus
|
||||||
|
spi_bus_config_t spi_bus_config;
|
||||||
|
spi_bus_config.miso_io_num = TTN_PIN_SPI_MISO;
|
||||||
|
spi_bus_config.mosi_io_num = TTN_PIN_SPI_MOSI;
|
||||||
|
spi_bus_config.sclk_io_num = TTN_PIN_SPI_SCLK;
|
||||||
|
spi_bus_config.quadwp_io_num = -1;
|
||||||
|
spi_bus_config.quadhd_io_num = -1;
|
||||||
|
spi_bus_config.max_transfer_sz = 0;
|
||||||
|
err = spi_bus_initialize(TTN_SPI_HOST, &spi_bus_config, TTN_SPI_DMA_CHAN);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
|
// Configure the SX127x pins
|
||||||
|
ttn.configurePins(TTN_SPI_HOST, TTN_PIN_NSS, TTN_PIN_RXTX, TTN_PIN_RST, TTN_PIN_DIO0, TTN_PIN_DIO1);
|
||||||
|
|
||||||
|
// The below line can be commented after the first run as the data is saved in NVS
|
||||||
|
ttn.provision(devEui, appEui, appKey);
|
||||||
|
|
||||||
|
// Register callback for received messages
|
||||||
|
ttn.onMessage(messageReceived);
|
||||||
|
|
||||||
|
printf("Joining...\n");
|
||||||
|
if (ttn.join())
|
||||||
|
{
|
||||||
|
printf("Joined.\n");
|
||||||
|
printAllRFSettings();
|
||||||
|
xTaskCreate(sendMessages, "send_messages", 1024 * 4, (void* )0, 3, nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Join failed. Goodbye\n");
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,115 @@ enum TTNResponseCode
|
|||||||
kTTNSuccessfulReceive = 2
|
kTTNSuccessfulReceive = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RX/TX window
|
||||||
|
*/
|
||||||
|
enum TTNRxTxWindow
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Outside RX/TX window
|
||||||
|
*/
|
||||||
|
kTTNIdleWindow = 0,
|
||||||
|
/**
|
||||||
|
* @brief Transmission window (up to RX1 window)
|
||||||
|
*/
|
||||||
|
kTTNTxWindow = 1,
|
||||||
|
/**
|
||||||
|
* @brief Reception window 1 (up to RX2 window)
|
||||||
|
*/
|
||||||
|
kTTNRx1Window = 2,
|
||||||
|
/**
|
||||||
|
* @brief Reception window 2
|
||||||
|
*/
|
||||||
|
kTTNRx2Window = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Spreading Factor
|
||||||
|
*/
|
||||||
|
enum TTNSpreadingFactor
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Unused / undefined spreading factor
|
||||||
|
*/
|
||||||
|
kTTNSFNone = 0,
|
||||||
|
/**
|
||||||
|
* @brief Frequency Shift Keying (FSK)
|
||||||
|
*/
|
||||||
|
kTTNFSK = 1,
|
||||||
|
/**
|
||||||
|
* @brief Spreading Factor 7 (SF7)
|
||||||
|
*/
|
||||||
|
kTTNSF7 = 2,
|
||||||
|
/**
|
||||||
|
* @brief Spreading Factor 8 (SF8)
|
||||||
|
*/
|
||||||
|
kTTNSF8 = 3,
|
||||||
|
/**
|
||||||
|
* @brief Spreading Factor 9 (SF9)
|
||||||
|
*/
|
||||||
|
kTTNSF9 = 4,
|
||||||
|
/**
|
||||||
|
* @brief Spreading Factor 10 (SF10)
|
||||||
|
*/
|
||||||
|
kTTNSF10 = 5,
|
||||||
|
/**
|
||||||
|
* @brief Spreading Factor 11 (SF11)
|
||||||
|
*/
|
||||||
|
kTTNSF11 = 6,
|
||||||
|
/**
|
||||||
|
* @brief Spreading Factor 12 (SF12)
|
||||||
|
*/
|
||||||
|
kTTNSF12 = 7
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bandwidth
|
||||||
|
*/
|
||||||
|
enum TTNBandwidth
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Undefined/unused bandwidth
|
||||||
|
*/
|
||||||
|
kTTNBWNone = 0,
|
||||||
|
/**
|
||||||
|
* @brief Bandwidth of 125 kHz
|
||||||
|
*/
|
||||||
|
kTTNBW125 = 1,
|
||||||
|
/**
|
||||||
|
* @brief Bandwidth of 250 kHz
|
||||||
|
*/
|
||||||
|
kTTNBW250 = 2,
|
||||||
|
/**
|
||||||
|
* @brief Bandwidth of 500 kHz
|
||||||
|
*/
|
||||||
|
kTTNBW500 = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RF settings for TX or RX
|
||||||
|
*/
|
||||||
|
struct TTNRFSettings
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Spreading Factor (SF)
|
||||||
|
*/
|
||||||
|
TTNSpreadingFactor spreadingFactor;
|
||||||
|
/**
|
||||||
|
* @brief Bandwidth (BW)
|
||||||
|
*/
|
||||||
|
TTNBandwidth bandwidth;
|
||||||
|
/**
|
||||||
|
* @brief Frequency, in Hz
|
||||||
|
*/
|
||||||
|
uint32_t frequency;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Callback for recieved messages
|
* @brief Callback for recieved messages
|
||||||
*
|
*
|
||||||
@ -200,7 +309,7 @@ public:
|
|||||||
* parameters. The values are only valid during the duration of the
|
* parameters. The values are only valid during the duration of the
|
||||||
* callback. So they must be immediately processed or copied.
|
* callback. So they must be immediately processed or copied.
|
||||||
*
|
*
|
||||||
* Messages are received as a result of 'transmitMessage' or 'poll'. The callback is called
|
* Messages are received as a result of 'transmitMessage'. The callback is called
|
||||||
* in the task that called any of these functions and it occurs before these functions
|
* in the task that called any of these functions and it occurs before these functions
|
||||||
* return control to the caller.
|
* return control to the caller.
|
||||||
*
|
*
|
||||||
@ -261,6 +370,36 @@ public:
|
|||||||
*/
|
*/
|
||||||
void startup();
|
void startup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets currentRX/TX window
|
||||||
|
* @return window
|
||||||
|
*/
|
||||||
|
TTNRxTxWindow rxTxWindow();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the RF settings for the specified window
|
||||||
|
* @param window RX/TX windows (valid values are `kTTNTxWindow`, `kTTNRx1Window` and `kTTNRx2Window`)
|
||||||
|
*/
|
||||||
|
TTNRFSettings getRFSettings(TTNRxTxWindow window);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the RF settings of the last (or ongoing) transmission.
|
||||||
|
* @return RF settings
|
||||||
|
*/
|
||||||
|
TTNRFSettings txSettings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the RF settings of the last (or ongoing) reception of RX window 1.
|
||||||
|
* @return RF settings
|
||||||
|
*/
|
||||||
|
TTNRFSettings rx1Settings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the RF settings of the last (or ongoing) reception of RX window 2.
|
||||||
|
* @return RF settings
|
||||||
|
*/
|
||||||
|
TTNRFSettings rx2Settings();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TTNMessageCallback messageCallback;
|
TTNMessageCallback messageCallback;
|
||||||
|
|
||||||
|
@ -63,10 +63,14 @@ static TTNProvisioning provisioning;
|
|||||||
#if LMIC_ENABLE_event_logging
|
#if LMIC_ENABLE_event_logging
|
||||||
static TTNLogging* logging;
|
static TTNLogging* logging;
|
||||||
#endif
|
#endif
|
||||||
|
static TTNRFSettings lastRfSettings[4];
|
||||||
|
static TTNRxTxWindow currentWindow;
|
||||||
|
|
||||||
static void eventCallback(void* userData, ev_t event);
|
static void eventCallback(void* userData, ev_t event);
|
||||||
static void messageReceivedCallback(void *userData, uint8_t port, const uint8_t *message, size_t messageSize);
|
static void messageReceivedCallback(void *userData, uint8_t port, const uint8_t *message, size_t messageSize);
|
||||||
static void messageTransmittedCallback(void *userData, int success);
|
static void messageTransmittedCallback(void *userData, int success);
|
||||||
|
static void saveRFSettings(TTNRFSettings& rfSettings);
|
||||||
|
static void clearRFSettings(TTNRFSettings& rfSettings);
|
||||||
|
|
||||||
|
|
||||||
TheThingsNetwork::TheThingsNetwork()
|
TheThingsNetwork::TheThingsNetwork()
|
||||||
@ -110,6 +114,7 @@ void TheThingsNetwork::reset()
|
|||||||
{
|
{
|
||||||
ttn_hal.enterCriticalSection();
|
ttn_hal.enterCriticalSection();
|
||||||
LMIC_reset();
|
LMIC_reset();
|
||||||
|
LMIC_setClockError(MAX_CLOCK_ERROR * 4 / 100);
|
||||||
waitingReason = eWaitingNone;
|
waitingReason = eWaitingNone;
|
||||||
ttn_hal.leaveCriticalSection();
|
ttn_hal.leaveCriticalSection();
|
||||||
}
|
}
|
||||||
@ -289,6 +294,32 @@ void TheThingsNetwork::setAdrEnabled(bool enabled)
|
|||||||
LMIC_setAdrMode(enabled);
|
LMIC_setAdrMode(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TTNRFSettings TheThingsNetwork::getRFSettings(TTNRxTxWindow window)
|
||||||
|
{
|
||||||
|
int index = static_cast<int>(window) & 0x03;
|
||||||
|
return lastRfSettings[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
TTNRFSettings TheThingsNetwork::txSettings()
|
||||||
|
{
|
||||||
|
return lastRfSettings[static_cast<int>(kTTNTxWindow)];
|
||||||
|
}
|
||||||
|
|
||||||
|
TTNRFSettings TheThingsNetwork::rx1Settings()
|
||||||
|
{
|
||||||
|
return lastRfSettings[static_cast<int>(kTTNRx1Window)];
|
||||||
|
}
|
||||||
|
|
||||||
|
TTNRFSettings TheThingsNetwork::rx2Settings()
|
||||||
|
{
|
||||||
|
return lastRfSettings[static_cast<int>(kTTNRx2Window)];
|
||||||
|
}
|
||||||
|
|
||||||
|
TTNRxTxWindow TheThingsNetwork::rxTxWindow()
|
||||||
|
{
|
||||||
|
return currentWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- Callbacks ---
|
// --- Callbacks ---
|
||||||
|
|
||||||
@ -300,6 +331,34 @@ const char *eventNames[] = { LMIC_EVENT_NAME_TABLE__INIT };
|
|||||||
// Called by LMIC when an LMIC event (join, join failed, reset etc.) occurs
|
// Called by LMIC when an LMIC event (join, join failed, reset etc.) occurs
|
||||||
void eventCallback(void* userData, ev_t event)
|
void eventCallback(void* userData, ev_t event)
|
||||||
{
|
{
|
||||||
|
// update monitoring information
|
||||||
|
switch(event)
|
||||||
|
{
|
||||||
|
case EV_TXSTART:
|
||||||
|
currentWindow = kTTNTxWindow;
|
||||||
|
saveRFSettings(lastRfSettings[static_cast<int>(kTTNTxWindow)]);
|
||||||
|
clearRFSettings(lastRfSettings[static_cast<int>(kTTNRx1Window)]);
|
||||||
|
clearRFSettings(lastRfSettings[static_cast<int>(kTTNRx2Window)]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EV_RXSTART:
|
||||||
|
if (currentWindow != kTTNRx1Window)
|
||||||
|
{
|
||||||
|
currentWindow = kTTNRx1Window;
|
||||||
|
saveRFSettings(lastRfSettings[static_cast<int>(kTTNRx1Window)]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentWindow = kTTNRx2Window;
|
||||||
|
saveRFSettings(lastRfSettings[static_cast<int>(kTTNRx2Window)]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
currentWindow = kTTNIdleWindow;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
#if LMIC_ENABLE_event_logging
|
#if LMIC_ENABLE_event_logging
|
||||||
logging->logEvent(event, eventNames[event], 0);
|
logging->logEvent(event, eventNames[event], 0);
|
||||||
#elif CONFIG_LOG_DEFAULT_LEVEL >= 3
|
#elif CONFIG_LOG_DEFAULT_LEVEL >= 3
|
||||||
@ -345,3 +404,19 @@ void messageTransmittedCallback(void *userData, int success)
|
|||||||
TTNLmicEvent result(success ? eEvtTransmissionCompleted : eEvtTransmissionFailed);
|
TTNLmicEvent result(success ? eEvtTransmissionCompleted : eEvtTransmissionFailed);
|
||||||
xQueueSend(lmicEventQueue, &result, pdMS_TO_TICKS(100));
|
xQueueSend(lmicEventQueue, &result, pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --- Helpers
|
||||||
|
|
||||||
|
|
||||||
|
void saveRFSettings(TTNRFSettings& rfSettings)
|
||||||
|
{
|
||||||
|
rfSettings.spreadingFactor = static_cast<TTNSpreadingFactor>(getSf(LMIC.rps) + 1);
|
||||||
|
rfSettings.bandwidth = static_cast<TTNBandwidth>(getBw(LMIC.rps) + 1);
|
||||||
|
rfSettings.frequency = LMIC.freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearRFSettings(TTNRFSettings& rfSettings)
|
||||||
|
{
|
||||||
|
memset(&rfSettings, 0, sizeof(rfSettings));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user