Raspberry Pi的一個(gè)流行應(yīng)用是構(gòu)建Web服務(wù)器。為此,我們可以使用不同的技術(shù),如Python、Node.JS甚至PHP。由于Raspberry Pi的絕大多數(shù)腳本都是用Python編寫的,因此使用Python創(chuàng)建REST API接口也是合情合理的。然后,我們可以調(diào)用特定的函數(shù),例如控制或讀取GPIO。這可以方便地控制LED或其他傳感器/模塊。其美妙之處在于,我們可以使迄今為止為Raspberry Pi用Python編寫的幾乎所有代碼都可以輕松通過REST API進(jìn)行調(diào)用。因此,在本教程中,我們將使用FastAPI創(chuàng)建這樣一個(gè)接口,并探討如何擴(kuò)展和保障其安全。
所需硬件部件
原則上,本教程不需要太多的配件。但是,由于我們想測試我們的設(shè)置是否有效,我建議使用以下部件:
Raspberry Pi
LED燈
330Ω電阻
面包板
雌性-雌性跳線
當(dāng)然,你可以根據(jù)自己的需求進(jìn)行擴(kuò)展,并連接傳感器(如?溫度傳感?器等),我們可以通過API對其進(jìn)行查詢。
什么是REST API?
API(應(yīng)用程序編程接口)是一種可以通過URL等調(diào)用的接口。REST(表述性狀態(tài)轉(zhuǎn)移)概括了一些原則,描述了接口應(yīng)該如何表現(xiàn),例如,GET請求應(yīng)該是只讀的,并且不應(yīng)該更改服務(wù)器上的任何內(nèi)容。另一方面,POST命令允許創(chuàng)建新實(shí)體(例如,書籍的新實(shí)例)。你可以在這里了解更多關(guān)于實(shí)現(xiàn)的信息。
Raspberry Pi上的設(shè)置
在本教程中,Raspberry Pi上的設(shè)置非常簡單,因?yàn)槲覀冎皇褂靡粋€(gè)LED和一個(gè)按鈕。當(dāng)然,你的場景可以(應(yīng)該!)與此不同,因?yàn)樗皇且粋€(gè)示例,因此也非常簡單。
LED通過330Ω串聯(lián)電阻連接到GPIO 17,按鈕連接到3.3V和GPIO 21。
此外,我們在以下內(nèi)容中使用GPIO的BCM編號,而不是板載編號:
Raspberry PiGPIO引腳分配
Python REST API 的軟件組件
現(xiàn)在,我們將逐步創(chuàng)建API。首先,我們準(zhǔn)備所需的工具。之后,我們創(chuàng)建并擴(kuò)展我們的REST API,以切換或讀取GPIO。最后但同樣重要的是,我們要保障API的安全,以免任何人都可以訪問它。
順便說一下:你也可以在Github上找到我們將逐步講解的整個(gè)代碼。
安裝庫
在開始之前,我們需要Python3和一些庫,我們通過包安裝器pip加載它們。
sudo apt-get install python3 python3-pip
之后,我們可以安裝所需的Python庫:
pip3 install fastapi uvicorn[standard] rpi.gpio
可以在各自的文檔頁面(fastapi、uvicorn、rpi.gpio)上找到更多信息。
入門:首先通過API讀取狀態(tài)
讓我們開始第一次測試。為此,我們創(chuàng)建一個(gè)簡單的Python腳本。
sudo nano main.py
腳本內(nèi)容如下:
from fastapi import FastAPIimport RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False) app = FastAPI() @app.get("/read/{gpio}")def read_root(gpio: int): GPIO.setup(gpio, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) return {"gpio": gpio, "on": GPIO.input(gpio)}
使用CTRL+O保存文件,并使用CTRL+X關(guān)閉nano編輯器。之后,我們就可以啟動程序了。
uvicorn main:app --reload
現(xiàn)在,你可以在Raspberry Pi的瀏覽器中打開以下URL:http://127.0.0.1:8000/read/17
如果按鈕連接到不同的引腳,你可以更改GPIO編號。如果你沒有按下按鈕,結(jié)果將如下所示:
{"gpio":17,"on":false}
這是我們在此端點(diǎn)下定義的響應(yīng)。如果你按下按鈕并再次調(diào)用URL,結(jié)果將發(fā)生變化。僅用幾行代碼,我們就編寫了第一個(gè)REST端點(diǎn)。但現(xiàn)在我們想對其進(jìn)行擴(kuò)展。
擴(kuò)展我們的Python API——設(shè)置GPIO狀態(tài)
純讀取有點(diǎn)無聊,所以我們當(dāng)然還想控制和設(shè)置GPIO。因此,我們創(chuàng)建了另一個(gè)端點(diǎn)(這次是PATCH,因?yàn)槲覀円膬?nèi)容):
from fastapi import FastAPIfrom pydantic import BaseModelimport RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False) app = FastAPI() class SetGPIO(BaseModel): on: bool @app.get("/read/{gpio}")def read_root(gpio: int): GPIO.setup(gpio, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) return {"gpio": gpio, "on": GPIO.input(gpio)} @app.patch("/set/{gpio}")def read_item(gpio: int, value: SetGPIO): if value.on: GPIO.setup(gpio, GPIO.OUT, initial=GPIO.HIGH) else: GPIO.setup(gpio, GPIO.OUT, initial=GPIO.LOW) return {"gpio": gpio, "on": value.on}
如您所見,第一個(gè)參數(shù)再次是GPIO編號,
你可以使用Postman、瀏覽器擴(kuò)展或cURL(sudo apt-get install curl)。我使用了后者:
curl -X PATCH http://127.0.0.1:8000/set/21 -H "Content-Type: application/json" -d '{"on": true}'
這樣,LED就亮了!
順便說一下,你可以在http://127.0.0.1:8000/docs找到API文檔,這是使用Swagger/OpenAPI自動生成的。為了使響應(yīng)更具可讀性,我們定義了模型(response_model)。這只是一個(gè)具有屬性的類,在端點(diǎn)的定義中,我們聲明將返回此模型。
from fastapi import FastAPIfrom pydantic import BaseModelimport RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False) app = FastAPI() class GpioStatusResponse(BaseModel): gpio: int on: bool class SetGPIO(BaseModel): on: bool @app.get("/read/{gpio}", response_model=GpioStatusResponse)def read_root(gpio: int): GPIO.setup(gpio, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) return GpioStatusResponse(gpio=gpio, on=GPIO.input(gpio)) @app.patch("/set/{gpio}", response_model=GpioStatusResponse)def read_item(gpio: int, value: SetGPIO): if value.on: GPIO.setup(gpio, GPIO.OUT, initial=GPIO.HIGH) else: GPIO.setup(gpio, GPIO.OUT, initial=GPIO.LOW) return GpioStatusResponse(gpio=gpio, on=value.on)
最后一項(xiàng)練習(xí):構(gòu)建一個(gè)端點(diǎn)(POST),用于在GPIO上激活PWM,以便我們能夠調(diào)節(jié)LED的亮度(點(diǎn)擊此處訪問PWM文檔)。
https://sourceforge.net/p/raspberry-gpio-python/wiki/PWM/此外,您現(xiàn)在擁有足夠的資源來構(gòu)建一個(gè)與用戶界面交互的GPIO,例如:
https://github.com/tutRPi/Raspberry-Pi-Simple-Web-GPIO-GUI
安全性——基本認(rèn)證和其他方法
如果我們開放Raspberry Pi的8000端口,任何人都可以訪問該API。我們要防止這種情況發(fā)生,并加入認(rèn)證機(jī)制。為此,我們有幾種選擇:
1.每次調(diào)用API時(shí),都會在請求頭中發(fā)送用戶名和密碼。為此,我們使用基本認(rèn)證,并在調(diào)用時(shí)驗(yàn)證數(shù)據(jù)的正確性。
2.另外,我們還可以使用帶有JWT(JSON Web Tokens)的oauth2,它們也是通過請求頭發(fā)送的。為了簡化起見,本教程中不會進(jìn)行此操作。如果您仍然想實(shí)現(xiàn)它(作為練習(xí)),可以在此處了解更多相關(guān)信息。
現(xiàn)在,我們再次打開腳本并相應(yīng)地進(jìn)行調(diào)整:
from fastapi.security import HTTPBasic, HTTPBasicCredentialsfrom pydantic import BaseModelfrom fastapi import Depends, FastAPI, HTTPException, statusimport RPi.GPIO as GPIOimport secrets GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False) app = FastAPI()security = HTTPBasic() class GpioStatusResponse(BaseModel): gpio: int on: bool class SetGPIO(BaseModel): on: bool def get_current_username(credentials: HTTPBasicCredentials = Depends(security)): correct_username = secrets.compare_digest(credentials.username, "admin") correct_password = secrets.compare_digest(credentials.password, "passw0rd") if not (correct_username and correct_password): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect email or password", headers={"WWW-Authenticate": "Basic"}, ) return credentials.username @app.get("/read/{gpio}", response_model=GpioStatusResponse)def read_root(gpio: int, username: str = Depends(get_current_username)): GPIO.setup(gpio, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) return GpioStatusResponse(gpio=gpio, on=GPIO.input(gpio)) @app.patch("/set/{gpio}", response_model=GpioStatusResponse)def read_item(gpio: int, value: SetGPIO, username: str = Depends(get_current_username)): if value.on: GPIO.setup(gpio, GPIO.OUT, initial=GPIO.HIGH) else: GPIO.setup(gpio, GPIO.OUT, initial=GPIO.LOW) return GpioStatusResponse(gpio=gpio, on=value.on)
為了使查詢能夠成功進(jìn)行,我們需要包含用戶名和密碼(第24/25行)。使用curl或Postman可以很容易地實(shí)現(xiàn)這一點(diǎn):
curl -X PATCH http://127.0.0.1:8000/set/21 -H "Content-Type: application/json" -d '{"on": false}' -u "admin:passw0rd"
最后但同樣重要的是:如果您希望通過互聯(lián)網(wǎng)訪問API(即向外部世界開放您的端口),建議使用SSL證書(如Let’s Encrypt),以確保連接加密。您可以在此頁面上了解更多相關(guān)信息。
結(jié)論
使用FastAPI,我們可以非常輕松、快速地創(chuàng)建一個(gè)REST接口,并調(diào)用特定于Raspberry Pi的函數(shù)。通過它,我們可以控制GPIO、讀取傳感器數(shù)據(jù)等等。如果外部系統(tǒng)需要調(diào)用Raspberry Pi,這是一個(gè)簡單且清晰的解決方案。然而,您應(yīng)該注意適當(dāng)?shù)纳矸蒡?yàn)證,以確保不是每個(gè)人都可以遠(yuǎn)程控制Raspberry Pi。
作為Python REST API的替代方案,有諸如MQTT之類的解決方案:如果只需要傳輸/接收數(shù)據(jù),并且沒有公共API,MQTT是一個(gè)不錯(cuò)的選擇。如果我們?nèi)匀恍枰狝PI,也可以使用Node.JS來切換GPIO。總的來說,我覺得通過Python的解決方案更加舒適,而且它擁有最多的兼容擴(kuò)展。
-
GPIO
+關(guān)注
關(guān)注
16文章
1278瀏覽量
53691 -
樹莓派
+關(guān)注
關(guān)注
121文章
1964瀏覽量
107097
發(fā)布評論請先 登錄
為什么樹莓派GPIO輸入的時(shí)候會出現(xiàn)錯(cuò)誤?
詳解樹莓派的gpio功能及實(shí)用方法
樹莓派gpio應(yīng)用
樹莓派gpio接口及編程方法
樹莓派的gpio有什么用_怎么用
用網(wǎng)頁控制樹莓派的GPIO引腳

樹莓派控制PWM控制電機(jī)轉(zhuǎn)速

樹莓派接繼電器的使用

使用樹莓派GPIO口點(diǎn)亮雙色LED燈

基于樹莓派點(diǎn)亮RGB三基色LED燈

評論