Statistics
| Branch: | Tag: | Revision:

mongoose / examples / CC3200 / data.c @ eaef5bd1

History | View | Annotate | Download (5.04 KB)

1
/*
2
 * Copyright (c) 2014-2016 Cesanta Software Limited
3
 * All rights reserved
4
 */
5

    
6
#include "data.h"
7

    
8
#include <stdio.h>
9
#include <stdlib.h>
10

    
11
#include "gpio_if.h"
12

    
13
#include "bm222.h"
14
#include "tmp006.h"
15
#include "cs_dbg.h"
16

    
17
struct temp_data {
18
  double ts;
19
  double volt;
20
  double temp;
21
};
22

    
23
struct conn_state {
24
  struct temp_data td;
25
  double last_sent_td;
26
  unsigned char led;
27
  double last_sent_led;
28
  double last_sent_acc;
29
};
30

    
31
static int s_tmp006_addr;
32
static struct temp_data s_temp_data;
33
static struct bm222_ctx *s_accel_ctx;
34

    
35
void data_init_sensors(int tmp006_addr, int bm222_addr) {
36
  s_tmp006_addr = tmp006_addr;
37
  if (!tmp006_init(tmp006_addr, TMP006_CONV_2, false)) {
38
    LOG(LL_ERROR, ("Failed to init temperature sensor"));
39
  } else {
40
    LOG(LL_INFO, ("Temperature sensor initialized"));
41
  }
42
  s_accel_ctx = bm222_init(bm222_addr);
43
  if (s_accel_ctx == NULL) {
44
    LOG(LL_ERROR, ("Failed to init accelerometer"));
45
  } else {
46
    LOG(LL_INFO, ("Accelerometer initialized"));
47
  }
48
}
49

    
50
void data_collect(void) {
51
  double volt = tmp006_read_sensor_voltage(s_tmp006_addr);
52
  double temp = tmp006_read_die_temp(s_tmp006_addr);
53
  if (volt != TMP006_INVALID_READING && temp != TMP006_INVALID_READING) {
54
    s_temp_data.temp = temp;
55
    s_temp_data.volt = volt;
56
    s_temp_data.ts = mg_time();
57
    LOG(LL_DEBUG, ("V = %lf mV, T = %lf C", volt, temp));
58
  }
59
  bm222_get_data(s_accel_ctx);
60
}
61

    
62
static void send_temp(struct mg_connection *nc, const struct temp_data *td) {
63
  if (td->ts == 0) return;
64
  mg_printf_websocket_frame(nc, WEBSOCKET_OP_TEXT,
65
                            "{\"t\": 0, \"ts\": %lf, \"sv\": %lf, \"dt\": %lf}",
66
                            td->ts, td->volt, td->temp);
67
}
68

    
69
static void send_led(struct mg_connection *nc, double ts, unsigned char led) {
70
  if (ts == 0) return;
71
  mg_printf_websocket_frame(nc, WEBSOCKET_OP_TEXT,
72
                            "{\"t\": 1, \"ts\": %lf, \"v\": %d}", ts, led);
73
}
74

    
75
static void send_acc_sample(struct mg_connection *nc,
76
                            const struct bm222_sample *s) {
77
  if (s->ts == 0) return;
78
  mg_printf_websocket_frame(
79
      nc, WEBSOCKET_OP_TEXT,
80
      "{\"t\": 2, \"ts\": %lf, \"x\": %d, \"y\": %d, \"z\": %d}", s->ts, s->x,
81
      s->y, s->z);
82
}
83

    
84
static double send_acc_data_since(struct mg_connection *nc,
85
                                  const struct bm222_ctx *ctx, double since) {
86
  int i = (ctx->last_index + 1) % BM222_NUM_SAMPLES, n = BM222_NUM_SAMPLES;
87
  double last_sent_ts = 0;
88
  for (; n > 0; i = (i + 1) % BM222_NUM_SAMPLES, n--) {
89
    const struct bm222_sample *s = ctx->data + i;
90
    if (s->ts <= since) continue;
91
    send_acc_sample(nc, s);
92
    last_sent_ts = s->ts;
93
  }
94
  return last_sent_ts;
95
}
96

    
97
static void process_command(struct mg_connection *nc, unsigned char *data,
98
                            size_t len) {
99
  // TODO(lsm): use proper JSON parser
100
  int cmd, val;
101
  if (sscanf((char *) data, "{\"t\":%d,\"v\":%d}", &cmd, &val) != 2) {
102
    LOG(LL_ERROR, ("Invalid request: %.*s", (int) len, data));
103
    return;
104
  }
105
  if (cmd == 1) {
106
    switch (val) {
107
      case '0': {
108
        GPIO_IF_LedOff(MCU_RED_LED_GPIO);
109
        break;
110
      }
111
      case '1': {
112
        GPIO_IF_LedOn(MCU_RED_LED_GPIO);
113
        break;
114
      }
115
      case '2': {
116
        GPIO_IF_LedToggle(MCU_RED_LED_GPIO);
117
        break;
118
      }
119
      default: {
120
        LOG(LL_ERROR, ("Invalid value: %.*s", (int) len, data));
121
        return;
122
      }
123
    }
124
  } else {
125
    LOG(LL_ERROR, ("Unknown command: %.*s", (int) len, data));
126
    return;
127
  }
128
}
129

    
130
void data_conn_handler(struct mg_connection *nc, int ev, void *ev_data) {
131
  struct conn_state *cs = (struct conn_state *) nc->user_data;
132
  if (cs == NULL) {
133
    cs = (struct conn_state *) calloc(1, sizeof(*cs));
134
    nc->user_data = cs;
135
  }
136
  switch (ev) {
137
    case MG_EV_POLL:
138
    case MG_EV_TIMER: {
139
      const double now = mg_time();
140
      const unsigned char led = GPIO_IF_LedStatus(MCU_RED_LED_GPIO);
141
      /* Send if there was a change or repeat last data every second. */
142
      if (s_temp_data.volt != cs->td.volt || s_temp_data.temp != cs->td.temp ||
143
          now > cs->last_sent_td + 1.0) {
144
        memcpy(&cs->td, &s_temp_data, sizeof(cs->td));
145
        send_temp(nc, &cs->td);
146
        cs->last_sent_td = now;
147
      }
148
      if (led != cs->led || now > cs->last_sent_led + 1.0) {
149
        send_led(nc, now, led);
150
        cs->led = led;
151
        cs->last_sent_led = now;
152
      }
153
      if (s_accel_ctx != NULL) {
154
        const struct bm222_sample *ls =
155
            s_accel_ctx->data + s_accel_ctx->last_index;
156
        if (cs->last_sent_acc == 0) {
157
          send_acc_sample(nc, ls);
158
          cs->last_sent_acc = ls->ts;
159
        } else {
160
          double last_sent_ts =
161
              send_acc_data_since(nc, s_accel_ctx, cs->last_sent_acc);
162
          if (last_sent_ts > 0) cs->last_sent_acc = last_sent_ts;
163
        }
164
      }
165
      nc->ev_timer_time = now + 0.05;
166
      break;
167
    }
168
    case MG_EV_WEBSOCKET_FRAME: {
169
      struct websocket_message *wm = (struct websocket_message *) ev_data;
170
      process_command(nc, wm->data, wm->size);
171
      break;
172
    }
173
    case MG_EV_CLOSE: {
174
      LOG(LL_INFO, ("%p closed", nc));
175
      free(cs);
176
      break;
177
    }
178
  }
179
}