8#include <libtock-sync/services/alarm.h>
9#include <libtock/kernel/ipc.h>
10#include <libtock/tock.h>
21#define LOG_LINE_SIZE 240
40static uint8_t meas_buffer[256] = {};
41static uint8_t meas_buffer_length = 0;
44static uint8_t uc_buffer[256] = {};
45static uint8_t uc_buffer_length = 0;
47static uint8_t cmd = 0;
50static int last_pid = 0;
52static bool has_data =
false;
54static bool network_ready =
false;
57static int timesync_retry_delay_ms = 10000;
60static int upload_interval = 60000;
63static const int userconfig_timeout_ms = 300 * 1000;
72static void ipc_callback(
int pid,
int len,
int buf,
void* ud);
86static int get_payload(uint8_t*
buffer,
int size);
100 snprintf(prefix, prefix_size,
"Core\t");
109static void microsd_log_output(ulog_event* ev,
void* arg) {
114 static bool busy =
false;
124 if (ulog_event_to_cstr(ev, line,
sizeof(line)) == ULOG_STATUS_OK) {
133 ulog_output_level_set_all(ULOG_LEVEL_TRACE);
135 ulog_info(
"=== Core App Initialized ===");
145 ulog_error(
"Could not load user config.");
156 ipc_register_service_callback(
"org.ents.core", ipc_callback, NULL);
159#ifdef TEST_USER_CONFIG
160 ulog_warn(
"TEST_USER_CONFIG is enabled!\n");
167 ulog_output_id sd_output =
168 ulog_output_add(microsd_log_output, NULL, ULOG_LEVEL_INFO);
169 if (sd_output == ULOG_OUTPUT_INVALID) {
172 ulog_error(
"Could not register microSD log output");
201 ulog_info(
"Retrying in %d ms", timesync_retry_delay_ms);
202 libtocksync_alarm_delay_ms(timesync_retry_delay_ms);
208 network_ready =
true;
211 ulog_trace(
"main loop");
213 ret = libtocksync_alarm_yield_for_with_timeout(&has_data, upload_interval);
215 ulog_info(
"Loop triggered with condition");
216 }
else if (ret == -1) {
217 ulog_info(
"Loop triggered with timeout");
219 ulog_warn(
"Unknown behavior with yield_for_with_timeout (error: %d)",
227 if (has_data && cmd == 2) {
230 ulog_info(
"Received %d bytes:", meas_buffer_length);
237 ret =
fifo_put(meas_buffer, meas_buffer_length);
239 ulog_error(
"Could not store measurement in buffer");
245 ipc_notify_client(last_pid);
257 if (meas_in_buffer > 1) {
259 while (meas_in_buffer > 1) {
260 ulog_debug(
"Buffer has %d measurements", meas_in_buffer);
266 ulog_debug(
"Uploading %d bytes", len);
272 ulog_error(
"Could not upload with LoRaWAN (error: %d)", ret);
274 ulog_debug(
"Uploaded %d bytes with LoRaWAN.");
285 ulog_debug(
"Sending heartbeat");
290 ulog_error(
"Error sending heartbeat (error: %d)");
293 ulog_debug(
"Heartbeat sent");
302 "total uploads: %d failed uploads: %d measurements: %d bytes: "
309static void ipc_callback(
int pid,
int len,
int buf,
void* ud) {
313 ulog_trace(
"ipc_callabck");
315 uint8_t*
buffer = (uint8_t*)buf;
319 uint8_t* length =
buffer + 1;
324 ulog_trace(
"user config command");
327 memcpy(
data, uc_buffer, uc_buffer_length);
328 *length = uc_buffer_length;
331 ipc_notify_client(pid);
334 }
else if (cmd == 2) {
335 ulog_trace(
"measurement command");
338 meas_buffer_length = *length;
339 memcpy(meas_buffer,
data, *length);
347 }
else if (cmd == 3) {
348 ulog_trace(
"ready command");
350 buffer[1] = (uint8_t)network_ready;
353 ipc_notify_client(pid);
357 ulog_error(
"IPC command %d not implemented.",
buffer[0]);
361static int get_payload(uint8_t*
buffer,
int size) {
362 ulog_trace(
"get_payload");
370 SensorMeasurement meas[8] = {};
375 for (
i = 0;
i < length;
i++) {
378 ulog_error(
"Could not read from buffer (error: %d)", ret);
381 ulog_debug(
"Read %d bytes from buffer", len);
386 ulog_error(
"Could not decode measurement (error %d), malformed data?",
395 ulog_error(
"Could not find size of payload (error %d)", ret);
398 ulog_debug(
"Size of repeated sensor measurements: %d", len);
402 ulog_debug(
"Over sensors size limit of %d. Removing last measurement.",
415 ulog_error(
"Could not encode %d repeated measurements (error %d)",
i, ret);
421 for (uint16_t j = 0; j <
i; j++) {
424 ulog_error(
"Could not remove measurement index %d from buffer", j);
Controller module for stm32.
Circular buffer as FIFO data structure for buffering measurements.
void ControllerDeviceReset(void)
Resets the controller interface.
void ControllerInit(void)
Shared initialization for all esp32 modules.
uint32_t ControllerMicroSDLog(const char *msg, const char *base)
Append a line of plain text to the log file on the microSD card.
uint16_t fifo_buffer_len(void)
Get the current number of measurements stored in the buffer.
fram_status fifo_put(const uint8_t *data, const uint8_t num_bytes)
Puts a measurement into the circular buffer.
fram_status fifo_drop(void)
Drops the next measurement in the buffer.
fram_status fifo_peek(size_t idx, uint8_t *data, uint8_t *len)
Peeks at the next measurement in the buffer without removing it.
SensorStatus DecodeSensorMeasurement(const uint8_t *data, const size_t len, SensorMeasurement *meas)
Decodes a sensor measurement from a buffer.
SensorStatus RepeatedSensorMeasurementsSize(Metadata meta, const SensorMeasurement meas[], size_t count, size_t *size)
Gets the size of multiple repeated sensor measurements when encoded.
SensorStatus EncodeRepeatedSensorMeasurements(Metadata meta, const SensorMeasurement meas[], size_t count, uint8_t *buffer, size_t size, size_t *length)
Encodes multiple sensor measurements into a buffer.
void PrintSensorMeasurement(const SensorMeasurement *m)
UserConfigStatus UserConfigBytes(uint8_t *buffer, uint16_t *length)
Gets encoded bytes from userconfig.
int lorawan_timesync(void)
int lorawan_upload(uint8_t *buffer, int length)
int lorawan_heartbeat(void)
void ulog_prefix_handler(ulog_event *ev, char *prefix, size_t prefix_size)
Callback to add prefix to ulog messages.
MicroSD interface implementation with the esp32.
Library for sensor measurement encoding/decoding.
Controls the user config webserver.
void UserConfigUpdateFromServer(void)
void UserConfigStart(uint32_t retry_ms)
Starts the user config webserver.