IoT Starter Raspberry Pi Lumi





5.00/5 (4投票s)
IoT.Starter.Pi.Thing 正在成长为一个通用红外遥控器的雏形
引言
本系列文章面向运行 Linux 的树莓派,始于使用 API 优先设计策略的 IoT.Starter.Pi.Core,该策略通过 Swagger Hub 自动生成 ASP.NET Core Web 服务器。
第二部分介绍了 IoT.Starter.Pi.Thing,它是面向智能家居的雏形,运行在 Linux 的树莓派上。它被设计为物联网项目的入门套件,提供了一个坚实且结构化的平台,以加速产品开发。这个 入门套件概念 鼓励团队立即开始产品开发。
第三部分是 IoT.Starter.Pi.Lirc,专门用于需要红外设备的物联网项目。通过由 Lirc(Linux 红外遥控)驱动的控制台,创建了一个测试环境。现在是时候利用这些测试中学到的东西了。
作为第三部分的补充,本次的目标是扩展 `Thing` Web 服务,以便 API 能够考虑红外遥控器及其相应的代码。由 Lirc 驱动的 `IoT.Starter.Pi.Lumi` 在需要红外支持的物联网项目中非常有用。
届时将有两个 `Things`,作为物联网入门套件提供:
-
IoT.Starter.Pi.Thing:物联网项目的雏形,适用于所有项目
-
IoT.Starter.Pi.Lumi:由 Lirc 驱动的物联网项目雏形,适用于红外 (IR) 项目
API 优先
遵循 API 优先战略,创建了一个新的 API 版本 1.0.2,并在下面进行了总结,向现有规范添加了一个 `RemoteApi` 控制器。`GET` 操作应该能够识别遥控器及其相应的红外代码。`POST` 操作反映了向已安装在 RPI 主机上的遥控器发送红外信号的意图,使用 Lirc 软件。
生成 RemoteApi
在我们将 swagger 文件更改为 1.0.2 版本后,`SwaggerHub` 自动生成了 `RemoteApi` 控制器代码。您还记得“升级 API”吗?这在 IoT.Starter.Pi.Core 中已经解释过,如果您有任何疑问,请参考那里。
然后,对生成的代码进行了修改以适应目标,产生了以下四个操作:
public class RemoteApiController : Controller
{
/// <summary>
///
/// </summary>
/// <remarks>returns ir code from remote</remarks>
/// <param name="remote">Lirc remote</param>
/// <param name="code">ir code</param>
/// <response code="200">All the codes</response>
[HttpGet]
[Route("/motta/home/1.0.1/remotes/{remote}/{code}")]
[ValidateModelState]
[SwaggerOperation("GetRemoteCode")]
[SwaggerResponse(200, typeof(List<string>), "All the codes")]
public virtual IActionResult GetRemoteCode
([FromRoute]string remote, [FromRoute]string code)
{
string example = ("/usr/bin/irsend list " + remote + " " + code).Bash();
return new ObjectResult(example);
}
/// <summary>
///
/// </summary>
/// <remarks>returns all ir codes from remote</remarks>
/// <param name="remote">Lirc remote</param>
/// <response code="200">All the codes</response>
[HttpGet]
[Route("/motta/home/1.0.1/remotes/{remote}")]
[ValidateModelState]
[SwaggerOperation("GetRemoteCodes")]
[SwaggerResponse(200, typeof(List<string>), "All the codes")]
public virtual IActionResult GetRemoteCodes([FromRoute]string remote)
{
string example = (@"/usr/bin/irsend list " + remote + @" """"").Bash();
return new ObjectResult(example);
}
/// <summary>
///
/// </summary>
/// <remarks>returns all installed remotes</remarks>
/// <param name="skip">number of records to skip</param>
/// <param name="limit">max number of records to return</param>
/// <response code="200">All the installed remotes</response>
[HttpGet]
[Route("/motta/home/1.0.1/remotes")]
[ValidateModelState]
[SwaggerOperation("GetRemotes")]
[SwaggerResponse(200, typeof(List<string>), "All the installed remotes")]
public virtual IActionResult GetRemotes([FromQuery]int? skip, [FromQuery]int? limit)
{
string example = (@"/usr/bin/irsend list """" """"").Bash();
return new ObjectResult(example);
}
/// <summary>
///
/// </summary>
/// <remarks>flashes ir code simulating the remote control</remarks>
/// <param name="remote">Lirc remote</param>
/// <param name="code">ir code</param>
/// <response code="200">response</response>
[HttpPost]
[Route("/motta/home/1.0.1/remotes/{remote}/{code}")]
[ValidateModelState]
[SwaggerOperation("SendRemoteCode")]
[SwaggerResponse(200, typeof(ApiResponse), "response")]
public virtual IActionResult SendRemoteCode([FromRoute]string remote,
[FromRoute]string code)
{
string example = (@"/usr/bin/irsend send_once " + remote + " " + code).Bash();
return new ObjectResult(example);
}
}
您可以看到 `irsend` 命令在所有操作中都使用了!`HttpGet` 操作识别红外遥控器及其相应的代码。例如,要列出所有已安装的遥控器,应在主机上通过 Bash 执行以下命令:
pi@lumi:~ $ irsend list "" ""
等效代码如下所示:
public virtual IActionResult GetRemotes([FromQuery]int? skip, [FromQuery]int? limit)
{
string example = (@"/usr/bin/irsend list """" """"").Bash();
return new ObjectResult(example);
}
`HttpPost` 操作具有 `remote` 和 `code` 参数,以便通过输出的 IR LED 正确地发送红外代码。在这种情况下,RPI 主机上的 `irsend` 命令将是:
pi@lumi:~ $ irsend SEND_ONCE LED_44_KEY CYAN
`SendRemoteCode` 显示了如下的等效代码:
public virtual IActionResult SendRemoteCode
([FromRoute]string remote, [FromRoute]string code)
{
string example = (@"/usr/bin/irsend send_once " + remote + " " + code).Bash();
return new ObjectResult(example);
}
正如在 `Lirc-Console` 中已经展示的,由 loune.net 发布的 `ShellHelper` 负责繁重的工作,启动一个 bash 进程,捕获响应,并返回 `string` 结果。
public static class ShellHelper
{
public static string Bash(this string cmd)
{
var escapedArgs = cmd.Replace("\"", "\\\"");
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "/bin/bash",
Arguments = $"-c \"{escapedArgs}\"",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};
process.Start();
string result = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return result;
}
}
home-web-ir:由 Lirc 驱动
为了将 Lirc 支持添加到项目中,我们采用了之前相同的策略,即在构建 Web 服务之前安装 Lirc。Dockerfile 和 docker-compose 中所做的更改如下所示。
lirc-web.dockerfile
下面显示的 `lirc-web.dockerfile` 使用 `dotnet:2.0.0-runtime-stretch-arm32v7` 镜像作为基础。在安装 Lirc 之前,会更新和升级操作系统。安装 Lirc 包后,会将 RPI 配置复制到容器中,确保 RPI 主机上安装的遥控器能够被识别。`/boot/config.txt` 和 `/etc/lirc/lirc_options.conf` 会被更新,远程配置文件会被移动到 `/etc/lirc/lircd.conf.d`,以保持与 RPI 主机上安装的相同设置。
FROM microsoft/dotnet:2.0.0-runtime-stretch-arm32v7 AS base
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV ASPNETCORE_URLS "http://*:5010"
WORKDIR /app
RUN \
apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y \
lirc \
--no-install-recommends && \
rm -rf /var/lib/apt/lists/*
RUN \
mkdir -p /var/run/lirc \
&& rm -f /etc/lirc/lircd.conf.d/devinput.*
COPY Lirc/setup/config.txt /boot/config.txt
COPY Lirc/setup/lirc_options.conf /etc/lirc/lirc_options.conf
COPY Lirc/setup/ir-remote.conf /etc/modprobe.d/ir-remote.conf
COPY Lirc/remotes /etc/lirc/lircd.conf.d
FROM microsoft/dotnet:2.0-sdk AS build
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV ASPNETCORE_URLS "http://*:5010"
WORKDIR /src
COPY *.sln ./
COPY *.dcproj ./
COPY src/IO.Swagger/IO.Swagger.csproj src/IO.Swagger/
RUN dotnet restore src/IO.Swagger/
COPY . .
WORKDIR /src/src/IO.Swagger
RUN dotnet build -c Release -r linux-arm -o /app
FROM build AS publish
RUN dotnet publish -c Release -r linux-arm -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "IO.Swagger.dll"]
然后,与 `IoT.Starter.Pi.Thing` 中使用的相同构建会完成 `home-web-ir` 的构建。
lirc-compose.yml
如下所示,`io.swagger` 服务是 `lirc-compose.yml` 中唯一的更改。由 Lirc 驱动的 Web 服务的镜像已更改为 `home-web-ir`,以区别于之前没有 Lirc 支持的 `home-web`。
<services:
io.swagger:
container_name: home-web-ir
image: josemottalopes/home-web-ir
build:
context: .
dockerfile: Lirc/lirc-web.Dockerfile
ports:
- "5010"
network_mode: bridge
privileged: true
restart: always
volumes:
- /var/run/lirc:/var/run/lirc
environment:
- ASPNETCORE_ENVIRONMENT=Release
在 `/var/run/lirc` 创建了一个 Docker 卷,确保正在运行 `irsend` 命令的容器与 RPI 主机上安装的 Lirc 输出套接字之间能够正确通信。由于 `IoT.Starter.Pi.Thing` 中的其他服务保持不变,因此从 `IoT.Starter.Pi.Thing` 到 `IoT.Starter.Pi.Lumi` 的唯一更改是从 `home-web` 到 `home-web-ir`。
在 RPI 上运行
在运行测试之前,请注意,Lirc 应根据 RPI 设置说明 正确安装和配置。以下是下载并运行 `home-web-ir` 的命令,包括 Docker 卷配置:
docker run --privileged -p 5010:5010 -d -it
--name=home-web-ir -v /var/run/lirc:/var/run/lirc josemottalopes/home-web-ir:latest
下面的会话展示了实时操作。
root@lumi:~# docker run --privileged -p 5010:5010 -d -it
--name=home-web-ir -v /var/run/lirc:/var/run/lirc josemottalopes/home-web-ir:latest
Unable to find image 'josemottalopes/home-web-ir:latest' locally
latest: Pulling from josemottalopes/home-web-ir
0d9fbbfaa2cd: Already exists
b015fdc7d33a: Already exists
60aaa226f085: Already exists
01963091a185: Already exists
a289a8a5c81a: Already exists
9432c55829c7: Already exists
87334e3159b5: Already exists
08a216585c0f: Pull complete
ac1e370475ca: Pull complete
ed21dfb3a130: Pull complete
885b38cb4c35: Pull complete
f8526fd2a07f: Pull complete
Digest: sha256:c374826cfd091ed89fb9da3992bad4d06488fb0152a44d5110401f5ff41de793
Status: Downloaded newer image for josemottalopes/home-web-ir:latest
3c11eeecbc26b258e3d57191f2d4ec5d96e60c1bd4478e334da6ebc77a9c222c
root@lumi:~#
请参考有关 使用最新镜像更新 RPI 的进一步说明,以优化您的 RPI 内存。
检查结果
有几种方法可以使用 Internet 浏览器检查 `home-web-ir`。我们可以使用 Swagger IO 中的“立即试用!”按钮,查看详细响应,例如消息体、响应代码和标头等。另一种简单的方法是直接在浏览器中访问该服务,使用 `curl` 命令或 Swagger IO 提供的“请求 URL”字段。
以下是从运行 Windows 10 的 x64 机器上截取的示例,显示了 RPI 主机上已安装的遥控器。
我们只需在之前的地址后面加上 `remote` 名称即可 `GET` 其相应的红外代码,如下所示:
测试红外输出需要使用 swagger IO 接口,通过“立即试用!”按钮生成 `POST` 命令。您可以看到三星显示器按照预期响应了“KEY_VOLUMEUP
”命令。
结论
首先,在此任务中,我们将 API 改进到了新版本,为 `Thing` 设备添加了红外支持。SwaggerHub 为我们自动生成了代码,并添加了一个新的控制器,该控制器已合并到 `home-web` 项目中。
生成的代码被修改成了一个简单的解决方案,该方案展示了一个连接到红外 LED 的 RPI,它正在成长为一个通用红外遥控器的雏形。然后,您可以使用 `http` 向大量的旧式红外控制家居设备发送命令,例如空调、加热器、RGB 灯、电视、家庭影院等。Lirc 数据库 中有超过 2500 个遥控器,您的遥控器很可能已经包含在其中!
根据您的应用程序目标,您现在应该开发一个自定义的 `home-ui` 项目来处理用户界面,以 `RemoteApi` 作为起点!当前的 ASP.NET MVC `home-ui` 是一个建议,当然还有许多其他工具可以利用 `home-web` API。但请记住,由于两者都使用相同的 .NET 平台,当前的 `home-web` 和 `home-ui` 共享一些镜像层,从而优化了内存。
希望您喜欢这一系列文章,我肯定学到了很多。
尽情享受 **IoT.Starter.Pi.Thing 和 **IoT.Starter.Pi.Lumi**,以加速您的物联网项目!
物联网入门套件
入门套件 | IoT.Starter.Pi.Thing | IoT.Starter.Pi.Lumi |
适用于 | 所有项目 | 红外 (IR) 项目 |
描述 | 物联网的雏形 | 由 Lirc 驱动的物联网红外雏形 |
SSL 代理 | nginx-proxy | nginx-proxy |
用户界面 | home-ui | home-ui |
Web服务 | home-web | home-web-ir |
请评论、fork 仓库并使用 Docker 镜像来启动美好的物联网项目!
玩得开心!
历史
- 2018 年 2 月 2 日:初始版本,仓库位于 https://github.com/josemotta/IoT.Starter.Pi.Lumi
- 2018 年 2 月 14 日:版本 1.1,仓库位于 https://github.com/josemotta/IoT.Starter.Pi.Thing