``
-----------------------------防吞分隔线-----------------------------
拿到钛极小龟开发板将近三周,陆陆续续做了一些实验,现在对这块板子了解的也比较全面了,在此非常感谢电子发烧友网提供的试用机会。
今天做一下结项实验,总结展示这段时间的学习成果。
实验名称:钛极小龟阿里云物联网云端通讯及Android APP控制
实验目的:使用Android App,通过阿里云物联网,实现与钛极小龟开发板的云端通讯及控制。
实验效果:Android App实时显示开发板环境参数, 且可点击按钮远程通过继电器控制外设台灯的亮灭. 效果演示如下(不太清晰,可看文末视频):
1. 实验概述
1.1 数据传输
以阿里云端做为数据中转,通过规则引擎转发, 实现控制端(安卓APP)与开发板的数据交互。数据传输流程如图:
1.2 云端设置
因上一篇贴子已有对阿里云端设置进行详细说明,此处仅作简要介绍。
1.2.1 创建产品及设备
在阿里云控制台物联网模块下创建一个产品,并在此产品下创建两个设备tikit-demo(开发板)和controller(安卓控制端), 同时记录相关参数(ProductKey,DeviceName,DeviceSecret)
1.2.2 创建转发规则
阿里物联网限制同一台设备同时只可存在一个连接, 因此APP控制端与开发板端无法使用同一个MQQT账号. 为实现开发板与安卓APP数据交互的目的,需要在规则引擎创建两条转发规则,分别是数据从开发板转发至APP及指令从APP转发至开发板。
1.3 数据格式
数据与指令因转发需要,采用Json格式。Json结构参数说明如下:
2. 实验材料
本次实验用到的工具材料有:钛极小龟开发板,安卓手机,USB充电头,USB小台灯(也可换为其他外设如小风扇),遥控器,USB线及杜邦线。如下图(洞洞板是为了方便与开发板继电器连接而焊接的引脚,仅用于连接中转,上面的两个模块请无视):
3. 实验步骤
3.1 模块连接
开发板继电器一端连接电源端,一端连接USB小台灯,以便于进行控制。连接方式如图:
3.2 APP连接
打开APP,输入controller设备的参数(ProductKey,DeviceName,DeviceSecret),并点击连接按钮。APP内部会根据相应算法,计算出MQQT用户名与密码, 网络正常的话会连接阿里云服务端并跳转至主界面,此时因开发板离线,故参数均为空。
3.3 开发板通讯
开发板上电,LED闪烁表示正在连接WiFi,连接成功后LED长亮,并将相关参数显示在LED并通过网络上传至云端。APP实时获取参数并显示,如图:
3.4 数据传输
用手掌遮盖开发板,传感器接收到的光照大大减少,APP端显示当前亮度为4流明。
手指按在开发板触摸按钮上,APP实时显示触摸状态为“有”,手指移开后状态消失。
按下开发板Key/F键,APP显示按钮为“有”,弹起后状态消失
用红外遥控器对准开发板按下按钮,APP实时显示遥控器所按下的键码。
3.5 云端远程控制
点击APP端按钮,按钮状态变更为“已开启”,此时开发板继电器发出咔嗒声吸合,USB小台灯通电开启,APP端显示的亮度增加至177流明。
再次点击APP控制按钮,状态变更为“已关闭”,此时继电器发出咔嗒声断开,台灯断电关闭,APP端显示的亮度恢复之前的45流明。
注意事项:
1.继电器应连接NO(常开)与GND
2.开发板多线程受性能影响,有时不那么准确,可能会出现红外接收线程抢占主线程情况,导致结果不准确
3.开发板本身有一定发热,导致DHT11测量到的温度不是准确室温
实验完毕,本次实验实现了通过云端将开发板检测到的环境参数显示在手机APP中,同时可用手机APP控制开发板连接的外部设备。达到实验目的。
实验过程视频:
[media]http://v.youku.com/v_show/id_XMzkzNjc4MDYzNg==.html?spm=a2h3j.8428770.3416059.1[/media]
关键代码(Android):
- public class MainActivity extends Activity implements MonitorService.ChangedListener {
- public MonitorService monitorService;
- private ToggleButton toggleSwitch;
- private TextView txtViewLumen = null, txtParaTemp, txtParaHumi, txtParaVice, txtParaTouch, txtParaKey, txtParaRed;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- System.err.println("onCreate");
- toggleSwitch = (ToggleButton) findViewById(R.id.toggleButtonLED);
- txtViewLumen = (TextView)findViewById(R.id.lighting);
- txtParaTemp = (TextView)findViewById(R.id.txtParaTemp);
- txtParaHumi = (TextView)findViewById(R.id.txtParaHumi);
- txtParaVice = (TextView)findViewById(R.id.txtParaVice);
- txtParaTouch = (TextView)findViewById(R.id.txtParaTouch);
- txtParaKey = (TextView)findViewById(R.id.txtParaKey);
- txtParaRed = (TextView)findViewById(R.id.txtParaRed);
- MyApplication app = (MyApplication) getApplication();
- monitorService = app.getMonitorService();
- monitorService.registerChangedListener(this);
- /**
- * 开关控制事件
- */
- toggleSwitch.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- try {
- monitorService.switchControl();
- }
- catch (Exception ex){
- ex.printStackTrace();
- }
- }
- });
- }
- /**
- * 退出时断开连接
- */
- @Override
- protected void onDestroy() {
- System.err.println("onDestroy");
- monitorService.unregisterChangedListener(this);
- monitorService.disconnect();
- super.onDestroy();
- }
- /**
- * 收到数据消息
- * 更新界面
- */
- @Override
- public void onDataChange(final int state, final int lumen, final String other) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if(state == 0)
- toggleSwitch.setChecked(false);
- else
- toggleSwitch.setChecked(true);
- //Log.d("Tipos", "State: " + state);
- txtViewLumen.setText(Integer.toString(lumen) + " 流明");
- if(other.length() > 10) {
- String[] arys = other.split(";");
- if(arys.length >= 6) {
- txtParaTemp.setText(arys[0] + " ℃");
- txtParaHumi.setText(arys[1] + " %");
- txtParaVice.setText(arys[2]);
- txtParaTouch.setText("0".equals(arys[3]) ? "-" : "有");
- txtParaKey.setText("0".equals(arys[4]) ? "-" : "有");
- txtParaRed.setText("N".equals(arys[5]) ? "-" : arys[5]);
- }
- }
- }
- });
- }
- }
关键代码(开发板):
- public static void main(String[] args) {
- try {
- TiWiFi obj = TiWiFi.getInstance();
- obj.startup(30);
- TiDNS.getInstance().startup();
- System.out.println("Wi-Fi Connect. IP: " + obj.getAddress());
- } catch (IOException ex) {
- System.out.println("Wi-Fi Connect Failed.");
- ex.printStackTrace();
- return;
- }
- try {
- // GPIO资源分配,GPIO0的PIN2/3/4/5脚
- TiGPIO gpio0 = TiGPIO.open(0, 2, 3, 4, 5);
- // I2C主机总线资源分配,I2CM0
- TiI2CMaster i2cm0 = TiI2CMaster.open(0);
- // ADC资源分配,ADC0的CH0通道
- TiADC adc0 = TiADC.open(0, 0);
- /* ---资源绑定--- */
- // I2C主机总线资源PORT0与屏幕对象绑定,屏幕地址:0x3C
- TiOLED_UG2864 oled = new TiOLED_UG2864(i2cm0, 0x3c);
- // I2C主机总线资源PORT0与照度计BH1750对象绑定,默认地址:0x23
- TiBH1750 bh1750 = new TiBH1750(i2cm0);
- // GPIO总线资源PIN2与继电器对象绑定
- TiRelay1CH relay = new TiRelay1CH(gpio0, 2);
- // GPIO总线资源PIN3与温湿度传感器DHT11绑定
- TiDHT dht11 = new TiDHT(gpio0, 3);
- // GPIO总线资源PIN4与触摸按钮对象绑定,触发电平:高电平
- TiButton touch = new TiButton(gpio0, 4, true);
- // GPIO总线资源PIN5与红外解码对象绑定
- TiVS1838BNEC vs1838b = new TiVS1838BNEC(gpio0, 5);
- // 获取键盘实例并设置键盘事件监听对象
- TiKeyboard keyboard = TiKeyboard.getInstance();
- keyboard.setEventListener(new KeyboardListener());
- // 设置ADC参考电压及分压倍数
- adc0.setRefVoltageValue(1.0, 2);
-
- /* ---资源使用--- */
- // 屏幕开启并清屏
- oled.turnOn();
- oled.clear();
- oled.print(0, 0, "AliYun&Android APP!");
- touch.setEventListener(new TouchListener(relay));
- vs1838b.setEventListener(new IRDecodeListener());
- Thread.sleep(2000);
-
- MqttConnectOptions connOpts = new MqttConnectOptions();
- connOpts.setCleanSession(true);
- connOpts.setKeepAliveInterval(80);
- connOpts.setUserName(USER_NAME);
- connOpts.setPassword(USER_PASS);
- connOpts.setAutomaticReconnect(true);
-
- MqttClient mqttClient = new MqttClient(BROKER, CLIENT_ID);
- mqttClient.SetMqttClientListener(new MqttClientListener() {
-
- @Override
- public void unsubscribeCompleted(Object arg0, int arg1, String arg2, int arg3) {
- //System.err.println("unsubscribeCompleted");
- }
-
- @Override
- public void subscribeCompleted(Object arg0, int arg1, String arg2, int arg3) {
- //System.err.println("subscribeCompleted: " + arg2);
- }
-
- @Override
- public void publishCompleted(Object arg0, int arg1, String arg2, int arg3) {
- //System.err.println("publishCompleted: " + arg2);
- }
-
- @Override
- public void onMqttConnectSuccess(Object arg0) {
- //System.err.println("onMqttConnectSuccess");
- }
-
- @Override
- public void onMqttConnectFailure(Object arg0, int arg1) {
- //System.err.println("onMqttConnectFailure");
- }
-
- @Override
- public void messageArrived(Object arg0, String arg1, byte[] payload) {
- if("cmd".equals(arg1.substring(arg1.length() - 3))) {
- String cmd = new String(payload);
- cmd = cmd.substring(11, cmd.length() - 2);
- //System.err.println("Received Cmd: " + cmd);
- try {
- if("OPEN".equals(cmd)) {
- relay.turnOn();
- System.err.println("Relay Turn On.");
- } else if("CLOSE".equals(cmd)) {
- relay.turnOff();
- System.err.println("Relay Turn Off.");
- }
- }catch(Exception e) {}
- }
-
- }
-
- @Override
- public void connectionLost(Object arg0) {
- //System.err.println("connectionLost");
- }
-
- @Override
- public void connectComplete(Object arg0, boolean arg1) {
- //System.err.println("connectComplete");
-
- }
- });
- try {
- mqttClient.connect(connOpts, mqttClient);
- } catch (Exception e) {
- e.printStackTrace();
- System.err.println("Connect failed.");
- }
-
- mqttClient.subscribe(TOPIC_CMD, 1);
-
- while(true) {
- // 启动温湿度测量
- dht11.measure();
- // 获取温湿度值
- double temp = dht11.getTemperature();
- double humi = dht11.getHumidity();
- int lux = bh1750.readLightLevel();
- int val = adc0.getRawValue(0);
- String sensorState = "{ switch: " + (relay.isTurnedOn() ? "1" : "0") + ",lumen: " + lux + ",other: '" + temp + ";" + humi + ";" + val + ";" + touchState + ";" + keyState + ";" + vs1838State + "' }";
-
- oled.print(1, 0, "Temp:" + temp + " C ");
- oled.print(2, 0, "Humi:" + humi + " % ");
- oled.print(3, 0, "Light:" + lux + " ");
- vs1838State = "N";
- try {
- System.out.println("Send to Cloud: " + sensorState);
- mqttClient.publish(Main.TOPIC_DATA, sensorState.getBytes(), 0, false);
- Thread.sleep(1200);
- } catch (Exception e) {}
- }
-
- } catch (Exception ex) {
- ex.printStackTrace();
- } finally {
- try {
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
``