- 作者:
- 分类:项目&制作->小制作
- 阅读:10251
- 点赞:25
- 难度:
- 版权:CC BY-SA 4.0
- 创建:2019-10-15
- 更新:2024-02-28
原文链接(持续更新):https://neucrack.com/p/190
本文章介绍了如何使用 ESP32 + 自己写代码和部署服务器实现远程控制和查看电脑开关机状态,原理是通过 ESP32 的引脚控制开关机按钮,甚至可以强制关机
另外,你可能觉得自己写代码,并且部署服务器很麻烦,可以看 用 ESP32 + 腾讯云explorer + 腾讯练练小程序30分钟实现远程硬开关机(非WOL方式) 这篇文章,不需要写代码(用我写好的代码),只需要开通免费的腾讯云 explorer 服务,就可以使用微信小程序腾讯练练控制和查看电脑开关机状态了,同理可以用到任何远程开关
原理
控制开关及
机箱的开关及按钮连接到主板的两个引脚: Power+ 和 Power-, 也可以说是Power Out和Power In, 平时两个引脚的连接是断开的,当机箱按钮按下短路, Power-是主板的 开关机检测引脚, 主板检测当这个引脚高电平的时间超过一定时间(t1)就开关机, 若发现是长按(时间t2),则强制关机
所以我们只需要用单片机去控制向Power In输入高电平即可(注意共地)
读取主机开机状态
主板会有一对(PLED+和PLED-)甚至更多对引脚来指示开关机状态,一般会被连接到机箱的开关机指示灯, 通过PLED+的电平就可以知道主机是开机(高电平)还是关机(低电平)了
所以我们只需要用单片机去读取PLED+的电平即可(注意共地),是高电平就表示是开机状态
系统组成
硬件
ESP32 + 杜邦线 + 插针: ESP32非常便宜性能又高,最关键的是集成的 2.4G WiFi 硬件和协议栈, 而且支持 Micropython编程,可以在非常短的时间内完成本设计
电路

通过USB共地, 也可以接PLED-到ESP32的GND
更新:这里原理图画得比较潦草,如zean1987 指出,这里 PLED+ 输出的是 5v 电压,可能会让 3.3v 耐受的 GPIO 被烧,虽然 ESP32 这样接也能用,但是官方文档是没有说 5v 耐受的,所以最好加个电压转换电路,最简单的就是用一个或者两个电阻分压一下,当然实测 ESP32-S 直接接也能耐受。
系统通信网络(序列图)
制作步骤
按照精简电路图搭建硬件电路
下载 Micropython 固件并按照说明更新到开发板
编写
Micropython程序,使用MQTT与云端建立长连接,定时向某个主题(topic1)上传状态,订阅某个主题(topic2),制定自己的协议,最好对数据进行加密,根据接收到的数据来决定采取什么动作编写服务器程序,订阅发布硬件状态的
MQTT主题topic1,这样就可以获得开关机状态了,并且用一个接口来接受我们(用户)发送的开关机命令或者查询命令编写前端应用,比如
Android应用,然后对接服务器的API,达到可以控制开关机的目的。当然,最好服务器采用带用户界面的WEB应用,这样就直接访问网页操作就好了,最好做权限控制,以及加密通信到这里基本就完成了
其它
配合 teamviewer 设置开机自启使用就可以随时随地使用自己的电脑啦~~
代码
木有现成的工程噢嘿嘿嘿
贴个简单的框架代码吧(无法直接使用)
ESP32:
client = MQTTClient(CLIENT_ID, SERVER)g_power_status = machine.Pin(21, machine.Pin.IN, 0)g_power_control = machine.Pin(22, machine.Pin.OUT, 0)def power_status():global g_power_statusreturn g_power_status.value()def power_on():global g_power_controlg_power_control.value(1)time.sleep(1.5)g_power_control.value(0)def power_off():global g_power_controlg_power_control.value(1)time.sleep(1.5)g_power_control.value(0)def power_off_force():global g_power_controlg_power_control.value(1)time.sleep(6)g_power_control.value(0)def sub_cb(topic, msg):print((topic, msg))if topic == TOPIC_DOWN:if msg == b"on":print("receive power on")power_on()elif msg == b"off":print("receive power off")power_off()elif msg == b"off force":print("receive power off force")power_off_force()elif msg == b"status":print("receive status")upload = b'{"power":%d}' %(power_status())print("upload:", upload)client.publish(TOPIC_UP, upload )def main():global clientclient.set_callback(sub_cb)client.connect()client.subscribe(TOPIC_UP)client.subscribe(TOPIC_DOWN)print("Connected to %s, subscribed to %s and %s topic" % (SERVER, TOPIC_UP, TOPIC_DOWN))try:while 1:client.wait_msg()finally:client.disconnect()if __name__ == "__main__":t = Thread(target=upload_thread)t.start()try:main()except Exception as e:machine.reset()
服务器:
以 Flask 为例,同样没有加密过程,大概上是这样的:
app = Flask(__name__)@app.route('/set')def set():cmd = request.args.get("cmd")if cmd == None:cmd = "param error cmd"else:mqtt_client.publish(TOPIC_DOWN, cmd)return cmd@app.route('/get')def get_status():global device_statusmqtt_client.publish(TOPIC_DOWN, "status")return device_statusdef on_connect(client, userdata, flags, rc):print("Connected with result code "+str(rc))client.subscribe(TOPIC_UP)print("subscribe topic succss")global isConnectedisConnected = Trueprint("connected")# The callback for when a PUBLISH message is received from the server.def on_message(client, userdata, msg):print(len(msg.payload))timeNow = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())print(timeNow+":"+msg.topic+" "+str(msg.payload))if msg.topic == TOPIC_UP:global device_statusdevice_status = timeNow + ": " + msg.payload.decode('utf-8')def web_task():app.run(host="0.0.0.0", port=12345)def mqtt_task():client = mqtt.Client(client_id="RPCC_server2",clean_session=True,userdata=None,# protocol=MQTTv311)global mqtt_clientmqtt_client = clientclient.on_connect = on_connectclient.on_message = on_messageprint("connect mqtt")client.connect("mqtt.com", 1883, 60)print("connect mqtt end")client.loop_forever()if __name__ == "__main__":t = threading.Thread(target=web_task)t.setDaemon(True)t.start()mqtt_task()
然后打开浏览器输入.../get就可以得到状态了,.../set?cmd=on就可以开机了
