O Raspberry Pi é um microcomputador muito potente que tem a particularidade de ser equipado com um chip que gerencia a conexão Wifi. Isso faz dele um equipamento ideal para desenvolver objetos conectados e, sobretudo, servidores web. Neste tutorial, veremos como criar e hospedar uma interface web para controlar o Raspberry Pi.
Pré-requisitos: Programar o Raspberry Pi, Conectar o Raspberry ao Wifi
Material
- Computador
- Raspberry Pi 3 B+ ou Zero (com Raspbian e conexão remota VNC)
- Fonte de alimentação 5V 2A
Obs: Este tutorial foi escrito para um Raspberry Pi, mas pode ser aplicado a qualquer computador com o Python instalado e acesso ao WiFi.
Código
Para criar uma página web, é necessário um sistema de arquivos: um arquivo HTML combinado com um CSS para descrever a página (front-end) e um script Python para tratar os pedidos enviados do navegador para o servidor (back-end). É possível adicionar arquivos PHP e JavaScript para estruturar e dar funcionalidades à aplicação web.
Para organizar esses arquivos, iremos colocá-los em subpastas:
- Na pasta principal (acwebapp), o script RaspWebInterface.py
- Uma subpasta static, onde colocamos o script css
- Uma subpasta templates para o script HTML
Código Python com Flask
Vamos criar um script Python utilizando o Flask para exibir a página rpi3b_webcontroller.html quando o navegador da web o solicitar. A biblioteca utilizada para gerar um aplicativo web de forma simples é o micro-framework Flask.
Funções para lembrar:
- app=Flask(name) para instanciar o aplicativo Flask
- @app.route(‘/’) decorador para gerir pedidos de URL
- return render_template(‘rpi3b_webcontroller.html’,**templateData) para enviar a página web para o navegador
- return ” OK 200 ” para confirmar a recepção de um pedido
- app.run(debug=True, port=5000, host=’0.0.0.0′,threaded=True) para executar o aplicativo no IP local com a entrada 5000
import os import RPi.GPIO as GPIO from flask import Flask, render_template, Response import datetime GPIO.setmode(GPIO.BCM) dataPin=[i for i in range(2,28)] for dp in dataPin: GPIO.setup(dp,GPIO.IN)#,pull_up_down=GPIO.PUD_UP) data=[] now=datetime.datetime.now() timeString=now.strftime("%Y-%m-%d %H:%M") templateData={ 'title':'Raspberry Pi 3B+ Web Controller', 'time':timeString, 'data':data, } def getData(): data=[] for i,dp in enumerate(dataPin): data.append(GPIO.input(dataPin[i])) return data app=Flask(__name__) @app.route('/') def index(): #return 'hello world!' now=datetime.datetime.now() timeString=now.strftime("%Y-%m-%d %H:%M") data=getData() templateData={ 'title':'Raspberry Pi 3B+ Web Controller', 'time':timeString, 'data':data, } #return render_template('rpi_index.html',**templateData) return render_template('rpi3b_webcontroller.html',**templateData) @app.route('/<actionid>') def handleRequest(actionid): print("Button pressed : {}".format(actionid)) return "OK 200" if __name__=='__main__': os.system("sudo rm -r ~/.cache/chromium/Default/Cache/*") app.run(debug=True, port=5000, host='0.0.0.0',threaded=True) #local web server http://192.168.1.200:5000/ #after Port forwarding Manipulation http://xx.xx.xx.xx:5000/
Código HTML da página
O arquivo .html contém a descrição da página web e também o código JavaScript, que permite gerir os botões.
<!DOCTYPE HTML> <html> <head> <title> AranaCorp </title> <meta http-equiv='content-type' content='text/html; charset=UTF-8'> <meta name='apple-mobile-web-app-capable' content='yes' /> <meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' /> <meta http-equiv='refresh' content='10'> <link rel="stylesheet" href='../static/rpi_style.css'/> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> </head> <body bgcolor = '#70706F'> <hr/><hr> <h1 style='color : #3AAA35;'><center> AranaCorp - {{title}} </center></h1> <hr/><hr> <br><br> <h2><center><p>Date and time : {{time}}</p></center></h2> <br><br><h2> Digital Inputs/Ouputs </h2> <div id='btnContainer'> <center> Pin GPIO2 <input value={{data[0]}} readonly></input> <button id='dig2on'>Turn On </button></a> <button id='dig2off'>Turn Off </button></a><br /> </center> <center> Pin GPIO3 <input value={{data[1]}} readonly></input> <button id='dig3on'>Turn On </button></a> <button id='dig3off'>Turn Off </button></a><br /> </center><center> Pin GPIO4 <input value={{data[2]}} readonly></input> <button id='dig4on'>Turn On </button></a> <button id='dig4off'>Turn Off </button></a><br /> </center><center> Pin GPIO5 <input value={{data[3]}} readonly></input> <button id='dig5on'>Turn On </button></a> <button id='dig5off'>Turn Off </button></a><br /> </center><center> Pin GPIO6 <input value={{data[4]}} readonly></input> <button id='dig6on'>Turn On </button></a> <button id='dig6off'>Turn Off </button></a><br /> </center><center> Pin GPIO7 <input value={{data[5]}} readonly></input> <button id='dig7on'>Turn On </button></a> <button id='dig7off'>Turn Off </button></a><br /> </center><center> Pin GPIO8 <input value={{data[6]}} readonly></input> <button id='dig8on'>Turn On </button></a> <button id='dig8off'>Turn Off </button></a><br /> </center><center> Pin GPIO9 <input value={{data[7]}} readonly></input> <button id='dig9on'>Turn On </button></a> <button id='dig9off'>Turn Off </button></a><br /> </center><center> Pin GPIO10 <input value={{data[8]}} readonly></input> <button id='dig10on'>Turn On </button></a> <button id='dig10off'>Turn Off </button></a><br /> </center><center> Pin GPIO11 <input value={{data[9]}} readonly></input> <button id='dig11on'>Turn On </button></a> <button id='dig11off'>Turn Off </button></a><br /> </center><center> Pin GPIO12 <input value={{data[10]}} readonly></input> <button id='dig12on'>Turn On </button></a> <button id='dig12off'>Turn Off </button></a><br /> </center><center> Pin GPIO13 <input value={{data[11]}} readonly></input> <button id='dig13on'>Turn On </button></a> <button id='dig13off'>Turn Off </button></a><br /> </center><center> Pin GPIO14 <input value={{data[12]}} readonly></input> <button id='dig14on'>Turn On </button></a> <button id='dig14off'>Turn Off </button></a><br /> </center><center> Pin GPIO15 <input value={{data[13]}} readonly></input> <button id='dig15on'>Turn On </button></a> <button id='dig15off'>Turn Off </button></a><br /> </center><center> Pin GPIO16 <input value={{data[14]}} readonly></input> <button id='dig16on'>Turn On </button></a> <button id='dig16off'>Turn Off </button></a><br /> </center><center> Pin GPIO17 <input value={{data[15]}} readonly></input> <button id='dig17on'>Turn On </button></a> <button id='dig17off'>Turn Off </button></a><br /> </center> <center> Pin GPIO18 <input value={{data[16]}} readonly></input> <button id='dig18on'>Turn On </button></a> <button id='dig18off'>Turn Off </button></a><br /> </center><center> Pin GPIO19 <input value={{data[17]}} readonly></input> <button id='dig19on'>Turn On </button></a> <button id='dig19off'>Turn Off </button></a><br /> </center> <center> Pin GPIO20 <input value={{data[18]}} readonly></input> <button id='dig20on'>Turn On </button></a> <button id='dig20off'>Turn Off </button></a><br /> </center> <center> Pin GPIO21 <input value={{data[19]}} readonly></input> <button id='dig21on'>Turn On </button></a> <button id='dig21off'>Turn Off </button></a><br /> </center> <center> Pin GPIO22 <input value={{data[20]}} readonly></input> <button id='dig22on'>Turn On </button></a> <button id='dig22off'>Turn Off </button></a><br /> </center> <center> Pin GPIO23 <input value={{data[21]}} readonly></input> <button id='dig23on'>Turn On </button></a> <button id='dig23off'>Turn Off </button></a><br /> </center> <center> Pin GPIO24 <input value={{data[22]}} readonly></input> <button id='dig24on'>Turn On </button></a> <button id='dig24off'>Turn Off </button></a><br /> </center> <center> Pin GPIO25 <input value={{data[23]}} readonly></input> <button id='dig25on'>Turn On </button></a> <button id='dig25off'>Turn Off </button></a><br /> </center> <center> Pin GPIO26 <input value={{data[24]}} readonly></input> <button id='dig26on'>Turn On </button></a> <button id='dig26off'>Turn Off </button></a><br /> </center> <center> Pin GPIO27 <input value={{data[25]}} readonly></input> <button id='dig27on'>Turn On </button></a> <button id='dig27off'>Turn Off </button></a><br /> </center> </div> <script> // Event Listener var buttonClick = document.getElementById('btnContainer').addEventListener('click', function(event) { if (event.target.nodeName == "BUTTON") { var tar = event.target.id; console.log(tar); $.getJSON('/'+tar, function(data) { //do nothing }); return false; } }); </script> </body> </html>
Foco no código JavaScript
O código JavaScript permite gerir o acionamento dos botões da interface. Para esse fim, criaremos um listener de eventos “click” no elemento “btnContainer”, que irá detectar se um botão (Button) é clicado e devolver o seu identificador através de um pedido json.
// Event Listener var buttonClick = document.getElementById('btnContainer').addEventListener('click', function(event) { if (event.target.nodeName == "BUTTON") { var tar = event.target.id; console.log(tar); $.getJSON('/'+tar, function(data) { //do nothing }); return false; } });
Arquivo rpi_style.css
O arquivo css contém o estilo da página, em particular os botões, para conferir a ela um visual personalizado.
body{ background-color:#70706F; } h1{ color:#3AAA35; } h3{ #width:100%; border: 3px solid #3AAA35; border-radius: 6px; overflow: hidden; text-align:center; padding:20px; } button{ width:auto; height:60px; background-color: #3aaa35;/* Green */ border: none; color: white; /*padding: 15px 32px;*/ text-align: center; vertical-align:middle; text-decoration: none; display: inline-block; font-size: 20px; border-radius: 12px; -webkit-transition-duration: 0.4s; /* Safari */ transition-duration: 0.4s; margin: 5px; } button:hover{ background-color: #4CAF50; /* Green */ color: white; }
Obter o endereço IP do Raspberry Pi
Para acessar a interface web hospedada no Raspberry Pi, é preciso conhecer o endereço IP para poder conectar-se à rede local a partir de um navegador web. Para isso, basta introduzir a linha de comando ifconfig no terminal do Raspberry Pi.
Obs: É possível acessar o Raspberry Pi por fora da rede local realizando um procedimento no roteador no qual o Raspberry Pi está conectado. Este procedimento chama-se “Port Forwarding”.
Resultado
Depois de executar o script Python no Raspberry Pi, pode introduzir o endereço IP do seu Raspberry Pi seguido da porta (aqui 192.168.1.200:5000) no seu computador ou smartphone. A página web deverá então aparecer.
Então já pode ver o que acontece quando os botões do terminal são apertados por meio do aplicativo VNC.
Aplicações
- Criar um sistema de domótica controlável via Wifi
- Controlar o seu Raspberry Pi de qualquer lugar
Fontes
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie