Merhaba bu yazımızda Orange pi ile web server oluşturup, NodeMCU ve Orange pi pinlerini web tarayıcısı üzerinden kontrol edeceğiz. Bu yazıda kullanılan Orange pi ve NodeMCU python kodları ile çalışmaktadır. Orange pi yerine kendi bilgisayarınız veya raspberry pi kullana bilirsiniz. Ancak bu yazıdaki kodları ortama göre değiştirmek gerekecektir.
Bu web serverin amacı lokal ağ üzerinde Orange pi ve NodeMCU’nun haberleşerek web tarayıcısı üzerinden cihazları kontrol etmektir.
Bu örnekte aşağıdaki görselde görüldüğü gibi iki lamba kontrol edilmektedir. Lamba 1 NodeMCU üzerinde, Lamba 2 ise Orange pi üzerinde çalışmaktadır. Not: sıcaklık bilgisi NodeMCU üzerinden bilgi alınması için “random(0,50)” komutuyla test amaçlı eklenmiştir. Gerçek sıcaklık değildir. 🙂
NodeMCU(Lamba 1) üzerindeki D0 pini, Orange pi(Lamba 2) üzerindeki GPIO 7 pini kullanılmıştır.

Temel python, html ve css bilgisini kullanarak kendi nesnelerin interneti (Internet of Things) projenizi bu şekilde yapabilirsiniz.
Öncelikle NodeMCU tarafında çalışan python kodlarını yazıp yüklemek için Zerynth Studio programı kullanıldı. Bu programı yüklemek ve nasıl kullanıldığına göz atmak için aşağıdaki linklere bakabilirsiniz:
Zerynth Studio : https://www.zerynth.com/zerynth-studio/
Bu program içerisinde bir çok örnek mevcut, örnekleri incelemek ve kullanımını görmek için şu linke bakabilirsiniz: Zerynth Docs documentation
NodeMCU üzerine python kodları yüklemek için firmware ve virtualize gibi bazı işlemleri yapmak gerekiyor bu işlemler programın web sitesinde ve docs documentation sitesinde bulunmaktadır.
Programı kurup, NodeMCU’ya kod yüklemek için hazır hale getirdikten sonra yeni dosya açıp aşağıdaki kodları yazarak NodeMCU içerisine yüklüyoruz. Kodların daha hızlı çalışması için print komutlarını silebilirsiniz:
NOT: Aşağıdaki tüm kodların içindeki ip adreslerini kullandığınız NodeMCU ve Orange pi ip adreslerine göre güncelleyiniz. Bu projede NodeMCU ip adresi :192.168.1.176 ve html kodları içinde yer alan Orange pi ip adresi: 192.168.1.70 dir.
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 |
############################################################################### # NodeMCU web server # www.elektromaker.com # NodeMCU üzerindeki D0 pini kontrol edilecektir. # ############################################################################### import streams import socket from wireless import wifi from espressif.esp8266wifi import esp8266wifi as wifi_driver streams.serial() pinMode(LED0,OUTPUT) wifi_driver.auto_init() #Statik ip almak için aşağıdaki komut kullanıldı: wifi.set_link_info<span class="sig-paren">(</span><em>ip</em>, <em>mask</em>, <em>gw</em>, <em>dns</em><span class="sig-paren">)</span> wifi.set_link_info("192.168.1.176", "255.255.255.0", "192.168.1.1", "192.168.1.1") print("Baglanti kuruluyor...") try: #Ağ adınızı ve şifrenizi aşağıdaki satıra yazınız wifi.link("Ag adınız",wifi.WIFI_WPA2,"Ag sifreniz") except Exception as e: print("Baglanti kurulamadi :(", e) while True: sleep(1000) print("Aga baglandi") info = wifi.link_info() print("IP adresi:",info[0]) sock = socket.socket() sock.bind(80) sock.listen() while True: try: print("Baglanti icin bekleniyor...") clientsock,addr = sock.accept() print("Gelen baglanti IP adresi",addr) client = streams.SocketStream(clientsock) line = client.readline() # aşağıda web serverden gelen bilgi okunarak lamba kontrol edilir oku = line print(oku[5:6]) #on butonuna basılırsa gelen bilgi "1" Lamba açılır if oku[5:6] == "1": print("on") digitalWrite(LED0, HIGH) #off butonuna basılırsa gelen bilgi "0" Lamba kapatılır if oku[5:6] == "0": print("off") digitalWrite(LED0, LOW) while line!="\n" and line!="\r\n": line = client.readline() print("HTTP request received!") print("HTTP/1.1 200 OK\r",stream=client) print("Content-Type: text/html\r",stream=client) print("Connection: close\r\n\r",stream=client) #aşağıdaki satırda bilgi server olarak bilgi göndermeye örnektir. #Tarayıcıdan her istek geldiğinde 0 ile 50 arası bir sayı ekrana yazdırılır. print("<html><body>Hello Zerynth!",random(0,50),"</body></html>",stream=client) client.close() except Exception as e: print("Baglanti saglanamadi:",e) |
Orange pi üzerindeki kodlara geçmeden önce aşağıdaki python modüllerini terminal üzerinden kurmanız gerekir.
1-Orange pi GPIO pinlerini python3 ile kontrol etmemizi sağlayan python-periphery kütüphanesi kurulur:
Not: python-periphery ile ilgili örnekler ve daha fazla bilgi için aşağıdaki linklere bakınız.
http://python-periphery.readthedocs.io/en/latest/index.html
https://github.com/vsergeev/python-periphery
1 2 3 4 5 |
sudo apt-get update sudo apt-get install python-dev git clone https://github.com/vsergeev/python-periphery.git cd python-periphery sudo python setup.py install |
2-Flask modülü kurulur:
1 2 3 |
sudo apt-get install python-pip python-flask sudo apt-get install python3-setuptools sudo pip3 install flask |
3-BeautifulSoup modülü kurulur:
1 |
sudo apt-get install python3-bs4 |
İsterseniz bu projeyi NodeMCU kullanmadan sadece Orange pi ile yapabilirsiniz. Şimdi Orange pi Üzerinde çalışan kodlara bakalım. Orange pi için masaüstüne server isimli dosya açıp içine aşağıdaki gibi dosyaları açıyoruz.

Yukarıdaki resimdeki gibi dosya bağlantılarımızı hazırladıktan sonra aşağıdaki; server.py python dosyasını static dosyasının içine, buton.css dosyasını /static/css dosyasının içine ve node.html dosyasını /templates dosyasının içine kaydediyoruz. NOT: buton.css dosyası olmadan da kodlarınız çalışır ancak butonların şekillerini ve renklerini göremezsiniz. Standart html buton biçimleri görünür.
1- server.py dosyası:
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 |
# -*- coding: utf-8 -*- from periphery import GPIO from flask import Flask, render_template, request from bs4 import BeautifulSoup import urllib.request import requests app = Flask(__name__) GPIO(7, "out") GPIO(7, "low") @app.route('/') def student(): url = "http://192.168.1.176" url_oku = urllib.request.urlopen(url) soup = BeautifulSoup(url_oku, 'html.parser') a = str(soup.body) sayi = a[20:23] return render_template("node.html", number=sayi) @app.route('/',methods = ['POST', 'GET']) def result(): if request.method == 'POST': result = request.form oku = (result['Buton']) if oku == '1_off': print('Node_OFF') r = requests.get("http://192.168.1.176/1") print(r.status_code) if oku == '1_on': print('Node_ON') r = requests.get("http://192.168.1.176/0") print(r.status_code) if oku == '2_off': print('Orange_OFF') GPIO(7, "low") if oku == '2_on': print('Orange_ON') GPIO(7, "high") return render_template('node.html') #return render_template("result.html",result = result) if __name__ == '__main__': app.jinja_env.auto_reload = True app.config['TEMPLATES_AUTO_RELOAD'] = True app.run(host='0.0.0.0', port=80, debug = True) |
2- buton.css dosyası:
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 |
body { background: #555; } .btn-style{ border : solid 2px #c7c7c7; border-radius : 5px 5px 20px 20px ; moz-border-radius : 5px 5px 20px 20px ; font-size : 20px; color : #186480; padding : 2px 10px; background : #ffffff; background : -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#e6e6e6)); background : -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); background : -webkit-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); background : -o-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); background : -ms-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); background : linear-gradient(top, #ffffff 0%, #e6e6e6 100%); filter : progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#e6e6e6',GradientType=0 ); } .btn-yesil{ border : solid 1px #288c1a; border-radius : 20px 3px 20px 4px ; moz-border-radius : 20px 3px 20px 4px ; -webkit-box-shadow : 0px 0px 1px rgba(0,0,0,0.7); -moz-box-shadow : 0px 0px 1px rgba(0,0,0,0.7); box-shadow : 0px 0px 1px rgba(0,0,0,0.7); font-size : 20px; color : #ffffff; padding : 1px 17px; background : #31fa1e; background : -webkit-gradient(linear, left top, left bottom, color-stop(0%,#31fa1e), color-stop(100%,#30ab00)); background : -moz-linear-gradient(top, #31fa1e 0%, #30ab00 100%); background : -webkit-linear-gradient(top, #31fa1e 0%, #30ab00 100%); background : -o-linear-gradient(top, #31fa1e 0%, #30ab00 100%); background : -ms-linear-gradient(top, #31fa1e 0%, #30ab00 100%); background : linear-gradient(top, #31fa1e 0%, #30ab00 100%); filter : progid:DXImageTransform.Microsoft.gradient( startColorstr='#31fa1e', endColorstr='#30ab00',GradientType=0 ); } .btn-kirmizi{ border : solid 1px #cf4043; border-radius : 20px 3px 20px 4px ; moz-border-radius : 20px 3px 20px 4px ; -webkit-box-shadow : 0px 0px 1px rgba(0,0,0,0.7); -moz-box-shadow : 0px 0px 1px rgba(0,0,0,0.7); box-shadow : 0px 0px 1px rgba(0,0,0,0.7); font-size : 20px; color : #ffffff; padding : 1px 17px; background : #f03943; background : -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f03943), color-stop(100%,#bd0606)); background : -moz-linear-gradient(top, #f03943 0%, #bd0606 100%); background : -webkit-linear-gradient(top, #f03943 0%, #bd0606 100%); background : -o-linear-gradient(top, #f03943 0%, #bd0606 100%); background : -ms-linear-gradient(top, #f03943 0%, #bd0606 100%); background : linear-gradient(top, #f03943 0%, #bd0606 100%); filter : progid:DXImageTransform.Microsoft.gradient( startColorstr='#f03943', endColorstr='#bd0606',GradientType=0 ); } .btn-sic{ border : solid 1px #ff0000; border-radius : 6px; moz-border-radius : 6px; font-size : 20px; color : #000000; padding : 1px 17px; background : #d67c7c; background : -webkit-gradient(linear, left top, left bottom, color-stop(0%,#d67c7c), color-stop(100%,#eb1515)); background : -moz-linear-gradient(top, #d67c7c 0%, #eb1515 100%); background : -webkit-linear-gradient(top, #d67c7c 0%, #eb1515 100%); background : -o-linear-gradient(top, #d67c7c 0%, #eb1515 100%); background : -ms-linear-gradient(top, #d67c7c 0%, #eb1515 100%); background : linear-gradient(top, #d67c7c 0%, #eb1515 100%); filter : progid:DXImageTransform.Microsoft.gradient( startColorstr='#d67c7c', endColorstr='#eb1515',GradientType=0 ); } |
3- node.html kodları:
Not: Kodların içindeki IP adresi olan yere kendi orange pi ip adresini yazmanız gerekiyor.
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 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <!-- Cep telefonu ekranına uyumluluk için alttaki iki satır eklendi --> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Web Server</title> <link href="{{ url_for('static', filename='css/buton.css') }}" rel="stylesheet" /> <meta http-equiv="refresh" content="5" > </head> <body> <!--Aşağıdaki ip adresi olan yere orange pi ip adresi yazılacak --> <form action = "http://192.168.1.70:80/" method = "POST"> <input type="button" name="btn" class="btn-style" value="Lamba 1" /> <button type="submit" name="Buton" class="btn-yesil" value="1_on" > on </button> <button type="submit" name="Buton" class="btn-kirmizi" value="1_off"> off </button> <br/><br/> <input type="button" name="btn" class="btn-style" value="Lamba 2" /> <button type="submit" name="Buton" class="btn-yesil" value="2_on" > on </button> <button type="submit" name="Buton" class="btn-kirmizi" value="2_off"> off </button> </form> <br/> <input type="button" name="btn" class="btn-style" value="Sıcaklık" /> <input type="button" name="btn" class="btn-sic" value= {{number}}°C /> <style type="text/css"> body { background: #555; } </style> </body> </html> <!-- --> |
Kodları yazdıktan sonra terminali açıp aşağıdaki şekilde python kodlarını orange pi üzerinde çalıştırabiliriz.
1 2 3 |
cd Desktop cd server sudo python3 server.py |
Kodlar çalışınca terminal ekranında server kurulduğuna dair bazı bilgiler gelir. Eğer herhangi bir hata alırsanız dosya yolunun doğru olduğuna bakınız veya Orange pi kartını yeniden başlatıp deneyiniz.
Artık işlemlerimiz tamamlanmış oldu orange pi kartını yeniden başlatıp cep telefonu üzerinden web tarayıcısını açıp orange pi kartının ip adresini yazdığınızda aşağıdaki ekren karşınıza gelecektir. Ip adresini öğrenmek için orange pi terminali açıp ifconfig komutunu kullanabilirsiniz.

Açılışta Python Kodlarını Otomatik Çalıştırma (Run Python script at startup in Orange pi or Linux)
Orange pi her açıldığında serverin otomatik olarak başlatılmasını istersek, yani server.py dosyası her açılışta otomatik olarak çalıştırılmak istenirse aşağıdaki adımları yapmamız gerekir.(Dosyalar /bin klasörüne kopyalanır)
1-server.py dosyasının /bin klasörüne kopyalanması:NOT: dosya yolundaki hakan yazan yere kendi dosya yolun adınızı yazmalısınız.
1 |
sudo cp -i /home/hakan/Desktop/NodeMCU/server.py /bin |
2-server.py dosyasını taşıdıktan sonra bunu açılışta başlatmak için terminale şu komut yazılır:
1 |
sudo crontab -e |
Alttaki fotoğrafta görüldüğü gibi açılan dosyanın en altına şu satır yazılır:
1 |
@reboot python3 /bin/server.py & |

En alt satıra eklenen komutun önunde # işareti olmamalıdır. Ekledikten sonra önce CTRL+O ile dosyayı kaydedip, CTRL+X ile kapatabilirsiniz.
4-Python kodlarımızın içindeki html ve css kodlarınında çalışması için server klasörünün içinde bulunan static ve templates klasörlerinin de /bin klasörüne kopyalanması gerekir. Önce statik dosyasını kopyalayalım:
1 |
sudo cp -i /home/hakan/Desktop/NodeMCU/static /bin |
Daha sonra templates klasörünü kopyalayalım:
1 |
sudo cp -i /home/hakan/Desktop/NodeMCU/templates /bin |
Artık işlemlerimiz tamamlanmış oldu orange pi kartını yeniden başlatıp cep telefonu üzerinden web tarayıcısını açıp orange pi kartının ip adresini yazdığınızda aşağıdaki ekren karşınıza gelecektir. Ip adresini öğrenmek için orange pi terminali açıp ifconfig komutunu kullanabilirsiniz.
