做一个简单的“远程”开关 ESP8266 + APP

简单的远程开关制作(纯代码、无解析版、UDP通信)

引言

  本篇文章,我们将做一个超级简单的开关,当你学会该操作后,就可以自己进行一些简单的添加、修改从而实现一些自定义的功能。你可以做一个简单的远程开关,或驱动小车,以及众多有意思的玩意,现在就来跟着我一起学习吧!当然了,请注意我们这里的“远程”是打引号的,因为我们是用局域网通过UDP协议进行数据传输的,因此我们必须保证设备与客户端在同一局域网下才可进行以下实验。

文章干货满满,不讲废话,点赞收藏不迷路~

介绍

    如果你有想在床上不用下床就把灯关了,把窗帘打开,或者自制一个机器人的话,那么本教程将是你入门的不二之选。我们采用了开销较小的UDP协议进行传输数据,同时也降低了传输的延时,从而使你能够在进行一些需要高精度的机械设计时减少误差。我们的8266与手机在接入到同一站点后,即可进行UDP通信进行指令的传输了。我们暂且称8266为服务端,移动端为客户端,我们在服务端进行数据的接收与回传,同时对硬件设备进行相应的控制,在客户端主要进行就是控制指令的设计,并向服务端进行数据发送与接收。具体的相关信息,我们将在后续的教程中更新!请及时关注。

准备工作

硬件

  • 一颗ESP8266 某宝很便宜,十几块钱就有,这里就不推荐了,直接去搜就可以。
    在这里插入图片描述
  • 一个单路继电器开关。
    在这里插入图片描述
  • 公母头杜邦线、公头杜邦线、母头杜邦线等。
    在这里插入图片描述
  • 一台安卓手机。
    在这里插入图片描述
  • 如有进行其他改造想法的可自行采购相关硬件。

软件

安卓工程文件

代码部分

    8266代码

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char *ssid = "esp8266";     //网络名称
const char *password = "asd123456"; //网络密码

WiFiUDP Udp;
unsigned int localUdpPort = 2333; // 本地端口号
char incomingPacket[537];         // 接收缓冲区

void setup()
{
  //以下为基本功能初始化,初始化串口和网络和LED
  pinMode(2, OUTPUT);
  Serial.begin(115200);
  Serial.println();
  WiFi.softAP(ssid,password);
  Serial.print("Access Point: ");    // 通过串口监视器输出信息
  Serial.println(ssid);              // 告知用户NodeMCU所建立的WiFi名
  Serial.print("IP address: ");      // 以及NodeMCU的IP地址
  Serial.println(WiFi.softAPIP());   // 通过调用WiFi.softAPIP()可以得到NodeMCU的IP地址
  
  //以下开启UDP监听并打印输出信息
  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}

void loop()
{
  int packetSize = Udp.parsePacket(); //获取当前队首数据包长度
  Serial.print(packetSize);
  delay(2000); //这里做了延时处理 如果你觉得慢可以注释掉
  if (packetSize)                     // 有数据可用
  {
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(incomingPacket, 536); // 读取数据到incomingPacket
    if (len > 0)                             // 如果正确读取
    {
      incomingPacket[len] = 0; //末尾补0结束字符串
      Serial.printf("UDP packet contents: %s\n", incomingPacket);

      if (strcmp(incomingPacket, "Turn off") == 0) // 如果收到Turn off
      {
        digitalWrite(2, HIGH); // 关闭Switch 
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
        Udp.write("Switch has been turn off"); // 回复Switch has been turn off
        Udp.endPacket();
      }
      else if (strcmp(incomingPacket, "Turn on") == 0) // 如果收到Turn on
      {
        digitalWrite(2, LOW); // 打开Switch 
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
        Udp.write("Switch has been turn on"); // 回复Switch has been turn on
        Udp.endPacket();
      }
      else // 如果非指定消息
      {
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
        Udp.write("Data Error!"); // 回复Data Error!
        Udp.endPacket();
      }
    }
  }
}

APP代码
    MainActivity

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;


public class MainActivity extends Activity {
    TextView textView;
    String recvStr = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.status);

        new Thread(){
            @Override
            public void run(){
                try {
                    DatagramSocket ds = new DatagramSocket();
                    byte[] bytes = "Get status".getBytes();
                    int length = bytes.length;
                    InetAddress address = InetAddress.getByName("192.168.4.1");
                    int port = 2333;
                    DatagramPacket dp = new DatagramPacket(bytes,length,address,port);
                    ds.send(dp);
//                    接收消息
                    byte[] recvBuf = new byte[100];
                    DatagramPacket recvPacket
                            = new DatagramPacket(recvBuf , recvBuf.length);
                    ds.receive(recvPacket);
                    recvStr = new String(recvPacket.getData() , 0 ,recvPacket.getLength());
                    if(recvStr.equalsIgnoreCase("3")){
                        textView.setText("开");
                    }else if(recvStr.equalsIgnoreCase("4")){
                        textView.setText("关");
                    }else{
                        ;
                    }
                    ds.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }.start();

    }


    public void turnOn(View view) throws IOException {
        new Thread(){
            @Override
            public void run(){
                try {
                    DatagramSocket ds = new DatagramSocket();
                    byte[] bytes = "Turn on".getBytes();
                    int length = bytes.length;
                    InetAddress address = InetAddress.getByName("192.168.4.1");
                    int port = 2333;
                    DatagramPacket dp = new DatagramPacket(bytes,length,address,port);
                    ds.send(dp);
                    ds.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }.start();
        textView.setText("开");
    }

    public void turnOff(View view) throws IOException {
        new Thread(){
            @Override
            public void run() {
                try {
                    DatagramSocket ds = new DatagramSocket();
                    byte[] bytes = "Turn off".getBytes();
                    int length = bytes.length;
                    InetAddress address = InetAddress.getByName("192.168.4.1");
                    int port = 2333;
                    DatagramPacket dp = new DatagramPacket(bytes,length,address,port);
                    ds.send(dp);
                    ds.close();
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        textView.setText("关");
    }
}

     样式代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/teal_700"
        app:title="ESP8266_UDP_Test_Pro"
        app:titleTextColor="@color/white"
        app:titleMarginStart="100dp"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <EditText
            android:id="@+id/et1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:cursorVisible="false"
            android:editable="false"
            android:ems="10"
            android:textSize="20dp"
            android:layout_marginBottom="10dp"
            android:text="控制开关按钮"
            android:gravity="center">
        </EditText>


    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="10dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="当前状态:"
            android:textSize="26dp"
            android:textColor="@color/black"/>
        <TextView
            android:id="@+id/status"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="未知"
            android:textSize="26dp"
            android:paddingLeft="20dp"
            android:textColor="@color/teal_700"/>

    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="30dp"
            android:onClick="turnOn"
            android:text="打开" />
        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="turnOff"
            android:text="关闭" />

    </LinearLayout>


</LinearLayout>

Tip

  可能你无法直接将代码直接运行上手进行的实验,或者不知道如何进行试验,又或者遇到了各种各样的问题,这是因为你还没有具备一些必要的知识,你可以在评论区发表你的疑问,为防止文章篇幅过长不易观看,我在另一篇文章里进行了详细的介绍。
后期将会更新教程!
后期将会更新教程!
后期将会更新教程!


分割线来了!快一年了才来更新~~~真是抱歉!其实现在也没多少时间,但怕越往后越忘完了索性大概讲一下需要更改的地方就行,后边如果有机会的话再详细讲一下

  正文开始。首先你需要有两个工程文件,一个是Arduino的一个工程文件,这个工程文件你自己创建即可(可能需要ESP8266的一些库,可以自己下去搜一下,由于时间太久了我也忘了需要哪些库了~),创建好文件之后直接把我上边的代码内容粘贴进去即可。注意,还不要直接运行,这里有需要修改的信息,就是ssid网络名称,后边的字符串内容改成你自己的WiFi热点名称,password是网络密码,改成你设置的密码,注意,最好用手机开热点,不要连路由WiFi(理论上路由WiFi也没问题),还有一个端口号需要注意,即localUdpPort,这里的端口号要与安卓工程文件中的端口号相一致,不要动这个端口号,因为我已经在安卓工程文件中设置好了端口号,这两个端口号必须相一致,一旦改了其中任何一个都无法接收到对方发送的数据,到这里你就可以点击运行将代码烧录进ESP8266了。
  安卓工程文件请翻到上面,直接下载(前提你的电脑已经下好了Android Studio),然后打开该文件,可以在虚拟机上进行运行,也可以直接将该文件进行打包成apk安装到你的手机上,然后用手机开热点,注意要与你在Arduino设置的名称密码相一致,否则ESP8266连接不上。然后你就可以打开该软件进行操作了。


 需要提醒的是,软件并没有多少异常处理,比如你点了开,但实际上ESP8266根本没连上WiFi,这时也会显示开,也就是没有数据反馈处理,当然如果已经连上的话就没什么问题了。
好了,终于把这篇文章差不多彻底结束了,希望对各位小伙伴有帮助!

如果这篇文章对您有帮助的话,不妨点个赞吧~

  • 7
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
### 回答1: AppESP8266远程通信可以通过以下步骤实现: 首先,ESP8266需要连接到一个与网络连接的路由器。ESP8266通过Wi-Fi模块连接到路由器,获取网络访问权限。 其次,App需要在手机上安装一个支持远程通信的应用程序。这个应用程序可以通过手机的Wi-Fi连接到与ESP8266相同的路由器。 然后,ESP8266需要有一个固定的IP地址,以便App能够找到它。可以通过在路由器中将ESP8266的MAC地址与一个固定的IP地址进行绑定,确保每次连接时ESP8266都能获得相同的IP地址。 接下来,在App中设置一个ESP8266相同的IP地址和端口号。这样,App就可以通过相同的IP地址和端口号与ESP8266建立通信连接。 一旦连接建立,App可以通过向ESP8266发送命令来控制它。这些命令可以是开关操作、传感器数据读取等。 ESP8266接收到App发送的命令后,可以执行相应的操作。例如,如果命令是开关操作,ESP8266可以通过控制继电器或其他设备来实现开关远程控制。 最后,ESP8266可以将执行结果或传感器数据通过Wi-Fi返回给AppApp可以根据需要对这些数据进行处理和显示。 综上所述,AppESP8266远程通信是通过在同一局域网中建立连接,并通过发送命令和接收数据来实现的。这种通信方式可以实现对ESP8266远程控制和数据传输。 ### 回答2: appesp8266远程通信,可以通过以下步骤实现。 首先,确保你的esp8266模块已正确连接到Wi-Fi网络,并且已安装好必要的库和开发环境。接着,需要编写一个基于Arduino或其他适合的开发平台的程序,在ESP8266上运行。 在这个程序中,你可以使用TCP/IP协议与app进行通信。ESP8266可以作为服务器或客户端,具体取决于你的应用场景。如果你选择将其设置为服务器,可以通过监听一个特定的端口,等待app的请求。 在app方面,你需要根据你所用的开发框架,编写与ESP8266通信的代码。你可以使用Socket编程或HTTP请求等方式来与ESP8266进行交互。需要注意的是,在与ESP8266通信时,你需要发送和接收一定的指令和数据,以确保正常的通信。 对于数据的传输,你可以使用JSON等格式,将需要传输的数据进行封装和解析,以便在appESP8266之间进行数据交换。 当app发送请求到ESP8266时,ESP8266可以根据请求进行相应的处理,并向app返回所需的数据或执行相应的操作。 要实现远程通信,确保ESP8266app之间的网络连接是可靠和稳定的非常重要。在实践中可能会遇到一些网络相关的问题,例如丢包、延迟等,需要适当地处理和调试。 总而言之,通过上述步骤,你就可以实现appESP8266之间的远程通信。这样,你可以使用app控制和监控ESP8266,实现一些智能化的远程控制应用。 ### 回答3: AppESP8266远程通信的过程可以分为以下几步: 1. 在ESP8266上搭建Web服务器:通过编程将ESP8266设置为一个Web服务器,以便能够接收来自App的请求和发送数据给App。这个服务器可以使用ESP8266的WiFi模块与App进行通信。 2. 连接AppESP8266:在App中,使用WiFi模块与ESP8266建立连接。这需要提供ESP8266的IP地址和端口号。一旦连接成功,App就可以通过与ESP8266建立的连接发送请求和接收响应。 3. 定义通信协议:为了使AppESP8266能够相互理解,需要定义一种通信协议。这个协议可以规定请求和响应的格式,例如使用JSON或XML。 4. 发送请求和接收响应:App可以通过发送HTTP请求给ESP8266来请求获取传感器数据、执行某些操作等。ESP8266接收到请求后,根据请求的内容进行处理,并将响应发送给AppApp收到响应后,可以根据协议解析得到的数据,并进行相应的操作或显示。 需要注意的是,在远程通信中,确保ESP8266App都在同一网络环境下,以便能够通过WiFi相互连接。同时,也要确保ESP8266的Web服务器运行正常,并且AppESP8266代码都正确配置和编写。 总的来说,通过在ESP8266上搭建Web服务器,连接AppESP8266,定义通信协议,发送请求和接收响应,可以实现AppESP8266远程通信。这种通信方式在物联网和智能家居等领域具有广泛的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值