WiFi 应用

通过前面的实验,我们已经对 ESP32-S2 有了一定的了解。从本章开始,将迎来非常重要实用的内容,那就是 WIFI 应用。ESP32-S2 就是为 WIFI 无线连接而生的。通过本章内容,我们可以看到基于 MicroPython 的 WIFI 开发是多么的简单而美妙。物联网的学习变得非常简单有趣!事不宜迟,马上开始学习。

连接无线路由器

前言:

WIFI 是物联网中非常重要的角色,现在基本上家家户户都有 WIFI 网络了,通过 WIFI 接入到互联网,成了智能家居产品普遍的选择。而要想上网,首先需要连接上无线路由器。这一节我们就来学习如何通过 MicroPython 编程连上路由器。

实验目的:

编程实现连接路由器,将 IP 地址等相关信息通过 OLED 显示(只支持 2.4G网络)。

实验讲解:

连接路由器上网是我们每天都做的事情,日常生活中我们只需要知道路由器的账号和密码,就能使用电脑或者手机连接到无线路由器,然后上网冲浪。

MicroPython 已经集成了 network 模块,开发者使用内置的 network 模块函数可以非常方便地连接上路由器。但往往也有各种连接失败的情况,如密码不正确等。这时候我们只需要再加上一些简单的判断机制,避免陷入连接失败的死循环即可!

我们先来看看 network 基于 WiFi(WLAN 模块)的构造函数和使用方法。

 

构造函数

wlan = network.WLAN(interface_id)

构建 WIFI 连接对象。interface_id:分为热点 network.AP_IF 和客户端

network.STA_IF 模式。

使用方法

wlan.active([is_active])

激活 wlan 接口。Ture:激活;False:关闭。

wlan.scan ()

扫描允许访问的 SSID。

wlan.isconnected()

检查设备是否已经连接上。返回 Ture:已连接;False:未连接。

wlan.connected(ssid,passwork)

WIFI 连接。ssid:账号;passwork:密码。

wlan.ifconfig([ip,subnet,gateway,dns])

设备信息配置。ip:IP 地址;subnet:子网掩码;gateway:网关地址;dns:DNS

信息。(如果参数为空,则返回当前连接信息。)

wlan.disconnected()

断开连接。

 

从上表可以看到 MicroPython 通过模块封装,让 WIFI 联网变得非常简单。模块包含热点 AP 模块和客户端 STA 模式,热点 AP 是指电脑端直接连接 ESP32-S2发出的热点实现连接,但这样你的电脑就不能上网了,因此我们一般情况下都是使用 STA 模式。也就是电脑和设备同时连接到相同网段的路由器上。模块上电后可以先判断是否已经连接到网络,如果是则无需再次连接,否的话则进入 WIFI 连接状态,指示灯闪烁,连接成功后指示灯常亮,IP 等相关信息通过 OLED 显示和串口打印。另外需要配置超时 15 秒还没连接成功时执行取消连接,避免因无法连接而陷入死循环。代码编写流程如下:

image-20230702142321217

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
'''
实验名称:连接无线路由器
版本:v1.0
日期:2021.8
作者:01Studio
说明:编程实现连接路由器,将IP地址等相关信息通过OLED显示(只支持2.4G网络)。
'''
import network,time
from machine import SoftI2C,Pin
from ssd1306 import SSD1306_I2C

#初始化相关模块
i2c = SoftI2C(sda=Pin(40), scl=Pin(38))
oled = SSD1306_I2C(128, 64, i2c, addr=0x3c)

#WIFI连接函数
def WIFI_Connect():

WIFI_LED=Pin(2, Pin.OUT) #初始化WIFI指示灯

wlan = network.WLAN(network.STA_IF) #STA模式
wlan.active(True) #激活接口
start_time=time.time() #记录时间做超时判断

if not wlan.isconnected():
print('connecting to network...')
wlan.connect('01Studio', '88888888') #输入WIFI账号密码

while not wlan.isconnected():

#LED闪烁提示
WIFI_LED.value(1)
time.sleep_ms(300)
WIFI_LED.value(0)
time.sleep_ms(300)

#超时判断,15秒没连接成功判定为超时
if time.time()-start_time > 15 :
print('WIFI Connected Timeout!')
break

if wlan.isconnected():
#LED点亮
WIFI_LED.value(1)

#串口打印信息
print('network information:', wlan.ifconfig())

#OLED数据显示
oled.fill(0) #清屏背景黑色
oled.text('IP/Subnet/GW:',0,0)
oled.text(wlan.ifconfig()[0], 0, 20)
oled.text(wlan.ifconfig()[1],0,38)
oled.text(wlan.ifconfig()[2],0,56)
oled.show()

#执行WIFI连接函数
WIFI_Connect()

总结:

本节是 WIFI 应用的基础,成功连接到无线路由器的实验后,后面就可以做socket 等相关网络通信的应用了。

 

Socket 通信

前言:

上一节我们学习了如何通过 MicroPython 编程实现 pyWiFi-ESP32-S2 模块连接到无线路由器。这一节我们则来学习一下 Socket 通信实验。Socket 几乎是整个互联网通信的基础。

实验目的:

通过 Socket 编程实现 pyWiFi-ESP32-S2 与电脑服务器助手建立连接,相互收发数据。

实验讲解:

Socket 我们听得非常多了,但由于网络工程是一门系统工程,涉及的知识非常广,概念也很多,任何一个知识点都能找出一堆厚厚的的书,因此我们经常会混淆。在这里,我们尝试以最容易理解的方式来讲述 Socket,如果需要全面了解,可以自行查阅相关资料学习。

我们先来看看网络层级模型图,这是构成网络通信的基础:

我们看看 TCP/IP 模型的传输层和应用层,传输层比较熟悉的概念是 TCP 和UDP,UPD 协议基本就没有对 IP 层的数据进行任何的处理了。而 TCP 协议还加入了更加复杂的传输控制,比如滑动的数据发送窗口(Slice Window),以及接收确认和重发机制,以达到数据的可靠传送。应用层中网页常用的则是 HTTP。那么我们先来解析一下这 TCP 和 HTTP 两者的关系。我们知道网络通信是最基础是依赖于 IP 和端口的,HTTP 一般情况下默认使用端口 80。举个简单的例子:我们逛淘宝,浏览器会向淘宝网的网址(本质是IP)和端口发起请求,而淘宝网收到请求后响应,向我们手机返回相关网页数据信息,实现了网页交互的过程。而这里就会引出一个多人连接的问题,很多人访问淘宝网,实际上接收到网页信息后就断开连接,否则淘宝网的服务器是无法支撑这么多人长时间的连接的,哪怕能支持,也非常占资源。

也就是应用层的 HTTP 通过传输层进行数据通信时,TCP 会遇到同时为多个应用程序进程提供并发服务的问题。多个 TCP 连接或多个应用程序进程可能需要通过同一个 TCP 协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与 TCP/IP 协议交互提供了套接字(Socket)接口。应用层可以和传输层通过 Socket 接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。简单来说,Socket 抽象层介于传输层和应用层之间,跟 TCP/IP 并没有必然的联系。Socket 编程接口在设计的时候,就希望也能适应其他的网络协议。

套接字(socket)是通信的基石,是支持 TCP/IP 协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议(通常是 TCP UDP),本地主机的 IP 地址,本地进程的协议端**口,远地主机的IP 地址,远地进程的协议端口。

所以,socket 的出现只是可以更方便的使用 TCP/IP 协议栈而已,简单理解就是其对 TCP/IP 进行了抽象,形成了几个最基本的函数接口。比如 create,listen,accept,connect,read 和 write 等等。以下是通讯流程:

image-20230702143005669

从上图可以看到,建了 Socket 通信需要一个服务器端和一个客户端,以本实验为例,pyWiFi-ESP32-S2 作为客户端,电脑使用网络调试助手作为服务器端,双方使用 TCP 协议传输。对于客户端,则需要知道电脑端的 IP 和端口即可建立连接。(端口可以自定义,范围在 0~65535,注意不占用常用的 80 等端口即可。)以上的内容,简单来说就是如果用户面向应用来说,那么 ESP32-S2 只需要知道通讯协议是 TCP UDP**、服务器的 IP 和端口号**这 3 个信息,即可向服务器发起连接和发送信息。就这么简单。

MicroPython 已经封装好相关模块 usocket,跟传统的 socket 大部分兼容,两者均可使用,本实验使用 usocket,对象如下介绍:

构造函数

s=usocket.socekt(af=AF_INET, type=SOCK_STREAM,proto=IPPROTO_TCP)

构建 usocket 对象。

af: AF_INET→IPV4,AF_INET6 → IPV6;

type: SCOK_STREAM→TCP,SOCK_DGRAM→UDP;

proto: IPPROTO_TCP→TCP 协议,IPPROTO_UDP→UDP 协议。

(如果要构建 TCP 连接,可以使用默认参数配置,即不输入任何参数。)

使用方法

addr=usocket.getaddrinfo(‘www.01studio.org’, 80)[0][-1]

获取 Socket 通信格式地址。返回:(‘47.91.208.161’,80)

s.connect(address)

创建连接。address:地址格式为 IP+端口。例:(‘192.168.1.115’,10000)

s.send(bytes)

发送。bytes:发送内容格式为字节

s.recv(bufsize)

接收数据。bufsize:单次最大接收字节个数。

s.bind(address)

绑定,用于服务器角色

s.listen([backlog])

监听,用于服务器角色。backlog:允许连接个数,必须大于 0。

s.accept()

接受连接,用于服务器角色。

 

本实验中 pyWiFi-ESP32-S2 属于客户端,因此只用到客户端的函数即可。实验代码编写流程如下:

image-20230702143126631

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
'''
实验名称:连接无线路由器
版本:v1.0
日期:2021.8
作者:01Studio
说明:通过Socket编程实现pyWiFi-ESP32与电脑服务器助手建立TCP连接,相互收发数据。
'''

#导入相关模块
import network,usocket,time
from machine import SoftI2C,Pin,Timer
from ssd1306 import SSD1306_I2C

#初始化相关模块
i2c = SoftI2C(sda=Pin(40), scl=Pin(38))
oled = SSD1306_I2C(128, 64, i2c, addr=0x3c)

#WIFI连接函数
def WIFI_Connect():

WIFI_LED=Pin(2, Pin.OUT) #初始化WIFI指示灯

wlan = network.WLAN(network.STA_IF) #STA模式
wlan.active(True) #激活接口
start_time=time.time() #记录时间做超时判断

if not wlan.isconnected():
print('Connecting to network...')
wlan.connect('henu-student', 'hbwz12138') #输入WIFI账号密码

while not wlan.isconnected():

#LED闪烁提示
WIFI_LED.value(1)
time.sleep_ms(300)
WIFI_LED.value(0)
time.sleep_ms(300)

#超时判断,15秒没连接成功判定为超时
if time.time()-start_time > 15 :
print('WIFI Connected Timeout!')
break

if wlan.isconnected():
#LED点亮
WIFI_LED.value(1)

#串口打印信息
print('network information:', wlan.ifconfig())

#OLED数据显示
oled.fill(0) #清屏背景黑色
oled.text('IP/Subnet/GW:',0,0)
oled.text(wlan.ifconfig()[0], 0, 20)
oled.text(wlan.ifconfig()[1],0,38)
oled.text(wlan.ifconfig()[2],0,56)
oled.show()
return True

else:
return False


#判断WIFI是否连接成功
if WIFI_Connect():

#创建socket连接TCP类似,连接成功后发送“Hello 01Studio!”给服务器。
s=usocket.socket()
addr=('192.168.1.115',10000) #服务器IP和端口
s.connect(addr)
s.send('Hello 01Studio!')


while True:

text=s.recv(128) #单次最多接收128字节
if text == '':
pass

else: #打印接收到的信息为字节,可以通过decode('utf-8')转成字符串
print(text)
s.send('I got:'+text.decode('utf-8'))

time.sleep_ms(300)

WIFI 连接代码在上一节已经讲解,这里不再重复,WIFI 连接成功后返回 True,否则返回 False。程序在返回连接成功后建了 Socket 连接,连接成功发送‘Hello 01Studio!’信息到服务器。另外 RTOS 定时器设定了了每 300ms 处理从服务器接收到的数据。将接收到数据通过串口打印和发送给服务器。

实验结果:

先在电脑端打开网络调试助手并建立服务器,软件在 零一科技(01Studio)MicroPython 开发套件配套资料_latest\01-开发工具\01-Windows\网络调试助手下的 NetAssist.exe ,直接双击打开即可!

image-20230702143433653

以下是新建服务器的方法,打开网络调试助手后在左上角协议类型选择 TCP Server;中间的本地 IP 地址是自动识别的,不要修改,这个就是服务器的 IP 地址。然后端口写 10000(0-65535 都可以。),点击连接,成功后红点亮。如下图:

image-20230702143452690

在时候服务器已经在监听状态!用户需要根据自己的实际情况自己输入 WIFI信息和服务器 IP 地址+端口。即修改上面的代码以下部分内容。(服务器 IP 和端口可以在网络调试助手找到。)

WiFi 网络信息:

wlan.connect(‘01Studio’, ‘88888888’) #输入 WIFI 账号密码

服务器信息:

addr=(‘192.168.1.115’,10000) #服务器 IP 和端口

下载程序,开发板成功连接 WIFI 后,发起了 socket 连接,连接成功可以可以看到网络调试助手收到了开发板发来的信息。在下方列表多了一个连接对象,点击选中

选中后我们在发送框输入信息“Hi”,点击发送,可以看到开发板的 REPL 打印出来信息 Hi。为字节数据。另外由于程序将收到的信息发回给服务器,所以在网络调试助手中也接收到开发板返回的信息:I got:Hi。

image-20230702143554343

image-20230702143618314

总结:

通过本节学习,我们了解了socket通信原理以及使用MicroPython进行socket编程并且通信的实验。得益于优秀的封装,让我们可以直接面向 socket 对象编程就可以快速实现 socket 通信,从而开发更多的网络应用,例如将前面采集到的传感器数据发送到服务器。