Merge pull request #415 from cyberman54/development

v1.7.974
This commit is contained in:
Verkehrsrot 2019-08-28 22:21:23 +02:00 committed by GitHub
commit 1de4c467b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 86 additions and 49 deletions

View File

@ -156,7 +156,7 @@ If you're using a device with OLED display, or if you add such one to the I2C bu
You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*sensor.cpp*](src/sensor.cpp). Bosch BME280 / BME680 environment sensors are supported. Enable flag *lib_deps_sensors* for your board in [*platformio.ini*](src/platformio.ini) and configure BME in board's hal file before build. If you need Bosch's proprietary BSEC libraray (e.g. to get indoor air quality value from BME680) further enable *build_flags_sensors*, which comes on the price of reduced RAM and increased build size. RTC DS3231, generic serial NMEA GPS, I2C LoPy GPS are supported, and to be configured in board's hal file. See [*generic.h*](src/hal/generic.h) for all options and for proper configuration of BME280/BME680. You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*sensor.cpp*](src/sensor.cpp). Bosch BME280 / BME680 environment sensors are supported. Enable flag *lib_deps_sensors* for your board in [*platformio.ini*](src/platformio.ini) and configure BME in board's hal file before build. If you need Bosch's proprietary BSEC libraray (e.g. to get indoor air quality value from BME680) further enable *build_flags_sensors*, which comes on the price of reduced RAM and increased build size. RTC DS3231, generic serial NMEA GPS, I2C LoPy GPS are supported, and to be configured in board's hal file. See [*generic.h*](src/hal/generic.h) for all options and for proper configuration of BME280/BME680.
Output of user sensor data can be switched by user remote control command 0x13 sent to Port 2. Output of user sensor data can be switched by user remote control command 0x14 sent to Port 2.
Output of sensor and peripheral data is internally switched by a bitmask register. Default mask (0xFF) can be tailored by editing *cfg.payloadmask* initialization value in [*configmanager.cpp*](src/configmanager.cpp) following this scheme: Output of sensor and peripheral data is internally switched by a bitmask register. Default mask (0xFF) can be tailored by editing *cfg.payloadmask* initialization value in [*configmanager.cpp*](src/configmanager.cpp) following this scheme:
@ -383,6 +383,15 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
byte 1 = user sensor number (1..3) byte 1 = user sensor number (1..3)
byte 2 = sensor mode (0 = disabled / 1 = enabled [default]) byte 2 = sensor mode (0 = disabled / 1 = enabled [default])
0x14 set payload mask
byte 1 = sensor data payload mask (0..255, meaning of bits see above)
0x15 set BME data on/off
0 = BME data off
1 = BME data on, sends BME data on port 7 [default]
0x80 get device configuration 0x80 get device configuration
Device answers with it's current configuration on Port 3. Device answers with it's current configuration on Port 3.

View File

@ -45,6 +45,9 @@
#define I2C_MUTEX_LOCK() (xSemaphoreTake(I2Caccess, pdMS_TO_TICKS(10)) == pdTRUE) #define I2C_MUTEX_LOCK() (xSemaphoreTake(I2Caccess, pdMS_TO_TICKS(10)) == pdTRUE)
#define I2C_MUTEX_UNLOCK() (xSemaphoreGive(I2Caccess)) #define I2C_MUTEX_UNLOCK() (xSemaphoreGive(I2Caccess))
enum sendprio_t { prio_low, prio_normal, prio_high };
enum timesource_t { _gps, _rtc, _lora, _unsynced };
// Struct holding devices's runtime configuration // Struct holding devices's runtime configuration
typedef struct { typedef struct {
uint8_t lorasf; // 7-12, lora spreadfactor uint8_t lorasf; // 7-12, lora spreadfactor
@ -73,6 +76,7 @@ typedef struct {
typedef struct { typedef struct {
uint8_t MessageSize; uint8_t MessageSize;
uint8_t MessagePort; uint8_t MessagePort;
sendprio_t MessagePrio;
uint8_t Message[PAYLOAD_BUFFER_SIZE]; uint8_t Message[PAYLOAD_BUFFER_SIZE];
} MessageBuffer_t; } MessageBuffer_t;
@ -95,9 +99,6 @@ typedef struct {
float gas; // raw gas sensor signal float gas; // raw gas sensor signal
} bmeStatus_t; } bmeStatus_t;
enum sendprio_t { prio_low, prio_normal, prio_high };
enum timesource_t { _gps, _rtc, _lora, _unsynced };
extern std::set<uint16_t, std::less<uint16_t>, Mallocator<uint16_t>> macs; extern std::set<uint16_t, std::less<uint16_t>, Mallocator<uint16_t>> macs;
extern std::array<uint64_t, 0xff>::iterator it; extern std::array<uint64_t, 0xff>::iterator it;
extern std::array<uint64_t, 0xff> beacons; extern std::array<uint64_t, 0xff> beacons;

View File

@ -13,6 +13,6 @@ void refreshTheMatrixDisplay(bool nextPage = false);
void DrawNumber(String strNum, uint8_t iDotPos = 0); void DrawNumber(String strNum, uint8_t iDotPos = 0);
uint8_t GetCharFromFont(char cChar); uint8_t GetCharFromFont(char cChar);
uint8_t GetCharWidth(char cChar); uint8_t GetCharWidth(char cChar);
void ScrollLeft(uint8_t *buf, uint16_t cols, uint16_t rows); void ScrollLeft(uint8_t *buf, const uint16_t cols, const uint16_t rows);
#endif #endif

View File

@ -35,7 +35,7 @@ void os_getDevEui(u1_t *buf);
void showLoraKeys(void); void showLoraKeys(void);
void switch_lora(uint8_t sf, uint8_t tx); void switch_lora(uint8_t sf, uint8_t tx);
void lora_send(osjob_t *job); void lora_send(osjob_t *job);
void lora_enqueuedata(MessageBuffer_t *message, sendprio_t prio); void lora_enqueuedata(MessageBuffer_t *message);
void lora_queuereset(void); void lora_queuereset(void);
#if (TIME_SYNC_LORAWAN) #if (TIME_SYNC_LORAWAN)
void user_request_network_time_callback(void *pVoidUserUTCTime, void user_request_network_time_callback(void *pVoidUserUTCTime,

View File

@ -28,7 +28,7 @@ licenses. Refer to LICENSE.txt file in repository for more details.
esp_err_t spi_init(); esp_err_t spi_init();
void spi_enqueuedata(MessageBuffer_t *message, sendprio_t prio); void spi_enqueuedata(MessageBuffer_t *message);
void spi_queuereset(); void spi_queuereset();
#endif // _SPISLAVE_H #endif // _SPISLAVE_H

View File

@ -42,7 +42,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I
[common] [common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c" ; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
release_version = 1.7.93 release_version = 1.7.974
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 3 debug_level = 3
@ -61,7 +61,7 @@ lib_deps_display =
lib_deps_matrix_display = lib_deps_matrix_display =
https://github.com/Seeed-Studio/Ultrathin_LED_Matrix.git https://github.com/Seeed-Studio/Ultrathin_LED_Matrix.git
lib_deps_rgbled = lib_deps_rgbled =
SmartLeds@>=1.1.5 SmartLeds@>=1.1.6
lib_deps_gps = lib_deps_gps =
1655@>=1.0.2 ;TinyGPSPlus by Mikal Hart 1655@>=1.0.2 ;TinyGPSPlus by Mikal Hart
lib_deps_sensors = lib_deps_sensors =
@ -114,7 +114,7 @@ upload_protocol = custom
upload_protocol = esptool upload_protocol = esptool
[env:dev] [env:dev]
upload_protocol = esptool upload_protocol = custom
build_type = debug build_type = debug
platform = https://github.com/platformio/platform-espressif32.git#develop platform = https://github.com/platformio/platform-espressif32.git#develop
platform_packages = platform_packages =

View File

@ -143,7 +143,9 @@ int checkIaqSensorStatus(void) {
// store current BME sensor data in struct // store current BME sensor data in struct
void bme_storedata(bmeStatus_t *bme_store) { void bme_storedata(bmeStatus_t *bme_store) {
if (I2C_MUTEX_LOCK()) { // block i2c bus access
if ((cfg.payloadmask && MEMS_DATA) &
(I2C_MUTEX_LOCK())) { // block i2c bus access
#ifdef HAS_BME680 #ifdef HAS_BME680
if (iaqSensor.run()) { // if new data is available if (iaqSensor.run()) { // if new data is available

View File

@ -204,13 +204,14 @@ uint8_t GetCharWidth(char cChar) {
return CharDescriptor.width; return CharDescriptor.width;
} }
void ScrollLeft(uint8_t *buf, uint16_t cols, uint16_t rows) { void ScrollLeft(uint8_t *buf, const uint16_t cols, const uint16_t rows) {
uint32_t i, k, idx; uint32_t i, k, idx;
const uint32_t x = cols / 8;
for (k = 0; k < rows; k++) { for (k = 0; k < rows; k++) {
// scroll a line with x bytes one dot to the left // scroll a line with x bytes one dot to the left
for (i = 0; i < cols / 8 - 1; ++i) { for (i = 0; i < x - 1; ++i) {
idx = i + k * cols / 8; idx = i + k * x;
buf[idx] = (buf[idx] << 1) | ((buf[idx + 1] >> 7) & 1); buf[idx] = (buf[idx] << 1) | ((buf[idx + 1] >> 7) & 1);
} }
buf[idx + 1] <<= 1; buf[idx + 1] <<= 1;

View File

@ -248,6 +248,11 @@ void onEvent(ev_t ev) {
: PSTR("TX COMPLETE")); : PSTR("TX COMPLETE"));
sprintf(display_line6, " "); // clear previous lmic status sprintf(display_line6, " "); // clear previous lmic status
// schedule next transmission with some random delay to prevent systematic
// collisions
os_setTimedCallback(&sendjob, os_getTime() + ms2osticks(random(500)),
lora_send);
if (LMIC.dataLen) { // did we receive payload data -> display info if (LMIC.dataLen) { // did we receive payload data -> display info
ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d",
LMIC.dataLen, LMIC.rssi, LMIC.snr / 4); LMIC.dataLen, LMIC.rssi, LMIC.snr / 4);
@ -391,27 +396,22 @@ void switch_lora(uint8_t sf, uint8_t tx) {
void lora_send(osjob_t *job) { void lora_send(osjob_t *job) {
MessageBuffer_t SendBuffer; MessageBuffer_t SendBuffer;
// Check if there is a pending TX/RX job running, if yes don't eat data
// since it cannot be sent right now // Check if there is not a current TX/RX job running
if ((LMIC.opmode & (OP_JOINING | OP_REJOIN | OP_TXDATA | OP_POLL)) != 0) { if (LMIC.opmode & OP_TXRXPEND) {
// waiting for LoRa getting ready ESP_LOGE(TAG, "LMIC busy, data not sent and lost");
} else { return;
if (xQueueReceive(LoraSendQueue, &SendBuffer, (TickType_t)0) == pdTRUE) {
// SendBuffer now filled with next payload from queue
if (!LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message,
SendBuffer.MessageSize, (cfg.countermode & 0x02))) {
ESP_LOGI(TAG, "%d byte(s) sent to LoRa", SendBuffer.MessageSize);
} else {
ESP_LOGE(TAG, "could not send %d byte(s) to LoRa",
SendBuffer.MessageSize);
} }
// sprintf(display_line7, "PACKET QUEUED");
// fetch next payload to send from queue or wait until new payload shows up in
// queue
if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) == pdTRUE) {
if (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message,
SendBuffer.MessageSize, (cfg.countermode & 0x02)) == 0)
ESP_LOGI(TAG, "%d byte(s) delivered to LMIC", SendBuffer.MessageSize);
else
lora_enqueuedata(&SendBuffer); // re-enqueue unsent message
} }
}
// reschedule job every 0,5 - 1 sec. including a bit of random to prevent
// systematic collisions
os_setTimedCallback(job, os_getTime() + 500 + ms2osticks(random(500)),
lora_send);
} }
esp_err_t lora_stack_init() { esp_err_t lora_stack_init() {
@ -441,15 +441,19 @@ esp_err_t lora_stack_init() {
return ESP_OK; // continue main program return ESP_OK; // continue main program
} }
void lora_enqueuedata(MessageBuffer_t *message, sendprio_t prio) { void lora_enqueuedata(MessageBuffer_t *message) {
// enqueue message in LORA send queue // enqueue message in LORA send queue
BaseType_t ret; BaseType_t ret = pdFALSE;
MessageBuffer_t DummyBuffer; MessageBuffer_t DummyBuffer;
sendprio_t prio = message->MessagePrio;
switch (prio) { switch (prio) {
case prio_high: case prio_high:
// clear space in queue if full, then fallthrough to normal // clear some space in queue if full, then fallthrough to prio_normal
if (uxQueueSpacesAvailable(LoraSendQueue) == 0) if (uxQueueSpacesAvailable(LoraSendQueue) == 0) {
xQueueReceive(LoraSendQueue, &DummyBuffer, (TickType_t)0); xQueueReceive(LoraSendQueue, &DummyBuffer, (TickType_t)0);
ESP_LOGW(TAG, "LORA sendqueue purged, data is lost");
}
case prio_normal: case prio_normal:
ret = xQueueSendToFront(LoraSendQueue, (void *)message, (TickType_t)0); ret = xQueueSendToFront(LoraSendQueue, (void *)message, (TickType_t)0);
break; break;
@ -458,7 +462,9 @@ void lora_enqueuedata(MessageBuffer_t *message, sendprio_t prio) {
ret = xQueueSendToBack(LoraSendQueue, (void *)message, (TickType_t)0); ret = xQueueSendToBack(LoraSendQueue, (void *)message, (TickType_t)0);
break; break;
} }
if (ret != pdTRUE) if (ret == pdTRUE)
ESP_LOGD(TAG, "LORA sendqueue data enqueued");
else
ESP_LOGW(TAG, "LORA sendqueue is full"); ESP_LOGW(TAG, "LORA sendqueue is full");
} }

View File

@ -131,6 +131,20 @@ void set_gps(uint8_t val[]) {
} }
} }
void set_bme(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set BME mode to %s", val[0] ? "on" : "off");
if (val[0]) {
cfg.payloadmask |= (uint8_t)MEMS_DATA; // set bit in mask
} else {
cfg.payloadmask &= ~(uint8_t)MEMS_DATA; // clear bit in mask
}
}
void set_payloadmask(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set payload mask to %X", val[0]);
cfg.payloadmask = val[0];
}
void set_sensor(uint8_t val[]) { void set_sensor(uint8_t val[]) {
#if (HAS_SENSORS) #if (HAS_SENSORS)
switch (val[0]) { // check if valid sensor number 1...4 switch (val[0]) { // check if valid sensor number 1...4
@ -307,7 +321,8 @@ cmd_t table[] = {
{0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true}, {0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true},
{0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true}, {0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true},
{0x11, set_monitor, 1, true}, {0x12, set_beacon, 7, false}, {0x11, set_monitor, 1, true}, {0x12, set_beacon, 7, false},
{0x13, set_sensor, 2, true}, {0x80, get_config, 0, false}, {0x13, set_sensor, 2, true}, {0x14, set_payloadmask, 1, true},
{0x15, set_bme, 1, true}, {0x80, get_config, 0, false},
{0x81, get_status, 0, false}, {0x84, get_gps, 0, false}, {0x81, get_status, 0, false}, {0x84, get_gps, 0, false},
{0x85, get_bme, 0, false}, {0x86, get_time, 0, false}, {0x85, get_bme, 0, false}, {0x86, get_time, 0, false},
{0x87, set_time, 0, false}, {0x99, set_flush, 0, false}}; {0x87, set_time, 0, false}, {0x99, set_flush, 0, false}};

View File

@ -10,9 +10,11 @@ void sendcycle() {
// put data to send in RTos Queues used for transmit over channels Lora and SPI // put data to send in RTos Queues used for transmit over channels Lora and SPI
void SendPayload(uint8_t port, sendprio_t prio) { void SendPayload(uint8_t port, sendprio_t prio) {
MessageBuffer_t SendBuffer; // contains MessageSize, MessagePort, Message[] MessageBuffer_t SendBuffer; // contains MessageSize, MessagePort, MessagePrio, Message[]
SendBuffer.MessageSize = payload.getSize(); SendBuffer.MessageSize = payload.getSize();
SendBuffer.MessagePrio = prio;
switch (PAYLOAD_ENCODER) { switch (PAYLOAD_ENCODER) {
case 1: // plain -> no mapping case 1: // plain -> no mapping
case 2: // packed -> no mapping case 2: // packed -> no mapping
@ -38,14 +40,14 @@ void SendPayload(uint8_t port, sendprio_t prio) {
default: default:
SendBuffer.MessagePort = port; SendBuffer.MessagePort = port;
} }
memcpy(SendBuffer.Message, payload.getBuffer(), payload.getSize()); memcpy(SendBuffer.Message, payload.getBuffer(), SendBuffer.MessageSize);
// enqueue message in device's send queues // enqueue message in device's send queues
#if (HAS_LORA) #if (HAS_LORA)
lora_enqueuedata(&SendBuffer, prio); lora_enqueuedata(&SendBuffer);
#endif #endif
#ifdef HAS_SPI #ifdef HAS_SPI
spi_enqueuedata(&SendBuffer, prio); spi_enqueuedata(&SendBuffer);
#endif #endif
} // SendPayload } // SendPayload

View File

@ -147,10 +147,12 @@ esp_err_t spi_init() {
return ret; return ret;
} }
void spi_enqueuedata(MessageBuffer_t *message, sendprio_t prio) { void spi_enqueuedata(MessageBuffer_t *message) {
// enqueue message in SPI send queue // enqueue message in SPI send queue
BaseType_t ret; BaseType_t ret;
MessageBuffer_t DummyBuffer; MessageBuffer_t DummyBuffer;
sendprio_t prio = message->MessagePrio;
switch (prio) { switch (prio) {
case prio_high: case prio_high:
// clear space in queue if full, then fallthrough to normal // clear space in queue if full, then fallthrough to normal

View File

@ -57,7 +57,7 @@ void wifi_sniffer_init(void) {
wificfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM wificfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM
wificfg.wifi_task_core_id = 0; // we want wifi task running on core 0 wificfg.wifi_task_core_id = 0; // we want wifi task running on core 0
//wifi_promiscuous_filter_t filter = { // wifi_promiscuous_filter_t filter = {
// .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // only MGMT frames // .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // only MGMT frames
// .filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}; // we use all frames // .filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}; // we use all frames
@ -71,9 +71,8 @@ void wifi_sniffer_init(void) {
ESP_ERROR_CHECK( ESP_ERROR_CHECK(
esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
ESP_ERROR_CHECK(esp_wifi_stop()); ESP_ERROR_CHECK(esp_wifi_start()); // channel switch throws error without
ESP_ERROR_CHECK( ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set frame filter
esp_wifi_set_promiscuous_filter(&filter)); // set frame filter
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler)); ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler));
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode