米家联动小爱同学语音唤醒休眠笔记本电脑-软件实现方案
- 2022-04-13 05:04:19
- 幻音い
- 8853
温馨提示: 这篇文章于911天前编写,现在可能不再适用或落后.
前言
实现效果展示
https://www.bilibili.com/video/BV1Ca411e77B/
开发语言
- Golang【这里开发用的golang,也可以自行选择】
- TypeScript【sdk使用ts,也可以自行使用其他sdk语言】
需要准备的设备
- 一台树莓派或长期开启的小型服务器或支持ssh的路由器【以下简称服务器】
唤醒方案
- 通过局域网内WOL网络唤醒实现开机
休眠方案
- 通过内置Windows系统服务提供API实现休眠
实现流程
- 1.在【服务器】上运行编写好的wol唤醒程序,通过目标电脑的mac地址和网卡名称远程唤醒。
- 2.在【笔记本】上安装编写好的Windows服务,通过【服务器】调用接口实现。
- 3.在「休眠」和「唤醒」都处理好之后,就可以开始接入【米家】了,这里使用【点灯科技】提供的米家物联网平台实现。
- 4.在点灯科技app上创建独立设备,名称设置为【电脑】,获取秘钥,然后在开发文档中下载nodejs-sdk,找到例子中的miot文件夹,找到开关的例子,填写设备秘钥。
- 5.然后ts-node运行对应例子文件代码,然后对着小爱同学说【打开电脑】这样当前启动的代码就能收到消息,然后根据收到的消息状态,去调用之前的休眠、唤醒接口就可以实现开关机操作了。
- 6.当nodejs例子连接对应的点灯独立设备成功后,会在点灯APP上显示在线状态,这时候就可以在米家->我的->其他平台设备->添加点灯科技账号->同步设备这时候就会有你创建的独立设备了,如果米家同步后没有你的设备,请检查你的设备是否在线、使用的SDK是否是miot下的(重要)其他文档请参考点灯开放文档
- 7.如果你想要通过外网接口来访问接口的话,请自行使用frp映射端口到外网实现
自行编译 Windows休眠服务 - Golang
https://github.com/balrogsxt/wol-api
#安装依赖
go mod tidy
#构建当前平台
go build
#或使用make构建linux平台(一般都放linux吧。。)
make build-linux
如果接口出现没有权限请设置开机运行命令
sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"
自行编译 Wol唤醒以及调用休眠的HTTP接口服务
https://github.com/balrogsxt/win-sleep-service
服务使用方法
#安装依赖
go mod tidy
#构建项目为当前平台,如果是mac请自行交叉编译成windows
go build
#停止服务
xt-service.exe stop
#卸载服务
xt-service.exe uninstall
#安装服务
xt-service.exe install
#启动服务
xt-service.exe start
############
#日志文件会出现在: C:\Windows\System32\Logs\
接入点灯SDK - TypeScript
安装sdk 【官方提供的node-sdk部分代码是有问题的,请参考底部修改,只针对开关设备,其他设备没试过】
npm i -g ts-node
git clone https://github.com/blinker-iot/blinker-js.git
cd blinker-js
npm i
编写独立设备代码
/**
* 电脑开关
*/
//请自行调整
import { BlinkerDevice } from './../lib/blinker';
import { Miot, VA_TYPE } from './../lib/voice-assistant';
import axios from 'axios';
let device = new BlinkerDevice('填写点灯SDK的设备资料');
let miot = device.addVoiceAssistant(new Miot(VA_TYPE.OUTLET));
device.ready().then(() => {
// 米家电源状态改变
miot.powerChange.subscribe(async message => {
switch (message.data.set.pState) {
case 'true':
if(await WindowsAPI.open()){
message.power('true').update();
}
break;
case 'false':
if(await WindowsAPI.close()){
message.power('false').update();
}
break;
default:
break;
}
})
//由于只处理米家设备,不处理点灯那边app操作,所以这下面都没管它
device.dataRead.subscribe(message => {
})
device.builtinSwitch.change.subscribe(message => {
})
});
//基于本地实现的Http接口实现唤醒和休眠功能
class WindowsAPI{
private static url:string = "http://127.0.0.1:8089";//长期启动的那台设备上的接口
private static token:string = "";//令牌
//唤醒电脑
public static async open(){
let params = "isForce=true";
return axios.post(`${this.url}/windows/wol_call`,params,{
headers:{
token:this.token
}
}).then(r=>{
console.error('唤醒电脑成功: ',r.data);
return true;
}).catch(r=>{
console.error('唤醒电脑失败: ',r);
return false;
});
}
//休眠电脑
public static async close(){
return axios.post(`${this.url}/windows/sleep_call`,"",{
headers:{
token:this.token
}
}).then(r=>{
console.error('休眠电脑成功: ',r.data);
return true;
}).catch(r=>{
console.error('休眠电脑失败: ',r);
return false;
});
}
}
遇到的坑 - SDK修改部分
点灯科技Nodejs-sdk的BUG
1.接收MIOT消息时,无法走到订阅代码部分。
//找到文件lib/voice-assistant.ts,VoiceAssistant类中90行左右的listen事件,替换成以下代码 listen() { this.device.mqttClient.on('message', (topic, message) => { if (topic.indexOf(this.subTopic.substr(0, this.subTopic.length - 1)) > -1) { let data; let fromDevice; let messageId; try { let messageString = u8aToString(message) let messageObject = JSON.parse(messageString); //判断是否data里面有form data = messageObject.data; if(typeof(data.from) != 'undefined'){ fromDevice = data.from; }else{ fromDevice = messageObject.fromDevice; } this.targetDevice = fromDevice messageId = topic.split('/')[6] vaLog(data, `${this.vaName}>device`) } catch (error) { console.log(error); } // console.log('收到MQTT订阅消息: ',fromDevice,this.vaName,topic) if (fromDevice == this.vaName){ this.processData(messageId, data) } } }) }
2.上报米家状态时,格式错误,导致小爱同学提示【操作的设备出错了】
//找到文件lib/voice-assistant.ts,200行左右VaMessage类中的update方法,替换成以下代码
update() {
let messageId = {messageId:this.data.messageId}
this.response = Object.assign(this.response,messageId)
let responseStr = JSON.stringify(this.response)
let data = `{ "fromDevice": "${this.device.config.deviceName}", "toDevice": "ServerReceiver", "data": ${responseStr}, "deviceType": "vAssistant"}`
this.device.mqttClient.publish(this.voiceAssistant.pubTopic, data)
vaLog(data, `device>${this.voiceAssistant.vaName}`)
}
阁下需要登录后才可以查看评论哦~