ESP8266物联网远距离控制实现
转载请注明出处!
重要的事情放在前面源码在GitHub上面欢迎issue,如果可以的话Star一下也是表示对作者的支持,有很多不足,希望可以得到指教。
https://github.com/yesbutter/ESP8266-Data-Transmission
不多说废话,开门见山。实现功能。单片机通过轮询查询服务器端的指定文件夹
下的内容,在显示屏上显示。手机端可以发送消息到服务器端来实现更改显示屏的
内容。
实际扩展可以实现手机端和单片机进行远程通信。理论上只需要有网络就可以实
现联系手机端发送消息到服务器,实际实现方式:服务器发送信息给单片机,单片
机返回信息给服务器,并将服务器返回的信息给手机。
心里路程,寒假接触了stm32,esp8266。没有实际去使用,加入的嵌入式要做结
营作品。就准备摸索一下ESP8266实现远距离控制。然后就在考完4级之后去学习做
这个通信。
工具
- Android studio
- Keil5
- STM32开发板
- ESP8266WIFI模块
- 网络调试工具,串口调试工具
- Eclipse
遇到的坑:
1.单片机调试的时候没能清楚理解单片机程序发送的信息在那里显示。单片机发送消
息给网络的代码是导致调试了很久。
2.单片机和服务器通信的时候,当单片机发送AT+CIPMODE=1和AT+CIPSEND需要服务
器返回信息OK
3.寻找单片机接受服务器的消息的代码,实际ESP8266打开了USART2串口,然后根据
返回信息进行判断,额外加了一个代码判断返回信息的标志。加了一个标志位即当读
到'\n'就认为是结束。
if(ucCh=='\n')
{
ESP8266_Fram_Record_Struct .InfBit .FramFinishFlag = 1
}
4.服务器端的代码确保能打开端口,实现端口通信。如果不太懂可以打开防火墙,要
是被自己的防火墙给墙了也是一种极好的体验。
开发过程:
第一天:实现单片机和网络调试工具通信,通过网络调试工具发送信息给单片机。
第二天:继续做第一天任务,寻找服务器代码实现,学习之后实现自己的功能,实
现了服务器和单片机通信。
第三天:编写Android 移动程序实现和服务器的通信,继续编写服务器代码实现数
据通信。
第四天:收尾工作,写代码,写历程。emm该爬去复习了。溜了
ESP8266AT指令
- ESP8266初始化设置通信波特率。
- 1.发送AT指令看是否收到OK,没有就重启ESP8266
- 2.发送AT+CWMODE=1,设置工作模式为station,直到设置成功
- 3.AT+CWJAP=”你的WiFi名字”,”你的WiFi密码”,直到加入成功
- 4.发送AT+CIPMUX=0,设置禁止多连接模式
- 5.发送AT+CIPSTART=”TCP”,”192.168.1.111”,8080。表示去连连接192.168.1.111 的8080端口
- 6.发送AT+CIPMODE=1设置进入透传模式,响应为��。
- 7.发送AT+CIPSEND表示发送数据,等待服务器返回信息。
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
LED_Init();
USART1_Init(115200);
ESP8266_Init(115200);
ESP8266_STA_TCPClient_Test();
}
void ESP8266_STA_TCPClient_Test(void)
{
char str[100]= {0};
TFTLCD_Init();
ESP8266_CH_PD_Pin_SetH;
ESP8266_AT_Test();
ESP8266_Net_Mode_Choose(STA);
while(!ESP8266_JoinAP(User_ESP8266_SSID, User_ESP8266_PWD));
ESP8266_Enable_MultipleId ( DISABLE );
while(!ESP8266_Link_Server(enumTCP, User_ESP8266_TCPServer_IP, User_ESP8266_TCPServer_PORT, Single_ID_0));
while(!ESP8266_UnvarnishSend());
while ( 1 )
{
while(!ESP8266_UnvarnishSend());
if(ESP8266_Fram_Record_Struct .InfBit .FramFinishFlag)
{
USART_ITConfig ( USART2, USART_IT_RXNE, DISABLE );
ESP8266_Fram_Record_Struct .Data_RX_BUF [ ESP8266_Fram_Record_Struct .InfBit .FramLength ] = '\0';
strcpy(str,ESP8266_Fram_Record_Struct .Data_RX_BUF);
LCD_ShowString(10,120,tftlcd_data.width,tftlcd_data.height,24,str+3);
ESP8266_Fram_Record_Struct .InfBit .FramLength = 0;
ESP8266_Fram_Record_Struct .InfBit .FramFinishFlag = 0;
USART_ITConfig ( USART2, USART_IT_RXNE, ENABLE );
}
delay_ms(10);
}
public class Server {
Socket socket;
public static void main(String[] args) {
Server server = new Server();
server.startServer();
}
public void startServer() {
try {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器启动>>> 8080端口");
while (true) {
socket = serverSocket.accept();
if (socket != null) {
Thread thread = new Thread(new Handler(socket));
thread.start();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Handler implements Runnable {
private Socket socket;
private OutputStream outputStream;
private InputStream inputStream;
private BufferedReader reader;
private PrintWriter writer;
private static String WEB_ROOT = "D:\\KEIL IDE";
private static long times = 0;
private String ans = "";
public Handler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"));
String msg = "";
StringBuffer request = new StringBuffer();
if ((msg = reader.readLine()) != null) {
System.out.println(msg);
if (msg.equals("AT+CIPMODE=1") || msg.equals("AT+CIPSTO=1800") || msg.equals("AT+CIPSERVER=1,8080")) {
writer.write("OK\n");
writer.flush();
} else if (msg.equals("AT+CIPSEND")) {
writer.write("OK\n");
writer.flush();
{
FileInputStream fileInputStream = new FileInputStream(new File(WEB_ROOT + "\\main.txt"));
InputStreamReader reader = new InputStreamReader(fileInputStream, "UTF-8");
BufferedReader br = new BufferedReader(reader);
String tmp = br.readLine();
{
writer.write(tmp);
System.out.println(tmp);
writer.flush();
}
}
} else {
FileOutputStream fileOutputStream = new FileOutputStream(new File(WEB_ROOT + "\\main.txt"));
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
bufferedWriter.write(msg);
bufferedWriter.close();
outputStreamWriter.close();
fileOutputStream.close();
writer.write(msg);
writer.flush();
}
}
outputStream.close();
inputStream.close();
reader.close();
socket.close();
System.out.println("---6----");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_send;
private EditText et_send,ip,so;
private RecyclerView recyclerView;
private MainRecyAdapter recyAdapter;
private Toolbar toolbar;
private ArrayList data = new ArrayList<>();
private Socket socket = null;
private String TAG = "main";
@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
String socket = msg.obj.toString();
data.add("服务器说:" + socket);
recyAdapter.notifyDataSetChanged();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init_view();
con_socket();
}
private void init_view() {
btn_send = findViewById(R.id.btn_send);
btn_send.setOnClickListener(this);
et_send = findViewById(R.id.ed_send);
recyclerView = findViewById(R.id.main_recycler);
recyAdapter = new MainRecyAdapter(R.layout.recycle_item, data);
toolbar=findViewById(R.id.toolbar2);
so=toolbar.findViewById(R.id.main_so);
ip=toolbar.findViewById(R.id.main_ip);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(recyAdapter);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_send:
if (socket == null || socket.isClosed()) {
con_socket();
}
final String tmp = et_send.getText().toString();
if (!tmp.isEmpty()) {
new Thread() {
@Override
public void run() {
super.run();
PrintWriter wirter = null;
try {
wirter = new PrintWriter(new OutputStreamWriter(new DataOutputStream(socket.getOutputStream()),"UTF-8"));
wirter.write(tmp);
wirter.flush();
socket.shutdownOutput();
read(socket);
con_socket();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
data.add(tmp);
recyAdapter.notifyDataSetChanged();
Log.e(TAG, "onClick: " + "i am click");
}
break;
default:
break;
}
}
public void con_socket() {
new Thread() {
@Override
public void run() {
super.run();
try {
Log.e(TAG, "run: "+ ip.getText().toString()+Integer.parseInt(so.getText().toString()));
socket = new Socket(ip.getText().toString(),Integer.parseInt(so.getText().toString()));
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
public void read(Socket socket) {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String info = null;
StringBuilder result = new StringBuilder("");
while ((info = br.readLine()) != null) {
result.append(info);
}
Message message=new Message();
message.what=1;
message.obj=result.toString();
handler.sendMessage(message);
br.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MainRecyAdapter extends RecyclerView.Adapter<MainRecyAdapter.ViewHoder>{
private int resourceId;
private ArrayList data;
public MainRecyAdapter(int resourceId, ArrayList list)
{
this.resourceId=resourceId;
data= list;
}
@Override
public ViewHoder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(resourceId, parent, false);
ViewHoder viewHoder=new ViewHoder(view);
return viewHoder;
}
@Override
public void onBindViewHolder(ViewHoder holder, int position) {
holder.textView.setText(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
class ViewHoder extends RecyclerView.ViewHolder {
protected TextView textView;
public ViewHoder(View itemView) {
super(itemView);
textView=itemView.findViewById(R.id.item_text);
}
}
}
说了这么多还有没完善的地方值当单片机一直去询问的时候是开启了多个端口的,这样会导致产生大量的TCP TIME_WAIT,设置的断开时间为3分钟。还有更多的问题欢迎来提出,等考完试继续填坑。!