Mă ud picioarele cu „instalator” și javascript

URMĂREȘTE-NE
16,065FaniÎmi place
1,142CititoriConectați-vă

Încercați instalatorul și un pic de JavaScript pentru a construi o API locală simplă pentru exploatarea evenimentelor de migrenă 🧠💻. Doar o atingere rapidă pe telefonul meu înregistrează acum timpul către un CSV – la îndemână! 📱✅

Motivație

După blogul nostru anterior despre monitorizarea presiunii barometrice, prietenul meu Alec Wong a spus „Nu va fi minunat dacă putem doar să apăsăm un buton și va înregistra un eveniment?”.

În acest caz, motivul înregistrării presiunii barometrice este de a vedea dacă există o legătură între evenimentul migrenă și valorile/schimbarea presiunii barometrice etc. Și da, ar fi minunat dacă putem crea o aplicație de ceva de ceva pentru a face înregistrarea mult mai ușoară!

Există multe modalități de a face acest lucru. Modul în care putem maximiza învățarea în mediul R este să folosim plumber Pentru a crea o API pentru noi să interacționăm și să înregistrăm evenimentul! Cazul nostru de utilizare este de fapt destul de simplu. Avem nevoie doar de ceva care să înregistreze un timestamp curent atunci când este clic pe un buton. Simplu!

Dar din moment ce nu am folosit niciodată plumber Înainte, aceasta este o oportunitate excelentă de a o explora! Și, de asemenea, un pic de JavaScript. Din nou, acest blog este mai mult în beneficiul meu, unde servește ca o notă pentru mine. Începem!

Obiective:

Imagine mare

După cum arată imaginea de mai sus, dorim o aplicație pe telefonul nostru care, odată ce a dat clic, va schimba cumva un date de date CSV. Toate acestea pot fi făcute de plumber Setarea unei API la csv. Întrucât vreau doar să pot face acest lucru într -o rețea locală a unui dispozitiv diferit (de exemplu, Raspberrypi), nu trebuie să implementăm acest lucru în Digital Ocean sau un server în sine. Îl putem rula în fundal și set systemctl În cazul în care RPI repornește, indicați -l către 0.0.0.0 Și putem primi/posta prin intermediul IP -ului dispozitivului.

Da, din păcate, acest lucru nu va funcționa dacă nu mai suntem în rețeaua locală, care cel puțin din utilitatea mea, va fi bine. Nu este nevoie să expuneți redirecționarea porturilor. Modul mai sigur ar fi să folosești digitală ocean digital pentru a face acest lucru, astfel încât să nu expuii propriul IP și să deschizi portul publicului. Asta înseamnă și, este posibil să fiți nevoit să plătiți ceva 💰 (de exemplu, 5 $/lună). Poate într -o zi când poate încorpora presiunea barometrică și/sau alte valori

instalator.R

library(plumber)
library(readr)

file <- "migraine.csv"

if (file.exists(file)) {
  df <- read_csv(file)
} else {
df <- tibble(date=as.POSIXct(character()))
}

#* @apiTitle Migraine logger
#* @apiDescription A simple API to log migraine events

#* Return HTML content
#* @get /
#* @serializer html
function() {
  
  # Return HTML code with the log button
  html_content <- '
     
     
     
       Migraine Logger
     
     
       
       
       
       
      
      
     
     
     '
  return(html_content)
}

#* logging 
#* @post /log
function(){
  date_now <- tibble(date=Sys.time())
  df <<- rbind(df,date_now)
  write_csv(df, "migraine.csv")
  list(paste0("you have logged ", date_now$date(1), " to migraine.csv"))
}

#* download data
#* @get /download
#* @serializer csv
function(){
  df
}

Bine, să explorăm codul unul câte unul. Din nou, ca o notă în beneficiul meu.

Încărcați biblioteci, date de încărcare, metadate

library(plumber)
library(readr)

file <- "migraine.csv"

if (file.exists(file)) {
  df <- read_csv(file)
} else {
df <- tibble(date=as.POSIXct(character()))
}

#* @apiTitle Migraine logger
#* @apiDescription A simple API to log migraine events

Cele de mai sus sunt destul de auto-expulzătoare. Indicați -vă spre un fișier, dacă există, citiți -l, dacă nu creați un DataFrame gol. Titlul și descrierea acestei API sunt descrise ca atare.

Să scriem HTML și JavaScript

#* Return HTML content
#* @get /
#* @serializer html
function() {
  
  # Return HTML code with the log button
  html_content <- '
     
     
     
       Migraine Logger
     
     
       
       
       
       
      
      
     
     
     '
  return(html_content)
}
  1. Scheletul #*, mai întâi este comentariul, al doilea este GET / (Metoda HTTP), a 3 -a este Turn this function into HTML output
    Serializator. Practic înseamnă dacă mergem la http://localhost:8000/va returna acest html. Acum dacă ne stabilim GET /helloatunci HTML va arăta și dacă mergeți la http://localhost:8000/hello
  2. Următorul este HTML (fără JavaScript, care este între). Practic, scrieți o rubrică, creați un buton și un rezultat DIV pentru a returna.
  3. JavaScript:
  • document.getElementById("submit").onclick: Când submit butonul a fost dat clic, rulați funcția
  • fetch("/log", { method : "post" }): aceasta este partea în care se va numi POST /log Funcție (vezi mai jos) și rulează -l.
  • .then(response => response.json()): Acesta este un lanț de promisiuni. După finalizarea cererii de preluare, acest lucru ia răspunsul de la server și apelează la metoda .json () pe ea, care analizează corpul de răspuns JSON într -un obiect JavaScript. Această metodă returnează, de asemenea, o promisiune care se rezolvă la datele JSON analizate.
  • .then(data => { const resultDiv = document.getElementById("result"); resultDiv.textContent = data(0); resultDiv.style.display = "block";}): Acesta este următorul pas în lanțul de promisiuni. Odată ce JSON este analizat, acesta găsește elementul HTML cu ID -ul „Rezultatul”. Setează conținutul de text pentru a fi primul element din tabloul de date (date (0)). Face ca elementul să fie vizibil prin setarea proprietății sale de afișare CSS la „blocare”
  • .catch(error => { const resultDiv = document.getElementById("result"); resultDiv.textContent = error.message })};Acest lucru surprinde orice erori care ar putea apărea în timpul funcționării de preluare sau la procesarea răspunsului. Dacă se întâmplă o eroare, găsește elementul HTML cu ID „Rezultat”. Setează conținutul său de text la mesajul de eroare.

Lucrul interesant pe care nu l -am întâlnit este funcția săgeată. response => response.json() mijloace function(response) { return response.json() }.

Mai multe funcții API de instalator:

#* logging 
#* @post /log
function(){
  date_now <- tibble(date=Sys.time())
  df <<- rbind(df,date_now)
  write_csv(df, "migraine.csv")
  list(paste0("you have logged ", date_now$date(1), " to migraine.csv"))
}

#* download data
#* @get /download
#* @serializer csv
function(){
  df
}
  1. POST /log Funcția este locul în care se întâmplă magia. Când este clic pe butonul, acesta va rula această funcție. Acesta va crea un nou rând cu Timestamp -ul curent și îl va adăuga la DataFrame. Apoi scrie -l la migraine.csv. <<- Operatorul este utilizat pentru a atribui o valoare unei variabile în mediul părinte (în acest caz, mediul global). Acest lucru ne permite să modificăm df variabilă definită în afara funcției. list(paste0("you have logged ", date_now$date(1), " to migraine.csv")) va returna un mesaj utilizatorului potrivit căruia evenimentul a fost înregistrat. Aceasta este ceea ce va fi afișat în div cu ID „Rezultat” în HTML.

  2. GET /download Funcția este de a descărca datele. Va returna DataFrame ca fișier CSV atunci când accesați http://localhost:8000/download. @serializer csv Linia îi spune instalatorului să serializeze ieșirea ca fișier CSV.

Ok, hai să o verificăm! Faceți clic pe asta Run API Buton pentru un test rulat!

Ar trebui să vedem așa ceva. Îl puteți testa prin Swagger UI sau puteți merge la adresa fără __doc__ Pentru a ajunge direct la HTML.

Ura! Funcționează, local … acum să vedem dacă funcționează dacă este pe un alt dispozitiv.

Cum să -l rulezi?

  1. Transfer plumber.R sau orice fișier pe care l -ați salvat, la dispozitivul la alegere.
  2. Instalați pachete, desigur
  3. Apoi rulați următorul cod
Rscript -e "pr <- plumber::plumb('plumber.R'); pr |> pr_run(port=8000,host='0.0.0.0')"

Ce face, va rula API -ul instalatorului. Și utilizați un dispozitiv diferit în aceeași rețea, apoi accesați http://your-local-device-ip:8000/ Și ar trebui să vezi ceva de genul următoarelor

imagineimagine

Ura! Funcționează! Acum, să ne asigurăm că îl rulăm în fundal și dacă RPI repornește, va re-rula scriptul folosind systemctl. Toate codul de mai jos trebuie să fie rulat bash

sudo nano /etc/systemd/system/migraine-logger.service

Lipiți acest lucru în migrenă-logger.service

(Unit)
Description=Migraine Logger Plumber API
After=network.target

(Service)
Type=simple
User=pi
WorkingDirectory=/path/to/your/app
ExecStart=/usr/bin/Rscript -e "pr <- plumber::plumb('plumber.R'); pr |> pr_run(port=8000, host='0.0.0.0')"
Restart=on-failure
RestartSec=5

(Install)
WantedBy=multi-user.target
  • Schimba /path/to/your/app în directorul unde plumber.R Fișierul este localizat.

Activați, începeți, verificați starea

sudo systemctl enable migraine-logger.service
sudo systemctl start migraine-logger.service
sudo systemctl status migraine-logger.service

Hurray !!!

Un singur clic pe iOS?

Utilizați browserul dvs. pe iOS pentru a merge la IP -ul și portul dispozitivului dvs. http://192.168.1.11:8000 apoi faceți clic pe Share și creați ecranul de scurtă durată, așa cum este așa

imagineimagine

Apoi, puteți avea o scurtătură pe dispozitivul dvs. iOS care va deschide aplicația și va face clic pe butonul pentru dvs.!

Oportunități de îmbunătățire

  • Acest lucru funcționează numai dacă sunteți în rețeaua locală, puteți extinde acest lucru la picătura digitală ocean, mai ales dacă adăugăm mai multe caracteristici (de exemplu, postați jurnal vechi dacă am fi uitat să înregistrăm una, să arătăm 10 ultime date, să arătăm date barometrice etc.)
  • trebuie să înveți mai multe node.js/javascript, chiar mi -a plăcut să folosești pozitron și Code Runner pentru a putea apela rapid node și rulați întregul script pe consolă
  • trebuie să afli mai multe despre plumberde exemplu, cum să -l implemezi în oceanul digital
  • O parte Python la care am putea traduce este FastApi, trebuie să învățăm și asta, dar implementarea și structura codului ar trebui să fie destul de similară

Lecții învățate

  • Am învățat câteva API simple pentru instalații de instalație
  • Am învățat câteva javascript simplu, a descoperit că acest potențial major pentru proiectele viitoare.
  • Învăţat systemctl

Dacă vă place acest articol:

Dominic Botezariu
Dominic Botezariuhttps://www.noobz.ro/
Creator de site și redactor-șef.

Cele mai noi știri

Pe același subiect

LĂSAȚI UN MESAJ

Vă rugăm să introduceți comentariul dvs.!
Introduceți aici numele dvs.