-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsolar-weather-station.ino
199 lines (159 loc) · 6.69 KB
/
solar-weather-station.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// Platform libraries.
#include <Arduino.h> // To add IntelliSense for platform constants.
#include <ESP8266WiFi.h> // To connect to the WiFi network.
// Third-party libraries.
#include <WiFiManager.h> // To manage network configuration and connection.
// My classes.
#include "bme280.h" // To read the temperature, pressure and humidity sensor.
#include "ifttt-client.h" // To manage the communication with the IFTTT service.
#include "magicmirror-client.h" // To manage the communication with the MagicMirror.
#include "status-led.h" // To control the status LED.
#include "thingspeak-client.h" // To send measured data to the ThingSpeak service.
#include "blynk-client.h" // To send measured data to the Blynk service.
// #include "ota-updater.h" // To manage over-the-air updates of new code.
#include "config.h" // To store configuration and secrets.
WiFiManager wifiManager;
BME280 bme;
MagicMirrorClient magicMirror;
IftttClient ifttt;
ThingSpeakClient thingSpeak;
BlynkClient blynk;
StatusLed led;
// OTAUpdater updater;
void setup() {
initSerial();
initLed();
led.onBootStarted();
initNetwork();
initMagicMirrorClient();
initIftttClient();
initThingSpeakClient();
initBlynkClient();
initTemperatureSensor();
// initUpdater();
sendStartNotification();
led.onBootEnded();
Serial.printf("Application version: %s\n", APP_VERSION);
Serial.println("Setup completed.");
measureAndUpdateTargets();
goToDeepSleep();
}
void loop() {
// No code here, because all logic is running in the setup phase and then the device goes to deep sleep.
// After waking up the setup phase is executed again.
}
void initSerial() {
Serial.begin(74880); // 74880 is the speed used to print boot messages.
Serial.println();
Serial.println("Initializing serial connection DONE.");
}
void initLed() {
Serial.printf("Initializing RGB LED on pins %d, %d, %d...", PIN_LED_RED, PIN_LED_GREEN, PIN_LED_BLUE);
led.setPins(PIN_LED_RED, PIN_LED_GREEN, PIN_LED_BLUE);
Serial.println("DONE.");
}
void initNetwork() {
Serial.printf("Initializing connection to the network with MAC address %s using WiFiManager (SSID: %s)...\n", WiFi.macAddress().c_str(), WIFI_AP_SSID);
wifiManager.setAPCallback([](WiFiManager *mgr) {
led.onWifiManagerAccessPointModeStarted();
});
wifiManager.setSaveConfigCallback([]() {
led.onWifiManagerAccessPointModeEnded();
});
// Configuration portal timeout and automatic restart is required because sometimes the device does not find the
// network credentials after booting up, but after a restart it can connect to the network without any issue.
// This ensures that the device retries connecting to the network without waiting for user interaction.
wifiManager.setConfigPortalTimeout(WIFI_CONFIG_PORTAL_TIMEOUT_SECONDS);
if (!wifiManager.autoConnect(WIFI_AP_SSID, WIFI_AP_PASSWORD)) {
Serial.println("Failed to connect to the network and the WiFi configuration portal hit inactivity timeout. Restarting the device in 3 seconds and trying again...");
delay(3000);
// The restart() function triggers a more clean reboot than reset(), so this one is the preferred.
// Read more: https://www.pieterverhees.nl/sparklesagarbage/esp8266/130-difference-between-esp-reset-and-esp-restart
ESP.restart();
}
Serial.printf("DONE. IP address: %s, MAC address: %s\n", WiFi.localIP().toString().c_str(), WiFi.macAddress().c_str());
}
void initMagicMirrorClient() {
Serial.printf("Initializing MagicMirror client to host %s...", MAGIC_MIRROR_HOST);
magicMirror.setHostUrl(MAGIC_MIRROR_HOST);
Serial.println("DONE.");
}
void initIftttClient() {
Serial.print("Initializing IFTTT client...");
ifttt.setApiKey(IFTTT_WEBHOOK_API_KEY);
String deviceName = String(OTA_UPDATE_HOSTNAME) + " (Version: " + APP_VERSION + ", IP: " + WiFi.localIP().toString() + ", MAC: " + WiFi.macAddress() + ")";
ifttt.setDeviceName(deviceName);
Serial.println("DONE.");
}
void initThingSpeakClient() {
Serial.print("Initializing ThingSpeak client...");
thingSpeak.setApiKey(THINGSPEAK_API_KEY);
Serial.println("DONE.");
}
void initBlynkClient() {
Serial.print("Initializing Blynk client...");
blynk.setAuthToken(BLYNK_AUTH_TOKEN);
blynk.waitUntilConnected();
Serial.println("DONE.");
}
void initTemperatureSensor() {
Serial.print("Initializing the temperature sensor...");
bme.init();
Serial.println("DONE.");
}
// void initUpdater() {
// Serial.print("Initializing over-the-air updater...");
// updater.initialize(OTA_UPDATE_HOSTNAME, OTA_UPDATE_PASSWORD, ifttt, led);
// Serial.println("DONE.");
// }
void sendStartNotification() {
// Send start notification only if the device has not waken up from deep sleep,
// so the start happened unexpectedly.
String resetReason = ESP.getResetReason();
Serial.println("Reset reason: " + resetReason);
if (resetReason != "Deep-Sleep Wake") {
Serial.println("Sending notification about unexpected start...");
String message = String("Your device is starting. Reason: ") + resetReason + " (" + ESP.getResetInfo() + ")";
ifttt.triggerEvent(IFTTT_WEBHOOK_EVENT_NAME, "Starting", message);
Serial.println("DONE.");
}
}
void measureAndUpdateTargets() {
Serial.println("Measuring...");
led.onMeasurementStarted();
Serial.print("Reading sensor data...");
BME280::Measurement m = bme.getMeasuredData();
Serial.println(" DONE.");
Serial.printf("Temperature: %.1f °C\n", m.temperature);
Serial.printf("Pressure: %.1f hPa\n", m.pressure);
Serial.printf("Altitude: %.1f m\n", m.altitude);
Serial.printf("Humidity: %.1f %%\n", m.humidity);
Serial.print("Reading battery voltage... ");
float voltage = readBatteryVoltage();
Serial.print(voltage);
Serial.println("V DONE.");
Serial.println("Sending data to ThingSpeak...");
thingSpeak.writeField(String(m.temperature), String(m.humidity), String(voltage), "");
Serial.println("DONE.");
Serial.println("Sending data to MagicMirror...");
magicMirror.sendTemperature(m.temperature, m.humidity, voltage);
Serial.println("DONE.");
Serial.print("Sending data to Blynk...");
blynk.sendUpdate(m.temperature, m.humidity, voltage);
Serial.println("DONE.");
led.onMeasurementEnded();
Serial.println("Measuring: DONE.");
}
float readBatteryVoltage() {
// Voltage divider R1 = 220k+100k+220k =540k and R2=100k
float calib_factor = 5.28; // change this value to calibrate the battery voltage
unsigned long raw = analogRead(A0);
float volt = raw * calib_factor/1024;
return volt;
}
void goToDeepSleep() {
Serial.printf("Going to sleep for %.0f seconds...\n", UPDATE_INTERVAL_SECONDS);
pinMode(D0, WAKEUP_PULLUP);
ESP.deepSleep(UPDATE_INTERVAL_SECONDS * 1e6); // Microseconds.
delay(10);
}