-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsketch.ino
182 lines (157 loc) · 6.04 KB
/
sketch.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
/**********************************************************************************************
--- Arduino Ehternet HTTP webclient ---
Written by Stanley Skarshaug, 03.02.2020 - Norway.
Free to use - if credit is given to author.
Fast and simple web server API that can be used to controll a LED on the Arduino.
Does include the HTTP parser to check for variables in the HTTP request.
The API reqire that a APIkey is given as a variable. Else it will not act.
Does respont to client with a JSON.
**********************************************************************************************/
#include<SPI.h>
#include<Ethernet.h>
const int ledPin = 3; // LED that is controlled via the API.
const int httpLEDPin = 4; // LED indicator for http activity. Both as a server and a client
const int errorLEDPin = 5; // LED indicator for any system error
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; // Custom MAC-address. Can be pretty much anything...
IPAddress ip(10,22,22,60); // Static IP Address
IPAddress myDns(8,8,8,8); // DNS Server - dns.google
IPAddress myGateway(10,22,22,1);
EthernetServer server(80); // Start server in port 80.
String apiKey = "s3cr37"; // Key to access the API. Must be provided in order to use API
String readString;
bool ledStatus = 0;
bool apiAuth = 0;
bool firstLine = true;
void setup(){
pinMode(ledPin, OUTPUT);
pinMode(httpLEDPin, OUTPUT);
pinMode(errorLEDPin, OUTPUT);
Serial.begin(9600);
Serial.println("OK - Serial communication is established ");
Ethernet.begin(mac, ip, myDns, myGateway);
server.begin();
if(Ethernet.localIP()){
Serial.print("Arduino IP address: ");
Serial.println(Ethernet.localIP());
Serial.println("OK - Ethernet system is ready...");
} else {
Serial.println("ERROR! - Failed to configure Ethernet using static IP");
digitalWrite(errorLEDPin, HIGH); // turn ON Error LED indicator of DHCP setup failed.
while (true); // Stop program forever.
}
Serial.println("OK - All systems active");
Serial.println();
}
void loop() {
runApi();
}
/***********************************************************************************************************************/
/* Recieve data from a web client, act on instructions */
/***********************************************************************************************************************/
void runApi(){
EthernetClient client = server.available();
// If a client connects, run the API logic.
if (client) {
Serial.println("new client: " + String(client.remoteIP()));
digitalWrite(httpLEDPin, HIGH);
bool currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
//Serial.write(c);
//Read the first line of the get request to figure out what the client wants from the API.
//Stop reading the line if it's more than 100 characters long, and it's no longer on the first line.
if(readString.length()<100 && firstLine){
readString += c;
// This API only cares about the first line of the HTTP request.
if(c == '\n'){
firstLine = false;
Serial.println(readString);
// Check if the correct apikey us supplied, if not - send error response.
// If ok, run commands.
if(parseRequest(readString, "apikey") == apiKey){
apiAuth = 1;
runCommands(readString);
} else {
apiAuth = 0;
}
// Reset the readString to be ready for a new connection.
readString = "";
}
}
// Wait for the get request header to finish. It will end with a empty line containing a newline character.
// This API does not care about the body of the request
// Then respond to client
if (c == '\n' && currentLineIsBlank) {
if(apiAuth){
returnStatus(client);
} else {
returnForbidden(client);
}
break;
}
if (c == '\n') {
currentLineIsBlank = true;
}
else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
//delay for stability.
delay(1);
client.stop();
Serial.println("client disconnected");
digitalWrite(httpLEDPin, LOW);
firstLine = true;
Serial.println("*******************************************************************************************");
Serial.println();
}
}
String parseRequest(String requestString, String variableName){
if(requestString.indexOf(variableName)>0){
unsigned int varStarts = readString.indexOf(variableName) + variableName.length()+1;
unsigned int varEnds;
if(readString.indexOf("&", varStarts)>0) {
varEnds = readString.indexOf("&", varStarts);
} else {
varEnds = readString.indexOf(" ", varStarts);
}
return requestString.substring(varStarts, varEnds);
} else {
return "-1";
}
}
void runCommands(String readString){
// Check for specied variable, and value.
if(parseRequest(readString, "led") == "1"){
digitalWrite(ledPin, HIGH);
ledStatus = 1;
} else if(parseRequest(readString, "led") == "0"){
digitalWrite(ledPin, LOW);
ledStatus = 0;
}
}
void returnStatus(EthernetClient client){
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: application/json;charset=utf-8");
client.println("Server: Arduino");
client.println("Connection: close");
client.println();
// HTTP Responese body - this is a JSON with status info
client.print("{");
client.print("\"ledStatus\":" + String(ledStatus) + ",");
client.print("\"IOT-Device\": \"Arduino LED switch API\"");
client.println("}");
client.println();
}
void returnForbidden(EthernetClient client){
client.println("HTTP/1.1 403 Forbidden");
client.println("Content-Type: Text/html");
client.println("Server: Arduino");
client.println("Connection: close");
client.println();
// HTTP Responese body
client.println("403 Forbidden");
client.println();
}