Merge pull request #855 from cyberman54/development

v3.2.0
This commit is contained in:
Verkehrsrot authored and GitHub committed 2022-02-16 21:20:12 +01:00
commit 19ade61e66
52 files changed
+580 -638

No files matched your search

-5
View File
@@ -84,11 +84,6 @@ function Decoder(bytes, port) {
}
}
if (port === 10) {
// ENS count
return decode(bytes, [uint16], ['ens']);
}
}
-5
View File
@@ -90,11 +90,6 @@ function decodeUplink(input) {
data = decode(input.bytes, [uint32, uint8], ['time', 'timestatus']);
}
}
if (input.fPort === 10) {
// ENS count
data = decode(input.bytes, [uint16], ['ens']);
}
data.bytes = input.bytes; // comment out if you do not want to include the original payload
data.port = input.fPort; // comment out if you do not want to inlude the port
-7
View File
@@ -84,13 +84,6 @@ function decodeUplink(input) {
}
}
if (input.fPort === 10) {
var i = 0;
if (input.bytes.length >= 2) {
data.ens = (input.bytes[i++] << 8) | input.bytes[i++];
}
}
if (data.hdop) {
data.hdop /= 100;
data.latitude /= 1000000;
-7
View File
@@ -6,12 +6,6 @@
// Local logging tag
static const char TAG[] = __FILE__;
// default settings for device data to be sent
#define PAYLOADMASK \
((GPS_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | SENSOR2_DATA | \
SENSOR3_DATA) & \
(~BATT_DATA) & (~RESERVED_DATA))
// namespace for device runtime preferences
#define DEVCONFIG "paxcntcfg"
@@ -57,7 +51,6 @@ static void defaultConfig(configData_t *myconfig) {
myconfig->wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4)
myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%)
myconfig->payloadmask = PAYLOADMASK; // payloads as defined in default
myconfig->enscount = COUNT_ENS; // 0=disabled, 1=enabled
#ifdef HAS_BME680
// initial BSEC state for BME680 sensor
-54
View File
@@ -1,54 +0,0 @@
// routines for counting the number of devices which advertise Exposure
// Notification Service e.g. "Corona Warn App" in Germany
// copied from https://github.com/kmetz/BLEExposureNotificationBeeper
// (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
static const char TAG[] = __FILE__;
#define BT_BD_ADDR_HEX(addr) \
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
#include "corona.h"
// When to forget old senders ** currently not used **
#define FORGET_AFTER_MINUTES 2
// array of timestamps for seen notifiers: hash -> timestamp[ms]
static std::map<uint16_t, unsigned long> cwaSeenNotifiers;
// Remove notifiers last seen over FORGET_AFTER_MINUTES ago.
void cwa_clear() {
#ifdef VERBOSE
ESP_LOGV(TAG, "CWA: forget old notifier: %d", cwaSeenNotifiers.size());
for (auto const &notifier : cwaSeenNotifiers) {
ESP_LOGD(TAG, "CWA forget <%04X>", notifier.first);
// }
}
#endif
// clear everything, otherwise we would count the same device again, as in the
// next cycle it likely will advertise with a different hash-value
cwaSeenNotifiers.clear();
}
// return the total number of devices seen advertising ENS
uint16_t cwa_report(void) { return cwaSeenNotifiers.size(); }
bool cwa_init(void) {
ESP_LOGD(TAG, "init BLE-scanner for ENS");
return true;
}
void cwa_mac_add(uint16_t hashedmac) {
cwaSeenNotifiers[hashedmac] = millis(); // hash last seen at ....
}
#endif
+40 -28
View File
@@ -9,10 +9,6 @@ static const char TAG[] = __FILE__;
Ticker cyclicTimer;
#if (HAS_SDS011)
extern boolean isSDS011Active;
#endif
void setCyclicIRQ() { xTaskNotify(irqHandlerTask, CYCLIC_IRQ, eSetBits); }
// do all housekeeping
@@ -22,44 +18,62 @@ void doHousekeeping() {
if ((RTC_runmode == RUNMODE_UPDATE) || (RTC_runmode == RUNMODE_MAINTENANCE))
do_reset(true); // warmstart
// heap and task storage debugging
// try to get time if we don't yet have a recent timesource
if (timeSource == _unsynced || timeSource == _set)
calibrateTime();
// print heap and task storage information
ESP_LOGD(TAG, "Heap: Free:%d, Min:%d, Size:%d, Alloc:%d, StackHWM:%d",
ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getHeapSize(),
ESP.getMaxAllocHeap(), uxTaskGetStackHighWaterMark(NULL));
ESP_LOGD(TAG, "IRQhandler %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(irqHandlerTask),
eTaskGetState(irqHandlerTask));
ESP_LOGD(TAG, "Rcommand interpreter %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(rcmdTask), eTaskGetState(rcmdTask));
if (irqHandlerTask != NULL)
ESP_LOGD(TAG, "IRQhandler %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(irqHandlerTask),
eTaskGetState(irqHandlerTask));
if (rcmdTask != NULL)
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));
ESP_LOGD(TAG, "Lorasendtask %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(lorasendTask),
eTaskGetState(lorasendTask));
if (lmicTask != NULL)
ESP_LOGD(TAG, "LMiCtask %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(lmicTask), eTaskGetState(lmicTask));
if (lorasendTask != NULL)
ESP_LOGD(TAG, "Lorasendtask %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(lorasendTask),
eTaskGetState(lorasendTask));
#endif
#if (HAS_GPS)
ESP_LOGD(TAG, "Gpsloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(GpsTask), eTaskGetState(GpsTask));
if (GpsTask != NULL)
ESP_LOGD(TAG, "Gpsloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(GpsTask), eTaskGetState(GpsTask));
#endif
#ifdef HAS_SPI
ESP_LOGD(TAG, "spiloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(spiTask), eTaskGetState(spiTask));
if (spiTask != NULL)
ESP_LOGD(TAG, "spiloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(spiTask), eTaskGetState(spiTask));
#endif
#ifdef HAS_MQTT
ESP_LOGD(TAG, "MQTTloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(mqttTask), eTaskGetState(mqttTask));
if (mqttTask != NULL)
ESP_LOGD(TAG, "MQTTloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(mqttTask), eTaskGetState(mqttTask));
#endif
#if (defined HAS_DCF77 || defined HAS_IF482)
ESP_LOGD(TAG, "Clockloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(ClockTask), eTaskGetState(ClockTask));
if (ClockTask != NULL)
ESP_LOGD(TAG, "Clockloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(ClockTask), eTaskGetState(ClockTask));
#endif
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
ESP_LOGD(TAG, "LEDloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(ledLoopTask),
eTaskGetState(ledLoopTask));
if (ledLoopTask != NULL)
ESP_LOGD(TAG, "LEDloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(ledLoopTask),
eTaskGetState(ledLoopTask));
#endif
// read battery voltage into global variable
@@ -106,10 +120,8 @@ void doHousekeeping() {
#if (HAS_SDS011)
if (isSDS011Active) {
ESP_LOGD(TAG, "SDS011: go to sleep");
sds011_loop();
} else {
ESP_LOGD(TAG, "SDS011: wakeup");
sds011_wakeup();
}
#endif
+10 -11
View File
@@ -51,18 +51,17 @@ void DCF77_Pulse(uint8_t bit) {
// helper function to convert decimal to bcd digit
uint64_t dec2bcd(uint8_t const dec, uint8_t const startpos,
uint8_t const endpos, uint8_t *odd_parity) {
uint8_t const endpos, uint8_t *parity) {
uint8_t data = (dec < 10) ? dec : ((dec / 10) << 4) + (dec % 10);
uint8_t data = dec < 10 ? dec : ((dec / 10) << 4) + dec % 10;
uint64_t bcd = 0;
*odd_parity = 0;
*parity = 0;
for (uint8_t i = startpos; i <= endpos; i++) {
bcd += (data & 1) ? set_dcfbit(i) : 0;
*odd_parity += (data & 1);
bcd += data & 1 ? set_dcfbit(i) : 0;
*parity ^= data & 1;
data >>= 1;
}
*odd_parity %= 2;
return bcd;
}
@@ -96,14 +95,14 @@ uint64_t DCF77_Frame(const struct tm t) {
// DATE (36..58)
frame += dec2bcd(t.tm_mday, 36, 41, &parity);
parity_sum += parity;
parity_sum ^= parity;
frame += dec2bcd((t.tm_wday == 0) ? 7 : t.tm_wday, 42, 44, &parity);
parity_sum += parity;
parity_sum ^= parity;
frame += dec2bcd(t.tm_mon + 1, 45, 49, &parity);
parity_sum += parity;
parity_sum ^= parity;
frame += dec2bcd(t.tm_year + 1900 - 2000, 50, 57, &parity);
parity_sum += parity;
frame += parity_sum % 2 ? set_dcfbit(58) : 0;
parity_sum ^= parity;
frame += parity_sum ? set_dcfbit(58) : 0;
return frame;
+24 -29
View File
@@ -174,16 +174,10 @@ void dp_init(bool verbose) {
void dp_refresh(bool nextPage) {
// update counter values from libpax
libpax_counter_count(&count_from_libpax);
#ifndef HAS_BUTTON
static uint32_t framecounter = 0;
#endif
// update histogram
dp_plotCurve(count_from_libpax.pax, false);
// if display is switched off we don't refresh it to relax cpu
if (!DisplayIsOn && (DisplayIsOn == cfg.screenon))
return;
@@ -207,7 +201,6 @@ void dp_refresh(bool nextPage) {
#endif
dp_drawPage(nextPage);
dp_dump(displaybuf);
I2C_MUTEX_UNLOCK(); // release i2c bus access
@@ -219,6 +212,7 @@ void dp_drawPage(bool nextpage) {
// write display content to display buffer
// nextpage = true -> flip 1 page
struct count_payload_t count; // libpax count storage
static uint8_t DisplayPage = 0;
char timeState, strftime_buf[64];
time_t now;
@@ -233,6 +227,9 @@ void dp_drawPage(bool nextpage) {
dp_clear();
}
// update counter values from libpax
libpax_counter_count(&count);
// cursor home
dp_setTextCursor(0, 0);
@@ -240,7 +237,7 @@ void dp_drawPage(bool nextpage) {
// display number of unique macs total Wifi + BLE
if (DisplayPage < 5) {
dp_setFont(MY_FONT_STRETCHED);
dp_printf("%-5d", count_from_libpax.pax);
dp_printf("%-5d", count.pax);
}
switch (DisplayPage) {
@@ -264,32 +261,22 @@ void dp_drawPage(bool nextpage) {
#if ((WIFICOUNTER) && (BLECOUNTER))
if (cfg.wifiscan)
dp_printf("WIFI:%-5d", count_from_libpax.wifi_count);
dp_printf("WIFI:%-5d", count.wifi_count);
else
dp_printf("WIFI:off");
if (cfg.blescan)
#if (COUNT_ENS)
if (cfg.enscount)
dp_printf(" CWA:%-5d", cwa_report());
else
#endif
dp_printf("BLTH:%-5d", count_from_libpax.ble_count);
dp_printf("BLTH:%-5d", count.ble_count);
else
dp_printf(" BLTH:off");
#elif ((WIFICOUNTER) && (!BLECOUNTER))
if (cfg.wifiscan)
dp_printf("WIFI:%-5d", count_from_libpax.wifi_count);
dp_printf("WIFI:%-5d", count.wifi_count);
else
dp_printf("WIFI:off");
#elif ((!WIFICOUNTER) && (BLECOUNTER))
if (cfg.blescan)
dp_printf("BLTH:%-5d", count_from_libpax.ble_count);
#if (COUNT_ENS)
if (cfg.enscount)
dp_printf("(CWA:%d)", cwa_report());
else
#endif
dp_printf("BLTH:off");
dp_printf("BLTH:%-5d", count.ble_count);
dp_printf("BLTH:off");
#else
dp_printf("Sniffer disabled");
#endif
@@ -327,7 +314,6 @@ void dp_drawPage(bool nextpage) {
#if (TIME_SYNC_INTERVAL)
timeState = TimePulseTick ? ' ' : timeSetSymbols[timeSource];
TimePulseTick = false;
time(&now);
localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
@@ -355,6 +341,8 @@ void dp_drawPage(bool nextpage) {
dp_printf("%-4s", getSfName(updr2rps(LMIC.datarate)));
dp_setFont(MY_FONT_SMALL, 0);
#endif // HAS_LORA
dp_dump(displaybuf);
break;
// ---------- page 1: lorawan parameters ----------
@@ -380,6 +368,8 @@ void dp_drawPage(bool nextpage) {
LMIC.seqnoDn ? LMIC.seqnoDn - 1 : 0);
dp_println();
dp_printf("SNR:%-5d RSSI:%-5d", (LMIC.snr + 2) / 4, LMIC.rssi);
dp_dump(displaybuf);
break;
#else // flip page if we are unattended
DisplayPage++;
@@ -412,6 +402,8 @@ void dp_drawPage(bool nextpage) {
dp_printf("No fix");
wasnofix = true;
}
dp_dump(displaybuf);
break;
#else // flip page if we are unattended
DisplayPage++;
@@ -435,10 +427,12 @@ void dp_drawPage(bool nextpage) {
#ifdef HAS_BME680
// line 6-7: IAQ
dp_printf("IAQ:%-3.0f", bme_status.iaq);
#else // is BME280 or BMP180
#else // is BME280 or BMP180
// line 6-7: Pre
dp_printf("PRE:%-2.1f", bme_status.pressure);
#endif // HAS_BME680
#endif // HAS_BME680
dp_dump(displaybuf);
break; // page 3
#else // flip page if we are unattended
DisplayPage++;
@@ -453,14 +447,15 @@ void dp_drawPage(bool nextpage) {
localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%T", &timeinfo);
dp_printf("%.8s", strftime_buf);
dp_dump(displaybuf);
break;
// ---------- page 5: pax graph ----------
case 5:
dp_setFont(MY_FONT_NORMAL);
dp_setTextCursor(0, 0);
dp_printf("Pax graph");
// update histogram
dp_plotCurve(count.pax, false);
dp_dump(plotbuf);
break;
+161 -108
View File
@@ -6,68 +6,147 @@
// Local logging tag
static const char TAG[] = __FILE__;
// we use NMEA ZDA sentence field 1 for time synchronization
// ZDA gives time for preceding pps pulse
// downsight is that it does not have a constant offset
// thus precision is only +/- 1 second
TinyGPSPlus gps;
TinyGPSCustom gpstime(gps, "GPZDA", 1); // field 1 = UTC time (hhmmss.ss)
TinyGPSCustom gpsday(gps, "GPZDA", 2); // field 2 = day (01..31)
TinyGPSCustom gpsmonth(gps, "GPZDA", 3); // field 3 = month (01..12)
TinyGPSCustom gpsyear(gps, "GPZDA", 4); // field 4 = year (4-digit)
static const String ZDA_Request = "$EIGPQ,ZDA*39\r\n";
TaskHandle_t GpsTask;
#ifdef GPS_SERIAL
HardwareSerial GPS_Serial(1); // use UART #1
static uint16_t nmea_txDelay_ms =
(tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL) / portTICK_PERIOD_MS);
#else
static uint16_t nmea_txDelay_ms = 0;
#endif
// Ublox UBX packet data
// UBX CFG-PRT packet
byte CFG_PRT[] = {
0xB5, // sync char 1
0x62, // sync char 2
0x06, // class
0x00, // id
0x14, // length
0x00, // .
0x01, // portID (UART 1)
0x00, // reserved
0x00, // txReady
0x00, // .
0b11010000, // UART mode: 8N1
0b00001000, // .
0x00, // .
0x00, // .
(byte)GPS_BAUDRATE, // baudrate
(byte)(GPS_BAUDRATE >> 8), // .
(byte)(GPS_BAUDRATE >> 16), // .
(byte)(GPS_BAUDRATE >> 24), // .
0b00000011, // input protocols: NMEA + UBX
0b00000000, // .
0b00000010, // output protocols: NMEA
0x00000000, // .
0x00, // reserved
0x00, // .
0x00, // .
0x00 // .
};
// Array of two bytes for CFG-MSG packets payload.
byte CFG_MSG_CID[][2] = {{0xF0, 0x01}, {0xF0, 0x02}, {0xF0, 0x03}, {0xF0, 0x05},
{0xF0, 0x06}, {0xF0, 0x07}, {0xF0, 0x08}, {0xF0, 0x09},
{0xF0, 0x0A}, {0xF0, 0x0E}, {0xF1, 0x00}, {0xF1, 0x03},
{0xF1, 0x04}, {0xF1, 0x05}, {0xF1, 0x06}};
// UBX CFG-MSG packet
byte CFG_MSG[] = {
0xB5, // sync char 1
0x62, // sync char 2
0x06, // class
0x01, // id
0x03, // length
0x00, // .
0x00, // payload (first byte from messages array element)
0x00, // payload (second byte from messages array element)
0x00 // payload (zero to disable message)
};
// UBX CFG-CFG packet
byte CFG_CFG[] = {
0xB5, // sync char 1
0x62, // sync char 2
0x06, // class
0x09, // id
0x0D, // length
0x00, // .
0b00011111, // clearmask
0b00000110, // .
0x00, // .
0x00, // .
0x00, // savemask
0x00, // .
0x00, // .
0x00, // .
0b00011111, // loadmask
0b00000110, // .
0x00, // .
0x00, // .
0b00010001 // devicemask
};
// helper functions to send UBX commands to ublox gps chip
void sendPacket(byte *packet, byte len) {
uint8_t CK_A = 0;
uint8_t CK_B = 0;
for (int i = 0; i < len; i++)
GPS_Serial.write(packet[i]);
// calculate and send Fletcher checksum
for (int i = 2; i < len; i++) {
CK_A += packet[i];
CK_B += CK_A;
}
GPS_Serial.write(CK_A);
GPS_Serial.write(CK_B);
}
void restoreDefaults() { sendPacket(CFG_CFG, sizeof(CFG_CFG)); }
void changeBaudrate() { sendPacket(CFG_PRT, sizeof(CFG_PRT)); }
void disableNmea() {
// tinygps++ processes only $GPGGA/$GNGGA and $GPRMC/$GNRMC
// thus, we disable all other NMEA messages
byte packetSize = sizeof(CFG_MSG);
// Offset to the place where payload starts.
byte payloadOffset = 6;
// Iterate over the messages array.
for (byte i = 0; i < sizeof(CFG_MSG_CID) / sizeof(*CFG_MSG_CID); i++) {
// Copy two bytes of payload to the packet buffer.
for (byte j = 0; j < sizeof(*CFG_MSG_CID); j++) {
CFG_MSG[payloadOffset + j] = CFG_MSG_CID[i][j];
}
sendPacket(CFG_MSG, packetSize);
}
}
// initialize and configure GPS
int gps_init(void) {
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);
#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
if (Wire.endTransmission()) {
ESP_LOGE(TAG, "Quectel L76 GPS chip not found");
return 0;
} else
ESP_LOGI(TAG, "Quectel L76 GPS chip found");
#endif
restoreDefaults();
delay(100);
changeBaudrate();
delay(100);
GPS_Serial.flush();
GPS_Serial.updateBaudRate(GPS_BAUDRATE);
disableNmea();
return 1;
} // gps_init()
// detect gps chipset type and configure it with device specific settings
int gps_config() {
int rslt = 1; // success
#if defined GPS_SERIAL
/* insert user configuration here, if needed */
#elif defined GPS_I2C
/* insert user configuration here, if needed */
#endif
return rslt;
}
// store current GPS location data in struct
void gps_storelocation(gpsStatus_t *gps_store) {
if (gps.location.isUpdated() && gps.location.isValid() &&
@@ -90,46 +169,45 @@ bool gps_hasfix() {
}
// function to poll UTC time from GPS NMEA data; note: this is costly
time_t get_gpstime(uint16_t *msec) {
time_t get_gpstime(uint16_t *msec = 0) {
// poll NMEA ZDA sentence
#ifdef GPS_SERIAL
GPS_Serial.print(ZDA_Request);
// wait for gps NMEA answer
// vTaskDelay(tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL));
#elif defined GPS_I2C
Wire.print(ZDA_Request);
#endif
const uint16_t txDelay =
70U * 1000 / (GPS_BAUDRATE / 9); // serial tx of 70 NMEA chars
// did we get a current date & time?
if (gpstime.isValid()) {
if (gps.time.age() < 1000) {
uint32_t delay_ms =
gpstime.age() + nmea_txDelay_ms + NMEA_COMPENSATION_FACTOR;
uint32_t zdatime = atof(gpstime.value());
// convert UTC time from gps NMEA ZDA sentence to tm format
// convert tinygps time format to struct tm format
struct tm gps_tm = {0};
gps_tm.tm_sec = zdatime % 100; // second (UTC)
gps_tm.tm_min = (zdatime / 100) % 100; // minute (UTC)
gps_tm.tm_hour = zdatime / 10000; // hour (UTC)
gps_tm.tm_mday = atoi(gpsday.value()); // day, 01 to 31
gps_tm.tm_mon = atoi(gpsmonth.value()) - 1; // month, 01 to 12
gps_tm.tm_year = atoi(gpsyear.value()) - 1900; // year, YYYY
gps_tm.tm_sec = gps.time.second();
gps_tm.tm_min = gps.time.minute();
gps_tm.tm_hour = gps.time.hour();
gps_tm.tm_mday = gps.date.day();
gps_tm.tm_mon = gps.date.month() - 1; // 1-12 -> 0-11
gps_tm.tm_year = gps.date.year() - 1900; // 2000+ -> years since 1900
// convert UTC tm to time_t epoch
gps_tm.tm_isdst = 0; // UTC has no DST
gps_tm.tm_isdst = 0; // UTC has no DST
time_t t = mkgmtime(&gps_tm);
// add protocol delay with millisecond precision
t += (time_t)(delay_ms / 1000);
*msec = delay_ms % 1000; // fractional seconds
#ifdef GPS_INT
// if we have a recent GPS PPS pulse, sync on top of next second
uint16_t ppsDiff = millis() - lastPPS;
if (ppsDiff < 1000)
*msec = ppsDiff;
else {
ESP_LOGD(TAG, "no PPS from GPS");
return 0;
}
#else
// best guess for sync on top of next second
*msec = gps.time.centisecond() * 10U + txDelay;
#endif
return t;
}
ESP_LOGD(TAG, "no valid GPS time");
return 0;
} // get_gpstime()
@@ -139,42 +217,17 @@ void gps_loop(void *pvParameters) {
_ASSERT((uint32_t)pvParameters == 1); // FreeRTOS check
// feed GPS decoder with serial NMEA data from GPS device
while (1) {
while (cfg.payloadmask & GPS_DATA) {
if (cfg.payloadmask & GPS_DATA) {
#ifdef GPS_SERIAL
// feed GPS decoder with serial NMEA data from GPS device
while (GPS_Serial.available()) {
while (GPS_Serial.available())
gps.encode(GPS_Serial.read());
yield();
}
#elif defined GPS_I2C
Wire.requestFrom(GPS_ADDR, 32); // caution: this is a blocking call
while (Wire.available()) {
gps.encode(Wire.read());
delay(2); // 2ms delay according L76 datasheet
yield();
}
#endif
// (only) while device time is not set or unsynched, and we have a valid
// GPS time, we trigger a device time update to poll time from GPS
if ((timeSource == _unsynced || timeSource == _set) &&
(gpstime.isUpdated() && gpstime.isValid() && gpstime.age() < 1000)) {
calibrateTime();
}
} // if
// show NMEA data in verbose mode, useful only for debugging GPS, very
// noisy ESP_LOGV(TAG, "GPS NMEA data: passed %u / failed: %u / with fix:
// %u",
// gps.passedChecksum(), gps.failedChecksum(),
// gps.sentencesWithFix());
yield(); // yield to CPU
} // end of infinite loop
delay(5);
}
delay(1000);
} // infinite while loop
} // gps_loop()
+1 -1
View File
@@ -18,7 +18,7 @@
#define CFG_sx1276_radio 1
#define HAS_DISPLAY 1 // OLED-Display on board
#define HAS_LED LED_BUILTIN // white LED on board
#define HAS_LED LED_BUILTIN // white LED on board (set to NOT_A_PIN to disable)
#define HAS_BUTTON KEY_BUILTIN // button "PROG" on board
// Pins for I2C interface of OLED Display
+1 -1
View File
@@ -20,7 +20,7 @@
#define CFG_sx1276_radio 1
#define HAS_DISPLAY 1 // OLED-Display on board
#define HAS_LED LED_BUILTIN // white LED on board
#define HAS_LED LED_BUILTIN // white LED on board (set to NOT_A_PIN to disable)
#define HAS_BUTTON KEY_BUILTIN // button "PROG" on board
#define BAT_MEASURE_ADC ADC2_GPIO13_CHANNEL // battery probe GPIO pin
+1 -1
View File
@@ -20,7 +20,7 @@
#define CFG_sx1276_radio 1
#define HAS_DISPLAY 1 // OLED-Display on board
#define HAS_LED LED_BUILTIN // white LED on board
#define HAS_LED LED_BUILTIN // white LED on board (set to NOT_A_PIN to disable)
#define HAS_BUTTON KEY_BUILTIN // button "PROG" on board
#define BAT_MEASURE_ADC ADC1_GPIO37_CHANNEL // battery probe GPIO pin
+1 -1
View File
@@ -10,7 +10,7 @@
// Hardware related definitions for lolin32lite (without LoRa shield)
#define HAS_LED LED_BUILTIN // on board LED on GPIO5
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW (set to NOT_A_PIN to disable)
#define MY_SDA SDA
#define MY_SCL SCL
+1 -1
View File
@@ -15,7 +15,7 @@
#define HAS_DISPLAY 1 // OLED-Display on board
//#define MY_DISPLAY_FLIP 1 // uncomment this for rotated display
#define HAS_LED 22 // ESP32 GPIO12 (pin22) On Board LED
#define HAS_LED 22 // ESP32 GPIO12 (pin22) On Board LED (set to NOT_A_PIN to disable)
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
#define HAS_RGB_LED SmartLed rgb_led(LED_WS2812, 1, GPIO_NUM_13) // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED
#define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield
-5
View File
@@ -20,11 +20,6 @@
#define HAS_ANTENNA_SWITCH (16) // pin for switching wifi antenna
#define WIFI_ANTENNA 0 // 0 = internal, 1 = external
// uncomment this only if your LoPy runs on a PYTRACK BOARD
#define HAS_GPS 1
#define GPS_I2C GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21)
#define GPS_ADDR 0x10
// uncomment this only if your LoPy runs on a EXPANSION BOARD
//#define HAS_LED (12) // use if LoPy is on Expansion Board, this has a user LED
//#define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED
-5
View File
@@ -30,11 +30,6 @@
#define HAS_ANTENNA_SWITCH (21) // pin for switching wifi antenna (P12)
#define WIFI_ANTENNA 0 // 0 = internal, 1 = external
// uncomment defines in this section ONLY if your LoPy lives on a PYTRACK BOARD
//#define HAS_GPS 1
//#define GPS_I2C GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21)
//#define GPS_ADDR 0x10
// uncomment defines in this section ONLY if your LoPy lives on a EXPANSION BOARD
//#define HAS_LED (12) // use if LoPy is on Expansion Board, this has a user LED
//#define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED
+1 -1
View File
@@ -14,7 +14,7 @@
#define HAS_DISPLAY 1 // OLED-Display on board
//#define MY_DISPLAY_FLIP 1 // uncomment this for rotated display
#define HAS_LED LED_BUILTIN
#define HAS_LED LED_BUILTIN // set to NOT_A_PIN to disable
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
#define HAS_BUTTON KEY_BUILTIN
+3 -1
View File
@@ -16,10 +16,12 @@
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
// enable only if you want to store a local paxcount table on the device
#define HAS_SDCARD 2 // // this board has a SDMMC card-reader/writer
#define HAS_SDCARD 2 // this board has a SDMMC card-reader/writer
#define HAS_DISPLAY 1
#define HAS_LED (25) // green on board LED
//#define HAS_LED NOT_A_PIN
#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 100k/100k on board
+7 -6
View File
@@ -86,18 +86,19 @@ static const char TAG[] = __FILE__;
String IF482_Frame(time_t t) {
char mon, out[IF482_FRAME_SIZE + 1];
char mon, out[IF482_FRAME_SIZE + 1], buf[IF482_FRAME_SIZE - 3];
if (sntp_get_sync_status() == SNTP_SYNC_STATUS_IN_PROGRESS)
mon = 'M'; // time had been set but sync not completed
else
mon = 'A'; // time has been set and was recently synced
// generate IF482 telegram
// snprintf(out, sizeof(out), "O%cL%s\r", mon, myTZ.dateTime(t, UTC_TIME,
// "ymdwHis").c_str());
// ESP_LOGD(TAG, "[%s] IF482 date/time: %s", ctime(time(NULL), out);
// generate IF482 telegram for local time
struct tm tt;
localtime_r(&t, &tt);
mktime(&tt);
strftime(buf, sizeof(buf), "%y%m%d%u%H%M%S", &tt);
snprintf(out, sizeof(out), "O%cL%s\r", mon, buf);
return out;
}
+1 -1
View File
@@ -212,7 +212,7 @@ void ledLoop(void *parameter) {
previousLEDState = LEDState;
}
// give yield to CPU
delay(2);
delay(5);
} // while(1)
}; // ledloop()
+8 -7
View File
@@ -13,6 +13,7 @@ uint8_t MatrixDisplayIsOn = 0;
static uint8_t displaybuf[LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / 8] = {0};
static unsigned long ulLastNumMacs = 0;
static time_t ulLastTime = time(NULL);
static struct count_payload_t count; // libpax count storage
hw_timer_t *matrixDisplayIRQ = NULL;
@@ -76,12 +77,12 @@ void refreshTheMatrixDisplay(bool nextPage) {
case 0:
// update counter values from libpax
libpax_counter_count(&count_from_libpax);
libpax_counter_count(&count);
if (cfg.countermode == 1) {
// cumulative counter mode -> display total number of pax
if (ulLastNumMacs != count_from_libpax.pax) {
ulLastNumMacs = count_from_libpax.pax;
if (ulLastNumMacs != count.pax) {
ulLastNumMacs = count.pax;
matrix.clear();
DrawNumber(String(ulLastNumMacs));
}
@@ -89,10 +90,10 @@ void refreshTheMatrixDisplay(bool nextPage) {
else { // cyclic counter mode -> plot a line diagram
if (ulLastNumMacs != count_from_libpax.pax) {
if (ulLastNumMacs != count.pax) {
// next count cycle?
if (count_from_libpax.pax == 0) {
if (count.pax == 0) {
// matrix full? then scroll left 1 dot, else increment column
if (col < (LED_MATRIX_WIDTH - 1))
@@ -104,7 +105,7 @@ void refreshTheMatrixDisplay(bool nextPage) {
matrix.drawPoint(col, row, 0); // clear current dot
// scale and set new dot
ulLastNumMacs = count_from_libpax.pax;
ulLastNumMacs = count.pax;
level = ulLastNumMacs / LINE_DIAGRAM_DIVIDER;
row = level <= LED_MATRIX_HEIGHT
? LED_MATRIX_HEIGHT - 1 - level % LED_MATRIX_HEIGHT
@@ -120,7 +121,7 @@ void refreshTheMatrixDisplay(bool nextPage) {
if (ulLastTime != t) {
ulLastTime = t;
matrix.clear();
//DrawNumber(myTZ.dateTime("H:i:s").c_str());
// DrawNumber(myTZ.dateTime("H:i:s").c_str());
}
break;
+1 -10
View File
@@ -5,18 +5,9 @@ static const char TAG[] = __FILE__;
// libpax payload
struct count_payload_t count_from_libpax;
uint16_t volatile libpax_macs_ble, libpax_macs_wifi;
void process_count(void) {
ESP_LOGD(TAG, "pax: %d / %d / %d", count_from_libpax.pax,
count_from_libpax.wifi_count, count_from_libpax.ble_count);
libpax_macs_ble = count_from_libpax.ble_count;
libpax_macs_wifi = count_from_libpax.wifi_count;
setSendIRQ();
}
void init_libpax(void) {
libpax_counter_init(process_count, &count_from_libpax, cfg.sendcycle * 2,
libpax_counter_init(setSendIRQ, &count_from_libpax, cfg.sendcycle * 2,
cfg.countermode);
libpax_counter_start();
}
@@ -90,12 +90,7 @@ function decodeUplink(input) {
data = decode(input.bytes, [uint32, uint8], ['time', 'timestatus']);
}
}
if (input.fPort === 10) {
// ENS count
data = decode(input.bytes, [uint16], ['ens']);
}
data.bytes = input.bytes; // comment out if you do not want to include the original payload
data.port = input.fPort; // comment out if you do not want to inlude the port
+3 -3
View File
@@ -179,10 +179,10 @@ void showLoraKeys(void) {
// all EUI buffer so we do it here to a temp
// buffer to be able to display them
uint8_t buf[32];
os_getDevEui((u1_t *)buf);
printKey("DevEUI", buf, 8, true);
os_getArtEui((u1_t *)buf);
printKey("AppEUI", buf, 8, true);
os_getDevEui((u1_t *)buf);
printKey("DevEUI", buf, 8, true);
os_getDevKey((u1_t *)buf);
printKey("AppKey", buf, 16, false);
}
@@ -314,7 +314,7 @@ esp_err_t lmic_init(void) {
"lorasendtask", // name of task
3072, // stack size of task
(void *)1, // parameter of the task
1, // priority of the task
2, // priority of the task
&lorasendTask, // task handle
1); // CPU core
+39 -55
View File
@@ -25,62 +25,54 @@ licenses. Refer to LICENSE.txt file in repository for more details.
// Tasks and timers:
Task Core Prio Purpose
Task Core Prio Purpose
-------------------------------------------------------------------------------
ledloop 0 3 blinks LEDs
spiloop 0 2 reads/writes data on spi interface
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
ledloop* 1 1 blinks LEDs
spiloop# 0 2 reads/writes data on spi interface
lmictask* 1 2 MCCI LMiC LORAWAN stack
clockloop# 1 6 generates realtime telegrams for external clock
mqttloop# 1 5 reads/writes data on ETH interface
timesync_proc# 1 7 processes realtime time sync requests
irqhandler# 1 4 application IRQ (i.e. displayrefresh)
gpsloop* 1 1 reads data from GPS via serial or i2c
lorasendtask# 1 2 feeds data from lora sendqueue to lmcic
rmcd_process# 1 1 Remote command interpreter loop
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
rmcd_process 1 1 Remote command interpreter loop
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
* spinning task, always ready
# blocked/waiting task
Low priority numbers denote low priority tasks.
NOTE: Changing any timings will have impact on time accuracy of whole code.
So don't do it if you do not own a digital oscilloscope.
-------------------------------------------------------------------------------
// ESP32 hardware timers
-------------------------------------------------------------------------------
0 displayIRQ -> display refresh -> 40ms (DISPLAYREFRESH_MS)
1 ppsIRQ -> pps clock irq -> 1sec
2 (unused)
3 MatrixDisplayIRQ -> matrix mux cycle -> 0,5ms (MATRIX_DISPLAY_SCAN_US)
// Interrupt routines
-------------------------------------------------------------------------------
irqHandlerTask (Core 1), see irqhandler.cpp
fired by hardware
DisplayIRQ -> esp32 timer 0
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
TIMESYNC_IRQ -> setTimeSyncIRQ() -> Ticker.h
CYCLIC_IRQ -> setCyclicIRQ() -> Ticker.h
SENDCYCLE_IRQ -> setSendIRQ() -> xTimer
BME_IRQ -> setBMEIRQ() -> Ticker.h
ClockTask (Core 1), see timekeeper.cpp
fired by hardware
CLOCKIRQ -> esp32 timer 1
// External RTC timer (if present)
-------------------------------------------------------------------------------
triggers pps 1 sec impulse
// Interrupt routines
-------------------------------------------------------------------------------
ISRs fired by CPU or GPIO:
DisplayIRQ <- esp32 timer 0
CLOCKIRQ <- esp32 timer 1 or GPIO (RTC_INT)
MatrixDisplayIRQ<- esp32 timer 3
ButtonIRQ <- GPIO <- Button
PMUIRQ <- GPIO <- PMU chip
Application IRQs fired by software:
TIMESYNC_IRQ <- setTimeSyncIRQ() <- Ticker.h
CYCLIC_IRQ <- setCyclicIRQ() <- Ticker.h
SENDCYCLE_IRQ <- setSendIRQ() <- xTimer or libpax callback
BME_IRQ <- setBMEIRQ() <- Ticker.h
*/
// Basic Config
@@ -126,7 +118,7 @@ void setup() {
snprintf(clientId, 20, "paxcounter_%08x", hashedmac);
ESP_LOGI(TAG, "Starting %s v%s (runmode=%d / restarts=%d)", clientId,
PROGVERSION, RTC_runmode, RTC_restarts);
ESP_LOGI(TAG, "code build date: %d", _COMPILETIME);
ESP_LOGI(TAG, "code build date: %d", compileTime());
// print chip information on startup if in verbose mode after coldstart
#if (VERBOSE)
@@ -244,9 +236,9 @@ void setup() {
"ledloop", // name of task
1024, // stack size of task
(void *)1, // parameter of the task
3, // priority of the task
1, // priority of the task
&ledLoopTask, // task handle
0); // CPU core
1); // CPU core
#endif
// initialize wifi antenna
@@ -328,7 +320,7 @@ void setup() {
ESP_LOGI(TAG, "Starting GPS Feed...");
xTaskCreatePinnedToCore(gps_loop, // task function
"gpsloop", // name of task
4096, // stack size of task
8192, // stack size of task
(void *)1, // parameter of the task
1, // priority of the task
&GpsTask, // task handle
@@ -339,15 +331,9 @@ void setup() {
// initialize sensors
#if (HAS_SENSORS)
#if (HAS_SENSOR_1)
#if (COUNT_ENS)
ESP_LOGI(TAG, "init CWA-counter");
if (cwa_init())
strcat_P(features, " CWA");
#else
strcat_P(features, " SENS(1)");
sensor_init();
#endif
#endif
#if (HAS_SENSOR_2)
strcat_P(features, " SENS(2)");
sensor_init();
@@ -432,7 +418,7 @@ void setup() {
"irqhandler", // name of task
4096, // stack size of task
(void *)1, // parameter of the task
2, // priority of the task
4, // priority of the task
&irqHandlerTask, // task handle
1); // CPU core
@@ -494,8 +480,7 @@ void setup() {
cyclicTimer.attach(HOMECYCLE, setCyclicIRQ);
// only if we have a timesource we do timesync
#if ((TIME_SYNC_LORAWAN) || (TIME_SYNC_LORASERVER) || (HAS_GPS) || \
defined HAS_RTC)
#if ((TIME_SYNC_LORAWAN) || (TIME_SYNC_LORASERVER) || (HAS_GPS) || (HAS_RTC))
#if (defined HAS_IF482 || defined HAS_DCF77)
ESP_LOGI(TAG, "Starting Clock Controller...");
@@ -507,8 +492,7 @@ void setup() {
#endif
ESP_LOGI(TAG, "Starting Timekeeper...");
_ASSERT(timepulse_init()); // setup pps timepulse
timepulse_start(); // starts pps and cyclic time sync
_ASSERT(timepulse_init()); // starts pps and cyclic time sync
strcat_P(features, " TIME");
#endif // timesync
+1 -1
View File
@@ -37,7 +37,7 @@ esp_err_t mqtt_init(void) {
SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
ESP_LOGI(TAG, "Starting MQTTloop...");
xTaskCreatePinnedToCore(mqtt_client_task, "mqttloop", 4096, (void *)NULL, 1,
xTaskCreatePinnedToCore(mqtt_client_task, "mqttloop", 4096, (void *)NULL, 5,
&mqttTask, 1);
return ESP_OK;
}
+5 -4
View File
@@ -18,6 +18,11 @@
#define PAYLOAD_ENCODER 2 // payload encoder: 1=Plain, 2=Packed, 3=Cayenne LPP dynamic, 4=Cayenne LPP packed
#define COUNTERMODE 0 // 0=cyclic, 1=cumulative, 2=cyclic confirmed
// default settings for transmission of sensor data (first list = data on / second line = data off)
#define PAYLOADMASK \
((GPS_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | SENSOR2_DATA | SENSOR3_DATA) & \
(~BATT_DATA) & (~RESERVED_DATA))
// MAC sniffing parameters
#define BLECOUNTER 1 // set to 0 if you do not want to install the BLE sniffer
#define WIFICOUNTER 1 // set to 0 if you do not want to install the WIFI sniffer
@@ -27,10 +32,6 @@
#define BLESCANWINDOW 80 // [milliseconds] scan window, see below, 3 .. 10240, default 80ms
#define BLESCANINTERVAL 80 // [illiseconds] scan interval, see below, 3 .. 10240, default 80ms = 100% duty cycle
// Corona Exposure Notification Service(ENS) counter
#define COUNT_ENS 0 // count found number of devices which advertise Exposure Notification Service
// set to 1 if you want to enable this function [default=0]
/* Note: guide for setting bluetooth parameters
*
* |< Scan Window > |< Scan Window > | ... |< Scan Window > |
+2 -12
View File
@@ -1,7 +1,6 @@
// Basic Config
#include "globals.h"
#include "rcommand.h"
#include "libpax_helpers.h"
// Local logging tag
static const char TAG[] = __FILE__;
@@ -397,15 +396,6 @@ void set_flush(uint8_t val[]) {
// used to open receive window on LoRaWAN class a nodes
};
void set_enscount(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set ENS_COUNT to %s", val[0] ? "on" : "off");
cfg.enscount = val[0] ? 1 : 0;
if (val[0])
cfg.payloadmask |= (uint8_t)SENSOR1_DATA;
else
cfg.payloadmask &= (uint8_t)~SENSOR1_DATA;
}
void set_loadconfig(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: load config from NVRAM");
loadConfig();
@@ -430,7 +420,7 @@ static const cmd_t table[] = {
{0x10, set_rgblum, 1}, {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, 2},
{0x18, set_flush, 0}, {0x19, set_sleepcycle, 2},
{0x20, set_loadconfig, 0}, {0x21, set_saveconfig, 0},
{0x80, get_config, 0}, {0x81, get_status, 0},
{0x83, get_batt, 0}, {0x84, get_gps, 0},
@@ -493,7 +483,7 @@ void rcmd_process(void *pvParameters) {
rcmd_execute(RcmdBuffer.cmd, RcmdBuffer.cmdLen);
}
delay(2); // yield to CPU
delay(5); // yield to CPU
} // rcmd_process()
// enqueue remote command
+5
View File
@@ -126,6 +126,11 @@ void enter_deepsleep(const uint64_t wakeup_sec, gpio_num_t wakeup_gpio) {
sds011_sleep();
#endif
// flush & close sd card, if we have
#if (HAS_SDCARD)
sdcard_close();
#endif
// wait a while (max 100 sec) to clear send queues
ESP_LOGI(TAG, "Waiting until send queues are empty...");
for (i = 100; i > 0; i--) {
+14 -6
View File
@@ -25,14 +25,14 @@ uint8_t rtc_init(void) {
}
#if (TIME_SYNC_COMPILEDATE)
// initialize a blank RTC without battery backup with compiled time
// initialize a blank RTC without battery backup with build time
RtcDateTime tt = Rtc.GetDateTime();
time_t t = tt.Epoch32Time(); // sec2000 -> epoch
if (!Rtc.IsDateTimeValid() || !timeIsValid(t)) {
ESP_LOGW(TAG, "RTC has no recent time, setting to compiled time");
Rtc.SetDateTime(
RtcDateTime(_COMPILETIME - SECS_YR_2000)); // epoch -> sec2000
ESP_LOGW(TAG, "RTC has no recent time, setting to compiletime");
Rtc.SetDateTime(RtcDateTime(mkgmtime(compileTime()) -
SECS_YR_2000)); // epoch -> sec2000
}
#endif
@@ -62,15 +62,23 @@ uint8_t set_rtctime(time_t t) { // t is sec epoch time
}
} // set_rtctime()
time_t get_rtctime(void) {
time_t get_rtctime(uint16_t *msec) {
time_t t = 0;
*msec = 0;
if (I2C_MUTEX_LOCK()) {
if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) {
RtcDateTime tt = Rtc.GetDateTime();
t = tt.Epoch32Time(); // sec2000 -> epoch
}
I2C_MUTEX_UNLOCK();
return timeIsValid(t);
#ifdef RTC_INT
// adjust time to top of next second by waiting TimePulseTick to flip
bool lastTick = TimePulseTick;
while (TimePulseTick == lastTick) {
};
t++;
#endif
return t;
} else {
ESP_LOGE(TAG, "RTC get time failure");
return 0; // failure
+72 -42
View File
@@ -1,4 +1,7 @@
// routines for writing data to an SD-card, if present
// use FAT32 formatted card
// check whether your card reader supports SPI oder SDMMC and select appropriate
// SD low level driver in board hal file
// Local logging tag
static const char TAG[] = __FILE__;
@@ -8,20 +11,26 @@ static const char TAG[] = __FILE__;
#ifdef HAS_SDCARD
static bool useSDCard;
static void createFile(void);
static void openFile(void);
File fileSDCard;
bool sdcard_init() {
ESP_LOGI(TAG, "looking for SD-card...");
#if HAS_SDCARD == 1
SPIClass sd_spi;
#endif
bool sdcard_init(bool create) {
// for usage of SD drivers on ESP32 platform see
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sdspi_host.html
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sdmmc_host.html
ESP_LOGI(TAG, "looking for SD-card...");
#if HAS_SDCARD == 1 // use SD SPI host driver
useSDCard = SD.begin(SDCARD_CS, SDCARD_MOSI, SDCARD_MISO, SDCARD_SCLK);
digitalWrite(SDCARD_CS, HIGH);
sd_spi.begin(SDCARD_SCLK, SDCARD_MISO, SDCARD_MOSI, SDCARD_CS);
digitalWrite(SDCARD_CS, LOW);
useSDCard = SD.begin(SDCARD_CS, sd_spi);
#elif HAS_SDCARD == 2 // use SD MMC host driver
// enable internal pullups of sd-data lines
gpio_set_pull_mode(gpio_num_t(SDCARD_DATA0), GPIO_PULLUP_ONLY);
@@ -33,20 +42,27 @@ bool sdcard_init() {
if (useSDCard) {
ESP_LOGI(TAG, "SD-card found");
createFile();
} else
openFile();
return true;
} else {
ESP_LOGI(TAG, "SD-card not found");
return useSDCard;
return false;
}
}
void sdcard_close(void) {
ESP_LOGI(TAG, "closing SD-card");
fileSDCard.flush();
fileSDCard.close();
}
void sdcardWriteData(uint16_t noWifi, uint16_t noBle,
__attribute__((unused)) uint16_t noBleCWA) {
__attribute__((unused)) uint16_t voltage) {
static int counterWrites = 0;
char tempBuffer[12 + 1];
char tempBuffer[20 + 1];
time_t t = time(NULL);
struct tm tt;
localtime_r(&t, &tt);
mktime(&tt);
gmtime_r(&t, &tt); // make UTC timestamp
#if (HAS_SDS011)
sdsStatus_t sds;
@@ -55,71 +71,85 @@ void sdcardWriteData(uint16_t noWifi, uint16_t noBle,
if (!useSDCard)
return;
ESP_LOGD(TAG, "writing to SD-card");
strftime(tempBuffer, sizeof(tempBuffer), "%d.%m.%Y", &tt);
ESP_LOGI(TAG, "SD: writing data");
strftime(tempBuffer, sizeof(tempBuffer), "%FT%TZ", &tt);
fileSDCard.print(tempBuffer);
strftime(tempBuffer, sizeof(tempBuffer), "%H.%M.%S", &tt);
snprintf(tempBuffer, sizeof(tempBuffer), ",%d,%d", noWifi, noBle);
fileSDCard.print(tempBuffer);
sprintf(tempBuffer, "%d,%d", noWifi, noBle);
fileSDCard.print(tempBuffer);
#if (COUNT_ENS)
sprintf(tempBuffer, ",%d", noBleCWA);
#if (defined BAT_MEASURE_ADC || defined HAS_PMU)
snprintf(tempBuffer, sizeof(tempBuffer), ",%d", voltage);
fileSDCard.print(tempBuffer);
#endif
#if (HAS_SDS011)
sds011_store(&sds);
sprintf(tempBuffer, ",%5.1f,%4.1f", sds.pm10, sds.pm25);
snprintf(tempBuffer, sizeof(tempBuffer), ",%5.1f,%4.1f", sds.pm10 / 10,
sds.pm25 / 10);
fileSDCard.print(tempBuffer);
#endif
fileSDCard.println();
if (++counterWrites > 2) {
// force writing to SD-card
ESP_LOGD(TAG, "flushing data to card");
ESP_LOGI(TAG, "SD: flushing data");
fileSDCard.flush();
counterWrites = 0;
}
}
void createFile(void) {
char bufferFilename[8 + 1 + 3 + 1];
void openFile(void) {
char bufferFilename[30];
useSDCard = false;
for (int i = 0; i < 100; i++) {
sprintf(bufferFilename, SDCARD_FILE_NAME, i);
// ESP_LOGD(TAG, "SD: looking for file <%s>", bufferFilename);
snprintf(bufferFilename, sizeof(bufferFilename), "/%s.csv", SDCARD_FILE_NAME);
ESP_LOGI(TAG, "SD: looking for file <%s>", bufferFilename);
#if HAS_SDCARD == 1
bool fileExists = SD.exists(bufferFilename);
bool fileExists = SD.exists(bufferFilename);
#elif HAS_SDCARD == 2
bool fileExists = SD_MMC.exists(bufferFilename);
bool fileExists = SD_MMC.exists(bufferFilename);
#endif
if (!fileExists) {
// ESP_LOGD(TAG, "SD: file does not exist: opening");
// file not exists, create it
if (!fileExists) {
ESP_LOGD(TAG, "SD: file not found, creating...");
#if HAS_SDCARD == 1
fileSDCard = SD.open(bufferFilename, FILE_WRITE);
fileSDCard = SD.open(bufferFilename, FILE_WRITE);
#elif HAS_SDCARD == 2
fileSDCard = SD_MMC.open(bufferFilename, FILE_WRITE);
fileSDCard = SD_MMC.open(bufferFilename, FILE_WRITE);
#endif
if (fileSDCard) {
ESP_LOGD(TAG, "SD: name opened: <%s>", bufferFilename);
fileSDCard.print(SDCARD_FILE_HEADER);
#if (COUNT_ENS)
fileSDCard.print(SDCARD_FILE_HEADER_CWA); // for Corona-data (CWA)
if (fileSDCard) {
ESP_LOGD(TAG, "SD: name opened: <%s>", bufferFilename);
fileSDCard.print(SDCARD_FILE_HEADER);
#if (defined BAT_MEASURE_ADC || defined HAS_PMU)
fileSDCard.print(SDCARD_FILE_HEADER_VOLTAGE); // for battery level data
#endif
#if (HAS_SDS011)
fileSDCard.print(SDCARD_FILE_HEADER_SDS011);
fileSDCard.print(SDCARD_FILE_HEADER_SDS011);
#endif
fileSDCard.println();
useSDCard = true;
break;
}
fileSDCard.println();
useSDCard = true;
}
}
// file exists, append data
else {
ESP_LOGD(TAG, "SD: file found, opening...");
#if HAS_SDCARD == 1
fileSDCard = SD.open(bufferFilename, FILE_APPEND);
#elif HAS_SDCARD == 2
fileSDCard = SD_MMC.open(bufferFilename, FILE_APPEND);
#endif
if (fileSDCard) {
ESP_LOGD(TAG, "SD: name opened: <%s>", bufferFilename);
useSDCard = true;
}
}
return;
}
+22 -21
View File
@@ -10,35 +10,37 @@ static const char TAG[] = __FILE__;
#if (HAS_IF482)
#error cannot use IF482 together with SDS011 (both use UART#2)
#endif
// UART(2) is unused in this project
static HardwareSerial sdsSerial(2); // so we use it here
static SDS011 sdsSensor; // fine dust sensor
// the results of the sensor:
static float pm10, pm25;
boolean isSDS011Active;
SdsDustSensor sds(Serial2);
bool isSDS011Active = false;
static float pm10 = 0.0, pm25 = 0.0;
// init
bool sds011_init() {
pm25 = pm10 = 0.0;
sdsSensor.begin(&sdsSerial, SDS_RX, SDS_TX);
sds011_sleep(); // we do sleep/wakup by ourselves
sds.begin(9600, SERIAL_8N1, SDS_RX, SDS_TX);
sds011_wakeup();
ESP_LOGI(TAG, "SDS011: %s", sds.queryFirmwareVersion().toString().c_str());
sds.setQueryReportingMode();
return true;
}
// reading data:
void sds011_loop() {
if (isSDS011Active) {
int sdsErrorCode = sdsSensor.read(&pm25, &pm10);
if (sdsErrorCode) {
pm25 = pm10 = 0.0;
ESP_LOGI(TAG, "SDS011 error: %d", sdsErrorCode);
PmResult pm = sds.queryPm();
if (!pm.isOk()) {
ESP_LOGE(TAG, "SDS011: query error %s", pm.statusToString().c_str());
pm10 = pm25 = 0.0;
} else {
ESP_LOGI(TAG, "fine-dust-values: %5.1f,%4.1f", pm10, pm25);
ESP_LOGI(TAG, "SDS011: %s", pm.toString().c_str());
pm10 = pm.pm10;
pm25 = pm.pm25;
}
ESP_LOGD(TAG, "SDS011: go to sleep");
sds011_sleep();
}
return;
}
// retrieving stored data:
@@ -49,17 +51,16 @@ void sds011_store(sdsStatus_t *sds_store) {
// putting the SDS-sensor to sleep
void sds011_sleep(void) {
sdsSensor.sleep();
isSDS011Active = false;
WorkingStateResult state = sds.sleep();
isSDS011Active = state.isWorking();
}
// start the SDS-sensor
// needs 30 seconds for warming up
void sds011_wakeup() {
if (!isSDS011Active) {
sdsSensor.wakeup();
isSDS011Active = true;
}
WorkingStateResult state = sds.wakeup();
isSDS011Active = state.isWorking();
ESP_LOGD(TAG, "SDS011: %s", state.toString().c_str());
}
#endif // HAS_SDS011
+33 -28
View File
@@ -5,6 +5,8 @@ void setSendIRQ(TimerHandle_t xTimer) {
xTaskNotify(irqHandlerTask, SENDCYCLE_IRQ, eSetBits);
}
void setSendIRQ(void) { setSendIRQ(NULL); }
void initSendDataTimer(uint8_t sendcycle) {
static TimerHandle_t SendDataTimer = NULL;
@@ -65,31 +67,26 @@ void SendPayload(uint8_t port) {
mqtt_enqueuedata(&SendBuffer);
#endif
// write data to sdcard, if present
#if (HAS_SDCARD)
if (port == COUNTERPORT) {
sdcardWriteData(libpax_macs_wifi, libpax_macs_ble
#if (COUNT_ENS)
,
cwa_report()
#endif
);
}
#endif
} // SendPayload
// interrupt triggered function to prepare payload to send
// timer triggered function to prepare payload to send
void sendData() {
uint8_t bitmask = cfg.payloadmask;
uint8_t mask = 1;
#if (HAS_GPS)
gpsStatus_t gps_status;
#endif
#if (HAS_SDS011)
sdsStatus_t sds_status;
#endif
#if ((WIFICOUNTER) || (BLECOUNTER))
struct count_payload_t count =
count_from_libpax; // copy values from global libpax var
ESP_LOGD(TAG, "Sending count results: pax=%d / wifi=%d / ble=%d", count.pax,
count.wifi_count, count.ble_count);
#endif
while (bitmask) {
switch (bitmask & mask) {
@@ -97,14 +94,14 @@ void sendData() {
#if ((WIFICOUNTER) || (BLECOUNTER))
case COUNT_DATA:
payload.reset();
#if !(PAYLOAD_OPENSENSEBOX)
ESP_LOGI(TAG, "Sending libpax wifi count: %d", libpax_macs_wifi);
payload.addCount(libpax_macs_wifi, MAC_SNIFF_WIFI);
payload.addCount(count.wifi_count, MAC_SNIFF_WIFI);
if (cfg.blescan) {
ESP_LOGI(TAG, "Sending libpax ble count: %d", libpax_macs_ble);
payload.addCount(libpax_macs_ble, MAC_SNIFF_BLE);
payload.addCount(count.ble_count, MAC_SNIFF_BLE);
}
#endif
#if (HAS_GPS)
if (GPSPORT == COUNTERPORT) {
// send GPS position only if we have a fix
@@ -115,23 +112,35 @@ void sendData() {
ESP_LOGD(TAG, "No valid GPS position");
}
#endif
#if (PAYLOAD_OPENSENSEBOX)
ESP_LOGI(TAG, "Sending libpax wifi count: %d", libpax_macs_wifi);
payload.addCount(libpax_macs_wifi, MAC_SNIFF_WIFI);
payload.addCount(count.wifi_count, MAC_SNIFF_WIFI);
if (cfg.blescan) {
ESP_LOGI(TAG, "Sending libpax ble count: %d", libpax_macs_ble);
payload.addCount(libpax_macs_ble, MAC_SNIFF_BLE);
payload.addCount(count.ble_count, MAC_SNIFF_BLE);
#endif
#if (HAS_SDS011)
sds011_store(&sds_status);
payload.addSDS(sds_status);
#endif
SendPayload(COUNTERPORT);
#ifdef HAS_DISPLAY
dp_plotCurve(libpax_macs_ble + libpax_macs_wifi, true);
dp_plotCurve(count.pax, true);
#endif
break;
#if (HAS_SDCARD)
sdcardWriteData(count.wifi_count, count.ble_count
#if (defined BAT_MEASURE_ADC || defined HAS_PMU)
,
read_voltage()
#endif
);
#endif // HAS_SDCARD
SendPayload(COUNTERPORT);
break; // case COUNTDATA
#endif // ((WIFICOUNTER) || (BLECOUNTER))
#if (HAS_BME)
case MEMS_DATA:
@@ -162,10 +171,6 @@ void sendData() {
payload.reset();
payload.addSensor(sensor_read(1));
SendPayload(SENSOR1PORT);
#if (COUNT_ENS)
if (cfg.countermode != 1)
cwa_clear();
#endif
break;
#endif
#if (HAS_SENSOR_2)
-12
View File
@@ -2,12 +2,6 @@
#include "globals.h"
#include "sensor.h"
#if (COUNT_ENS)
#include "payload.h"
#include "corona.h"
extern PayloadConvert payload;
#endif
// Local logging tag
static const char TAG[] = __FILE__;
@@ -53,16 +47,10 @@ uint8_t *sensor_read(uint8_t sensor) {
case 1:
// insert user specific sensor data frames here
// note: Sensor1 fields are used for ENS count, if ENS detection enabled
#if (COUNT_ENS)
if (cfg.enscount)
payload.addCount(cwa_report(), MAC_SNIFF_BLE_ENS);
#else
buf[0] = length;
buf[1] = 0x01;
buf[2] = 0x02;
buf[3] = 0x03;
#endif
break;
case 2:
+58 -54
View File
@@ -19,9 +19,9 @@ static const char TAG[] = __FILE__;
// G = GPS / R = RTC / L = LORA / * = no sync / ? = never synced
const char timeSetSymbols[] = {'G', 'R', 'L', '*', '?'};
bool volatile TimePulseTick = false;
DRAM_ATTR bool TimePulseTick = false;
DRAM_ATTR unsigned long lastPPS = millis();
timesource_t timeSource = _unsynced;
time_t _COMPILETIME = compileTime(__DATE__);
TaskHandle_t ClockTask = NULL;
hw_timer_t *ppsIRQ = NULL;
@@ -40,8 +40,7 @@ Ticker timesyncer;
void setTimeSyncIRQ() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
void calibrateTime(void) {
ESP_LOGD(TAG, "[%0.3f] calibrateTime, timeSource == %d", _seconds(),
timeSource);
time_t t = 0;
uint16_t t_msec = 0;
@@ -57,7 +56,7 @@ void calibrateTime(void) {
// has RTC -> fallback to RTC time
#ifdef HAS_RTC
t = get_rtctime();
t = get_rtctime(&t_msec);
// set time from RTC - method will check if time is valid
setMyTime((uint32_t)t, t_msec, _rtc);
#endif
@@ -101,26 +100,27 @@ void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec,
vTaskDelay(pdMS_TO_TICKS(1000 - t_msec % 1000));
}
// from here on we are on top of next second
tv.tv_sec = time_to_set;
tv.tv_usec = 0;
sntp_sync_time(&tv);
ESP_LOGI(TAG, "[%0.3f] UTC time: %d.000 sec", _seconds(), time_to_set);
// if we have a software pps timer, shift it to top of second
if (ppsIRQ != NULL) {
timerWrite(ppsIRQ, 0); // reset pps timer
CLOCKIRQ(); // fire clock pps, this advances time 1 sec
}
// if we have got an external timesource, set RTC time and shift RTC_INT pulse
// to top of second
// if we have a precise time timesource, set RTC time and shift RTC_INT
// pulse to top of second
#ifdef HAS_RTC
if ((mytimesource == _gps) || (mytimesource == _lora))
set_rtctime(time_to_set);
#endif
// if we have a software pps timer, shift it to top of second
if (ppsIRQ != NULL) {
timerWrite(ppsIRQ, 0); // reset pps timer
CLOCKIRQ(); // fire clock pps to advance wall clock by 1 sec
}
timeSource = mytimesource; // set global variable
timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ);
@@ -132,7 +132,7 @@ void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec,
"[%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,
_COMPILETIME);
compileTime());
}
}
@@ -140,29 +140,26 @@ void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec,
uint8_t timepulse_init() {
// set esp-idf API sntp sync mode
//sntp_init();
// sntp_init();
sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED);
// use time pulse from GPS as time base with fixed 1Hz frequency
// if we have, use PPS time pulse from GPS for syncing time on top of second
#ifdef GPS_INT
// setup external interupt pin for rising edge GPS INT
// setup external interupt pin for rising edge of GPS PPS
pinMode(GPS_INT, INPUT_PULLDOWN);
// setup external rtc 1Hz clock as pulse per second clock
ESP_LOGI(TAG, "Timepulse: external (GPS)");
return 1; // success
attachInterrupt(digitalPinToInterrupt(GPS_INT), GPSIRQ, RISING);
#endif
// use pulse from on board RTC chip as time base with fixed frequency
#elif defined RTC_INT
// if we have, use pulse from on board RTC chip as time base for calendar time
#if defined RTC_INT
// setup external interupt pin for falling edge RTC INT
pinMode(RTC_INT, INPUT_PULLUP);
// setup external rtc 1Hz clock as pulse per second clock
// setup external rtc 1Hz clock pulse
if (I2C_MUTEX_LOCK()) {
Rtc.SetSquareWavePinClockFrequency(DS3231SquareWaveClock_1Hz);
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock);
I2C_MUTEX_UNLOCK();
pinMode(RTC_INT, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
ESP_LOGI(TAG, "Timepulse: external (RTC)");
return 1; // success
} else {
@@ -172,33 +169,39 @@ uint8_t timepulse_init() {
return 1; // success
#else
// use ESP32 hardware timer as time base with adjustable frequency
// use ESP32 hardware timer as time base for calendar time
ppsIRQ = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec
timerAlarmWrite(ppsIRQ, 10000, true); // 1000ms
timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, true);
timerAlarmEnable(ppsIRQ);
ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)");
return 1; // success
#endif
} // timepulse_init
void timepulse_start(void) {
#ifdef GPS_INT // start external clock gps pps line
attachInterrupt(digitalPinToInterrupt(GPS_INT), CLOCKIRQ, RISING);
#elif defined RTC_INT // start external clock rtc
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
#else // start internal clock esp32 hardware timer
timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, true);
timerAlarmEnable(ppsIRQ);
#endif
// start cyclic time sync
timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ);
// get time if we don't have one
if (timeSource != _set)
setTimeSyncIRQ(); // init systime by RTC or GPS or LORA
// start cyclic time sync
timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ);
} // timepulse_init
// interrupt service routine triggered by GPS PPS
void IRAM_ATTR GPSIRQ(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
// take timestamp
lastPPS = millis(); // last time of pps
// yield only if we should
if (xHigherPriorityTaskWoken)
portYIELD_FROM_ISR();
}
// interrupt service routine triggered by either pps or esp32 hardware timer
// interrupt service routine triggered by esp32 hardware timer
void IRAM_ATTR CLOCKIRQ(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
@@ -211,9 +214,7 @@ void IRAM_ATTR CLOCKIRQ(void) {
// flip time pulse ticker, if needed
#ifdef HAS_DISPLAY
#if (defined GPS_INT || defined RTC_INT)
TimePulseTick = !TimePulseTick; // flip pulse ticker
#endif
TimePulseTick = !TimePulseTick; // flip global variable pulse ticker
#endif
// yield only if we should
@@ -224,7 +225,9 @@ void IRAM_ATTR CLOCKIRQ(void) {
// helper function to check plausibility of a given epoch time
bool timeIsValid(time_t const t) {
// is t a time in the past? we use compile time to guess
return (t > _COMPILETIME);
// compile time is some local time, but we do not know it's time zone
// thus, we go 1 full day back to be sure to catch a time in the past
return (t > (compileTime() - 86400));
}
// helper function to calculate serial transmit time
@@ -252,7 +255,7 @@ void clock_init(void) {
"clockloop", // name of task
3072, // stack size of task
(void *)1, // task parameter
4, // priority of the task
6, // priority of the task
&ClockTask, // task handle
1); // CPU core
@@ -283,7 +286,7 @@ void clock_loop(void *taskparameter) { // ClockTask
// set calendar time for next second of clock output
tt = (time_t)(current_time + 1);
localtime_r(&tt, &t);
mktime(&t);
tt = mktime(&t);
#if defined HAS_IF482
@@ -293,13 +296,13 @@ void clock_loop(void *taskparameter) { // ClockTask
if (xTaskNotifyWait(0x00, ULONG_MAX, &current_time, txDelay) == pdTRUE) {
tt = (time_t)(current_time + 1);
localtime_r(&tt, &t);
mktime(&t);
tt = mktime(&t);
}
// send IF482 telegram
IF482.print(IF482_Frame(t)); // note: telegram is for *next* second
IF482.print(IF482_Frame(tt)); // note: telegram is for *next* second
ESP_LOGD(TAG, "[%0.3f] IF482: %s", _seconds(), IF482_Frame(t));
ESP_LOGD(TAG, "[%0.3f] IF482: %s", _seconds(), IF482_Frame(tt).c_str());
#elif defined HAS_DCF77
@@ -340,7 +343,7 @@ void clock_loop(void *taskparameter) { // ClockTask
} // clock_loop()
// we use compile date to create a time_t reference "in the past"
time_t compileTime(const String compile_date) {
time_t compileTime(void) {
char s_month[5];
int year;
@@ -353,10 +356,11 @@ time_t compileTime(const String compile_date) {
if (secs == -1) {
// determine date
// we go one day back to bypass unknown timezone of local time
sscanf(compile_date.c_str(), "%s %d %d", s_month, &t.tm_mday - 1, &year);
sscanf(__DATE__, "%s %d %d", s_month, &t.tm_mday, &year);
t.tm_mon = (strstr(month_names, s_month) - month_names) / 3;
t.tm_year = year - 1900;
// determine time
sscanf(__TIME__, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
// convert to secs local time
secs = mktime(&t);
+1 -1
View File
@@ -34,7 +34,7 @@ void timesync_init(void) {
"timesync_proc", // name of task
4096, // stack size of task
(void *)1, // task parameter
3, // priority of the task
7, // priority of the task
&timeSyncProcTask, // task handle
1); // CPU core
}