抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

介绍

在嵌入式课程作业中做了个智能家居的简单产品,用到了ESP8266的NodeMCU开发板和stm32开发板(程序后面介绍),为了能够将采集的数据通过网络发布出去,这里采用了MQTT协议,服务端采用的是腾讯云MQTT服务

数据发布到服务器后,Android客户端可以向服务器订阅主题来获取到消息,然后进行展示。ESP8266客户端通过订阅也能获取到Android客户端发布的消息。

这是通信过程框图:

image-20211116233340883

功能

  1. 连接WiFi
  2. 启动后led点亮,连接上MQTT服务端后闪烁,未连接常亮
  3. 通过网络获取如下信息
  4. 与STM32通过串口进行数据通信
  5. 建立与MQTT服务器的连接
  6. 向服务器指定的主题发布消息和接收消息
  7. json数据处理

完整代码

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <ESP8266HTTPClient.h>
#include <WiFiManager.h>

//wifi配置
const char* ssid = "xxxxxx";
const char* password = "xxxxxxxx";

//mqtt服务器连接配置
const char *mqttBroker = "xxxxxx.iotcloud.tencentdevices.com";
const char *mqttUsername = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char *mqttPassword = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char *mqttClientId = "xxxxxxxxxxxesp8266";
const char *pubTopic = "xxxxxx/esp8266/data";
const char *subTopic = "xxxxxx/esp8266/data";
const int mqttPort = 1883;

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

struct Weather{
String wea="";
String temp="";
String windpower=""; //风力,单位:级
String humi="";
};

struct ServerMsg{
String alarmTemp="";
String minLight="";
};

//时间api
const String timeUrl = "http://quan.suning.com/getSysTime.do";
//高德地图api(自己获取key, city是城市编码)
const String gaoDeUrl = "http://restapi.amap.com/v3/weather/weatherInfo?key=xxxxx&city=610100";
String timeMsg="";
String weatherMsg="";
String timeAfterParse="";
struct Weather weatherAfterParse;
String data2stm=""; //打包后发送给stm32的信息
String data2server=""; //发布到mqtt服务器的信息

String callHttp(String httpUrl);
String parseJsonTime(String tjson);
struct Weather parseJsonWeather(String wjson);
void ledOnOff();
String tqzh2py(String zhtq); //中文天气转拼音
String windpowerFormat(String wp);

void connectWifi();
void setLedOnOff();
void publishTopic(const char* topic, char* jsonMsg);
void subscribeTopic(const char* topic);
struct ServerMsg parseServerMsg(String jsonMsg);
void getSerialDataAndProcess();

void setup() {
pinMode(LED_BUILTIN, OUTPUT); // 设置板上LED引脚为输出模式
digitalWrite(LED_BUILTIN, LOW); // 启动后打开板上LED
Serial.begin(115200); // 启动串口通讯

connectWifi();
mqttInit();
connectMqttServer();

timeMsg = callHttp(timeUrl);
weatherMsg = callHttp(gaoDeUrl);
}

struct ServerMsg serverMsgAfterParse;
String serverMsg="";
String stm32Msg="";
int n = 0;

void loop() {

delay(500);
n++;

//获取网络数据(时间、天气)

if(n % 2 == 0){
ledOnOff();
timeMsg = callHttp(timeUrl);
if(n >= 20){ //10s获取一次天气
weatherMsg = callHttp(gaoDeUrl);
n=0;
}
}

//获取stm32数据,并发送到mqtt服务器
getSerialDataAndProcess();

//对网络获取到的数据处理
if(timeMsg!=""){
timeAfterParse = parseJsonTime(timeMsg);
}
if(weatherMsg!=""){
weatherAfterParse = parseJsonWeather(weatherMsg);
}
if(serverMsg!=""){
serverMsgAfterParse = parseServerMsg(serverMsg);
}

//打包发送到stm32
if(timeMsg!="" && weatherMsg!=""){
data2stm = (timeAfterParse + "," + tqzh2py(weatherAfterParse.wea) + "," + weatherAfterParse.temp + "," +weatherAfterParse.humi +"," + windpowerFormat(weatherAfterParse.windpower) + "," + serverMsgAfterParse.alarmTemp + "," + serverMsgAfterParse.minLight + "," + "\r\n"); //日期,天气,温度,湿度,风力等级,报警温度,最低光照
Serial.print(data2stm);
}

if (mqttClient.connected()) { // 如果开发板成功连接服务器
mqttClient.loop(); // 处理信息以及心跳
} else { // 如果开发板未能成功连接服务器
connectMqttServer(); // 则尝试连接服务器
}

}

void mqttInit(){
mqttClient.setServer(mqttBroker, mqttPort);
// 设置MQTT订阅回调函数
mqttClient.setCallback(receiveCallback);
}

// 连接MQTT服务器并订阅信息
void connectMqttServer(){
while (!mqttClient.connected()) {
if (mqttClient.connect(mqttClientId, mqttUsername, mqttPassword)) {
subscribeTopic(subTopic); //订阅主题
} else {
delay(2000);
// Serial.println("连接失败");
}
}
}

// 订阅指定主题
void subscribeTopic(const char* topic){
if(mqttClient.subscribe(topic)){

} else {

}
}

// 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length) {
serverMsg = ""; //当下次调用时清空数据
for (int i = 0; i < length; i++) {
// Serial.print((char)payload[i]);
serverMsg += (char)payload[i];
}
// Serial.println("\n");
// Serial.println(serverMsg);
}

struct ServerMsg parseServerMsg(String jsonMsg){
struct ServerMsg smsg;
const size_t capacity = 96;
DynamicJsonDocument sdoc(capacity);

// 反序列化数据
deserializeJson(sdoc, jsonMsg);
smsg.alarmTemp = sdoc["atemp"].as<String>();
smsg.minLight = sdoc["mlight"].as<String>();
return smsg;
}

void publishTopic(const char* topic, char* jsonMsg){
mqttClient.publish(topic, jsonMsg, false);
}

void ledOnOff(){
static bool LEDState=0;
if(mqttClient.connected()){
LEDState = !LEDState; //连上,led闪烁
}
else{
LEDState = 0; //没连上,led常亮
}
digitalWrite(LED_BUILTIN, LEDState);
}

String callHttp(String httpUrl) {
HTTPClient hClient;
String message;
hClient.begin(httpUrl);

int httpCode = hClient.GET();
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) {
String payload = hClient.getString();
message = payload;
}
} else {
message = "[1-HTTP]failed, error:" + String(hClient.errorToString(httpCode).c_str());
}
hClient.end();
return message;
}

void getTimeMsg(){
timeMsg = callHttp(timeUrl);
}

void getWeatherMsg(){
weatherMsg = callHttp(gaoDeUrl);
}

String parseJsonTime(String tjson){

const size_t capacity = 96;
DynamicJsonDocument tdoc(capacity);

// 反序列化数据
deserializeJson(tdoc, tjson);

// 获取解析后的数据信息
String datetime = tdoc["sysTime2"].as<String>();

return datetime;
}


//{"status":"1","count":"1","info":"OK","infocode":"10000","lives":[{"province":"陕西","city":"西安市","adcode":"610100","weather":"晴","temperature":"13","winddirection":"北","windpower":"≤3","humidity":"88","reporttime":"2021-10-29 21:03:10"}]}
struct Weather parseJsonWeather(String wjson){

struct Weather weather;

const size_t capacity = 512;
DynamicJsonDocument wdoc(capacity);

// 反序列化数据
deserializeJson(wdoc, wjson);

JsonObject lives_0 = wdoc["lives"][0];

weather.wea = lives_0["weather"].as<String>(); // "晴"
weather.temp = lives_0["temperature"].as<String>(); // "13"
weather.humi = lives_0["humidity"].as<String>(); // "88"
weather.windpower = lives_0["windpower"].as<String>(); // "≤3"
return weather;
}


String tqzh2py(String zhtq){

String zh_cn[68] = {"晴","少云","晴间多云","多云","阴","有风","平静","微风","和风","清风","强风/劲风","疾风","大风","烈风","风暴","狂爆风","飓风","热带风暴","霾","中度霾","重度霾","严重霾","阵雨","雷阵雨","雷阵雨并伴有冰雹","小雨","中雨","大雨","暴雨","大暴雨","特大暴雨","强阵雨","强雷阵雨","极端降雨","毛毛雨/细雨","雨","小雨-中雨","中雨-大雨","大雨-暴雨","暴雨-大暴雨","大暴雨-特大暴雨","雨雪天气","雨夹雪","阵雨夹雪","冻雨","雪","阵雪","小雪","中雪","大雪","暴雪","小雪-中雪","中雪-大雪","大雪-暴雪","浮尘","扬沙","沙尘暴","强沙尘暴","龙卷风","雾","浓雾","强浓雾","轻雾","大雾","特强浓雾","热","冷","未知",};
String py[68] = {"qing","shaoyun","qingjianduoyun","duoyun","yin","youfeng","pingjing","weifeng","hefeng","qingfeng","qiangfeng/jinfeng","jifeng","dafeng","liefeng","fengbao","kuangbaofeng","jufeng","redaifengbao","mai","zhongdumai","zhongdumai","yanzhongmai","zhenyu","leizhenyu","leizhenyubingbanyoubingbao","xiaoyu","zhongyu","dayu","baoyu","dabaoyu","tedabaoyu","qiangzhenyu","qiangleizhenyu","jiduanjiangyu","maomaoyu/xiyu","yu","xiaoyu-zhongyu","zhongyu-dayu","dayu-baoyu","baoyu-dabaoyu","dabaoyu-tedabaoyu","yuxuetianqi","yujiaxue","zhenyujiaxue","dongyu","xue","zhenxue","xiaoxue","zhongxue","daxue","baoxue","xiaoxue-zhongxue","zhongxue-daxue","daxue-baoxue","fuchen","yangsha","shachenbao","qiangshachenbao","longjuanfeng","wu","nongwu","qiangnongwu","qingwu","dawu","teqiangnongwu","re","leng","weizhi"};

for(int i=0; i<68; i++){

// if(strstr())
if(zh_cn[i] == zhtq)
return py[i];
}

return zhtq; //没有就返回中文
}

String windpowerFormat(String wp){

if(wp=="≤3"){
return "<=3";
}
return wp;
}

//得到数据后处理方式,把它当作一个串口(伪)中断函数
void getSerialDataAndProcess(){
if (Serial.available()) { //串口读取到的转发到wifi,因为串口是一位一位的发送所以在这里缓存完再发送
size_t countBytes = Serial.available();
char sbuf[countBytes];
Serial.readBytes(sbuf, countBytes);

// Serial.write(sbuf, countBytes);
publishTopic(pubTopic, sbuf);
Serial.flush();
}
}



void connectWifi(){

// WiFiManager wifiManager;
//
// 自动连接WiFi。以下语句的参数是连接ESP8266时的WiFi名称
// wifiManager.autoConnect("IamESP8266");

WiFi.mode(WIFI_STA); //WIFI_STA、WIFI_AP、WIFI_AP_STA
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}

在实现MQTT通信之前通过Socket与Android客户端进行通信,缺点是只能在同一个网络下(局域网)才能通信,这里也把代码呈上

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <vector>
#include <Ticker.h>

Ticker ticker;

struct Weather{
String wea="";
String temp="";
String windpower=""; //风力,单位:级
String humi="";
};

const char* ssid = "xxxxx";
const char* password = "xxxxxx";

const String timeUrl = "http://quan.suning.com/getSysTime.do";
const String gaoDeUrl = "http://restapi.amap.com/v3/weather/weatherInfo?key=xxxxxx&city=610100";
String timeMsg="";
String weatherMsg="";
String timeAfterParse="";
struct Weather weatherAfterParse;
String data2stm=""; //打包后发送给stm32的信息
String data2client=""; //发送给socket客户端的信息

String callHttp(String httpUrl);
String parseJsonTime(String tjson);
struct Weather parseJsonWeather(String wjson);
void led_on_off();
String tqzh2py(String zhtq);//中文天气转拼音
String windpowerFormat(String wp);

void connectWIFI(char* ssid, char* password);
void NewClient();
void setLedOnOff(WiFiClient serverClient);
void sendData2Client(WiFiClient serverClient, uint8_t sbuf[], int len);
void receiveDataFromClient(WiFiClient serverClient);
void getSerialDataAndProcess();


WiFiServer server(5045); //端口号,随意修改,范围0-65535
WiFiClient serverClient; //连接到服务器的客户端

//初始化
void setup() {
Serial.begin(115200);
server.begin();
pinMode(2, OUTPUT); //设置内置LED引脚为输出模式
digitalWrite(2, LOW);

connectWIFI(ssid, password);

// ticker.attach(1, getTimeMsg);
// ticker.attach(10, getWeatherMsg);

timeMsg = callHttp(timeUrl);
weatherMsg = callHttp(gaoDeUrl);
}

String clientMsg="";
String stm32Msg="";
int n = 0;

void loop() {
n++;
NewClient();
setLedOnOff(serverClient); //指示灯提示是否连接到客户端


//get data from client, Internet
timeMsg = callHttp(timeUrl);
if(n >= 12){ //大概10s请求一次
//timeMsg = callHttp(timeUrl);
weatherMsg = callHttp(gaoDeUrl);
n=0;
}
receiveDataFromClient(serverClient);

//get data from stm32 and process
getSerialDataAndProcess();

//data process
if(timeMsg!=""){
timeAfterParse = parseJsonTime(timeMsg);
}

if(weatherMsg!=""){
weatherAfterParse = parseJsonWeather(weatherMsg);
}


//打包数据发到stm32
//data2stm += (clientMsg + ",");
if(timeMsg!="" && weatherMsg!=""){
data2stm = (timeAfterParse + "," + tqzh2py(weatherAfterParse.wea) + "," + weatherAfterParse.temp + "," +weatherAfterParse.humi +"," + windpowerFormat(weatherAfterParse.windpower) + "," + clientMsg + "," + "\r\n"); //日期,天气,温度,湿度,风力等级
Serial.print(data2stm);
// if(n%6 == 0){
// Serial.print(data2stm);
// }
}


//data2stm="";


//send data to stm32
// if(n==5 && data2stm!=""){
// Serial.print("data to stm: " + data2stm);
// }


// send data to client
// if(stm32Msg!=""){
// data2client = stm32Msg;
// sendData2Client(serverClient, data2client);
// stm32Msg="";
// }


//delay(100);
}


void led_on_off(){
static bool LEDState=0;
LEDState = !LEDState;
digitalWrite(LED_BUILTIN, LEDState);
}


String callHttp(String httpUrl) {
HTTPClient hClient;
String message;
hClient.begin(httpUrl);

int httpCode = hClient.GET();
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) {
String payload = hClient.getString();
message = payload;
}
} else {
message = "[1-HTTP]failed, error:" + String(hClient.errorToString(httpCode).c_str());
}
hClient.end();
return message;
}

void getTimeMsg(){
timeMsg = callHttp(timeUrl);
}

void getWeatherMsg(){
weatherMsg = callHttp(gaoDeUrl);
}

String parseJsonTime(String tjson){

const size_t capacity = 96;
DynamicJsonDocument tdoc(capacity);

// 反序列化数据
deserializeJson(tdoc, tjson);

// 获取解析后的数据信息
String datetime = tdoc["sysTime2"].as<String>();

return datetime;
}


//{"status":"1","count":"1","info":"OK","infocode":"10000","lives":[{"province":"陕西","city":"西安市","adcode":"610100","weather":"晴","temperature":"13","winddirection":"北","windpower":"≤3","humidity":"88","reporttime":"2021-10-29 21:03:10"}]}
struct Weather parseJsonWeather(String wjson){

struct Weather weather;

const size_t capacity = 512;
DynamicJsonDocument wdoc(capacity);

// 反序列化数据
deserializeJson(wdoc, wjson);

JsonObject lives_0 = wdoc["lives"][0];

weather.wea = lives_0["weather"].as<String>(); // "晴"
weather.temp = lives_0["temperature"].as<String>(); // "13"
weather.humi = lives_0["humidity"].as<String>(); // "88"
weather.windpower = lives_0["windpower"].as<String>(); // "≤3"
return weather;
}

String tqzh2py(String zhtq){

String zh_cn[68] = {"晴","少云","晴间多云","多云","阴","有风","平静","微风","和风","清风","强风/劲风","疾风","大风","烈风","风暴","狂爆风","飓风","热带风暴","霾","中度霾","重度霾","严重霾","阵雨","雷阵雨","雷阵雨并伴有冰雹","小雨","中雨","大雨","暴雨","大暴雨","特大暴雨","强阵雨","强雷阵雨","极端降雨","毛毛雨/细雨","雨","小雨-中雨","中雨-大雨","大雨-暴雨","暴雨-大暴雨","大暴雨-特大暴雨","雨雪天气","雨夹雪","阵雨夹雪","冻雨","雪","阵雪","小雪","中雪","大雪","暴雪","小雪-中雪","中雪-大雪","大雪-暴雪","浮尘","扬沙","沙尘暴","强沙尘暴","龙卷风","雾","浓雾","强浓雾","轻雾","大雾","特强浓雾","热","冷","未知",};
String py[68] = {"qing","shaoyun","qingjianduoyun","duoyun","yin","youfeng","pingjing","weifeng","hefeng","qingfeng","qiangfeng/jinfeng","jifeng","dafeng","liefeng","fengbao","kuangbaofeng","jufeng","redaifengbao","mai","zhongdumai","zhongdumai","yanzhongmai","zhenyu","leizhenyu","leizhenyubingbanyoubingbao","xiaoyu","zhongyu","dayu","baoyu","dabaoyu","tedabaoyu","qiangzhenyu","qiangleizhenyu","jiduanjiangyu","maomaoyu/xiyu","yu","xiaoyu-zhongyu","zhongyu-dayu","dayu-baoyu","baoyu-dabaoyu","dabaoyu-tedabaoyu","yuxuetianqi","yujiaxue","zhenyujiaxue","dongyu","xue","zhenxue","xiaoxue","zhongxue","daxue","baoxue","xiaoxue-zhongxue","zhongxue-daxue","daxue-baoxue","fuchen","yangsha","shachenbao","qiangshachenbao","longjuanfeng","wu","nongwu","qiangnongwu","qingwu","dawu","teqiangnongwu","re","leng","weizhi"};

for(int i=0; i<68; i++){

// if(strstr())
if(zh_cn[i] == zhtq)
return py[i];
}

return zhtq; //没有就返回中文
}

String windpowerFormat(String wp){

if(wp=="≤3"){
return "<=3";
}
return wp;
}

void connectWIFI(const char* ssid, const char* password) {
WiFi.mode(WIFI_STA); //WIFI_STA、WIFI_AP、WIFI_AP_STA
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}

//检测新的client
void NewClient() {
uint8_t i=0;

//检测是否有新的client请求进来
if (server.hasClient()) {
//释放旧无效或者断开的client
if (!serverClient || !serverClient.connected()) {
if (serverClient) {
serverClient.stop();
}
//分配最新的client
serverClient = server.available();
//Serial.print("New client: ");
//Serial.print(i);
i=1;
}
if(i==1){
//当达到最大连接数 无法释放无效的client,需要拒绝连接
WiFiClient serverClient = server.available();
serverClient.stop();
//Serial.println("Connection rejected ");
}
}
}

//客户端连接时常亮,无连接时闪烁
void setLedOnOff(WiFiClient serverClient) {
//连接情况 用led灯的状态显示
if(serverClient.connected()){
digitalWrite(2, LOW);
delay(800);
} else{
digitalWrite(2, HIGH);
delay(400);
digitalWrite(2, LOW);
delay(400);
}
}

//接收客户端的数据
void receiveDataFromClient(WiFiClient serverClient) {
uint8_t buffLen=0;
char buff[100];

if (serverClient && serverClient.connected()) {
// while (serverClient.available()){
// r[i] = serverClient.read();
// i++;
// }
// if (serverClient.read() == -1){
// Serial.printf("%s", r);
// }

if(serverClient.available()){
buffLen = serverClient.available();
serverClient.readBytes(buff, buffLen);
//Serial.write(buff, buffLen);
//Serial.printf("\r\nbufflen: %d\r\n", buffLen);
serverClient.flush();

clientMsg = "";
for(uint8_t i=2; i<buffLen; i++){ //i=2表示舍弃客户端发送的第一个字符(安卓客户端在数据开头会发送一个特殊字符,由于是UTF-8编码方式,占用2Bytes)
clientMsg += (buff[i]);
}
//Serial.println("msg: "+ clientMsg);
}
//else Serial.println("--------------------");
}
}


void sendData2Client(WiFiClient serverClient, char data[], uint8_t len) { //len为字节数
if (serverClient && serverClient.connected()) {
serverClient.write(data, len); //将数据发送给客户端
// Serial.write(sbuf, len);
delay(200);
}
}


//得到数据后处理方式,把它当作一个串口(伪)中断函数
void getSerialDataAndProcess(){
if (Serial.available()) { //串口读取到的转发到wifi,因为串口是一位一位的发送所以在这里缓存完再发送
size_t countBytes = Serial.available();
char sbuf[countBytes];
Serial.readBytes(sbuf, countBytes);

// Serial.write(sbuf, countBytes);
sendData2Client(serverClient, sbuf, countBytes);
Serial.flush();
}
}

评论