玩转OneNET物联网平台之MQTT服务⑦ —— 远程控制LED(数量无限制)+ Android App控制 优化第一版

授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。

快速导航
单片机菜鸟的博客快速索引(快速找到你要的)

如果觉得有用,麻烦点赞收藏,您的支持是博主创作的动力。

1.前言

    在前面的博文 玩转OneNET物联网平台之MQTT服务④ —— 远程控制LED(数量无限制)+ Android App控制 中,博主只是大体上讲述了整个小项目的构造。但是,如果作为一个产品来开发的话,还是存在不少问题。这里罗列几个我认为比较重要的问题点:

  • 问题1:App作为一个特殊的设备,理论上也应该支持自注册功能,不应该由开发者或者用户额外去调用API调试工具创建设备,起码得简化这个流程
  • 问题2:App没有处理设备从在线状态切换成离线状态的过程,需要实时更新设备状态

接下来,博主就会针对这两个重要的问题点进行解决思路以及解决步骤的讲解,请读者边思考边实验。

2.解决问题点1

  • App作为一个特殊的设备,理论上也应该支持自注册功能,不应该由开发者或者用户额外去调用API调试工具创建设备,起码得简化这个流程

2.1 解决思路

  • 我们目的无非是为了得到一个真实存在的DeviceID,既然OneNet 平台给我们提供了 新增设备 的API,那么我们可以通过它来创建设备并且获取设备ID。
    在这里插入图片描述
  • 因为创建设备需要设备唯一性标识,而android手机上唯一性东西非常多,我们这里考虑用设备序列号
Android系统2.3版本以上可以通过下面的方法得到Serial Number,且非手机设备也可以通过该接口获取。

String serial= android.os.Build.SERIAL;

在这里插入图片描述

2.2 解决步骤

  • 修改app逻辑,加上注册方法
/**
 * 新增OneNet设备
 */
public class RegisterOneNetDeviceEntity extends BaseResponseEntity {

    public dataModel data;

    public static class dataModel{
        public String device_id;
    }

    @Override
    protected String createArgs(Object... params) {
        OneNetDeviceModel model = (OneNetDeviceModel) params[0];
        JSONObject object = new JSONObject();
        try {
            object.put("title",model.getTitle());
            object.put("auth_info",model.getAuth_info());
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return object.toString();
    }

    @Override
    protected String makeUrl() {
        return API_POST_REGISTER_DEVICE;
    }

    public String request(OneNetDeviceModel model) {
        method = HttpUtilCore.Method.Post;
        String json = requestJson(model);
        //内部消化
        return handleResponse(json, new OnResponseListener<RegisterOneNetDeviceEntity>() {

            @Override
            public void onSuccess(String json, RegisterOneNetDeviceEntity response) {
               data = response.data;
            }

            @Override
            public void onFailed(String reason) {
                Logger.d(reason);
            }

            @Override
            public void onTimeout() {
                Logger.d("请求超时");
            }
        });
    }
}
  • 用户点击注册,加上设备序列号
    @Override
    public void onInitView(Bundle savedInstanceState) {
        PreferenceUtil preference = PreferenceUtil.getInstance();
        if(!TextUtils.isEmpty(preference.getDeviceId())){
            this.onConfigConfirm();
            return;
        }

        getDefaultNavigation().setTitle("配置智能灯");
        getDefaultNavigation().getLeftButton().hide();

        etDevice.setText("Android_" + android.os.Build.SERIAL);
        etProduct.setText(preference.getProductId());
        etApikey.setText(preference.getApiKey());
    }
  • 新增成功之后,存储服务器返回的device_id
@Override
    public void register(Context context, final OneNetConfigDALEx config, final ICallBack<String> callBack) {
        if(task != null && task.getStatus()== AsyncTask.Status.RUNNING){
            task.cancel(true);
        }

        task = new SimpleTask() {

            OneNetDeviceModel device;
            RegisterOneNetDeviceEntity entity;

            @Override
            protected void onPreExecute() {
                PreferenceUtil preference = PreferenceUtil.getInstance();
                preference.writePreferences(PreferenceUtil.ApiKey,config.getApikey());
                preference.writePreferences(PreferenceUtil.ProductId,config.getProductId());

                entity = new RegisterOneNetDeviceEntity();
                device = new OneNetDeviceModel();
                device.setTitle(config.getDeviceId());
                device.setAuth_info(config.getDeviceId());
            }

            @Override
            protected Object doInBackground(String... strings) {
                return entity.request(device);
            }

            @Override
            protected void onPostExecute(Object o) {
                String result = (String) o;
                PreferenceUtil preference = PreferenceUtil.getInstance();
                if("200".equals(result)){//保存设备id
                    preference.writePreferences(PreferenceUtil.DeviceId,entity.data.device_id);
                    callBack.onSuccess("");
                }else {
                    callBack.onFaild(result);
                }
            }
        };
        task.startTask();
  • 这样就完成了手机自注册设备功能

在这里插入图片描述
这种方案有个好处就是:

  • 非常适合多个成员同时控制一组智能灯,并且不会产生掉线的情况

但是,请读者注意:

  • 如果你先注册了一次,然后卸载app,再重新注册,这个时候会失败的(原因请读者自行分析)。这个时候请到后台手动删除Android_xxxx的设备

  • App下载地址

3.解决问题点2

  • 问题点:App没有处理设备从在线状态切换成离线状态的过程,需要实时更新设备状态

3.1 解决方案

目前大概有几种方案:

  • 方案a:手机端不断轮询批量获取设备列表接口,可以设置较大的时间间隔,这个方案准确性高,但是耗费流量。目前这个方案相对靠谱
  • 方案b:esp8266端发布设备状态topic和信息,手机端订阅该topic,通过mqtt来更新状态;
  • 方案c:利用mqtt的遗嘱消息,但是这个博哥验证了OneNet的,感觉不好用。
  • 方案d:如果mqtt的遗嘱消息比较快速实时,可以考虑方案b+c的组合,个人觉得这个是比较理想的方案。(不过,目前我还没有很好实现)
  • 方案e:本项目不追求实时性,我们可以手动下拉刷新或者在activity的onshow自动刷一遍,基本上满足要求,采取该方案。

4.总结

  • 问题1:App作为一个特殊的设备,理论上也应该支持自注册功能,不应该由开发者或者用户额外去调用API调试工具创建设备,起码得简化这个流程;可以解决。
  • 问题2:App没有处理设备从在线状态切换成离线状态的过程,需要实时更新设备状态;赞未完美解决,只能兜底方案。
  • 但是,我们离产品化越来越近了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

单片机菜鸟哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值