ESP8266安卓TCP客户端开发
最近在玩8266模块,想让它在局域网控制下开关,所以就搞开发一个安卓客户端调试的工具 直接上步骤:
第一步新建一个空白的Activity
工程名字自己可以改
第二先在AndroidManifest.xml加入网络权限
<uses
-permission android
:name
="android.permission.INTERNET"/>
第三修改界面布局(注意这个布局必须要支持约束布局才能正常使用不然会报错,可以使用AS3.6以上版本):
<?xml version
="1.0" encoding
="utf-8"?>
<androidx
.constraintlayout
.widget
.ConstraintLayout xmlns
:android
="http://schemas.android.com/apk/res/android"
xmlns
:app
="http://schemas.android.com/apk/res-auto"
xmlns
:tools
="http://schemas.android.com/tools"
android
:layout_width
="match_parent"
android
:layout_height
="match_parent"
tools
:context
=".MainActivity">
<Button
android
:id
="@+id/btn_send"
android
:layout_width
="0dp"
android
:layout_height
="wrap_content"
android
:background
="@color/colorPrimary"
android
:text
="@string/c"
android
:textColor
="#F4F2F2"
android
:textSize
="18sp"
app
:layout_constraintBottom_toTopOf
="@+id/guideline2"
app
:layout_constraintEnd_toEndOf
="parent"
app
:layout_constraintHorizontal_bias
="0.0"
app
:layout_constraintStart_toStartOf
="parent"
app
:layout_constraintTop_toTopOf
="@+id/guideline2"
app
:layout_constraintVertical_bias
="0.52" />
<EditText
android
:id
="@+id/et_port"
android
:layout_width
="0dp"
android
:layout_height
="wrap_content"
android
:autofillHints
=""
android
:ems
="10"
android
:hint
="@string/s"
android
:inputType
="number"
app
:layout_constraintBottom_toTopOf
="@+id/guideline3"
app
:layout_constraintEnd_toEndOf
="parent"
app
:layout_constraintHorizontal_bias
="0.81"
app
:layout_constraintStart_toStartOf
="@+id/guideline4"
app
:layout_constraintTop_toTopOf
="@+id/guideline3"
app
:layout_constraintVertical_bias
="0.555" />
<EditText
android
:id
="@+id/et_ip"
android
:layout_width
="0dp"
android
:layout_height
="wrap_content"
android
:autofillHints
=""
android
:ems
="10"
android
:hint
="@string/sip"
android
:inputType
="date"
app
:layout_constraintBottom_toTopOf
="@+id/guideline"
app
:layout_constraintEnd_toEndOf
="parent"
app
:layout_constraintHorizontal_bias
="0.81"
app
:layout_constraintStart_toStartOf
="@+id/guideline4"
app
:layout_constraintTop_toTopOf
="@+id/guideline"
app
:layout_constraintVertical_bias
="0.555" />
<TextView
android
:id
="@+id/textView"
android
:layout_width
="0dp"
android
:layout_height
="wrap_content"
android
:text
="@string/ssip"
android
:textAlignment
="textEnd"
android
:textSize
="18sp"
app
:layout_constraintBottom_toTopOf
="@+id/guideline"
app
:layout_constraintEnd_toStartOf
="@+id/guideline4"
app
:layout_constraintStart_toStartOf
="parent"
app
:layout_constraintTop_toTopOf
="@+id/guideline" />
<TextView
android
:id
="@+id/textView2"
android
:layout_width
="0dp"
android
:layout_height
="wrap_content"
android
:text
="@string/sd"
android
:textAlignment
="textEnd"
android
:textSize
="18sp"
app
:layout_constraintBottom_toTopOf
="@+id/guideline3"
app
:layout_constraintEnd_toStartOf
="@+id/guideline4"
app
:layout_constraintHorizontal_bias
="0.51"
app
:layout_constraintStart_toStartOf
="parent"
app
:layout_constraintTop_toTopOf
="@+id/guideline3"
app
:layout_constraintVertical_bias
="0.526" />
<androidx
.constraintlayout
.widget
.Guideline
android
:id
="@+id/guideline3"
android
:layout_width
="wrap_content"
android
:layout_height
="wrap_content"
android
:orientation
="horizontal"
app
:layout_constraintGuide_percent
="0.3" />
<androidx
.constraintlayout
.widget
.Guideline
android
:id
="@+id/guideline5"
android
:layout_width
="wrap_content"
android
:layout_height
="wrap_content"
android
:orientation
="horizontal"
app
:layout_constraintGuide_percent
="0.6" />
<androidx
.constraintlayout
.widget
.Guideline
android
:id
="@+id/guideline6"
android
:layout_width
="wrap_content"
android
:layout_height
="wrap_content"
android
:orientation
="horizontal"
app
:layout_constraintGuide_percent
="0.9" />
<androidx
.constraintlayout
.widget
.Guideline
android
:id
="@+id/guideline"
android
:layout_width
="wrap_content"
android
:layout_height
="wrap_content"
android
:orientation
="horizontal"
app
:layout_constraintGuide_percent
="0.2" />
<androidx
.constraintlayout
.widget
.Guideline
android
:id
="@+id/guideline2"
android
:layout_width
="wrap_content"
android
:layout_height
="wrap_content"
android
:orientation
="horizontal"
app
:layout_constraintGuide_percent
="0.75" />
<androidx
.constraintlayout
.widget
.Guideline
android
:id
="@+id/guideline4"
android
:layout_width
="wrap_content"
android
:layout_height
="wrap_content"
android
:orientation
="vertical"
app
:layout_constraintGuide_percent
="0.38" />
<androidx
.constraintlayout
.widget
.Guideline
android
:id
="@+id/guideline7"
android
:layout_width
="wrap_content"
android
:layout_height
="wrap_content"
android
:orientation
="vertical"
app
:layout_constraintGuide_percent
="0.5" />
<androidx
.constraintlayout
.widget
.Guideline
android
:id
="@+id/guideline8"
android
:layout_width
="wrap_content"
android
:layout_height
="wrap_content"
android
:orientation
="horizontal"
app
:layout_constraintGuide_percent
="0.45" />
<Button
android
:id
="@+id/btn_link"
android
:layout_width
="0dp"
android
:layout_height
="wrap_content"
android
:background
="#16E6CE"
android
:text
="@string/contenct"
android
:textColor
="#F4EFEF"
android
:textSize
="18sp"
app
:layout_constraintBottom_toTopOf
="@+id/guideline8"
app
:layout_constraintEnd_toEndOf
="parent"
app
:layout_constraintHorizontal_bias
="0.0"
app
:layout_constraintStart_toStartOf
="parent"
app
:layout_constraintTop_toTopOf
="@+id/guideline8" />
<EditText
android
:id
="@+id/et_data"
android
:layout_width
="255dp"
android
:layout_height
="48dp"
android
:autofillHints
=""
android
:ems
="10"
android
:hint
="@string/plesdata"
android
:inputType
="date|text"
app
:layout_constraintBottom_toTopOf
="@+id/guideline5"
app
:layout_constraintEnd_toEndOf
="parent"
app
:layout_constraintHorizontal_bias
="1.0"
app
:layout_constraintStart_toStartOf
="parent"
app
:layout_constraintTop_toTopOf
="@+id/guideline5"
app
:layout_constraintVertical_bias
="0.446"
tools
:ignore
="LabelFor" />
<TextView
android
:id
="@+id/tv_sendata"
android
:layout_width
="0dp"
android
:layout_height
="wrap_content"
android
:text
="@string/senddata"
android
:textAlignment
="textEnd"
android
:textSize
="18sp"
app
:layout_constraintBottom_toTopOf
="@+id/guideline5"
app
:layout_constraintEnd_toStartOf
="@+id/guideline4"
app
:layout_constraintStart_toStartOf
="parent"
app
:layout_constraintTop_toTopOf
="@+id/guideline5" />
<TextView
android
:id
="@+id/textView4"
android
:layout_width
="wrap_content"
android
:layout_height
="wrap_content"
android
:text
="@string/tcp"
app
:layout_constraintBottom_toTopOf
="@+id/guideline6"
app
:layout_constraintEnd_toEndOf
="parent"
app
:layout_constraintStart_toStartOf
="parent"
app
:layout_constraintTop_toTopOf
="@+id/guideline6" />
</androidx
.constraintlayout
.widget
.ConstraintLayout
>
第四新建SendAsyncTask.java文件
package com
.kizai
.projects
.esp8266
;
import android
.os
.AsyncTask
;
import java
.io
.IOException
;
import java
.io
.PrintStream
;
import java
.net
.Socket
;
import static com
.kizai
.projects
.esp8266
.MainActivity
.ip
;
import static com
.kizai
.projects
.esp8266
.MainActivity
.port
;
public class SendAsyncTask extends AsyncTask<String, Void, Void> {
private static final String IP
= ip
;
private static final int PORT
= port
;
@Override
protected Void
doInBackground(String
... params
) {
String str
= params
[0];
try {
Socket client
= new Socket(IP
, PORT
);
client
.setSoTimeout(5000);
PrintStream out
= new PrintStream(client
.getOutputStream());
out
.print(str
);
out
.flush();
out
.close();
client
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
return null
;
}
}
第五回到主活动代码MainActivity.java:
package com
.kizai
.projects
.esp8266
;
import androidx
.appcompat
.app
.AppCompatActivity
;
import android
.annotation
.SuppressLint
;
import android
.os
.Bundle
;
import android
.os
.Handler
;
import android
.os
.Message
;
import android
.view
.View
;
import android
.widget
.Button
;
import android
.widget
.EditText
;
import android
.widget
.Toast
;
import java
.net
.Socket
;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static String ip
, pport
, sendData
;
public static int port
;
private EditText et_ip
, et_port
, et_data
;
@Override
protected void onCreate(Bundle savedInstanceState
) {
super.onCreate(savedInstanceState
);
setContentView(R
.layout
.activity_main
);
initView();
}
private void initView() {
Button btn_send
= findViewById(R
.id
.btn_send
);
Button btn_link
= findViewById(R
.id
.btn_link
);
et_ip
= findViewById(R
.id
.et_ip
);
et_port
= findViewById(R
.id
.et_port
);
et_data
= findViewById(R
.id
.et_data
);
btn_send
.setOnClickListener(this);
btn_link
.setOnClickListener(this);
}
@Override
public void onClick(View v
) {
switch (v
.getId()) {
case R
.id
.btn_link
:
if (et_port
.length() != 0 && et_ip
.length() != 0) {
ip
= et_ip
.getText().toString().trim();
pport
= et_port
.getText().toString().trim();
port
= Integer
.parseInt(pport
);
String str
= "o\n";
new SendAsyncTask().execute(str
);
Toast
.makeText(getApplicationContext(), "如果看到ESP8266的灯闪烁两次就代表连接成功!", Toast
.LENGTH_SHORT
).show();
} else {
Toast
.makeText(getApplicationContext(), "请输入正确的ip和端口号!", Toast
.LENGTH_SHORT
).show();
}
break;
case R
.id
.btn_send
:
sendData
= et_data
.getText().toString().trim();
if (!sendData
.isEmpty()) {
new SendAsyncTask().execute(sendData
);
} else {
Toast
.makeText(getApplicationContext(), "请输入数据!", Toast
.LENGTH_SHORT
).show();
}
break;
}
}
}
第六ESP8266 TCPServer服务端代码:
#include <ESP8266WiFi.h>
#define MAX_SRV_CLIENTS 2
#define DebugBegin(baud_rate) Serial.begin(baud_rate)
#define DebugPrintln(message) Serial.println(message)
#define DebugPrint(message) Serial.print(message)
const char* ssid
= "KIZAI-HOME";
const char* password
= "700800900";
WiFiServer
server(23);
WiFiClient serverClients
[MAX_SRV_CLIENTS
];
void setup() {
DebugBegin(115200);
pinMode(LED_BUILTIN
, OUTPUT
);
digitalWrite(LED_BUILTIN
, HIGH
);
WiFi
.mode(WIFI_STA
);
WiFi
.begin(ssid
, password
);
DebugPrint("\nConnecting to ");
DebugPrintln(ssid
);
uint8_t i
= 0;
while (WiFi
.status() != WL_CONNECTED
&& i
++ < 20) {
delay(500);
}
if (i
== 21) {
DebugPrint("Could not connect to");
DebugPrintln(ssid
);
while (1) {
delay(500);
}
}
server
.begin();
server
.setNoDelay(true
);
DebugPrint("Ready! Use 'telnet ");
DebugPrint(WiFi
.localIP());
DebugPrintln(" 23' to connect");
}
void loop() {
uint8_t i
;
if (server
.hasClient()) {
for (i
= 0; i
< MAX_SRV_CLIENTS
; i
++) {
if (!serverClients
[i
] || !serverClients
[i
].connected()) {
if (serverClients
[i
]) {
serverClients
[i
].stop();
}
serverClients
[i
] = server
.available();
DebugPrint("New client: ");
DebugPrint(i
);
break;
}
}
if (i
== MAX_SRV_CLIENTS
) {
WiFiClient serverClient
= server
.available();
serverClient
.stop();
DebugPrintln("Connection rejected ");
}
}
for (i
= 0; i
< MAX_SRV_CLIENTS
; i
++) {
if (serverClients
[i
] && serverClients
[i
].connected()) {
if (serverClients
[i
].available()) {
while (serverClients
[i
].available()) {
char data
= serverClients
[i
].read();
Serial
.print(data
);
switch(data
){
case 'o':
digitalWrite(LED_BUILTIN
, LOW
);
delay(100);
digitalWrite(LED_BUILTIN
, HIGH
);
delay(100);
digitalWrite(LED_BUILTIN
, LOW
);
delay(100);
digitalWrite(LED_BUILTIN
, HIGH
);
delay(100);
digitalWrite(LED_BUILTIN
, LOW
);
break;
}
}
}
}
}
if (Serial
.available()) {
size_t len
= Serial
.available();
uint8_t sbuf
[len
];
Serial
.readBytes(sbuf
, len
);
for (i
= 0; i
< MAX_SRV_CLIENTS
; i
++) {
if (serverClients
[i
] && serverClients
[i
].connected()) {
serverClients
[i
].write(sbuf
, len
);
delay(1);
}
}
}
}
void blink()
{
static long previousMillis
= 0;
static int currstate
= 0;
if (millis() - previousMillis
> 200)
{
previousMillis
= millis();
currstate
= 1 - currstate
;
digitalWrite(LED_BUILTIN
, currstate
);
}
}
8266端口监视器:
第七现在运行软件(真机和虚拟机都可以实现连接:前提是连接在统一个局域网里面)
也可以看到串口监视器会有反应:New client:0o 测试发送数据: 看到串口监视器都是可以接收到数据的 希望这篇文章对你有所帮助,觉得还可以点赞收藏喔!也还可以点个关注,你们的支持是对我最大的鼓励!!!