energy-meter/energy-meter.ino

175 lines
3.5 KiB
C++

#include <SPI.h>
#include <Ethernet.h>
#include <MySQL_Encrypt_Sha1.h>
#include <MySQL_Packet.h>
#include <MySQL_Cursor.h>
#include <MySQL_Connection.h>
#include <Dns.h>
#include "config.h"
typedef struct Input {
int id;
unsigned long timer;
};
char query[50];
unsigned long lastRefresh;
unsigned long lastDebug;
unsigned long lastRecord;
Input inputs[N_INPUTS];
EthernetClient ethClient;
MySQL_Connection db((Client *) &ethClient);
IPAddress dbServer;
void printTitle(String title) {
#ifdef DEBUG
for (int i = 0; i < 10; i++)
Serial.print('=');
Serial.println(" " + title);
#endif
}
void showError(String error) {
#ifdef DEBUG
Serial.println(error);
#endif
}
void abortWithError(String error) {
showError(error);
while (true) delay(1);
}
int freeRam() {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
void setup() {
#ifdef DEBUG
Serial.begin(9600);
while (!Serial);
#endif
if (Ethernet.begin(mac) == 0)
abortWithError("DHCP config failed.");
if (Ethernet.hardwareStatus() == EthernetNoHardware)
abortWithError("Eth shield not found.");
if (Ethernet.linkStatus() == LinkOFF)
abortWithError("Eth cable not connected.");
#ifdef DEBUG
Serial.println("IP: " + String(Ethernet.localIP()));
#endif
if (!dbConnect())
abortWithError("Aborting.");
unsigned long now = millis();
lastRefresh = now;
lastDebug = now;
lastRecord = now;
for (int i = 0; i < N_INPUTS; i++) {
Input* input = &inputs[i];
input->id = i + 1;
input->timer = 0;
pinMode(pins[i], INPUT);
}
#ifdef DEBUG
Serial.println("RAM: " + String(freeRam()));
#endif
}
boolean dbConnect() {
DNSClient dns;
dns.begin(Ethernet.dnsServerIP());
if (dns.getHostByName(DB_HOST, dbServer) != 1) {
showError("Cannot resolve DB.");
return false;
}
#ifdef DEBUG
Serial.println("Connecting to DB: " + String(dbServer));
#endif
if (!db.connect(dbServer, DB_PORT, DB_USER, DB_PASS)) {
showError("Cannot connect to DB.");
return false;
}
return true;
}
void refreshTimers() {
unsigned long now = millis();
for (int i = 0; i < N_INPUTS; i++) {
Input* input = &inputs[i];
if (digitalRead(pins[i]) == HIGH)
input->timer += now - lastRefresh;
}
lastRefresh = now;
}
void loop() {
refreshTimers();
Ethernet.maintain();
#ifdef DEBUG
if (millis() - lastDebug > DEBUG_INTERVAL) {
printTitle("Status");
for (int i = 0; i < N_INPUTS; i++) {
Input* input = &inputs[i];
Serial.print("Input ");
String id = String(input->id);
for (int j = 2 - id.length(); j > 0; j--)
Serial.print(" ");
Serial.print(String(input->id) + ": ");
Serial.print(String(digitalRead(pins[i]) == HIGH));
Serial.println("/" + String(input->timer));
}
lastDebug = millis();
}
#endif
if (millis() - lastRecord > RECORD_INTERVAL) {
printTitle("Recording to DB");
if (!db.connected())
dbConnect();
for (int i = 0; i < N_INPUTS; i++) {
refreshTimers();
Input* input = &inputs[i];
int timer = input->timer;
int seconds = timer / 1000;
input->timer = 0;
if (seconds > 0 && db.connected()) {
sprintf(query, SQL, input->id, seconds);
#ifdef DEBUG
Serial.println(query);
#endif
MySQL_Cursor *cur = new MySQL_Cursor(&db);
cur->execute(query);
delete cur;
}
}
lastRecord = millis();
}
delay(DELAY);
}