-
Notifications
You must be signed in to change notification settings - Fork 0
/
orp_exporter_wifi_shield.ino
249 lines (227 loc) · 9.26 KB
/
orp_exporter_wifi_shield.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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#include <SoftwareSerial.h>
#include "WiFly.h"
// Wifi connection settings
#define SSID "YOUR_AP"
#define KEY "YOUR_PASSWORD"
#define AUTH WIFLY_AUTH_WPA2_PSK
#define RETRIES "30"
// ORP sensor settings for Grove ORP sensor
#define ORPPIN 1 //orp meter output,connect to Arduino controller ADC pin (A1)
#define VOLTAGE 5.00 //system voltage
#define OFFSET -42 //zero drift voltage
// ORP sensor value
double orpValue;
int crashes = 0;
int drops = 0;
boolean enabled = true;
// https://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else // __ARM__
extern char *__brkval;
#endif // __arm__
int freeMemory() {
char top;
#ifdef __arm__
return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
return &top - __brkval;
#else // __arm__
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif // __arm__
}
// Initialise uptime variables
// https://hackaday.io/project/7008-fly-wars-a-hackers-solution-to-world-hunger/log/25043-updated-uptime-counter
long TotalSeconds = 0;
long Day = 0;
int Hour = 0;
int Minute = 0;
int Second = 0;
int HighMillis = 0;
int Rollover = 0;
// Uptime monitor
void uptime() {
//** Making Note of an expected rollover *****//
if (millis() >= 3000000000) {
HighMillis = 1;
}
//** Making note of actual rollover **//
if (millis() <= 100000 && HighMillis == 1) {
Rollover++;
HighMillis = 0;
}
long secsUp = millis() / 1000;
TotalSeconds = (Rollover * 50) + (secsUp);
Second = secsUp % 60;
Minute = (secsUp / 60) % 60;
Hour = (secsUp / (60 * 60)) % 24;
Day = (Rollover * 50) + (secsUp / (60 * 60 * 24)); //First portion takes care of a rollover [around 50 days]
};
String returnUptime() {
char output[11];
sprintf(output, "%02d:%02d:%02d:%02d", Day, Hour, Minute, Second);
return output;
};
SoftwareSerial wiflyUart(2, 3); // create a WiFi shield serial object
WiFly wifly(&wiflyUart); // pass the wifi siheld serial object to the WiFly class
void connectToWifi()
{
Serial.println("------Configuring Wifi shield------");
wifly.reset(); // reset the shield
delay(1000);
//set parameters to make wifi shield safer against outside attacks.
wifly.sendCommand("set ip tcp-mode 0x10\r"); // disable remote configuration via TCP connections
delay(100);
wifly.sendCommand("set wlan hide 1\r"); //when the module shows the wlan settings, the passphrase is shown as ******
delay(100);
//set WiFly params
wifly.sendCommand("set ip local 80\r"); // set the local comm port to 80
delay(100);
wifly.sendCommand("set comm remote 0\r"); // do not send a default string when a connection opens
delay(100);
wifly.sendCommand("set comm open *OPEN*\r"); // set the string that the wifi shield will output when a connection is opened
delay(100);
// https://forum.arduino.cc/index.php?topic=538388.0
//set parameters so the module automatically connects to the access point and attempts to reconnect after loss of connection
wifly.sendCommand("set wlan auth WIFLY_AUTH_WPA2_PSK\r"); //set authentication mode to WPA2 with personal key
delay(100);
wifly.sendCommand("set wlan passphrase ssid " SSID "\r"); //set the SSID
delay(100);
wifly.sendCommand("set wlan passphrase " KEY "\r"); //set the passphrase (WPA/WPA2 personal key)
delay(500); //longer delay needed, otherwise linkmon causes failure of connection; no documentation found on this topic; just trial and error :-(
//set parameters so the module automatically connects to the access point and attempts to reconnect after loss of connection
delay(500); //longer delay needed, otherwise linkmon causes failure of connection; no documentation found on this topic; just trial and error :-(
wifly.sendCommand("set wlan linkmon " RETRIES "\r"); //set the link monitor to RETRIES attempts of reconnecting when detecting the loss of connection to the access point
delay(500); //longer delay needed, otherwise linkmon causes failure of connection; no documentation found on this topic; just trial and error :-(
wifly.sendCommand("set wlan join 1\r"); //set the mode (value 1) so the module will auto-connect and re-connect to the access point
delay(100);
Serial.println("Join " SSID );
// check if WiFly is associated with AP(SSID)
if (!wifly.isAssociated(SSID)) {
while (!wifly.join(SSID, KEY, AUTH)) {
Serial.println("Failed to join " SSID);
Serial.println("Wait 0.5 secs and try again...");
delay(500);
}
wifly.save(); // save configuration,
}
Serial.println("Success joining " SSID);
// Print the IP configuration
delay(5000);
wifly.sendCommand("get ip\r");
char c;
while (wifly.receive((uint8_t *)&c, 1, 300) > 0) { // print the response from the get ip command
Serial.print((char)c);
}
Serial.println("------Web server ready------");
}
void htmlHeader(String code, String contentType, String output) {
String contentLength = "Content-Length: ";
contentLength += output.length();
wiflyUart.print("HTTP/1.1 ");
wiflyUart.println(code);
wiflyUart.print("Content-Type: ");
wiflyUart.print(contentType);
wiflyUart.println("; charset=UTF-8");
wiflyUart.println(contentLength);
wiflyUart.println("Connection: close");
wiflyUart.println();
wiflyUart.print(output);
}
void setup()
{
wiflyUart.begin(9600); // start wifi shield uart port
Serial.begin(9600); // start the arduino serial port
// wait for initilization of wifly
delay(1000);
connectToWifi();
}
void loop()
{
// Update uptime counters
uptime();
if (wifly.available())
{ // the wifi shield has data available
// Recieve and print the request
char c;
String response;
while (wifly.receive((uint8_t *)&c, 1, 1000) > 0) {
response += (char)c;
}
Serial.println(response);
if (response.indexOf("OPEN*") > 0) {
delay(1000); // delay enough time for the browser to complete sending its HTTP request string
String output = "";
if (response.indexOf("GET /metrics") > 0) {
// Only return a 200 OK if sensor is enabled
if (enabled == true) {
// Sample three times to calibrate
for (int sample = 0; sample <= 3; sample++) {
orpValue = ((30 * (double)VOLTAGE * 1000) - (75 * analogRead(ORPPIN) * VOLTAGE * 1000 / 1024)) / 75 - OFFSET; //convert the analog value to orp according the circuit
delay(200);
}
// Output in prometheus compatible format, including the uptime as a comment
output += "# HELP orp_sensor_value_mv Returns the sensor value from the ORP sensor in mV\n";
output += "# TYPE orp_sensor_value_mv gauge\n";
output += "orp_sensor_value_mv ";
output += orpValue;
output += "\n";
output += "# HELP orp_sensor_free_memory Returns the board free memory in Kb\n";
output += "# TYPE orp_sensor_free_memory gauge\n";
output += "orp_sensor_free_memory ";
output += freeMemory();
output += "\n";
output += "# HELP orp_sensor_wifi_associations Returns the number of times the wifi has reassociated\n";
output += "# TYPE orp_sensor_wifi_associations gauge\n";
output += "orp_sensor_wifi_associations ";
output += drops;
output += "\n";
output += "# HELP orp_sensor_crashes Returns the number of times the board has crashed\n";
output += "# TYPE orp_sensor_crashes gauge\n";
output += "orp_sensor_crashes ";
output += crashes;
output += "\n";
output += "# HELP orp_sensor_uptime Returns the board uptime in seconds\n";
output += "# TYPE orp_sensor_uptime gauge\n";
output += "orp_sensor_uptime ";
output += TotalSeconds;
output += "\n";
output += "# UPTIME (DD:HH:MM:SS) ";
output += returnUptime();
output += "\n";
htmlHeader("200 OK", "text/plain", output);
} else {
output = "<html><body>Sensor Disabled</body></html>";
htmlHeader("404 Not Found", "text/html", output);
}
} else if (response.indexOf("GET /enable") > 0) {
enabled = true;
output = "<html><body>Sensor Enabled</body></html>";
htmlHeader("200 OK", "text/html", output);
} else if (response.indexOf("GET /disable") > 0) {
enabled = false;
output = "<html><body>Sensor Disabled</body></html>";
htmlHeader("200 OK", "text/html", output);
} else {
output = "<html><body><ul><li><a href='/metrics'>/metrics</a></li></ul></body></html>";
htmlHeader("404 Not Found", "text/html", output);
}
Serial.println(output);
} else if (response.indexOf("CLOS*") > 0) {
// Ack connection close
} else if (response.indexOf("isconn") > 0 || response.indexOf("AUTH-ERR") > 0) {
// AP association failure - Disconn / AUTH-ERR
drops += 1;
Serial.println("Lost Wifi AP association, reconnecting ...");
} else if (response.indexOf("CRASH*") > 0) {
// Total board crash, cross your fingers
crashes += 1;
Serial.println("Wifi board has crashed ...");
delay(1000);
connectToWifi();
} else {
Serial.println("UNKNOWN MESSAGE");
}
}
}