Johdanto
Tämä on ensimmäinen IoT-harjoitus, jonka tein alunperin opiskelijoita varten. Harjoituksessa rakennetaan laite, jolla voidaan ohjata mm. LED-valoja ja tuuletinta sekä tarkkaillaan tilan valaistusta ja lämpötilaa. Laitteeseen voidaan ottaa yhteys WiFi-verkon kautta tietokoneella tai mobiililaitteella. Käytännössä Arduino toimii web-serverinä.
Esimerkkikoodi
Tätä koodia ei kannata käyttää ”oikeassa” sovelluksessa, mutta sillä pääset nopeasti testaamaan ethernet shieldin toimintaa ja tekemään jotain konkreettisia ohjauksia. Esimerkissä ei ole huomioitu tietoturvaa millään tavalla, eikä toteutus ole muutenkaan sieltä optimaalisimmasta päästä. ”This is just for fun”
#include <SPI.h>
#include <Ethernet.h>
#define lampoanturi A5
#define ldrvastus A2
int tuuletinPin = 6;
int ledPin = 7;
int valaistusPin = 5;
int lampo = 0;
int valoisuus = 0;
int porrastus = 40;
int viive = 1000;
int ledtila=0;
int headerSent=0;
int jaahdytysPaalla = 0;
int valaistustila = 0;
int valaistuskirkkaus = 200;
int incoming;
// Arduino Ethernet MAC-osoite (Samassa verkossa olevilla laitteilla oltava uniikki MAC-osoite eli muista vaihtaa tarvittaessa!!)
// Googlesta löytyy myös MAC-generaattori
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// Kiinteä IP-osoite (MUISTA VAIHTAA OIKEALLE IP-ALUEELLE JA TARKISTA, ETTÄ OSOITE EI OLE DHCP:LLÄ JAOSSA!)
IPAddress ip(192,168,1,123);
// Arduino web-serverin portti
EthernetServer server(80);
void setup()
{
pinMode(ledPin, OUTPUT);
pinMode(tuuletinPin, OUTPUT);
pinMode(valaistusPin, OUTPUT);
// Muodostetaan verkkoyhteys ja käynnistetään serveri
Ethernet.begin(mac, ip);
server.begin();
}
void loop()
{
headerSent=0;
// Seuraillaan yhdistääkö joku serveriin
EthernetClient client = server.available();
if (client) {
// HTTP-pyyntö päättyy tyhjään riviin
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// Jos osoitteessa ei ole muuta niin ei käydä läpi käskyjä vaan tulostetaan pelkkä HTML-sivu
if (incoming && c==' ')
{
incoming=0;
}
// Jos osoitteessa on komentoja niin käydään läpi käskyt
if (c=='$')
{
incoming=1;
}
// Tsekataan url ja tehdään sen perusteella juttuja (ip/$1, ip/$2 jne jne...)
if (incoming==1)
{
headerSent=1;
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
// Laitetaan tuulettimen ohjaus päälle ja sytytetään merkkivalo
if(c=='1')
{
digitalWrite(ledPin, HIGH);
ledtila = 1;
headerSent=1;
jaahdytysPaalla = 1;
client.println("<meta http-equiv='refresh' content='0;URL=/'>\n");
}
// Tuulettimen ohjaus pois
if(c=='2')
{
digitalWrite(ledPin, LOW);
ledtila = 0;
jaahdytysPaalla = 0;
client.println("<meta http-equiv='refresh' content='0;URL=/'>\n");
}
// Valaistus päälle
if(c=='3')
{
valaistustila = 1;
client.println("<meta http-equiv='refresh' content='0;URL=/'>\n");
}
// Valaistus pois
if(c=='4')
{
valaistustila = 0;
client.println("<meta http-equiv='refresh' content='0;URL=/'>\n");
}
// Kirkkautta lisää
if(c=='5')
{
// Tarkistetaan, että säädettävä arvo pysyy halutulla alueella (PWM alue 0-255)
if(valaistuskirkkaus<=250 && (valaistuskirkkaus+porrastus)<=250) {
valaistuskirkkaus += porrastus;
}
client.println("<meta http-equiv='refresh' content='0;URL=/'>\n");
}
// Kirkkautta vähemmän
if(c=='6')
{
// Tarkistetaan, että säädettävä arvo pysyy halutulla alueella (PWM alue 0-255)
// Ei kuitenkaan haluta sammuttaa valoa kokonaan vaan pidetään 10 miniminä
if(valaistuskirkkaus>=10 && (valaistuskirkkaus-porrastus)>=10) {
valaistuskirkkaus -= porrastus;
}
client.println("<meta http-equiv='refresh' content='0;URL=/'>\n");
}
}
// Käskyt käyty läpi eli tulostetaan varsinainen HTML-sivu
if (c == '\n' && currentLineIsBlank) {
// TULOSTETAAN HTML SIVU
// Luetaan valoanturin arvo
valoisuus = analogRead(ldrvastus);
// Luetaan lämpötila
lampo = analogRead(lampoanturi);
float voltage = lampo * 5;
voltage /= 1024.0;
float temperatureC = (voltage - 0.5) * 100 ;
// Jos http-header lähetetty jo ylempänä niin ei lähetetä uudelleen, koska se ilmestyisi tekstinä www-sivulle
// Muuten lähetetään header data niin saadaan renderöity www-sivu selaimeen
if(headerSent == 0) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
}
// Tulostetaan HTML-runko
client.println("<html>\n<head>\n<meta charset='UTF-8'>\n");
client.println("<meta name='viewport' content='width=device-width, initial-sclae=1.0'>\n");
client.println("<meta http-equiv='refresh' content='5'>\n");
client.println("<title>Arduino Ethernet IoT testi</title>\n");
client.println("<style>");
client.println("body { background-color:#143366; color : #FFF; font-size:24px; font-family: Calibri, Arial, Verdana; text-align:center; margin : 10px; } \n");
client.println(".painike { display:block; margin:0 auto; min-width:80px; max-width : 70%; background-color:#e28000; border-radius:10px; padding:10px; color:#FFF; font-weight:bold; color:#FFF; text-decoration:none; margin-bottom:20px; }");
client.println(".painike:hover { border:2px solid white; }");
client.println(".puolikas { display:block; margin:0 auto; width:50%; text-align:center; }");
client.println(".mini { display:inline-block; margin:10px; font-size:32px; }");
client.println("</style>");
client.println("</head>\n<body>\n");
client.println("<h1>Huone X</h1>\n");
client.println("<b>Tilan valaistus:</b> ");
// Tsekataan onko valot päällä (LDR-vastuksen arvot luettu valojen ollessa päällä ja ilman valoa)
if(valoisuus>=980) {
client.println("päällä <br>\n");
}
else {
client.println("pois <br>\n");
}
// Jos haluat tarkistaa LDR-vastuksen arvot niin poista kommentti alemmasta rivistä
//client.println(valoisuus);
// Tulostetaan lämpötila
client.println("<b>Lämpötila:</b> ");
client.println(temperatureC);
client.println(" C <br><br>");
// Tulostellaan jäähdytyksen painike
if(ledtila == 1) {
client.println("<a class='painike' href='/$2'>Sammuta jäähdytys</a><br>");
}
else {
client.println("<a class='painike' href='/$1'>Käynnistä jäähdytys</a><br>");
}
// Tulostetaan valaistuksen painike
if(valaistustila == 1) {
client.println("<a class='painike' href='/$4'>LED-valaistus pois</a><br>");
client.println("<span class='puolikas'>");
client.println("<b>Kirkkaus:</b><br>");
client.println("<a class='painike mini' href='/$5'>+</a>");
client.println("<a class='painike mini' href='/$6'>-</a>");
client.println("</span>");
}
else {
client.println("<a class='painike' href='/$3'>LED-valaistus päälle</a><br>");
}
client.println("</body>\n</html>");
break;
}
if (c == '\n') {
// Osoite loppuu
currentLineIsBlank = true;
}
else if (c != '\r') {
// Osoitteessa on merkkejä
currentLineIsBlank = false;
}
}
}
// Odotellaan hetki www-serveriä...
delay(1);
// Suljetaan yhteys
client.stop();
}
// Tuulettimen ohjaus
if(jaahdytysPaalla == 1) {
analogWrite(tuuletinPin,255);
}
else {
digitalWrite(tuuletinPin,LOW);
}
// Valaistuksen ohjaus
if(valaistustila == 1) {
analogWrite(valaistusPin,valaistuskirkkaus);
}
else {
digitalWrite(valaistusPin,LOW);
}
}
Lopputulos
Mikäli kaikki meni niin kuin strömsössä niin lopputulema pitäisi olla jotakuinkin tämmöinen: