kopia lustrzana https://github.com/Max-Plastix/tbeam-helium-mapper
Added Downlink handling and broke something
rodzic
6bcce5fb77
commit
dc4a031d3d
|
@ -0,0 +1,28 @@
|
|||
import base64
|
||||
import argparse
|
||||
import struct
|
||||
|
||||
parser = argparse.ArgumentParser(description='Encode a downlink payload for a Helium mapper.')
|
||||
parser.add_argument('--distance', '-d', type=int, help='Map distance interval (kilometers)')
|
||||
parser.add_argument('--time', '-t', type=int, help='Minimum time interval (seconds)')
|
||||
parser.add_argument('--cutoffvolts', '-c', type=float, help='Low Voltage Power Off (volts)')
|
||||
args = parser.parse_args()
|
||||
|
||||
distance = 0
|
||||
if args.distance and rgs.distance > 0 and args.distance < 0xFFFF:
|
||||
distance = args.distance
|
||||
|
||||
time_interval = 0
|
||||
if args.time and args.time > 0 and args.time < 0xFFFF:
|
||||
time_interval = args.time
|
||||
|
||||
cutoffvolts = 2.0 # Not a valid value, zero
|
||||
if args.cutoffvolts and args.cutoffvolts >= 2.1 and args.cutoffvolts < 4.56:
|
||||
cutoffvolts = args.cutoffvolts
|
||||
|
||||
|
||||
payload = struct.pack('>HHB', distance, time_interval, int((cutoffvolts - 2.0) * 100))
|
||||
encodedBytes = base64.b64encode(payload)
|
||||
encodedStr = str(encodedBytes, "utf-8")
|
||||
print(payload.hex(' ').upper())
|
||||
print(encodedStr)
|
|
@ -46,15 +46,17 @@
|
|||
void ttn_register(void (*callback)(uint8_t message));
|
||||
|
||||
bool justSendNow = true; // Start by sending
|
||||
unsigned long int last_send_millis = 0;
|
||||
unsigned long int last_moved_millis = 0;
|
||||
unsigned long int last_send_millis = 0;
|
||||
unsigned long int last_moved_millis = 0;
|
||||
float last_send_lat = 0;
|
||||
float last_send_lon = 0;
|
||||
float min_dist_moved = MIN_DIST;
|
||||
float dist_moved = 0;
|
||||
|
||||
// do we want to auto-scale transmit window size?
|
||||
bool autoScaleTX = false;
|
||||
/* Defaults that can be overwritten by downlink messages */
|
||||
unsigned long int tx_interval_ms = STATIONARY_TX_INTERVAL * 1000;
|
||||
boolean freeze_tx_interval_ms = false;
|
||||
float battery_low_voltage = BATTERY_LOW_VOLTAGE;
|
||||
float min_dist_moved = MIN_DIST;
|
||||
|
||||
AXP20X_Class axp;
|
||||
bool pmu_irq = false;
|
||||
|
@ -64,6 +66,7 @@ bool ssd1306_found = false;
|
|||
bool axp192_found = false;
|
||||
|
||||
bool packetSent, packetQueued;
|
||||
bool isJoined = false;
|
||||
|
||||
#if defined(PAYLOAD_USE_FULL)
|
||||
// includes number of satellites and accuracy
|
||||
|
@ -91,7 +94,6 @@ void buildPacket(uint8_t txBuffer[]); // needed for platformio
|
|||
If we have a valid position send it to the server.
|
||||
@return true if we decided to send.
|
||||
*/
|
||||
unsigned long int tx_interval_ms = STATIONARY_TX_INTERVAL * 1000;
|
||||
|
||||
bool trySend()
|
||||
{
|
||||
|
@ -104,6 +106,9 @@ bool trySend()
|
|||
)
|
||||
return false; // Rejected as bogus GPS reading.
|
||||
|
||||
if (!isJoined)
|
||||
return false;
|
||||
|
||||
// distance from last transmitted location
|
||||
float dist_moved = gps_distanceBetween(last_send_lat, last_send_lon, gps_latitude(), gps_longitude());
|
||||
#if 0
|
||||
|
@ -247,7 +252,7 @@ void update_status() {
|
|||
|
||||
|
||||
void callback(uint8_t message) {
|
||||
#if 0
|
||||
#if 1
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer), "MSG %d\n", message);
|
||||
screen_print(buffer);
|
||||
|
@ -255,6 +260,7 @@ void callback(uint8_t message) {
|
|||
#endif
|
||||
if (EV_JOIN_TXCOMPLETE == message) Serial.println("# JOIN_TXCOMPLETE");
|
||||
if (EV_TXCOMPLETE == message) Serial.println("# TXCOMPLETE");
|
||||
if (EV_RXCOMPLETE == message) Serial.println("# RXCOMPLETE");
|
||||
if (EV_RXSTART == message) Serial.println("# RXSTART");
|
||||
if (EV_TXCANCELED == message) Serial.println("# TXCANCELED");
|
||||
if (EV_TXSTART == message) Serial.println("# TXSTART");
|
||||
|
@ -268,6 +274,9 @@ void callback(uint8_t message) {
|
|||
if (EV_PENDING == message) Serial.println("# PENDING");
|
||||
if (EV_QUEUED == message) Serial.println("# QUEUED");
|
||||
|
||||
if (EV_JOINED == message)
|
||||
isJoined = true;
|
||||
|
||||
if (EV_TXSTART == message) {
|
||||
screen_print("Tx.. ");
|
||||
}
|
||||
|
@ -278,22 +287,51 @@ void callback(uint8_t message) {
|
|||
packetSent = true;
|
||||
}
|
||||
|
||||
if (EV_RESPONSE == message) {
|
||||
screen_print("[Helium] Response: ");
|
||||
if (EV_RXCOMPLETE == message) {
|
||||
screen_print("Downlink: ");
|
||||
|
||||
size_t len = ttn_response_len();
|
||||
uint8_t data[len];
|
||||
ttn_response(data, len);
|
||||
|
||||
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
snprintf(buffer, sizeof(buffer), "%02X", data[i]);
|
||||
screen_print(buffer);
|
||||
}
|
||||
screen_print("\n");
|
||||
|
||||
/*
|
||||
* Downlink format:
|
||||
* 2 Bytes: Minimum Distance (1 to 65535) meters, or 0 no-change
|
||||
* 2 Bytes: Minimum Time (1 to 65535) seconds (18.2 hours) between pings, or 0 no-change
|
||||
* 1 Byte: Battery voltage (2.0 to 4.5) for auto-shutoff, or 0 no-change
|
||||
*/
|
||||
if (len == 5) {
|
||||
snprintf(buffer, sizeof(buffer), "(no changes)\n");
|
||||
|
||||
float new_distance = (float)(data[0] << 8 | data[1]);
|
||||
if (new_distance > 0.0) {
|
||||
min_dist_moved = new_distance;
|
||||
snprintf(buffer, sizeof(buffer), "New Dist: %.0fm\n", new_distance);
|
||||
}
|
||||
|
||||
unsigned long int new_interval = data[2] << 8 | data[3];
|
||||
if (new_interval) {
|
||||
tx_interval_ms = new_interval * 1000;
|
||||
freeze_tx_interval_ms = true;
|
||||
snprintf(buffer, sizeof(buffer), "New Time: %.0lum\n", new_interval);
|
||||
}
|
||||
|
||||
float new_low_voltage = data[4] / 2.56 + 2.0;
|
||||
if (new_low_voltage) {
|
||||
battery_low_voltage = new_low_voltage;
|
||||
snprintf(buffer, sizeof(buffer), "New LowBat: %.2fm\n", new_low_voltage);
|
||||
}
|
||||
screen_print(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scanI2Cdevice(void)
|
||||
{
|
||||
byte err, addr;
|
||||
|
@ -481,7 +519,7 @@ void update_activity()
|
|||
float charge_ma = axp.getBattChargeCurrent();
|
||||
// float discharge_ma = axp.getBatChargeCurrent();
|
||||
|
||||
if (axp.isBatteryConnect() && bat_volts < BATTERY_LOW_VOLTAGE && charge_ma < 99.0)
|
||||
if (axp.isBatteryConnect() && bat_volts < battery_low_voltage && charge_ma < 99.0)
|
||||
{
|
||||
Serial.println("Low Battery OFF");
|
||||
screen_print("Low Battery OFF\n");
|
||||
|
@ -496,15 +534,15 @@ void update_activity()
|
|||
tx_interval_ms = STATIONARY_TX_INTERVAL * 1000;
|
||||
else
|
||||
*/
|
||||
unsigned long int now_interval;
|
||||
if (millis() - last_moved_millis > REST_WAIT * 1000)
|
||||
now_interval = REST_TX_INTERVAL * 1000;
|
||||
else
|
||||
now_interval = STATIONARY_TX_INTERVAL * 1000;
|
||||
if (now_interval != tx_interval_ms) {
|
||||
tx_interval_ms = now_interval;
|
||||
// snprintf(buffer, sizeof(buffer), "Interval: %lus\n", now_interval / 1000);
|
||||
// screen_print(buffer);
|
||||
if (!freeze_tx_interval_ms)
|
||||
{
|
||||
unsigned long int now_interval;
|
||||
if (millis() - last_moved_millis > REST_WAIT * 1000)
|
||||
now_interval = REST_TX_INTERVAL * 1000;
|
||||
else
|
||||
now_interval = STATIONARY_TX_INTERVAL * 1000;
|
||||
if (now_interval != tx_interval_ms)
|
||||
tx_interval_ms = now_interval;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ void _screen_header() {
|
|||
if (axp192_found && millis() % 4000 < 2000)
|
||||
{
|
||||
// 2 bytes of Device EUI with Voltage and Current
|
||||
snprintf(buffer, sizeof(buffer), "#%03X", (((DEVEUI[7] & 0xF) << 8) | DEVEUI[6]));
|
||||
snprintf(buffer, sizeof(buffer), "#%03X", ((DEVEUI[7] << 4) | (DEVEUI[6] & 0xF0) >> 4));
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->drawString(0, 2, buffer);
|
||||
|
||||
|
|
137
main/ttn.ino
137
main/ttn.ino
|
@ -130,73 +130,82 @@ void initDevEUI() {
|
|||
|
||||
// LMIC library will call this method when an event is fired
|
||||
void onEvent(ev_t event) {
|
||||
switch(event) {
|
||||
case EV_JOINED: {
|
||||
#ifdef SINGLE_CHANNEL_GATEWAY
|
||||
forceTxSingleChannelDr();
|
||||
#endif
|
||||
// Some special-case event handling
|
||||
switch (event) {
|
||||
case EV_JOINED: {
|
||||
#ifdef SINGLE_CHANNEL_GATEWAY
|
||||
forceTxSingleChannelDr();
|
||||
#endif
|
||||
|
||||
// Disable link check validation (automatically enabled
|
||||
// during join, but because slow data rates change max TX
|
||||
// size, we don't use it in this example.
|
||||
if(!LORAWAN_ADR){
|
||||
LMIC_setLinkCheckMode(0); // Link check problematic if not using ADR. Must be set after join
|
||||
}
|
||||
|
||||
Serial.println(F("! EV_JOINED as:"));
|
||||
|
||||
u4_t netid = 0;
|
||||
devaddr_t devaddr = 0;
|
||||
u1_t nwkKey[16];
|
||||
u1_t artKey[16];
|
||||
LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
|
||||
Serial.print("netid: ");
|
||||
Serial.println(netid, DEC);
|
||||
Serial.print("devaddr: ");
|
||||
Serial.println(devaddr, HEX);
|
||||
Serial.print("AppSKey: ");
|
||||
for (size_t i=0; i<sizeof(artKey); ++i) {
|
||||
if (i != 0)
|
||||
Serial.print("-");
|
||||
printHex2(artKey[i]);
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("NwkSKey: ");
|
||||
for (size_t i=0; i<sizeof(nwkKey); ++i) {
|
||||
if (i != 0)
|
||||
Serial.print("-");
|
||||
printHex2(nwkKey[i]);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Preferences p;
|
||||
if(p.begin("lora", false)) {
|
||||
p.putUInt("netId", netid);
|
||||
p.putUInt("devAddr", devaddr);
|
||||
p.putBytes("nwkKey", nwkKey, sizeof(nwkKey));
|
||||
p.putBytes("artKey", artKey, sizeof(artKey));
|
||||
p.end();
|
||||
}
|
||||
break; }
|
||||
case EV_TXCOMPLETE:
|
||||
Serial.println(F("! EV_TXCOMPLETE"));
|
||||
if (LMIC.txrxFlags & TXRX_ACK) {
|
||||
Serial.println(F("! Received ACK"));
|
||||
_ttn_callback(EV_ACK);
|
||||
}
|
||||
if (LMIC.dataLen) {
|
||||
Serial.print(F("Data Received: "));
|
||||
Serial.write(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
|
||||
Serial.println();
|
||||
_ttn_callback(EV_RESPONSE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// Disable link check validation (automatically enabled
|
||||
// during join, but because slow data rates change max TX
|
||||
// size, we don't use it in this example.
|
||||
if (!LORAWAN_ADR) {
|
||||
LMIC_setLinkCheckMode(0); // Link check problematic if not using ADR.
|
||||
// Must be set after join
|
||||
}
|
||||
|
||||
// Send message callbacks
|
||||
_ttn_callback(event);
|
||||
Serial.println(F("! EV_JOINED as:"));
|
||||
|
||||
u4_t netid = 0;
|
||||
devaddr_t devaddr = 0;
|
||||
u1_t nwkKey[16];
|
||||
u1_t artKey[16];
|
||||
LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
|
||||
Serial.print("netid: ");
|
||||
Serial.println(netid, DEC);
|
||||
Serial.print("devaddr: ");
|
||||
Serial.println(devaddr, HEX);
|
||||
Serial.print("AppSKey: ");
|
||||
for (size_t i = 0; i < sizeof(artKey); ++i) {
|
||||
if (i != 0)
|
||||
Serial.print("-");
|
||||
printHex2(artKey[i]);
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("NwkSKey: ");
|
||||
for (size_t i = 0; i < sizeof(nwkKey); ++i) {
|
||||
if (i != 0)
|
||||
Serial.print("-");
|
||||
printHex2(nwkKey[i]);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Preferences p;
|
||||
if (p.begin("lora", false)) {
|
||||
p.putUInt("netId", netid);
|
||||
p.putUInt("devAddr", devaddr);
|
||||
p.putBytes("nwkKey", nwkKey, sizeof(nwkKey));
|
||||
p.putBytes("artKey", artKey, sizeof(artKey));
|
||||
p.end();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case EV_TXCOMPLETE:
|
||||
// Before sending the EV_TXCOMPLETE callback, send EV_ACK and EV_Response
|
||||
// virtual events? Serial.println(F("! EV_TXCOMPLETE"));
|
||||
if (LMIC.txrxFlags & TXRX_ACK) {
|
||||
Serial.println(F("! Tx got ACK"));
|
||||
_ttn_callback(EV_ACK);
|
||||
}
|
||||
if (LMIC.dataLen) {
|
||||
Serial.print(F("! Tx got Response"));
|
||||
Serial.write(LMIC.frame + LMIC.dataBeg, LMIC.dataLen);
|
||||
Serial.println();
|
||||
_ttn_callback(EV_RESPONSE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Serial.print(F("Data Received: "));
|
||||
// Serial.write(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
|
||||
// Serial.println();
|
||||
|
||||
// Send the original message callbacks
|
||||
_ttn_callback(event);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -31,6 +31,7 @@ build_flags = -Wall
|
|||
-D ARDUINO_LMIC_PROJECT_CONFIG_H_SUPPRESS
|
||||
-D CFG_us915=1
|
||||
-D CFG_sx1276_radio=1
|
||||
-D LMIC_DEBUG_LEVEL=3
|
||||
-D ARDUINO_TTGO_LoRa32_v21new
|
||||
; -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
|
||||
|
|
|
@ -4,5 +4,9 @@
|
|||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
"settings": {
|
||||
"files.associations": {
|
||||
"vector": "cpp"
|
||||
}
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue