mongoose/examples/CC3200/data.c

184 lines
5.2 KiB
C
Raw Normal View History

/*
* Copyright (c) 2014-2016 Cesanta Software Limited
* All rights reserved
*/
#include "data.h"
#include <stdio.h>
#include <stdlib.h>
#include "gpio_if.h"
#include "bm222.h"
#include "tmp006.h"
struct temp_data {
double ts;
double volt;
double temp;
};
struct conn_state {
struct temp_data td;
double last_sent_td;
unsigned char led;
double last_sent_led;
double last_sent_acc;
};
static int s_tmp006_addr;
static struct temp_data s_temp_data;
static struct bm222_ctx *s_accel_ctx;
void data_init_sensors(int tmp006_addr, int bm222_addr) {
s_tmp006_addr = tmp006_addr;
if (!tmp006_init(tmp006_addr, TMP006_CONV_2, false)) {
LOG(LL_ERROR, ("Failed to init temperature sensor"));
} else {
LOG(LL_INFO, ("Temperature sensor initialized"));
}
s_accel_ctx = bm222_init(bm222_addr);
if (s_accel_ctx == NULL) {
LOG(LL_ERROR, ("Failed to init accelerometer"));
} else {
LOG(LL_INFO, ("Accelerometer initialized"));
}
}
void data_collect() {
double volt = tmp006_read_sensor_voltage(s_tmp006_addr);
double temp = tmp006_read_die_temp(s_tmp006_addr);
if (volt != TMP006_INVALID_READING && temp != TMP006_INVALID_READING) {
s_temp_data.temp = temp;
s_temp_data.volt = volt;
s_temp_data.ts = mg_time();
LOG(LL_DEBUG, ("V = %lf mV, T = %lf C", volt, temp));
}
bm222_get_data(s_accel_ctx);
}
static void send_temp(struct mg_connection *nc, const struct temp_data *td) {
if (td->ts == 0) return;
mg_printf_websocket_frame(nc, WEBSOCKET_OP_TEXT,
"{\"t\": 0, \"ts\": %lf, \"sv\": %lf, \"dt\": %lf}",
td->ts, td->volt, td->temp);
}
static void send_led(struct mg_connection *nc, double ts, unsigned char led) {
if (ts == 0) return;
mg_printf_websocket_frame(nc, WEBSOCKET_OP_TEXT,
"{\"t\": 1, \"ts\": %lf, \"v\": %d}", ts, led);
}
static void send_acc_sample(struct mg_connection *nc,
const struct bm222_sample *s) {
if (s->ts == 0) return;
mg_printf_websocket_frame(
nc, WEBSOCKET_OP_TEXT,
"{\"t\": 2, \"ts\": %lf, \"x\": %d, \"y\": %d, \"z\": %d}", s->ts, s->x,
s->y, s->z);
}
static double send_acc_data_since(struct mg_connection *nc,
const struct bm222_ctx *ctx, double since) {
int i = (ctx->last_index + 1) % BM222_NUM_SAMPLES, n = BM222_NUM_SAMPLES;
double last_sent_ts = 0;
for (; n > 0; i = (i + 1) % BM222_NUM_SAMPLES, n--) {
const struct bm222_sample *s = ctx->data + i;
if (s->ts <= since) continue;
send_acc_sample(nc, s);
last_sent_ts = s->ts;
}
return last_sent_ts;
}
static void process_command(struct mg_connection *nc, unsigned char *data,
size_t len) {
// TODO(lsm): use proper JSON parser
int cmd, n, val;
double t;
if (sscanf((char *) data, "{\t\": %d, \"ts\": %lf, %n", &cmd, &t, &n) != 2) {
LOG(LL_ERROR, ("Invalid command: %.*s", (int) len, data));
return;
}
if (t == 1) {
if (sscanf((char *) data + n, "\"v\": %d", &val) != 1) {
LOG(LL_ERROR, ("Missing value: %.*s", (int) len, data));
return;
}
switch (val) {
case '0': {
GPIO_IF_LedOff(MCU_RED_LED_GPIO);
break;
}
case '1': {
GPIO_IF_LedOn(MCU_RED_LED_GPIO);
break;
}
case '2': {
GPIO_IF_LedToggle(MCU_RED_LED_GPIO);
break;
}
default: {
LOG(LL_ERROR, ("Invalid value: %.*s", (int) len, data));
return;
}
}
} else {
LOG(LL_ERROR, ("Unknown command: %.*s", (int) len, data));
return;
}
}
void data_conn_handler(struct mg_connection *nc, int ev, void *ev_data) {
struct conn_state *cs = (struct conn_state *) nc->user_data;
if (cs == NULL) {
cs = (struct conn_state *) calloc(1, sizeof(*cs));
nc->user_data = cs;
}
switch (ev) {
case MG_EV_POLL:
case MG_EV_TIMER: {
const double now = mg_time();
const unsigned char led = GPIO_IF_LedStatus(MCU_RED_LED_GPIO);
/* Send if there was a change or repeat last data every second. */
if (s_temp_data.volt != cs->td.volt || s_temp_data.temp != cs->td.temp ||
now > cs->last_sent_td + 1.0) {
memcpy(&cs->td, &s_temp_data, sizeof(cs->td));
send_temp(nc, &cs->td);
cs->last_sent_td = now;
}
if (led != cs->led || now > cs->last_sent_led + 1.0) {
send_led(nc, now, led);
cs->led = led;
cs->last_sent_led = now;
}
if (s_accel_ctx != NULL) {
const struct bm222_sample *ls =
s_accel_ctx->data + s_accel_ctx->last_index;
if (cs->last_sent_acc == 0) {
send_acc_sample(nc, ls);
cs->last_sent_acc = ls->ts;
} else {
double last_sent_ts =
send_acc_data_since(nc, s_accel_ctx, cs->last_sent_acc);
if (last_sent_ts > 0) cs->last_sent_acc = last_sent_ts;
}
}
nc->ev_timer_time = now + 0.05;
break;
}
case MG_EV_WEBSOCKET_FRAME: {
struct websocket_message *wm = (struct websocket_message *) ev_data;
process_command(nc, wm->data, wm->size);
break;
}
case MG_EV_CLOSE: {
LOG(LL_INFO, ("%p closed", nc));
free(cs);
break;
}
}
}