最近打算做一个远程数据采集的项目,需要单片机+传感器模块采集数据并发送到云端,在家只有个ESP8266-NodeMCU开发板,将就模拟一下这个过程。
信息只需要单向传输而且也不需要反馈,所以干脆简单粗暴用udp协议吧,如果需要双向控制并且设备比较复杂的话还是用mqtt协议比较好,毕竟目前物联网大趋势如此。
接收端(服务端):
这个比较简单,用java接收一下并输出,目前想的就是能把数据接收过来保存到字符串中,后期再用正则表达式提取一下有用的数据就行。接收分为以下几步:
- 1.建立socket服务,监听指定端口
- 2.定义一个Packet用于存放接收到的字节数据
- 3.通过socket的receive方法将接收到的数据存放到Packet中
- 4.取出数据,打印
- 5.关闭资源(没写,持续运行接收中)
public class Server {
public static void main(String[] args) throws Exception {
DatagramSocket ds=new DatagramSocket(12345);//1
byte[] buf =new byte[1000];
DatagramPacket dp= new DatagramPacket(buf,buf.length);//2
while(true)
{
ds.receive(dp);//3
String data =new String(dp.getData(),0,dp.getLength());//4
SimpleDateFormat sdf = new SimpleDateFormat("时间:yyyy年MM月dd日 HH:mm:ss 数据:");
Calendar c = Calendar.getInstance();
String time=sdf.format(c.getTime());
System.out.println(time+data);
}
}
}
发送端:
发送端有两步,一是连接WiFi,二是发送数据。需要用到ESP8266WiFi.h
和WiFiUdp.h
这两个库。
连接WiFi比较容易,官方例程的方法直接拿来用,我把它封装到一个函数里了。
void connectWIFI()
{
Serial.begin(115200);
Serial.println();
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(" connected");
}
发送数据跟接收数据那里差不多,步骤:
- 1.定义一个UDP服务
- 2.开启udp,指定对方的主机和端口
- 3.向上述主机和端口发送数据
- 关闭资源
但是这里遇到了一个大坑,一开始发送一个固定的字符串(其实是char数组)没啥问题,后来把int数据(来自传感器的数据就是int类型)封装到string中发送直接报错,因为write方法只能接受char数组作为参数。后来我打算把string转成char[],用了各种方法都失败了(可能是我用的Arduino IDE编译或烧录有问题,毕竟在DEVcpp里运行没啥问题),所以干脆简单粗暴把int数据一个一个的存到char[]中了。
(其实这里没必要这么麻烦,用byte[]封装数据或许也可以,有时间再试试)
void pack(char* str,int x,int y)
{
for(int i=0;i<25;i++)
{
str[i]=',';
}
int i=4;
while(x!=0)
{
str[i--]=x%10+48;
x=x/10;
}
int j=14;
while(y!=0)
{
str[j--]=y%10+48;
y=y/10;
}
}
发送端代码:
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char* ssid = "FAST_6A98";
const char* password = "87654321";
char str[30];
int i = 1;//用i分别代表传感器返回的数据吧,家里没有传感器没法测试了
WiFiUDP Udp;//1
void setup()
{
connectWIFI();
}
void loop() {
pack(str,i,i++);
Udp.beginPacket("47.93.184.169", 12345);//2
Udp.write(str);//3
Udp.endPacket();//4
delay(1000);
}