Created
September 4, 2024 15:58
-
-
Save rdlauer/6fdef0866439690153d3d5149fb46107 to your computer and use it in GitHub Desktop.
Supervised Anomaly Detection with Edge Impulse, Blues, Datacake, and Twilio
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <Wire.h> | |
#include <Adafruit_Sensor.h> | |
#include <Adafruit_ADXL343.h> | |
#include <Edge_Impulse_Imagine_2024_inferencing.h> // your ML library referenced here! | |
#include <Adafruit_SSD1327.h> | |
#include <Notecard.h> | |
#define DEBUG true | |
#define OLED_RESET -1 | |
#define productUID "com.something.something" // your Notehub project! | |
static bool debug_nn = false; | |
uint8_t last_inference = -1; | |
HardwareSerial stlinkSerial(PIN_VCP_RX, PIN_VCP_TX); | |
Adafruit_ADXL343 accel = Adafruit_ADXL343(12345); | |
Adafruit_SSD1327 display(128, 128, &Wire, OLED_RESET, 1000000); | |
Notecard notecard; | |
float voltage = 0.0; | |
float temperature = 0.0; | |
int rssi = 0; | |
int bars = 0; | |
const unsigned char blues_logo[] PROGMEM = { | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, | |
0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, | |
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, | |
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, | |
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, | |
0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xff, | |
0xff, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, | |
0x00, 0x07, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x01, 0xff, | |
0xff, 0xf8, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfc, 0x00, | |
0x00, 0x00, 0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x0f, | |
0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfc, 0x00, | |
0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, | |
0x01, 0xff, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
0xc0, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x00, | |
0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xff, 0x80, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, | |
0xff, 0xf8, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xf8, 0x00, | |
0x01, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xf8, | |
0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xf8, 0x00, 0xff, 0xff, | |
0xff, 0xff, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, | |
0x00, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xfe, | |
0x00, 0x07, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0xfe, 0x00, 0x07, 0xff, | |
0xe0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0xfe, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, | |
0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, | |
0xf8, 0x00, 0x3f, 0xff, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, | |
0xff, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0x00, 0x0f, | |
0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x00, 0x0f, 0xff, 0x80, 0x01, | |
0xff, 0xf8, 0x01, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x00, 0x1f, 0xff, 0x80, 0x01, 0xff, 0xf0, 0x00, | |
0xff, 0xf8, 0x00, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x01, 0xff, 0xf0, 0x00, 0xff, 0xf8, 0x00, | |
0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x01, 0xff, 0xf0, 0x00, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x80, | |
0x1f, 0xff, 0x80, 0x01, 0xff, 0xf0, 0x00, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, | |
0x01, 0xff, 0xf0, 0x00, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x01, 0xff, 0xf0, | |
0x00, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x01, 0xff, 0xf0, 0x00, 0xff, 0xf8, | |
0x00, 0x1f, 0xff, 0x80, 0x1f, 0xff, 0x80, 0x01, 0xff, 0xf0, 0x00, 0xff, 0xf8, 0x00, 0x1f, 0xff, | |
0x80, 0x1f, 0xff, 0x80, 0x01, 0xff, 0xf0, 0x00, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x80, 0x1f, 0xff, | |
0x80, 0x01, 0xff, 0xf0, 0x00, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x80, 0x0f, 0xff, 0x80, 0x01, 0xff, | |
0xf8, 0x01, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0x00, 0x0f, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, | |
0xf8, 0x00, 0x1f, 0xff, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, | |
0xff, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0x00, 0x0f, | |
0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0x00, 0x0f, 0xff, 0xc0, 0x01, | |
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0x00, 0x07, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xff, | |
0xff, 0xf8, 0x00, 0x7f, 0xfe, 0x00, 0x07, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, | |
0x7f, 0xfe, 0x00, 0x07, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xfe, 0x00, | |
0x03, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xfe, 0x00, 0x03, 0xff, 0xf8, | |
0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xf8, 0x00, 0xff, 0xff, | |
0xff, 0xff, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xe0, | |
0x03, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xf8, | |
0x00, 0x01, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf8, 0x00, 0x00, 0xff, | |
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0x80, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, | |
0xc0, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, | |
0x1f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xfc, | |
0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00, | |
0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x1f, 0xff, | |
0xfe, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfc, 0x00, 0x00, | |
0x00, 0x01, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, | |
0xff, 0xfe, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0, | |
0x00, 0x7f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, | |
0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, | |
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, | |
0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, | |
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, | |
0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00}; | |
void drawCircles(void); | |
void drawInferenceResult(uint8_t); | |
void setup() | |
{ | |
#ifdef DEBUG | |
stlinkSerial.begin(115200); | |
const size_t usb_timeout_ms = 3000; | |
for (const size_t start_ms = millis(); !stlinkSerial && (millis() - start_ms) < usb_timeout_ms;) | |
; | |
notecard.setDebugOutputStream(stlinkSerial); | |
#endif | |
// initialize notecard | |
notecard.begin(); | |
J *req = notecard.newRequest("hub.set"); | |
if (req != NULL) | |
{ | |
JAddStringToObject(req, "product", productUID); | |
JAddStringToObject(req, "mode", "continuous"); | |
notecard.sendRequestWithRetry(req, 5); | |
} | |
// create template | |
req = notecard.newRequest("note.template"); | |
if (req != NULL) | |
{ | |
JAddStringToObject(req, "file", "alert.qo"); | |
J *body = JCreateObject(); | |
if (body != NULL) | |
{ | |
JAddStringToObject(body, "current_state", "x"); | |
JAddNumberToObject(body, "voltage", 12.1); | |
JAddNumberToObject(body, "temperature", 12.1); | |
JAddNumberToObject(body, "rssi", 12); | |
JAddNumberToObject(body, "bars", 12); | |
JAddItemToObject(req, "body", body); | |
} | |
notecard.sendRequestWithRetry(req, 5); | |
} | |
// OPTIONAL: setting a fixed GPS location just for kicks | |
req = notecard.newRequest("card.location.mode"); | |
if (req != NULL) | |
{ | |
JAddStringToObject(req, "mode", "fixed"); | |
JAddNumberToObject(req, "lat", 37.41440219477441); | |
JAddNumberToObject(req, "lon", -122.07703349318825); | |
} | |
notecard.sendRequestWithRetry(req, 5); | |
// force a sync just in case | |
req = notecard.newRequest("hub.sync"); | |
if (req != NULL) | |
{ | |
notecard.sendRequestWithRetry(req, 5); | |
} | |
// initialize accelerometer | |
if (!accel.begin()) | |
{ | |
#ifdef DEBUG | |
stlinkSerial.println("No accelerometer detected"); | |
#endif | |
while (1) | |
; | |
} | |
accel.setRange(ADXL343_RANGE_16_G); | |
// check that samples per frame is accurate for this model | |
if (EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME != 3) | |
{ | |
#ifdef DEBUG | |
stlinkSerial.println("ERR: EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME should be equal to 3 (the 3 sensor axes)\n"); | |
#endif | |
while (1) | |
; | |
} | |
// initialize display | |
if (!display.begin(0x3D)) | |
{ | |
stlinkSerial.println("Unable to initialize OLED"); | |
while (1) | |
; | |
} | |
display.clearDisplay(); | |
display.display(); | |
// draw some test circles | |
drawCircles(); | |
display.display(); | |
delay(1000); | |
display.setRotation(1); | |
display.clearDisplay(); | |
// display the blues logo | |
display.drawBitmap(13, 30, blues_logo, 100, 100, SSD1327_WHITE); | |
display.display(); | |
} | |
void loop() | |
{ | |
#ifdef DEBUG | |
stlinkSerial.println("\nStarting inferencing in 2 seconds...\n"); | |
#endif | |
delay(2000); | |
#ifdef DEBUG | |
stlinkSerial.println("Sampling...\n"); | |
#endif | |
// Allocate a buffer here for the values we'll read from the IMU | |
float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = {0}; | |
for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix += 3) | |
{ | |
// Determine the next tick (and then sleep later) | |
uint64_t next_tick = micros() + (EI_CLASSIFIER_INTERVAL_MS * 1000); | |
sensors_event_t event; | |
accel.getEvent(&event); | |
buffer[ix] = event.acceleration.x; | |
buffer[ix + 1] = event.acceleration.y; | |
buffer[ix + 2] = event.acceleration.z; | |
delayMicroseconds(next_tick - micros()); | |
} | |
// Turn the raw buffer in a signal which we can the classify | |
signal_t signal; | |
int err = numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal); | |
if (err != 0) | |
{ | |
#ifdef DEBUG | |
stlinkSerial.println("Failed to create signal from buffer"); | |
#endif | |
return; | |
} | |
// Run the classifier | |
ei_impulse_result_t result = {0}; | |
err = run_classifier(&signal, &result, debug_nn); | |
if (err != EI_IMPULSE_OK) | |
{ | |
#ifdef DEBUG | |
stlinkSerial.println("ERR: Failed to run classifier"); | |
#endif | |
return; | |
} | |
// stlinkSerial.println("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)\n", | |
// result.timing.dsp, result.timing.classification, result.timing.anomaly); | |
uint8_t predictionLabel = 0; | |
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) | |
{ | |
#ifdef DEBUG | |
stlinkSerial.print(" "); | |
stlinkSerial.print(result.classification[ix].label); | |
stlinkSerial.print(": "); | |
stlinkSerial.println(result.classification[ix].value); | |
#endif | |
if (result.classification[ix].value > result.classification[predictionLabel].value) | |
predictionLabel = ix; | |
} | |
// print the predictions | |
String label = result.classification[predictionLabel].label; | |
if (label == "off") | |
{ | |
drawInferenceResult(0); | |
} | |
else if (label == "low") | |
{ | |
drawInferenceResult(1); | |
} | |
else if (label == "medium") | |
{ | |
drawInferenceResult(2); | |
} | |
else if (label == "high") | |
{ | |
drawInferenceResult(3); | |
} | |
#ifdef DEBUG | |
stlinkSerial.print("\nPrediction: "); | |
stlinkSerial.println(label); | |
#endif | |
#if EI_CLASSIFIER_HAS_ANOMALY == 1 && DEBUG | |
stlinkSerial.println(" anomaly score: %.3f\n", result.anomaly); | |
#endif | |
} | |
void drawCircles(void) | |
{ | |
for (uint8_t i = 0; i < display.height(); i += 2) | |
{ | |
display.drawCircle(display.width() / 2, display.height() / 2, i, i % 15 + 1); | |
display.display(); | |
} | |
} | |
void drawInferenceResult(uint8_t inference) | |
{ | |
if (inference != last_inference) | |
{ | |
last_inference = inference; | |
// display inference | |
display.clearDisplay(); | |
display.setTextSize(3); | |
display.setTextColor(SSD1327_WHITE); | |
display.setCursor(0, 0); | |
switch (inference) | |
{ | |
case 0: | |
display.println("OFF"); | |
break; | |
case 1: | |
display.println("LOW"); | |
break; | |
case 2: | |
display.println("MEDIUM"); | |
break; | |
case 3: | |
display.println("ALERT!"); | |
break; | |
default: | |
break; | |
} | |
display.display(); | |
// display blues logo | |
display.drawBitmap(13, 30, blues_logo, 100, 100, SSD1327_WHITE); | |
display.display(); | |
// query notecard for voltage reading | |
J *req = notecard.newRequest("card.voltage"); | |
if (req != NULL) | |
{ | |
J *rsp = notecard.requestAndResponse(req); | |
if (rsp && JGetNumber(rsp, "value")) | |
{ | |
voltage = JGetNumber(rsp, "value"); | |
notecard.deleteResponse(rsp); | |
} | |
} | |
// query notecard for last cellular info | |
req = notecard.newRequest("card.wireless"); | |
if (req != NULL) | |
{ | |
J *rsp = notecard.requestAndResponse(req); | |
if (rsp && JGetObject(rsp, "net") && JGetNumber(JGetObject(rsp, "net"), "rssi") && JGetNumber(JGetObject(rsp, "net"), "bars")) | |
{ | |
rssi = JGetNumber(JGetObject(rsp, "net"), "rssi"); | |
bars = JGetNumber(JGetObject(rsp, "net"), "bars"); | |
notecard.deleteResponse(rsp); | |
} | |
} | |
// query notecard for temp reading | |
req = notecard.newRequest("card.temp"); | |
if (req != NULL) | |
{ | |
J *rsp = notecard.requestAndResponse(req); | |
if (rsp && JGetNumber(rsp, "value")) | |
{ | |
temperature = JGetNumber(rsp, "value"); | |
notecard.deleteResponse(rsp); | |
} | |
} | |
// send note | |
req = notecard.newRequest("note.add"); | |
if (req != NULL) | |
{ | |
JAddBoolToObject(req, "sync", true); | |
JAddStringToObject(req, "file", "alert.qo"); | |
J *body = JCreateObject(); | |
if (body != NULL) | |
{ | |
switch (inference) | |
{ | |
case 0: | |
JAddStringToObject(body, "current_state", "OFF"); | |
break; | |
case 1: | |
JAddStringToObject(body, "current_state", "LOW"); | |
break; | |
case 2: | |
JAddStringToObject(body, "current_state", "MEDIUM"); | |
break; | |
case 3: | |
JAddStringToObject(body, "current_state", "ALERT!"); | |
break; | |
default: | |
JAddStringToObject(body, "current_state", "N/A"); | |
break; | |
} | |
JAddNumberToObject(body, "voltage", voltage); | |
JAddNumberToObject(body, "temperature", temperature); | |
JAddNumberToObject(body, "rssi", rssi); | |
JAddNumberToObject(body, "bars", bars); | |
JAddItemToObject(req, "body", body); | |
} | |
notecard.sendRequestWithRetry(req, 5); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment