mirror of
https://github.com/revspace/operame
synced 2024-10-31 21:47:30 +00:00
First commit
This commit is contained in:
commit
56d4912e87
3
LICENSE
Normal file
3
LICENSE
Normal file
@ -0,0 +1,3 @@
|
||||
Pick your favourite OSI approved license :)
|
||||
|
||||
http://www.opensource.org/licenses/alphabetical
|
242
operame.ino
Normal file
242
operame.ino
Normal file
@ -0,0 +1,242 @@
|
||||
#define Sprintf(f, ...) ({ char* s; asprintf(&s, f, __VA_ARGS__); String r = s; free(s); r; })
|
||||
#include <WiFi.h>
|
||||
#include <MQTT.h>
|
||||
#include <SPIFFS.h>
|
||||
#include <WiFiSettings.h>
|
||||
#include <MHZ19.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include <SPI.h>
|
||||
#include <TFT_eSPI.h>
|
||||
#include <list>
|
||||
|
||||
using namespace std;
|
||||
|
||||
unsigned long mqtt_interval;
|
||||
const int portalbutton = 35;
|
||||
const int demobutton = 0;
|
||||
bool ota_enabled;
|
||||
int co2_warning;
|
||||
int co2_critical;
|
||||
int co2_blink;
|
||||
|
||||
MQTTClient mqtt;
|
||||
HardwareSerial hwserial1(1);
|
||||
TFT_eSPI display;
|
||||
TFT_eSprite sprite(&display);
|
||||
MHZ19 mhz;
|
||||
String mqtt_topic;
|
||||
String mqtt_template;
|
||||
bool add_units;
|
||||
bool wifi_enabled;
|
||||
bool mqtt_enabled;
|
||||
int max_failures;
|
||||
|
||||
void retain(String topic, String message) {
|
||||
Serial.printf("%s %s\n", topic.c_str(), message.c_str());
|
||||
mqtt.publish(topic, message, true, 0);
|
||||
}
|
||||
|
||||
void display_big(const String& text, int fg = TFT_WHITE, int bg = TFT_BLACK) {
|
||||
sprite.setTextSize(1);
|
||||
bool nondigits = false;
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char c = text.charAt(i);
|
||||
if (c < '0' || c > '9') nondigits = true;
|
||||
}
|
||||
sprite.setTextFont(nondigits ? 4 : 8);
|
||||
sprite.setTextSize(nondigits && text.length() < 10 ? 2 : 1);
|
||||
sprite.setTextDatum(MC_DATUM);
|
||||
sprite.setTextColor(fg, bg);
|
||||
sprite.fillSprite(bg);
|
||||
if (WiFi.status() == WL_CONNECTED)
|
||||
sprite.drawRect(0, 0, display.width(), display.height(), TFT_BLUE);
|
||||
sprite.drawString(text, display.width()/2, display.height()/2);
|
||||
|
||||
sprite.pushSprite(0, 0);
|
||||
}
|
||||
|
||||
|
||||
void setup_ota() {
|
||||
ArduinoOTA.setHostname(WiFiSettings.hostname.c_str());
|
||||
ArduinoOTA.setPassword(WiFiSettings.password.c_str());
|
||||
ArduinoOTA.onStart( []() { display_big("OTA", TFT_BLUE); });
|
||||
ArduinoOTA.onEnd( []() { display_big("OTA done", TFT_GREEN); });
|
||||
ArduinoOTA.onError( [](ota_error_t e) { display_big("OTA failed", TFT_RED); });
|
||||
ArduinoOTA.onProgress([](unsigned int p, unsigned int t) {
|
||||
String pct { (int) ((float) p / t * 100) };
|
||||
display_big(pct + "%");
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
}
|
||||
|
||||
void check_portalbutton() {
|
||||
if (digitalRead(portalbutton)) return;
|
||||
delay(50);
|
||||
if (digitalRead(portalbutton)) return;
|
||||
WiFiSettings.portal();
|
||||
}
|
||||
|
||||
void check_demobutton() {
|
||||
if (digitalRead(demobutton)) return;
|
||||
delay(50);
|
||||
if (digitalRead(demobutton)) return;
|
||||
ppm_demo();
|
||||
}
|
||||
|
||||
void check_buttons() {
|
||||
check_portalbutton();
|
||||
check_demobutton();
|
||||
}
|
||||
|
||||
void display_ppm(int ppm) {
|
||||
int fg, bg;
|
||||
if (ppm >= co2_critical) {
|
||||
fg = TFT_WHITE;
|
||||
bg = TFT_RED;
|
||||
} else if (ppm >= co2_warning) {
|
||||
fg = TFT_BLACK;
|
||||
bg = TFT_YELLOW;
|
||||
} else {
|
||||
fg = TFT_GREEN;
|
||||
bg = TFT_BLACK;
|
||||
}
|
||||
|
||||
if (ppm >= co2_blink && millis() % 2000 < 1000) {
|
||||
std::swap(fg, bg);
|
||||
}
|
||||
display_big(String(ppm), fg, bg);
|
||||
}
|
||||
|
||||
void ppm_demo() {
|
||||
display_big("demo!");
|
||||
delay(3000);
|
||||
for (int p = 400; p < 1200; p++) {
|
||||
display_ppm(p);
|
||||
delay(30);
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Operame start");
|
||||
SPIFFS.begin(true);
|
||||
pinMode(portalbutton, INPUT_PULLUP);
|
||||
pinMode(demobutton, INPUT_PULLUP);
|
||||
pinMode(4, OUTPUT);
|
||||
digitalWrite(4, HIGH);
|
||||
|
||||
display.init();
|
||||
display.fillScreen(TFT_BLACK);
|
||||
display.setRotation(1);
|
||||
sprite.createSprite(display.width(), display.height());
|
||||
|
||||
hwserial1.begin(9600, SERIAL_8N1, 22, 21);
|
||||
mhz.begin(hwserial1);
|
||||
display_big("operame");
|
||||
delay(1000);
|
||||
check_sensor();
|
||||
mhz.setFilter(true, true);
|
||||
mhz.autoCalibration();
|
||||
|
||||
WiFiSettings.hostname = "operame-";
|
||||
wifi_enabled = WiFiSettings.checkbox("operame_wifi", false, "WiFi-verbinding gebruiken");
|
||||
ota_enabled = WiFiSettings.checkbox("operame_ota", false, "Draadloos herprogrammeren inschakelen. (Gebruikt portaalwachtwoord!)") && wifi_enabled;
|
||||
|
||||
WiFiSettings.heading("CO2-niveaus");
|
||||
co2_warning = WiFiSettings.integer("operame_co2_warning", 400, 5000, 700, "Geel vanaf [ppm]");
|
||||
co2_critical = WiFiSettings.integer("operame_co2_critical",400, 5000, 800, "Rood vanaf [ppm]");
|
||||
co2_blink = WiFiSettings.integer("operame_co2_blink", 800, 5000, 800, "Knipperen vanaf [ppm]");
|
||||
|
||||
WiFiSettings.heading("MQTT");
|
||||
mqtt_enabled = WiFiSettings.checkbox("operama_mqtt", false, "Metingen via het MQTT-protocol versturen") && wifi_enabled;
|
||||
String server = WiFiSettings.string("mqtt_server", 64, "", "Broker");
|
||||
int port = WiFiSettings.integer("mqtt_port", 0, 65535, 1883, "Broker TCP-poort");
|
||||
max_failures = WiFiSettings.integer("operame_max_failures", 0, 1000, 10, "Aantal verbindingsfouten voor automatische herstart");
|
||||
mqtt_topic = WiFiSettings.string("operame_mqtt_topic", WiFiSettings.hostname, "Topic");
|
||||
mqtt_interval = 1000UL * WiFiSettings.integer("operame_mqtt_interval", 10, 3600, 60, "Publicatie-interval [s]");
|
||||
mqtt_template = WiFiSettings.string("operame_mqtt_template", "{} PPM", "Berichtsjabloon");
|
||||
WiFiSettings.info("De {} in het sjabloon wordt vervangen door de gemeten waarde.");
|
||||
|
||||
if (ota_enabled) WiFiSettings.onPortal = setup_ota;
|
||||
|
||||
WiFiSettings.onConnect = []() {
|
||||
check_buttons();
|
||||
display_big("Verbinden met WiFi...", TFT_BLUE);
|
||||
return 50;
|
||||
};
|
||||
WiFiSettings.onFailure = []() {
|
||||
display_big("WiFi mislukt!", TFT_RED);
|
||||
delay(2000);
|
||||
};
|
||||
WiFiSettings.onPortal = []() {
|
||||
display_big("Configuratieportal", TFT_BLUE);
|
||||
};
|
||||
WiFiSettings.onPortalWaitLoop = []() {
|
||||
if (ota_enabled) ArduinoOTA.handle();
|
||||
};
|
||||
|
||||
if (wifi_enabled) WiFiSettings.connect(false, 15);
|
||||
|
||||
static WiFiClient wificlient;
|
||||
if (mqtt_enabled) mqtt.begin(server.c_str(), port, wificlient);
|
||||
|
||||
if (ota_enabled) setup_ota();
|
||||
|
||||
display_big(":-)");
|
||||
}
|
||||
|
||||
void connect_mqtt() {
|
||||
if (mqtt.connected()) return; // already/still connected
|
||||
|
||||
static int failures = 0;
|
||||
if (mqtt.connect(WiFiSettings.hostname.c_str())) {
|
||||
failures = 0;
|
||||
} else {
|
||||
failures++;
|
||||
if (failures >= max_failures) ESP.restart();
|
||||
}
|
||||
}
|
||||
|
||||
void check_sensor() {
|
||||
if (mhz.errorCode == RESULT_OK) return;
|
||||
while (1) {
|
||||
delay(1000);
|
||||
mhz.verify();
|
||||
if (mhz.errorCode == RESULT_OK) return;
|
||||
display_big("sensorfout", TFT_RED);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
unsigned long next = millis() + 6000;
|
||||
static unsigned long next_mqtt = 0;
|
||||
|
||||
if (mqtt_enabled) mqtt.loop();
|
||||
|
||||
int CO2 = mhz.getCO2();
|
||||
check_sensor();
|
||||
|
||||
Serial.println(CO2);
|
||||
|
||||
if (CO2) {
|
||||
display_ppm(CO2);
|
||||
|
||||
if (mqtt_enabled && millis() > next_mqtt) {
|
||||
connect_mqtt();
|
||||
String message = mqtt_template;
|
||||
message.replace("{}", String(CO2));
|
||||
retain(mqtt_topic, message);
|
||||
next_mqtt = millis() + mqtt_interval;
|
||||
}
|
||||
} else {
|
||||
display_big("wacht...");
|
||||
}
|
||||
|
||||
while (millis() < next) {
|
||||
if (CO2) display_ppm(CO2); // repeat, for blinking
|
||||
if (ota_enabled) ArduinoOTA.handle();
|
||||
check_buttons();
|
||||
delay(20);
|
||||
}
|
||||
Serial.println(esp_get_free_heap_size());
|
||||
}
|
65
platformio.ini
Normal file
65
platformio.ini
Normal file
@ -0,0 +1,65 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; http://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
src_dir = .
|
||||
default_envs = serial
|
||||
extra_configs = platformio-*.ini
|
||||
|
||||
[env]
|
||||
platform = espressif32
|
||||
board = esp32thing
|
||||
board_build.partitions = default.csv
|
||||
framework = arduino
|
||||
targets = upload
|
||||
monitor_speed = 115200
|
||||
#upload_speed = 460800
|
||||
lib_deps =
|
||||
ESP-WiFiSettings @^3.5
|
||||
MH-Z19
|
||||
TFT_eSPI
|
||||
# MQTT
|
||||
build_flags =
|
||||
-DUSER_SETUP_LOADED=1
|
||||
-DST7789_DRIVER=1
|
||||
-DCGRAM_OFFSET=1
|
||||
-DTFT_WIDTH=135
|
||||
-DTFT_HEIGHT=240
|
||||
-DTFT_MOSI=19
|
||||
-DTFT_SCLK=18
|
||||
-DTFT_CS=5
|
||||
-DTFT_DC=16
|
||||
-DTFT_RST=-23
|
||||
-DTFT_BL=4
|
||||
-DTFT_BACKLIGHT_ON=HIGH
|
||||
-DLOAD_GLCD=1
|
||||
-DLOAD_FONT2=1
|
||||
-DLOAD_FONT4=1
|
||||
-DLOAD_FONT6=1
|
||||
-DLOAD_FONT7=1
|
||||
-DLOAD_FONT8=1
|
||||
-DLOAD_GFXFF=1
|
||||
-DSPI_FREQUENCY=40000000
|
||||
|
||||
[env:serial]
|
||||
upload_protocol = esptool
|
||||
|
||||
[env:ota]
|
||||
upload_protocol = espota
|
||||
upload_port = snuffelaar-HEX_HERE.local
|
||||
upload_flags =
|
||||
--port=3232
|
||||
--auth=PASSWORD_HERE
|
||||
; Alternatively, instead of editing this file (which is annoying because it
|
||||
; might end up being committed in git), you can create extra an extra config
|
||||
; file.
|
||||
; Just copy the [env:ota] section to a new file called platformio-NAME.ini
|
||||
; and change [env:ota] to [env:NAME]. You can use this to OTA-update multiple
|
||||
; Snuffelaars with a single command: pio run -t upload -e NAME -e NAME -e NAME
|
Loading…
Reference in New Issue
Block a user