Add LED status and accelerator data feed

It is also possible to control LED by sending a command:
  {"t": 1, "v": 0/1/2}
0/1 = off/on, 2 = toggle

PUBLISHED_FROM=da176b70c4cd356c5d56eca58c2926619748d895
This commit is contained in:
Deomid Ryabkov authored and rojer committed 2016-03-25 17:10:57 +00:00
1 parent b6d700077a
commit 41971a95b2
6 files changed
+305 -39

No files matched your search

+157 -34
View File
@@ -4,6 +4,7 @@
*/
#include <malloc.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -21,7 +22,8 @@
#include "uart.h"
#include "utils.h"
#include <stdbool.h>
#include "gpio.h"
#include "gpio_if.h"
#include "i2c_if.h"
#include "simplelink.h"
@@ -30,16 +32,20 @@
#include "oslib/osi.h"
#include "mongoose.h"
#include "bm222.h"
#include "tmp006.h"
#define WIFI_SSID "YourWiFi"
#define WIFI_PASS "YourPassword"
#define DATA_SAMPLING_INTERVAL_MS 20
#define CONSOLE_BAUD_RATE 115200
#define CONSOLE_UART UARTA0_BASE
#define CONSOLE_UART_PERIPH PRCM_UARTA0
#define SYS_CLK 80000000
#define WIFI_SSID "YourWiFi"
#define WIFI_PASS "YourPassword"
#define BM222_ADDR 0x18
#define TMP006_ADDR 0x41
struct sj_event {
@@ -50,6 +56,8 @@ struct sj_event {
OsiMsgQ_t s_v7_q;
struct mg_mgr mg_mgr;
static struct bm222_ctx *s_accel_ctx;
void SimpleLinkWlanEventHandler(SlWlanEvent_t *e) {
if (e->Event == SL_WLAN_CONNECT_EVENT) {
LOG(LL_INFO, ("WiFi: connected"));
@@ -62,8 +70,9 @@ void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *e) {
if (e->Event == SL_NETAPP_IPV4_IPACQUIRED_EVENT) {
SlIpV4AcquiredAsync_t *ed = &e->EventData.ipAcquiredV4;
LOG(LL_INFO, ("IP: %lu.%lu.%lu.%lu", SL_IPV4_BYTE(ed->ip, 3),
SL_IPV4_BYTE(ed->ip, 2), SL_IPV4_BYTE(ed->ip, 1),
SL_IPV4_BYTE(ed->ip, 0)));
SL_IPV4_BYTE(ed->ip, 2), SL_IPV4_BYTE(ed->ip, 1),
SL_IPV4_BYTE(ed->ip, 0)));
GPIO_IF_LedOff(MCU_RED_LED_GPIO);
}
}
@@ -108,7 +117,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *p) {
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
LOG(LL_INFO, ("%p switching to data mode", nc));
nc->handler = data_ev_handler;
nc->ev_timer_time = mg_time(); /* Immediately */
nc->ev_timer_time = mg_time(); /* Immediately */
break;
}
case MG_EV_TIMER: {
@@ -120,50 +129,149 @@ static void ev_handler(struct mg_connection *nc, int ev, void *p) {
s_temp_data.ts = mg_time();
LOG(LL_DEBUG, ("V = %lf mV, T = %lf C", volt, temp));
}
nc->ev_timer_time = mg_time() + 0.05;
bm222_get_data(s_accel_ctx);
nc->ev_timer_time = mg_time() + (DATA_SAMPLING_INTERVAL_MS * 0.001);
}
}
}
struct conn_data {
double last_ts;
double last_temp;
double last_volt;
struct conn_state {
struct temp_data td;
double last_sent_td;
unsigned char led;
double last_sent_led;
double last_sent_acc;
};
static void send_temp(struct mg_connection *nc) {
LOG(LL_DEBUG, ("%p sending temp data", nc));
mg_printf_websocket_frame(
nc, WEBSOCKET_OP_TEXT,
"{\"type\": \"temp\", \"ts\": %lf, \"v\": %lf, \"t\": %lf}",
s_temp_data.ts, s_temp_data.volt, s_temp_data.temp);
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 data_ev_handler(struct mg_connection *nc, int ev, void *p) {
struct conn_data *cd = (struct conn_data *) nc->user_data;
if (cd == NULL) {
cd = (struct conn_data *) calloc(1, sizeof(*cd));
nc->user_data = cd;
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) {
struct json_token *toks = parse_json2((const char *) data, len);
if (toks == NULL) {
LOG(LL_ERROR, ("Invalid command: %.*s", (int) len, data));
return;
}
struct json_token *t = find_json_token(toks, "t");
if (t == NULL) {
LOG(LL_ERROR, ("Missing type field: %.*s", (int) len, data));
goto out_free;
}
if (t->len == 1 && *t->ptr == '1') {
struct json_token *v = find_json_token(toks, "v");
if (v == NULL) {
LOG(LL_ERROR, ("Missing value: %.*s", (int) len, data));
goto out_free;
}
if (v->len != 1) {
LOG(LL_ERROR, ("Invalid value: %.*s", (int) len, data));
goto out_free;
}
switch (*v->ptr) {
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));
goto out_free;
}
}
} else {
LOG(LL_ERROR, ("Unknown command: %.*s", (int) t->len, t->ptr));
goto out_free;
}
out_free:
free(toks);
}
static void data_ev_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 != cd->last_volt ||
s_temp_data.temp != cd->last_temp ||
now > cd->last_ts + 1.0) {
send_temp(nc);
cd->last_ts = now;
cd->last_volt = s_temp_data.volt;
cd->last_temp = s_temp_data.temp;
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(cd);
free(cs);
break;
}
}
@@ -175,8 +283,16 @@ static void mg_task(void *arg) {
osi_MsgQCreate(&s_v7_q, "V7", sizeof(struct sj_event), 32 /* len */);
sl_Start(NULL, NULL, NULL);
if (!tmp006_set_config(TMP006_ADDR, TMP006_CONV_2, false)) {
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"));
}
if (strlen(WIFI_SSID) > 0) {
@@ -212,7 +328,7 @@ static void mg_task(void *arg) {
struct mg_connection *nc = mg_bind(&mg_mgr, "80", ev_handler);
if (nc != NULL) {
mg_set_protocol_http_websocket(nc);
nc->ev_timer_time = mg_time(); /* Start data collection */
nc->ev_timer_time = mg_time(); /* Start data collection */
} else {
LOG(LL_ERROR, ("Failed to create listener: %s", err));
}
@@ -252,6 +368,14 @@ int main() {
MAP_PinTypeI2C(PIN_02, PIN_MODE_1); /* SCL */
I2C_IF_Open(I2C_MASTER_MODE_FST);
/* Set up the red LED. Note that amber and green cannot be used as they share
* pins with I2C. */
MAP_PRCMPeripheralClkEnable(PRCM_GPIOA1, PRCM_RUN_MODE_CLK);
MAP_PinTypeGPIO(PIN_64, PIN_MODE_0, false);
MAP_GPIODirModeSet(GPIOA1_BASE, 0x2, GPIO_DIR_MODE_OUT);
GPIO_IF_LedConfigure(LED1);
GPIO_IF_LedOn(MCU_RED_LED_GPIO);
VStartSimpleLinkSpawnTask(8);
osi_TaskCreate(mg_task, (const signed char *) "mg", 8192, NULL, 3, NULL);
osi_start();
@@ -275,4 +399,3 @@ void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *e,
void SimpleLinkSockEventHandler(SlSockEvent_t *e) {
}