西电通院大二项目设计保姆式教程(上位机部分)

这篇具有很好参考价值的文章主要介绍了西电通院大二项目设计保姆式教程(上位机部分)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:
本文相关:西安电子科技大学通信工程学院大二项目设计
内容:安卓上位机软件开发、使用MQTT通信协议进行上位机与wifi模块之间的无线通信、wifi模块与下位机f411实现串口通信。
上位机部分:Android Studio、Arduino、友善之臂smart4418、esp8266无线通信模块
使用无线通信可以避免使用官方提供的接口,提高代码的复用性,毕竟不同的开发板厂商提供的接口也不同。同时,提高作品的便携程度。

安卓软件开发

控件及布局

这里会介绍需要用到的控件Button、TextView、EditView(已button为例)和两种布局:线性布局、约束布局
Button

//声明变量
public Button btn_getcolor;
//绑定.xml中的id
btn_getcolor=findViewById(R.id.button_get_TCS_data);
//设置点击事件
btn_getcolor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                publishmessageplus(mqtt_pub_topic, "THREE");
                if(flag_c==0){
                    flag_c=1;
                }else if (flag_c==1){
                    flag_c=0;
                }
            }
        });

点击一次按钮,上位机会向wifi模块发送字符串THREE,并且改变标志位,以方便消息回传时的接收操作

LinearLayout 又称线性布局。该布局可以使放入其中的组件以水平方式或者垂直方式整齐排列,通过 android:orientation 属性指定具体的排列方式,通过 weight 属性设置每个组件在布局中所占的比重。该布局是安卓开发中最常用的布局,但是嵌套较多,代码书写较为麻烦。

我更喜欢约束布局,ConstraintLayout(约束布局)的出现是为了在Android应用布局中保持扁平的层次结构,减少布局的嵌套,为应用创建响应快速而灵敏的界面。Android Studio可以自由拖动控件,并在右侧的attributes中调节组件的位置、大小。控件需要先与四个边都进行约束,如果不这么做,会出现运行后偏在一侧的情况,当然与其他控件约束也是可以的。

声音提醒

// 声音提醒
public void showSound(int raw) {
        MediaPlayer mediaPlayer = null;
        mediaPlayer = MediaPlayer.create(getApplicationContext(), raw);
        mediaPlayer.setVolume(1, 1);
        mediaPlayer.start();
    }

这里使用的是安卓原生框架的MediaPlayer类,在res文件下创建raw文件,将录音文件更改为.wmv格式放在raw里,用create方法创建实例,调节音量大小。这些代码封装在showSound方法里,用时直接调用即可

无线通信

MQTT通信协议

MQTT是一种基于TCP/IP协议的轻量级通信协议,在物联网、小型设备、移动应用等方面有较广泛的应用。该协议基于发布pub和订阅sub模式,连接同一后台服务器的两个对象,订阅他人后可以接收到别人发布的信息,类似于订阅报刊杂志,这个消息的传播可以是单向的也可以是双向。

MQTT传输的消息分为:主题(Topic)和负载(payload)两部分,Topic可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload)这在Adruino代码中会体现出来

安卓部分

首先在libs中导入mqtt包 :org.eclipse.paho.client.mqttv3-1.2.0.jar
点击add as library添加到库中,添加后可以从build.gradle中看到

implementation files('libs\\org.eclipse.paho.client.mqttv3-1.2.0.jar')

然后就可以调用接口啦!

// mqtt初始化
public void Mqtt_init()
    {
        try {
            //host为主机名,test为clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
            client = new MqttClient(host, mqtt_id,
                    new MemoryPersistence());
            //MQTT的连接设置
            options = new MqttConnectOptions();
            //设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
            options.setCleanSession(false);
            //设置连接的用户名
            options.setUserName(userName);
            //设置连接的密码
            options.setPassword(passWord.toCharArray());
            // 设置超时时间 单位为秒
            options.setConnectionTimeout(10);
            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
            options.setKeepAliveInterval(20);
            //设置回调
            client.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable cause) {
                    //连接丢失后,一般在这里面进行重连
                    System.out.println("connectionLost----------");
                    /artReconnect();
                }
                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    //publish后会执行到这里
                    System.out.println("deliveryComplete---------"
                            + token.isComplete());
                }
                @Override
                public void messageArrived(String topicName, MqttMessage message)
                        throws Exception {
                    //subscribe后得到的消息会执行到这里面
                    System.out.println("messageArrived----------");
                    Message msg = new Message();
                    msg.what = 3;   //收到消息标志位
                    msg.obj = topicName + "---" + message.toString();
                    handler.sendMessage(msg);    // hander 回传
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void Mqtt_connect() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    if(!(client.isConnected()) )  //如果还未连接
                    {
                        client.connect(options);
                        Message msg = new Message();
                        msg.what = 31;
                        handler.sendMessage(msg);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    Message msg = new Message();
                    msg.what = 30;
                    handler.sendMessage(msg);
                }
            }
        }).start();
    }
    public void startReconnect() {
        scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                if (!client.isConnected()) {
                    Mqtt_connect();
                }
            }
        }, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS);
    }

这里涉及到多线程,因为安卓中必须遵循单线程模式,所有耗时操作必须在子线程中进行,否则会导致app闪退崩溃。通过msg.what定义标志位,在handler里进行分类操作
消息回传处理

//
handler = new Handler() {
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 1: //开机校验更新回传
                        break;
                    case 2:  // 反馈回传

                        break;
                    case 3:  //MQTT 收到消息回传   UTF8Buffer msg=new UTF8Buffer(object.toString());
                        //String C_val = msg.obj.toString().substring(msg.obj.toString).indexOf("color:") + 6,msg.obj.toString().indexOf("}"));
                        //String D_val = msg.obj.toString().substring(msg.obj.toString().indexOf("distance:") + 9,msg.obj.toString().indexOf("]"));
                        String C_val = msg.obj.toString().substring(12,20);
                        String D_val = msg.obj.toString().substring(20,31);
                        //String val = msg.obj.toString();
                        if(flag_c==1){
                            text_color.setText(C_val);
                        }else {text_color.setText("空");}
                       if(flag_d==1){
                           text_distance.setText(D_val);
                       }else{text_distance.setText("空");}
                        break;
                    case 30:  //连接失败
                        Toast.makeText(MaintenanceActivity.this, "连接失败", Toast.LENGTH_SHORT).show();
                        break;
                    case 31:   //连接成功
                        //Toast.makeText(MaintenanceActivity.this, "连接成功", Toast.LENGTH_SHORT).show();
                        try {
                            client.subscribe(mqtt_sub_topic, 1);
                        } catch (MqttException e) {
                            e.printStackTrace();
                        }
                        break;
                    default:
                        break;
                }
            }
        };

该代码会爆黄,可能是内存泄漏导致,不过并不影响,可以通过加@SuppressLint(“HandlerLeak”)消除

发送消息,相当于重写了client.publish方法,设置message的payload属性为字节数组,方便Arduino操作

// 发送消息的方法
public void publishmessageplus(String topic,String message2)
    {
        if (client == null || !client.isConnected()) {
            return;
        }
        MqttMessage message = new MqttMessage();
        message.setPayload(message2.getBytes());
        try {
            client.publish(topic,message);
        } catch (MqttException e) {

            e.printStackTrace();
        }
    }

需要注意的是:在其他界面不能声明通过类然后调用该界面的方法,需要重新定义handler和方法

Arduino部分

arduino不显式地使用main作为入口函数,基本的函数时setup()和loop(),在setup中执行初始化,再进入loop中循环,除此以外可以自定义函数或者使用库函数,本例中接收消息并通过串口发送给411就是在PubSubClient.h库中的回调函数callback中执行的。

// 接收信息
void callback(char* topic, byte* payload, unsigned int length) {
  String msg="";
  String LED_set = "";
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    msg+= (char)payload[i];
  }
  Serial.println(msg);
  if(msg=="ONE"){
   Serial.print("ONE");
  }else if(msg=="TWO"){
     Serial.print("TWO");//发送数据给411
  }else if(msg=="THREE"){
    //Serial.print(sendJson("THREE"));
    Serial.print("THREE");
  }else if(msg=="FOUR"){
    Serial.print("FOUR");
  }else if(msg=="FIVE"){
    Serial.print("FIVE");
  }else if(msg=="SIX"){
    Serial.print("SIX");
  }else if(msg=="SEVEN"){
    Serial.print("SEVEN");
  }
}

将收到的信息存储到msg中,判断后执行if中语句

回传信息

// 
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  if(Serial.available())
  {
       comdata = "";//缓存清零
      while (Serial.available() > 0)//循环串口是否有数据
      {
        comdata += char(Serial.read());//叠加数据到comdata
        delay(2);//延时等待响应
      } 
        if(comdata!=""){
          mark=1;
        //Serial.println(comdata);
        }
        else{mark=0;}
      }
   if(mark==1)
  {
    Serial.println(comdata);
    String json = ""+comdata;
    client.publish(Mqtt_pub_topic,json.c_str());
      digitalWrite(2,HIGH);
      delay(500);
      digitalWrite(2,LOW);
      delay(500);
   } 
}

接收到411传来的信息并通过publish发送给上位机,使用板载小灯的亮灭来提醒8266是否接收到该信息。

到这里就结束了,理解比较浅陋,如果文章中有什么不准确或者需要改进的地方,还请大佬不吝赐教。
西电通院大二项目设计保姆式教程(上位机部分)文章来源地址https://www.toymoban.com/news/detail-454215.html

到了这里,关于西电通院大二项目设计保姆式教程(上位机部分)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux之Kafka保姆式详细安装教程

    《Kafka官网下载》 注意:下载的是二进制文件,不要下载源码!这里可以采用第三方下载工具加速下载,如:迅雷等 tar -zxvf是解压文件命令,-C表示把解压文件放到哪个目录下 修改环境变量 export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL下追加内容: 按ESC键后输入:wq保存,使

    2024年02月13日
    浏览(48)
  • 微信小程序——Echarts使用(保姆式教程)

    ✅作者简介:2022年 博客新星 第八 。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:微信小程序学习分享 ✨特色专栏:国学周更-心性养成之路 🥭本文内容:微信小程序——

    2024年02月09日
    浏览(45)
  • 【科普向】Jmeter 如何测试接口保姆式教程

    现在对测试人员的要求越来越高,不仅仅要做好功能测试,对接口测试的需求也越来越多!所以也越来越多的同学问,怎样才能做好接口测试? 要真正的做好接口测试,并且弄懂如何测试接口,需要从如下几个方面去分析问题,再找准学习的的方向,才能让自己在工作中,运

    2024年02月09日
    浏览(47)
  • 微信小程序开发(保姆式教程,点赞+收藏)

    二,微信开发者工具 下载微信web开发者工具,根据自己的操作系统下载对应的安装包进行安装即可。 新建项目 页面介绍 项目组成 page.json 文件 5,新建页面 文件用途 设置主页 把新建的文件路径调到最上面那就是主页了,意思就是,第一个路径就是首页的路径! 三,基本语法

    2024年02月22日
    浏览(63)
  • stable diffusion本地搭建, 保姆式安装教程 已经填坑

    一、优势 对于Midjourney 高额的会员费,SD的高性价比成为了大多数人的选择 二、软件准备 1、在整个安装过程中,我们需要用到以下软件: Python 3.10.6 Git 一键启动器 软件可以到官网上自行下载,不会下载的也没关系,阿良已经帮你们把软件打包下载好了。 领取方法: 需要安

    2024年02月11日
    浏览(61)
  • Windows系统如何关闭防火墙保姆式教程,超详细

    前言 1.以学习为目的使用某些pojie软件时,需要关闭电脑防火墙,系统自带的杀毒软件(迈克菲等),后期下载的杀毒软件(360安全卫士,金山毒霸等),他们会有实时扫描功能,建议关掉,不然软件可能安装不成功,或者可能某天你的pojie软件突然就打不开了,发现相应的文

    2024年02月20日
    浏览(51)
  • 有什么stable diffusion保姆式AI绘画教程?推荐三个方法

    随着人工智能(AI)技术的飞速发展,AI绘画软件正逐渐引起人们的关注和兴趣。这些软件利用先进的深度学习算法和图像处理技术,能够模拟艺术家的绘画风格和技巧,创造出令人惊叹的艺术作品。AI绘画软件不仅成为艺术创作的新工具,还成为创造力的数字助手,为艺术家

    2024年02月11日
    浏览(49)
  • Python基于Mirai开发的QQ机器人保姆式教程(亲测可用)

    在本教程中,我们将使用Python和Mirai来开发一个 QQ机器人 ,本文提供了三个教学视频, 包教包会 ,本文也很贴心 贴了代码和相关文件 。话不多说,直接开始教学。 目录 一、安装配置MIrai 图片验证码报错: 二、机器人的认证与绑定 视频教学 代码 认证和绑定 主程序 三、好

    2024年02月09日
    浏览(44)
  • uniapp从入门到精通(全网保姆式教程)~ 别再说你不会开发小程序了

    目录 一、介绍 二、环境搭建(hello world) 2.1 下载HBuilderX 2.2 下载微信开发者工具 2.3 创建uniapp项目 2.4 在浏览器运行 2.5 在微信开发者工具运行 2.6 在手机上运行 三、项目基本目录结构 四、开发规范概述 五、全局配置文件(pages.json) 5.1 globalStyle(全局样式) 导航栏:背景

    2024年02月08日
    浏览(58)
  • 八米云-N1盒子、机顶盒等设备-小白保姆式超详细刷机教程

    这里以魔百盒CM211-1为例,本次刷机用到的零碎工具比较多,不过都是常见刚需设备,大家可以按照清单核对一下。 目前只支持S905 L3、L3a、L2 系列的各种盒子 机顶盒本体 电脑一台 说明:U口需要稳定。 双公头USB线(连接盒子与笔记本电脑) U盘 说明:容量大于等于8G。 路由

    2024年02月03日
    浏览(431)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包