Skip to content

Commit

Permalink
Update to latest Prom library
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanahuckova committed Jun 15, 2021
1 parent 44ad365 commit e5298de
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 102 deletions.
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,30 @@ To start, review and follow steps in the **[Grafana DIY IoT repo](https://github

To build this system, you will need:

- **1 [Arduino MKR Wifi 1010](https://store.arduino.cc/arduino-mkr-wifi-1010)** development board
- **1 [Waveshare Sharp GP2Y1010AU0F](https://www.waveshare.com/dust-sensor.htm)** sensor for PM paricles
- **1 [Flame sensor](https://www.electronicshub.org/arduino-flame-sensor-interface/)** to detect flame
- **1 [Arduino MKR Wifi 1010](https://store.arduino.cc/arduino-mkr-wifi-1010)** development board
- **F-F, M-F && M-M Dupont cables**
- **1[L298N DC motor driver](https://lastminuteengineers.com/l298n-dc-stepper-driver-arduino-tutorial/)** to control DC motor
- **1 DC motor**
- **1 9V battery**
- **1 9V battery clip**
- **1 micro USB cable**
- **1 USB charger**
- **F-F, M-F && M-M Dupont cables**

Plus:

- **Box or stand** to put this all together and build the monitoring system

<img src="imgs/developing.JPG" width="700" title="Image of hardware">

## Libraries:

- **ArduinoBearSSL** by Arduino
- **ArduinoHttpClient** by Arduino
- **PrometheusArduino** by Ed Welch
- **PromLokiTransport** by Ed Welch
- **SnappyProto** by Ed Welch

## Circuit & Wiring diagrams

Expand All @@ -41,7 +50,6 @@ Download this repo that includes the software for room comfort monitoring. Updat

## Extinguishing candle from Grafana

This repo contains simple server that stores information if the lid that puts of the candle has been closed or open. This can be simply hosted trough [Heroku platform](https://dashboard.heroku.com/) or whatever you prefer. In config.h add the client and secret (if secret is used).
This repo contains simple server that stores information if the lid that puts of the candle has been closed or open. This can be simply hosted trough [Heroku platform](https://dashboard.heroku.com/) or whatever you prefer. In config.h add the client and secret (if secret is used).

In Grafana, use the [Button panel](https://grafana.com/grafana/plugins/cloudspout-button-panel/) to send request to open/close the candle monitoring.

2 changes: 1 addition & 1 deletion WaveshareSharpDustSensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define SYS_VOLTAGE 3300
class WaveshareSharpDustSensor{
public:
WaveshareSharpDustSensor::WaveshareSharpDustSensor();
WaveshareSharpDustSensor();
float density;
float voltage;
int Filter(int m);
Expand Down
205 changes: 111 additions & 94 deletions candle_monitoring_grafana.ino
Original file line number Diff line number Diff line change
@@ -1,96 +1,98 @@
#include <Arduino.h>
#include <WiFiNINA.h>
#include <SPI.h>
#include <NTPClient.h>
#include <ArduinoHttpClient.h>
#include <PromLokiTransport.h>
#include <PrometheusArduino.h>
#include "WaveshareSharpDustSensor.h"

#include "config.h"
#include "certificates.h"

//Wifi and http clients
//Http client
WiFiClient wifi;
WiFiUDP ntpUDP;
HttpClient lokiClient = HttpClient(wifi, LOKI_CLIENT, 80);
HttpClient candleClient = HttpClient(wifi, CANDLE_CLIENT, 80);
NTPClient ntpClient(ntpUDP);

char ssid[] = WIFI_SSID;
char pass[] = WIFI_PASSWORD;
// Prometheus client and transport
PromLokiTransport transport;
PromClient client(transport);

// Create a write request for 2 series.
WriteRequest req(2,1024);

// Define a TimeSeries which can hold up to 5 samples
TimeSeries ts1(5, "flame_value", "{monitoring_type=\"candle\",board_type=\"arduino_mkr1010\",room=\"living_room\"}");
TimeSeries ts2(5, "dust_density", "{monitoring_type=\"candle\",board_type=\"arduino_mkr1010\",room=\"living_room\"}");

//Sensors
WaveshareSharpDustSensor dustSensor;

//Previous state of candle
// Global variables
bool prevCandleIsOpen;
int loopCounter = 0;

//Setup
void setup(void)
{
pinMode(DUST_SENSOR_LED, OUTPUT);
digitalWrite(DUST_SENSOR_LED, LOW);
pinMode(FLAME_SENSOR, INPUT);
pinMode(TOUCH_SENSOR, INPUT);
pinMode(MOTOR_A, OUTPUT);
pinMode(MOTOR_B, OUTPUT);
Serial.begin(9600);
while (!Serial) {
Serial.begin(9600);

setupClient();
setupWiFi();

; // wait for serial port to connect. Needed for native USB port only

}
setupWiFi();

// Initialize a NTPClient to get time
ntpClient.begin();
prevCandleIsOpen = getIsOpen();
// goDown(1000);

prevCandleIsOpen = getIsOpen(false);
}

void loop(void) {

// Reconnect to WiFi if required
if (WiFi.status() != WL_CONNECTED) {
WiFi.disconnect();
yield();
setupWiFi();
}

// Update time via NTP if required
while (!ntpClient.update()) {
yield();
ntpClient.forceUpdate();
}
//Get current timestamp
unsigned long timestamp = ntpClient.getEpochTime();

int64_t time;
time = transport.getTimeMillis();

//Get current open/close state of candle
bool candleIsOpen = getIsOpen();
bool candleIsOpen = getIsOpen(prevCandleIsOpen);

//Get values from sensors
float dustDensity = getDustValue();
int flameValue = getFlameValue();
int touchValue = digitalRead(TOUCH_SENSOR);

//Handle opening and closing if necssary
handleOpeningAndClosing(candleIsOpen, prevCandleIsOpen, touchValue);

//Send data to Loki
submitToLoki(timestamp, flameValue, dustDensity);
handleOpeningAndClosing(candleIsOpen, prevCandleIsOpen);

//Set prevCandleIsOpen
//Set prevCandleIsOpen
prevCandleIsOpen = candleIsOpen;
delay(2000);

//Send data to Prometheus
if (loopCounter >= 5) {
//Send
loopCounter = 0;
PromClient::SendResult res = client.send(req);
if (!res == PromClient::SendResult::SUCCESS) {
Serial.println(client.errmsg);
}

// Reset batches after a succesful send.
ts1.resetSamples();
ts2.resetSamples();
} else {
if (!ts1.addSample(time, flameValue)) {
Serial.println(ts1.errmsg);
}
if (!ts2.addSample(time, dustDensity)) {
Serial.println(ts2.errmsg);
}
loopCounter++;
}


delay(INTERVAL * 1000);
}

//Helper functions
void setupWiFi() {
Serial.print("Connecting to '");
Serial.print(WIFI_SSID);
Serial.print("' ...");
Serial.print("Connecting to wifi ...'");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

while (WiFi.status() != WL_CONNECTED) {
delay(10000);
delay(5000);
Serial.print(".");
}

Expand All @@ -99,6 +101,45 @@ void setupWiFi() {
Serial.println(WiFi.localIP());
}

// Function to set up Prometheus client
void setupClient() {
Serial.println("Setting up client...");

uint8_t serialTimeout;
while (!Serial && serialTimeout < 50) {
delay(100);
serialTimeout++;
}

// Configure and start the transport layer
transport.setUseTls(true);
transport.setCerts(grafanaCert, strlen(grafanaCert));
transport.setWifiSsid(WIFI_SSID);
transport.setWifiPass(WIFI_PASSWORD);
transport.setDebug(Serial); // Remove this line to disable debug logging of the client.
if (!transport.begin()) {
Serial.println(transport.errmsg);
while (true) {};
}

// Configure the client
client.setUrl(GC_PROM_URL);
client.setPath(GC_PROM_PATH);
client.setPort(GC_PORT);
client.setUser(GC_PROM_USER);
client.setPass(GC_PROM_PASS);
client.setDebug(Serial); // Remove this line to disable debug logging of the client.
if (!client.begin()) {
Serial.println(client.errmsg);
while (true) {};
}

// Add our TimeSeries to the WriteRequest
req.addTimeSeries(ts1);
req.addTimeSeries(ts2);
req.setDebug(Serial); // Remove this line to disable debug logging of the write request serialization and compression.
}

float getDustValue() {
digitalWrite(DUST_SENSOR_LED, HIGH);
delayMicroseconds(280);
Expand All @@ -112,54 +153,50 @@ float getDustValue() {
}

int getFlameValue() {
int flameValue = digitalRead(FLAME_SENSOR);
if (flameValue == 0) {
return 1;
int flameValue = analogRead(FLAME_SENSOR);
if (flameValue < 200) {
return 1;
}
return 0;

}
void openCandle() {
Serial.println("Opening candle");
void closeCandle() {
Serial.println("Closing candle");
digitalWrite(MOTOR_A, LOW);
digitalWrite(MOTOR_B, HIGH);
delay(4700);
delay(4000);
digitalWrite(MOTOR_B, LOW);
}

void closeCandle() {
Serial.println("Closing candle");
void openCandle() {
Serial.println("Opening candle");
digitalWrite(MOTOR_A, HIGH);
digitalWrite(MOTOR_B, LOW);
delay(4700);
delay(4000);
digitalWrite(MOTOR_A, LOW);
}

bool getIsOpen() {
bool getIsOpen(bool prevValue) {
candleClient.get("/status");
String response = candleClient.responseBody();
if(response.indexOf("1") > 0) {
Serial.println("candle is open");
return true;
}
if(response.indexOf("0") > 0) {
} else if(response.indexOf("0") > 0) {
Serial.println("candle is closed");
return false;
} else {
return prevValue;
}

}

void toggleCandle() {
String path = String("/toggle?secret=") + CANDLE_SECRET;
candleClient.get(path);
}

void handleOpeningAndClosing(bool candleIsOpen, bool prevCandleIsOpen, bool touched) {
Serial.print("prevCandleIsOpen: ");
Serial.print(prevCandleIsOpen);
Serial.println("");
Serial.print("candleIsOpen: ");
Serial.print(candleIsOpen);
Serial.println("");
void handleOpeningAndClosing(bool candleIsOpen, bool prevCandleIsOpen) {
if (prevCandleIsOpen != candleIsOpen) {
if (candleIsOpen) {
openCandle();
Expand All @@ -169,37 +206,17 @@ void handleOpeningAndClosing(bool candleIsOpen, bool prevCandleIsOpen, bool touc
}
}

void submitToLoki(unsigned long ts, int flameValue, float dustDensity )
{
String body = String("{\"streams\": [{ \"stream\": { \"candle_id\": \"1\", \"monitoring_type\": \"candle\"}, \"values\": [ [ \"") + ts + "000000000\", \"" + "PMparticles=" + dustDensity + " flame=" + flameValue + "\" ] ] }]}";
lokiClient.beginRequest();
lokiClient.post("/loki/api/v1/push");
lokiClient.sendHeader("Authorization", LOKI_TOKEN);
lokiClient.sendHeader("Content-Type", "application/json");
lokiClient.sendHeader("Content-Length", String(body.length()));
lokiClient.beginBody();
lokiClient.print(body);
lokiClient.endRequest();

// Read the status code and body of the response
int statusCode = lokiClient.responseStatusCode();
Serial.print("Status code: ");
Serial.println(statusCode);
}

void goDown(int sec) {
void goUp(int sec) {
digitalWrite(MOTOR_A, HIGH);
digitalWrite(MOTOR_B, LOW);
delay(sec);
digitalWrite(MOTOR_A, LOW);
}

void goUp(int sec) {
void goDown(int sec) {
digitalWrite(MOTOR_B, HIGH);
digitalWrite(MOTOR_A, LOW);
delay(sec);
digitalWrite(MOTOR_B, LOW);
}



Loading

0 comments on commit e5298de

Please sign in to comment.