当前位置:   article > 正文

【语音控制】0成本实现小爱远程开关电脑_小爱同学wake on lan

小爱同学wake on lan

背景:之前使用HACS/网页版实现了电脑网络唤醒,但不能关机,不支持小爱

问题:不能语音关机,不支持小爱

环境:支持WOL的主板电脑,python 3.X环境(我这里用了群晖)

解法:1.使用小爱添加第三方设备

           2.第三方平台提供API,

          3.找台服务器运行Python脚本虚拟一个开关设备,定义开关触发bash脚本

  • 方案评估:在评估方案时,在网上查资料最终方案为点灯科技 Blinker

  • 系统架构:一番研究后最终系统架构和步骤如下:

  •  Python程序逻辑如下

流程、架构理清了,开始执行:

1.准备python3.X的环境,确保pip3 命令可用,群晖没有PIP3可以装,但是后面很多库、依赖安装出错,最终放弃,我直接使用docker python环境

已经搞好的(包含依赖环境)上传到了:https://hub.docker.com/r/realwang/blinker-wol

 2.在python环境中安装Blinker依赖环境,参考官方教程

  点灯科技-点灯物联网解决方案

3.手机端操作

  1. 1.下载个点灯科技APP,注册账户
  2. 2. 添加设备-->独立设备-->WIFI接入-->阿里云-->复制key
  3. 3. 右上角编辑-->添加按钮-->修改键名为"btn-pc1"类型勾选开关按键
  4. 4. 右拉添加个调试组件,锁定退出

4.编写python脚本,确保服务器81端口闲置

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # 本代码引用arduino论坛 南岛孤云
  4. # 直接拿去用需要改5处,1,密匙,2,局域网电脑的固定IP,3,电脑ssh用户名,4,电脑ssh密码 5,电脑的MAC地址
  5. from Blinker import Blinker, BlinkerButton, BlinkerNumber, BlinkerMIOT
  6. from Blinker.BlinkerConfig import *
  7. from Blinker.BlinkerDebug import *
  8. from wakeonlan import send_magic_packet
  9. import paramiko
  10. import time
  11. import subprocess
  12. auth = 'xxxxxxxxxx' # 1,点灯app上获得的密匙
  13. BLINKER_DEBUG.debugAll()
  14. Blinker.mode("BLINKER_WIFI")
  15. Blinker.miotType('BLINKER_MIOT_OUTLET')
  16. Blinker.begin(auth)
  17. staticip = "192.168.1.200" # 2,电脑局域网固定IP,用于检测电脑开关状态以及利用SSH关机,改为你的设置
  18. pcusr = 'xxxxxx' # 3,电脑ssh用户名
  19. pcpw = 'xxxxxx' # 4,电脑ssh密码
  20. pcmac = 'ff.ff.ff.ff.ff.ff' # 5,MAC地址,改成你自己电脑网卡的
  21. button1 = BlinkerButton("btn-pc1") # 数据键,在App里设置一个一样的开关,类型为 '开关按键',图标用滑动开关,其他随意,文本可为空
  22. cmd1 = "timeout 0.1 ping -c 1 " + staticip # 电脑开关检测就是一个局域网内的ping,超时我设置为100ms,貌似太短或太长小爱都容易出错
  23. lockbutton1 = False
  24. oState = ''
  25. def miotPowerState(state):
  26. ''' '''
  27. global oState
  28. BLINKER_LOG('need set power state: ', state)
  29. oState = state
  30. BlinkerMIOT.powerState(state)
  31. BlinkerMIOT.print()
  32. # 小爱控制的实际部分放在上报状态之后,因为电脑开机实际时间很长,小爱等久了她会以为没开
  33. if state == 'true':
  34. button1_callback('on')
  35. elif state == 'false':
  36. button1_callback('off')
  37. def miotQuery(queryCode):
  38. ''' '''
  39. global oState
  40. # 问小爱电脑开了吗,ping一次获得电脑实际状态
  41. if subprocess.call(cmd1, shell=True)==0:
  42. oState = 'true'
  43. else:
  44. oState = 'false'
  45. BLINKER_LOG('MIOT Query codes: ', queryCode)
  46. if queryCode == BLINKER_CMD_QUERY_ALL_NUMBER :
  47. BLINKER_LOG('MIOT Query All')
  48. BlinkerMIOT.powerState(oState)
  49. BlinkerMIOT.print()
  50. elif queryCode == BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
  51. BLINKER_LOG('MIOT Query Power State')
  52. BlinkerMIOT.powerState(oState)
  53. BlinkerMIOT.print()
  54. else :
  55. BlinkerMIOT.powerState(oState)
  56. BlinkerMIOT.print()
  57. # 关机部分用paramiko的sshclient,不用密码的话可以改用密匙,具体查阅paramiko用法
  58. def shutdownpc():
  59. global staticip
  60. global pcusr
  61. global pcpw
  62. client = paramiko.SSHClient()
  63. client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  64. client.connect(staticip, username=pcusr, password=pcpw)
  65. stdin, stdout, stderr = client.exec_command('shutdown -s -f -c "小爱将在10秒内关闭这个电脑" -t 10')
  66. if client is not None:
  67. client.close()
  68. del client, stdin, stdout, stderr
  69. # 开关键,集成了开关功能,状态报告给小爱,开关过程中的运行保护,开关后状态的更新。
  70. def button1_callback(state):
  71. """ """
  72. global lockbutton1
  73. global oState
  74. global pcmac
  75. dtimeout = 60 # 开关机超时默认60秒
  76. if lockbutton1==False:
  77. BLINKER_LOG('get button state: ', state)
  78. if state=='on':
  79. if subprocess.call(cmd1, shell=True)==0:
  80. oState = 'true'
  81. Blinker.print("检测到电脑已开,按钮状态已更新")
  82. button1.text('已开机')
  83. button1.print(state)
  84. else:
  85. Blinker.print("发送开机指令...")
  86. oState = 'true'
  87. lockbutton1 = True
  88. tic = time.perf_counter()
  89. toc = time.perf_counter()
  90. send_magic_packet(pcmac) # 发魔术包开机
  91. while subprocess.call(cmd1, shell=True)!=0 and toc-tic<dtimeout+2:
  92. time.sleep(2)
  93. toc = time.perf_counter()
  94. if toc-tic >= dtimeout:
  95. Blinker.print("开机超时!")
  96. button1.text('已关机')
  97. button1.print('off')
  98. else:
  99. button1.text('已开机')
  100. button1.print(state)
  101. lockbutton1 = False
  102. elif state=='off':
  103. if subprocess.call(cmd1, shell=True)==0:
  104. Blinker.print("发送关机指令...")
  105. oState = 'false'
  106. lockbutton1 = True
  107. tic = time.perf_counter()
  108. toc = time.perf_counter()
  109. shutdownpc() # 关机
  110. while subprocess.call(cmd1, shell=True)==0 and toc-tic<dtimeout+2:
  111. time.sleep(2)
  112. toc = time.perf_counter()
  113. if toc-tic >= dtimeout:
  114. Blinker.print("关机超时!")
  115. button1.text('已开机')
  116. button1.print('on')
  117. else:
  118. button1.text('已关机')
  119. button1.print(state)
  120. lockbutton1 = False
  121. else:
  122. oState = 'false'
  123. Blinker.print("检测到电脑已关闭,按钮状态已更新")
  124. button1.text('已关机')
  125. button1.print(state)
  126. else:
  127. Blinker.print("正在开机或关机中..")
  128. # 心跳加入了电脑状态检测,更新按钮
  129. def heartbeat_callback():
  130. global oState
  131. if subprocess.call(cmd1, shell=True)==0:
  132. oState = 'true'
  133. button1.text('已开机')
  134. button1.print("on")
  135. else:
  136. oState = 'false'
  137. button1.text('已关机')
  138. button1.print("off")
  139. button1.attach(button1_callback)
  140. Blinker.attachHeartbeat(heartbeat_callback)
  141. BlinkerMIOT.attachPowerState(miotPowerState)
  142. BlinkerMIOT.attachQuery(miotQuery)
  143. if __name__ == '__main__':
  144. while True:
  145. Blinker.run()

5.运行脚本,如果报错,缺什么补什么

6.电脑安装openssh,ssh测试一下到win10

6.跑起来手机上的设备会显示在线,手动操作开机后用小爱测试下

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号