小爱同学和树莓派开关电脑,加强版。
本帖最后由 南岛孤云 于 2021-5-9 13:00 编辑以前有人做了个树莓派开机的,貌似只能开机。我这个改进了下,可以开,可以关。可以小爱控制。
Win10需要开openssh server,win10自带,开启就可以了。
已加入小爱控制,小爱把它当个插座,app里设备名字改成电脑就好。
需要电脑有局域网固定IP,用来ping电脑状态,可以在网卡或者路由上设置。
App里图标用滑动开关,类型用'开关按键', 就可以正确的表现电脑的开关状态。另外需要wakeonlan 以及 paramiko
sudo pip3 install wakeonlan
sudo pip3 install paramiko
另外注意下目前Github上blinker的python包有bug,
记得用pull request里那个100%CPU占用的修正。
我的树莓派3B+,这个后台开着应该是基本不占资源。
===================
更新了两句开关机超时的判定,默认都是60秒
设定超时的原因在于开关命令发出后,一般电脑要几十秒后才彻底完成开关动作,程序会通过ping的方式来确定电脑状态
如果出现意外,开关机一直无法完成(开机1分钟ping不到,或者关机1分钟一直能ping到),就要通过超时来停止ping,然后取消开关运行保护。
这样的结构一举三得,
1,避免重复开关机,最起码电脑要实际完成开关动作或者超时以后才能再发出指令,当然小爱是不知道的,你一直让她开她也会去开,但只是去帮你按了开关而已,逻辑都在开关上。
2,正确显示电脑状态,比如你手动开关的电脑,点灯不知道,最坏的情况下,一个心跳以后状态也同步了。
3,因为是纯软件的方法,一个设备就是个进程而已,不需要每个电脑去接线,所以你如果有多台电脑,完全可以一个派控制所有的。
===================
更新下win10下开ssh服务的步骤,以及需要注意的几个点。
开始 - 设置 - 应用 - 可选功能 - 添加功能 - OPENssh服务器 选择安装
然后打开PowerShell
Start-Service sshd
# 这一步开启ssh服务的自动启动,或者你也可以到 搜索-服务 里找到openssh ssh server这一条,用鼠标开启自动:
Set-Service -Name sshd -StartupType 'Automatic'
# 检查一下防火墙设置.
Get-NetFirewallRule -Name *ssh*
# 应该可以看到一条 "OpenSSH-Server-In-TCP",而且已经开启了
# 如果找不到,执行一下这条添加新的防火墙规则,如果自行更改了端口 注意同时修改我们python代码上面paramiko的参数,具体加在client.connect(port=xxxx)
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
默认的win10 openssh配置文件在 C:\ProgramData\ssh\sshd_config
如果你打算用公匙私匙方式来登录shh,这个文件的最后两句要用#注释掉,这两句会造成你安装在你管理员帐号下.ssh的密匙不起作用(密匙安装位置在C:\Users\xxxx\.ssh)。
#Match Group administrators
#AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
配置完成后,最好在派上终端里手动登录一次,第一次登录好像需要输入确定。
==================================
```
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 树莓派利用WOL和OPENSSH实现开关机。 针对WIN10, 电脑需要openssh!
# 直接拿去用需要改5处,1,密匙,2,局域网电脑的固定IP,3,电脑ssh用户名,4,电脑ssh密码 5,电脑的MAC地址
from Blinker import Blinker, BlinkerButton, BlinkerNumber, BlinkerMIOT
from Blinker.BlinkerConfig import *
from Blinker.BlinkerDebug import *
from wakeonlan import send_magic_packet
import paramiko
import time
import subprocess
auth = 'xxxxxxxxxx'# 1,点灯app上获得的密匙
BLINKER_DEBUG.debugAll()
Blinker.mode("BLINKER_WIFI")
Blinker.miotType('BLINKER_MIOT_OUTLET')
Blinker.begin(auth)
staticip = "192.168.1.200"# 2,电脑局域网固定IP,用于检测电脑开关状态以及利用SSH关机,改为你的设置
pcusr = 'xxxxxx'# 3,电脑ssh用户名
pcpw = 'xxxxxx'# 4,电脑ssh密码
pcmac = 'ff.ff.ff.ff.ff.ff'# 5,MAC地址,改成你自己电脑网卡的
button1 = BlinkerButton("btn-pc1")# 数据键,在App里设置一个一样的开关,类型为 '开关按键',图标用滑动开关,其他随意,文本可为空
cmd1 = "timeout 0.1 ping -c 1 " + staticip# 电脑开关检测就是一个局域网内的ping,超时我设置为100ms,貌似太短或太长小爱都容易出错
lockbutton1 = False
oState = ''
def miotPowerState(state):
''' '''
global oState
BLINKER_LOG('need set power state: ', state)
oState = state
BlinkerMIOT.powerState(state)
BlinkerMIOT.print()
# 小爱控制的实际部分放在上报状态之后,因为电脑开机实际时间很长,小爱等久了她会以为没开
if state == 'true':
button1_callback('on')
elif state == 'false':
button1_callback('off')
def miotQuery(queryCode):
''' '''
global oState
# 问小爱电脑开了吗,ping一次获得电脑实际状态
if subprocess.call(cmd1, shell=True)==0:
oState = 'true'
else:
oState = 'false'
BLINKER_LOG('MIOT Query codes: ', queryCode)
if queryCode == BLINKER_CMD_QUERY_ALL_NUMBER :
BLINKER_LOG('MIOT Query All')
BlinkerMIOT.powerState(oState)
BlinkerMIOT.print()
elif queryCode == BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
BLINKER_LOG('MIOT Query Power State')
BlinkerMIOT.powerState(oState)
BlinkerMIOT.print()
else :
BlinkerMIOT.powerState(oState)
BlinkerMIOT.print()
# 关机部分用paramiko的sshclient,不用密码的话可以改用密匙,具体查阅paramiko用法
def shutdownpc():
global staticip
global pcusr
global pcpw
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(staticip, username=pcusr, password=pcpw)
stdin, stdout, stderr = client.exec_command('shutdown -s -f -c "小爱将在10秒内关闭这个电脑" -t 10')
if client is not None:
client.close()
del client, stdin, stdout, stderr
# 开关键,集成了开关功能,状态报告给小爱,开关过程中的运行保护,开关后状态的更新。
def button1_callback(state):
""" """
global lockbutton1
global oState
global pcmac
dtimeout = 60# 开关机超时默认60秒
if lockbutton1==False:
BLINKER_LOG('get button state: ', state)
if state=='on':
if subprocess.call(cmd1, shell=True)==0:
oState = 'true'
Blinker.print("检测到电脑已开,按钮状态已更新")
button1.text('已开机')
button1.print(state)
else:
Blinker.print("发送开机指令...")
oState = 'true'
lockbutton1 = True
tic = time.perf_counter()
toc = time.perf_counter()
send_magic_packet(pcmac)# 发魔术包开机
while subprocess.call(cmd1, shell=True)!=0 and toc-tic<dtimeout+2:
time.sleep(2)
toc = time.perf_counter()
if toc-tic >= dtimeout:
Blinker.print("开机超时!")
button1.text('已关机')
button1.print('off')
else:
button1.text('已开机')
button1.print(state)
lockbutton1 = False
elif state=='off':
if subprocess.call(cmd1, shell=True)==0:
Blinker.print("发送关机指令...")
oState = 'false'
lockbutton1 = True
tic = time.perf_counter()
toc = time.perf_counter()
shutdownpc()# 关机
while subprocess.call(cmd1, shell=True)==0 and toc-tic<dtimeout+2:
time.sleep(2)
toc = time.perf_counter()
if toc-tic >= dtimeout:
Blinker.print("关机超时!")
button1.text('已开机')
button1.print('on')
else:
button1.text('已关机')
button1.print(state)
lockbutton1 = False
else:
oState = 'false'
Blinker.print("检测到电脑已关闭,按钮状态已更新")
button1.text('已关机')
button1.print(state)
else:
Blinker.print("正在开机或关机中..")
# 心跳加入了电脑状态检测,更新按钮
def heartbeat_callback():
global oState
if subprocess.call(cmd1, shell=True)==0:
oState = 'true'
button1.text('已开机')
button1.print("on")
else:
oState = 'false'
button1.text('已关机')
button1.print("off")
button1.attach(button1_callback)
Blinker.attachHeartbeat(heartbeat_callback)
BlinkerMIOT.attachPowerState(miotPowerState)
BlinkerMIOT.attachQuery(miotQuery)
if __name__ == '__main__':
while True:
Blinker.run()
```
可以可以,大家都想的是接物理开关去关,缺忘了可以ssh连上去关 大佬 请问下我这个是什么原因无法运行
Traceback (most recent call last):
File "p.py", line 21, in <module>
Blinker.begin(auth)
File "/usr/local/lib/python3.7/dist-packages/Blinker-0.2.0-py3.7.egg/Blinker/Blinker.py", line 171, in begin
bProto.conn1.start(auth, bProto.aliType, bProto.duerType, bProto.miType)
File "/usr/local/lib/python3.7/dist-packages/Blinker-0.2.0-py3.7.egg/BlinkerAdapters/BlinkerMQTT.py", line 328, in start
self.client.connect(self.bmqtt.host, self.bmqtt.port, 60)
File "/usr/local/lib/python3.7/dist-packages/paho_mqtt-1.5.1-py3.7.egg/paho/mqtt/client.py", line 940, in connect
bind_address, bind_port, clean_start, properties)
File "/usr/local/lib/python3.7/dist-packages/paho_mqtt-1.5.1-py3.7.egg/paho/mqtt/client.py", line 1005, in connect_async
raise ValueError('Invalid host.')
ValueError: Invalid host.
小明没吃饱 发表于 2021-10-1 21:38
大佬 请问下我这个是什么原因无法运行
Traceback (most recent call last):
File "p.py", line 21, in
知道了 是python库bug 感谢大佬提供的新思路,我之前是在win10上跑一个web服务暴露接口用于关机和重启,直接通过ssh就可以把这个去掉了 小明没吃饱 发表于 2021-10-2 01:23
知道了 是python库bug
你好我也遇到这个问题了,你是怎么解决的呢
页:
[1]