ESP8266-WIFI模块使用AT指令连接外网服务器
第一步用java代码写一个服务器,代码如下:
代码解释:我是用nio写了一个,异步通信,用到了线程池,比较简单.当wifi模块连接后,会自动创建一个文件,用来保存 wifi模块发来的数据,这里大家可以脑洞大开实现别的功能了…
public class NIOEchoServer {
public static void main(String[] args) throws Exception {
new EchoServerHandle() ;
}
}
/**
* 实现一个专门用于客户端请求处理的线程对象
*/
class SocketClientChannelThread implements Runnable {
private SocketChannel clientChannel ; // 客户端的信息
private boolean flag = true ; // 循环处理的标记
public SocketClientChannelThread(SocketChannel clientChannel) {
this.clientChannel = clientChannel ;
System.out.println("服务器端连接成功,可以与服务器端进行数据的交互操作...");
}
@Override
public void run() { // 真正的通讯处理的核心需要通过run()方法来进行操作
createFile(null); //创建文件
// NIO是基于Buffer缓冲操作实现的功能,需要将输入的内容保存在缓存之中
ByteBuffer buffer = ByteBuffer.allocate(50) ; // 开辟一个50大小的缓存空间
try {
while(this.flag) {
buffer.clear() ; // 清空缓存操作,可以进行该缓存空间的重复使用
int readCount = this.clientChannel.read(buffer) ; // 服务器端读取客户端发送来的内容
// 将缓冲区之中保存的内容转位字节数组之后进行存储
String readMessage = new String(buffer.array(),0,readCount).trim() ;
//接收数据==========================
System.out.println("【服务器端接收消息】" + readMessage); // 输出一下提示信息
createFile(readMessage);
// 在进行整个的通讯过程里面,分隔符是一个绝对重要的概念,如果不能够很好的处理分隔符,那么无法进行有效通讯
String writeMessage = "[ECHO]" + readMessage + "\n"; // 进行消息的回应处理
if ("exit".equalsIgnoreCase(readMessage)) {
writeMessage = "[ECHO]" ; // 结束消息
this.flag = false ; // 要结束当前的循环操作
}
// 现在的数据是在字符串之中,如果要回应内容,需要将内容保存在Buffer之中
buffer.clear() ; // 将已经保存的内容(内容已经处理完毕)清除
buffer.put(writeMessage.getBytes()) ; // 保存回应信息
buffer.flip() ; // 重置缓冲区
this.clientChannel.write(buffer) ;
}
this.clientChannel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void createFile(String txt) {
String path= "/usr/Project/log/wifi.txt";//这里是创建文件位置 自行修改
File file = new File(path);
if(!file.exists()){
try {
file.createNewFile();
System.err.println("创建文件成功");
return ;
} catch (Exception e) {
e.printStackTrace();
}
}
if(txt == null || txt == "") {return ;}
FileWriter fw = null;
try {
fw = new FileWriter(path,true);
fw.write(txt.toString());
System.err.println("写入文件成功");
} catch (IOException e) {
}finally {
try {
if(fw != null) {
fw.flush();
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class EchoServerHandle implements AutoCloseable { // 定义服务器端的服务处理类
private final int PORT = 80; //端口号
private ExecutorService executorService ;
private ServerSocketChannel serverSocketChannel ; // 服务器端的通讯通道
private Selector selector ;
private SocketChannel clientChannel ; // 客户端的信息
public EchoServerHandle() throws Exception {
this.executorService = Executors.newFixedThreadPool(5) ; // 当前的执行线程只允许有5个
this.serverSocketChannel = ServerSocketChannel.open() ; // 打开服务器端连接通道
this.serverSocketChannel.configureBlocking(false) ; // 设置为非阻塞模式
this.serverSocketChannel.bind(new InetSocketAddress(PORT)) ;
// NIO之中的Reactor模型重点在于所有的Channel需要向Selector之中进行注册
this.selector = Selector.open() ; // 获取Selector实例
this.serverSocketChannel.register(this.selector,SelectionKey.OP_ACCEPT) ; // 服务器端需要进行接收
System.out.println("服务器端程序启动,该程序在" + PORT + "端口上进行监听...");
this.clientHandle();
}
private void clientHandle() throws Exception {
int keySelect = 0 ; // 保存一个当前的状态
while((keySelect = this.selector.select()) > 0) { // 需要进行连接等待
Set<SelectionKey> selectedKeys = this.selector.selectedKeys() ; // 获取全部连接通道信息
Iterator<SelectionKey> selectionIter = selectedKeys.iterator() ;
while(selectionIter.hasNext()) {
SelectionKey selectionKey = selectionIter.next() ; // 获取每一个通道
if(selectionKey.isAcceptable()) { // 该通道为接收状态
this.clientChannel = this.serverSocketChannel.accept() ; // 等待连接
if (this.clientChannel != null) { // 当前有连接
this.executorService.submit(new SocketClientChannelThread(this.clientChannel)) ;
}
}
selectionIter.remove(); // 移除掉此通道
}
}
}
@Override
public void close() throws Exception {
this.executorService.shutdown(); // 关闭线程池
this.serverSocketChannel.close(); // 关闭服务器端
}
服务器完整代码上传码云了,点击
代码写完后打成jar包上传到服务器上-- 然后运行 命令 java-jar wifi.jar
第二步开始连接服务器
连接命令如下:
1,AT+GMR //启动查询版本信息
AT version:1.1.0.0(May 11 2016 18:09:56)
SDK version:1.5.4(baaeaebb)
compile time:May 20 2016 15:08:19
OK
2,AT+CWMODE_DEF=1 //配置WiFi模组工作模式为单STA模式,并把配置保存在flash
OK
3,AT+CWJAP_DEF=“huanglong123”,“anxsdfinsdke123” //连接网络
WIFI CONNECTED
WIFI GOT IP
OK
4,AT+CWAUTOCONN=1 //使能上电自动连接AP
OK
5,AT+CIPSTART=“TCP”,“129.231.40.13”,80 //连接服务器
连接成功后会创建一个文件,用来保存接收到的数据
这里有个坑,之前外网服务器端口换成了其他端口8099什么的,一直连不上,坑了我两天,还以为wifi模块有问题,后来把端口换成80就能连上了,
CONNECT
OK
6,AT+CIPMODE=1 //设置透传
OK
7,AT+CIPSEND //启动发送
OK
**8,> hello //发送数据
10, +++ !!退出透传,不要勾选新行(\r\n)
3 . 51单片机代码
#include<reg52.h>
#include <intrins.h>
#include <led.h>
#include <stdio.h>
#include <string.h>
#include <wd.h>
/*************
-------黄龙原创-------
**************/
unsigned char receive[20]; //用于接收wifi模块反馈到MCU上的数据
unsigned char datas;
unsigned char i = 0;
unsigned int openStatu = 2;
unsigned char flag = 3;
sbit kg = P2 ^ 7;
sbit k2 = P3 ^ 7; //按键
//如果收到心跳 重新计时
void change()
{
flag ++;
flag ++;
flag ++;
}
void InitUART(void)
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xFD;
TL1 = TH1;
PCON = 0x00;
EA = 1;
ES = 1;
TR1 = 1;
LED_3();
kg = 1;
}
void SendOneBytes(unsigned char c)
{
ES = 0; //关闭串口中断
TI = 0; //清发送完毕中断请求标志位
SBUF = c;
while(!TI); //等待发送完毕
TI = 0;//清发送完毕中断请求标志位
ES = 1; //允许串口中断
}
void ESP8266_Sets(unsigned char *puf) // 数组指针*puf指向字符串数组
{
while(*puf != '\0')
{
SendOneBytes(*puf);
puf++;
}
}
/**初始化**/
void ESP8266_Set()
{
//说明 0000是wifi客户端编号 1:是wifi唯一id
unsigned char info[] = "[:0000:w-10000:]\r\n"; //客户端编号
ESP8266_Sets("AT+CIPSTART=\"TCP\",\"47.96.183.158\",2999\r\n"); //连接服务器
LED_4();
LED_4();
LED_4();
ESP8266_Sets("AT+CIPMODE=1\r\n"); // 开启透传模式
LED_4();
ESP8266_Sets("AT+CIPSEND\r\n"); //开启透传
LED_4();
ESP8266_Sets(info); //向服务器发送数据
}
//重试机制
void delay70ms(void) //误差 -0.000000000016us
{
//LED_8();
while(1)
{
//30秒flag 减一
delay_led(10000);
delay_led(10000);
delay_led(5000);
flag --;
LED_7();
if(flag == 0)
{
LED_8();
LED_8();
LED_8();
// ESP8266_Sets("AT+CWJAP_DEF=\"ChinaNet-huanglong\",\"1528177109huanglong\"\r\n"); //连接路由器
delay_led(5000);
ESP8266_Set(); //如果一分半还没有收到服务器心跳 重新连接服务器
change();
}
}
}
//按钮
void button()
{
while(1)
{
if(k2 == 0)
{
ESP8266_Set(); //初始化wifi模块
// delay70ms();
}
}
}
void main(void)
{
InitUART();
delay_led(6000);
ESP8266_Set(); //初始化wifi模块
delay70ms(); //监听心跳
//button();
// lcd_init();//初始化液晶屏
}
void UARTInterrupt(void) interrupt 4
{
if(RI)
{
unsigned char res;
res = SBUF; //取出接受到的数据
RI = 0; //清除接受中断标志位
receive[i] = res;
i++;
//ESP8266_Sets(receive);
//打开 低电平触发
if(receive[i - 5] == 'S' && receive[i - 4] == 'T' && receive[i - 3] == 'A' && receive[i - 2] == 'R' && receive[i - 1] == 'T')
{
if(openStatu == 0)
{
kg = 0; //打开开关
LED_8();
kg = 1;
ESP8266_Sets("[:3333:w-10000:a-10001:open:]\r\n");
openStatu = 1; //设置打开状态
change();
}
else
{
ESP8266_Sets("[:3333:w-10000:a-10001:isOpen:]\r\n");
}
}
//关闭
if(receive[i - 5] == 'C' && receive[i - 4] == 'L' && receive[i - 3] == 'O' && receive[i - 2] == 'S' && receive[i - 1] == 'E')
{
if(openStatu == 1)
{
kg = 0;
LED_8();
LED_8();
LED_8();
LED_8();
kg = 1;
ESP8266_Sets("[:3333:w-10000:a-10001:close:]\r\n");
openStatu = 0;
change();
}
else
{
ESP8266_Sets("[:3333:w-10000:a-10001:isClose:]\r\n");
}
}
//复位
if(receive[i - 5] == 'R' && receive[i - 4] == 'E' && receive[i - 3] == 'S' && receive[i - 2] == 'E' && receive[i - 1] == 'T')
{
openStatu = 0;
ESP8266_Sets("[:3333:w-10000:a-10001:reset_ok:]\r\n");
}
if(receive[i - 1] == 'P') //接收心跳
{
change(); //改变标识状态
// LED_0();
// delay70ms();
}
if(receive[i] == '\0') //如果接收完数据 清空数组
{
int j;
for(j = 0; j < sizeof(receive); j++)
{
receive[j] =0;
}
// i = 0;
}
}
}