Skip to content

Commit

Permalink
Merge pull request #344 from cyberman54/development
Browse files Browse the repository at this point in the history
v1.7.5
  • Loading branch information
cyberman54 authored Apr 6, 2019
2 parents 2017065 + 20dafae commit 973c821
Show file tree
Hide file tree
Showing 18 changed files with 104 additions and 85 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,9 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.

Device answers with it's current status on Port 4.

0x85 get BME680 sensor data
0x85 get BME280 / BME680 sensor data

Device answers with BME680 sensor data set on Port 7.
Device answers with BME sensor data set on Port 7.

0x86 get time/date

Expand Down
3 changes: 0 additions & 3 deletions include/button.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#ifndef _BUTTON_H
#define _BUTTON_H

#include "display.h"
#include "senddata.h"

void readButton();

#endif
2 changes: 0 additions & 2 deletions include/irqhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ int mask_user_IRQ();
int unmask_user_IRQ();

#ifdef HAS_DISPLAY
#include "display.h"
void IRAM_ATTR DisplayIRQ();
#endif

#ifdef HAS_BUTTON
#include "button.h"
void IRAM_ATTR ButtonIRQ();
#endif

Expand Down
4 changes: 2 additions & 2 deletions include/timesync.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
#include "timekeeper.h"

//#define TIME_SYNC_TRIGGER 100 // threshold for time sync [milliseconds]
#define TIME_SYNC_FRAME_LENGTH 0x06 // timeserver answer frame length [bytes]
#define TIME_SYNC_FRAME_LENGTH 0x05 // timeserver answer frame length [bytes]
#define TIME_SYNC_FIXUP 6 // calibration to fixup processing time [milliseconds]

void send_timesync_req(void);
int recv_timesync_ans(uint8_t buf[], uint8_t buf_len);
int recv_timesync_ans(uint8_t seq_no, uint8_t buf[], uint8_t buf_len);
void process_timesync_req(void *taskparameter);
void store_time_sync_req(uint32_t t_millisec);
void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec);
Expand Down
2 changes: 1 addition & 1 deletion lib/microTime/src/TimeLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ time_t now(uint32_t &sysTimeMicros); // return the current time as seconds and

#endif
#ifdef usePPS
void SyncToPPS();
void IRAM_ATTR SyncToPPS();
#endif
void setTime(time_t t);
void setTime(int hr, int min, int sec, int day, int month, int yr);
Expand Down
2 changes: 1 addition & 1 deletion lib/microTime/src/microTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
#endif

#ifdef usePPS
void SyncToPPS() {
void IRAM_ATTR SyncToPPS() {
sysTime++;
prevMicros = micros();
}
Expand Down
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng

[common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
release_version = 1.7.422
release_version = 1.7.5
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 3
Expand Down
14 changes: 7 additions & 7 deletions src/TTN/packed_decoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function Decoder(bytes, port) {

var decoded = {};

if (bytes.length === 0) {
if (bytes.length === 0) {
return {};
}

Expand Down Expand Up @@ -33,10 +33,6 @@ function Decoder(bytes, port) {
if (bytes.length === 17) {
return decode(bytes, [uint16, uptime, uint8, uint32, uint8, uint8], ['voltage', 'uptime', 'cputemp', 'memory', 'reset0', 'reset1']);
}
// epoch time answer
if (bytes.length === 5) {
return decode(bytes, [uint32, uint8], ['time', 'timestatus']);
}
}

if (port === 3) {
Expand Down Expand Up @@ -72,9 +68,13 @@ function Decoder(bytes, port) {
if (port === 9) {
// timesync request
if (bytes.length === 1) {
decoded.timesync_seqno = bytes[0];
decoded.timesync_seqno = bytes[0];
return decoded;
}
// epoch time answer
if (bytes.length === 5) {
return decode(bytes, [uint32, uint8], ['time', 'timestatus']);
}
return decoded;
}

}
Expand Down
27 changes: 18 additions & 9 deletions src/TTN/plain_decoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ function Decoder(bytes, port) {
var i = 0;

if (bytes.length >= 2) {
decoded.wifi = (bytes[i++] << 8) | bytes[i++];}

decoded.wifi = (bytes[i++] << 8) | bytes[i++];
}

if (bytes.length === 4 || bytes.length > 15) {
decoded.ble = (bytes[i++] << 8) | bytes[i++];}
decoded.ble = (bytes[i++] << 8) | bytes[i++];
}

if (bytes.length > 4) {
decoded.latitude = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]);
Expand Down Expand Up @@ -52,27 +54,34 @@ function Decoder(bytes, port) {
decoded.rssi = bytes[i++];
decoded.beacon = bytes[i++];
}

if (port === 7) {
var i = 0;
decoded.temperature = ((bytes[i++] << 8) | bytes[i++]);
decoded.pressure = ((bytes[i++] << 8) | bytes[i++]);
decoded.humidity = ((bytes[i++] << 8) | bytes[i++]);
decoded.air = ((bytes[i++] << 8) | bytes[i++]);
}

if (port === 8) {
var i = 0;
if (bytes.length >= 2) {
decoded.battery = (bytes[i++] << 8) | bytes[i++];}
decoded.battery = (bytes[i++] << 8) | bytes[i++];
}
}

if (port === 9) {
// timesync request
if (bytes.length === 1) {
decoded.timesync_seqno = bytes[0];
decoded.timesync_seqno = bytes[0];
}
// epoch time answer
if (bytes.length === 5) {
var i = 0;
decoded.time = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]);
decoded.timestatus = bytes[i++];
}
return decoded;
}

return decoded;

}
64 changes: 32 additions & 32 deletions src/Timeserver/Nodered-Timeserver.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,6 @@
"to": "down",
"tot": "str"
},
{
"t": "move",
"p": "payload",
"pt": "msg",
"to": "payload.payload_raw",
"tot": "msg"
},
{
"t": "set",
"p": "payload.port",
"pt": "msg",
"to": "9",
"tot": "num"
},
{
"t": "set",
"p": "payload.confirmed",
Expand All @@ -41,6 +27,20 @@
"pt": "msg",
"to": "replace",
"tot": "str"
},
{
"t": "move",
"p": "payload",
"pt": "msg",
"to": "payload.payload_raw",
"tot": "msg"
},
{
"t": "move",
"p": "port",
"pt": "msg",
"to": "payload.port",
"tot": "msg"
}
],
"action": "",
Expand Down Expand Up @@ -68,7 +68,7 @@
"y": 120,
"wires": [
[
"9f4b8dd3.2f0d2"
"4f97d75.6c87528"
]
]
},
Expand All @@ -94,10 +94,10 @@
"action": "",
"pretty": false,
"x": 260,
"y": 200,
"y": 120,
"wires": [
[
"8ed813a9.a9319"
"9f4b8dd3.2f0d2"
]
]
},
Expand All @@ -106,23 +106,23 @@
"type": "switch",
"z": "449c1517.e25f4c",
"name": "Timeport",
"property": "payload",
"property": "payload.port",
"propertyType": "msg",
"rules": [
{
"t": "cont",
"v": "\"port\":9",
"vt": "str"
"t": "eq",
"v": "9",
"vt": "num"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 260,
"x": 420,
"y": 120,
"wires": [
[
"4f97d75.6c87528"
"8ed813a9.a9319"
]
]
},
Expand All @@ -149,8 +149,8 @@
"name": "Decode",
"action": "",
"property": "payload.payload_raw",
"x": 420,
"y": 200,
"x": 580,
"y": 120,
"wires": [
[
"831ab883.d6a238"
Expand All @@ -176,22 +176,22 @@
"id": "6190967b.01f758",
"type": "comment",
"z": "449c1517.e25f4c",
"name": "LoRaWAN Timeserver",
"name": "LoRaWAN Timeserver v1.1",
"info": "PLEASE NOTE: There is a patent filed for the time sync algorithm used in the\ncode of this file. The shown implementation example is covered by the\nrepository's licencse, but you may not be eligible to deploy the applied\nalgorithm in applications without granted license by the patent holder.",
"x": 160,
"x": 170,
"y": 40,
"wires": []
},
{
"id": "831ab883.d6a238",
"type": "function",
"z": "449c1517.e25f4c",
"name": "Generate Time Answer",
"func": "/* LoRaWAN Timeserver\n\nconstruct 6 byte timesync_answer from gateway timestamp and node's time_sync_req\n\nbyte meaning\n0 sequence number (taken from node's time_sync_req)\n1..4 current second (from epoch time 1970)\n5 1/250ths fractions of current second\n\n*/\n\nfunction timecompare(a, b) {\n \n const timeA = a.time;\n const timeB = b.time;\n\n let comparison = 0;\n if (timeA > timeB) {\n comparison = 1;\n } else if (timeA < timeB) {\n comparison = -1;\n }\n return comparison;\n}\n\nlet confidence = 2000; // max millisecond diff gateway time to server time\n\nvar deviceMsg = { payload: msg.payload.dev_id };\nvar seqno = msg.payload.payload_raw[0];\nvar seqnoMsg = { payload: seqno };\nvar gateway_list = msg.payload.metadata.gateways;\n\n// filter all gateway timestamps that have milliseconds part (which we assume have a \".\")\nvar gateways = gateway_list.filter(function (element) {\n return (element.time.includes(\".\"));\n});\n\nvar gateway_time = gateways.map(gw => {\n return {\n time: new Date(gw.time),\n eui: gw.gtw_id,\n }\n });\nvar server_time = new Date(msg.payload.metadata.time);\n\n// validate all gateway timestamps against lorawan server_time (which is assumed to be recent)\nvar gw_timestamps = gateway_time.filter(function (element) {\n return ((element.time > (server_time - confidence) && element.time <= server_time));\n});\n\n// if no timestamp left, we have no valid one and exit\nif (gw_timestamps.length === 0) {\n var notavailMsg = { payload: \"n/a\" };\n var notimeMsg = { payload: 0xff }; \n var buf2 = Buffer.alloc(1);\n msg.payload = new Buffer(buf2.fill(0xff));\n return [notavailMsg, notavailMsg, deviceMsg, seqnoMsg, msg];}\n\n// sort time array in ascending order to find most recent timestamp for time answer\ngw_timestamps.sort(timecompare);\n\nvar timestamp = gw_timestamps[0].time;\nvar eui = gw_timestamps[0].eui;\nvar offset = server_time - timestamp;\n\nvar seconds = Math.floor(timestamp/1000);\nvar fractions = (timestamp % 1000) / 4;\n\nlet buf = new ArrayBuffer(6);\nnew DataView(buf).setUint8(0, seqno);\nnew DataView(buf).setUint32(1, seconds);\nnew DataView(buf).setUint8(5, fractions);\n\nmsg.payload = new Buffer(new Uint8Array(buf));\nvar euiMsg = { payload: eui };\nvar offsetMsg = { payload: offset };\n\nreturn [euiMsg, offsetMsg, deviceMsg, seqnoMsg, msg];",
"name": "Timeserver Logic",
"func": "/* LoRaWAN Timeserver\n\nconstruct 5 byte timesync_answer from gateway timestamp and node's time_sync_req\n\nbyte meaning\n1..4 current second (from epoch time 1970)\n5 1/250ths fractions of current second\n\nFPort = sequence number (taken from node's time_sync_req)\n\n*/\n\nfunction timecompare(a, b) {\n \n const timeA = a.time;\n const timeB = b.time;\n\n let comparison = 0;\n if (timeA > timeB) {\n comparison = 1;\n } else if (timeA < timeB) {\n comparison = -1;\n }\n return comparison;\n}\n\nlet confidence = 2000; // max millisecond diff gateway time to server time\n\n// guess if we have received a valid time_sync_req command\nif (msg.payload.payload_raw.length != 1)\n return;\n\nvar deviceMsg = { payload: msg.payload.dev_id };\nvar seqNo = msg.payload.payload_raw[0];\nvar seqNoMsg = { payload: seqNo };\nvar gateway_list = msg.payload.metadata.gateways;\n\n// filter all gateway timestamps that have milliseconds part (which we assume have a \".\")\nvar gateways = gateway_list.filter(function (element) {\n return (element.time.includes(\".\"));\n});\n\nvar gateway_time = gateways.map(gw => {\n return {\n time: new Date(gw.time),\n eui: gw.gtw_id,\n }\n });\nvar server_time = new Date(msg.payload.metadata.time);\n\n// validate all gateway timestamps against lorawan server_time (which is assumed to be recent)\nvar gw_timestamps = gateway_time.filter(function (element) {\n return ((element.time > (server_time - confidence) && element.time <= server_time));\n});\n\n// if no timestamp left, we have no valid one and exit\nif (gw_timestamps.length === 0) {\n var notavailMsg = { payload: \"n/a\" };\n var notimeMsg = { payload: 0xff }; \n var buf2 = Buffer.alloc(1);\n msg.payload = new Buffer(buf2.fill(0xff));\n return [notavailMsg, notavailMsg, deviceMsg, seqNoMsg, msg];}\n\n// sort time array in ascending order to find most recent timestamp for time answer\ngw_timestamps.sort(timecompare);\n\nvar timestamp = gw_timestamps[0].time;\nvar eui = gw_timestamps[0].eui;\nvar offset = server_time - timestamp;\n\nvar seconds = Math.floor(timestamp/1000);\nvar fractions = (timestamp % 1000) / 4;\n\nlet buf = new ArrayBuffer(5);\nnew DataView(buf).setUint32(0, seconds);\nnew DataView(buf).setUint8(4, fractions);\n\nmsg.payload = new Buffer(new Uint8Array(buf));\nmsg.port = seqNo;\nvar euiMsg = { payload: eui };\nvar offsetMsg = { payload: offset };\n\nreturn [euiMsg, offsetMsg, deviceMsg, seqNoMsg, msg];",
"outputs": 5,
"noerr": 0,
"x": 360,
"y": 340,
"x": 350,
"y": 320,
"wires": [
[
"37722d4b.08e3c2",
Expand Down Expand Up @@ -224,7 +224,7 @@
"type": "debug",
"z": "449c1517.e25f4c",
"name": "Timeserver Gw",
"active": false,
"active": true,
"tosidebar": false,
"console": false,
"tostatus": true,
Expand Down
1 change: 1 addition & 0 deletions src/bmesensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ void bme_loop(void *pvParameters) {
(bme.readPressure() / 100.0); // conversion Pa -> hPa
// bme.readAltitude(SEALEVELPRESSURE_HPA);
bme_status.humidity = bme.readHumidity();
bme_status.iaq = 0; // IAQ feature not present with BME280
I2C_MUTEX_UNLOCK();
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/cyclic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ static const char TAG[] = __FILE__;

Ticker housekeeper;

void housekeeping() { xTaskNotify(irqHandlerTask, CYCLIC_IRQ, eSetBits); }
void housekeeping() { xTaskNotifyFromISR(irqHandlerTask, CYCLIC_IRQ, eSetBits, NULL); }

// do all housekeeping
void doHousekeeping() {
Expand Down
18 changes: 13 additions & 5 deletions src/lorawan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,16 +256,24 @@ void onEvent(ev_t ev) {
sprintf(display_line6, "RSSI %d SNR %d", LMIC.rssi, LMIC.snr / 4);

if (LMIC.txrxFlags & TXRX_PORT) { // FPort -> use to switch

switch (LMIC.frame[LMIC.dataBeg - 1]) {
#if (TIME_SYNC_LORASERVER)
case TIMEPORT: // timesync answer -> call timesync processor
recv_timesync_ans(LMIC.frame + LMIC.dataBeg, LMIC.dataLen);
break;
#endif

case RCMDPORT: // opcode -> call rcommand interpreter
rcommand(LMIC.frame + LMIC.dataBeg, LMIC.dataLen);
break;

default: // unknown port -> display info

#if (TIME_SYNC_LORASERVER)
// timesync answer -> call timesync processor
if ((LMIC.frame[LMIC.dataBeg - 1] >= TIMEANSWERPORT_MIN) &&
(LMIC.frame[LMIC.dataBeg - 1] <= TIMEANSWERPORT_MAX)) {
recv_timesync_ans(LMIC.frame[LMIC.dataBeg - 1],
LMIC.frame + LMIC.dataBeg, LMIC.dataLen);
break;
}
#endif
ESP_LOGI(TAG, "Received data on unsupported port #%d",
LMIC.frame[LMIC.dataBeg - 1]);
break;
Expand Down
4 changes: 3 additions & 1 deletion src/paxcounter.conf
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@
#define BEACONPORT 6 // beacon alarms
#define BMEPORT 7 // BME680 sensor
#define BATTPORT 8 // battery voltage
#define TIMEPORT 9 // time
#define TIMEPORT 9 // time query
#define TIMEANSWERPORT_MIN 0xA0 // time answer, start of port range
#define TIMEANSWERPORT_MAX 0xDF // time answer, end of port range
#define SENSOR1PORT 10 // user sensor #1
#define SENSOR2PORT 11 // user sensor #2
#define SENSOR3PORT 12 // user sensor #3
Expand Down
2 changes: 1 addition & 1 deletion src/rcommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ void get_time(uint8_t val[]) {
payload.reset();
payload.addTime(now());
payload.addByte(timeStatus() << 4 | timeSource);
SendPayload(STATUSPORT, prio_high);
SendPayload(TIMEPORT, prio_high);
};

void set_time(uint8_t val[]) {
Expand Down
2 changes: 1 addition & 1 deletion src/senddata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

Ticker sendcycler;

void sendcycle() { xTaskNotify(irqHandlerTask, SENDCYCLE_IRQ, eSetBits); }
void sendcycle() { xTaskNotifyFromISR(irqHandlerTask, SENDCYCLE_IRQ, eSetBits, NULL); }

// put data to send in RTos Queues used for transmit over channels Lora and SPI
void SendPayload(uint8_t port, sendprio_t prio) {
Expand Down
2 changes: 1 addition & 1 deletion src/timekeeper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ HardwareSerial IF482(2); // use UART #2 (#1 may be in use for serial GPS)

Ticker timesyncer;

void timeSync() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
void timeSync() { xTaskNotifyFromISR(irqHandlerTask, TIMESYNC_IRQ, eSetBits, NULL); }

time_t timeProvider(void) {

Expand Down
Loading

0 comments on commit 973c821

Please sign in to comment.