关于小爱同学自定义指令执行

1.前言

之前买了小爱同学音响,一直想让其让我的生活变得更智能,编写一些程序来完成一些自动化任务,但是经过搜索发现,官方开发者平台不能用了,寻找api阶段浪费了我很长时间。最后在github 开源项目发现了俩个比较关键的项目:
https://github.com/Yonsm/MiService
https://github.com/yihong0618/xiaogpt
其实关键点在于,我需要俩个接口:

  1. 我说了什么
  2. 让音响答复我说了什么

只需要这俩个接口

2. 实现

对于第一个接口我找了很久,最后在xiaogpt这个项目中找到了这个api 的实现,xiaogpt也是miservice 这个项目实现的。

这里我简单做了个demo,相信能帮助大家节约很长时间:

#!/usr/bin/python3
from miservice.miaccount   import   MiAccount
from miservice.minaservice import   MiNAService
from aiohttp import ClientSession
from requests.utils import cookiejar_from_dict
import time
import os
import json
import asyncio

COMMAND = {
"打开主机":["wakeonlan xx:xx:xx:xx:xx:xx","已开启主机"],
"关闭主机":["ssh -o ConnectTimeout=1 root@192.168.123.60 shutdown -h now","已关闭主机"],
"打开桌面":["/root/tools/switch/switch.py on","已打开桌面电脑"],
"关闭桌面":["ssh -o ConnectTimeout=1 root@192.168.123.100 shutdown -h now; sleep 30; /root/tools/switch/switch.py off","已关闭桌面电脑"]
}

async def main():
    user_id = "小米账号" 
    password = "密码"
    hardware = "LX06" # 音响型号
    while True:
        try:
            misession = ClientSession()
            account = MiAccount(misession, user_id,password,"mi.token")
            await account.login("micoapi")
            service = MiNAService(account)
            device_list = await service.device_list()
            deviceID = device_list[0]['deviceID']
            LATEST_ASK_API=  "https://userprofile.mina.mi.com/device_profile/v2/conversation?source=dialogu&hardware={hardware}×tamp={timestamp}&limit=1"
            async with ClientSession() as session:
                cookies = dict(
                    deviceId=deviceID,
                )
                misession.cookie_jar.update_cookies(cookiejar_from_dict(cookies))
                session._cookie_jar = misession.cookie_jar
                # print(session._cookie_jar._cookies)
                while True:
                    r = await session.get(LATEST_ASK_API.format(hardware=hardware, timestamp=str(int(time.time()* 1000))))
                    data = await r.json()
                    query = json.loads(data["data"])['records'][0]['query']
                    qtime = int(json.loads(data["data"])['records'][0]['time']/1000)
                    # print(qtime,int(time.time()))
                    if abs(qtime - int(time.time())) < 5 and COMMAND.get(query):
                        print(f"{query} 已执行命令")
                        os.popen(COMMAND.get(query)[0])
                        await service.text_to_speech(deviceID, COMMAND.get(query)[1])
                        time.sleep(5)
                    time.sleep(1)
        except Exception as e:
            print(e)

要使用上述代码,首先要满足几个条件:

  1. python支持异步(忘记是几点几版本开始支持了)
  2. 安装miservice
pip install miservice

其他把账号、密码、音响型号 配置进去 就可以在COMMAND 字典中自定义shell 命令了

这里简单介绍一些 COMMAND 字典,键 为语控命令,值 为一个列表,列表中第一个值 为 要执行的shell 命令,第二个值 为 音响答复

后面要增加命令可以直接修改 COMMAND字典。这里可以看到我对俩个电脑开关机进行控制:
对于桌面电脑,我是先 执行shutdown -h now, 等待30s后,再对电源进行关闭操作(switch为我写的控制电源的一个脚本),因为我总觉得直接下电对 电脑不好。

对于主机电脑,我直接使用 网络唤醒实现的开机(连接网线),对于桌面电脑由于我没有网线接口了,所有用上电自动开机实现的开机控制。

3.其他一些细节

3.1 让小爱知道这个指令

由于自定义的一些指令,直接问小爱,小爱会回答不知道这个指令,那么我们可以在 小爱训练中加入这些自定义指令:
在这里插入图片描述
这里小爱,会先回答“好的”, 然后我们api响应的话语会打断说话,紧接着说“已开启主机”

3.2 回答内容为自定义查询的内容

在COMMAND 里,我们可以用这种方式进行定义列表中的第二个字段:

f"查询的信息是 {data}"

可以注意到,这里我执行shell, 使用 os.popen 来执行的(非阻塞),一方面也是为了可以读取返回内容,然后给与相应的赋值
data 直接赋值为 os.popen 返回的read() 即可
当然os.popen不是一种良好的执行 命令的方式,有更官方的写法,懒得优化了。

4.效果展示

https://7.z.wiki/autoupload/20240707/Yfx4/1.mp4

终于可以在床上控制电脑开关机了

### ESP8266与米家及小爱同学的集成方法及兼容性 ESP8266作为一种低成本、高效率的Wi-Fi模块,在物联网设备开发中被广泛应用。其支持多种协议和框架,能够轻松实现与其他智能家居生态系统的集成。以下是关于ESP8266与小米生态系统(包括米家App和小爱同学)的集成方法及其兼容性的详细介绍。 #### 一、ESP8266与米家App的集成 为了使基于ESP8266的设备可以接入米家App,通常需要通过Mi Home SDK或者第三方中间件来完成连接配置。具体过程如下: 1. **使用MiOT开发者平台注册产品并获取认证** 开发者需先登录小米IoT开发者平台,创建一个新的硬件项目,并按照指引提交必要的资料以获得审核批准[^1]。一旦成功注册,即可下载对应的固件文件用于后续烧录操作。 2. **OTA升级至官方指定固件版本** 完成上述步骤之后,将目标板载入由小米提供的特定固件镜像,该镜像包含了适配于米家应用的功能逻辑以及安全机制。此阶段可能涉及多次迭代测试直至满足所有功能需求为止。 3. **编写自定义业务代码并与云端交互** 基础网络层初始化完成后,还需针对实际应用场景设计个性化的控制指令集,这些命令最终会被上传到服务器端供手机客户端调用显示状态更新或执行动作反馈等服务[^2]。 ```c #include <Arduino.h> #include <WiFiClientSecure.h> void setup() { Serial.begin(9600); } void loop() { WiFiClient client; if (!client.connect("api.miot-spec.com", 443)) { return; } String postStr = "{\"id\": \"light\", \"value\": true}"; client.print(String("POST /v2/action HTTP/1.1\r\n") + "Host: api.miot-spec.com\r\n" + "Content-Type: application/json;charset=utf-8\r\n" + "Content-Length: " + postStr.length() + "\r\n\r\n" + postStr); while (client.connected()) { String line = client.readStringUntil('\n'); if (line == "\r") break; } } ``` 以上是一个简单的示例程序片段,展示了如何向小米开放API发送HTTP请求模拟开关灯泡的操作。 --- #### 二、ESP8266与小爱同学的语音控制对接 为了让用户的语音输入可以通过小爱音箱触发相应的家庭自动化响应,则除了基本联网能力外还需要额外考虑以下几个方面的工作流程: 1. **绑定关系建立** 用户首次启动时应引导他们完成账户关联手续,即允许授权访问个人数据以便同步偏好设置信息给本地网关节点处理。 2. **解析意图模型训练样本准备** 提前准备好一系列标准句型作为机器学习算法素材库的一部分,从而提高识别精度减少误判率。 3. **事件驱动架构下的消息分发策略制定** 当检测到来自信号源的有效音频流后迅速分析其中蕴含的意义并将结果转发至相应的目标实体上进一步处置。 值得注意的是,由于目前市面上主流的小爱系列终端并不直接暴露对外RESTful接口资源位置地址列表出来让用户自行抓取利用;因此更多时候我们倾向于借助某些成熟的中介解决方案比如NodeRED图形化编程工具链配合IFTTT之类的服务提供商间接达成目的效果更好一些[^3]。 --- ### 总结 综上所述可以看出尽管存在一定的技术门槛障碍但仍可通过合理规划逐步克服困难顺利实现预期目标成果展示。对于初学者而言建议优先参考现成案例文档积累实践经验后再尝试独立探索未知领域拓展视野范围。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hello_wshuo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值