Zavod sv. Stanislava Škofijska klasična gimnazija Povezava elektronskih naprav v moji sobi z omrežjem Maturitetna seminarska naloga iz Informatike Kandidat: Andraž Novak Mentor: Helena Starc Grlj Vodice, februar 2017
Povzetek V tej maturitetni seminarski nalogi sem napisal kodo za upravljanje elektronskih naprav preko wifi omrežja in te naprave povezal na način, ki mi omogoča njihovo upravljanje. Abstract I have written a code for controlling electronic devices over wifi. I have also connected these devices, so I can actually control them. Ključne besede Programiranje, Arduino IDE, nodemcu, websockets, javascript, C++ 2
Kazalo Povzetek... 2 Abstract... 2 Ključne besede... 2 Kazalo... 3 1 Uvod... 4 2 Teoretična rešitev... 5 3 Praktična rešitev... 6 3.1 Strežnik... 6 3.1.1 Koda... 6 3.1.2 Vzpostavitev strežnika... 7 3.1.3 Spletni vmesnik... 10 3.2 NodeMCU... 11 3.2.1 Oddajnik... 11 3.2.2 Sprejemnik... 14 4 Sklep... 17 4.1 Strnjena vsebina naloge... 17 4.2 Ocena rešitve... 18 4.3 Odprta vprašanja... 19 5 Viri in literatura... 21 3
1 Uvod Z vse večjo dostopnostjo in podprtostjo povezave wifi, se veliko izdelovalcev električnih naprav odloča, da zmožnost povezovanja vključijo v svoje naprave in jim s tem do določene mere povečajo uporabnost. Bolj kot to pa naredijo naprave bolj priročne za uporabo, saj jih v veliko primerih uporabnik lahko upravlja na daljavo. Nekatere imajo funkcijo, da uporabniku sporočijo podatke o stanju te naprave ali okolice naprave. Vse to mi je zelo fascinantno in se velikokrat sprašujem, kako jim to uspeva. Zato sem se tudi sam poglobil v to. Meni najbližja metoda je, da bi kupil eno napravo in se z njo igral toliko časa, dokler ne bi razumel, kako to dejansko deluje. Tokrat pa sem se odločil, da bom naredil nekaj, kar sicer že obstaja, ampak s funkcijami, ki bodo zadovoljile moje potrebe. Za začetek bom naredil sistem za upravljanje luči v svoji sobi. Gradil ga bom na platformi pod imenom nodemcu, ki temelji na platformi ESP8266. ESP8266 je izum podjetja Espressif in je najcenejši zelo zmogljiv sistem za povezavo z internetom. NodeMCU pa je sestavljen iz modula ESP8266 in prevajalnika iz signala USB v TTL, kar pomeni, da ga lahko direktno priključimo preko vmesnika USB in nanj naložimo kodo. V izvirniku naj bi nanj naložili kodo v programskem jeziku LUA, ki ga ne znam, na srečo pa obstaja možnost uporabe jezika C++ in tolmača Arduino IDE. Za komunikacijo med strežnikom in NodeMcu-jem bom uporabljal protokol websockets, o katerem bom govoril v teoretičnem delu. Strojna oprema Programska oprema Intel i7-4770 @3,40GHz Windows 8.1 16GB ram Arduino IDE Nvidia gtx-760 Node.js 512GB SSD 4
2 Teoretična rešitev Moja celotna seminarska naloga je osnovana okoli protokola websockets. To je protokol, ki se je razvil iz protokola http. Razlog za njegov nastanek je bila potreba po hitri dvosmerni komunikacijami med klientom in strežnikom. Takrat je http omogočal nekaj podobnega, ampak je bilo zelo nepraktično, saj se je morala celotna spletna stran ponovno naložiti, tudi če bi spremenili le eno številko na celotni strani. To je bilo zelo zamudno in potreba je klicala po boljši rešitvi tega problema. Tako je nastal protokol websocket. Od protokola http se razlikuje po tem, da se povezava po začetnem prenosu informacij ne zapre, ampak ostane odprta, kar omogoča (glede na hitrost omrežne povezave) osveževanje informacij tudi več stokrat na sekundo. Najbolj pogosta uporaba takšnega protokola je napoved pisanja, ko nam google search že med pisanjem ponudi možna iskana gesla. Za to potrebuje izjemno hitro povezavo, ki jo omogoča ta protokol. V mojem projektu hitrost ni ključnega pomena, ampak je to kar lahek način za rešitev problema. Omogočiti želim tudi kontrolo preko spletne strani. Ta protokol mi omogoča hitro in relativno lahko rešitev tega. Strežniško stran za posredovanje podatkov preko websocketov se običajno piše v jeziku javascript, program ki izvršuje to kodo pa se imenuje Node.js. Za delovanje tega je potrebna tudi strojna oprema. Ker si želim, da bi sistem deloval 24ur na dan, si ne morem privoščiti, da bi bil računalnik vedno prižgan. Zato bom koristil rešitev Amazon Web Services, ki med drugimi stvarmi omogoča, da ima uporabnik na njihovi strojni opremi virtualni računalnik, ki je ob najbolj osnovni konfiguraciji (kar je za moj projekt več kot dovolj) za 750 ur na mesec za 12 mesecev prižgan brezplačno. Seveda vsak virtualni računalnik dobi svoj IP naslov. Same kliente pa bom programiral v jeziku C++, ki se ga najbolj pogosto uporablja za programiranje platforme z imenom Arduino in omogoča dobro povezovanje fizičnega sveta s programskim. V tem jeziku sem malo bolj vešč, ampak je programiranje naprav, ki se povezujejo na internet zame še neznano. Torej, same kliente, na katere bodo priklopljeni aktuatorji in senzorji bom programiral v jeziku C++, ti klienti bodo preko interneta s protokolom websocket komunicirali z Amazonovimi strežniki, na katerih bo virtualni računalnik, ki bo poganjal program Node.js, na katerem se bo izvajala koda napisana v jeziku javascript. 5
3 Praktična rešitev 3.1 Strežnik Del tega projekta je strežnik, ki vedno obratuje v ozadju. Ima več nalog: -Sprejme podatke z oddajnika ali spletnega vmesnika, -Pošlje podatke prejemniku -Na zahtevo pošlje html datoteko, ki služi kot spletni vmesnik -Je vedno na voljo 3.1.1 Koda Koda je napisana v jeziku javascript. Tukaj je koda, ki sprejme povezavo z oddajnika, čaka na sporočila in jih potem posreduje na sprejemnik in je shranjena kot index.js. Slika 1: Koda websocket stežnika 6
Tukaj je koda, ki čaka na zahtevek na povezavo in pošlje datoteko html, ki služi kot spletni vmesnik. Slika 2: Koda strežnika za spletni vmesnik 3.1.2 Vzpostavitev strežnika Prvi korak je, da poskrbim, da strežnik dejansko obstaja. To mi je uspelo s storitvijo Amazon Web Services, ki omogoča, da uporabnik zakupi del strežnika in ima na njem virtualni računalnik s svojim IP naslovom in vsemu kar paše k računalniku. Kreacija novega virtualnega računalnika je relativno enostavna. V konzoli na spletni strani Amazon Web Services sem izbral EC2 in sledil čarovniku. Na koncu postopka sem dobil poseben ključ, ki sem ga shranil. Pozoren sem bil, ko sem nastavljal varnost, pustiti sem moral, da je ta virtualni računalnik dosegljiv na pravilnih vratih. Za potrebe svojega projekta sem dodal vrata 80 in 9000. Slika 3: Pravila za povezavo na strežnik 7
Virtualnemu računalniku je treba določiti tudi statičen IP naslov, ker je treba povsod definirati, kam naj se klienti povezujejo, ampak če strežnik ugasnem in prižgem nazaj, se IP strežnika spremeni, kar pa ni ugodno za preostalo kodo, ki sem jo napisal. To se da urediti s funkcijo»elastic IPs«. Postopek je zelo enostaven. Pritisnil sem na gumb»allocate new adress«in IP se je avtomatično rezerviral. Ta IP naslov sem povezal z ustvarjenim virtualnim računalnikom tako, da sem ga označimil, kliknil na gumb»actions«in pod zavihkom Networking pritisnil»associate Elastic IP Adress«in označiil ustvarjen IP naslov. V to virtualno napravo sem se prijavil preko protokola SSH s programom Putty. V programu PUTTYgen sem najprej pretvoril ključ za povezavo iz oblike.pem v obliko.ppk. Potem pa sem se v programu PUTTY prijavil z uporabniškim imenom Ubuntu, svojim ključem v obliki.ppk in IP naslovom, ki sem ga našel v konzoli AWS. Slika 4: Primer izpolnitve obraca v progrmu PUTTY Ko sem se prijavil, se mi je pojavil terminal mojega strežnika. Vanj sem vpisal ukaze, ki jih je izvadel. Najprej je izvedel te ukaze, da se je sistem posodobil: sudo apt-get update sudo apt-get install libssl-dev g++ make 8
Ker moj strežnik poganja program node.js, sem ga naložil: curl -sl https://deb.nodesource.com/setup_7.x sudo -E bash - sudo apt-get install -y nodejs Naložil sem še podporo za websockete: npm install websocket Na koncu sem naložil še program, ki bo samodejno odprl proces, če se zaradi kateregakoli vzroka ustavi: sudo npm install forever g Moj strežnik sedaj deluje in se mi z njim ni več treba ukvarjati. Kodo pa sem na svoj virtualni računalnik prenesel s programom filezilla. V programu sem najprej pritisnil CTRL+S, potem pa sem pojavno okno izpolnil na podoben način kot v programu PUTTY. Ko sem se povezal, sem skopiral datoteke na virtualni računalnik in zaprl program. Ko sem na strežnik naložili še kodo mojega strežnika, sem jo pognal takole: forever --minuptime 1 spinsleeptime 1 start index.js forever --minuptime 1 spinsleeptime 1 start wbs.js 9
3.1.3 Spletni vmesnik Ker želim luči upravljati tudi preko internetnega brskalnika, sem napisal še precej osnovno spletno stran, ki mi to omogoča. V glavi datoteke sem napisal kodo za povezavo na websocket strežnik in funkcijo za pošiljanje podatkov nanj. V telo te strani pa sem napisal kodo za nekaj drsnikov. Tukaj sem moral biti pozoren, da sem nastavil pravilne vrednosti, ki se potem pretvorijo v svetlost na pravilni luči v sobi. Pametno je dodati tudi avtorizacijo, ampak sem jo za enkrat spustil. Slika 6: Koda spletnega vmesnika Tako pa izgleda grafični vmesnik za nastavljanje svetlosti luči. Slika 5: Izgled spletnega vmesnika 10
3.2 NodeMCU Povezava projektov na internet je bila dolgo zamudno in drago opravilo, dokler ni podjetje Espressif ustvarilo čipa pod imenom ESP8266. Dobre lastnosti tega čipa so to, da je majhen, poceni, ima precej priključkov, ogromno procesorske moči in ima povezavo WI-FI. Nek tretji proizvajalec pa je ta čip opremil še z izjemnimi razvijalskimi možnostmi, dal vse to na kos tiskanega vezja in poimenoval NodeMCU. To rešitev uporablja moj projekt. Izvorno se ga programira v programskem okolju Lua, ki ga ne znam, obstaja pa možnost z programiranje v programskem okolju Arduino IDE, ki pa mi je precej blizu. Slika 7: NodeMCU 3.2.1 Oddajnik Luči potrebujejo daljinec za upravljanje. Naredil sem ga z nekaj ostanki pleksi stekla, potenciometrom, nekaj žice in nekaj stikali. Napajanje zagotavlja usb priključek. Slika 8: Daljinec Pri pisanju kode sem moral upoštevati, da ima NodeMCU samo en analogni vhod, želim pa nastavljati vrednosti za tri različne luči. Rešitev se skriva v tem, da sem na daljinec dal šest stikal. Program bere katero stikalo je prižgano in glede na to pošilja podatke. Moral pa sem še 11
ugotoviti, kako najlažje določiti, katero stikalo je bilo pritisnjeno ko je daljinec poslal podatke, da lahko sprejemnik spremeni osvetlitev pravilne luči. To sem naredil tako, da sem vrednosti iz potenciometra prištel 10000 za prvo stikalo, 20000 za drugo in tako dalje. Sprejemnik tako le preveri če je prejeta številka nekje med 10000 in 20000 in ve, da mora spremeniti osvetljenost luči pri mizi. Od prejete vrednosti še odšteje 10000 in ve na koliko mora spremeniti vrednost. Med testiranjem sem tudi ugotovil, da strežnik slabo prenaša preveč sporočil naenkrat, zato sem omejil število sporočil poslanih na sekundo na 4. To sem dosegel z ukazom delay(250); Tukaj je koda, ki sem jo naložil nanj. Slika 9: Prvi del kode daljinca 12
Slika 10: Drugi del kode daljinca 13
3.2.2 Sprejemnik Naloga sprejemnika je, da čaka na sporočila, jih dekodira in glede na to prižge luči na določeno vrednost. Izdelal sem ga iz plastične škatle in nekaj osnovnih električnih komponent. Nanj sem priklopil 12V, 60W napajalnik, ki naj bi zadostoval za napajanje teh luči. Slika 11: Sprejemnik in krmilnik luči Pri programiranju sprejemnika sem upošteval enak protokol kot pri oddajniku. Sprejemnik torej sprejme sporočilo, ugotovi v katero kategorijo velikosti spada in glede na to odreagira. Torej recimo da sprejemnik prejme sporočilo 10100. Najprej ugotovi, da je večji od 10000 in manjši od 20000. Potem pa sporočilu odšteje 10000 in dobljeno vrednost kvadrira. Kvadrira pa zato, ker je tako razlika med obratom potenciometra in osvetljenostjo prostora manjša. Če pa dobi vrednost, ki je med 50000 in 60000 pa ne določi svetlosti glede na sprejeto vrednost, ampak glede na že prej nastavljene vrednosti. V tem primeru imam nastavljeno idealno nastavitev za branje knjig v postelji. Podobno se zgodi tudi, če dobi vrednost nekje med 60000 in 70000, le da v tem primeru nastavi osvetlitev na precej manjšo vrednost, saj je to nočna luč. Tukaj je koda. 14
Slika 12: Prvi del kode sprejemnika 15
Slika 13: Drugi del kode sprejemnika 16
4 Sklep 4.1 Strnjena vsebina naloge Cel sistem deluje preko protokola websockets, ki omogoča spontano dvosmerno komunikacijo med uporabnikom in strežnikom. To pri meni služi kot prenašalec sporočil od uporabnika do sprejemnika, ki nato osvetli luči na želeno svetlost. Podatke na sprejemnik lahko pošiljam na dva načina. Eden je z daljincem, drugi pa je s spletnim vmesnikom. Sprejemnik je vedno buden in preko wi-fi omrežja povezan na internet in čaka na podatke. Vedno je buden tudi strežnik, ki čaka na sporočila. Ko prižgem daljinec, se najprej poveže z internetom, nato pa še s strežnikom, ki je odgovoren za prenos sporočil. Potem nastavim potenciometer na želeno vrednost in pritisnem na enega od šestih gumbov. Daljinec zazna vrednost na potenciometru in kateri gumb sem pritisnil. Glede na pritisnjen gumb, program vrednosti potenciometra prišteje ustrezen celoštevilski večkratnik števila 10000. To služi kot koda, ki pove sprejemniku, za katero luč je vrednost iz potenciometra namenjena. Ko to ugotovi, odšteje prišteto vrednost in dobljeni rezultat, ki je enak prebrani vrednosti iz potenciometra, kvadrira in glede na kvadrat določi eno vrednost med 0 in 1023 (luči imajo 1024 stopenj svetlosti). Kvadrira pa zato, ker se tako našim očem zdi naraščanje svetlosti bolj linearno. Sprejemnik nastavlja svetlost z uporabo PWM signala, ki bi z multimetrom izgledal kot spreminjajoča se napetost, v resnici pa je to hitro prižiganje in ugašanje električnega toka. Seveda je signal iz NodeMCU-ja prešibak, da bi napajal luči, zato sem v vezje vključil tranzistorje, ki 3,3V signal spremenijo v 12V do 60W signal. Po specifikacijah proizvajalca, naj bi moje luči proizvedle približno enako jakost svetlobe kot 600W halogenska žarnica, ampak po mojih ocenah je ta številka bliže 250W, kar je še zmeraj precej. Upravljanje s spletnim vmesnikom je precej podobno. Ko se brskalnik skuša povezati na IP naslov strežnika, to strežnik zazna in kot odgovor pošlje html datoteko, v kateri je preprosta skripta, ki se poveže na websocket strežnik in ko na drsniku nastavimo vrednost, pošlje številko na strežnik, od tam naprej pa je postopek isti kot pri daljincu. 17
4.2 Ocena rešitve Cilj naloge je dosežen. V sobi imam z internetom povezane luči, ki jih lahko upravljam z daljincem ali pa s telefonom iz kjerkoli na svetu. Možnosti za dodajanje funkcij so seveda odprte. Lahko bi dodal termometer, da bi vedel, kako toplo je v moji sobi, ali pa senzor, če je okno odprto. Lahko bi nastavil, naj se mi luči prižigajo takrat ko se zbujam, da bi se zbudil po malo bolj naravni poti- s sončnim vzhodom. Možnosti so definitivno odprte. Poraba časa Pridobivanje podatkov Pisanje kode Izdelava daljinca in sprejemnika Pisanje dokumentacije 18
4.3 Odprta vprašanja Pustil sem tudi nekaj možnosti za izboljšavo takšnega sistema, kot ga imam sedaj. -Lepotne izboljšave so področje, na katerem bi lahko še precej naredil. Vezja niso na tiskanem vezju, ampak so komponente prilepljene na ohišje sprejemnika in daljinca. Luči so narejeno precej na hitro in vidi se, da sem bil zelo omejen z materialom in z orodjem. Lahko bi kupil tudi malo lepše kable, saj imam trenutno po sobi napeljane črno-rdeče žice, ki niso paša za oči. -Varnostne izboljšave so nekaj, v kar se bom sigurno poglobil. V tem trenutku se lahko vsak poveže na moj websocket strežnik, nekaj časa opazuje poslane podatke in potem začne pošiljati svoje podatke. Vsak ki ima IP naslov mojega strežnika, lahko prav tako le tega vpiše v spletni brskalnik in se mi v sobi nastavlja svetlost luči po mili volji. 19
-Izboljšal bi lahko tudi uporabnost cele stvari. Dodal bi lahko zatemnjevanje in počasno prižiganje luči, kar bi bilo zelo uporabno, ampak mi zaradi neznanega razloga to ne deluje. Daljincu bi lahko dodal baterije, da bi ga lahko uporabljal brez da bi bil z USB priključkom povezan na napajalnik. 20
5 Viri in literatura Neznani avtor: WebSocket Server and Client for Arduino (online). [Uporabljeno 19.2.2017] Dostopno na: https://github.com/links2004/arduinowebsockets _C1D: So you want to setup a socket.io server on EC2 (online). [Uporabljeno 16.2.2017] Dostopno na: http://c-1-d.tumblr.com/post/43307121272/so-you-want-to-setup-a-socketioserver-on-ec2 Neznan avtor: How to Setup Node and Express on Amazon Web Services EC2 (online). [Uporabljeno 20.2.2017] Dostopno na: https://www.youtube.com/watch?v=wxhfq64fqza Alma, P.: Assign a fixed IP to AWS EC2 instance (online). [Uporabljeno 22.2.201] Dostopno na: https://pragmaticintegrator.wordpress.com/2012/12/13/assign-a-fixed-ip-toaws-ec2-instance/ Neznan avtor: Websocket (online). [Uporabljeno 5.2.2017] Dostopno na: https://en.wikipedia.org/wiki/websocket 21