Android 物联网APP
提示:该工程是连接阿里云物联网平台的模板代码,将MQTT连接、JSON数据的订阅发布等操作封装,并且能够迅速将获取到的数据显示到手机界面上。使用了Servier进行网络连接的逻辑操作,并且使用自定义控件,绑定对用标识符的数据对象,实现了数据自动实时更新等操作,并且显示的自定义控件还可以修改显示的样式,可以加载gif图片等。
文章目录
- Android 物联网APP
- 前言
- 一、文件列表
- 二、工程详解
- 1.执行逻辑
- 2.核心代码
- 三、简单使用
- 总结
前言
可以直接看第三步简单使用
如果不了解MQTT连接或是JSON数据处理、物联网平台相关操作的,可以在哔哩哔哩看太极创客的视频进行MQTT的理论学习。
学习这些知识只是让你能够工程中的逻辑,如果是只需呀使用模板代码也可以直接跟着教程进行操作,只需要有一点java和Android基础。
提示:以下将阿里云物联网平台简称“云平台”
一、文件列表
这个是整个项目的文件
app和manager包:
其中的java代码是云平台中的java示例代码中连接云平台的代码,以及云平台下行回调和连接状态回调等,我们暂时可以不用太过关注。
my_enum包:
其中包含了云平台数据传输中的KEY值,以及对KEY值的描述:
以及MQTT连接后,数据订阅和发布的主题字符串,通过调用枚举类型,然后调用getTopic方法根据对应格式将字符串拼接,获取对应的Topic,用于对数据的发布和消息的订阅:
myfragment包:
其中包含了Android碎片文件,用于通过碎片加载在活动上,将界面显示到手机屏幕。同时,通过底部菜单栏(BottomNavigationView)或者其他的方式进行碎片的切换。
所有的碎片继承于BaseFragment类,然后重写initView()方法用于加载碎片中的控件,重写initData()方法用于加载数据,将数据与控件进行绑定。绑定之后,就能自动更新数据。
Fragment1 - Fragment3都是写好的碎片模板,对应了MainActivity中的底部菜单栏的三个菜单。
LoginFragment是写的一个超级简单的登录界面,模拟用户登录。
myitem包
其中有自定义的控件LineChartItem(折线图控件),SensorItem(硬件设备数据显示控件),以及Item(硬件设备数据源)。
LineChartItem是使用MPAndroidChart工具包进行绘制的一个线型图,可以通过设置对应的List数据,显示出对应的图表。并且可以动态添加数据,并且跳转到最新数据的点的位置。目前只编写了最简单的折线图,如果需要修改,可以参考MPAndroidChart的详细使用——LineChart折线图(一)。
Item用于存储云平台下发的数据。当Android软件连接到云平台后,会返回一个较长的JSON数据,其中包括了物模型的相关数据(我们通过物模型为硬件设备的抽象载体,当然物模型只是作为一个规范,没有物模型依旧能够进行通信)。
我们将这些JSON数据进行提取,变成对应的java对象。
上图中,第二个构造器传入一个JSON物模型数据,然后对数据进行解析。最后调用第一个构造器,将解析的参数传入,构建一个数据对象,并将数据对象添加到上述的集合当中。
集合可以在本项目的任何类中调用,通过云平台的标识符获取这个物模型的信息(由于当前集合是在连接阿里云成功后获取数据进行初始化,所以务必在使用前判空)。
下图是Item的两个构造器:
SensorItem 是用于显示物模型实时数据的自定义控件。有数据绑定、数据更新等方法可以调用(本项目中只需绑定Item数据,不需要自己调用更新)。并且在数据绑定和数据更新的时候,可以根据对应的设备类型进行对应的UI展示和数据处理。
例如,我们可以将数据分为传感器和执行器。云平台并没有标识这个物模型是传感器还是执行器,怎么办呢?
我暂时想到了两种解决方法:
1、通过云平台的标识符设置。因为云平台的标识符仅用于接收、发布数据,我暂时还没有发现其他的用处,那为何不能将其分为不同的字段呢。
我们拿单个智能光照系统举例
传感器:sensor_light - 光照传感器
执行器:actuator_led - LED灯
这样,我们就区分了传感器和执行器。在使用自定义控件构建传感器,绑定Item数据时,
我们可以显示传感器的名字、实时数据、单位等,并且在自定义控件实时更新时,
可以直接在TextView中设置数据的值+单位,用来显示数据。
在通过自定义控件构建执行器时,由于执行器的值一般只有0(关)和1(开),我们有多种选择:
1、显示0/1用于表示执行器的开关,但是不便于他人使用(SensorItem更新数据时直接设置)。
2、通过判断是执行器,然后在调用Item中的getValueUint()时(这个方法是返回数据值+单位),
将0/1更换为“开”或“关”再返回。然后显示到自定义控件上(Item中获取数据的方法中修改)。
3、在绑定数据时,将原先的用于显示传感器数据的TextView隐藏。然后将隐藏的ImageView或者GifImageViewe显示。然后设置好初始UI资源。在数据更新时,将获取的0/1进行if判断,
然后根据值替换成不同的图片或者动图素材。
以下 是SensorItem中绑定数据和数据更新的代码,绑定数据中,我们可以进行一些初始化操作,监听事件的注册,显示以及隐藏一些控件等。而在数据更新代码中,我们可以判断设备类型,通过不同的方式将数据展示到手机界面上。
并且,我们可以直接将特定的标识符进行特定的处理,例如将Sensor_led的UI改成灯泡,当数据为0时,修改成灯泡灭的图片资源,反之则设置灯泡亮的图片资源(指定标识符设置资源、硬件较少等情况可以忽略设备类型的判断)。
那我们如何将标识符转换为设备类型呢?
可以往上看Item的两个构造器,上面已经通过字符串截取将标识符中表示设备类型的字段提取并且调用另外一个构造器设置好了。
根据规范设置标识符的好处二:用于区分不同的硬件子系统
例如,现在有一个智能家居系统。其中又包括:智能光照,智能安防,智能门禁,智能监控,智能厨房、智能浴室等(随便举例的)。那么多的系统和传感器、执行器设备,我们不可能将其全部使用RecyclerVIew平铺在一个界面当中,肯定要分页面展示。
智能光照系统:
sensor_light_led 第一个字段是传感器,第二个字段是light子系统,第三个字段是led灯
智能门禁系统:
actuator_door_door 第一个字段是执行器,第二个字段是door子系统,第三个字段是控制门的执行器
分页面展示的话,通常是编写一个页面通用模板,然后根据页面布局加载不同的设备UI(不可能每个子系统都手写一个单独的页面吧)。
在不同的页面(通常可以是Activity或者Fragment),我们可以通过编写一个通用的RecyclerView对设备UI进行列表显示(虽然很丑,但是省事),也可以在不同的页面中直接通过将自定义控件添加到布局文件中,然后再页面代码实例化,设置对应的数据资源。
并且由于这是个模板,可以通过标识符判断有多少个子系统,然后将子系统通过列表显示出来,然后再通过设备子系统标识,将对应的设备显示到对应的子系统中(点击对应的子系统,加载对应设备界面)。
这样设置的话,就可以通用于不同情况的IOT硬件设备,而不需要做太多重复的更改,并且规范标识符命名。
2、通过云平台物模型的单位。
因为物模型中,bool类型和enum类型都没有数据单位,然后这些类型又是适合表示执行器数据(不考虑数组、结构体、文本等)。
所以,我们区分设备类型的时候,可以判断这个设备对象是否有单位。如果有单位,就是传感器,反之则是执行器(前提是云平台物模型规范设置,设置合理正确)。
其余的和方法一同理,这里不过多赘述。
utils包
这里都是一些我编写代码时,为了偷懒而封装的简单工具类。
功能如类名一样,对话框工具类、状态栏通知工具类、订阅和发布工具类(MQTT的订阅和发布,云平台用的)、TTS文本转语音工具类。
这些工具类都是一些非常基础的Android知识,如果需要详细了解,或者自己添加自己所需的,可以自行搜索对应的教程讲解等。
接下来就是我们的活动和服务:
BaseActivity:所有的Activity都继承这个类,原先是将MQTT连接操作放在这个类中。然后有获取硬件设备是否在线信息、监测网络是否连接等操作。(只是为了后序创建Activity比较规范,每个Activity都能监测上述信息)
MainActvity:启动MyService,初始化底部菜单栏,通过Timer和TimerTask初始化定时任务,构建碎片和加载碎片等。
MyService:这个是后序改进的时候添加的。因为发现通过使用服务连接云平台,会更加稳定。并且再服务中可以开启前台服务。
这个服务类中存储了连接云平台的信息,我们这个工程采用的是云平台一机一密的连接方式。关于设备接入相关,可以参考云平台连接手册。
这个方法用于调用连接函数,并且重写连接回调方法,接收连接返回的数据。
连接成功后,就将返回的JSON数据提取后,传入initData()方法中进行Item对象的创建。
这个数据处理开启了一个新的线程,防止主线程出现延迟。
最后是OnLine,就是一个自定义控件,用于显示硬件设备是否在线的控件。现在暂时没有使用了。
二、工程详解
1.执行逻辑
软件执行:
云平台数据下发:
断线重连机制:
2.核心代码
- 数据自动更新
提供一个静态方法,对所有的UI数据对象,调用其update()进行更新显示的数据。
/**
* 根据数据源集合更新所有的UI数据
* 用于接收到云平台下发的数据后,将接收到的数据进行解析
*
* 然后将更新好的数据集合传入,对显示在屏幕上的UI进行自动更新
*
* @param activity 上下文
* @param mapList 管理着数据源的集合
*/
public static void updateDevice(Activity activity, LinkedHashMap<String, Item> mapList) {
for (SensorItem sensorItem : deviceItemView) {//遍历UI集合
Item item = mapList.get(sensorItem.getIdentifier());//根据标识符获取对应的数据源
if (item == null) {//新的数据集合中没有这个数据,则跳过这个UI的更新
continue;
}
activity.runOnUiThread(new Runnable() {//否则在UI线程中调用更新UI的方法更新对应的UI
@Override
public void run() {
sensorItem.update(item.getValueUnit());//调用更新当前UI的方法,将对应的数据源传入,修改UI控件数据
}
});
}
}
- SubAndPubUtils工具类
提供了订阅、取消订阅、发布等方法。并且提供了发送的数据字符串封装的方法,在发布数据时,只需传入Pair数组对象,就会自动转换成云平台对应的JSON字符串发送。
发布和订阅的方法,云平台手册中都有,这里就展示一下数据的处理,看起来非常简单,就是字符串拼接的基础代码。
- 数据的解析与存储
MQTT连接云平台成功后,将返回的输入传入此方法进行提取,然后创建Item对象。
通过Item中这两个构造器,将数据进行解析、存储、并添加到集合中管理。
- 云平台数据流转
前提是设备订阅了对应的主题。
这里简单的提了下,很多东西在文件列表介绍中就讲解了。
三、简单使用
这里介绍工程模板的简单使用,加快开发速度,并且零基础也能掌握
- Android Studio的下载
编译器的下载,已经有很多优秀的文章,阐述了详细的过程。
Android Studio安装和使用教程(全文图解)
- 阿里云账号的注册和物联网平台的开通
这个比较简单,注册账号后,在右上角搜索栏搜索物联网平台,然后进入开通(开通需要实名)。
开通成功后,会有一个公共实例。
如果没有的话,可以切换地区看看。
进入公共实例后:
由于云平台已经有了更加规范的教程文档,这里就不过多赘述。
- APP设备上线
我们创建好产品和设备后,打开代表APP端的设备。
然后我们打开工程文件,等待更新配置后。
打开app->src->main->java,然后打开其中的MyService文件。
运行这个项目,等待显示连接成功,然后回到阿里云物联网平台设备列表。
我们可以看到,未激活的设备现在显示在线。
- 数据添加与显示
布局文件中添加控件
java碎片中初始化布局,并且绑定数据
这个时候,我们就将UI显示到手机界面上了。运行代码,手机会先进入一个登录界面。
这个是之前写的简单登录界面,账号:admin密码:123456。也可也自己在代码中修改账号密码。
登录后就是这个界面,这是我们刚刚添加的一个自定义控件。
我们并没有做其他的操作,只是绑定了Item数据,控件就自动显示了物模型的名字。
现在还没有接收到数据,所以显示的是0,单位是摄氏度。
上面的数据和我们云平台定义的物模型相同。
由于我没有硬件设备,所以选择使用云平台提供的设备模拟器,用来模拟硬件设备的数据发送操作。
在硬件数据发送之前,必须确保云产品流转规则已经设置正确。
点开设备模拟器,选择模拟硬件设备,并且选中属性上报。
我们模拟温度上报,上报数据为30℃。
这个时候,手机上的数据也立马更新了。
然后,我们还要测试MQTT发布功能。
SubAndPubUtils.publish(MyService.deviceInfo, Topic.POST.getTopic(Topic.MODE_1), 0, false, MainActivity.activity,
new Pair<String,String>("temp","50"));
我们只需通过上面的一行代码,就能将数据发布到云平台对应上。
发布的数据标识符是“temp”,值是50。我们可以看到云平台对应的设备物模型已经有数据显示了。
这个就是简单的模板使用教程,解决了与硬件数据的通信。
这里的测试只是简单的对数据进行了接收,数据的发布操作只需要调用SubAndPubUtils工具类中的方法即可实现。
还有更多的功能,如在线注册账号、动态更新数据图表、动态图片、语音转文字、通知警告等,需要自己探索。
并且,在网上也有更加详细的教程,这里由于篇幅原因,就不过多介绍。
总结
工程代码私聊我即可领取
这个工程模板是为了开发简单的IOT应用减少一些不必要的代码编写,实现简单的功能。帮助有相关兴趣和需求的朋友参考学习。可能在版本适配等方面还不是做的很好,如果有需要改进的地方或者问题欢迎评论区留言讨论!