# 智能家居之网络子系统
网络子系统采用ESP8266模块,利用串口发送AT指令,来进行数据收发控制。同样的,进行分层设计。分为网卡管理层
这里使用到的网络输入设备主要是ESP8266这一模块,关于ESP8266这一模块,可点击下面的官网了解:
[ESP8266 Wi-Fi SoC|乐鑫科技](https://www.espressif.com.cn/zh-hans/products/socs/esp8266)
网络输入系统大致的结构如下:
单片机的UART1用来与PC机器进行通信,来传输数据。UART3用于与ESP8266设备进行通信。因此,我们要实现UART1、UART3两个串口设备的管理。
同时,还要实现ESP8266网络设备的管理以及关于利用AT指令进行网络连接,收发数据,断开的接口。
## 1.网卡管理
可以支持多个网卡,向上注册网卡
首先抽象设备网络设备结构体:
```C
typedef struct NetDevice{
char *name;
char ip[4];
char mac[6];
int (*init)(struct NetDevice *ptNetDev);
//链接网卡,SSID名字,password密码
int (*connect)(struct NetDevice *ptNetDev, char *SSID, char *password);
void (*disconnect)(struct NetDevice *ptNetDev);
//发送数据 type TCP/UDP pdestip 目的ip idestport 目的端口 data 数据 len 数据长度
int (*send)(struct NetDevice *ptNetDev, char *type, char *pdestip ,int idestport ,unsigned char *data, int len);
//接收数据 type TCP/UDP localport 本地端口 psrcip 源ip data 数据 plen 数据长度 timeout 超时时间 单位ms 0表示一直等待
int (*recv)(struct NetDevice *ptNetDev, char *type, int localport, char *psrcip, unsigned char *data, int *plen, int timeout);
}NetDevice, *pNetDevice;
/**
* @brief 注册网络设备到全局链表中。
*
* 该函数将传入的网络设备结构体指针添加到全局网络设备链表的头部。
* 如果传入的指针为空,则直接返回,不进行任何操作。
*
* @param ptNetDev 指向要注册的网络设备结构体的指针。
*/
void netdeviceresiger(struct NetDevice *ptNetDev)
{
if(ptNetDev == NULL) return;
ptNetDev->next = g_netdevice;
g_netdevice = ptNetDev;
}
/**
* @brief 根据设备名称查找网络设备。
*
* 该函数遍历全局网络设备链表,查找与传入名称匹配的网络设备。
* 如果找到匹配的设备,则返回该设备的指针;若未找到,则返回 NULL。
*
* @param name 指向要查找的网络设备名称字符串的指针。
* @return 若找到匹配的网络设备,返回该设备的指针;否则返回 NULL。
*/
pNetDevice __Getnetdevice(char *name)
{
pNetDevice ptNetDev = g_netdevice;
while(ptNetDev != NULL)
{
if(strcmp(ptNetDev->name, name) == 0) return ptNetDev;
ptNetDev = ptNetDev->next;
}
return NULL;
}
```
## 2.实现网卡设备-ESP8266
```C
static NetDevice net_esp8266device = {
"esp8266",
"0.0.0.0",
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
esp8266init,
esp8266connect,
esp8266getinfo,
esp8266createudp,
esp8266closetransfer,
esp8266send,
esp8266recv,
};
#define ESP8266_DEFAULT_TIMEOUT 10 //ms //ESP8266默认超时时间 单位ms
static int esp8266init(struct NetDevice *ptNetDev)
{
/*设置ESP8266的复位引脚 不设置也行*/
/*初始化硬件接口*/
ATinterfaceinit();
/*设置WIFI模式*/
if(ATcmdsend("AT+CWMODE=3", ESP8266_DEFAULT_TIMEOUT*1000) != 0) return -1;//发送AT指令 0表示成功
//设置单连接模式
if(ATcmdsend("AT+CIPMUX=0", ESP8266_DEFAULT_TIMEOUT*1000) != 0) return -1;
return 0;
}
//链接网卡,SSID名字,password密码
static int esp8266connect(struct NetDevice *ptNetDev, char *SSID, char *password)
{
char cmd[100];
sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"", SSID, password);//构造的AT指令
printf("%s\r\n", cmd);
int ret = ATcmdsend(cmd, ESP8266_DEFAULT_TIMEOUT*1000);//发送AT指令 0表示成功
printf("esp8266connect ret = %d\r\n", ret);
return ret;
}
static void esp8266closetransfer(struct NetDevice *ptNetDev)
{
/*不是断开WIFI连接 而是应该断开某种传输*/
ATcmdsend("AT+CIPCLOSE", ESP8266_DEFAULT_TIMEOUT*1000);
}
//发送数据 type TCP/UDP pdestip 目的ip idestport 目的端口 data 数据 len 数据长度
static int esp8266send(struct NetDevice *ptNetDev, char *type, char *pdestip ,int idestport ,unsigned char *data, int len)
{
return 0;
}
//接收数据 type TCP/UDP localport 本地端口 psrcip 源ip data 数