Merge branch 'master' of https://github.com/cyberman54/ESP32-Paxcounter
This commit is contained in:
commit
b2931c148d
40 files changed
+936
-427
No files matched your search
@@ -0,0 +1,467 @@
|
||||
[
|
||||
{
|
||||
"id": "7bc3eb4f.fe4b64",
|
||||
"type": "mqtt in",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "Olimex",
|
||||
"topic": "paxout/#",
|
||||
"qos": "2",
|
||||
"datatype": "utf8",
|
||||
"broker": "bd56b04d.db0ff",
|
||||
"x": 190,
|
||||
"y": 160,
|
||||
"wires": [
|
||||
[
|
||||
"d0276db6.83c46"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4f59740b.296b7c",
|
||||
"type": "debug",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "data",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 1050,
|
||||
"y": 280,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "f10f8199.25183",
|
||||
"type": "binary",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "wifi",
|
||||
"property": "payload",
|
||||
"pattern": "l16, x16",
|
||||
"x": 630,
|
||||
"y": 100,
|
||||
"wires": [
|
||||
[
|
||||
"800f5faa.15155"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "df4bdce5.dc219",
|
||||
"type": "switch",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "Ports",
|
||||
"property": "topic",
|
||||
"propertyType": "msg",
|
||||
"rules": [
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/1",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/2",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/3",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/4",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/5",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/6",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/7",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/8",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/9",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "paxout/10",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "status",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"checkall": "true",
|
||||
"repair": false,
|
||||
"outputs": 11,
|
||||
"x": 370,
|
||||
"y": 260,
|
||||
"wires": [
|
||||
[
|
||||
"f10f8199.25183"
|
||||
],
|
||||
[
|
||||
"e2974f79.55d5b"
|
||||
],
|
||||
[
|
||||
"5f6987dd.b89378"
|
||||
],
|
||||
[],
|
||||
[
|
||||
"eaca83c4.5fcaf"
|
||||
],
|
||||
[],
|
||||
[],
|
||||
[
|
||||
"7b6cbc9d.18fe44"
|
||||
],
|
||||
[
|
||||
"d269537.4738fb"
|
||||
],
|
||||
[
|
||||
"409e4762.71ff68"
|
||||
],
|
||||
[
|
||||
"13fbfc5d.40dcc4"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "eaca83c4.5fcaf",
|
||||
"type": "binary",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "button",
|
||||
"property": "payload",
|
||||
"pattern": "b8 => button",
|
||||
"x": 630,
|
||||
"y": 280,
|
||||
"wires": [
|
||||
[
|
||||
"a6037445.eb8ac8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "409e4762.71ff68",
|
||||
"type": "binary",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "cwa",
|
||||
"property": "payload",
|
||||
"pattern": "l16 => cwa",
|
||||
"x": 630,
|
||||
"y": 140,
|
||||
"wires": [
|
||||
[
|
||||
"2966fd1c.0b33d2"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d0276db6.83c46",
|
||||
"type": "base64",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "Decode",
|
||||
"action": "",
|
||||
"property": "payload",
|
||||
"x": 200,
|
||||
"y": 260,
|
||||
"wires": [
|
||||
[
|
||||
"df4bdce5.dc219"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "13fbfc5d.40dcc4",
|
||||
"type": "binary",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "Connection",
|
||||
"property": "payload",
|
||||
"pattern": "b8[19]|str(\"ascii\")",
|
||||
"x": 650,
|
||||
"y": 440,
|
||||
"wires": [
|
||||
[
|
||||
"4f59740b.296b7c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "800f5faa.15155",
|
||||
"type": "ui_chart",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "pax",
|
||||
"group": "6838565d.06bf08",
|
||||
"order": 1,
|
||||
"width": 0,
|
||||
"height": 0,
|
||||
"label": "Pax [Wifi]",
|
||||
"chartType": "line",
|
||||
"legend": "false",
|
||||
"xformat": "dd HH:mm",
|
||||
"interpolate": "linear",
|
||||
"nodata": "Noch keine Daten",
|
||||
"dot": false,
|
||||
"ymin": "",
|
||||
"ymax": "",
|
||||
"removeOlder": 1,
|
||||
"removeOlderPoints": "",
|
||||
"removeOlderUnit": "3600",
|
||||
"cutout": 0,
|
||||
"useOneColor": false,
|
||||
"useUTC": false,
|
||||
"colors": [
|
||||
"#1f77b4",
|
||||
"#aec7e8",
|
||||
"#ff7f0e",
|
||||
"#2ca02c",
|
||||
"#98df8a",
|
||||
"#d62728",
|
||||
"#ff9896",
|
||||
"#9467bd",
|
||||
"#c5b0d5"
|
||||
],
|
||||
"outputs": 1,
|
||||
"x": 810,
|
||||
"y": 100,
|
||||
"wires": [
|
||||
[]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2966fd1c.0b33d2",
|
||||
"type": "ui_chart",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "cwa",
|
||||
"group": "6838565d.06bf08",
|
||||
"order": 1,
|
||||
"width": 0,
|
||||
"height": 0,
|
||||
"label": "CWA",
|
||||
"chartType": "line",
|
||||
"legend": "false",
|
||||
"xformat": "dd HH:mm",
|
||||
"interpolate": "linear",
|
||||
"nodata": "",
|
||||
"dot": false,
|
||||
"ymin": "",
|
||||
"ymax": "",
|
||||
"removeOlder": 1,
|
||||
"removeOlderPoints": "",
|
||||
"removeOlderUnit": "3600",
|
||||
"cutout": 0,
|
||||
"useOneColor": false,
|
||||
"useUTC": false,
|
||||
"colors": [
|
||||
"#1f77b4",
|
||||
"#aec7e8",
|
||||
"#ff7f0e",
|
||||
"#2ca02c",
|
||||
"#98df8a",
|
||||
"#d62728",
|
||||
"#ff9896",
|
||||
"#9467bd",
|
||||
"#c5b0d5"
|
||||
],
|
||||
"outputs": 1,
|
||||
"x": 810,
|
||||
"y": 140,
|
||||
"wires": [
|
||||
[]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a6037445.eb8ac8",
|
||||
"type": "ui_toast",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"position": "top right",
|
||||
"displayTime": "3",
|
||||
"highlight": "",
|
||||
"sendall": true,
|
||||
"outputs": 0,
|
||||
"ok": "OK",
|
||||
"cancel": "",
|
||||
"raw": false,
|
||||
"topic": "Button",
|
||||
"name": "Popup",
|
||||
"x": 810,
|
||||
"y": 280,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b4478f8.f8b747",
|
||||
"type": "mqtt out",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "Olimex",
|
||||
"topic": "paxin",
|
||||
"qos": "",
|
||||
"retain": "",
|
||||
"broker": "bd56b04d.db0ff",
|
||||
"x": 190,
|
||||
"y": 480,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "e2974f79.55d5b",
|
||||
"type": "binary",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "device status",
|
||||
"property": "payload",
|
||||
"pattern": "l16 => voltage,\nl64 => uptime,\nb8 => temperature,\nl32 => ram,\nb8 => reset0,\nb8 => reset1",
|
||||
"x": 650,
|
||||
"y": 200,
|
||||
"wires": [
|
||||
[
|
||||
"4f59740b.296b7c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5f6987dd.b89378",
|
||||
"type": "binary",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "device config",
|
||||
"property": "payload",
|
||||
"pattern": "b8 => loradr,\nb8 => txPower,\nl16 => rssilimit,\nb8 => sendcycle,\nb8 => wifichancycle,\nb8 => blescantime,\nb8 => rgblum,\nb8 => configmask,\nb8 => payloadmask,\nb8z|str(\"ascii\") => version",
|
||||
"x": 650,
|
||||
"y": 240,
|
||||
"wires": [
|
||||
[
|
||||
"4f59740b.296b7c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7b6cbc9d.18fe44",
|
||||
"type": "binary",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "battery",
|
||||
"property": "payload",
|
||||
"pattern": "l16 => voltage",
|
||||
"x": 630,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"4f59740b.296b7c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d269537.4738fb",
|
||||
"type": "binary",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "time",
|
||||
"property": "payload",
|
||||
"pattern": "l32 => unixtime",
|
||||
"x": 630,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"4f59740b.296b7c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ce0cb32b.b7b96",
|
||||
"type": "base64",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "Encode",
|
||||
"action": "",
|
||||
"property": "payload",
|
||||
"x": 200,
|
||||
"y": 420,
|
||||
"wires": [
|
||||
[
|
||||
"b4478f8.f8b747"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c246a129.eeb5e",
|
||||
"type": "inject",
|
||||
"z": "c26229c6.2d1ae8",
|
||||
"name": "rcmd",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "paxin",
|
||||
"payload": "[128, 129]",
|
||||
"payloadType": "bin",
|
||||
"x": 190,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"ce0cb32b.b7b96"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bd56b04d.db0ff",
|
||||
"type": "mqtt-broker",
|
||||
"name": "Shiftr.io",
|
||||
"broker": "public.cloud.shiftr.io",
|
||||
"port": "1883",
|
||||
"clientid": "",
|
||||
"usetls": false,
|
||||
"compatmode": false,
|
||||
"keepalive": "60",
|
||||
"cleansession": true,
|
||||
"birthTopic": "paxout/status",
|
||||
"birthQos": "0",
|
||||
"birthPayload": "on",
|
||||
"closeTopic": "paxout/status",
|
||||
"closeQos": "0",
|
||||
"closePayload": "off",
|
||||
"willTopic": "paxout/status",
|
||||
"willQos": "0",
|
||||
"willPayload": "unknown"
|
||||
},
|
||||
{
|
||||
"id": "6838565d.06bf08",
|
||||
"type": "ui_group",
|
||||
"name": "MQTT",
|
||||
"tab": "ad5894fa.466c58",
|
||||
"order": 1,
|
||||
"disp": true,
|
||||
"width": "6",
|
||||
"collapse": false
|
||||
},
|
||||
{
|
||||
"id": "ad5894fa.466c58",
|
||||
"type": "ui_tab",
|
||||
"name": "Paxcounter",
|
||||
"icon": "people",
|
||||
"order": 4
|
||||
}
|
||||
]
|
||||
File renamed without changes.
File renamed without changes.
@@ -262,7 +262,7 @@ var bitmap2 = function (byte) {
|
||||
}
|
||||
var i = bytesToInt(byte);
|
||||
var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean);
|
||||
return ['battery', 'sensor3', 'sensor2', 'sensor1', 'counter', 'bme', 'alarm', 'gps']
|
||||
return ['battery', 'sensor3', 'sensor2', 'sensor1', 'gps', 'bme', 'alarm', 'counter']
|
||||
.reduce(function (obj, pos, index) {
|
||||
obj[pos] = +bm[index];
|
||||
return obj;
|
||||
|
||||
+1
-2
@@ -277,12 +277,11 @@ void start_BLEscan(void) {
|
||||
// Register callback function for capturing bluetooth packets
|
||||
register_ble_callback(false);
|
||||
ESP_LOGI(TAG, "Bluetooth scanner started");
|
||||
#endif // BLECOUNTER
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Bluetooth controller start failed. Resetting device");
|
||||
do_reset(true);
|
||||
}
|
||||
|
||||
#endif // BLECOUNTER
|
||||
} // start_BLEscan
|
||||
|
||||
void stop_BLEscan(void) {
|
||||
|
||||
+11
-54
@@ -46,10 +46,10 @@ Adafruit_BMP085 bmp; // I2C
|
||||
void setBMEIRQ() { xTaskNotify(irqHandlerTask, BME_IRQ, eSetBits); }
|
||||
|
||||
// initialize MEMS sensor
|
||||
// return = 0 -> error / return = 1 -> success
|
||||
int bme_init(void) {
|
||||
|
||||
// return = 0 -> error / return = 1 -> success
|
||||
int rc = 1;
|
||||
int rc = 0;
|
||||
|
||||
#ifdef HAS_BME680
|
||||
// block i2c bus access
|
||||
@@ -63,76 +63,33 @@ int bme_init(void) {
|
||||
iaqSensor.version.minor_bugfix);
|
||||
|
||||
iaqSensor.setConfig(bsec_config_iaq);
|
||||
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "BME680 sensor found and initialized");
|
||||
else {
|
||||
ESP_LOGE(TAG, "BME680 sensor not found");
|
||||
rc = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
loadState();
|
||||
|
||||
iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET);
|
||||
iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
|
||||
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "BSEC subscription succesful");
|
||||
else {
|
||||
ESP_LOGE(TAG, "BSEC subscription error");
|
||||
rc = 0;
|
||||
goto finish;
|
||||
}
|
||||
} else {
|
||||
rc = checkIaqSensorStatus();
|
||||
|
||||
} else
|
||||
ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error");
|
||||
rc = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
#elif defined HAS_BME280
|
||||
|
||||
bool status;
|
||||
|
||||
// block i2c bus access
|
||||
if (I2C_MUTEX_LOCK()) {
|
||||
|
||||
status = bme.begin(BME280_ADDR);
|
||||
if (!status) {
|
||||
ESP_LOGE(TAG, "BME280 sensor not found");
|
||||
rc = 0;
|
||||
goto finish;
|
||||
}
|
||||
ESP_LOGI(TAG, "BME280 sensor found and initialized");
|
||||
} else {
|
||||
rc = bme.begin(BME280_ADDR);
|
||||
} else
|
||||
ESP_LOGE(TAG, "I2c bus busy - BME280 initialization error");
|
||||
rc = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
#elif defined HAS_BMP180
|
||||
bool status;
|
||||
// block i2c bus access
|
||||
if (I2C_MUTEX_LOCK()) {
|
||||
// Wire.begin(21, 22);
|
||||
status = bmp.begin();
|
||||
if (!status) {
|
||||
ESP_LOGE(TAG, "BMP180 sensor not found");
|
||||
rc = 0;
|
||||
goto finish;
|
||||
}
|
||||
ESP_LOGI(TAG, "BMP180 sensor found and initialized");
|
||||
} else {
|
||||
rc = bmp.begin();
|
||||
} else
|
||||
ESP_LOGE(TAG, "I2c bus busy - BMP180 initialization error");
|
||||
rc = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
finish:
|
||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
||||
if (rc)
|
||||
bmecycler.attach(BMECYCLE, setBMEIRQ);
|
||||
bmecycler.attach(BMECYCLE, setBMEIRQ); // start cyclic data transmit
|
||||
return rc;
|
||||
|
||||
} // bme_init()
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
// (c) by Kaspar Metz
|
||||
// modified for use in the Paxcounter by AQ
|
||||
|
||||
#if (COUNT_ENS) && !(BLECOUNTER)
|
||||
#warning ENS-Counter needs Bluetooth, but Bluetooth compile option is disabled
|
||||
#endif
|
||||
|
||||
#if (COUNT_ENS)
|
||||
|
||||
// Local logging tag
|
||||
|
||||
+7
-13
@@ -14,22 +14,15 @@ extern boolean isSDS011Active;
|
||||
#endif
|
||||
|
||||
void setCyclicIRQ() {
|
||||
xTaskNotifyFromISR(irqHandlerTask, CYCLIC_IRQ, eSetBits, NULL);
|
||||
xTaskNotify(irqHandlerTask, CYCLIC_IRQ, eSetBits);
|
||||
}
|
||||
|
||||
// do all housekeeping
|
||||
void doHousekeeping() {
|
||||
|
||||
// check if update mode trigger switch was set
|
||||
if (RTC_runmode == RUNMODE_UPDATE) {
|
||||
// check battery status if we can before doing ota
|
||||
if (batt_sufficient()) {
|
||||
do_reset(true); // warmstart to runmode update
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Battery level %d%% is too low for OTA", batt_level);
|
||||
RTC_runmode = RUNMODE_NORMAL; // keep running in normal mode
|
||||
}
|
||||
}
|
||||
// check if update mode trigger switch was set by rcommand
|
||||
if (RTC_runmode == RUNMODE_UPDATE)
|
||||
do_reset(true);
|
||||
|
||||
// heap and task storage debugging
|
||||
ESP_LOGD(TAG, "Heap: Free:%d, Min:%d, Size:%d, Alloc:%d, StackHWM:%d",
|
||||
@@ -41,6 +34,8 @@ void doHousekeeping() {
|
||||
ESP_LOGD(TAG, "MACprocessor %d bytes left | Taskstate = %d",
|
||||
uxTaskGetStackHighWaterMark(macProcessTask),
|
||||
eTaskGetState(macProcessTask));
|
||||
ESP_LOGD(TAG, "Rcommand interpreter %d bytes left | Taskstate = %d",
|
||||
uxTaskGetStackHighWaterMark(rcmdTask), eTaskGetState(rcmdTask));
|
||||
#if (HAS_LORA)
|
||||
ESP_LOGD(TAG, "LMiCtask %d bytes left | Taskstate = %d",
|
||||
uxTaskGetStackHighWaterMark(lmicTask), eTaskGetState(lmicTask));
|
||||
@@ -104,7 +99,6 @@ void doHousekeeping() {
|
||||
"free heap = %d bytes)",
|
||||
ESP.getMinFreeHeap(), ESP.getFreeHeap());
|
||||
reset_counters(); // clear macs container and reset all counters
|
||||
get_salt(); // get new salt for salting hashes
|
||||
|
||||
if (ESP.getMinFreeHeap() <= MEM_LOW) // check again
|
||||
do_reset(true); // memory leak, reset device
|
||||
@@ -115,7 +109,6 @@ void doHousekeeping() {
|
||||
if (ESP.getMinFreePsram() <= MEM_LOW) {
|
||||
ESP_LOGI(TAG, "PSRAM full, counter cleared");
|
||||
reset_counters(); // clear macs container and reset all counters
|
||||
get_salt(); // get new salt for salting hashes
|
||||
|
||||
if (ESP.getMinFreePsram() <= MEM_LOW) // check again
|
||||
do_reset(true); // memory leak, reset device
|
||||
@@ -147,6 +140,7 @@ void reset_counters() {
|
||||
macs.clear(); // clear all macs container
|
||||
macs_wifi = 0;
|
||||
macs_ble = 0;
|
||||
renew_salt(); // get new salt
|
||||
#ifdef HAS_DISPLAY
|
||||
dp_plotCurve(0, true);
|
||||
#endif
|
||||
|
||||
+3
-3
@@ -345,10 +345,10 @@ void dp_drawPage(time_t t, bool nextpage) {
|
||||
|
||||
#if (HAS_LORA)
|
||||
// LMiC event display
|
||||
dp_printf("%-16s", lmic_event_msg);
|
||||
dp_printf("%-16s ", lmic_event_msg);
|
||||
// LORA datarate, display inverse if ADR disabled
|
||||
dp_setFont(MY_FONT_SMALL, !cfg.adrmode);
|
||||
dp_printf(" %-4s", getSfName(updr2rps(LMIC.datarate)));
|
||||
dp_printf("%-4s", getSfName(updr2rps(LMIC.datarate)));
|
||||
dp_setFont(MY_FONT_SMALL, 0);
|
||||
dp_println();
|
||||
#endif // HAS_LORA
|
||||
@@ -400,7 +400,7 @@ void dp_drawPage(time_t t, bool nextpage) {
|
||||
gps.location.lat());
|
||||
|
||||
// line 6-7: GPS longitude
|
||||
dp_printf("%c%07.4f", gps.location.rawLat().negative ? 'W' : 'E',
|
||||
dp_printf("%c%07.4f", gps.location.rawLng().negative ? 'W' : 'E',
|
||||
gps.location.lng());
|
||||
|
||||
} else {
|
||||
|
||||
+12
-19
@@ -30,34 +30,27 @@ static uint16_t nmea_txDelay_ms = 0;
|
||||
// initialize and configure GPS
|
||||
int gps_init(void) {
|
||||
|
||||
int ret = 1;
|
||||
|
||||
if (!gps_config()) {
|
||||
ESP_LOGE(TAG, "GPS chip initializiation error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef GPS_SERIAL
|
||||
ESP_LOGI(TAG, "Opening serial GPS");
|
||||
GPS_Serial.begin(GPS_SERIAL);
|
||||
ESP_LOGI(TAG, "Using serial GPS");
|
||||
#elif defined GPS_I2C
|
||||
ESP_LOGI(TAG, "Opening I2C GPS");
|
||||
Wire.begin(GPS_I2C, 400000); // I2C connect to GPS device with 400 KHz
|
||||
Wire.beginTransmission(GPS_ADDR);
|
||||
Wire.write(0x00); // dummy write
|
||||
ret = Wire.endTransmission(); // check if chip is seen on i2c bus
|
||||
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG,
|
||||
"Quectel L76 GPS chip not found on i2c bus, bus error %d. "
|
||||
"Stopping GPS-Task.",
|
||||
ret);
|
||||
ret = 0;
|
||||
} else {
|
||||
Wire.write(0x00); // dummy write
|
||||
if (Wire.endTransmission()) {
|
||||
ESP_LOGE(TAG, "Quectel L76 GPS chip not found");
|
||||
return 0;
|
||||
} else
|
||||
ESP_LOGI(TAG, "Quectel L76 GPS chip found");
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return 1;
|
||||
} // gps_init()
|
||||
|
||||
// detect gps chipset type and configure it with device specific settings
|
||||
@@ -109,7 +102,7 @@ time_t get_gpstime(uint16_t *msec) {
|
||||
#endif
|
||||
|
||||
// did we get a current date & time?
|
||||
if (gpstime.isValid() && gpsday.isValid()) {
|
||||
if (gpstime.isValid()) {
|
||||
|
||||
time_t t = 0;
|
||||
tmElements_t tm;
|
||||
@@ -126,8 +119,8 @@ time_t get_gpstime(uint16_t *msec) {
|
||||
tm.Year = CalendarYrToTm(atoi(gpsyear.value())); // year offset from 1970
|
||||
t = makeTime(tm);
|
||||
|
||||
// ESP_LOGD(TAG, "GPS time/date = %2d:%2d:%2d / %2d.%2d.%2d", tm.Hour,
|
||||
// tm.Minute, tm.Second, tm.Day, tm.Month, tm.Year + 1970);
|
||||
ESP_LOGD(TAG, "GPS time/date = %02d:%02d:%02d / %02d.%02d.%2d", tm.Hour,
|
||||
tm.Minute, tm.Second, tm.Day, tm.Month, tm.Year + 1970);
|
||||
|
||||
// add protocol delay with millisecond precision
|
||||
t += delay_ms / 1000 - 1; // whole seconds
|
||||
@@ -188,4 +181,4 @@ void gps_loop(void *pvParameters) {
|
||||
|
||||
} // gps_loop()
|
||||
|
||||
#endif // HAS_GPS
|
||||
#endif // HAS_GPS
|
||||
@@ -10,7 +10,6 @@
|
||||
// Hardware related definitions for Pycom LoPy4 Board
|
||||
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define LORA_RST LMIC_UNUSED_PIN // reset pin of lora chip is not wired von LoPy4
|
||||
|
||||
//#defin HAS_SPI 1 // comment out if device shall not send data via SPI
|
||||
// pin definitions for local wired SPI slave interface
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// clang-format off
|
||||
// upload_speed 1500000
|
||||
// board pico32
|
||||
|
||||
#ifndef _TTGOTWRISTBAND_H
|
||||
#define _TTGOTWRISTBAND_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
|
||||
|
||||
#define HAS_DISPLAY 2 // TFT-LCD, support work in progess, not ready yet
|
||||
#define MY_DISPLAY_FLIP 1 // use if display is rotated
|
||||
|
||||
#define HAS_LED NOT_A_PIN // no on board LED (?)
|
||||
#define HAS_BUTTON (33) // on board button A
|
||||
|
||||
// power management settings
|
||||
#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
|
||||
#define BAT_VOLTAGE_DIVIDER 2.605f // voltage divider
|
||||
|
||||
// Display Settings
|
||||
#define MY_DISPLAY_WIDTH 80
|
||||
#define MY_DISPLAY_HEIGHT 160
|
||||
#define MY_DISPLAY_INVERT 1
|
||||
|
||||
// setting for TTGO T-display
|
||||
#define USER_SETUP_LOADED 1
|
||||
#define ST7735_DRIVER 1
|
||||
|
||||
#define CGRAM_OFFSET
|
||||
|
||||
#define TFT_MISO -1
|
||||
#define TFT_MOSI GPIO_NUM_19 // SPI
|
||||
#define TFT_SCLK GPIO_NUM_18 // SPI
|
||||
#define TFT_CS GPIO_NUM_5 // Chip select control
|
||||
#define TFT_DC GPIO_NUM_23 // Data Command control
|
||||
#define TFT_RST GPIO_NUM_26 // Reset
|
||||
#define TFT_BL GPIO_NUM_27 // LED back-light
|
||||
#define TFT_BACKLIGHT_ON 1
|
||||
#define ST7735_GREENTAB160x80
|
||||
|
||||
#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
|
||||
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
#define SMOOTH_FONT
|
||||
|
||||
#define SPI_FREQUENCY 27000000
|
||||
#define SPI_READ_FREQUENCY 6000000
|
||||
|
||||
#endif
|
||||
|
||||
+5
-47
@@ -36,52 +36,10 @@
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
uint32_t IRAM_ATTR rokkit(const char *data, int len) {
|
||||
uint32_t hash, tmp;
|
||||
int rem;
|
||||
#ifdef ROKKIT_ENABLE_8BIT_OPTIMIZATIONS
|
||||
#undef ROKKIT_ENABLE_8BIT_OPTIMIZATIONS
|
||||
#endif
|
||||
|
||||
if (len <= 0 || data == 0)
|
||||
return 0;
|
||||
hash = len;
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
while (len > 0) {
|
||||
hash += *((uint16_t *)data);
|
||||
tmp = (*((uint16_t *)(data + 2)) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2 * 2;
|
||||
hash += hash >> 11;
|
||||
len--;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3:
|
||||
hash += *((uint16_t *)data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= ((signed char)data[2]) << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2:
|
||||
hash += *((uint16_t *)data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1:
|
||||
hash += (signed char)*data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
uint32_t IRAM_ATTR hash(const char *data, int len) {
|
||||
return rokkit(data, len);
|
||||
}
|
||||
+2
-2
@@ -84,7 +84,7 @@ void i2c_scan(void) {
|
||||
}
|
||||
|
||||
// mutexed functions for i2c r/w access
|
||||
uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||
int i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||
if (I2C_MUTEX_LOCK()) {
|
||||
|
||||
uint8_t ret = 0;
|
||||
@@ -112,7 +112,7 @@ uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||
int i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||
if (I2C_MUTEX_LOCK()) {
|
||||
|
||||
uint8_t ret = 0;
|
||||
|
||||
+4
-3
@@ -18,9 +18,10 @@
|
||||
|
||||
// use interrupts only if LORA_IRQ and LORA_DIO are connected to interrupt
|
||||
// capable and separate GPIO pins on your board, if not don't enable
|
||||
#if (LORA_IRQ) != (LORA_IO1)
|
||||
#define LMIC_USE_INTERRUPTS 1
|
||||
#endif
|
||||
// note: this feature can't be used on ESP32 unless PR #556 of MCCI LMIC was merged
|
||||
//#if (LORA_IRQ) != (LORA_IO1)
|
||||
//#define LMIC_USE_INTERRUPTS 1
|
||||
//#endif
|
||||
|
||||
// avoid lmic warning if we don't configure radio in case we haven't one
|
||||
#if !(defined(CFG_sx1272_radio) || defined(CFG_sx1276_radio))
|
||||
|
||||
+5
-9
@@ -19,7 +19,7 @@ RTC_DATA_ATTR lmic_t RTC_LMIC;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
QueueHandle_t LoraSendQueue;
|
||||
static QueueHandle_t LoraSendQueue;
|
||||
TaskHandle_t lmicTask = NULL, lorasendTask = NULL;
|
||||
|
||||
class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t {
|
||||
@@ -284,14 +284,10 @@ esp_err_t lmic_init(void) {
|
||||
// Pass OTA parameters to LMIC_setSession
|
||||
#else
|
||||
// load saved session from RTC, if we have one
|
||||
if (RTC_runmode == RUNMODE_WAKEUP) {
|
||||
if (RTC_runmode == RUNMODE_WAKEUP)
|
||||
LoadLMICFromRTC();
|
||||
}
|
||||
// otherwise start join procedure if not already joined
|
||||
else {
|
||||
if (!LMIC_startJoining())
|
||||
ESP_LOGI(TAG, "Already joined");
|
||||
}
|
||||
if (!LMIC_startJoining())
|
||||
ESP_LOGI(TAG, "Already joined");
|
||||
#endif
|
||||
|
||||
// start lmic loop task
|
||||
@@ -545,7 +541,7 @@ void SaveLMICToRTC(int deepsleep_sec) {
|
||||
unsigned long now = millis();
|
||||
|
||||
// EU Like Bands
|
||||
#if defined(CFG_LMIC_EU_like)
|
||||
#if CFG_LMIC_EU_like
|
||||
for (int i = 0; i < MAX_BANDS; i++) {
|
||||
ostime_t correctedAvail =
|
||||
RTC_LMIC.bands[i].avail -
|
||||
|
||||
+25
-29
@@ -6,13 +6,14 @@
|
||||
// Local logging tag
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
QueueHandle_t MacQueue;
|
||||
static QueueHandle_t MacQueue;
|
||||
TaskHandle_t macProcessTask;
|
||||
|
||||
uint16_t salt = 0;
|
||||
static uint32_t salt = renew_salt();
|
||||
|
||||
uint16_t get_salt(void) {
|
||||
salt = (uint16_t)random(65536); // get new 16bit random for salting hashes
|
||||
uint32_t renew_salt(void) {
|
||||
salt = esp_random();
|
||||
ESP_LOGV(TAG, "new salt = %04X", salt);
|
||||
return salt;
|
||||
}
|
||||
|
||||
@@ -101,8 +102,9 @@ void IRAM_ATTR mac_add(uint8_t *paddr, int8_t rssi, snifftype_t sniff_type) {
|
||||
|
||||
uint16_t mac_analyze(MacBuffer_t MacBuffer) {
|
||||
|
||||
if (salt == 0) // ensure we have salt (appears after radio is turned on)
|
||||
return 0;
|
||||
uint32_t *mac; // pointer to shortened 4 byte MAC
|
||||
uint32_t saltedmac;
|
||||
uint16_t hashedmac;
|
||||
|
||||
if ((cfg.rssilimit) &&
|
||||
(MacBuffer.rssi < cfg.rssilimit)) { // rssi is negative value
|
||||
@@ -117,18 +119,13 @@ uint16_t mac_analyze(MacBuffer_t MacBuffer) {
|
||||
int8_t beaconID = isBeacon(macConvert(MacBuffer.mac));
|
||||
if (beaconID >= 0) {
|
||||
ESP_LOGI(TAG, "Beacon ID#%d detected", beaconID);
|
||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||
blink_LED(COLOR_WHITE, 2000);
|
||||
#endif
|
||||
payload.reset();
|
||||
payload.addAlarm(MacBuffer.rssi, beaconID);
|
||||
SendPayload(BEACONPORT);
|
||||
}
|
||||
};
|
||||
|
||||
char buff[10]; // temporary buffer for printf
|
||||
uint32_t *mac; // temporary buffer for shortened MAC
|
||||
|
||||
// only last 3 MAC Address bytes are used for MAC address anonymization
|
||||
// but since it's uint32 we take 4 bytes to avoid 1st value to be 0.
|
||||
// this gets MAC in msb (= reverse) order, but doesn't matter for hashing it.
|
||||
@@ -138,11 +135,15 @@ uint16_t mac_analyze(MacBuffer_t MacBuffer) {
|
||||
// and increment counter on display
|
||||
// https://en.wikipedia.org/wiki/MAC_Address_Anonymization
|
||||
|
||||
snprintf(buff, sizeof(buff), "%08X",
|
||||
*mac + (uint32_t)salt); // convert unsigned 32-bit salted MAC
|
||||
// to 8 digit hex string
|
||||
uint16_t hashedmac = rokkit(&buff[3], 5); // hash MAC 8 digit -> 5 digit
|
||||
auto newmac = macs.insert(hashedmac); // add hashed MAC, if new unique
|
||||
// reversed 4 byte MAC added to current salt
|
||||
saltedmac = *mac + salt;
|
||||
|
||||
// hashed 4 byte MAC
|
||||
// to save RAM, we use only lower 2 bytes of hash, since collisions don't
|
||||
// matter in our use case
|
||||
hashedmac = hash((const char *)&saltedmac, 4);
|
||||
|
||||
auto newmac = macs.insert(hashedmac); // add hashed MAC, if new unique
|
||||
bool added =
|
||||
newmac.second ? true : false; // true if hashed MAC is unique in container
|
||||
|
||||
@@ -153,37 +154,30 @@ uint16_t mac_analyze(MacBuffer_t MacBuffer) {
|
||||
|
||||
case MAC_SNIFF_WIFI:
|
||||
macs_wifi++; // increment Wifi MACs counter
|
||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||
blink_LED(COLOR_GREEN, 50);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if (BLECOUNTER)
|
||||
case MAC_SNIFF_BLE:
|
||||
macs_ble++; // increment BLE Macs counter
|
||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||
blink_LED(COLOR_MAGENTA, 50);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if (COUNT_ENS)
|
||||
case MAC_SNIFF_BLE_ENS:
|
||||
macs_ble++; // increment BLE Macs counter
|
||||
cwa_mac_add(hashedmac); // process ENS beacon
|
||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||
blink_LED(COLOR_WHITE, 50);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#endif // COUNT_ENS
|
||||
#endif // BLECOUNTER
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
|
||||
} // switch
|
||||
} // added
|
||||
|
||||
// Log scan result
|
||||
ESP_LOGV(TAG,
|
||||
"%s %s RSSI %ddBi -> salted MAC %s -> Hash %04X -> WiFi:%d "
|
||||
"%s %s RSSI %ddBi -> MAC %0x:%0x:%0x:%0x:%0x:%0x -> salted %04X"
|
||||
" -> hashed %04X -> WiFi:%d "
|
||||
"BLTH:%d "
|
||||
#if (COUNT_ENS)
|
||||
"(CWA:%d)"
|
||||
@@ -191,7 +185,9 @@ uint16_t mac_analyze(MacBuffer_t MacBuffer) {
|
||||
"-> %d Bytes left",
|
||||
added ? "new " : "known",
|
||||
MacBuffer.sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH",
|
||||
MacBuffer.rssi, buff, hashedmac, macs_wifi, macs_ble,
|
||||
MacBuffer.rssi, MacBuffer.mac[0], MacBuffer.mac[1], MacBuffer.mac[2],
|
||||
MacBuffer.mac[3], MacBuffer.mac[4], MacBuffer.mac[5], saltedmac,
|
||||
hashedmac, macs_wifi, macs_ble,
|
||||
#if (COUNT_ENS)
|
||||
cwa_report(),
|
||||
#endif
|
||||
|
||||
+16
-7
@@ -29,16 +29,17 @@ Task Core Prio Purpose
|
||||
-------------------------------------------------------------------------------
|
||||
ledloop 0 3 blinks LEDs
|
||||
spiloop 0 2 reads/writes data on spi interface
|
||||
mqttloop 0 2 reads/writes data on ETH interface
|
||||
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
||||
|
||||
lmictask 1 2 MCCI LMiC LORAWAN stack
|
||||
clockloop 1 4 generates realtime telegrams for external clock
|
||||
mqttloop 1 2 reads/writes data on ETH interface
|
||||
timesync_proc 1 3 processes realtime time sync requests
|
||||
irqhandler 1 2 cyclic tasks (i.e. displayrefresh) triggered by timers
|
||||
gpsloop 1 1 reads data from GPS via serial or i2c
|
||||
lorasendtask 1 1 feeds data from lora sendqueue to lmcic
|
||||
macprocess 1 1 analyzes sniffed MACs
|
||||
macprocess 1 1 MAC analyzer loop
|
||||
rmcd_process 1 1 Remote command interpreter loop
|
||||
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
||||
|
||||
Low priority numbers denote low priority tasks.
|
||||
@@ -60,8 +61,10 @@ irqHandlerTask (Core 1), see irqhandler.cpp
|
||||
|
||||
fired by hardware
|
||||
DisplayIRQ -> esp32 timer 0
|
||||
ButtonIRQ -> external gpio
|
||||
PMUIRQ -> PMU chip gpio
|
||||
CLOCKIRQ -> esp32 timer 1 or external GPIO (RTC_INT or GPS_INT)
|
||||
MatrixDisplayIRQ-> esp32 timer 3
|
||||
ButtonIRQ -> external GPIO
|
||||
PMUIRQ -> PMU chip GPIO
|
||||
|
||||
fired by software (Ticker.h)
|
||||
TIMESYNC_IRQ -> setTimeSyncIRQ()
|
||||
@@ -100,7 +103,7 @@ timesource_t timeSource = _unsynced;
|
||||
|
||||
// container holding unique MAC address hashes with Memory Alloctor using PSRAM,
|
||||
// if present
|
||||
std::set<uint16_t, std::less<uint16_t>, Mallocator<uint16_t>> macs;
|
||||
DRAM_ATTR std::set<uint16_t, std::less<uint16_t>, Mallocator<uint16_t>> macs;
|
||||
|
||||
// initialize payload encoder
|
||||
PayloadConvert payload(PAYLOAD_BUFFER_SIZE);
|
||||
@@ -291,6 +294,10 @@ void setup() {
|
||||
ESP_LOGI(TAG, "Starting MAC processor...");
|
||||
macQueueInit();
|
||||
|
||||
// start rcommand processing task
|
||||
ESP_LOGI(TAG, "Starting rcommand interpreter...");
|
||||
rcmd_init();
|
||||
|
||||
// start BLE scan callback if BLE function is enabled in NVRAM configuration
|
||||
// or remove bluetooth stack from RAM, if option bluetooth is not compiled
|
||||
#if (BLECOUNTER)
|
||||
@@ -428,7 +435,7 @@ void setup() {
|
||||
// initialize salt value using esp_random() called by random() in
|
||||
// arduino-esp32 core. Note: do this *after* wifi has started, since
|
||||
// function gets it's seed from RF noise
|
||||
get_salt(); // get new 16bit for salting hashes
|
||||
reset_counters();
|
||||
|
||||
// start state machine
|
||||
ESP_LOGI(TAG, "Starting Interrupt Handler...");
|
||||
@@ -451,8 +458,10 @@ void setup() {
|
||||
#endif
|
||||
if (bme_init())
|
||||
ESP_LOGI(TAG, "BME sensor initialized");
|
||||
else
|
||||
else {
|
||||
ESP_LOGE(TAG, "BME sensor could not be initialized");
|
||||
cfg.payloadmask &= ~MEMS_DATA; // switch off transmit of BME data
|
||||
}
|
||||
#endif
|
||||
|
||||
// starting timers and interrupts
|
||||
|
||||
+47
-60
@@ -4,7 +4,7 @@
|
||||
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
QueueHandle_t MQTTSendQueue;
|
||||
static QueueHandle_t MQTTSendQueue;
|
||||
TaskHandle_t mqttTask;
|
||||
|
||||
Ticker mqttTimer;
|
||||
@@ -12,6 +12,7 @@ WiFiClient netClient;
|
||||
MQTTClient mqttClient;
|
||||
|
||||
void mqtt_deinit(void) {
|
||||
mqttClient.unsubscribe(MQTT_INTOPIC);
|
||||
mqttClient.onMessageAdvanced(NULL);
|
||||
mqttClient.disconnect();
|
||||
vTaskDelete(mqttTask);
|
||||
@@ -19,12 +20,10 @@ void mqtt_deinit(void) {
|
||||
|
||||
esp_err_t mqtt_init(void) {
|
||||
|
||||
// setup network connection
|
||||
WiFi.onEvent(NetworkEvent);
|
||||
// setup network connection and MQTT client
|
||||
ETH.begin();
|
||||
|
||||
// setup mqtt client
|
||||
mqttClient.begin(MQTT_SERVER, MQTT_PORT, netClient);
|
||||
mqttClient.setKeepAlive(MQTT_KEEPALIVE);
|
||||
mqttClient.onMessageAdvanced(mqtt_callback);
|
||||
|
||||
_ASSERT(SEND_QUEUE_SIZE > 0);
|
||||
@@ -37,15 +36,20 @@ esp_err_t mqtt_init(void) {
|
||||
SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
|
||||
|
||||
ESP_LOGI(TAG, "Starting MQTTloop...");
|
||||
xTaskCreate(mqtt_client_task, "mqttloop", 4096, (void *)NULL, 1, &mqttTask);
|
||||
|
||||
xTaskCreatePinnedToCore(mqtt_client_task, "mqttloop", 4096, (void *)NULL, 1,
|
||||
&mqttTask, 1);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int mqtt_connect(const char *my_host, const uint16_t my_port) {
|
||||
IPAddress mqtt_server_ip;
|
||||
uint8_t mac[6];
|
||||
char clientId[20];
|
||||
|
||||
static String clientId = "paxcounter-" + ETH.macAddress();
|
||||
// hash 6 byte MAC to 4 byte hash
|
||||
esp_eth_get_mac(mac);
|
||||
const uint32_t hashedmac = hash((const char *)mac, 6);
|
||||
snprintf(clientId, 20, "paxcounter_%08x", hashedmac);
|
||||
|
||||
ESP_LOGI(TAG, "MQTT name is %s", MQTT_CLIENTNAME);
|
||||
|
||||
@@ -75,41 +79,6 @@ int mqtt_connect(const char *my_host, const uint16_t my_port) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NetworkEvent(WiFiEvent_t event) {
|
||||
switch (event) {
|
||||
case SYSTEM_EVENT_ETH_START:
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
ESP_LOGI(TAG, "Network link layer started");
|
||||
// ETH.setHostname(ETH.macAddress().c_str());
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_STOP:
|
||||
case SYSTEM_EVENT_STA_STOP:
|
||||
ESP_LOGI(TAG, "Network link layer stopped");
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_CONNECTED:
|
||||
case SYSTEM_EVENT_STA_CONNECTED:
|
||||
ESP_LOGI(TAG, "Network link connected");
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "Network link disconnected");
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
||||
ESP_LOGI(TAG, "IP: %s", ETH.localIP().toString().c_str());
|
||||
ESP_LOGI(TAG, "Link Speed: %d Mbps %s", ETH.linkSpeed(),
|
||||
ETH.fullDuplex() ? "full duplex" : "half duplex");
|
||||
mqtt_connect(MQTT_SERVER, MQTT_PORT);
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
ESP_LOGI(TAG, "IP: %s", WiFi.localIP().toString().c_str());
|
||||
mqtt_connect(MQTT_SERVER, MQTT_PORT);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mqtt_client_task(void *param) {
|
||||
|
||||
MessageBuffer_t msg;
|
||||
@@ -128,21 +97,28 @@ void mqtt_client_task(void *param) {
|
||||
MQTT_KEEPALIVE * 1000 / portTICK_PERIOD_MS) != pdTRUE)
|
||||
continue;
|
||||
|
||||
// send data to mqtt server
|
||||
char buffer[PAYLOAD_BUFFER_SIZE + 3];
|
||||
snprintf(buffer, msg.MessageSize + 3, "%u/%s", msg.MessagePort,
|
||||
msg.Message);
|
||||
// prepare mqtt topic
|
||||
char topic[16];
|
||||
snprintf(topic, 16, "%s/%u", MQTT_OUTTOPIC, msg.MessagePort);
|
||||
size_t out_len = 0;
|
||||
|
||||
if (mqttClient.publish(MQTT_OUTTOPIC, buffer)) {
|
||||
ESP_LOGI(TAG, "%d byte(s) sent to MQTT server", msg.MessageSize + 2);
|
||||
// delete sent item from queue
|
||||
// get length of base64 encoded message
|
||||
mbedtls_base64_encode(NULL, 0, &out_len, (unsigned char *)msg.Message,
|
||||
msg.MessageSize);
|
||||
|
||||
// base64 encode the message
|
||||
unsigned char encoded[out_len];
|
||||
mbedtls_base64_encode(encoded, out_len, &out_len,
|
||||
(unsigned char *)msg.Message, msg.MessageSize);
|
||||
|
||||
// send encoded message to mqtt server and delete it from queue
|
||||
if (mqttClient.publish(topic, (const char *)encoded, out_len)) {
|
||||
ESP_LOGD(TAG, "%u bytes sent to MQTT server", out_len);
|
||||
xQueueReceive(MQTTSendQueue, &msg, (TickType_t)0);
|
||||
} else
|
||||
ESP_LOGD(TAG, "Couldn't sent message to MQTT server");
|
||||
} else {
|
||||
// attempt to reconnect to MQTT server
|
||||
ESP_LOGD(TAG, "MQTT error = %d / rc = %d", mqttClient.lastError(),
|
||||
mqttClient.returnCode());
|
||||
ESP_LOGD(TAG, "MQTT client reconnecting...");
|
||||
delay(MQTT_RETRYSEC * 1000);
|
||||
mqtt_connect(MQTT_SERVER, MQTT_PORT);
|
||||
@@ -150,16 +126,27 @@ void mqtt_client_task(void *param) {
|
||||
} // while (1)
|
||||
}
|
||||
|
||||
void mqtt_enqueuedata(MessageBuffer_t *message) {
|
||||
// enqueue message in MQTT send queue
|
||||
if (xQueueSendToBack(MQTTSendQueue, (void *)message, (TickType_t)0) != pdTRUE)
|
||||
ESP_LOGW(TAG, "MQTT sendqueue is full");
|
||||
// process incoming MQTT messages
|
||||
void mqtt_callback(MQTTClient *client, char *topic, char *payload, int length) {
|
||||
if (strcmp(topic, MQTT_INTOPIC) == 0) {
|
||||
|
||||
// get length of base64 encoded message
|
||||
size_t out_len = 0;
|
||||
mbedtls_base64_decode(NULL, 0, &out_len, (unsigned char *)payload, length);
|
||||
|
||||
// decode the base64 message
|
||||
unsigned char decoded[out_len];
|
||||
mbedtls_base64_decode(decoded, out_len, &out_len, (unsigned char *)payload,
|
||||
length);
|
||||
|
||||
rcommand(decoded, out_len);
|
||||
}
|
||||
}
|
||||
|
||||
void mqtt_callback(MQTTClient *client, char topic[], char payload[],
|
||||
int length) {
|
||||
if (strcmp(topic, MQTT_INTOPIC) == 0)
|
||||
rcommand((const uint8_t *)payload, (const uint8_t)length);
|
||||
// enqueue outgoing messages in MQTT send queue
|
||||
void mqtt_enqueuedata(MessageBuffer_t *message) {
|
||||
if (xQueueSendToBack(MQTTSendQueue, (void *)message, (TickType_t)0) != pdTRUE)
|
||||
ESP_LOGW(TAG, "MQTT sendqueue is full");
|
||||
}
|
||||
|
||||
void mqtt_queuereset(void) { xQueueReset(MQTTSendQueue); }
|
||||
|
||||
@@ -121,3 +121,15 @@
|
||||
#define CAYENNE_DEVICECONFIG 11 // device period configuration
|
||||
#define CAYENNE_SENSORREAD 13 // sensor period configuration
|
||||
#define CAYENNE_SENSORENABLE 14 // sensor enable configuration
|
||||
|
||||
// MQTT settings, only needed if MQTT is used (#define HAS_MQTT in board hal file)
|
||||
#define MQTT_ETHERNET 0 // select PHY: set 0 for Wifi, 1 for ethernet
|
||||
#define MQTT_INTOPIC "paxin"
|
||||
#define MQTT_OUTTOPIC "paxout"
|
||||
#define MQTT_PORT 1883
|
||||
#define MQTT_SERVER "public.cloud.shiftr.io"
|
||||
#define MQTT_USER "public"
|
||||
#define MQTT_PASSWD "public"
|
||||
#define MQTT_RETRYSEC 20 // retry reconnect every 20 seconds
|
||||
#define MQTT_KEEPALIVE 10 // keep alive interval in seconds
|
||||
//#define MQTT_CLIENTNAME "my_paxcounter" // generated by default
|
||||
+21
-7
@@ -46,6 +46,14 @@ void AXP192_powerevent_IRQ(void) {
|
||||
ESP_LOGI(TAG, "Battery high temperature.");
|
||||
if (pmu.isBattTempHighIRQ())
|
||||
ESP_LOGI(TAG, "Battery low temperature.");
|
||||
if (pmu.isLowVoltageLevel1IRQ()) {
|
||||
ESP_LOGI(TAG, "Battery has reached voltage level 1.");
|
||||
pmu.setChgLEDMode(AXP20X_LED_BLINK_4HZ);
|
||||
}
|
||||
if (pmu.isLowVoltageLevel2IRQ()) {
|
||||
ESP_LOGI(TAG, "Battery has reached voltage level 2.");
|
||||
pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ);
|
||||
}
|
||||
|
||||
// short press -> esp32 deep sleep mode, can be exited by pressing user button
|
||||
if (pmu.isPEKShortPressIRQ()) {
|
||||
@@ -129,10 +137,15 @@ void AXP192_init(void) {
|
||||
pmu.setLDO2Voltage(3300); // LORA VDD 3v3
|
||||
pmu.setLDO3Voltage(3300); // GPS VDD 3v3
|
||||
|
||||
// configure voltage warning levels
|
||||
pmu.setVWarningLevel1(3600);
|
||||
pmu.setVWarningLevel2(3800);
|
||||
pmu.setPowerDownVoltage(3300);
|
||||
|
||||
// configure PEK button settings
|
||||
pmu.setTimeOutShutdown(false); // forced shutdown by PEK enabled
|
||||
pmu.setShutdownTime(
|
||||
AXP_POWER_OFF_TIME_65); // 6 sec button press for shutdown
|
||||
AXP_POWER_OFF_TIME_6S); // 6 sec button press for shutdown
|
||||
pmu.setlongPressTime(
|
||||
AXP_LONGPRESS_TIME_1S5); // 1.5 sec button press for long press
|
||||
pmu.setStartupTime(
|
||||
@@ -158,9 +171,9 @@ void AXP192_init(void) {
|
||||
#endif // PMU_INT
|
||||
|
||||
// set charging parameterss according to user settings if we have (see power.h)
|
||||
#ifdef PMU_CHARGE_CURRENT
|
||||
pmu.setChargeControlCur(PMU_CHARGE_CURRENT);
|
||||
pmu.setChargingTargetVoltage(PMU_CHARGE_CUTOFF);
|
||||
#ifdef PMU_CHG_CURRENT
|
||||
pmu.setChargeControlCur(PMU_CHG_CURRENT);
|
||||
pmu.setChargingTargetVoltage(PMU_CHG_CUTOFF);
|
||||
pmu.enableChargeing(true);
|
||||
#endif
|
||||
|
||||
@@ -251,10 +264,11 @@ uint8_t read_battlevel(mapFn_t mapFunction) {
|
||||
|
||||
bool batt_sufficient() {
|
||||
#if (defined HAS_PMU || defined BAT_MEASURE_ADC || defined HAS_IP5306)
|
||||
return (batt_level > OTA_MIN_BATT);
|
||||
#else
|
||||
return true; // we don't know batt level
|
||||
if (batt_level) // we have a battery voltage
|
||||
return (batt_level > OTA_MIN_BATT);
|
||||
else
|
||||
#endif
|
||||
return true; // we don't know batt level
|
||||
}
|
||||
|
||||
#ifdef HAS_IP5306
|
||||
|
||||
+102
-37
@@ -5,8 +5,8 @@
|
||||
// Local logging tag
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
// global variable indicating if rcommand() is executing
|
||||
bool rcmd_busy = false;
|
||||
static QueueHandle_t RcmdQueue;
|
||||
TaskHandle_t rcmdTask;
|
||||
|
||||
// set of functions that can be triggered by remote commands
|
||||
void set_reset(uint8_t val[]) {
|
||||
@@ -18,7 +18,6 @@ void set_reset(uint8_t val[]) {
|
||||
case 1: // reset MAC counter
|
||||
ESP_LOGI(TAG, "Remote command: reset MAC counter");
|
||||
reset_counters(); // clear macs
|
||||
get_salt(); // get new salt
|
||||
break;
|
||||
case 2: // reset device to factory settings
|
||||
ESP_LOGI(TAG, "Remote command: reset device to factory settings");
|
||||
@@ -35,7 +34,11 @@ void set_reset(uint8_t val[]) {
|
||||
case 9: // reset and ask for software update via Wifi OTA
|
||||
ESP_LOGI(TAG, "Remote command: software update via Wifi");
|
||||
#if (USE_OTA)
|
||||
RTC_runmode = RUNMODE_UPDATE;
|
||||
// check power status before scheduling ota update
|
||||
if (batt_sufficient())
|
||||
RTC_runmode = RUNMODE_UPDATE;
|
||||
else
|
||||
ESP_LOGE(TAG, "Battery level %d%% is too low for OTA", batt_level);
|
||||
#endif // USE_OTA
|
||||
break;
|
||||
|
||||
@@ -115,7 +118,6 @@ void set_countmode(uint8_t val[]) {
|
||||
return;
|
||||
}
|
||||
reset_counters(); // clear macs
|
||||
get_salt(); // get new salt
|
||||
}
|
||||
|
||||
void set_screensaver(uint8_t val[]) {
|
||||
@@ -164,7 +166,7 @@ void set_payloadmask(uint8_t val[]) {
|
||||
|
||||
void set_sensor(uint8_t val[]) {
|
||||
#if (HAS_SENSORS)
|
||||
switch (val[0]) { // check if valid sensor number 1...4
|
||||
switch (val[0]) { // check if valid sensor number 1..3
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
@@ -367,41 +369,49 @@ void set_enscount(uint8_t val[]) {
|
||||
cfg.payloadmask &= ~SENSOR1_DATA;
|
||||
}
|
||||
|
||||
void set_loadconfig(uint8_t val[]) {
|
||||
ESP_LOGI(TAG, "Remote command: load config from NVRAM");
|
||||
loadConfig();
|
||||
};
|
||||
|
||||
void set_saveconfig(uint8_t val[]) {
|
||||
ESP_LOGI(TAG, "Remote command: save config to NVRAM");
|
||||
saveConfig(false);
|
||||
};
|
||||
|
||||
// assign previously defined functions to set of numeric remote commands
|
||||
// format: opcode, function, #bytes params,
|
||||
// flag (true = do make settings persistent / false = don't)
|
||||
//
|
||||
// format: {opcode, function, number of function arguments}
|
||||
|
||||
static const cmd_t table[] = {
|
||||
{0x01, set_rssi, 1, true}, {0x02, set_countmode, 1, true},
|
||||
{0x03, set_gps, 1, true}, {0x04, set_display, 1, true},
|
||||
{0x05, set_loradr, 1, true}, {0x06, set_lorapower, 1, true},
|
||||
{0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true},
|
||||
{0x09, set_reset, 1, false}, {0x0a, set_sendcycle, 1, true},
|
||||
{0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true},
|
||||
{0x0d, set_macfilter, 1, false}, {0x0e, set_blescan, 1, true},
|
||||
{0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true},
|
||||
{0x11, set_monitor, 1, true}, {0x12, set_beacon, 7, false},
|
||||
{0x13, set_sensor, 2, true}, {0x14, set_payloadmask, 1, true},
|
||||
{0x15, set_bme, 1, true}, {0x16, set_batt, 1, true},
|
||||
{0x17, set_wifiscan, 1, true}, {0x18, set_enscount, 1, true},
|
||||
{0x19, set_sleepcycle, 1, true}, {0x80, get_config, 0, false},
|
||||
{0x81, get_status, 0, false}, {0x83, get_batt, 0, false},
|
||||
{0x84, get_gps, 0, false}, {0x85, get_bme, 0, false},
|
||||
{0x86, get_time, 0, false}, {0x87, set_time, 0, false},
|
||||
{0x99, set_flush, 0, false}};
|
||||
{0x01, set_rssi, 1}, {0x02, set_countmode, 1},
|
||||
{0x03, set_gps, 1}, {0x04, set_display, 1},
|
||||
{0x05, set_loradr, 1}, {0x06, set_lorapower, 1},
|
||||
{0x07, set_loraadr, 1}, {0x08, set_screensaver, 1},
|
||||
{0x09, set_reset, 1}, {0x0a, set_sendcycle, 1},
|
||||
{0x0b, set_wifichancycle, 1}, {0x0c, set_blescantime, 1},
|
||||
{0x0d, set_macfilter, 1}, {0x0e, set_blescan, 1},
|
||||
{0x0f, set_wifiant, 1}, {0x10, set_rgblum, 1},
|
||||
{0x11, set_monitor, 1}, {0x12, set_beacon, 7},
|
||||
{0x13, set_sensor, 2}, {0x14, set_payloadmask, 1},
|
||||
{0x15, set_bme, 1}, {0x16, set_batt, 1},
|
||||
{0x17, set_wifiscan, 1}, {0x18, set_enscount, 1},
|
||||
{0x19, set_sleepcycle, 1}, {0x20, set_loadconfig, 0},
|
||||
{0x21, set_saveconfig, 0}, {0x80, get_config, 0},
|
||||
{0x81, get_status, 0}, {0x83, get_batt, 0},
|
||||
{0x84, get_gps, 0}, {0x85, get_bme, 0},
|
||||
{0x86, get_time, 0}, {0x87, set_time, 0},
|
||||
{0x99, set_flush, 0}};
|
||||
|
||||
static const uint8_t cmdtablesize =
|
||||
sizeof(table) / sizeof(table[0]); // number of commands in command table
|
||||
|
||||
// check and execute remote command
|
||||
void rcommand(const uint8_t cmd[], const uint8_t cmdlength) {
|
||||
void rcmd_execute(const uint8_t cmd[], const uint8_t cmdlength) {
|
||||
|
||||
if (cmdlength == 0)
|
||||
return;
|
||||
|
||||
uint8_t foundcmd[cmdlength], cursor = 0;
|
||||
bool storeflag = false;
|
||||
rcmd_busy = true;
|
||||
|
||||
while (cursor < cmdlength) {
|
||||
|
||||
@@ -413,8 +423,6 @@ void rcommand(const uint8_t cmd[], const uint8_t cmdlength) {
|
||||
memmove(foundcmd, cmd + cursor,
|
||||
table[i].params); // strip opcode from cmd array
|
||||
cursor += table[i].params;
|
||||
if (table[i].store) // ceck if function needs to store configuration
|
||||
storeflag = true;
|
||||
table[i].func(
|
||||
foundcmd); // execute assigned function with given parameters
|
||||
} else
|
||||
@@ -422,18 +430,75 @@ void rcommand(const uint8_t cmd[], const uint8_t cmdlength) {
|
||||
"Remote command x%02X called with missing parameter(s), "
|
||||
"skipped",
|
||||
table[i].opcode);
|
||||
break; // command found -> exit table lookup loop
|
||||
} // end of command validation
|
||||
} // end of command table lookup loop
|
||||
break; // command found -> exit table lookup loop
|
||||
} // end of command validation
|
||||
} // end of command table lookup loop
|
||||
|
||||
if (i < 0) { // command not found -> exit parser
|
||||
ESP_LOGI(TAG, "Unknown remote command x%02X, ignored", cmd[cursor]);
|
||||
break;
|
||||
}
|
||||
} // command parsing loop
|
||||
|
||||
if (storeflag)
|
||||
saveConfig();
|
||||
} // rcmd_execute()
|
||||
|
||||
rcmd_busy = false;
|
||||
// remote command processing task
|
||||
void rcmd_process(void *pvParameters) {
|
||||
_ASSERT((uint32_t)pvParameters == 1); // FreeRTOS check
|
||||
|
||||
RcmdBuffer_t RcmdBuffer;
|
||||
|
||||
while (1) {
|
||||
// fetch next or wait for incoming rcommand from queue
|
||||
if (xQueueReceive(RcmdQueue, &RcmdBuffer, portMAX_DELAY) != pdTRUE) {
|
||||
ESP_LOGE(TAG, "Premature return from xQueueReceive() with no data!");
|
||||
continue;
|
||||
}
|
||||
rcmd_execute(RcmdBuffer.cmd, RcmdBuffer.cmdLen);
|
||||
}
|
||||
|
||||
delay(2); // yield to CPU
|
||||
} // rcmd_process()
|
||||
|
||||
// enqueue remote command
|
||||
void IRAM_ATTR rcommand(const uint8_t *cmd, const size_t cmdlength) {
|
||||
|
||||
RcmdBuffer_t rcmd = {0};
|
||||
|
||||
rcmd.cmdLen = cmdlength;
|
||||
memcpy(rcmd.cmd, cmd, cmdlength);
|
||||
|
||||
if (xQueueSendToBack(RcmdQueue, (void *)&rcmd, (TickType_t)0) != pdTRUE)
|
||||
ESP_LOGW(TAG, "Remote command queue is full");
|
||||
} // rcommand()
|
||||
|
||||
void rcmd_queuereset(void) { xQueueReset(RcmdQueue); }
|
||||
|
||||
uint32_t rcmd_queuewaiting(void) { return uxQueueMessagesWaiting(RcmdQueue); }
|
||||
|
||||
void rcmd_deinit(void) {
|
||||
rcmd_queuereset();
|
||||
vTaskDelete(rcmdTask);
|
||||
}
|
||||
|
||||
esp_err_t rcmd_init(void) {
|
||||
|
||||
_ASSERT(RCMD_QUEUE_SIZE > 0);
|
||||
RcmdQueue = xQueueCreate(RCMD_QUEUE_SIZE, sizeof(RcmdBuffer_t));
|
||||
if (RcmdQueue == 0) {
|
||||
ESP_LOGE(TAG, "Could not create rcommand send queue. Aborting.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGI(TAG, "Rcommand send queue created, size %d Bytes",
|
||||
RCMD_QUEUE_SIZE * sizeof(RcmdBuffer_t));
|
||||
|
||||
xTaskCreatePinnedToCore(rcmd_process, // task function
|
||||
"rcmdloop", // name of task
|
||||
3072, // stack size of task
|
||||
(void *)1, // parameter of the task
|
||||
1, // priority of the task
|
||||
&rcmdTask, // task handle
|
||||
1); // CPU core
|
||||
|
||||
return ESP_OK;
|
||||
} // rcmd_init()
|
||||
+45
-56
@@ -9,7 +9,7 @@ static const char TAG[] = __FILE__;
|
||||
#define uS_TO_S_FACTOR 1000000ULL
|
||||
|
||||
// variables keep its values after a wakeup from sleep
|
||||
RTC_DATA_ATTR runmode_t RTC_runmode = RUNMODE_POWERCYCLE;
|
||||
RTC_NOINIT_ATTR runmode_t RTC_runmode = RUNMODE_POWERCYCLE;
|
||||
RTC_DATA_ATTR struct timeval RTC_sleep_start_time;
|
||||
RTC_DATA_ATTR unsigned long long RTC_millis = 0;
|
||||
timeval sleep_stop_time;
|
||||
@@ -36,14 +36,19 @@ void do_after_reset(void) {
|
||||
struct timeval sleep_stop_time;
|
||||
uint64_t sleep_time_ms;
|
||||
|
||||
switch (esp_sleep_get_wakeup_cause()) {
|
||||
case ESP_SLEEP_WAKEUP_EXT0: // Wakeup caused by external signal using RTC_IO
|
||||
case ESP_SLEEP_WAKEUP_EXT1: // Wakeup caused by external signal using
|
||||
// RTC_CNTL
|
||||
case ESP_SLEEP_WAKEUP_TIMER: // Wakeup caused by timer
|
||||
case ESP_SLEEP_WAKEUP_TOUCHPAD: // Wakeup caused by touchpad
|
||||
case ESP_SLEEP_WAKEUP_ULP: // Wakeup caused by ULP program
|
||||
switch (rtc_get_reset_reason(0)) {
|
||||
|
||||
case POWERON_RESET: // 0x01 Vbat power on reset
|
||||
case RTCWDT_BROWN_OUT_RESET: // 0x0f Reset when the vdd voltage is not
|
||||
// stable
|
||||
RTC_runmode = RUNMODE_POWERCYCLE;
|
||||
break;
|
||||
|
||||
case SW_CPU_RESET: // 0x0c Software reset CPU
|
||||
// keep previous runmode (could be RUNMODE_UPDATE)
|
||||
break;
|
||||
|
||||
case DEEPSLEEP_RESET: // 0x05 Deep Sleep reset digital core
|
||||
// calculate time spent in deep sleep
|
||||
gettimeofday(&sleep_stop_time, NULL);
|
||||
sleep_time_ms =
|
||||
@@ -51,48 +56,46 @@ void do_after_reset(void) {
|
||||
(sleep_stop_time.tv_usec - RTC_sleep_start_time.tv_usec) / 1000;
|
||||
ESP_LOGI(TAG, "Time spent in deep sleep: %d ms", sleep_time_ms);
|
||||
RTC_millis += sleep_time_ms; // increment system monotonic time
|
||||
|
||||
RTC_runmode = RUNMODE_WAKEUP;
|
||||
// set wakeup state, not if we have pending OTA update
|
||||
if (RTC_runmode == RUNMODE_SLEEP)
|
||||
RTC_runmode = RUNMODE_WAKEUP;
|
||||
break;
|
||||
|
||||
case ESP_SLEEP_WAKEUP_ALL:
|
||||
case ESP_SLEEP_WAKEUP_GPIO:
|
||||
case ESP_SLEEP_WAKEUP_UART:
|
||||
case ESP_SLEEP_WAKEUP_UNDEFINED:
|
||||
case SW_RESET: // 0x03 Software reset digital core
|
||||
case OWDT_RESET: // 0x04 Legacy watch dog reset digital core
|
||||
case SDIO_RESET: // 0x06 Reset by SLC module, reset digital core
|
||||
case TG0WDT_SYS_RESET: // 0x07 Timer Group0 Watch dog reset digital core
|
||||
case TG1WDT_SYS_RESET: // 0x08 Timer Group1 Watch dog reset digital core
|
||||
case RTCWDT_SYS_RESET: // 0x09 RTC Watch dog Reset digital core
|
||||
case INTRUSION_RESET: // 0x0a Instrusion tested to reset CPU
|
||||
case TGWDT_CPU_RESET: // 0x0b Time Group reset CPU
|
||||
case RTCWDT_CPU_RESET: // 0x0d RTC Watch dog Reset CPU
|
||||
case EXT_CPU_RESET: // 0x0e for APP CPU, reseted by PRO CPU
|
||||
case RTCWDT_RTC_RESET: // 0x10 RTC Watch dog reset digital core and rtc mode
|
||||
default:
|
||||
// not a deep sleep reset
|
||||
RTC_runmode = RUNMODE_POWERCYCLE;
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Starting Software v%s, runmode %s", PROGVERSION,
|
||||
runmode[RTC_runmode]);
|
||||
}
|
||||
|
||||
void enter_deepsleep(const uint64_t wakeup_sec = 60,
|
||||
gpio_num_t wakeup_gpio = GPIO_NUM_MAX) {
|
||||
void enter_deepsleep(const uint64_t wakeup_sec, gpio_num_t wakeup_gpio) {
|
||||
|
||||
#if (HAS_LORA)
|
||||
if (!LMIC.devaddr) {
|
||||
ESP_LOGI(TAG, "Can't go to sleep while joining");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Preparing to sleep...");
|
||||
|
||||
RTC_runmode = RUNMODE_SLEEP;
|
||||
int i;
|
||||
|
||||
// validate wake up pin, if we have
|
||||
if (!GPIO_IS_VALID_GPIO(wakeup_gpio))
|
||||
wakeup_gpio = GPIO_NUM_MAX;
|
||||
|
||||
ESP_LOGI(TAG, "Preparing to sleep...");
|
||||
|
||||
RTC_runmode = RUNMODE_SLEEP;
|
||||
|
||||
// stop further enqueuing of senddata and MAC processing
|
||||
sendTimer.detach();
|
||||
|
||||
// switch off radio
|
||||
// switch off radio and other power consuming hardware
|
||||
#if (WIFICOUNTER)
|
||||
switch_wifi_sniffer(0);
|
||||
#endif
|
||||
@@ -100,6 +103,9 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60,
|
||||
stop_BLEscan();
|
||||
btStop();
|
||||
#endif
|
||||
#if (HAS_SDS011)
|
||||
sds011_sleep(void);
|
||||
#endif
|
||||
|
||||
// stop MAC processing
|
||||
vTaskDelete(macProcessTask);
|
||||
@@ -109,27 +115,22 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60,
|
||||
|
||||
// wait a while (max 100 sec) to clear send queues
|
||||
ESP_LOGI(TAG, "Waiting until send queues are empty...");
|
||||
for (i = 10; i > 0; i--) {
|
||||
if (!allQueuesEmtpy())
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
else
|
||||
for (i = 100; i > 0; i--) {
|
||||
if (allQueuesEmtpy())
|
||||
break;
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
if (i == 0)
|
||||
goto Error;
|
||||
|
||||
// shutdown LMIC safely, waiting max 100 sec
|
||||
// shutdown LMIC safely, waiting max 100 sec
|
||||
#if (HAS_LORA)
|
||||
ESP_LOGI(TAG, "Waiting until LMIC is idle...");
|
||||
for (i = 10; i > 0; i--) {
|
||||
for (i = 100; i > 0; i--) {
|
||||
if ((LMIC.opmode & OP_TXRXPEND) ||
|
||||
os_queryTimeCriticalJobs(sec2osticks(wakeup_sec)))
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
goto Error;
|
||||
#endif // (HAS_LORA)
|
||||
|
||||
// shutdown MQTT safely
|
||||
@@ -142,17 +143,7 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60,
|
||||
spi_deinit();
|
||||
#endif
|
||||
|
||||
// wait until rcommands are all done
|
||||
for (i = 10; i > 0; i--) {
|
||||
if (rcmd_busy)
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
goto Error;
|
||||
|
||||
// save LMIC state to RTC RAM
|
||||
// save LMIC state to RTC RAM
|
||||
#if (HAS_LORA)
|
||||
SaveLMICToRTC(wakeup_sec);
|
||||
#endif // (HAS_LORA)
|
||||
@@ -162,9 +153,11 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60,
|
||||
dp_shutdown();
|
||||
#endif
|
||||
|
||||
// reduce power if has PMU
|
||||
// reduce power if has PMU or VEXT
|
||||
#ifdef HAS_PMU
|
||||
AXP192_power(pmu_power_sleep);
|
||||
#elif EXT_POWER_SW
|
||||
digitalWrite(EXT_POWER_SW, EXT_POWER_OFF);
|
||||
#endif
|
||||
|
||||
// shutdown i2c bus
|
||||
@@ -189,10 +182,6 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60,
|
||||
RTC_millis += millis();
|
||||
ESP_LOGI(TAG, "Going to sleep, good bye.");
|
||||
esp_deep_sleep_start();
|
||||
|
||||
Error:
|
||||
ESP_LOGE(TAG, "Can't go to sleep. Resetting.");
|
||||
do_reset(true);
|
||||
}
|
||||
|
||||
unsigned long long uptime() { return (RTC_millis + millis()); }
|
||||
+4
-5
@@ -4,7 +4,7 @@
|
||||
Ticker sendTimer;
|
||||
|
||||
void setSendIRQ() {
|
||||
xTaskNotifyFromISR(irqHandlerTask, SENDCYCLE_IRQ, eSetBits, NULL);
|
||||
xTaskNotify(irqHandlerTask, SENDCYCLE_IRQ, eSetBits);
|
||||
}
|
||||
|
||||
// put data to send in RTos Queues used for transmit over channels Lora and SPI
|
||||
@@ -12,8 +12,7 @@ void SendPayload(uint8_t port) {
|
||||
|
||||
ESP_LOGD(TAG, "sending Payload for Port %d", port);
|
||||
|
||||
MessageBuffer_t
|
||||
SendBuffer; // contains MessageSize, MessagePort, Message[]
|
||||
MessageBuffer_t SendBuffer; // contains MessageSize, MessagePort, Message[]
|
||||
|
||||
SendBuffer.MessageSize = payload.getSize();
|
||||
|
||||
@@ -115,7 +114,6 @@ void sendData() {
|
||||
// clear counter if not in cumulative counter mode
|
||||
if (cfg.countermode != 1) {
|
||||
reset_counters(); // clear macs container and reset all counters
|
||||
get_salt(); // get new salt for salting hashes
|
||||
ESP_LOGI(TAG, "Counter cleared");
|
||||
}
|
||||
#ifdef HAS_DISPLAY
|
||||
@@ -191,6 +189,7 @@ void sendData() {
|
||||
} // sendData()
|
||||
|
||||
void flushQueues(void) {
|
||||
rcmd_queuereset();
|
||||
#if (HAS_LORA)
|
||||
lora_queuereset();
|
||||
#endif
|
||||
@@ -203,7 +202,7 @@ void flushQueues(void) {
|
||||
}
|
||||
|
||||
bool allQueuesEmtpy(void) {
|
||||
uint32_t rc = 0;
|
||||
uint32_t rc = rcmd_queuewaiting();
|
||||
#if (HAS_LORA)
|
||||
rc += lora_queuewaiting();
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ static const char TAG[] = __FILE__;
|
||||
DMA_ATTR uint8_t txbuf[BUFFER_SIZE];
|
||||
DMA_ATTR uint8_t rxbuf[BUFFER_SIZE];
|
||||
|
||||
QueueHandle_t SPISendQueue;
|
||||
static QueueHandle_t SPISendQueue;
|
||||
|
||||
TaskHandle_t spiTask;
|
||||
|
||||
|
||||
+3
-2
@@ -109,8 +109,9 @@ void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec,
|
||||
_seconds(), timeSetSymbols[mytimesource]);
|
||||
} else {
|
||||
timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, setTimeSyncIRQ);
|
||||
ESP_LOGD(TAG, "[%0.3f] Timesync failed, invalid time fetched | source: %c",
|
||||
_seconds(), timeSetSymbols[mytimesource]);
|
||||
time_t unix_sec_at_compilation = compiledUTC();
|
||||
ESP_LOGD(TAG, "[%0.3f] Failed to synchronise time from source %c | unix sec obtained from source: %d | unix sec at program compilation: %d",
|
||||
_seconds(), timeSetSymbols[mytimesource], time_to_set, unix_sec_at_compilation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user