Skip to content

Instantly share code, notes, and snippets.

@rdlauer
Created September 4, 2024 15:58
Show Gist options
  • Save rdlauer/6fdef0866439690153d3d5149fb46107 to your computer and use it in GitHub Desktop.
Save rdlauer/6fdef0866439690153d3d5149fb46107 to your computer and use it in GitHub Desktop.
Supervised Anomaly Detection with Edge Impulse, Blues, Datacake, and Twilio
#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