Tietokoneiden näyttöjä, joissa näkyy kuvaa automaatiolaboratorion laitteistosta. Monitoreiden takana näkyy sama laitteisto kuin kuvissa.

timohei.net / Opintojaksot / Opintojaksot / Älykkään sähkölaitteen projekti / Web-käyttöliittymän luominen /
I/O-liitynnän määrittely

Raspberry Pi voidaan kytkeä ulkopuolisiin komponentteihin ns. GPIO-liitynnän (General Purpose Input/Output) kautta. Liitynnän ohjaus voidaan toteuttaa esimerkiksi web-palvelimen ja Python-kielisten sovellusten avulla, kuten tämän sivun esimerkissä.

Python-skripti

Luo tiedosto app.py, kopioi alla oleva sovellus siihen ja talleta se hakemistoon, jossa aiot käynnistää web-palvelimen (esimerkiksi hakemisto ~/web-server -> tiedosto ~/web-server/app.py.

# coding: utf-8
# Jotta ääkköset toimisivat nettisivulla oikein, pitää web-palvelin
# määritellä käyttämään UTF-8 -koodausta

import RPi.GPIO as GPIO # Noudetaan GPIO:n käsittelyssä tarvittava kirjasto RPi.GPIO
                        # ja nimetään se tämän sovelluksen sisällä lyhyemmin GPIO
from flask import Flask, render_template, request 
                        # render_template tarvitaan sivupohjien käyttämiseksi
                        # request tarvitaan selaimen lähettämän URL:n tulkitsemiseksi
app = Flask(__name__)

GPIO.setmode(GPIO.BCM) # Käytetään Broadcomin ohjainpiirin GPIO-numeroita (BCM)

# Luodaan pins-niminen assosiaatiotaulukko (dictionary), johon talletetaan kunkin
# I/O-nastan numero, nimi ja tila; esimerkiksi nastan numero 23 nimeksi annetaan
# GPIO 23 ja tilaksi määritellään RPi.GPIO-kirjastosta tuodulla vakiolla GPIO.LOW
# "matala jännite" eli digitaalinen nolla:

pins = {
   23 : {'name' : 'GPIO 23', 'state' : GPIO.LOW},
   24 : {'name' : 'GPIO 24', 'state' : GPIO.LOW},
   }

# Käydään for-luupilla läpi pins-taulukko (eli kaikki I/O-nastat) ja asetetaan
# ne yksi kerrallaan lähdöksi (vakio GPIO.OUT ja pois päältä (GPIO.LOW)

for pin in pins:
   GPIO.setup(pin, GPIO.OUT)
   GPIO.output(pin, GPIO.LOW)

@app.route("/") # määritellään RPi'n web-palvelimen juurisivu, joka löytyy "suoraan"
                # laitteen IP-osoitteella, esimerkiksi http://192.168.0.114/

def main():

   # Luetaan kunkin pinnin tila GPIO:n input-metodilla ja talletetaan
   # se pins-taulukon pinnikohtaiseen alkioon 'state':

   for pin in pins:
      pins[pin]['state'] = GPIO.input(pin)

   # Luodaan taulukkomuuttuja templateData, jonka pins-nimiseksi alkioksi
   # pin-taulukko kopioidaan:

   templateData = {
      'pins' : pins
      }

   # Välitetään templateData html-sivulle main.html, minkä jälkeen kyseinen
   # html-sivu lähetetään selaimelle (lisätietoja: vie hiiri alla olevan rivin
   # yksittäisten sanojen päälle):

   return render_template('main.html', **templateData)

# Alla oleva koodi käsittelee sellaiset selaimen pyynnöt, joissa on I/O-pinnin
# numero ja kyseiselle pinnille tehtävä operaatio (esimerkiksi antamalla selaimen
# osoitteeksi http://192.168.0.114/23/off, RPi asettaa pinnin 23 pois päältä):

@app.route("/<changePin>/<action>")
def action(changePin, action):

   # Selaimelta saatu osoite on tyypiltään merkkijono. Jatkokäsittelyä varten pinnin
   # numero pitää muuttaa merkkijonosta kokonaisluvuksi. Python ei osaa tehdä tätä
   # automaattisesti, joten tehdään muunnos funktiolla int:

   changePin = int(changePin)

   # Luetaan pinnille asetettu nimi ja talletetaan se muuttujaan deviceName:

   deviceName = pins[changePin]['name']

   # Mikäli selaimen osoitteessa annettu operaatio on "on", suoritetaan alla oleva koodi:

   if action == "on":

      # Asetetaan lähtö digitaaliseen ykköstilaan:

      GPIO.output(changePin, GPIO.HIGH)

      # Muodostetaan tehdystä toimenpiteestä kertova teksti ja talletetaan se
      # muuttujaan message - huomaa merkkijonojen yhdistäminen +-merkillä:

      message = "Turned " + deviceName + " on."

   # Mikäli selaimen osoitteessa annettu operaatio on "off", suoritetaan alla oleva koodi:

   if action == "off":

      # Asetetaan lähtö digitaaliseen nollatilaan:

      GPIO.output(changePin, GPIO.LOW)

      # Muodostetaan tehdystä toimenpiteestä kertova teksti kuten edellä:

      message = "Turned " + deviceName + " off."

   # Lopuksi luetaan kaikkien pinnien tilat ja talletetaan ne pins-taulukkoon:

   for pin in pins:
      pins[pin]['state'] = GPIO.input(pin)

   # Kuten main-osiossa, luodaan tässäkin taulukkomuuttuja templateData, jonka
   # pins-nimiseksi alkioksi pin-taulukko kopioidaan:

   templateData = {
      'pins' : pins
   }

   # Kuten main-osiossa, välitetään templateData html-sivulle main.html,
   # minkä jälkeen kyseinen html-sivu lähetetään selaimelle:

   return render_template('main.html', **templateData)

# Käynnistettäessä sovellus komentoriviltä, muuttujassa __name__ on merkkijono
# __main__ ja alla oleva ehtolauseke tunnistaa tämän. Tällöin suoritetaan (run)
# app-niminen sovellus (joka on määritelty tämän tiedoston kolmannella käskyrivillä
# app = Flask(__name__), jossa Flask on web-palvelinohjelma ja __name__
# on sille annettu parametrimuuttuja). Komentoriviltä käynnistettäessä web-palvelimelle
# määritetään lisäksi alla suluissa olevat parametrit (vie hiiri tekstin päälle!): 

if __name__ == "__main__":
   app.run(host='0.0.0.0', port=80, debug=True)

HTML-tiedosto

Luo ~/web-server-hakemistoon alihakemisto templates. Luo sinne tiedosto main.html ja kopioi alla oleva sovellus siihen.

<!DOCTYPE html>
<head>
   <title>Web-palvelin</title>
   <style>
     a {
       text-decoration: none;
     }
     .row {
       border: 3px groove;
       background-color: #e0e0e0;
       font-size: 1.5em;
       width: 8em;
       text-align: center;
     }
   </style>
</head>
<body>
<h1>RPi Web Server</h1>
{% for pin in pins %}
  <h2>{{ pins[pin].name }}
  {% if pins[pin].state == true %}
     is currently <strong>on</strong></h2>
     <div class="row">
        <a href="/{{pin}}/off" role="button">Turn off</a>
     </div>
  {% else %}
     is currently <strong>off</strong></h2>
     <div class="row">
         <a href="/{{pin}}/on" role="button">Turn on</a>
     </div>
  {% endif %}
{% endfor %}

Web-palvelimen käynnistäminen

Web-palvelin käynnistetään pääkäyttäjänä (sudo). Jos käynnistät palvelimen muusta hakemistosta kuin missä Python-skritpi app.py sijaitsee, pitää käynnistämisen yhteydessä antaa myös polku skriptitiedostoon.

Käynnistäminen skriptihakemistossa:
$ cd ~/web-server
$ sudo python app.py
Käynnistäminen muusta hakemistosta käsin:

1) suhteellisen polun kautta:

$ cd ~
$ pwd
 /home/pi
$ sudo python web-server/app.py

TAI 2) absoluuttisen polun kautta:

$ sudo python /home/pi/web-server/app.py

Lähde: Random Nerd Tutorials: Raspberry Pi Web Server using Flask to Control GPIOs

Päivitetty 28.8.2022

<<  Edellinen
(3) CSS-muotoilu
Sivu 4/4Takaisin ensimmäiseen >>
(1) Web-käyttöliittymän luominen
© Timo Heikkinen | timo piste heikkinen at oamk piste fi