Acest tutorial extinde tutorialul anterior, Cum se construiește un LCD RGB controlat prin intermediul unui Tweet, prin adăugarea controlului paginii web. Cu aceasta puteți schimba configurația casetei Tweet de pe laptop, tabletă sau telefon.
Veți învăța tehnici utile în acest tutorial, astfel încât să puteți adăuga controlul paginilor web la propriile proiecte Raspberry Pi.
sudo pip instala tornada
Tot codul pentru acest proiect este disponibil aici:
https://github.com/jerbly/tutorials/tree/master/tweetbox
Pentru a recapitula, pana la sfarsitul tutorialului anterior ai avut un Raspberry Pi cu RGB LCD conectat la Twitter primind tweets publice care se potrivesc cu un filtru. Luminile de fundal RGB ar schimba culoarea în funcție de alte cuvinte potrivite în tweet. Pentru a configura filtrul și harta de culoare a trebuit să modificați codul și să reporniți programul.
În această primă etapă voi adăuga un server web la program. Apoi puteți să accesați o pagină Web și să actualizați configurația live. Voi folosi Tornado, există multe cadre web pentru Python și le-am folosit de-a lungul anilor, dar acum este mergi la cadru. Se bate o mulțime de cutii pentru multe proiecte diferite.
Uitați-vă la Salut Lume exemplu pe pagina Tornado pentru a putea vedea cum să configurați un handler și să porniți un fir de tornadă. Voi folosi același principiu exact aici.
O să iau tweetbox.py
cod din tutorialul anterior și adăugați cadrul web. Pentru început, voi avea un simplu formular care ne va permite să schimbăm ceea ce urmăresc pe Twitter. Mai întâi, adăugați câteva importuri în partea de sus a scriptului:
import tornado.ioloop import tornado.web
Apoi am nevoie de doi agenți de manipulare: una pentru a afișa formularul HTML și oa doua pentru a primi formularul de trimitere:
Clasa MainHandler (tornado.web.RequestHandler): Define (self): self.render ("template / form1.html") clasa ConfigHandler (tornado.web.RequestHandler): def post (auto): config_track = self.get_argument "config_track") restart (config_track) auto.write ("Acum urmărire% s"% config_track) cerere = tornado.web.Application (r "/ config", ConfigHandler) )
Rețineți că MainHandler
utilizări obține
și ConfigHandler
utilizări post
, formularul HTML folosește metoda post pentru a trimite datele formularului înapoi la serverul web. Pentru a servi formularul MainHandler
pur și simplu solicită funcția de redare să aibă un șablon randat și trimis la browser. Mai multe despre asta într-un moment.
Când datele formularului revin ConfigHandler
extrage un argument, config_track
. Acest lucru este trimis unui a repornire
pentru a schimba setările cu tweepy înainte de a reveni la un șir simplu care arată ce este urmărit.
Creați șablonul adăugând un director numit template-uri la directorul sursă și creați form1.html
fișier acolo:
Raspberry Pi Tweetbox
Acesta este un formular foarte simplu, cu o casetă de introducere a textului și un buton de trimitere. Tot ce este necesar în acest stadiu. Apoi creați repornire
funcţie:
restart (track_text): stream.disconnect () time.sleep (5) # Timpul scurt pentru deconectarea firului ... stream.filter (track = [track_text], async = True)
Se deconectează fluxul Twitter și apoi se reconectează cu noul filtru, track_text
, care este ceea ce a fost prezentat din formular. O schimbare importantă, din tutorialul precedent, constă în faptul că firul Twitter rulează în modul asincron, async = Adevărat
. Aceasta rulează conexiunea fluxului într-un fir de fundal, astfel încât serverul web să funcționeze ca fir principal.
Adăugați câteva linii la sfârșit pentru a porni fluxul în modul asincron și pentru a porni apoi serverul web:
flux.filter (track = ['jeremy'], async = True) cerere.listen (8888) tornado.ioloop.IOLoop.instance () start ()
Aceasta pornește ascultarea serverului web pe portul 8888. Punctați un browser web la adresa http: // your-raspi-ipaddress: 8888 / și veți vedea formularul:
Formularul paginii de web a formularelorIntroduceți altceva pentru a urmări zmeură și faceți clic pe Trimiteți. După cinci secunde, va trece la urmărirea acestor tweets.
În această etapă, voi adăuga harta de culoare în configurație, astfel încât să puteți seta pentru a schimba cuvintele care declanșează iluminarea RGB. Deoarece există șapte setări, nu vreau să le reintroduc de fiecare dată când rulez aplicația, așa că le voi salva într-un fișier.
Programul utilizează pickle pentru a salva și a încărca fișierul de configurare, plus există o inițială fisierul exista verificați adăugați aceste importuri în partea de sus:
murătura de import din importul genericpath există
DisplayLoop
clasa este deja responsabil pentru gestionarea backlight_map
așa că voi extinde acest lucru, așa că are grijă de ceea ce urmăresc în prezent, track_text
. Se adaugă aici și metode de citire și scriere a configurărilor:
Clasa DisplayLoop (StreamListener): PICKLE_FILE = '/home/pi/py/tweetbox.pkl' def __init __ (auto): self.lcd = Adafruit_CharLCDPlate () self.lcd.backlight (self.lcd.RED) self.lcd.clear () auto.track_text = 'jeremy' auto.backlight_map = 'roșu': self.lcd.RED, 'verde': self.lcd.GREEN, 'albastru': self.lcd.BLUE, 'galben': auto. lcd.YELLOW, teal: self.lcd.TEAL, 'violet': self.lcd.VIOLET self.msglist = [] self.pos = 0 self.tweet = 'Nimic încă' def write_config (self) = "track_text": auto.track_text, "backlight_map": auto.backlight_map output = open (auto.PICKLE_FILE, 'wb') pickle.dump (date, ieșire) output.close () def read_config (pcl_file): pkl_file = deschide (self.PICKLE_FILE, 'rb') data = pickle.load (pkl_file) pkl_file.close () self.track_text = data ["track_text"] self.backlight_map = data [backlight_map „]
Schimbați managerii de solicitare pentru a avea grijă de culori. De asemenea, mai jos veți vedea că atunci când redă pagina principală pe care o parcurg în configurația curentă. Aceasta înseamnă că pot completa formularul de configurare cu setările curente când este cerut.
clasa MainHandler (tornado.web.RequestHandler): def get (auto): inverted_map = v: k pentru k, v în display_loop_instance.backlight_map.items () self.render ("templates / form3.html", config_track = display_loop_instance .track_text, config_red = inverted_map [Adafruit_CharLCDPlate.RED], config_green = inverted_map [Adafruit_CharLCDPlate.GREEN], config_blue = inverted_map [Adafruit_CharLCDPlate.BLUE], config_yellow = inverted_map [Adafruit_CharLCDPlate.YELLOW], config_teal = inverted_map [Adafruit_CharLCDPlate.TEAL], config_violet = inversat_map [Adafruit_CharLCDPlate.VIOLET]) clasa ConfigHandler (tornado.web.RequestHandler): def post (auto): config_track = self.get_argument ("config_track") colour_map = self.get_argument ("config_red"): Adafruit_CharLCDPlate.RED .get_argument ("config_green"): Adafruit_CharLCDPlate.GREEN, self.get_argument ("config_blue"): Adafruit_CharLCDPlate.BLUE, self.get_argument ("config_yellow"): Adafruit_CharLCDPlate.YELLOW, self.get_argument ("config_teal" , self.get_ argument ("config_violet"): Adafruit_CharLCDPlate.VIOLET set_config (config_track, colour_map) self.write ("Urmărirea% s"% config_track)
O tehnică de observat aici este modul în care inversez harta de culoare. Când o procesez, vreau să fie harta cuvânt> culoare dar când configurez-o în forma pe care o doresc culoare> cuvânt. O înțelegere a dicționarului Python poate fi utilizată pentru a inversa harta într-o singură instrucțiune: v: k pentru k, v în display_loop_instance.backlight_map.items ()
Un nou formular HTML este necesar pentru a suporta setările de culoare. De asemenea, trebuie să popula populetele de formular cu setările curente, utilizând sistemul de șablon Tornado. Acest lucru este foarte simplu, doar iau valorile transmise face
și trageți-le aici în șablon, de exemplu config_track
.
Raspberry Pi Tweetbox
Acum că pot salva și încărca configurația, prima repornire
rutina trebuie să fie puțin mai sofisticată:
def set_config (track_text, colour_map): display_loop_instance.set_text ("actualizarea configurației") stream.disconnect () display_loop_instance.track_text = track_text display_loop_instance.backlight_map = colour_map display_loop_instance.write_config () time.sleep (5) deconectați ... stream.filter (track = [display_loop_instance.track_text], async = True) display_loop_instance.set_text ("Configurație actualizată")
Deoarece este mai mult decât o repornire, numele este acum SET_CONFIG
. E aici unde am sunat acum write_config
pentru a salva modificările în fișier.
Tot ce a mai rămas este o serie de modificări pe care le puteți citi în configurație la pornire:
display_loop_instance = DisplayLoop () display_loop_instance.read_config ()
Și pentru a începe fluxul de la acest set mai degrabă decât 'Jeremy'
:
flux = Stream (auth, display_loop_instance) flux.filter (track = [display_loop_instance.track_text], async = True)
Porniți programul, indicați un browser web la http: // your-raspi-ipaddress: 8888 / și veți vedea formularul:
Formular WebExistă câteva lucruri care nu sunt foarte slick despre acest program:
Întârzierea în timp ce configurația se schimbă se datorează naturii asincrone a programului. Există un fir de gestionare a fluxului Twitter, un fir care defilează afișajul și firul principal care rulează serverul web.
Când vreau să modific setările din flux, trebuie să o deconectez și apoi să reconectez cu noile opțiuni. Din păcate, nu există nici un eveniment din tweepy pentru a-mi spune când am deconectat cu succes și așa până acum am întârziat cinci secunde între deconectare și reconectare.
Pentru a elimina această întârziere, ce trebuie să fac este să pornesc o nouă conexiune în timp ce vechea este deconectată, așa că nu trebuie să aștept. Desigur, acest lucru înseamnă că într-un moment pot exista două fluxuri care primesc tweets. Acest lucru ar fi confuz pe ecran, deoarece veți vedea vechea urmărire și noua urmărire combinate.
Prin urmare, chiar înainte de deconectare, voi conecta fluxul vechi la un ascultător care nu face nimic cu mesajele primite. Iată definiția NullListener
și modificările aduse SET_CONFIG
rutină:
NullListener (defunct): def on_data (sine, date): pass def set_config (track_text, color_map): print restarting display_loop_instance.set_text (Actualizarea configurației) #Cuți fluxul vechi asincron fluxul global stream.listener = ) stream.disconnect () display_loop_instance.track_text = track_text display_loop_instance.backlight_map = colour_map display_loop_instance.write_config () #Primați un flux de flux nou = Stream (auth, display_loop_instance) stream.filter (track = [display_loop_instance.track_text], async = True) display_loop_instance.set_text ("Configurație actualizată")
În ceea ce privește Urmărirea acum ... răspuns, versiunea curentă a formularului este trimisă la ConfigHandler
care modifică setările și returnează acest răspuns urât. Într-adevăr ceea ce vreau este ca formularul să reapară cu noile setări în vigoare.
Pot realiza acest lucru redirecționând utilizatorul înapoi la /
URL-ul. De asemenea, nu este nevoie de ConfigHandler
oricum, eu pot defini obține
și post
metode pe MainHandler
și pur și simplu trimiteți formularul acolo:
clasa MainHandler (tornado.web.RequestHandler): def get (auto): inverted_map = v: k pentru k, v în display_loop_instance.backlight_map.items () self.render ("templates / form4.html", config_track = display_loop_instance .track_text, config_red = inverted_map [Adafruit_CharLCDPlate.RED], config_green = inverted_map [Adafruit_CharLCDPlate.GREEN], config_blue = inverted_map [Adafruit_CharLCDPlate.BLUE], config_yellow = inverted_map [Adafruit_CharLCDPlate.YELLOW], config_teal = inverted_map [Adafruit_CharLCDPlate.TEAL], config_violet = inversat_map [Adafruit_CharLCDPlate.VIOLET]) def post (auto): config_track = self.get_argument ("config_track") colour_map = self.get_argument ("config_red"): Adafruit_CharLCDPlate.RED, self.get_argument ("config_green"): Adafruit_CharLCDPlate. GREEN, auto.get_argument ("config_blue"): Adafruit_CharLCDPlate.BLUE, self.get_argument ("config_yellow"): Adafruit_CharLCDPlate.YELLOW, self.get_argument ("config_teal"): Adafruit_CharLCDPlate.TEAL, self.get_argument ("config_violet" Adafruit_CharLCDPlate.V IOLET set_config (config_track, colour_map) # Utilizați o redirecționare pentru a evita problemele legate de reîmprospătarea în browser dintr-un formular post self.redirect ("/") application = tornado.web.Application ([(r "/", MainHandler) ])
În cele din urmă, stilul. A face acest aspect foarte frumos ar putea fi un tutorial complet nou în sine, dar un început foarte bun este de a introduce un cadru care să aibă grijă de o mulțime de stil pentru tine.
Sunt Bootstrap pentru stil și JQuery pentru scripting. Ambele sunt disponibile pe CDN-uri, astfel încât să nu fie nevoie să descărcați nimic, doar să le includeți în secțiunea cap a paginii:
Raspberry Pi Tweetbox
Pentru a face ca formularul să arate mai bine, vom folosi stilul stilului orizontal al lui Bootstrap:
În cele din urmă, pentru a pune un pic de poloneză pe UI vom indica utilizatorului că Raspberry Pi se actualizează atunci când fac clic pe a depune buton. Aceasta implică un pic de Javascript pentru a capta evenimentul de depunere a formularului, modificați textul butonului Se actualizează ... și dezactivați butonul:
Iată interfața web terminată:
Formularul web finalizatAcest tutorial sa extins pe cel precedent pentru a adăuga un interfață web pe RGB LCD Box. Acum puteți controla ceea ce urmăriți pe ecran și culorile de iluminare de fundal pe care le doriți de pe telefon, tabletă sau desktop.