切换语言
EN CN
论坛首页 / 树莓派开发者 / 仅仅使用代码,就能点亮树莓派的 GPIO 世界 / 硬件设计 / 仅仅使用代码,就能点亮树莓派的 GPIO 世界

仅仅使用代码,就能点亮树莓派的 GPIO 世界

admin发布于 2025-01-27
9879 浏览

Raspberry Pi的一个流行应用是构建Web服务器。为此,我们可以使用不同的技术,如Python、Node.JS甚至PHP。由于Raspberry Pi的绝大多数脚本都是用Python编写的,因此使用Python创建REST API接口也是合情合理的。然后,我们可以调用特定的函数,例如控制或读取GPIO。这可以方便地控制LED或其他传感器/模块。其美妙之处在于,我们可以使迄今为止为Raspberry Pi用Python编写的几乎所有代码都可以轻松通过REST API进行调用。

因此,在本教程中,我们将使用FastAPI创建这样一个接口,并探讨如何扩展和保障其安全。

所需硬件部件

原则上,本教程不需要太多的配件。但是,由于我们想测试我们的设置是否有效,我建议使用以下部件:

  • Raspberry Pi
  • LED灯
  • 330Ω电阻
  • 面包板
  • 雌性-雌性跳线

当然,你可以根据自己的需求进行扩展,并连接传感器(如温度传感器等),我们可以通过API对其进行查询。

什么是REST API?

API(应用程序编程接口)是一种可以通过URL等调用的接口。REST(表述性状态转移)概括了一些原则,描述了接口应该如何表现,例如,GET请求应该是只读的,并且不应该更改服务器上的任何内容。另一方面,POST命令允许创建新实体(例如,书籍的新实例)。你可以在这里了解更多关于实现的信息。

https://en.wikipedia.org/wiki/REST

Raspberry Pi上的设置

在本教程中,Raspberry Pi上的设置非常简单,因为我们只使用一个LED和一个按钮。当然,你的场景可以(应该!)与此不同,因为它只是一个示例,因此也非常简单。

LED通过330Ω串联电阻连接到GPIO 17,按钮连接到3.3V和GPIO 21。

此外,我们在以下内容中使用GPIO的BCM编号,而不是板载编号:

Raspberry Pi GPIO引脚分配

Python REST API 的软件组件

现在,我们将逐步创建API。首先,我们准备所需的工具。之后,我们创建并扩展我们的REST API,以切换或读取GPIO。最后但同样重要的是,我们要保障API的安全,以免任何人都可以访问它。

顺便说一下:你也可以在Github上找到我们将逐步讲解的整个代码。

https://github.com/tutRPi/raspberry-pi-fastapi-gpio-rest-api

安装库

在开始之前,我们需要Python3和一些库,我们通过包安装器pip加载它们。

sudo apt-get install python3 python3-pip

之后,我们可以安装所需的Python库:

pip3 install fastapi uvicorn[standard] rpi.gpio

可以在各自的文档页面(fastapi、uvicorn、rpi.gpio)上找到更多信息。

https://fastapi.tiangolo.com/

https://www.uvicorn.org/

https://sourceforge.net/p/raspberry-gpio-python/wiki/Examples/

入门:首先通过API读取状态

让我们开始第一次测试。为此,我们创建一个简单的Python脚本。

sudo nano main.py

脚本内容如下:


from fastapi import FastAPI
import 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关闭nano编辑器。之后,我们就可以启动程序了。

uvicorn main:app --reload

现在,你可以在Raspberry Pi的浏览器中打开以下URL:

http://127.0.0.1:8000/read/17

如果按钮连接到不同的引脚,你可以更改GPIO编号。如果你没有按下按钮,结果将如下所示:


{"gpio":17,"on":false}

这是我们在此端点下定义的响应。如果你按下按钮并再次调用URL,结果将发生变化。仅用几行代码,我们就编写了第一个REST端点。但现在我们想对其进行扩展。

扩展我们的Python API——设置GPIO状态

纯读取有点无聊,所以我们当然还想控制和设置GPIO。因此,我们创建了另一个端点(这次是PATCH,因为我们要更改内容):


from fastapi import FastAPI
from pydantic import BaseModel
import 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}

如您所见,第一个参数再次是GPIO编号,

你可以使用Postman、浏览器扩展或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自动生成的。为了使响应更具可读性,我们定义了模型(response_model)。这只是一个具有属性的类,在端点的定义中,我们声明将返回此模型。


from fastapi import FastAPI
from pydantic import BaseModel
import 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)

最后一项练习:构建一个端点(POST),用于在GPIO上激活PWM,以便我们能够调节LED的亮度(点击此处访问PWM文档)。

https://sourceforge.net/p/raspberry-gpio-python/wiki/PWM/

此外,您现在拥有足够的资源来构建一个与用户界面交互的GPIO,例如:

https://github.com/tutRPi/Raspberry-Pi-Simple-Web-GPIO-GUI

安全性——基本认证和其他方法

如果我们开放Raspberry Pi的8000端口,任何人都可以访问该API。我们要防止这种情况发生,并加入认证机制。为此,我们有几种选择:

1.每次调用API时,都会在请求头中发送用户名和密码。为此,我们使用基本认证,并在调用时验证数据的正确性。

2.另外,我们还可以使用带有JWT(JSON Web Tokens)的oauth2,它们也是通过请求头发送的。为了简化起见,本教程中不会进行此操作。如果您仍然想实现它(作为练习),可以在此处了解更多相关信息。

https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/

现在,我们再次打开脚本并相应地进行调整:from fastapi.security import HTTPBasic, HTTPBasicCredentials


from pydantic import BaseModel
from fastapi import Depends, FastAPI, HTTPException, status
import RPi.GPIO as GPIO
import 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)

为了使查询能够成功进行,我们需要包含用户名和密码(第24/25行)。使用curl或Postman可以很容易地实现这一点:


curl -X PATCH http://127.0.0.1:8000/set/21 -H "Content-Type: application/json" -d '{"on": false}' -u "admin:passw0rd"

最后但同样重要的是:如果您希望通过互联网访问API(即向外部世界开放您的端口),建议使用SSL证书(如Let’s Encrypt),以确保连接加密。您可以在此页面上了解更多相关信息。

https://fastapi.tiangolo.com/deployment/https/

结论

使用FastAPI,我们可以非常轻松、快速地创建一个REST接口,并调用特定于Raspberry Pi的函数。通过它,我们可以控制GPIO、读取传感器数据等等。如果外部系统需要调用Raspberry Pi,这是一个简单且清晰的解决方案。然而,您应该注意适当的身份验证,以确保不是每个人都可以远程控制Raspberry Pi。

作为Python REST API的替代方案,有诸如MQTT之类的解决方案:如果只需要传输/接收数据,并且没有公共API,MQTT是一个不错的选择。如果我们仍然需要API,也可以使用Node.JS来切换GPIO。总的来说,我觉得通过Python的解决方案更加舒适,而且它拥有最多的兼容扩展。

原文地址: https://tutorials-raspberrypi.com/control-all-gpios-with-the-raspberry-pi-rest-api-via-python/

树莓派 Raspberry Pi Raspberry PiCM5 PS3模拟器 模拟器游戏

上海晶珩

上海晶珩是树莓派官方设计合作伙伴和官方代理商,专注于推广树莓派技术在多个行业中的应用,并提供专业技术服务,以加速客户产品研发进程。上海晶珩为物联网(IoT)、工业自动化、人工智能(AI)、工业控制等领域提供全面的工业树莓派解决方案和可靠的工业计算机产品。

  • 上海市嘉罗公路1661号盛创企业家园29号楼
  • +86-159 2148 3028
  • sales@edatec.cn
提交您的留言

提示

提交即表示您同意 EDATEC 的隐私政策

请输入验证码

captcha
0.622663s