Skip to content

Instantly share code, notes, and snippets.

@dt
Last active March 30, 2019 20:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dt/f730abebb7c212fe71288057bd50fa13 to your computer and use it in GitHub Desktop.
Save dt/f730abebb7c212fe71288057bd50fa13 to your computer and use it in GitHub Desktop.
google logging co2 sensor
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <ArduinoOTA.h>
#include "HTTPSRedirect.h"
#include <SoftwareSerial.h>
byte cmdRead[2] = {0x86, 0x00};
byte cmdCalibrateZero[2] = {0x87, 0x00};
byte cmdEnableABC[2] = {0x79, 0xA0};
byte cmdDisableABC[2] = {0x79, 0x00};
byte cmdReset[2] = {0x8d, 0x00};
const int rx_pin = 4;
const int tx_pin = 5;
SoftwareSerial sensor(rx_pin, tx_pin, false, 256);
const char* ssid = "";
const char* password = "";
ESP8266WebServer server ( 80 );
const char* googleHost = "script.google.com";
const char *GScriptId = "AKfycbzbWIhqi9Dd2ofP7-OA8i2xWcDNyjFbPUMKcaLIKP-XWrhTn_Mo";
String googleUrl = String("/macros/s/") + GScriptId + "/exec";
// echo | openssl s_client -connect script.google.com:443 |& openssl x509 -fingerprint -noout
const char* fingerprint = "C2:00:62:1D:F7:ED:AF:8B:D1:D5:1D:24:D6:F0:A1:3A:EB:F1:B4:92";
// Write to Google Spreadsheet
void setup(void)
{
Serial.begin(115200);
delay(100);
sensor.begin(9600); // init CO2 sensor serial port
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.on ( "/", handleRoot );
server.begin();
Serial.println("webserver started");
MDNS.addService("http", "tcp", 80);
ArduinoOTA.setHostname("co2");
ArduinoOTA.begin();
delay(5000);
sendCmd(cmdDisableABC);
}
void handleRoot() {
String page = String(
"<html><head><meta charset='utf-8'/>"
"<meta http-equiv=\"refresh\" content=\"60\" />"
"<title>Sniffer</title>"
"<link href='https://fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet'/>"
"<style>"
"body { font-family: Helvetica, Arial, Sans-Serif; background-color: #eee; }"
"</style>"
"<meta name='viewport' content='width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable=0'>"
"</head>"
"<body>\n"
"<div class='sniffer'>\n"
"<p>CO2: "+String(sendCmd(cmdRead)) +" ppm </p>"
"</div>" // /stc
"</body></html>"
);
server.send(200, "text/html", page);
}
void logToGoogle() {
int ppm = sendCmd(cmdRead);
Serial.print("CO2: ");
Serial.print(ppm);
Serial.println("ppm");
if (ppm < 1) {
return;
}
HTTPSRedirect* client = new HTTPSRedirect();
client->setPrintResponseBody(true);
client->setContentTypeHeader("application/json");
client->connect(googleHost, 443);
client->POST(googleUrl, googleHost, String("{\"co2\": "+String(ppm)+"}"), true);
delete client;
}
unsigned long lastReport;
unsigned long nextReport;
uint32 ticks;
void loop() {
ArduinoOTA.handle();
server.handleClient();
ticks++;
if (ticks > 10000) {
ticks = 0;
unsigned long now = millis();
if (now > nextReport || now < lastReport) {
nextReport = now + 1000 * 30;
logToGoogle();
lastReport = now;
}
}
}
byte checksum(byte *array)
{
byte checksum = 0;
for (byte i = 1; i < 8; i++)
checksum+=array[i];
checksum = 0xFF - checksum;
return (checksum+1);
}
unsigned int sendCmd(byte* cmd) {
byte req[9];
memset(req, 0, 9);
req[0] = 0xFF;
req[1] = 0x01;
req[2] = cmd[0];
req[3] = cmd[1];
req[8] = checksum(req);
bool header_found = false;
sensor.write(req, 9);
if (cmd[0] != cmdRead[0]) {
return 0;
}
// read until we see the first two bytes of the reply.
while (sensor.available() && (!header_found)) {
if (sensor.read() == 0xff ) {
if (sensor.read() == 0x86 ) {
header_found = true;
}
}
}
if (!header_found) {
Serial.println("conn closed before header not found");
return 0;
}
// already read first two bytes while looking for the beginning so
// a) put those in the buffer so the checksum matches
// b) read the remaining 9-2=7 bytes into the buffer.
unsigned char resp[9];
memset(resp, 0, 9);
resp[0] = 0xff;
resp[1] = 0x86;
sensor.readBytes(&resp[2], 7);
// Check that the checksum matches.
byte crc = checksum(resp);
if ( !(resp[8] == crc) ) {
Serial.println(String("CO2: CRC error: ") + String(crc) + String(" vs ") + String(resp[8]));
return 0;
}
// Compute the result.
unsigned int ppmHigh = (unsigned int) resp[2];
unsigned int ppmLow = (unsigned int) resp[3];
unsigned int ppm = (256 * ppmHigh) + ppmLow;
return ppm;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment