一、背景
手机SIM卡无公网IP,要实现无人机端向地面端(5G模块供网)通讯,采用IPv6实现数据交互。
二、客户端(无人机端)
无人机端作为整个服务的客户端,通过地面端的IPv6地址向地面端发送数据。
import asyncio
import websockets
import time
import requests
import subprocess
import time
# 获取当前机器的IPv6地址
def get_address_ipv6():
response = requests.get('http://ifconfig.me')
if response.status_code == 200:
return str(response.text)
async def send_message():
uri = "ws://[2408:8956:8280:857d:24d:d77b:9ac0:2]:8765" #服务器的ipv6地址
while True:
try:
message = get_address_ipv6()
async with websockets.connect(uri, timeout=10) as websocket:
#print(f"Sending message: {message}")
await websocket.send(message)
response = await websocket.recv()
#print(f"Received response: {response}")
except (websockets.exceptions.ConnectionClosed, asyncio.TimeoutError) as e:
#print(f"Connection error: {e}")
pass
time.sleep(10)
if __name__ == "__main__":
flag = True
while flag: #这个循环是为了判断当前是否右网络,检测到网络跳出循环
result = subprocess.run(['ping','-c','1','www.baidu.com'],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
if result.returncode == 0:
#print("Connected successfully !!!")
flag = False
time.sleep(5)
asyncio.run(send_message())
三、服务端(地面端)
地面端端作为整个服务的服务端,用于接收无人机端发来的数据。
import asyncio
import websockets
async def echo(websocket, path):
async for message in websocket:
print(f"Received message: {message}")
await websocket.send(f"Echo: {message}")
async def main():
server = await websockets.serve(echo, "::", 8765) # 监听所有IPv6接口
print("Server started on ws://[::]:8765")
await server.wait_closed()
if __name__ == "__main__":
asyncio.run(main())
四、效果
服务端:
客户端:
注:说明一下为什么我使用的是5G模块没有公网IP,每次重启IPv6都会变,还使用这种方法需要预先知道服务端的IPv6地址才能进行数据传递。因为是工作需要,需要调试上机测试无人机代码,最初为了方便,不想太多精力都用在这上面,因为代码是写好的,直接终端“python3 XXX”就可以运行。在测试时发现在户外,无人机上的5G模块不知道是因为信号问题还是更换基站信息导致无人机上的IPv6会不定时改变,这样通过ssh远程连接无人机就会中断。
后续还会介绍优化后的方法,包括后期调试使用的内网穿透技术,无人机端将自身的IPv6地址发送到预先搭好的服务器,通过内网穿透技术将数据放到公网上,防止地面端IPv6地址发生改变,无人机数据发送不过来的情况。还有就是最后使用开机自启时遇到的各种问题。
开机程序自启教程:ubuntu实现程序开机自启(systemd 服务和系统自带启动应用程序)
!!!此篇为个人工作时遇到的问题总结,如有侵权联系删除