Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/littlebutt/fubuki-iot
物联网IoT智能终端,支持Windows和树莓派
https://github.com/littlebutt/fubuki-iot
ai iot iot-application iot-platform machine-learning self-made
Last synced: 16 days ago
JSON representation
物联网IoT智能终端,支持Windows和树莓派
- Host: GitHub
- URL: https://github.com/littlebutt/fubuki-iot
- Owner: littlebutt
- License: mit
- Created: 2022-09-16T06:05:04.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2022-10-12T01:46:20.000Z (about 2 years ago)
- Last Synced: 2024-11-30T22:49:30.443Z (22 days ago)
- Topics: ai, iot, iot-application, iot-platform, machine-learning, self-made
- Language: Python
- Homepage:
- Size: 38.1 KB
- Stars: 6
- Watchers: 1
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Fubuki Iot —— 物联网智能终端
![PyPI](https://img.shields.io/pypi/v/fubuki-iot) ![GitHub](https://img.shields.io/github/license/littlebutt/fubuki-iot) ![GitHub last commit](https://img.shields.io/github/last-commit/littlebutt/fubuki-iot) ![](https://img.shields.io/github/repo-size/littlebutt/fubuki-iot) ![](https://img.shields.io/badge/QQ-1136681910-9cf?logo=tencentqq&logoColor=9cf)
## 简介
Fubuki Iot是一款开源的物联网智能终端,类似于市面上的天猫精灵,小爱同学等。它可以监听智能家居的消息,也可以根据用户语音向智能家居
发送消息,从而实现家居智能化。与市面上各种终端相比,它具有以下优点:- 定制化程度更高:用户可以自己实现对家居的控制,甚至对原有的家居电器改造
- 安全性更好:由于可以部署在本地局域网上,因此个人信息不会被上传到外网
- 效率更高:通过MQTT协议完成设备之间的交流,不需要复杂的流程经过测试,本框架可以很好的支持Windows系统和树莓派(Linux)系统。
## 快速上手
### 安装
#### 方案一:通过`pip`安装(推荐)
```shell script
pip install fubuki-iot
```#### 方案二:下载安装
首先在终端执行以下命令:
```shell script
git clone [email protected]:littlebutt/fubuki-iot.git
```然后进入根目录,执行以下命令安装`fubuki-iot`包
```shell script
python setup.py install
```#### 方案三:通过`docker`安装
同样像方案三中下载项目到本地,然后执行以下命令
```shell script
docker build -t fubuki-iot:latest .
docker run -it fubuki-iot:latest /bin/bash
```
就可以进入到容器内部了
### 启动
本项目内置了 [百度云](https://cloud.baidu.com/) 的语音合成和语音识别的功能,因此使用之前需要免费申请百度云账号,
点击 [这里](https://login.bce.baidu.com/new-reg?tpl=bceplat&from=portal) 申请。申请之后开通"产品"-"人工智能"-"语音技术"的服务。
当然,您也可以用开源方案自己训练模型替代内置的语音功能,具体见 **进阶功能** 。
1.创建资源目录
首先创建一个Python工程 `demo` ,并在根目录下创建一个目录命名为`resources`
2.创建`.env`文件
在新建的工程下创建一个`.env`配置文件,其内容参考如下:
```text
ENVIRONMENT=dev
RESOURCE_PATH=刚才创建的resources目录,结尾不要加“/”
BAIDU_ACCESS_TOKEN=百度云API的token,可以留空
BAIDU_API_KEY=申请的百度云的AK
BAIDU_SECRET_KEY=申请的百度云的密钥
```3.创建主程序
在根目录下创建文件 `app.py`,并写入以下内容
```python
from iot import TerminalTerminal.run()
```
运行即可启动### 使用
目前主流的物联网信息交换都采用 [MQTT协议](https://www.runoob.com/w3cnote/mqtt-intro.html) ,因此要实现控制智能设备需要部署MQTT
服务器。本项目建议使用 [EMQX](https://www.emqx.com/zh/mqtt) 服务器,具体安装和部署方法点击 [这里](https://www.emqx.io/docs/en/v5.0/deploy/install.html#tar-gz-linux-macos-windows) 。若要完整的实现对硬件设备的控制可以参考 **相关资料** 。
#### 内置功能1.对话
运行智能终端后,按下键盘上的f可以进行录音。对着麦克风说出“在吗”、“你好”后,智能终端会回应“在的”。
2.控制开关和电灯
运行智能终端,按下键盘上的f后对着麦克风说出“打开开关”,然后它会向MQTT服务器的`default/switch` Topic发送以下信息:
```json
{
"switch": "on"
}
```同样,对着麦克风说出“关闭开关”后,它会向MQTT服务器的`default/switch` Topic发送以下信息:
```json
{
"switch": "off"
}
```具体效果需要由订阅了 `default/switch` Topic的智能设备实现。
此外,运行智能终端,按下键盘上的f后对着麦克风说出“打开卧室/客厅/餐厅灯”也会向MQTT服务器的`default/light` Topic发送以下信息:
```json
{
"position": "bedroom/livingroom/dinningroom"
}
```3.接受按钮信息
运行终端,当由设备向MQTT服务器的 `self/button` 发送如下消息后,终端会说“有人按下了按钮”。
```json
{
"topic":"self/button",
"device":"button",
"verbose":"false",
"message":"有人按下了按钮"
}
```#### 自定义功能
1.自定义语音功能
语音功能可以理解为用户和智能终端进行对话,类似于机器人的对话功能。这种功能一般不涉及硬件。在天猫精灵中,
就内置了提醒助手、墨迹天气等语音功能。首先在自己创建的Python项目的根目录中创建一个包(package)命名为 `models` ,在这个包中创建一个python文件 `acoustics.py`,
在文件中定义一个语义模型:```python
from iot import SemanticsGroup, SemanticsModel, SemanticsRedirectEnum, SemanticsFromEnum, SemanticsFunc@SemanticsGroup.add_model
class MySemanticsModel(SemanticsModel):code = 'hello' # 语义模型的标识,自定义
frm = SemanticsFromEnum.USER # 语义模型的来源,这里是接受用户的语音命令,所以是USER
topic = '' # 由于不涉及发布消息,所以这个字段用不到,留空就行
regex = "(.*)后提醒我(.*)" # 匹配用户语音命令的正则表达式,比如这里是一个有关提醒的命令
regex_num = 3 # 上述表达式匹配后的分组(group)的数量,第一个为用户命令全量文本,第二个是“后”前面的文本,第三个是“我”后面的文本
redirect = SemanticsRedirectEnum.ACOUSTICS # 语义处理好后的重定向,由于不需要发送消息等后续操作,所以这里是直接语音返回
func: SemanticsFunc = my_semantics_model_func # 处理用户命令的回调函数
```在上面的语义模型中,最后一个字段是一个 `SemanticsFunc` 实例,它是一个返回 `FunctionDeviceModel` 或者 `UniverseNoticeModel` 的方法
因此,需要这样定义:```python
from typing import Union
from iot import UniverseNoticeModel, FunctionDeviceModeldef my_semantics_model_func(*args) -> Union[FunctionDeviceModel, UniverseNoticeModel]:
time = args[1] # 获取时间
content = args[2] # 获取提醒内容
# 处理提醒命令,可以借助其他API实现
return FunctionDeviceModel( # 最后返回一个功能设备模型
smt_code='hello', # 对应的语义模型标识
is_raw=True, # 是否为纯文本
acoustics=f"好的,我会在{time}后提醒你{content}", # 返回给用户的语音内容
data="" # 由于是纯文本,所以这个字段用不到
)
```定义好以后需要在 `app.py` 中加入一行:
```python
from iot import TerminalTerminal.load_models('demo.models')
Terminal.run()
```2.自定义设备功能
智能终端最大的优势就是可以通过语音控制智能家居。同样,需要定义一个语义模型实现这个功能:
```python
from typing import Unionfrom iot import SemanticsGroup, SemanticsModel, SemanticsRedirectEnum, SemanticsFromEnum, SemanticsFunc, UniverseNoticeModel, FunctionDeviceModel
def curtain_semantics_model_func(*args) -> Union[FunctionDeviceModel, UniverseNoticeModel]:
return FunctionDeviceModel(smt_code="hi",
topic="default/curtain", # 发送的Topic,其实后续会被语义模型的Topic覆盖
is_raw=False, # 不再是纯文本返回了
acoustics="好的,正在为你打开窗帘", # 返回给用户的提示信息
data={ # 发送的数据
'state': 'on'
}
)@SemanticsGroup.add_model
class SwitchOnSemanticsModel(SemanticsModel):code = "hi"
frm = SemanticsFromEnum.USER
topic = 'default/curtain'
regex = "打开窗帘"
regex_num = 1
redirect = SemanticsRedirectEnum.MESSAGE # 重定向给消息,因为需要发送MQTT消息
func: SemanticsFunc = curtain_semantics_model_func
```具体怎么消费这个MQTT消息,即硬件设备如何处理则需要改造硬件,具体参考 **相关资料** 。
3.自定义消息推送
和之前一样,也需要定义一个语义模型:
```python
from typing import Optionalfrom iot import SemanticsGroup, SemanticsModel, SemanticsRedirectEnum, SemanticsFromEnum, SemanticsFunc, UniverseNoticeModel
def button_semantics_model_func(model) -> UniverseNoticeModel:
#处理设备推送的统一推送模型
return UniverseNoticeModel( # 这次返回的是统一推送模型
smt_code='hei',
topic='self/weather', # topic,被用来检索语义模型的
device='remote_server', # 设备来源
verbose=False, # 是否多语,这里只需要通知以下用户所以选择False
message="天气播报:短期将有大量降雨" # 返回给用户的信息
)@SemanticsGroup.add_model
class ButtonSemanticsModel(SemanticsModel):code = "hei"
frm = SemanticsFromEnum.DEVICE # 来自设备
topic = 'self/weather'
regex: Optional[str] = None
regex_num: Optional[str] = None
redirect = SemanticsRedirectEnum.ACOUSTICS #直接返回
func: SemanticsFunc = button_semantics_model_func
```
至此,可以实现一个简单的物联网终端!## 进阶功能
如果您对上述基本功能还不满足,可以试一下进阶功能。
1.语音唤醒功能
像主流的智能终端一样,本项目也可已开启语音唤醒功能。该功能是通过内置的 [Pocketsphinx](https://github.com/bambocher/pocketsphinx-python)
实现的,因此需要安装其依赖,包括swig,C语言环境等,具体可以查看相关文档。成功安装好依赖后将 `.env` 文件添加以下两行:
```text
TERMINAL_MODE=0
DEVICE_REC=PocketsphinxRecorder
```再次启动程序可以通过对它说hello或者hi唤醒。
2.生命周期和钩子函数
本智能终端在运行时分为以下几个阶段,在不同的阶段可以调用不同的钩子函数实现流程定制化:
```text
___________________________________循环______________________________________
| |
|加载用户模型| -> |加载上下文| -> |执行启动钩子| -> |监听用户/设备请求| -> |执行前置语义处理钩子| -> |处理请求| -> |执行后置语义处理钩子| ->|转发请求| -> |执行卸载钩子| -> |卸载|
| |
|——————————————————————————————————循环——————————————————————————————————————|
```从上图可以看出,一共有四个钩子函数,分别是 `OnStartUpHook`、 `OnModelPreprocessHook` 、 `OnModelPostprocessHook` 和 `OnTearDown`。可以通过以下方法编写钩子函数:
```python
from iot import HooksGroup@HooksGroup.on_start_up
def start_up(context, semantics_group):
...@HooksGroup.on_tear_down
def tear_down(context, semantics_group):
...@HooksGroup.on_model_preprocess
def model_preprocess(context, function_device_model):
...@HooksGroup.on_model_postprocess
def model_postprocess(context, function_device_model):
...
```钩子函数可以获取到执行阶段的上下文,包括各种处理器信息和配置信息。此外,**启动钩子** 和 **卸载钩子** 可以获取语义处理模型的集合而 **前置语义处理钩子** 和 **后置语义处理钩子** 可以获取到语义模型。
3.自定义设备和语音处理器
本智能终端的设备(麦克风和扬声器)都是用的Windows默认的,如果要用在树莓派或者其他环境则需要自定义设备,包括麦克风(Recorder)和扬声器(Player)。
首先实现对应的类:
```python
from iot import RecorderFactory, Recorder@RecorderFactory.set
class MyRecorder(Recorder): # 继承Recorder类,并加上注解
def awake(self) -> bool: # 实现awake方法,这个方法必须是个阻塞的方法,返回True则开始录音,返回False则推出程序
...def record(self, time: int) -> str: # 录音,time为录音时长,返回录音后保存的路径
...
```然后在 `.env` 文件中修改默认的麦克风设备:
```text
DEVICE_REC=MyRecorder
```同样,扬声器也是这样的步骤:
```python
from iot import PlayerFactory, Player@PlayerFactory.set
class MyPlayer(Player):def play(self, path: str) -> None: # path为存储语音文本的txt文件路径
...
```然后更改 `.env` 文件
```text
DEVICE_PLY=MyPlayer
```您也可以修改默认的语音处理器,包括语音识别(AsrProcessor)和语音合成(TtsProcessor),方法也是一样的。
```python
from iot import AsrProcessorFactory, AsrProcessor
from typing import Optional@AsrProcessorFactory.set
class MyAsrProcessor(AsrProcessor):def asr(self, path: str) -> Optional[str]: # path为音频文件(一般为wav)的路径,返回语音文字,如果为None则说明处理失败
...
````.env` 文件
```text
ASR_PROCESSOR=MyAsrProcessor
```语音合成可以这样修改:
```python
from iot import TtsProcessorFactory, TtsProcessor@TtsProcessorFactory.set
class MyTtsProcessor(TtsProcessor):def tts(self, text: str) -> str: # text为需要被合成的文字,返回合成后的音频文件路径
...
````.env` 文件
```text
TTS_PROCESSOR=MyTtsProcessor
```## 相关资料
1. [《手把手教你做一个天猫精灵》系列](https://juejin.cn/column/7149407148701663240)
2. [如何实现智能设备](https://juejin.cn/post/7150085767887323149)
3. [智能家居设备交流消息的抓取](https://juejin.cn/post/7151593732062576671)
## 待实现功能
1.语音追问功能
2.音频等流媒体的播放
3.语义模型的order