RF parameter monitoring
This commit is contained in:
parent
2a31ef0096
commit
9489f34542
|
@ -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)
|
|
@ -0,0 +1,5 @@
|
|||
PROJECT_NAME := monitoring
|
||||
|
||||
EXTRA_COMPONENT_DIRS := $(abspath ../..)
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
|
@ -0,0 +1,4 @@
|
|||
idf_component_register(
|
||||
SRCS "main.cpp"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES ttn-esp32)
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -29,12 +29,121 @@ typedef uint8_t port_t;
|
|||
*/
|
||||
enum TTNResponseCode
|
||||
{
|
||||
kTTNErrorTransmissionFailed = -1,
|
||||
kTTNErrorUnexpected = -10,
|
||||
kTTNSuccessfulTransmission = 1,
|
||||
kTTNSuccessfulReceive = 2
|
||||
kTTNErrorTransmissionFailed = -1,
|
||||
kTTNErrorUnexpected = -10,
|
||||
kTTNSuccessfulTransmission = 1,
|
||||
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
|
||||
*
|
||||
|
@ -200,7 +309,7 @@ public:
|
|||
* parameters. The values are only valid during the duration of the
|
||||
* 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
|
||||
* return control to the caller.
|
||||
*
|
||||
|
@ -261,6 +370,36 @@ public:
|
|||
*/
|
||||
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:
|
||||
TTNMessageCallback messageCallback;
|
||||
|
||||
|
|
|
@ -63,10 +63,14 @@ static TTNProvisioning provisioning;
|
|||
#if LMIC_ENABLE_event_logging
|
||||
static TTNLogging* logging;
|
||||
#endif
|
||||
static TTNRFSettings lastRfSettings[4];
|
||||
static TTNRxTxWindow currentWindow;
|
||||
|
||||
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 messageTransmittedCallback(void *userData, int success);
|
||||
static void saveRFSettings(TTNRFSettings& rfSettings);
|
||||
static void clearRFSettings(TTNRFSettings& rfSettings);
|
||||
|
||||
|
||||
TheThingsNetwork::TheThingsNetwork()
|
||||
|
@ -110,6 +114,7 @@ void TheThingsNetwork::reset()
|
|||
{
|
||||
ttn_hal.enterCriticalSection();
|
||||
LMIC_reset();
|
||||
LMIC_setClockError(MAX_CLOCK_ERROR * 4 / 100);
|
||||
waitingReason = eWaitingNone;
|
||||
ttn_hal.leaveCriticalSection();
|
||||
}
|
||||
|
@ -289,6 +294,32 @@ void TheThingsNetwork::setAdrEnabled(bool 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 ---
|
||||
|
||||
|
@ -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
|
||||
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
|
||||
logging->logEvent(event, eventNames[event], 0);
|
||||
#elif CONFIG_LOG_DEFAULT_LEVEL >= 3
|
||||
|
@ -345,3 +404,19 @@ void messageTransmittedCallback(void *userData, int success)
|
|||
TTNLmicEvent result(success ? eEvtTransmissionCompleted : eEvtTransmissionFailed);
|
||||
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