精华内容
下载资源
问答
  • 内含配置模块详细说明,另附有手机APP
  • eclipse安卓开发环境下,开发一个安卓APP与wifi模块连接,并通过此wifi模块与PC机实现双向通信。求大神指点。
  • 本身要实现一个简单的物联网App,硬件设备开启局域网wifi手机连接WIFI后进行TCP通信,但就这么简单的应用却遇到坑了,在这里记录一下; 2.问题 在测试硬件设备串口WIFI功能时遇到了奇怪的现象,在上图中设备以AP...

    1.背景

    在这里插入图片描述

    本身要实现一个简单的物联网App,硬件设备开启局域网wifi,手机连接WIFI后进行TCP通信,但就这么简单的应用却遇到坑了,在这里记录一下;

    2.问题

    在这里插入图片描述
    在测试硬件设备串口WIFI功能时遇到了奇怪的现象,在上图中设备以AP模式开启Wifi,客户端设备断开其他网络通道(手机关闭数据流量、PC拔掉网线)后连接此wifi,结果除PC端连接正常外,移动设备(ios与Android)都出现了TCP连接失败,ios端可以ping通192.168.8.0;

    查看Socket连接报错日志如下:

    java.net.ConnectException: failed to connect to /192.168.8.0 (port 8080) from /:: (port 0): connect failed: ENETUNREACH (Network is unreachable)
    	at libcore.io.IoBridge.connect(IoBridge.java:143)
    	at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
    	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
    	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
    	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
    	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
    	at java.net.Socket.connect(Socket.java:621)
    	at java.net.Socket.connect(Socket.java:570)
    	at java.net.Socket.<init>(Socket.java:450)
    	at java.net.Socket.<init>(Socket.java:218)
    	at top.luchenxi.lgrswifitest.TcpClient.run(TcpClient.java:60)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    	at java.lang.Thread.run(Thread.java:919)
    Caused by: android.system.ErrnoException: connect failed: ENETUNREACH (Network is unreachable)
    	at libcore.io.Linux.connect(Native Method)
    	at libcore.io.ForwardingOs.connect(ForwardingOs.java:95)
    	at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:136)
    	at libcore.io.ForwardingOs.connect(ForwardingOs.java:95)
    	at libcore.io.IoBridge.connectErrno(IoBridge.java:157)
    	at libcore.io.IoBridge.connect(IoBridge.java:135)
    	... 13 more
    

    connect failed: ENETUNREACH (Network is unreachable),而并非是 ETIMEDOUT

    尝试在以上连接下,局域网内各客户端进行通信,出现如下情况:

    在这里插入图片描述
    由于对网络知识的匮乏,经过好几天的无脑尝试(更换测试工具、更换测试手机品牌、客户端配置固定IP、配置网关、配置DNS、联系串口wifi供应商等),最后尝试修改设备串口wifi模块服务IP后,居然…神奇的解决了!!!!!!

    改动如下:

    将服务器IP:192.168.8.0 修改为 192.168.8.1

    在这里插入图片描述

    3.原因

    大概原因为192.168.8.0/24 与 192.168.8.255/24这个两个地址比较特殊,百度上有种说法是一个为域地址一个为广播地址,这两个地址并不在192.168.8.0/24这个网段中。

    但是如果不在一个网段中,为什么PC端能够连接呢?

    有大佬指导原因的话麻烦指导下!!不胜感激!!

    展开全文
  • 2.功能:APP通过tcp/ip协议单片机(配置好ESP8266WiFi模块的单片机)进行通信,也就是说,APP可以通过tcp/ip协议控制单片机去开关灯或者调节灯的亮度。只要APP所在手机和单片机是在同一个局域网里,即可实现控制。...

    1.项目:物联网的一个实践项目-----智能台灯安卓APP

    2.功能:APP通过tcp/ip协议与单片机(配置好ESP8266WiFi模块的单片机)进行通信,也就是说,APP可以通过tcp/ip协议控制单片机去开关灯或者调节灯的亮度。只要APP所在手机和单片机是在同一个局域网里,即可实现控制。

    3.软件效果:

    在这里插入图片描述
    硬件效果与上图类似。

    4.APP代码实现:

    (1)HomeActivity.java

    public class HomeActivity extends AppCompatActivity{
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_home);
        }
    }
    

    (2)activity_home.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.myclient.HomeActivity">
    
     <fragment
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:id="@+id/home"
         android:name="com.example.myclient.TestFragment"/>
    
    </RelativeLayout>
    

    (3)TestFragment.java

    public class TestFragment extends Fragment {
        private Button startButton;
        private EditText IPText;
        private Context mContext;
        private   boolean isConnecting=false;
        private Thread mThreadClient=null;
        private Socket mSocketClient=null;
        private static BufferedReader mBufferedReaderClient=null;
        private static PrintWriter mPrintWriterClient=null;
        private  String res="";
        private static TextView recvText,recvText1,recvText2;
        private ImageView imageView;
        private TempControlView tempControl;
        @SuppressLint("SetTextI18n")
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // TODO Auto-generated method stub
    
            View view = inflater.inflate(R.layout.fragment_test, null);
            mContext=getContext();
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectNetwork()
                    .penaltyLog()
                    .build()
            );
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                    .detectLeakedSqlLiteObjects()
                    .penaltyLog()
                    .penaltyDeath()
                    .build());
    
            IPText= view.findViewById(R.id.IPText);
         //  IPText.setText("10.10.10.11:8080");
            IPText.setText("192.168.1.127:8080");
            startButton= view.findViewById(R.id.StartConnect);
            startButton.setOnClickListener(StartClickListener);
    
            recvText= view.findViewById(R.id.tv1);
            recvText1= view.findViewById(R.id.textView3);
            recvText2= view.findViewById(R.id.textView4);
            imageView=view.findViewById(R.id.light);
    
            tempControl = view.findViewById(R.id.temp_control);
            // 设置三格代表温度1度
            tempControl.setAngleRate(1);
            tempControl.setTemp(0, 5, 0);
            //设置旋钮是否可旋转
            tempControl.setCanRotate(true);
            tempControl.setOnTempChangeListener(new TempControlView.OnTempChangeListener() {
                @Override
                public void change(int temp) {
                    switch (temp){
                        case 0:
                            if ( send("*C")){
                                imageView.setImageResource(R.drawable.light1);
                            }
                            break;
                        case 1:
                            if ( send("*1")){
                                imageView.setImageResource(R.drawable.light2);
                            }
                            break;
                        case 2:
                            if ( send("*2")){
                                imageView.setImageResource(R.drawable.light3);
                            }
                            break;
                        case 3:
                            if ( send("*3")){
                                imageView.setImageResource(R.drawable.light4);
                            }
                            break;
                        case 4:
                            if ( send("*4")){
                                imageView.setImageResource(R.drawable.light5);
                            }
                            break;
                        case 5:
                            if ( send("*5")){
                                imageView.setImageResource(R.drawable.light6);
                            }
                            break;
                    }
                }
            });
    
            tempControl.setOnClickListener(new TempControlView.OnClickListener() {
                @Override
                public void onClick(int temp) {
                    switch (temp){
                        case 0:
                            if ( send("*C")){
                                imageView.setImageResource(R.drawable.light1);
                            }
                            break;
                        case 1:
                            if ( send("*1")){
                                imageView.setImageResource(R.drawable.light2);
                            }
                            break;
                        case 2:
                            if ( send("*2")){
                                imageView.setImageResource(R.drawable.light3);
                            }
                            break;
                        case 3:
                            if ( send("*3")){
                                imageView.setImageResource(R.drawable.light4);
                            }
                            break;
                        case 4:
                            if ( send("*4")){
                                imageView.setImageResource(R.drawable.light5);
                            }
                            break;
                        case 5:
                            if ( send("*5")){
                                imageView.setImageResource(R.drawable.light6);
                            }
                            break;
                    }
                }
            });
            return view;
        }
    
        //连接到智能衣柜
        private View.OnClickListener StartClickListener = new View.OnClickListener() {
    
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                if(isConnecting)
                {
                    isConnecting=false;
                    if(mSocketClient!=null)
                    {
                        try{
                            mSocketClient.close();
                            mSocketClient = null;
                            if (mPrintWriterClient!=null){
                                mPrintWriterClient.close();
                                mPrintWriterClient = null;
                            }
                            mThreadClient.interrupt();
                            startButton.setText("开始连接");
                            IPText.setEnabled(true);//可以输入ip和端口号
                            recvText.setText("断开连接\n");
                            imageView.setImageResource(R.drawable.light1);
    
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }else
                {
                    mThreadClient = new Thread(mRunnable);
                    mThreadClient.start();
                }
            }
        };
    
        private Runnable mRunnable = new Runnable() {
    
            @Override
            public void run() {
                String msgText = IPText.getText().toString();
                if(msgText.length()<=0)
                {
                    Message msg = new Message();
                    msg.what = 5;
                    mHandler.sendMessage(msg);
                    return;
                }
                int start = msgText.indexOf(":");
                if((start==-1)||(start+1>=msgText.length()))
                {
                    Message msg = new Message();
                    msg.what = 6;
                    mHandler.sendMessage(msg);
                    return;
                }
                String sIP= msgText.substring(0,start);
                String sPort = msgText.substring(start+1);
                int port = Integer.parseInt(sPort);
    
                try
                {
                    //连接服务器
                    mSocketClient = new Socket();
                    SocketAddress socAddress = new InetSocketAddress(sIP, port);
                    mSocketClient.connect(socAddress, 2000);//设置超时时间为2秒
                    //取得输入、输出流
                    mBufferedReaderClient=new BufferedReader(new InputStreamReader(mSocketClient.getInputStream()));
                    mPrintWriterClient=new PrintWriter(mSocketClient.getOutputStream(),true);
                    Message msg = new Message();
                    msg.what = 1;
                    mHandler.sendMessage(msg);
    
                }catch (Exception e) {
                    Message msg = new Message();
                    msg.what = 2;
                    mHandler.sendMessage(msg);
                    return;
                }
                char[] buffer = new char[256];
                int count = 0;
    
                while(true)
                {
                    try
                    {
                        if((count = mBufferedReaderClient.read(buffer))>0)
                        {
                            res = getInfoBuff(buffer,count)+"\n";
                            Message msg = new Message();
                            msg.what = 4;
                            mHandler.sendMessage(msg);
                        }
                    }catch (Exception e) {
                        // TODO: handle exception
                        Message msg = new Message();
                        msg.what = 3;
                        mHandler.sendMessage(msg);
                    }
                }
            }
        };
    
        @SuppressLint("HandlerLeak")
        Handler mHandler = new Handler()
        {
            @SuppressLint("SetTextI18n")
            public void handleMessage(Message msg)
            {
                super.handleMessage(msg);
                if(msg.what==4)
                {
                    char []arrs=null;
                    arrs=res.toCharArray();//接收来自服务器的字符串
                    if (arrs.length>=9) {
                        recvText1.setText("温度: " + arrs[2] + arrs[3] + "℃" + ' ');
                        recvText2.setText("湿度: " + arrs[7] + arrs[8] + "%" + ' ');
                    }else {
                        showDialog("收到格式错误的数据");
                    }
    
    //                if (arrs[0]=='T'){
    //                    recvText1.setText("温度: "+arrs[3] + arrs[4] + "℃" + ' ' );
    //                }else if (arrs[0]=='R'){
    //                    recvText2.setText("湿度: "+arrs[3] + arrs[4] + "%" + ' ' );
    //                }
                }else if (msg.what==2){
                    showDialog("连接失败,服务器走丢了");
                    startButton.setText("开始连接");
    
                }else if (msg.what==1){
                    showDialog("连接成功!");
                    recvText.setText("已连接台灯\n");
                    IPText.setEnabled(false);//锁定ip地址和端口号
                    isConnecting = true;
                    startButton.setText("停止连接");
                }else if (msg.what==3){
                  //  recvText.setText("连接已断开\n");
                }else if (msg.what==5){
                    recvText.setText("IP和端口号不能为空\n");
                }
                else if (msg.what==6){
                    recvText.setText("IP地址不合法\n");
                }
            }
        };
        private  void showDialog(String msg) {
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            builder.setIcon(android.R.drawable.ic_dialog_info);
            builder.setTitle(msg);
            builder.setCancelable(false);
            builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
    
                }
            });
            builder.create().show();
        }
        private String getInfoBuff(char[] buff,int count)
        {
            char[] temp = new char[count];
            for (int i = 0; i < count; i++) {
                temp[i]=buff[i];
            }
            return new String(temp);
        }
        private boolean send(String msg){
            if(isConnecting&&mSocketClient!=null)
                    {
                        String msgText =msg;//发送给单片机的某个命令
                        try
                        {
                            mPrintWriterClient.print(msgText);
                            mPrintWriterClient.flush();
                            return true;
                        }catch (Exception e) {
                            // TODO: handle exception
                            Toast.makeText(mContext, "发送异常"+e.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    }else
                    {
                        showDialog("没有连接!");
                        return false;
                    }
            return false;
        }
    
    }
    

    (4)fragment_test.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/background"
        android:orientation="vertical"
        tools:context=".HomeActivity" >
    
    
        <LinearLayout
            android:layout_marginTop="10dp"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical"
            >
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <EditText
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="5dp"
                    android:layout_gravity="center"
                    android:layout_weight="1"
                    android:background="#CFCACA"
                    android:id="@+id/IPText"
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    android:ems="10"
                    android:textSize="20dp"
                    android:hint="请输入衣柜服务端的IP地址" />
    
                <Button
                    android:layout_marginRight="10dp"
                    android:layout_weight="2"
                    android:id="@+id/StartConnect"
                    android:background="#C3C7DA"
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    android:textSize="20dp"
                    android:text="连接台灯" />
            </LinearLayout>
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
    
                <TextView
                    android:id="@+id/tv1"
                    android:layout_marginTop="10dp"
                    android:layout_marginLeft="20dp"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textColor="#ffffff"
                    android:text="欢迎使用智能台灯!"
                    android:textSize="20dp" />
            </RelativeLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <com.example.myclient.TempControlView
            android:id="@+id/temp_control"
            android:layout_width="250dp"
            android:layout_height="250dp"
            />
        <ImageView
            android:layout_marginLeft="20dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/light"
            android:src="@drawable/light1"/>
    </LinearLayout>
            <LinearLayout
                android:layout_marginLeft="10dp"
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
               >
                <TextView
                    android:layout_weight="1"
                    android:textSize="25sp"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textColor="#810303"
                    android:text="温度:0℃"
                    android:id="@+id/textView3" />
    
                <TextView
                    android:layout_weight="1"
                    android:textSize="25sp"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="湿度:0%"
                    android:textColor="#810303"
                    android:id="@+id/textView4" />
            </LinearLayout>
    
        </LinearLayout>
    </RelativeLayout>
    

    (5)TempControlView.java

    public class TempControlView extends View {
    
        // 控件宽
        private int width;
        // 控件高
        private int height;
        // 刻度盘半径
        private int dialRadius;
        // 圆弧半径
        private int arcRadius;
        // 刻度高
        private int scaleHeight = dp2px(10);
        // 刻度盘画笔
        private Paint dialPaint;
        // 圆弧画笔
        private Paint arcPaint;
        // 标题画笔
        private Paint titlePaint;
        // 温度标识画笔
        private Paint tempFlagPaint;
        // 旋转按钮画笔
        private Paint buttonPaint;
        // 温度显示画笔
        private Paint tempPaint;
        // 文本提示
        private String title = "档数调节";
        // 温度
        private int temperature = 15;
        // 最低温度
        private int minTemp = 15;
        // 最高温度
        private int maxTemp = 5;
        // 四格代表温度1度
        private int angleRate = 4;
        // 每格的角度
        private float angleOne = (float) 270 / (maxTemp - minTemp) / angleRate;
        // 按钮图片
        private Bitmap buttonImage = BitmapFactory.decodeResource(getResources(),
                R.mipmap.btn_rotate);
        // 按钮图片阴影
        private Bitmap buttonImageShadow = BitmapFactory.decodeResource(getResources(),
                R.mipmap.btn_rotate_shadow);
        // 抗锯齿
        private PaintFlagsDrawFilter paintFlagsDrawFilter;
        // 温度改变监听
        private OnTempChangeListener onTempChangeListener;
        // 控件点击监听
        private OnClickListener onClickListener;
    
        // 以下为旋转按钮相关
    
        // 当前按钮旋转的角度
        private float rotateAngle;
        // 当前的角度
        private float currentAngle;
        /**
         * 是否可以旋转
         */
        private boolean canRotate = false;
    
        public TempControlView(Context context) {
            this(context, null);
        }
    
        public TempControlView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public TempControlView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            dialPaint = new Paint();
            dialPaint.setAntiAlias(true);
            dialPaint.setStrokeWidth(dp2px(2));
            dialPaint.setStyle(Paint.Style.STROKE);
    
            arcPaint = new Paint();
            arcPaint.setAntiAlias(true);
            arcPaint.setColor(Color.parseColor("#3CB7EA"));
            arcPaint.setStrokeWidth(dp2px(2));
            arcPaint.setStyle(Paint.Style.STROKE);
    
            titlePaint = new Paint();
            titlePaint.setAntiAlias(true);
            titlePaint.setTextSize(sp2px(20));
            titlePaint.setColor(Color.parseColor("#FFFFFF"));
            titlePaint.setStyle(Paint.Style.STROKE);
    
            tempFlagPaint = new Paint();
            tempFlagPaint.setAntiAlias(true);
            tempFlagPaint.setTextSize(sp2px(25));
            tempFlagPaint.setColor(Color.parseColor("#FFFFFF"));
            tempFlagPaint.setStyle(Paint.Style.STROKE);
    
            buttonPaint = new Paint();
            tempFlagPaint.setAntiAlias(true);
            paintFlagsDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
    
            tempPaint = new Paint();
            tempPaint.setAntiAlias(true);
            tempPaint.setTextSize(sp2px(60));
            tempPaint.setColor(Color.parseColor("#3B434E"));
            tempPaint.setStyle(Paint.Style.STROKE);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            // 控件宽、高
            width = height = Math.min(h, w);
            // 刻度盘半径
            dialRadius = width / 2 - dp2px(20);
            // 圆弧半径
            arcRadius = dialRadius - dp2px(20);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            drawScale(canvas);
            drawArc(canvas);
            drawText(canvas);
            drawButton(canvas);
            drawTemp(canvas);
        }
    
    
        /**
         * 绘制刻度盘
         *
         * @param canvas 画布
         */
        private void drawScale(Canvas canvas) {
            canvas.save();
            canvas.translate(getWidth() / 2, getHeight() / 2);
            // 顺时针旋转135-2度
            canvas.rotate(133);
            //未达到的温度
            dialPaint.setColor(Color.parseColor("#00ff00"));
            for (int i = angleRate * maxTemp; i > angleRate * temperature; i--) {
                canvas.drawLine(0, -dialRadius, 0, -dialRadius + scaleHeight, dialPaint);
                canvas.rotate(-angleOne);
            }
    
            //已经达到的温度
            dialPaint.setColor(Color.parseColor("#E37364"));
            for (int i = temperature * angleRate; i >= minTemp * angleRate; i--) {
                canvas.drawLine(0, -dialRadius, 0, -dialRadius + scaleHeight, dialPaint);
                canvas.rotate(-angleOne);
            }
            canvas.restore();
        }
    
        /**
         * 绘制刻度盘下的圆弧
         * @param canvas 画布
         */
        private void drawArc(Canvas canvas) {
            canvas.save();
            canvas.translate(getWidth() / 2, getHeight() / 2);
            canvas.rotate(135 + 2);
            RectF rectF = new RectF(-arcRadius, -arcRadius, arcRadius, arcRadius);
            canvas.drawArc(rectF, 0, 265, false, arcPaint);
            canvas.restore();
        }
    
        /**
         * 绘制标题与温度标识
         * @param canvas 画布
         */
        private void drawText(Canvas canvas) {
            canvas.save();
    
            // 绘制标题
            float titleWidth = titlePaint.measureText(title);
            canvas.drawText(title, (width - titleWidth) / 2, dialRadius * 2 + dp2px(15), titlePaint);
    
            // 绘制最小温度标识
            // 最小温度如果小于10,显示为0x
            String minTempFlag = "";
            if (minTemp <= 0) {
                minTempFlag = minTemp + "";
            } else {
                minTempFlag = minTemp < 10 ? "0" + minTemp : minTemp + "";
            }
    
            float tempFlagWidth = titlePaint.measureText(maxTemp + "");
            canvas.rotate(55, width / 2, height / 2);
            canvas.drawText(minTempFlag, (width - tempFlagWidth) / 2, height + dp2px(5), tempFlagPaint);
    
            // 绘制最大温度标识
            canvas.rotate(-105, width / 2, height / 2);
            canvas.drawText(maxTemp + "", (width - tempFlagWidth) / 2, height + dp2px(5), tempFlagPaint);
            canvas.restore();
        }
    
        /**
         * 绘制旋转按钮
         * @param canvas 画布
         */
        private void drawButton(Canvas canvas) {
            // 按钮宽高
            int buttonWidth = buttonImage.getWidth();
            int buttonHeight = buttonImage.getHeight();
            // 按钮阴影宽高
            int buttonShadowWidth = buttonImageShadow.getWidth();
            int buttonShadowHeight = buttonImageShadow.getHeight();
    
            // 绘制按钮阴影
            canvas.drawBitmap(buttonImageShadow, (width - buttonShadowWidth) / 2,
                    (height - buttonShadowHeight) / 2, buttonPaint);
    
            Matrix matrix = new Matrix();
            // 设置按钮位置,移动到控件中心
            matrix.setTranslate((width - buttonWidth) / 2, (height - buttonHeight) / 2);
            // 设置旋转角度,旋转中心为控件中心,当前也是按钮中心
            matrix.postRotate(45 + rotateAngle, width / 2, height / 2);
    
            //设置抗锯齿
            canvas.setDrawFilter(paintFlagsDrawFilter);
            canvas.drawBitmap(buttonImage, matrix, buttonPaint);
        }
    
        /**
         * 绘制温度
         *
         * @param canvas 画布
         */
        private void drawTemp(Canvas canvas) {
            canvas.save();
            canvas.translate(getWidth() / 2, getHeight() / 2);
    
            float tempWidth = tempPaint.measureText(temperature + "");
            float tempHeight = (tempPaint.ascent() + tempPaint.descent()) / 2;
    
            if (temperature==0){
                canvas.drawText("off", -tempWidth-30  - dp2px(5), -tempHeight, tempPaint);
    
            }else{
                canvas.drawText(temperature + "档", -tempWidth-30  - dp2px(5), -tempHeight, tempPaint);
            }
            canvas.restore();
        }
    
        private boolean isDown;
        private boolean isMove;
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (!canRotate) {
                return super.onTouchEvent(event);
            } else {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        isDown = true;
                        float downX = event.getX();
                        float downY = event.getY();
                        currentAngle = calcAngle(downX, downY);
                        break;
    
                    case MotionEvent.ACTION_MOVE:
                        isMove = true;
                        float targetX;
                        float targetY;
                        downX = targetX = event.getX();
                        downY = targetY = event.getY();
                        float angle = calcAngle(targetX, targetY);
    
                        // 滑过的角度增量
                        float angleIncreased = angle - currentAngle;
    
                        // 防止越界
                        if (angleIncreased < -270) {
                            angleIncreased = angleIncreased + 360;
                        } else if (angleIncreased > 270) {
                            angleIncreased = angleIncreased - 360;
                        }
    
                        IncreaseAngle(angleIncreased);
                        currentAngle = angle;
                        invalidate();
                        break;
    
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP: {
                        if (isDown) {
                            if (isMove) {
                                // 纠正指针位置
                                rotateAngle = (float) ((temperature - minTemp) * angleRate * angleOne);
                                invalidate();
                                // 回调温度改变监听
                                if (onTempChangeListener != null) {
                                    onTempChangeListener.change(temperature);
                                }
                                isMove = false;
                            } else {
                                // 点击事件
                                if (onClickListener != null) {
                                    onClickListener.onClick(temperature);
                                }
                            }
                            isDown = false;
                        }
                        break;
                    }
                }
                return true;
            }
        }
    
        /**
         * 以按钮圆心为坐标圆点,建立坐标系,求出(targetX, targetY)坐标与x轴的夹角
         *
         * @param targetX x坐标
         * @param targetY y坐标
         * @return (targetX, targetY)坐标与x轴的夹角
         */
        private float calcAngle(float targetX, float targetY) {
            float x = targetX - width / 2;
            float y = targetY - height / 2;
            double radian;
    
            if (x != 0) {
                float tan = Math.abs(y / x);
                if (x > 0) {
                    if (y >= 0) {
                        radian = Math.atan(tan);
                    } else {
                        radian = 2 * Math.PI - Math.atan(tan);
                    }
                } else {
                    if (y >= 0) {
                        radian = Math.PI - Math.atan(tan);
                    } else {
                        radian = Math.PI + Math.atan(tan);
                    }
                }
            } else {
                if (y > 0) {
                    radian = Math.PI / 2;
                } else {
                    radian = -Math.PI / 2;
                }
            }
            return (float) ((radian * 180) / Math.PI);
        }
    
        /**
         * 增加旋转角度
         *
         * @param angle 增加的角度
         */
        private void IncreaseAngle(float angle) {
            rotateAngle += angle;
            if (rotateAngle < 0) {
                rotateAngle = 0;
            } else if (rotateAngle > 270) {
                rotateAngle = 270;
            }
            // 加上0.5是为了取整时四舍五入
            temperature = (int) ((rotateAngle / angleOne) / angleRate + 0.5) + minTemp;
        }
    
        /**
         * 设置几格代表1度,默认4格
         *
         * @param angleRate 几格代表1度
         */
        public void setAngleRate(int angleRate) {
            this.angleRate = angleRate;
        }
    
        /**
         * 设置温度
         *
         * @param temp 设置的温度
         */
        public void setTemp(int temp) {
            setTemp(minTemp, maxTemp, temp);
        }
    
        /**
         * 设置温度
         *
         * @param minTemp 最小温度
         * @param maxTemp 最大温度
         * @param temp    设置的温度
         */
        public void setTemp(int minTemp, int maxTemp, int temp) {
            this.minTemp = minTemp;
            this.maxTemp = maxTemp;
            if (temp < minTemp) {
                this.temperature = minTemp;
            } else {
                this.temperature = temp;
            }
            // 计算每格的角度
            angleOne = (float) 270 / (maxTemp - minTemp) / angleRate;
            // 计算旋转角度
            rotateAngle = (float) ((temp - minTemp) * angleRate * angleOne);
            invalidate();
        }
    
        /**
         * 设置旋钮是否可以旋转
         *
         * @param canRotate
         */
        public void setCanRotate(boolean canRotate) {
            this.canRotate = canRotate;
        }
    
        public boolean getCanRotate() {
            return this.canRotate;
        }
    
    
        /**
         * 设置温度改变监听
         *
         * @param onTempChangeListener 监听接口
         */
        public void setOnTempChangeListener(OnTempChangeListener onTempChangeListener) {
            this.onTempChangeListener = onTempChangeListener;
        }
    
        /**
         * 设置点击监听
         *
         * @param onClickListener 点击回调接口
         */
        public void setOnClickListener(OnClickListener onClickListener) {
            this.onClickListener = onClickListener;
        }
    
        /**
         * 温度改变监听接口
         */
        public interface OnTempChangeListener {
            /**
             * 回调方法
             *
             * @param temp 温度
             */
            void change(int temp);
        }
    
        /**
         * 点击回调接口
         */
        public interface OnClickListener {
            /**
             * 点击回调方法
             *
             * @param temp 温度
             */
            void onClick(int temp);
        }
    
        public int dp2px(float dp) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                    getResources().getDisplayMetrics());
        }
    
        private int sp2px(float sp) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                    getResources().getDisplayMetrics());
        }
    }
    
    

    (6)manifests

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        package="com.example.myclient">
        <uses-permission android:name="android.permission.INTERNET" />
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme"
            tools:ignore="AllowBackup,GoogleAppIndexingWarning">
            <activity android:name=".HomeActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>
    

    需要的图片分别是light1~5.png,backgronud.png

    在这里插入图片描述

    展开全文
  • 请教:手机做个小app,利用wifi实现另一独立wifi模块(作为服务器使用)通信;这个app的思路是咋样的呢 求高手 指点; 只是socket(ip,port)?(tcp通信方式)
  • 基于WiFi模块的Android WiFi通信

    千次阅读 2019-04-28 20:43:43
    此篇文章记录的内容,需要手机连接到WiFi模块,通过wifi让Android端和硬件部分处于同一个局域网内。Android网络通信通过socket编程实现网络的连接,通过IO流实现数据的发送接收。 首先,创建一个Android项目,...

    基于ESP8266的Android WiFi通信广泛应用于物联网领域,常用是通过局域网实现Android端和下位机的通信,达到控制目的。

    此篇文章记录的内容,需要手机连接到WiFi模块,通过wifi让Android端和硬件部分处于同一个局域网内。Android网络通信通过socket编程实现网络的连接,通过IO流实现数据的发送与接收。

    首先,创建一个Android项目,首先,需要给予APP网络权限:

     <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    第二步,创建一个类SendThead,内容为发送和接收的代码,首先定义IP,端口port,以及接收/发送’变量,打开套接字实现网络的连接,连接结束关闭套接字,采取多线程实现信息的发送与接收:

    package com.example.a14942.smart_see;
     
    /**
     * Created by 14942 on 2018/3/26.
     */
     
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
     
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.util.ArrayList;
     
    class SendThread implements Runnable {
     
        private String ip;
        private int port;
        BufferedReader in;
        PrintWriter out;      //打印流
        Handler mainHandler;
        Socket s;
        private String receiveMsg;
     
        ArrayList<String> list = new ArrayList<String>();
     
        public SendThread(String ip,int port, Handler mainHandler) {     //IP,端口,数据
            this.ip = ip;
            this.port=port;
            this.mainHandler = mainHandler;
        }
     
        /**
         * 套接字的打开
         */
        void open(){
            try {
                s = new Socket(ip, port);
                //in收单片机发的数据
                in = new BufferedReader(new InputStreamReader(s.getInputStream()));
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                        s.getOutputStream())), true);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
        /**
         * 套接字的关闭
         */
        void close(){
            try {
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
        @Override
        public void run() {
     
            //创建套接字
            open();
     
            //BufferedReader
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            Thread.sleep(200);
                            close();
                            open();
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                        if (!s.isClosed()) {
                            if (s.isConnected()) {
                                if (!s.isInputShutdown()) {
                                    try {
                                        Log.i("mr", "等待接收信息");
     
                                        char[] chars = new char[1024];                    //byte[] bys = new byte[1024];        
                                        int len = 0;                            //int len = 0;
                                        while((len = in.read(chars)) != -1){                //while((len = in.read(bys)) != -1) {    
                                            System.out.println("收到的消息:  "+new String(chars, 0, len));      in.write(bys,0,len);
                                            receiveMsg = new String(chars, 0, len);                // }
                                                        
                                            Message msg=mainHandler.obtainMessage();
                                            msg.what=0x00;
                                            msg.obj=receiveMsg;
                                            mainHandler.sendMessage(msg);
                                        }
     
                                    } catch (IOException e) {
                                        Log.i("mr", e.getMessage());
                                        try {
                                            s.shutdownInput();
                                            s.shutdownOutput();
                                            s.close();
                                        } catch (IOException e1) {
                                            e1.printStackTrace();
                                        }
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
     
                    }
                }
     
            });
            thread.start();
     
            while (true) {
     
                //连接中
                if (!s.isClosed()&&s.isConnected()&&!s.isInputShutdown()) {
     
                    // 如果消息集合有东西,并且发送线程在工作。
                    if (list.size() > 0 && !s.isOutputShutdown()) {
                        out.println(list.get(0));
                        list.remove(0);
                    }
     
                    Message msg=mainHandler.obtainMessage();
                    msg.what=0x01;
                    mainHandler.sendMessage(msg);
                } else {
                    //连接中断了
                    Log.i("mr", "连接断开了");
                    Message msg=mainHandler.obtainMessage();
                    msg.what=0x02;
                    mainHandler.sendMessage(msg);
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    try {
                        out.close();
                        in.close();
                        s.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    e.printStackTrace();
                }
            }
     
        }
     
        public void send(String msg) {
            System.out.println("msg的值为:  " + msg);
            list.add(msg);
        }
     
    }
     
    第三步,创建主活动,编写布局(xml)文件,这里我创建了一个温度显示框,和两个开关控制按钮(switch控件):

    <?xml version="1.0" encoding="utf-8"?>
    <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/screen"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="@drawable/bb"
        >
     
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_x="30dp"
            android:layout_y="130dp"
            android:orientation="horizontal">
     
     
            <TextView
                android:id="@+id/textView2"
                android:layout_width="50sp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="33px"
                android:text="湿度"
                android:textColor="#000000"
                android:textSize="18sp" />
     
            <TextView
                android:id="@+id/ttv2"
                android:layout_width="160sp"
                android:layout_height="wrap_content"
                android:background="#FFFFFF"
                android:text=""
                android:textSize="18sp" />
     
            <TextView
                android:layout_width="60sp"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:paddingLeft="10px"
                android:text="%rh"
                android:textColor="#000000"
                android:textSize="18sp" />
     
        </LinearLayout>
     
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="开         关"
            android:textColor="#000000"
            android:textSize="18sp"
            android:layout_x="50dp"
            android:layout_y="200dp"
            />
     
        <Switch
            android:id="@+id/Switch2"
            android:layout_width="50sp"
            android:layout_height="wrap_content"
            android:layout_weight="1.01"
            android:layout_x="210dp"
            android:layout_y="270dp" />
     
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="自动手动"
            android:textColor="#000000"
            android:textSize="18sp"
            android:layout_x="50dp"
            android:layout_y="270dp"
            />
     
        <Switch
            android:id="@+id/Switch1"
            android:layout_width="50sp"
            android:layout_height="wrap_content"
            android:layout_x="210dp"
            android:layout_y="200dp" />
     
    </AbsoluteLayout>
     第四步,编写主活动,包括实现网络连接(SendThead),实现消息的发送和接收,对开关控件(switch)定义点击事件:

    package com.example.a14942.smart_see;
     
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.CompoundButton;
    import android.widget.Switch;
    import android.widget.TextView;
     
    import java.io.BufferedReader;
    import java.io.PrintWriter;
    import java.util.ArrayList;
    import java.util.List;
     
    public class MainActivity extends AppCompatActivity{
     
        /*接收发送定义的常量*/
        private String mIp = "192.168.4.1";
        private int mPort = 9000;
        private SendThread sendthread;
        String receive_Msg;
        String l;
        String total0,total1,total2,total3;
        private Button button0;
        private Button button1;
        static PrintWriter mPrintWriterClient = null;
        static BufferedReader mBufferedReaderClient    = null;
        Switch switch1,switch2;
        /*****************************/
     
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //getSupportActionBar().hide();
            setContentView(R.layout.activity_main);
    //        button0= (Button)findViewById(R.id.Water_W_N);
    //        button0.setOnClickListener(button0ClickListener);
    //        button1= (Button)findViewById(R.id.Water_W_O);
    //        button1.setOnClickListener(button1ClickListener);
     
            /***************连接*****************/
            sendthread = new SendThread(mIp, mPort, mHandler);
            Thread1();
            new Thread().start();
            /**********************************/
     
            switch1 = (Switch) findViewById(R.id.Switch1);
            switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
     
                @Override
                public void onCheckedChanged(CompoundButton buttonView,
                                             boolean isChecked) {
                    // TODO Auto-generated method stub
                    if (isChecked) {
                        sendthread.send("A");
                    } else {
                        sendthread.send("B");
                    }
                }
     
            });
     
            switch2 = (Switch) findViewById(R.id.Switch2);
            switch2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
     
                @Override
                public void onCheckedChanged(CompoundButton buttonView,
                                             boolean isChecked) {
                    // TODO Auto-generated method stub
                    if (isChecked) {
                        sendthread.send("C");
                    } else {
                        sendthread.send("D");
                    }
                }
     
            });
        }
    //    private View.OnClickListener button0ClickListener = new View.OnClickListener() {
    //        public void onClick(View arg0) {
    //            mPrintWriterClient.print("j");
    //            mPrintWriterClient.flush();
    //
    //        }
    //    };
    //    private View.OnClickListener button1ClickListener = new View.OnClickListener() {
    //        public void onClick(View arg0) {
    //            mPrintWriterClient.print("m");
    //            mPrintWriterClient.flush();
    //        }
    //    };
     
     
        private class FragmentAdapter extends FragmentPagerAdapter {
            List<Fragment> fragmentList = new ArrayList<Fragment>();
     
            public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
                super(fm);
                this.fragmentList = fragmentList;
            }
     
            @Override
            public Fragment getItem(int position) {
                return fragmentList.get(position);
            }
     
            @Override
            public int getCount() {
                return fragmentList.size();
            }
     
        }
     
     
        /*接收线程*******************************************************************************/
        /**
         * 开启socket连接线程
         */
        void Thread1(){
    //        sendthread = new SendThread(mIp, mPort, mHandler);
            new Thread(sendthread).start();//创建一个新线程
        }
     
        Handler mHandler = new Handler()
        {
            public void handleMessage(Message msg)
            {
                TextView text0 = (TextView)findViewById(R.id.ttv2);
                super.handleMessage(msg);
                if (msg.what == 0x00) {
     
                    Log.i("mr_收到的数据: ", msg.obj.toString());
                    receive_Msg = msg.obj.toString();
                    l = receive_Msg;
                    text0.setText(l);
                }
            }
        };


    原文:https://blog.csdn.net/weixin_40042248/article/details/81099324 
     

    展开全文
  • stm32f103c8t6控制ESP8266与手机APP通信

    千次阅读 多人点赞 2021-01-04 19:39:26
    之前已经发表过利用stm32控制蓝牙模块与手机APP通信的文章,那么现在我就来说说用WIFI模块来控制与手机APP通信 首先需要的器件如下: stm32f103c8t6 ESP8266-01S(默认波特率115200) 除此之外还需要手机下载一个...

    stm32f103c8t6控制ESP8266与手机APP通信


    之前已经发表过利用stm32控制蓝牙模块与手机APP通信的文章,那么现在我就来说说用WIFI模块来控制与手机APP的通信
    首先需要的器件如下:
    stm32f103c8t6
    ESP8266-01S(默认波特率115200)
    除此之外还需要手机下载一个通讯软件,我用的是安卓手机应用宝上面的TCP连接这个APP
    WIFI模块的连接如下所示:
    在这里插入图片描述

    代码很简单,我主要附上主函数代码:

    /*
    ESP8266 AP+Station服务器模式测试
    
    UART2 PA2 PA3  与网络模块ESP进行通信
    
    UART1 PA9 PA10 进行数据跟踪
    */
    
    #include  "delay.h"
    #include  "led.h"
    #include  "usart.h"
    #include  "string.h"
    #include  "stdio.h"
    extern  u8 RX_buffer[tbuf];
    extern u8 RX_num;				 //接收计数变量
    
    u8  esp_at[]="AT\r\n";                  // 握手连接指令,返回"OK"
    u8  esp_cifsr[]="AT+CIFSR\r\n";         // 本机IP地址查询指令
    u8  esp_cipsend[]="AT+CIPSEND=6\r\n";   // 设置发送数据长度
    u8  esp_test[]="sunny\r\n";   			//  数据内容
    u8  esp_rst[]="AT+RST\r\n"; 					// 软件复位
     
    u8  esp_cwmode[]="AT+CWMODE=3\r\n";     // 设置ESP8266的工作模式3 AP+Station,返回"OK"或者"no change"
    u8  esp_cwsap[]="AT+CWSAP=\"ESP8266_TEST\",\"1234567890\",1,3\r\n";//设置WIFI的名称及密码
    u8  esp_cipmux[]="AT+CIPMUX=1\r\n";   			//打开多连接	
    u8  esp_cipserver[]="AT+CIPSERVER=1,8080\r\n";  //建立TCP服务器,开放端口8080
    
    //指定字符串与缓存数组数据进行数据比较
    //*p 要比较的指定字符串指针数据
    //返回:1 数据一致  0 数据不一致 
    u8 Data_compare(u8 *p)
    { 
    	if(strstr(RX_buffer,p)!=NULL)
    	    return 1;
    	else
    		return 0;
    }
    
    int main(void)
       {	
       	delay_init();	    	 //延时函数初始化
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);		//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    	uart_init(115200);	 //串口初始化为9600  
    	LED_Init();		  	//初始化与LED连接的硬件接口
    	memset(RX_buffer, 0, tbuf);//清缓存数据
    	RX_num=0;				   //接收计数变量清0
    
    	//配置wifi工作模式为ap+sta模式
        while(1)
    	{
    	 Uart2SendStr(esp_cwmode);	   // 设置ESP8266的工作模式3 AP+Station,返回"OK"或者"no change"
    	 if(Data_compare("OK")||Data_compare("no change"))break;
    	 else  Uart1SendStr("ERROR1,some problems with ESP8266 \r\n");
    	 delay_ms(600);
    	}
    	 Uart1SendStr("OK,set mode as AP+Station with ESP8266! \r\n");	 
    	 memset(RX_buffer, 0, tbuf);//清缓存数据	
    	 RX_num=0;				   //接收计数变量清0
    	
    	while(1)
    	{
    	 Uart2SendStr(esp_cwsap);	   //设置WIFI的名称及密码
    	 if(Data_compare("OK"))break;
    	 else  Uart1SendStr("ERROR2,some problems with ESP8266 \r\n");
    	 delay_ms(600);
    	}
    	 Uart1SendStr("OK,set cwsap success! \r\n"); 
    	 memset(RX_buffer, 0, tbuf);//清缓存数据	
    	 RX_num=0;					//接收计数变量清0
    	
        while(1)
    	{
    	 Uart2SendStr(esp_cipmux);	   //设置多连接 (多路连接模式)
    	 if(Data_compare("OK"))break;
    	 else  Uart1SendStr("ERROR3,some problems with ESP8266 \r\n");
    	 delay_ms(600);
    	}
    	Uart1SendStr("OK,set cipmux success! \r\n");
    	memset(RX_buffer, 0, tbuf);//清缓存数据
    	RX_num=0;				   //接收计数变量清0
    
        while(1)
    	{
    	 Uart2SendStr(esp_cipserver);	   //设置wifi模块为TCP服务器模式,并配置端口为8080
    	 if(Data_compare("OK"))break;
    	 else  Uart1SendStr("ERROR4,some problems with ESP8266 \r\n");
    	 delay_ms(600);
    	}
    	Uart1SendStr("OK,set server success! \r\n");
    	memset(RX_buffer, 0, tbuf);//清缓存数据
    	RX_num=0;				   //接收计数变量清0
    
    	while(1)
    	{	
    		if(Data_compare("LEDK"))               //点亮板上了的led
    		{		
                led(1);	
    			memset(RX_buffer, 0, tbuf);//清缓存数据
    			RX_num=0;				   //接收计数变量
    			Uart1SendStr("led is open!\r\n");							
    		}
    	    else if(Data_compare("LEDG")) 		   //关闭板上了的led
    		{
                led(0);		
    			memset(RX_buffer, 0, tbuf);//清缓存数据
    			RX_num=0;				   //接收计数变量清0
    			Uart1SendStr("led is close!\r\n");									
    		}	
    	}
       }
    

    这里主要用到有如下几个AT指令:
    AT+CWMODE=3(设置ESP8266的工作模式3 AP+Station,返回"OK"或者"no change")
    AT+CWSAP=“ESP8266_TEST”,“1234567890”,1,3(设置WIFI的名称及密码,这个名称和密码你可以随便取你自己喜欢的就行,后面两个是通道号和密码模式,默认1,3就好)
    AT+CIPMUX=1(打开多连接 )
    AT+CIPSERVER=1,8080(建立TCP服务器,开放端口8080)
    这些AT指令我是在程序中执行的,不过你也可以利用USB转TTL模块直接与WIFI模块连接进行配置,这里说明一下,配置AP+Station模式以及配置WIFI名称和密码只要配置一次就行,即使之后断电再上电也不用重复配置,每次上电后只要输入AT+CIPMUX=1和AT+CIPSERVER=1,8080即可。为了让刚接触WIFI模块的人能直接使用这个模块,我在程序中把AP+Station模式以及WIFI名称和密码都写进去,这样无论你的模块之前是被配置成什么样,现在经过这四个配置后就可以在你的电脑上面热点发现有这个WIFI的出现,如下图:在这里插入图片描述
    到这里,我们的WIFI已经设置成功了。
    还有就是每次发送AT指令给WIFI模块,WIFI模块收到你发送的特定指令后基本都会发送一串数据返回(当作是数据应答,为了就是让你知道你这个AT指令是否配置成功,具体的AT指令集我将在文章末尾附上链接,在我看来下面的AT指令集很全面)
    接下来,我就简单的说下手机上面的APP"TCP连接"如何使用:
    打开APP之后,点击右上角的连接,此时他会叫你选择一个远程主机进行连接(你如果刚刚下载的话,下面是没有任何一个连接的),而在你点击右上角连接后,会看到右上角有一个省略号,点进去后,他会叫你输入地址以及端口号,这个地址固定是:192.168.4.1,如果不放心可以使用“AT+CIFSR”查询(用USB转TTL模块直接与WIFI模块连接,然后在PC端上面的串口调试助手可以看到你发送AT+CIFSR后,在上面会显示WIFI模块返回的数据,返回的数据中就包括了这个地址),端口:8080,这对应着“AT+CIPSERVER=1,8080”。然后点击APP上面的连接,这样就将手机APP与WIFI模块的通讯完成了(也就是手机连接上了WIFI模块创建出来的WIFI,不过这个WIFI是不能上网的,只能拿来通讯用),就可以实现通过手机APP控制WIFI模块,进而控制STM32控制板了,上面的程序中,我是写接收到LEDK(也就是LED开的缩写)就亮起stm32f103c8t6上面的红灯PA1,接收到LEDG(也就是LED关的缩写)就熄灭stm32f103c8t6上面的红灯。手机界面如下:
    在这里插入图片描述
    是不是看起来跟蓝牙串口的界面很像,这也是另一种通讯的方法,在我之前的文章中也有一篇是专门讲蓝牙通讯的,感兴趣的可以去看看。好了,要说的话就这么多了,下面就附上相关程序以及AT指令集的链接。
    stm32f103c8t6控制ESP8266与手机APP通信程序
    ESP8266AT指令集
    代码要的下方留言邮箱我会第一时间发给你们的,有什么问题也可以下面评论!

    展开全文
  • STM32F407单片机通过ESP8266 WiFi模块与Android 手机APP连接实现数据的相互传输,在单片机上通过LCD显示屏实时显示连接的状态以及互相传输的数据,先看效果图: STM32单片机 Android 手机APP 1.下位机硬件配置...
  • 手机APP与WiFi模块通信控制智能小车
  • 51单片机通过WIFI模块ESP8266控制LED灯

    万次阅读 多人点赞 2018-06-16 18:47:40
    手机APP通过ESP8266 WIFI模块与51单片机通信控制LED灯的开关。下位机由单片机、ESP8266模块和LED灯组成,上位机由Android手机APP承担。我们在APP上发送LED灯的开关控制指令,ESP8266将收到的数据发送给单片机,从而...
  • WIFI模块联网过程

    千次阅读 2018-01-08 11:59:59
    智能家电构成: ...| 这个过程就是wifi模块与手机APP绑定 手机APP 1.先是手机APP广播SSID、key手机IP 2.wifi模块收到后手机建立连接确认IP等信息后绑定成功 3.然后wifi模块与服务器建立连接 4.实现通信
  • 单片机的P3.0的P3.1(也就是串口通信线)分别与wifi模块的串口通信线连接,注意不要接反,esp8266其它脚位按规格书上连接即可。 3.单片机的P2.4口控制灯,可接于三极管基极上(或通过继电器可以控制ac220的灯)。注意...
  • 本例程采用ESP8266 wifi模块与STM32串口连接,并提供AT指令封装库STM32通讯,实现如下的通讯方式: 1、硬件部分 Wifi模块丝印图即引脚如下: 硬件连接如下: 2、手机APP部分 APP部分我们采用常用的APP wifi调试软件 ...
  • 无线通信技术高速发展的物联网时代,真正实现了人物、物物的信息交换和通讯,我们只需要在智能手机上安装好各种智能终端产品(智能插座、智能灯控)配套的App,就可以通过触控屏幕实现各种内置无线模块的智能...
  • 接到一个项目任务,做一个Android app:和另一个手机号码进行通信,通过外网,手机的蜂窝移动数据,非wifi。此app是客户端,另一手机号的手机卡安装在一个3G模块上,做为服务器端。注意,没有其他服务器,手机...
  • 支持wifi以太网双网络...使用Android Studio 自主写一个MQTT手机app远程控制。 onenet WEB界面 onenet 手机界面:下载onenet设备云app即可app控制监控。     阿里云IOT studio WEB界面:  
  • 手机APP通过ESP8266 WIFI模块与51单片机通信控制四路继电器。下位机由单片机、ESP8266模块和继电器模块组成,上位机由Android手机APP承担。我们在APP上发送继电器的开关控制指令,ESP8266将收到的数据发送给单片机,...
  • 通过手机App控制RGB调节灯带的亮度

    千次阅读 2020-01-21 20:48:51
    很久没有更新了,最近过年回家有空拿出来东西玩玩,花了半天的时间搞这个,主要实现的原理,通过Arduino单片机使用AT指令控制wifi模块,esp8266 wifi 模块与手机建立连接通信APP通过socket通信向esp8266 wifi发送...
  • 51单片机WiFi遥控小车是利用手机作为控制端,通过WIFI模块与单片机串口通信,实现小车的前进、后退、左拐、右拐停止等功能。 APP截图: 小车图片:
  • 本模块很多都是 从博客ESP8266 WIFI模块学习之路 学习来的,在这里非常感谢这位博主博客技术的分享...编写一个手机APP,通过socket编程,与WIFI ESP8266进行通信 首先介绍AT指令,什么是AT指令? AT指令就是控制WIFI...
  • 手机APP通过ESP8266 WIFI模块与51单片机通信控制LED灯的开关。下位机由单片机、ESP8266模块和LED灯组成,上位机由Android手机APP承担。我们在APP上发送LED灯的开关控制指令,ESP8266将收到的数据发送给单片机,从而...
  • 通过红外和声音传感器构成检测系统,基于WIFI模块实现公共网络平台远程发送给手机app客户端室内环境信号,可远程处理火警报警、灭火处理、住宅闯入报警。家居火警监测火情处理的功能是由红外传感器部分组成,声音...
  • 这一篇博客主要对手机app与该模块的一个通信方式,以及main函数的实现方法。 1、数据传输代码  通过WiFi与APP进行连接,控制。WiFi模块初始化代码。值得注意的是该配置方案是针对该模块-路由器-手机app实现的,所以...
  • 1.手机APP远程控制:STM32L432开发板通过WIFI模块与因特网服务器建立TCP连接,服务器使用腾讯云,服务器系统为ubuntu,就是在ubuntu上建立一个TCP中继服务器,实现远程手机端家居系统的信息中继传递,从而实现远程...
  • 要开始IoT项目的第一步是什么...对,这就是WIFI模块最重要解决的问题。 为了解决这个连接问题乐鑫在其SDK中加入了SmartConfig功能,所谓的smartconfig就是手机APP端发送包含WIFI 用户名 WIFI密码的 UDP 广播包或者组...
  • 目录需求与功能需求介绍网络设计实现功能介绍系统选型硬件选型技术...手机端使用APP与MQTT服务器相连,APP与WIFi模块相互订阅对方发布的消息实现数据 这里是引用 通信。 实现功能介绍 硬件功能:温湿度采集,光照强度
  • 本篇文章是TB系列蓝牙模块及TB02开发板应用开发资料的汇总,主要内容包括开发环境搭建,固件烧录,串口调试,烧录三元组,连接天猫精灵,Mesh组网,与手机APP或微信小程序通信,低功耗蓝牙基础知识讲解等等。...
  • WeMos下实现小车避障与手机控制

    千次阅读 2020-10-02 10:17:45
    蜂鸣器2.Wemos串口通信3.Wemos和wifi4.Wemos和超声波测距5.Wemos和L9110s步进电机控制器6.安卓APP控制小车三、项目整合总结 前言 通过WeMos D1开发板、超声波模块、蜂鸣器、L9110s步进电机实现:小车方向控制,如果...

空空如也

空空如也

1 2 3
收藏数 53
精华内容 21
关键字:

手机app与wifi模块通信