mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 03:06:33 +00:00
Add support for AU915 (#23372)
This commit is contained in:
parent
5d8b90d83b
commit
b5ae6bc035
@ -13,86 +13,146 @@
|
|||||||
#define USE_LORAWAN
|
#define USE_LORAWAN
|
||||||
#endif
|
#endif
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* LoRa defines and global struct
|
* LoRa and LoRaWan defines and global struct
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
//#define USE_LORA_DEBUG
|
//#define USE_LORA_DEBUG
|
||||||
|
|
||||||
#define XDRV_73_KEY "drvset73"
|
#define XDRV_73_KEY "drvset73"
|
||||||
|
|
||||||
#ifndef TAS_LORA_FREQUENCY
|
/*********************************************************************************************/
|
||||||
#define TAS_LORA_FREQUENCY 868.0 // Allowed values range from 150.0 to 960.0 MHz
|
|
||||||
|
// AU915 value
|
||||||
|
#ifndef TAS_LORA_AU915_FREQUENCY
|
||||||
|
#define TAS_LORA_AU915_FREQUENCY 915.0 // Allowed values range from 150.0 to 960.0 MHz
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// EU868 value
|
||||||
|
#ifndef TAS_LORA_FREQUENCY
|
||||||
|
#define TAS_LORA_FREQUENCY 868.0 // Allowed values range from 150.0 to 960.0 MHz
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Common LoRa values
|
||||||
#ifndef TAS_LORA_BANDWIDTH
|
#ifndef TAS_LORA_BANDWIDTH
|
||||||
#define TAS_LORA_BANDWIDTH 125.0 // Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0 and 500.0 kHz
|
#define TAS_LORA_BANDWIDTH 125.0 // Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0 and 500.0 kHz
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORA_SPREADING_FACTOR
|
#ifndef TAS_LORA_SPREADING_FACTOR
|
||||||
#define TAS_LORA_SPREADING_FACTOR 9 // Allowed values range from 5 to 12
|
#define TAS_LORA_SPREADING_FACTOR 9 // Allowed values range from 5 to 12
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORA_CODING_RATE
|
#ifndef TAS_LORA_CODING_RATE
|
||||||
#define TAS_LORA_CODING_RATE 7 // Allowed values range from 5 to 8
|
#define TAS_LORA_CODING_RATE 7 // Allowed values range from 5 to 8
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORA_SYNC_WORD
|
#ifndef TAS_LORA_SYNC_WORD
|
||||||
#define TAS_LORA_SYNC_WORD 0x12 // Allowed values range from 1 to 255
|
#define TAS_LORA_SYNC_WORD 0x12 // Allowed values range from 1 to 255
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORA_OUTPUT_POWER
|
#ifndef TAS_LORA_OUTPUT_POWER
|
||||||
#define TAS_LORA_OUTPUT_POWER 10 // Allowed values range from 1 to 20
|
#define TAS_LORA_OUTPUT_POWER 10 // Allowed values range from 1 to 20
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORA_PREAMBLE_LENGTH
|
#ifndef TAS_LORA_PREAMBLE_LENGTH
|
||||||
#define TAS_LORA_PREAMBLE_LENGTH 8 // Allowed values range from 1 to 65535
|
#define TAS_LORA_PREAMBLE_LENGTH 8 // Allowed values range from 1 to 65535
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORA_CURRENT_LIMIT
|
#ifndef TAS_LORA_CURRENT_LIMIT
|
||||||
#define TAS_LORA_CURRENT_LIMIT 60.0 // Overcurrent Protection - OCP in mA
|
#define TAS_LORA_CURRENT_LIMIT 60.0 // Overcurrent Protection - OCP in mA
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORA_HEADER
|
#ifndef TAS_LORA_HEADER
|
||||||
#define TAS_LORA_HEADER 0 // Explicit (0) or Implicit (1 to 4) Header
|
#define TAS_LORA_HEADER 0 // Explicit (0) or Implicit (1 to 4) Header
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORA_CRC_BYTES
|
#ifndef TAS_LORA_CRC_BYTES
|
||||||
#define TAS_LORA_CRC_BYTES 2 // No (0) or Number (1 to 4) of CRC bytes
|
#define TAS_LORA_CRC_BYTES 2 // No (0) or Number (1 to 4) of CRC bytes
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
// AU915 values
|
||||||
|
// These are default AU915 values when waiting for JOIN REQUEST
|
||||||
|
// AU915 has 2 sets up UPLINK channels
|
||||||
|
#ifndef TAS_LORAWAN_AU915_FREQUENCY_UP1
|
||||||
|
#define TAS_LORAWAN_AU915_FREQUENCY_UP1 915.2 // Channel 0. There are 64 125 MHz channels (0-63), spaced 0.2 MHz apart.
|
||||||
|
#endif
|
||||||
|
#ifndef TAS_LORAWAN_AU915_BANDWIDTH_UP1
|
||||||
|
#define TAS_LORAWAN_AU915_BANDWIDTH_UP1 125.0 // Allowed values are 125.0 and 500.0 kHz
|
||||||
|
#endif
|
||||||
|
#ifndef TAS_LORAWAN_AU915_SPREADING_FACTOR_UP1
|
||||||
|
#define TAS_LORAWAN_AU915_SPREADING_FACTOR_UP1 10 // Allowed values range from 7 to 12
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TAS_LORAWAN_AU915_FREQUENCY_UP2
|
||||||
|
#define TAS_LORAWAN_AU915_FREQUENCY_UP2 915.9 // Channel 64. There are 8 500 MHz channels (64-71), spaced 1.6 MHz apart
|
||||||
|
#endif
|
||||||
|
#ifndef TAS_LORAWAN_AU915_BANDWIDTH_UP2
|
||||||
|
#define TAS_LORAWAN_AU915_BANDWIDTH_UP2 500.0 // Allowed values are 125.0 and 500.0 kHz
|
||||||
|
#endif
|
||||||
|
#ifndef TAS_LORAWAN_AU915_SPREADING_FACTOR_UP2
|
||||||
|
#define TAS_LORAWAN_AU915_SPREADING_FACTOR_UP2 8 // Allowed values range from 7 to 12
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TAS_LORAWAN_AU915_FREQUENCY_DN
|
||||||
|
#define TAS_LORAWAN_AU915_FREQUENCY_DN 923.3 // Channel 0 down
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TAS_LORAWAN_AU915_BANDWIDTH_RX1
|
||||||
|
#define TAS_LORAWAN_AU915_BANDWIDTH_RX1 500 // DR8
|
||||||
|
#endif
|
||||||
|
#ifndef TAS_LORAWAN_AU915_SPREADING_FACTOR_RX1
|
||||||
|
#define TAS_LORAWAN_AU915_SPREADING_FACTOR_RX1 12 // DR8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TAS_LORAWAN_AU915_BANDWIDTH_RX2
|
||||||
|
#define TAS_LORAWAN_AU915_BANDWIDTH_RX2 500 // DR8
|
||||||
|
#endif
|
||||||
|
#ifndef TAS_LORAWAN_AU915_SPREADING_FACTOR_RX2
|
||||||
|
#define TAS_LORAWAN_AU915_SPREADING_FACTOR_RX2 12 // DR8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// EU868 values
|
||||||
#ifndef TAS_LORAWAN_FREQUENCY
|
#ifndef TAS_LORAWAN_FREQUENCY
|
||||||
#define TAS_LORAWAN_FREQUENCY 868.1 // Allowed values range from 150.0 to 960.0 MHz
|
#define TAS_LORAWAN_FREQUENCY 868.1 // Allowed values range from 150.0 to 960.0 MHz
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_BANDWIDTH
|
#ifndef TAS_LORAWAN_BANDWIDTH
|
||||||
#define TAS_LORAWAN_BANDWIDTH 125.0 // Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0 and 500.0 kHz
|
#define TAS_LORAWAN_BANDWIDTH 125.0 // Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0 and 500.0 kHz
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_SPREADING_FACTOR
|
#ifndef TAS_LORAWAN_SPREADING_FACTOR
|
||||||
#define TAS_LORAWAN_SPREADING_FACTOR 9 // Allowed values range from 5 to 12
|
#define TAS_LORAWAN_SPREADING_FACTOR 9 // Allowed values range from 5 to 12
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Common LoRaWan values
|
||||||
#ifndef TAS_LORAWAN_CODING_RATE
|
#ifndef TAS_LORAWAN_CODING_RATE
|
||||||
#define TAS_LORAWAN_CODING_RATE 5 // Allowed values range from 5 to 8
|
#define TAS_LORAWAN_CODING_RATE 5 // Allowed values range from 5 to 8
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_SYNC_WORD
|
#ifndef TAS_LORAWAN_SYNC_WORD
|
||||||
#define TAS_LORAWAN_SYNC_WORD 0x34 // Allowed values range from 1 to 255
|
#define TAS_LORAWAN_SYNC_WORD 0x34 // Allowed values range from 1 to 255
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_OUTPUT_POWER
|
#ifndef TAS_LORAWAN_OUTPUT_POWER
|
||||||
#define TAS_LORAWAN_OUTPUT_POWER 10 // Allowed values range from 1 to 20
|
#define TAS_LORAWAN_OUTPUT_POWER 10 // Allowed values range from 1 to 20
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_PREAMBLE_LENGTH
|
#ifndef TAS_LORAWAN_PREAMBLE_LENGTH
|
||||||
#define TAS_LORAWAN_PREAMBLE_LENGTH 8 // Allowed values range from 1 to 65535
|
#define TAS_LORAWAN_PREAMBLE_LENGTH 8 // Allowed values range from 1 to 65535
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_CURRENT_LIMIT
|
#ifndef TAS_LORAWAN_CURRENT_LIMIT
|
||||||
#define TAS_LORAWAN_CURRENT_LIMIT 60.0 // Overcurrent Protection - OCP in mA
|
#define TAS_LORAWAN_CURRENT_LIMIT 60.0 // Overcurrent Protection - OCP in mA
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_HEADER
|
#ifndef TAS_LORAWAN_HEADER
|
||||||
#define TAS_LORAWAN_HEADER 0 // Explicit (0) or Implicit (1 to 4) Header
|
#define TAS_LORAWAN_HEADER 0 // Explicit (0) or Implicit (1 to 4) Header
|
||||||
#endif
|
#endif
|
||||||
#ifndef TAS_LORAWAN_CRC_BYTES
|
#ifndef TAS_LORAWAN_CRC_BYTES
|
||||||
#define TAS_LORAWAN_CRC_BYTES 2 // No (0) or Number (1 to 4) of CRC bytes
|
#define TAS_LORAWAN_CRC_BYTES 2 // No (0) or Number (1 to 4) of CRC bytes
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TAS_LORA_MAX_PACKET_LENGTH 252 // Max packet length allowed (keeping room for control bytes)
|
/*********************************************************************************************/
|
||||||
#define TAS_LORA_REMOTE_COMMAND 0x17 // Header defining remote LoRaCommand
|
|
||||||
|
|
||||||
#define TAS_LORAWAN_JOINNONCE 0x00E50631 // Tasmota node 1 JoinNonce
|
#define TAS_LORA_MAX_PACKET_LENGTH 252 // Max packet length allowed (keeping room for control bytes)
|
||||||
#define TAS_LORAWAN_NETID 0x00000000 // Tasmota private network
|
#define TAS_LORA_REMOTE_COMMAND 0x17 // Header defining remote LoRaCommand
|
||||||
#define TAS_LORAWAN_RECEIVE_DELAY1 1000 // LoRaWan Receive delay 1
|
|
||||||
#define TAS_LORAWAN_RECEIVE_DELAY2 1000 // LoRaWan Receive delay 2
|
#define TAS_LORAWAN_JOINNONCE 0x00E50631 // Tasmota node 1 JoinNonce
|
||||||
#define TAS_LORAWAN_JOIN_ACCEPT_DELAY1 5000 // LoRaWan Join accept delay 1
|
#define TAS_LORAWAN_NETID 0x00000000 // Tasmota private network
|
||||||
#define TAS_LORAWAN_JOIN_ACCEPT_DELAY2 1000 // LoRaWan Join accept delay 2
|
#define TAS_LORAWAN_RECEIVE_DELAY1 1000 // LoRaWan Receive delay 1
|
||||||
#define TAS_LORAWAN_ENDNODES 4 // Max number of supported endnodes
|
#define TAS_LORAWAN_RECEIVE_DELAY2 1000 // LoRaWan Receive delay 2
|
||||||
#define TAS_LORAWAN_AES128_KEY_SIZE 16 // Size in bytes
|
#define TAS_LORAWAN_JOIN_ACCEPT_DELAY1 5000 // LoRaWan Join accept delay 1
|
||||||
|
#define TAS_LORAWAN_JOIN_ACCEPT_DELAY2 1000 // LoRaWan Join accept delay 2
|
||||||
|
#define TAS_LORAWAN_ENDNODES 4 // Max number of supported endnodes
|
||||||
|
#define TAS_LORAWAN_AES128_KEY_SIZE 16 // Size in bytes
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
enum TasLoraFlags {
|
enum TasLoraFlags {
|
||||||
TAS_LORA_FLAG_BRIDGE_ENABLED,
|
TAS_LORA_FLAG_BRIDGE_ENABLED,
|
||||||
@ -146,6 +206,24 @@ enum TasLoraWanCIDNode {
|
|||||||
TAS_LORAWAN_CID_DEVICE_TIME_REQ
|
TAS_LORAWAN_CID_DEVICE_TIME_REQ
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TasLoraRegion {
|
||||||
|
TAS_LORA_REGION_EU868, // 0
|
||||||
|
TAS_LORA_REGION_US915, // 1
|
||||||
|
TAS_LORA_REGION_CN779, // 2
|
||||||
|
TAS_LORA_REGION_EU433, // 3
|
||||||
|
TAS_LORA_REGION_AU915, // 4
|
||||||
|
TAS_LORA_REGION_CN470, // 5
|
||||||
|
TAS_LORA_REGION_AS923, // 6
|
||||||
|
TAS_LORA_REGION_KR920, // 7
|
||||||
|
TAS_LORA_REGION_IN865, // 8
|
||||||
|
TAS_LORA_REGION_RU864 // 9
|
||||||
|
};
|
||||||
|
|
||||||
|
// LoRaWan bands: One for each enum above
|
||||||
|
const char kLoraRegions[] PROGMEM = "EU868|US915|CN779|EU433|AU915|CN470|AS923|KR920|IN865|RU864";
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
typedef struct LoraNodeData_t {
|
typedef struct LoraNodeData_t {
|
||||||
float rssi;
|
float rssi;
|
||||||
float snr;
|
float snr;
|
||||||
@ -180,6 +258,7 @@ typedef struct LoraSettings_t {
|
|||||||
uint8_t implicit_header; // 0
|
uint8_t implicit_header; // 0
|
||||||
uint8_t crc_bytes; // 2 bytes
|
uint8_t crc_bytes; // 2 bytes
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
|
uint8_t region; // 0 = Default, 1 = AU915, ...
|
||||||
#ifdef USE_LORAWAN_BRIDGE
|
#ifdef USE_LORAWAN_BRIDGE
|
||||||
LoraEndNode_t end_node[TAS_LORAWAN_ENDNODES]; // End node parameters
|
LoraEndNode_t end_node[TAS_LORAWAN_ENDNODES]; // End node parameters
|
||||||
#endif // USE_LORAWAN_BRIDGE
|
#endif // USE_LORAWAN_BRIDGE
|
||||||
@ -190,6 +269,7 @@ typedef struct Lora_t {
|
|||||||
bool (* Available)(void);
|
bool (* Available)(void);
|
||||||
int (* Receive)(char*);
|
int (* Receive)(char*);
|
||||||
bool (* Send)(uint8_t*, uint32_t, bool);
|
bool (* Send)(uint8_t*, uint32_t, bool);
|
||||||
|
bool (* Init)(void);
|
||||||
LoraSettings_t settings; // Persistent settings
|
LoraSettings_t settings; // Persistent settings
|
||||||
volatile uint32_t receive_time;
|
volatile uint32_t receive_time;
|
||||||
float rssi;
|
float rssi;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#ifdef USE_SPI_LORA
|
#ifdef USE_SPI_LORA
|
||||||
#ifdef USE_LORAWAN_BRIDGE
|
#ifdef USE_LORAWAN_BRIDGE
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* EU868 LoRaWan bridge support
|
* EU868 and AU915 LoRaWan bridge support
|
||||||
*
|
*
|
||||||
* The goal of the LoRaWan Bridge is to receive from joined LoRaWan End-Devices or Nodes and
|
* The goal of the LoRaWan Bridge is to receive from joined LoRaWan End-Devices or Nodes and
|
||||||
* provide decrypted MQTT data.
|
* provide decrypted MQTT data.
|
||||||
@ -27,11 +27,11 @@
|
|||||||
* spreadingfactor using command
|
* spreadingfactor using command
|
||||||
* LoRaConfig 2
|
* LoRaConfig 2
|
||||||
* or individual commands
|
* or individual commands
|
||||||
* LoRaFrequency 868.1 (or 868.3 and 868.5)
|
* LoRaConfig {"Frequency":868.1} (or 868.3 and 868.5)
|
||||||
* LoRaSpreadingFactor 9 (or 7..12 equals LoRaWan DataRate 5..0)
|
* LoRaConfig {"SpreadingFactor":9} (or 7..12 equals LoRaWan DataRate 5..0)
|
||||||
* LoRaBandwidth 125
|
* LoRaConfig {"Bandwidth":125}
|
||||||
* LoRaCodingRate4 5
|
* LoRaConfig {"CodingRate4":5}
|
||||||
* LoRaSyncWord 52
|
* LoRaConfig {"SyncWord":52}
|
||||||
* - LoRaWan has to be enabled (#define USE_LORAWAN_BRIDGE) and configured for the End-Device
|
* - LoRaWan has to be enabled (#define USE_LORAWAN_BRIDGE) and configured for the End-Device
|
||||||
* 32 character AppKey using command LoRaWanAppKey <vendor provided appkey>
|
* 32 character AppKey using command LoRaWanAppKey <vendor provided appkey>
|
||||||
* - The End-Device needs to start it's LoRaWan join process as documented by vendor.
|
* - The End-Device needs to start it's LoRaWan join process as documented by vendor.
|
||||||
@ -110,7 +110,7 @@ bool LoraWanLoadData(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool LoraWanSaveData(void) {
|
bool LoraWanSaveData(void) {
|
||||||
bool result = false;
|
bool result = true; // Return true if no Endnodes
|
||||||
for (uint32_t n = 0; n < TAS_LORAWAN_ENDNODES; n++) {
|
for (uint32_t n = 0; n < TAS_LORAWAN_ENDNODES; n++) {
|
||||||
if (Lora->settings.end_node[n].AppKey[0] > 0) { // Only save used slots
|
if (Lora->settings.end_node[n].AppKey[0] > 0) { // Only save used slots
|
||||||
Response_P(PSTR("{\"" XDRV_73_KEY "_%d\":{\"" D_JSON_APPKEY "\":\"%16_H\""
|
Response_P(PSTR("{\"" XDRV_73_KEY "_%d\":{\"" D_JSON_APPKEY "\":\"%16_H\""
|
||||||
@ -126,17 +126,17 @@ bool LoraWanSaveData(void) {
|
|||||||
Lora->settings.end_node[n].FCntUp, Lora->settings.end_node[n].FCntDown,
|
Lora->settings.end_node[n].FCntUp, Lora->settings.end_node[n].FCntDown,
|
||||||
Lora->settings.end_node[n].flags,
|
Lora->settings.end_node[n].flags,
|
||||||
Lora->settings.end_node[n].name.c_str());
|
Lora->settings.end_node[n].name.c_str());
|
||||||
result = UfsJsonSettingsWrite(ResponseData());
|
result &= UfsJsonSettingsWrite(ResponseData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoraWanDeleteData(void) {
|
void LoraWanDeleteData(void) {
|
||||||
char key[12]; // Max 99 nodes (drvset73_1 to drvset73_99)
|
char key[12]; // Max 99 nodes (drvset73_1 to drvset73_99)
|
||||||
for (uint32_t n = 0; n < TAS_LORAWAN_ENDNODES; n++) {
|
for (uint32_t n = 0; n < TAS_LORAWAN_ENDNODES; n++) {
|
||||||
snprintf_P(key, sizeof(key), PSTR(XDRV_73_KEY "_%d"), n +1);
|
snprintf_P(key, sizeof(key), PSTR(XDRV_73_KEY "_%d"), n +1);
|
||||||
UfsJsonSettingsDelete(key); // Use defaults
|
UfsJsonSettingsDelete(key); // Use defaults
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_UFILESYS
|
#endif // USE_UFILESYS
|
||||||
@ -149,37 +149,89 @@ Ticker LoraWan_Send;
|
|||||||
void LoraWanTickerSend(void) {
|
void LoraWanTickerSend(void) {
|
||||||
Lora->send_buffer_step--;
|
Lora->send_buffer_step--;
|
||||||
if (1 == Lora->send_buffer_step) {
|
if (1 == Lora->send_buffer_step) {
|
||||||
Lora->rx = true; // Always send during RX1
|
Lora->rx = true; // Always send during RX1
|
||||||
Lora->receive_time = 0; // Reset receive timer
|
Lora->receive_time = 0; // Reset receive timer
|
||||||
LoraWan_Send.once_ms(TAS_LORAWAN_RECEIVE_DELAY2, LoraWanTickerSend); // Retry after 1000 ms
|
LoraWan_Send.once_ms(TAS_LORAWAN_RECEIVE_DELAY2, LoraWanTickerSend); // Retry after 1000 ms
|
||||||
}
|
}
|
||||||
if (Lora->rx) { // If received in RX1 do not resend in RX2
|
|
||||||
LoraSend(Lora->send_buffer, Lora->send_buffer_len, true);
|
bool uplink_profile = (Lora->settings.region == TAS_LORA_REGION_AU915);
|
||||||
|
if (Lora->rx) { // If received in RX1 do not resend in RX2
|
||||||
|
LoraSend(Lora->send_buffer, Lora->send_buffer_len, true, uplink_profile);
|
||||||
|
}
|
||||||
|
if (uplink_profile && (0 == Lora->send_buffer_step)) {
|
||||||
|
Lora->Init(); // Necessary to re-init the SXxxxx chip in cases where TX/RX frequencies differ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoraWanSendResponse(uint8_t* buffer, size_t len, uint32_t lorawan_delay) {
|
void LoraWanSendResponse(uint8_t* buffer, size_t len, uint32_t lorawan_delay) {
|
||||||
free(Lora->send_buffer); // Free previous buffer (if any)
|
free(Lora->send_buffer); // Free previous buffer (if any)
|
||||||
Lora->send_buffer = (uint8_t*)malloc(len +1);
|
Lora->send_buffer = (uint8_t*)malloc(len +1);
|
||||||
if (nullptr == Lora->send_buffer) { return; }
|
if (nullptr == Lora->send_buffer) { return; }
|
||||||
memcpy(Lora->send_buffer, buffer, len);
|
memcpy(Lora->send_buffer, buffer, len);
|
||||||
Lora->send_buffer_len = len;
|
Lora->send_buffer_len = len;
|
||||||
Lora->send_buffer_step = 2; // Send at RX1 and RX2
|
Lora->send_buffer_step = 2; // Send at RX1 and RX2
|
||||||
LoraWan_Send.once_ms(lorawan_delay - TimePassedSince(Lora->receive_time), LoraWanTickerSend);
|
LoraWan_Send.once_ms(lorawan_delay - TimePassedSince(Lora->receive_time), LoraWanTickerSend);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
uint32_t LoraWanSpreadingFactorToDataRate(void) {
|
size_t LoraWanCFList(uint8_t * CFList, size_t uLen) {
|
||||||
// Allow only JoinReq message datarates (125kHz bandwidth)
|
// Populates CFList for use in JOIN-ACCEPT message to lock device to specific frequencies
|
||||||
if (Lora->settings.spreading_factor > 12) {
|
// Returns: Number of bytes added
|
||||||
Lora->settings.spreading_factor = 12;
|
uint8_t idx = 0;
|
||||||
|
|
||||||
|
switch (Lora->settings.region) {
|
||||||
|
case TAS_LORA_REGION_AU915: {
|
||||||
|
if (uLen < 16) return 0;
|
||||||
|
|
||||||
|
uint8_t uChannel = LoraChannel(); // 0..71
|
||||||
|
uint8_t uMaskByte = uChannel /8; // 0..8
|
||||||
|
|
||||||
|
// Add first 10 bytes
|
||||||
|
for (uint32_t i = 0; i < 10; i++) {
|
||||||
|
CFList[idx++] = (i == uMaskByte) ? (0x01 << uChannel %8) : 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add next 6 bytes
|
||||||
|
CFList[idx++] = 0x00; //RFU
|
||||||
|
CFList[idx++] = 0x00;
|
||||||
|
|
||||||
|
CFList[idx++] = 0x00; //RFU
|
||||||
|
CFList[idx++] = 0x00;
|
||||||
|
CFList[idx++] = 0x00;
|
||||||
|
|
||||||
|
CFList[idx++] = 0x01; //CFListType
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: { // TAS_LORA_REGION_EU868
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (Lora->settings.spreading_factor < 7) {
|
return idx;
|
||||||
Lora->settings.spreading_factor = 7;
|
}
|
||||||
|
|
||||||
|
uint32_t LoraWanSpreadingFactorToDataRate(bool downlink) {
|
||||||
|
/*
|
||||||
|
Returns DLSettings defined as
|
||||||
|
Bits 7= RFA
|
||||||
|
6:4= RX1DROffset
|
||||||
|
3:0= RX2DataRate DateRate for RX2 window
|
||||||
|
*/
|
||||||
|
switch (Lora->settings.region) {
|
||||||
|
case TAS_LORA_REGION_AU915: {
|
||||||
|
return downlink ? 8 : 2; // AU915 must use DR8 for RX2, and we want to use DR2 for Uplinks
|
||||||
|
}
|
||||||
|
default: { // TAS_LORA_REGION_EU868
|
||||||
|
// Allow only JoinReq message datarates (125kHz bandwidth)
|
||||||
|
if (Lora->settings.spreading_factor > 12) {
|
||||||
|
Lora->settings.spreading_factor = 12;
|
||||||
|
}
|
||||||
|
if (Lora->settings.spreading_factor < 7) {
|
||||||
|
Lora->settings.spreading_factor = 7;
|
||||||
|
}
|
||||||
|
Lora->settings.bandwidth = 125;
|
||||||
|
return 12 - Lora->settings.spreading_factor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Lora->settings.bandwidth = 125;
|
|
||||||
return 12 - Lora->settings.spreading_factor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t LoraWanFrequencyToChannel(void) {
|
uint32_t LoraWanFrequencyToChannel(void) {
|
||||||
@ -217,15 +269,42 @@ void LoraWanSendLinkADRReq(uint32_t node) {
|
|||||||
data[2] = DevAddr >> 8;
|
data[2] = DevAddr >> 8;
|
||||||
data[3] = DevAddr >> 16;
|
data[3] = DevAddr >> 16;
|
||||||
data[4] = DevAddr >> 24;
|
data[4] = DevAddr >> 24;
|
||||||
data[5] = 0x05; // FCtrl with 5 FOpts
|
data[5] = 0x05; // FCtrl with 5 FOpts
|
||||||
data[6] = FCnt;
|
data[6] = FCnt;
|
||||||
data[7] = FCnt >> 8;
|
data[7] = FCnt >> 8;
|
||||||
data[8] = TAS_LORAWAN_CID_LINK_ADR_REQ;
|
data[8] = TAS_LORAWAN_CID_LINK_ADR_REQ;
|
||||||
data[9] = LoraWanSpreadingFactorToDataRate() << 4 | 0x0F; // DataRate 3 and unchanged TXPower
|
|
||||||
data[10] = 0x01 << LoraWanFrequencyToChannel(); // Single channel
|
|
||||||
data[11] = 0x00;
|
|
||||||
data[12] = 0x00; // ChMaskCntl applies to Channels0..15, NbTrans is default (1)
|
|
||||||
|
|
||||||
|
// Next 4 bytes are Region Specific
|
||||||
|
switch (Lora->settings.region) {
|
||||||
|
case TAS_LORA_REGION_AU915: {
|
||||||
|
//Ref: https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
||||||
|
// page 39
|
||||||
|
uint8_t uChannel = LoraChannel(); // 0..71
|
||||||
|
uint8_t ChMaskCntl = uChannel/16.0; // 0..4
|
||||||
|
uChannel = uChannel%16; // 0..15
|
||||||
|
uint16_t uMask = 0x01 << uChannel;
|
||||||
|
|
||||||
|
data[9] = LoraWanSpreadingFactorToDataRate(false) << 4 | 0x0F; // Uplink DataRate_TXPower Should be 'DR2' for & 'unchanged' = 0x2F
|
||||||
|
|
||||||
|
data[10] = uMask; // ChMask LSB
|
||||||
|
data[11] = uMask >> 8; // ChMask MSB
|
||||||
|
|
||||||
|
data[12] = ChMaskCntl << 4; // Redundancy:
|
||||||
|
// bits 7=RFU ------- 6:4=ChMaskCntl ----------- --- 3:0=NbTrans ---
|
||||||
|
// 0 000=Mask applies to Channels 0-15 0000 = Use Default
|
||||||
|
// 001=Mask applies to Channels 16-31
|
||||||
|
// ....
|
||||||
|
// 100=Mask applies to Channels 64-71
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: { // TAS_LORA_REGION_EU868
|
||||||
|
data[9] = LoraWanSpreadingFactorToDataRate(false) << 4 | 0x0F; // Uplink DataRate 3 and unchanged TXPower
|
||||||
|
data[10] = 0x01 << LoraWanFrequencyToChannel(); // Single channel
|
||||||
|
data[11] = 0x00;
|
||||||
|
data[12] = 0x00; // ChMaskCntl applies to Channels0..15, NbTrans is default (1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t MIC = LoraWanComputeLegacyDownlinkMIC(NwkSKey, DevAddr, FCnt, data, 13);
|
uint32_t MIC = LoraWanComputeLegacyDownlinkMIC(NwkSKey, DevAddr, FCnt, data, 13);
|
||||||
data[13] = MIC;
|
data[13] = MIC;
|
||||||
data[14] = MIC >> 8;
|
data[14] = MIC >> 8;
|
||||||
@ -308,34 +387,43 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
uint32_t DevAddr = Lora->device_address +node;
|
uint32_t DevAddr = Lora->device_address +node;
|
||||||
uint32_t NetID = TAS_LORAWAN_NETID;
|
uint32_t NetID = TAS_LORAWAN_NETID;
|
||||||
uint8_t join_data[33] = { 0 };
|
uint8_t join_data[33] = { 0 };
|
||||||
join_data[0] = TAS_LORAWAN_MTYPE_JOIN_ACCEPT << 5;
|
uint8_t join_data_index = 0;
|
||||||
join_data[1] = JoinNonce;
|
|
||||||
join_data[2] = JoinNonce >> 8;
|
|
||||||
join_data[3] = JoinNonce >> 16;
|
|
||||||
join_data[4] = NetID;
|
|
||||||
join_data[5] = NetID >> 8;
|
|
||||||
join_data[6] = NetID >> 16;
|
|
||||||
join_data[7] = DevAddr;
|
|
||||||
join_data[8] = DevAddr >> 8;
|
|
||||||
join_data[9] = DevAddr >> 16;
|
|
||||||
join_data[10] = DevAddr >> 24;
|
|
||||||
join_data[11] = LoraWanSpreadingFactorToDataRate(); // DLSettings
|
|
||||||
join_data[12] = 1; // RXDelay;
|
|
||||||
|
|
||||||
uint32_t NewMIC = LoraWanGenerateMIC(join_data, 13, Lora->settings.end_node[node].AppKey);
|
join_data[join_data_index++] = TAS_LORAWAN_MTYPE_JOIN_ACCEPT << 5; // [0]
|
||||||
join_data[13] = NewMIC;
|
join_data[join_data_index++] = JoinNonce;
|
||||||
join_data[14] = NewMIC >> 8;
|
join_data[join_data_index++] = JoinNonce >> 8;
|
||||||
join_data[15] = NewMIC >> 16;
|
join_data[join_data_index++] = JoinNonce >> 16;
|
||||||
join_data[16] = NewMIC >> 24;
|
join_data[join_data_index++] = NetID;
|
||||||
|
join_data[join_data_index++] = NetID >> 8;
|
||||||
|
join_data[join_data_index++] = NetID >> 16;
|
||||||
|
join_data[join_data_index++] = DevAddr;
|
||||||
|
join_data[join_data_index++] = DevAddr >> 8;
|
||||||
|
join_data[join_data_index++] = DevAddr >> 16;
|
||||||
|
join_data[join_data_index++] = DevAddr >> 24;
|
||||||
|
join_data[join_data_index++] = LoraWanSpreadingFactorToDataRate(true); // DLSettings - Downlink
|
||||||
|
join_data[join_data_index++] = 1; // RXDelay; [12]
|
||||||
|
|
||||||
|
// Add CFList to instruct device to use one channel
|
||||||
|
uint8_t CFList[16];
|
||||||
|
size_t CFListSize = LoraWanCFList(CFList, sizeof(CFList));
|
||||||
|
uint8_t CFListIdx = 0;
|
||||||
|
while (CFListSize > 0 ) {
|
||||||
|
join_data[join_data_index++] = CFList[CFListIdx++];
|
||||||
|
CFListSize--;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t NewMIC = LoraWanGenerateMIC(join_data, join_data_index, Lora->settings.end_node[node].AppKey);
|
||||||
|
join_data[join_data_index++] = NewMIC;
|
||||||
|
join_data[join_data_index++] = NewMIC >> 8;
|
||||||
|
join_data[join_data_index++] = NewMIC >> 16;
|
||||||
|
join_data[join_data_index++] = NewMIC >> 24; //[16] or [32]
|
||||||
uint8_t EncData[33];
|
uint8_t EncData[33];
|
||||||
EncData[0] = join_data[0];
|
EncData[0] = join_data[0];
|
||||||
LoraWanEncryptJoinAccept(Lora->settings.end_node[node].AppKey, &join_data[1], 16, &EncData[1]);
|
LoraWanEncryptJoinAccept(Lora->settings.end_node[node].AppKey, &join_data[1], join_data_index-1, &EncData[1]);
|
||||||
|
|
||||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Join %17_H"), join_data);
|
|
||||||
|
|
||||||
// 203106E5000000412E010003017CB31DD4 - Dragino
|
// 203106E5000000412E010003017CB31DD4 - Dragino
|
||||||
// 203206E5000000422E010003016A210EEA - MerryIoT
|
// 203206E5000000422E010003016A210EEA - MerryIoT
|
||||||
LoraWanSendResponse(EncData, 17, TAS_LORAWAN_JOIN_ACCEPT_DELAY1);
|
LoraWanSendResponse(EncData, join_data_index, TAS_LORAWAN_JOIN_ACCEPT_DELAY1);
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
break;
|
break;
|
||||||
@ -356,14 +444,16 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
// 80 412E0100 80 2A00 0A A58EF5E0D1DDE03424F0 6F2D56FA - decrypt using AppSKey
|
// 80 412E0100 80 2A00 0A A58EF5E0D1DDE03424F0 6F2D56FA - decrypt using AppSKey
|
||||||
// 80 412E0100 80 2B00 0A 8F2F0D33E5C5027D57A6 F67C9DFE - decrypt using AppSKey
|
// 80 412E0100 80 2B00 0A 8F2F0D33E5C5027D57A6 F67C9DFE - decrypt using AppSKey
|
||||||
// 80 909AE100 00 0800 0A EEC4A52568A346A8684E F2D4BF05
|
// 80 909AE100 00 0800 0A EEC4A52568A346A8684E F2D4BF05
|
||||||
// 40 412E0100 A0 1800 00 0395 2C94B1D8 - FCtrl ADR support, Ack, FPort = 0 -> MAC commands, decrypt using NwkSKey
|
// 40 412E0100 A0 1800 00 0395 2C94B1D8 - FCtrl ADR support , ADRACKReq=0, FPort = 0 -> MAC commands, decrypt using NwkSKey
|
||||||
// 40 412E0100 A0 7800 00 78C9 A60D8977 - FCtrl ADR support, Ack, FPort = 0 -> MAC commands, decrypt using NwkSKey
|
// 40 412E0100 A0 7800 00 78C9 A60D8977 - FCtrl ADR support , ADRACKReq=0, FPort = 0 -> MAC commands, decrypt using NwkSKey
|
||||||
// 40 F3F51700 20 0100 00 2A7C 407036A2 - FCtrl No ADR support, Ack, FPort = 0 -> MAC commands, decrypt using NwkSKey, response after LinkADRReq
|
// 40 F3F51700 20 0100 00 2A7C 407036A2 - FCtrl No ADR support, ADRACKReq=0, FPort = 0 -> MAC commands, decrypt using NwkSKey, response after LinkADRReq
|
||||||
// - MerryIoT
|
// - MerryIoT
|
||||||
// 40 422E0100 80 0400 78 B9C75DF9E8934C6651 A57DA6B1 - decrypt using AppSKey
|
// 40 422E0100 80 0400 78 B9C75DF9E8934C6651 A57DA6B1 - decrypt using AppSKey
|
||||||
// 40 422E0100 80 0100 CC 7C462537AC00C07F99 5500BF2B - decrypt using AppSKey
|
// 40 422E0100 80 0100 CC 7C462537AC00C07F99 5500BF2B - decrypt using AppSKey
|
||||||
// 40 422E0100 A2 1800 0307 78 29FBF8FD9227729984 8C71E95B - FCtrl ADR support, Ack, FOptsLen = 2 -> FOpts = MAC, response after LinkADRReq
|
// 40 422E0100 A2 1800 0307 78 29FBF8FD9227729984 8C71E95B - FCtrl ADR support, ADRACKReq=0, FOptsLen = 2 -> FOpts = MAC, response after LinkADRReq
|
||||||
// 40 F4F51700 A2 0200 0307 CC 6517D4AB06D32C9A9F 14CBA305 - FCtrl ADR support, Ack, FOptsLen = 2 -> FOpts = MAC, response after LinkADRReq
|
// 40 F4F51700 A2 0200 0307 CC 6517D4AB06D32C9A9F 14CBA305 - FCtrl ADR support, ADRACKReq=0, FOptsLen = 2 -> FOpts = MAC, response after LinkADRReq
|
||||||
|
|
||||||
|
bool bResponseSent = false; // Make sure do not send multiple responses
|
||||||
|
|
||||||
uint32_t DevAddr = (uint32_t)data[1] | ((uint32_t)data[2] << 8) | ((uint32_t)data[3] << 16) | ((uint32_t)data[4] << 24);
|
uint32_t DevAddr = (uint32_t)data[1] | ((uint32_t)data[2] << 8) | ((uint32_t)data[3] << 16) | ((uint32_t)data[4] << 24);
|
||||||
for (uint32_t node = 0; node < TAS_LORAWAN_ENDNODES; node++) {
|
for (uint32_t node = 0; node < TAS_LORAWAN_ENDNODES; node++) {
|
||||||
@ -384,8 +474,15 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
uint32_t CalcMIC = LoraWanComputeLegacyUplinkMIC(NwkSKey, DevAddr, FCnt, data, packet_size -4);
|
uint32_t CalcMIC = LoraWanComputeLegacyUplinkMIC(NwkSKey, DevAddr, FCnt, data, packet_size -4);
|
||||||
if (MIC != CalcMIC) { continue; } // Same device address but never joined
|
if (MIC != CalcMIC) { continue; } // Same device address but never joined
|
||||||
|
|
||||||
bool FCtrl_ADR = bitRead(FCtrl, 7);
|
bool FCtrl_ADR = bitRead(FCtrl, 7);
|
||||||
bool FCtrl_ACK = bitRead(FCtrl, 5);
|
bool FCtrl_ADRACKReq = bitRead(FCtrl, 6); //Device is requesting a response, so that it knows comms is still up.
|
||||||
|
// else device will eventually enter backoff mode and we loose comms
|
||||||
|
// ref: https://lora-alliance.org/wp-content/uploads/2021/11/LoRaWAN-Link-Layer-Specification-v1.0.4.pdf
|
||||||
|
// page 19
|
||||||
|
// In testing with a Dragino LHT52 device, FCtrl_ADRACKReq was set after 64 (0x40) uplinks (= 21.3 hrs)
|
||||||
|
bool FCtrl_ACK = bitRead(FCtrl, 5);
|
||||||
|
bool Fctrl_ClassB = bitRead(FCtrl, 4);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if ((0 == FOptsLen) && (0 == FOpts[0])) { // MAC response
|
if ((0 == FOptsLen) && (0 == FOpts[0])) { // MAC response
|
||||||
FOptsLen = payload_len;
|
FOptsLen = payload_len;
|
||||||
@ -491,6 +588,7 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (mac_data_idx > 0) {
|
if (mac_data_idx > 0) {
|
||||||
|
bResponseSent = true;
|
||||||
LoraWanSendMacResponse(node, mac_data, mac_data_idx);
|
LoraWanSendMacResponse(node, mac_data, mac_data_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,6 +624,7 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
data[packet_size -3] = MIC >> 8;
|
data[packet_size -3] = MIC >> 8;
|
||||||
data[packet_size -2] = MIC >> 16;
|
data[packet_size -2] = MIC >> 16;
|
||||||
data[packet_size -1] = MIC >> 24;
|
data[packet_size -1] = MIC >> 24;
|
||||||
|
bResponseSent = true;
|
||||||
LoraWanSendResponse(data, packet_size, TAS_LORAWAN_RECEIVE_DELAY1);
|
LoraWanSendResponse(data, packet_size, TAS_LORAWAN_RECEIVE_DELAY1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -533,10 +632,17 @@ bool LoraWanInput(uint8_t* data, uint32_t packet_size) {
|
|||||||
if (!bitRead(Lora->settings.end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ) &&
|
if (!bitRead(Lora->settings.end_node[node].flags, TAS_LORAWAN_FLAG_LINK_ADR_REQ) &&
|
||||||
FCtrl_ADR && !FCtrl_ACK) {
|
FCtrl_ADR && !FCtrl_ACK) {
|
||||||
// Try to fix single channel and datarate
|
// Try to fix single channel and datarate
|
||||||
|
bResponseSent = true;
|
||||||
LoraWanSendLinkADRReq(node); // Resend LinkADRReq
|
LoraWanSendLinkADRReq(node); // Resend LinkADRReq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!bResponseSent && FCtrl_ADRACKReq ) {
|
||||||
|
// FCtrl_ADRACKReq requires we send ANY Class A message. Here's one prepared earlier.
|
||||||
|
LoraWanSendLinkADRReq(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Not retransmission
|
||||||
result = true;
|
result = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -626,4 +732,4 @@ void LoraWanInit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_LORAWAN_BRIDGE
|
#endif // USE_LORAWAN_BRIDGE
|
||||||
#endif // USE_SPI_LORA
|
#endif // USE_SPI_LORA
|
@ -16,36 +16,242 @@
|
|||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
void LoraDefaults(void) {
|
void LoraDefaults(uint32_t region = TAS_LORA_REGION_EU868) {
|
||||||
Lora->settings.frequency = TAS_LORA_FREQUENCY;
|
Lora->settings.region = region;
|
||||||
Lora->settings.bandwidth = TAS_LORA_BANDWIDTH;
|
switch (region) {
|
||||||
|
case TAS_LORA_REGION_AU915:
|
||||||
|
Lora->settings.frequency = TAS_LORA_AU915_FREQUENCY;
|
||||||
|
break;
|
||||||
|
default: // TAS_LORA_REGION_EU868
|
||||||
|
Lora->settings.frequency = TAS_LORA_FREQUENCY;
|
||||||
|
}
|
||||||
|
Lora->settings.bandwidth = TAS_LORA_BANDWIDTH;
|
||||||
Lora->settings.spreading_factor = TAS_LORA_SPREADING_FACTOR;
|
Lora->settings.spreading_factor = TAS_LORA_SPREADING_FACTOR;
|
||||||
Lora->settings.coding_rate = TAS_LORA_CODING_RATE;
|
Lora->settings.coding_rate = TAS_LORA_CODING_RATE;
|
||||||
Lora->settings.sync_word = TAS_LORA_SYNC_WORD;
|
Lora->settings.sync_word = TAS_LORA_SYNC_WORD;
|
||||||
Lora->settings.output_power = TAS_LORA_OUTPUT_POWER;
|
Lora->settings.output_power = TAS_LORA_OUTPUT_POWER;
|
||||||
Lora->settings.preamble_length = TAS_LORA_PREAMBLE_LENGTH;
|
Lora->settings.preamble_length = TAS_LORA_PREAMBLE_LENGTH;
|
||||||
Lora->settings.current_limit = TAS_LORA_CURRENT_LIMIT;
|
Lora->settings.current_limit = TAS_LORA_CURRENT_LIMIT;
|
||||||
Lora->settings.implicit_header = TAS_LORA_HEADER;
|
Lora->settings.implicit_header = TAS_LORA_HEADER;
|
||||||
Lora->settings.crc_bytes = TAS_LORA_CRC_BYTES;
|
Lora->settings.crc_bytes = TAS_LORA_CRC_BYTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoraWanDefaults(void) {
|
/*********************************************************************************************/
|
||||||
Lora->settings.frequency = TAS_LORAWAN_FREQUENCY;
|
|
||||||
Lora->settings.bandwidth = TAS_LORAWAN_BANDWIDTH;
|
/*
|
||||||
Lora->settings.spreading_factor = TAS_LORAWAN_SPREADING_FACTOR;
|
For LoraWan EU bands, the Uplink/Downlink (TX/RX) frequencies can be the same.
|
||||||
Lora->settings.coding_rate = TAS_LORAWAN_CODING_RATE;
|
For Others, same Uplink/Downlink (TX/RX) frequencies may not be allowed.
|
||||||
Lora->settings.sync_word = TAS_LORAWAN_SYNC_WORD;
|
See: https://lora-alliance.org/wp-content/uploads/2020/11/RP_2-1.0.2.pdf
|
||||||
Lora->settings.output_power = TAS_LORAWAN_OUTPUT_POWER;
|
*/
|
||||||
Lora->settings.preamble_length = TAS_LORAWAN_PREAMBLE_LENGTH;
|
|
||||||
Lora->settings.current_limit = TAS_LORAWAN_CURRENT_LIMIT;
|
// Determines the channel from the current Uplink LoraSettings
|
||||||
Lora->settings.implicit_header = TAS_LORAWAN_HEADER;
|
// return 0..71
|
||||||
Lora->settings.crc_bytes = TAS_LORAWAN_CRC_BYTES;
|
uint32_t LoraChannel(void) {
|
||||||
|
float fFrequencyDiff;
|
||||||
|
uint8_t uChannel = 0;
|
||||||
|
|
||||||
|
switch (Lora->settings.region) {
|
||||||
|
case TAS_LORA_REGION_AU915:
|
||||||
|
if (125.0 == Lora->settings.bandwidth) {
|
||||||
|
fFrequencyDiff = Lora->settings.frequency - TAS_LORAWAN_AU915_FREQUENCY_UP1;
|
||||||
|
uChannel = (0.01 + (fFrequencyDiff / 0.2)); //0.01 to fix rounding errors
|
||||||
|
} else {
|
||||||
|
fFrequencyDiff = Lora->settings.frequency - TAS_LORAWAN_AU915_FREQUENCY_UP2;
|
||||||
|
uChannel = 64 + ((0.01 + (fFrequencyDiff / 1.6)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
//default:
|
||||||
|
//not implemented
|
||||||
|
}
|
||||||
|
return uChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoraSettings2Json(void) {
|
enum LoRaRadioMode_t {
|
||||||
ResponseAppend_P(PSTR("\"" D_JSON_FREQUENCY "\":%1_f"), &Lora->settings.frequency); // xxx.x MHz
|
TAS_LORAWAN_RADIO_UPLINK,
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":%1_f"), &Lora->settings.bandwidth); // xxx.x kHz
|
TAS_LORAWAN_RADIO_RX1,
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_SPREADING_FACTOR "\":%d"), Lora->settings.spreading_factor);
|
TAS_LORAWAN_RADIO_RX2
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct LoRaRadioInfo_t {
|
||||||
|
float frequency;
|
||||||
|
float bandwidth;
|
||||||
|
uint8_t spreading_factor;
|
||||||
|
} LoRaRadioInfo_t;
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
LoraRadioInfo()
|
||||||
|
Some regional profiles use different radio profiles for the Uplink, RX1, and RX2 transmissions
|
||||||
|
|
||||||
|
Get radio profiles for the Uplink, and RX1 & RX2 downlink transmissions
|
||||||
|
RX1 & RX2 profiles are derived from Lora->settings
|
||||||
|
|
||||||
|
****************************************************************************/
|
||||||
|
const uint8_t RX1DRs[] PROGMEM = {8,9,10,11,12,13,13}; //DR0..6
|
||||||
|
const uint8_t SF[] PROGMEM = {12,11,10,9,8,7,8,0,12,11,10,9,8,7}; //DR0..13
|
||||||
|
|
||||||
|
void LoraRadioInfo(uint8_t mode, void* pInfo) {
|
||||||
|
LoRaRadioInfo_t* pResult = (LoRaRadioInfo_t*) pInfo;
|
||||||
|
|
||||||
|
switch (Lora->settings.region) {
|
||||||
|
case TAS_LORA_REGION_AU915: {
|
||||||
|
//////////////// AU915 ////////////////////
|
||||||
|
/* ref: https://lora-alliance.org/wp-content/uploads/2020/11/RP_2-1.0.2.pdf page 47
|
||||||
|
DR0 LoRa: SF12 / 125 kHz
|
||||||
|
DR1 LoRa: SF11 / 125 kHz
|
||||||
|
DR2 LoRa: SF10 / 125 kHz <-- JOIN REQUEST
|
||||||
|
DR3 LoRa: SF9 / 125 kHz
|
||||||
|
DR4 LoRa: SF8 / 125 kHz
|
||||||
|
DR5 LoRa: SF7 / 125 kHz
|
||||||
|
DR6 LoRa: SF8 / 500 kHz Same as DR12
|
||||||
|
DR7 LR-FHSS CR1/3: 1.523 MHz OCW 162
|
||||||
|
DR8 LoRa: SF12 / 500 kHz
|
||||||
|
DR9 LoRa: SF11 / 500 kHz
|
||||||
|
DR10 LoRa: SF10 / 500 kHz
|
||||||
|
DR11 LoRa: SF9 / 500 kHz
|
||||||
|
DR12 LoRa: SF8 / 500 kHz Same as DR6
|
||||||
|
DR13 LoRa: SF7 / 500 kHz
|
||||||
|
|
||||||
|
UPLINK (RX) CHANNELS
|
||||||
|
There are 72 channels
|
||||||
|
0-63: DR0 to 5. Starting 915.2, incrementing by 0.2 Mhz to 927.8 <-- JOIN REQUEST
|
||||||
|
64-71: DR6 . Starting 915.9, incrementing by 1.6 MHz to 927.1
|
||||||
|
NOTE: Testing with two Dragino end devices shows they do not play nice with channels 64-71
|
||||||
|
1) LHT52 will JOIN OK on Ch64, but never sends any sensor messages on same channel
|
||||||
|
2) LHT65 will not even broadcast JOIN requests on any of the channels (as required by RP002)
|
||||||
|
For this reason, channels above 63 are not permitted.
|
||||||
|
|
||||||
|
DOWNLINK (TX) CHANNELS
|
||||||
|
There are 8 channels
|
||||||
|
0-7: DR8 to 13. Starting 923.3, incrementing by 0.6 MHz to 927.5
|
||||||
|
|
||||||
|
After an uplink: Downlink (TX) link subchannel = Uplink (RX) Channel Number modulo 8
|
||||||
|
e.g. --Uplink (RX)-- --Downlink (TX)--
|
||||||
|
Freq Channel Channel Frequency
|
||||||
|
915.2 0 0 923.3
|
||||||
|
927.8 63 7 927.1
|
||||||
|
|
||||||
|
After an uplink:
|
||||||
|
Downlink DR for RX1 must follow this table
|
||||||
|
Uplink Downlink
|
||||||
|
DR0 DR8
|
||||||
|
DR1 DR8
|
||||||
|
DR2 DR10 <----- channels 1-62
|
||||||
|
DR3 DR11
|
||||||
|
DR4 DR12
|
||||||
|
DR5 DR13
|
||||||
|
DR6 DR13 <------ channels 63-71
|
||||||
|
|
||||||
|
Downlink DR for RX2 must be DR8
|
||||||
|
|
||||||
|
Downlink
|
||||||
|
Reference: https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf)
|
||||||
|
Assume this is in response to an uplink RX, so we already know RX freq & bw & sf
|
||||||
|
TX channel depends on RX freq
|
||||||
|
DR for RX1 depends on incoming DR (and RX1DROffset)
|
||||||
|
DR for RX2 is fixed ar DR8
|
||||||
|
|
||||||
|
Tasmota does not support different RX1 & RX2 DRs (yet), so just use DR8 and rely on RX2 arriving at end device OK.
|
||||||
|
*/
|
||||||
|
uint32_t uChannel = LoraChannel();
|
||||||
|
uint8_t UplinkChannelBand = uChannel %8; //0..7
|
||||||
|
switch (mode) {
|
||||||
|
case TAS_LORAWAN_RADIO_UPLINK: {
|
||||||
|
// if (uChannel > 71) uChannel = 71; See note above
|
||||||
|
if (uChannel > 63) uChannel = 63;
|
||||||
|
if (uChannel < 64) {
|
||||||
|
(*pResult).frequency = TAS_LORAWAN_AU915_FREQUENCY_UP1 + (uChannel * 0.2);
|
||||||
|
(*pResult).bandwidth = TAS_LORAWAN_AU915_BANDWIDTH_UP1; //DR2
|
||||||
|
(*pResult).spreading_factor = TAS_LORAWAN_AU915_SPREADING_FACTOR_UP1; //DR2
|
||||||
|
} else {
|
||||||
|
(*pResult).frequency = TAS_LORAWAN_AU915_FREQUENCY_UP2 + ((uChannel-64) * 1.6);
|
||||||
|
(*pResult).bandwidth = TAS_LORAWAN_AU915_BANDWIDTH_UP2; //DR6
|
||||||
|
(*pResult).spreading_factor = TAS_LORAWAN_AU915_SPREADING_FACTOR_UP2; //DR6
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TAS_LORAWAN_RADIO_RX1: {
|
||||||
|
// RX1 DR depends on the Uplink settings
|
||||||
|
// https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
||||||
|
// Page 41
|
||||||
|
uint32_t UplinkDR = (125.0 == Lora->settings.bandwidth) ? (12 - Lora->settings.spreading_factor) : 6; // 0 .. 6
|
||||||
|
uint32_t RX1DR = pgm_read_byte(&RX1DRs[UplinkDR]);
|
||||||
|
uint32_t RX1SF = pgm_read_byte(&SF[RX1DR]);
|
||||||
|
float RX1BW = (RX1DR > 5) ? 500.0 : 125.0;
|
||||||
|
(*pResult).frequency = TAS_LORAWAN_AU915_FREQUENCY_DN + (UplinkChannelBand * 0.6);
|
||||||
|
(*pResult).bandwidth = RX1BW;
|
||||||
|
(*pResult).spreading_factor = RX1SF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TAS_LORAWAN_RADIO_RX2: {
|
||||||
|
(*pResult).frequency = TAS_LORAWAN_AU915_FREQUENCY_DN;
|
||||||
|
(*pResult).bandwidth = TAS_LORAWAN_AU915_BANDWIDTH_RX2;
|
||||||
|
(*pResult).spreading_factor = TAS_LORAWAN_AU915_SPREADING_FACTOR_RX2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// default:
|
||||||
|
// not implemented
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: { // TAS_LORA_REGION_EU868
|
||||||
|
//Default TX/RX1/TX1 same
|
||||||
|
(*pResult).frequency = TAS_LORAWAN_FREQUENCY;
|
||||||
|
(*pResult).bandwidth = TAS_LORAWAN_BANDWIDTH;
|
||||||
|
(*pResult).spreading_factor = TAS_LORAWAN_SPREADING_FACTOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoraWanDefaults(uint32_t region = TAS_LORA_REGION_EU868, LoRaRadioMode_t mode = TAS_LORAWAN_RADIO_UPLINK) {
|
||||||
|
bool multi_profile = false;
|
||||||
|
Lora->settings.region = region;
|
||||||
|
switch (region) {
|
||||||
|
case TAS_LORA_REGION_AU915:
|
||||||
|
// TO DO: Need 3 profiles: Uplink, RX1, RX2
|
||||||
|
// Works OK for now as RX2 always received by end device.
|
||||||
|
multi_profile = true;
|
||||||
|
LoRaRadioInfo_t RadioInfo;
|
||||||
|
LoraRadioInfo(mode, &RadioInfo); // Region specific
|
||||||
|
Lora->settings.frequency = RadioInfo.frequency;
|
||||||
|
Lora->settings.bandwidth = RadioInfo.bandwidth;
|
||||||
|
Lora->settings.spreading_factor = RadioInfo.spreading_factor;
|
||||||
|
break;
|
||||||
|
default: // TAS_LORA_REGION_EU868
|
||||||
|
Lora->settings.frequency = TAS_LORAWAN_FREQUENCY;
|
||||||
|
Lora->settings.bandwidth = TAS_LORAWAN_BANDWIDTH;
|
||||||
|
Lora->settings.spreading_factor = TAS_LORAWAN_SPREADING_FACTOR;
|
||||||
|
}
|
||||||
|
Lora->settings.coding_rate = TAS_LORAWAN_CODING_RATE;
|
||||||
|
Lora->settings.sync_word = TAS_LORAWAN_SYNC_WORD;
|
||||||
|
Lora->settings.output_power = TAS_LORAWAN_OUTPUT_POWER;
|
||||||
|
Lora->settings.preamble_length = TAS_LORAWAN_PREAMBLE_LENGTH;
|
||||||
|
Lora->settings.current_limit = TAS_LORAWAN_CURRENT_LIMIT;
|
||||||
|
Lora->settings.implicit_header = TAS_LORAWAN_HEADER;
|
||||||
|
Lora->settings.crc_bytes = TAS_LORAWAN_CRC_BYTES;
|
||||||
|
return multi_profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoraSettings2Json(bool show = false) {
|
||||||
|
if (show) {
|
||||||
|
char region[8];
|
||||||
|
ResponseAppend_P(PSTR("\"" D_JSON_REGION "\":\"%s\""), GetTextIndexed(region, sizeof(region), Lora->settings.region, kLoraRegions));
|
||||||
|
} else {
|
||||||
|
ResponseAppend_P(PSTR("\"" D_JSON_REGION "\":%d"), Lora->settings.region); // enum 0 = EU868, 1 = AU915
|
||||||
|
}
|
||||||
|
if (show && (Lora->settings.region == TAS_LORA_REGION_AU915)) {
|
||||||
|
LoRaRadioInfo_t Rx1Info;
|
||||||
|
LoraRadioInfo(TAS_LORAWAN_RADIO_RX1, &Rx1Info); // Get Rx1Info with values used for RX1 transmit window. (Region specific, calculated from Uplink radio settings)
|
||||||
|
LoRaRadioInfo_t Rx2Info;
|
||||||
|
LoraRadioInfo(TAS_LORAWAN_RADIO_RX2, &Rx2Info); // Get Rx2Info
|
||||||
|
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":[%1_f,%1_f,%1_f]"), &Lora->settings.frequency, &Rx1Info.frequency, &Rx2Info.frequency); // xxx.x MHz
|
||||||
|
ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":[%1_f,%1_f,%1_f]"), &Lora->settings.bandwidth, &Rx1Info.bandwidth, &Rx2Info.bandwidth); // xxx.x kHz
|
||||||
|
ResponseAppend_P(PSTR(",\"" D_JSON_SPREADING_FACTOR "\":[%d,%d,%d]"), Lora->settings.spreading_factor, Rx1Info.spreading_factor, Rx2Info.spreading_factor);
|
||||||
|
} else {
|
||||||
|
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%1_f"), &Lora->settings.frequency); // xxx.x MHz
|
||||||
|
ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":%1_f"), &Lora->settings.bandwidth); // xxx.x kHz
|
||||||
|
ResponseAppend_P(PSTR(",\"" D_JSON_SPREADING_FACTOR "\":%d"), Lora->settings.spreading_factor);
|
||||||
|
}
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_CODINGRATE4 "\":%d"), Lora->settings.coding_rate);
|
ResponseAppend_P(PSTR(",\"" D_JSON_CODINGRATE4 "\":%d"), Lora->settings.coding_rate);
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_SYNCWORD "\":%d"), Lora->settings.sync_word);
|
ResponseAppend_P(PSTR(",\"" D_JSON_SYNCWORD "\":%d"), Lora->settings.sync_word);
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_OUTPUT_POWER "\":%d"), Lora->settings.output_power); // dBm
|
ResponseAppend_P(PSTR(",\"" D_JSON_OUTPUT_POWER "\":%d"), Lora->settings.output_power); // dBm
|
||||||
@ -56,6 +262,7 @@ void LoraSettings2Json(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LoraJson2Settings(JsonParserObject root) {
|
void LoraJson2Settings(JsonParserObject root) {
|
||||||
|
Lora->settings.region = root.getUInt(PSTR(D_JSON_REGION), Lora->settings.region);
|
||||||
Lora->settings.frequency = root.getFloat(PSTR(D_JSON_FREQUENCY), Lora->settings.frequency);
|
Lora->settings.frequency = root.getFloat(PSTR(D_JSON_FREQUENCY), Lora->settings.frequency);
|
||||||
Lora->settings.bandwidth = root.getFloat(PSTR(D_JSON_BANDWIDTH), Lora->settings.bandwidth);
|
Lora->settings.bandwidth = root.getFloat(PSTR(D_JSON_BANDWIDTH), Lora->settings.bandwidth);
|
||||||
Lora->settings.spreading_factor = root.getUInt(PSTR(D_JSON_SPREADING_FACTOR), Lora->settings.spreading_factor);
|
Lora->settings.spreading_factor = root.getUInt(PSTR(D_JSON_SPREADING_FACTOR), Lora->settings.spreading_factor);
|
||||||
@ -104,7 +311,7 @@ bool LoraSaveData(void) {
|
|||||||
"\"Flags\":%u,"),
|
"\"Flags\":%u,"),
|
||||||
Lora->settings.crc32,
|
Lora->settings.crc32,
|
||||||
Lora->settings.flags);
|
Lora->settings.flags);
|
||||||
LoraSettings2Json();
|
LoraSettings2Json(false);
|
||||||
ResponseAppend_P(PSTR("}}"));
|
ResponseAppend_P(PSTR("}}"));
|
||||||
|
|
||||||
if (!UfsJsonSettingsWrite(ResponseData())) {
|
if (!UfsJsonSettingsWrite(ResponseData())) {
|
||||||
@ -174,11 +381,26 @@ void LoraSettingsSave(void) {
|
|||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
bool LoraSend(uint8_t* data, uint32_t len, bool invert) {
|
bool LoraSend(uint8_t* data, uint32_t len, bool invert, bool uplink_profile = false);
|
||||||
|
bool LoraSend(uint8_t* data, uint32_t len, bool invert, bool uplink_profile) {
|
||||||
|
LoraSettings_t RXsettings;
|
||||||
|
if (uplink_profile) {
|
||||||
|
// Different TX/RX profiles allowed. (e.g. LoRaWAN)
|
||||||
|
// For CmndLoraSend() ... do not allow changes.
|
||||||
|
RXsettings = Lora->settings; // Make a copy;
|
||||||
|
LoraWanDefaults(Lora->settings.region, TAS_LORAWAN_RADIO_RX2); // Set Downlink profile TO DO: Support different RX1 & RX2 profiles
|
||||||
|
Lora->Config();
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t lora_time = millis(); // Time is important for LoRaWan RX windows
|
uint32_t lora_time = millis(); // Time is important for LoRaWan RX windows
|
||||||
bool result = Lora->Send(data, len, invert);
|
bool result = Lora->Send(data, len, invert);
|
||||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LOR: Send (%u) '%*_H', Invert %d, Time %d"),
|
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LOR: Send (%u) '%*_H', Invert %d, Time %d"),
|
||||||
lora_time, len, data, invert, TimePassedSince(lora_time));
|
lora_time, len, data, invert, TimePassedSince(lora_time));
|
||||||
|
|
||||||
|
if (uplink_profile) {
|
||||||
|
Lora->settings = RXsettings; // Restore copy
|
||||||
|
Lora->Config();
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,11 +412,10 @@ void LoraInput(void) {
|
|||||||
if (!packet_size) { return; }
|
if (!packet_size) { return; }
|
||||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LOR: Rcvd (%u) '%*_H', RSSI %1_f, SNR %1_f"),
|
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LOR: Rcvd (%u) '%*_H', RSSI %1_f, SNR %1_f"),
|
||||||
Lora->receive_time, packet_size, data, &Lora->rssi, &Lora->snr);
|
Lora->receive_time, packet_size, data, &Lora->rssi, &Lora->snr);
|
||||||
|
|
||||||
#ifdef USE_LORAWAN_BRIDGE
|
#ifdef USE_LORAWAN_BRIDGE
|
||||||
if (bitRead(Lora->settings.flags, TAS_LORA_FLAG_BRIDGE_ENABLED)) {
|
if (bitRead(Lora->settings.flags, TAS_LORA_FLAG_BRIDGE_ENABLED)) {
|
||||||
if (LoraWanInput((uint8_t*)data, packet_size)) {
|
if (LoraWanInput((uint8_t*)data, packet_size)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_LORAWAN_BRIDGE
|
#endif // USE_LORAWAN_BRIDGE
|
||||||
@ -272,10 +493,11 @@ void LoraInit(void) {
|
|||||||
else if (PinUsed(GPIO_LORA_DI0)) {
|
else if (PinUsed(GPIO_LORA_DI0)) {
|
||||||
// SX1276, RFM95W
|
// SX1276, RFM95W
|
||||||
if (LoraSx127xInit()) {
|
if (LoraSx127xInit()) {
|
||||||
Lora->Config = &LoraSx127xConfig;
|
Lora->Config = &LoraSx127xConfig;
|
||||||
Lora->Available = &LoraSx127xAvailable;
|
Lora->Available = &LoraSx127xAvailable;
|
||||||
Lora->Receive = &LoraSx127xReceive;
|
Lora->Receive = &LoraSx127xReceive;
|
||||||
Lora->Send = &LoraSx127xSend;
|
Lora->Send = &LoraSx127xSend;
|
||||||
|
Lora->Init = &LoraSx127xInit;
|
||||||
strcpy_P(hardware, PSTR("SX127x"));
|
strcpy_P(hardware, PSTR("SX127x"));
|
||||||
present = true;
|
present = true;
|
||||||
}
|
}
|
||||||
@ -285,10 +507,11 @@ void LoraInit(void) {
|
|||||||
else if (PinUsed(GPIO_LORA_DI1) && PinUsed(GPIO_LORA_BUSY)) {
|
else if (PinUsed(GPIO_LORA_DI1) && PinUsed(GPIO_LORA_BUSY)) {
|
||||||
// SX1262, LilyGoT3S3
|
// SX1262, LilyGoT3S3
|
||||||
if (LoraSx126xInit()) {
|
if (LoraSx126xInit()) {
|
||||||
Lora->Config = &LoraSx126xConfig;
|
Lora->Config = &LoraSx126xConfig;
|
||||||
Lora->Available = &LoraSx126xAvailable;
|
Lora->Available = &LoraSx126xAvailable;
|
||||||
Lora->Receive = &LoraSx126xReceive;
|
Lora->Receive = &LoraSx126xReceive;
|
||||||
Lora->Send = &LoraSx126xSend;
|
Lora->Send = &LoraSx126xSend;
|
||||||
|
Lora->Init = &LoraSx126xInit;
|
||||||
strcpy_P(hardware, PSTR("SX126x"));
|
strcpy_P(hardware, PSTR("SX126x"));
|
||||||
present = true;
|
present = true;
|
||||||
}
|
}
|
||||||
@ -366,25 +589,25 @@ void CmndLoraSend(void) {
|
|||||||
invert = true;
|
invert = true;
|
||||||
}
|
}
|
||||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) {
|
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) {
|
||||||
Lora->raw = (XdrvMailbox.index > 3); // Global flag set even without data
|
Lora->raw = (XdrvMailbox.index > 3); // Global flag set even without data
|
||||||
if (XdrvMailbox.data_len > 0) {
|
if (XdrvMailbox.data_len > 0) {
|
||||||
char data[TAS_LORA_MAX_PACKET_LENGTH] = { 0 };
|
char data[TAS_LORA_MAX_PACKET_LENGTH] = { 0 };
|
||||||
uint32_t len = (XdrvMailbox.data_len < TAS_LORA_MAX_PACKET_LENGTH -1) ? XdrvMailbox.data_len : TAS_LORA_MAX_PACKET_LENGTH -2;
|
uint32_t len = (XdrvMailbox.data_len < TAS_LORA_MAX_PACKET_LENGTH -1) ? XdrvMailbox.data_len : TAS_LORA_MAX_PACKET_LENGTH -2;
|
||||||
#ifdef USE_LORA_DEBUG
|
#ifdef USE_LORA_DEBUG
|
||||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Len %d, Send %*_H"), len, len, XdrvMailbox.data);
|
AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Len %d, Send %*_H"), len, len, XdrvMailbox.data);
|
||||||
#endif
|
#endif
|
||||||
if (1 == XdrvMailbox.index) { // "Hello Tiger\n"
|
if (1 == XdrvMailbox.index) { // "Hello Tiger\n"
|
||||||
memcpy(data, XdrvMailbox.data, len);
|
memcpy(data, XdrvMailbox.data, len);
|
||||||
data[len++] = '\n';
|
data[len++] = '\n';
|
||||||
}
|
}
|
||||||
else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { // "Hello Tiger" or "A0"
|
else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { // "Hello Tiger" or "A0"
|
||||||
memcpy(data, XdrvMailbox.data, len);
|
memcpy(data, XdrvMailbox.data, len);
|
||||||
}
|
}
|
||||||
else if (3 == XdrvMailbox.index) { // "Hello\f"
|
else if (3 == XdrvMailbox.index) { // "Hello\f"
|
||||||
Unescape(XdrvMailbox.data, &len);
|
Unescape(XdrvMailbox.data, &len);
|
||||||
memcpy(data, XdrvMailbox.data, len);
|
memcpy(data, XdrvMailbox.data, len);
|
||||||
}
|
}
|
||||||
else if (5 == XdrvMailbox.index) { // "AA004566" as hex values
|
else if (5 == XdrvMailbox.index) { // "AA004566" as hex values
|
||||||
char *p;
|
char *p;
|
||||||
char stemp[3];
|
char stemp[3];
|
||||||
|
|
||||||
@ -400,7 +623,7 @@ void CmndLoraSend(void) {
|
|||||||
codes += 2;
|
codes += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (6 == XdrvMailbox.index) { // "72,101,108,108"
|
else if (6 == XdrvMailbox.index) { // "72,101,108,108"
|
||||||
char *p;
|
char *p;
|
||||||
uint8_t code;
|
uint8_t code;
|
||||||
char *values = XdrvMailbox.data;
|
char *values = XdrvMailbox.data;
|
||||||
@ -423,17 +646,24 @@ void CmndLoraSend(void) {
|
|||||||
|
|
||||||
void CmndLoraConfig(void) {
|
void CmndLoraConfig(void) {
|
||||||
// LoRaConfig - Show all parameters
|
// LoRaConfig - Show all parameters
|
||||||
// LoRaConfig 1 - Set default parameters
|
// LoRaConfig 1 - Set EU868 default parameters
|
||||||
// LoRaConfig 2 - Set default LoRaWan bridge parameters
|
// LoRaConfig 2 - Set EU868 default LoRaWan bridge parameters
|
||||||
|
// LoRaConfig 41 - Set AU915 default parameters
|
||||||
|
// LoRaConfig 42 - Set AU915 default LoRaWan bridge parameters
|
||||||
// LoRaConfig {"Frequency":868.0,"Bandwidth":125.0} - Enter float parameters
|
// LoRaConfig {"Frequency":868.0,"Bandwidth":125.0} - Enter float parameters
|
||||||
// LoRaConfig {"SyncWord":18} - Enter decimal parameter (=0x12)
|
// LoRaConfig {"SyncWord":18} - Enter decimal parameter (=0x12)
|
||||||
if (XdrvMailbox.data_len > 0) {
|
if (XdrvMailbox.data_len > 0) {
|
||||||
if (XdrvMailbox.payload == 1) {
|
if (XdrvMailbox.payload > 0) {
|
||||||
LoraDefaults();
|
uint32_t region = XdrvMailbox.payload / 10;
|
||||||
Lora->Config();
|
uint32_t option = ((XdrvMailbox.payload -1) &1) +1; // Option 1 or 2
|
||||||
}
|
switch (option) {
|
||||||
else if (XdrvMailbox.payload == 2) {
|
case 1:
|
||||||
LoraWanDefaults();
|
LoraDefaults(region); // Default region LoRa values
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
LoraWanDefaults(region); // Default region LoRaWan values
|
||||||
|
break;
|
||||||
|
}
|
||||||
Lora->Config();
|
Lora->Config();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -447,7 +677,7 @@ void CmndLoraConfig(void) {
|
|||||||
}
|
}
|
||||||
ResponseCmnd(); // {"LoRaConfig":
|
ResponseCmnd(); // {"LoRaConfig":
|
||||||
ResponseAppend_P(PSTR("{"));
|
ResponseAppend_P(PSTR("{"));
|
||||||
LoraSettings2Json();
|
LoraSettings2Json(true);
|
||||||
ResponseAppend_P(PSTR("}}"));
|
ResponseAppend_P(PSTR("}}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,4 +720,4 @@ bool Xdrv73(uint32_t function) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_SPI_LORA
|
#endif // USE_SPI_LORA
|
||||||
#endif // USE_SPI
|
#endif // USE_SPI
|
Loading…
x
Reference in New Issue
Block a user