【玄铁杯第三届RISC-V应用创新大赛】LicheePi"泄洪道安全警告控制系统"之四:反客为主
[复制链接]
《三十六计》有云“反客为主”,解辞云:乘隙插足,扼其主机。
上回说到楼主实现了以LicheePi 4A为服务器、以Pico W为客户端的模式后,想起了免配置的需求。就是说,需要控制端和监控端都不知道对方地址的情况下传递信息。
还是从说以太网说起——在3层上,主机之间是用IP连接的,但是在二层上,主机地址是用网卡的MAC地址表示的,那么一台只配了IP的主机,如何让知道已知IP主机的MAC地址呢?这就要解释一下ARP协议了。
ARP(Address Resolution Protocol)是一种用于将IP地址解析为物理MAC地址的协议,它在数据链路层上操作,解析过程是:需要知道某个IP对应的MAC地址的主机A发送ARP请求广播,ARP请求包含主机A的MAC地址、IP地址和目标IP地址,以及一个操作码,指示这是一个ARP请求。对应IP地址的主机B将自己的MAC地址作为响应发送给主机A。通过这种方式,ARP协议实现了将IP地址解析为对应的MAC地址,以便在局域网中进行通信。
对于"泄洪道安全警告控制系统"这个项目,可以从ARP协议中借鉴到一点,就是在不知道对端地址情况下,用“广播”的形式来实现信息的单向传递。比如想在LicheePi 4A上控制Pico W板载LED的亮灭,通过广播就可以在互不知道对端地址的情况下实现。方法如下:
首先,在已经联网的LicheePi 4A上执行这样的代码:
from socket import *
import time
port = 5000
address = ("<broadcast>", port)
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
之后就可以通过广播来发送指令了。开灯:
s.sendto("DON".encode(), address)
关灯代码:
s.sendto("DOFF".encode(), address)
屏幕显示是这样的:
而在Pico W端,要稍微复杂些:
from machine import Pin
import network
import socket
import time
# 常数定义
ssid = "FAST_538C80"
key = "12345678"
led = Pin('WL_GPIO0', Pin.OUT) # 板载LED连到WL_GPIO0
led.value(0) # 板载LED熄灭
# 定义连接WiFi函数
def connect():
global wlan
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, key)
while wlan.isconnected() == False:
print("等待连接...")
time.sleep(1)
print("已连接...")
connect()
port = 5000
UDP = ("", port)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(UDP)
# 主循环
while True:
buf, addr = sock.recvfrom(1024)
if buf:
buf = buf.decode('utf-8')
if buf[0]=="D" and buf[1]=="O" and buf[2]=='N':
led.value(1)
if buf[0]=="D" and buf[1]=='O' and buf[2]=='F' and buf[3]=='F':
led.value(0)
这样就可以在实现在LicheePi 4A上控制Pico W板载LED的亮灭了:
如此一来,基本上所有的关键点都已打通,下一步就是进行整个系统的开发了。
这正是:
乘隙插足,扼其主机,客主换位,可占先机。
欲知后事如何,且听下回分解。
|