在一个智能家居系统中,除了各种设备的自动化之外,远程管理和控制也是非常重要的一个功能。想象一下,你在外出的时候可以随时拿出手机检测房间信息。比如有没有煤气泄漏,有没有陌生人闯入等等,是不是很酷!所以在本节课中我们来学习如何做到及时通信与及时报警功能。
知识锦囊
想要实现远程通信功能最方便的方式就是通过电话,短信和移动网络功能了。在Wio LTE主控板背面集成了一块由中移物联网开发的LTE模组,就像我们的手机一样,我们只需要把SIM卡正确插入主控板,然后我们就可以通过程序控制来调用这些功能了。
将SIM卡以图示(下图一)方向插入模组的卡槽中,当SIM卡完全插入卡槽中(如下图二)我们才可以正常使用模组的功能。
实践操作
任务一:远程获取房间温湿度数据
在本任务中,我们将通过移动网络来获取安装在房间的温湿度传感器的数据。
它的原理是:将开发板连接到中国移动OneNET平台,然后开发板通过MQTT通信的方式将传感器获取的值远程发送到OneNET网站显示,然后我们就可以在OneNET上远程看到我们开发板传出的数据了。
我们一共将步骤分为3步,首先我们在OneNET注册并创建一个设备,然后将我们的开发板连接到设备,最后我们将数据发送到服务器并在页面上查看结果。
先正确插入SIM卡,连接温湿度传感器,完成硬件的准备工作:
打开OneNET的网站:https://open.iot.10086.cn/ 在右上角注册并登陆你的账号。
点击首页的“控制台”进入后台控制页面。
在控制台点击“全部产品服务”找到“多协议接入”并点击。
在多协议接入界面点击“添加产品”
在右侧弹出的界面中填写相关信息。注意红框选择需要和图片中一致,网络运营商需要选择插入Wio LTE开发板的SIM的运营商。
成功创建产品之后,在网站左侧找到“设备列表”点击右上角的“添加设备”按钮进行添加设备的操作。
在添加设备的界面正确填写信息并选择当前位置之后点击“添加”按钮,完成设备的添加。
添加完成设备后进入设备详情页。
点击“添加APIkey”然后系统会生成一个新的APIkey。此时请记住设备ID和APIkey的值,一会在后面连接设备时会用到。
然后回到主界面点击“产品概况”同样的查看并记录产品ID,一会会用到。
在界面左侧找到“数据流模板”然后添加数据流模板。
添加一个名为“TEST”的数据流名称,然后点击“添加”按钮。
之后这里会多出一个数据流模板,表示添加成功。
此时OneNET端的操作已经基本完成,接下来让我们转到代码。
首先下载安装ArduinoSerialCommand.zip库文件和DHT20温湿度传感器库文件(参考第5课),
然后打开Arduino IDE,新建一个程序文件,编写以下代码:
#include <SerialCommand.h>#include <SoftwareSerial.h>#include "DHT.h"#define DHTTYPE DHT20DHT dht(DHTTYPE);#define BAT_ENABLE 19 //Grove端口使能引脚int newval = 32; //定义变量#if defined(ARDUINO_ARCH_AVR)#define debug Serial#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)#define debug SerialUSB#else#define debug Serial#endifvoid setup() {digitalWrite(BAT_ENABLE, HIGH);//启用Grove端口pinMode(GROVE_ENABLE,OUTPUT);digitalWrite(GROVE_ENABLE,HIGH);delay(100);SerialUSB.begin(115200);LTE.begin(115200); //Serial2Serial1.begin(115200); //Grovewhile (!Serial) {;}Serial.println("SAMD MCU Ready");Wire.begin();dht.begin();pinMode(LTE_PWR,OUTPUT);pinMode(LTE_RESET,OUTPUT);pinMode(LTE_WAKEUP,OUTPUT);pinMode(LTE_ENABLE,OUTPUT);digitalWrite(LTE_PWR,HIGH);digitalWrite(LTE_RESET,LOW);digitalWrite(LTE_WAKEUP,LOW);digitalWrite(LTE_ENABLE,HIGH);Serial.println("SAMD21[1] Init OK");}void loop() {String ss = String(newval, DEC);char buf[9];//>>>>转字符串ss.toCharArray(buf, 9);float temp_hum_val[2] = {0}; //将温湿度定义为一个数组if(SerialUSB.available()){LTE.write(SerialUSB.read());}if(LTE.available()){SerialUSB.write(LTE.read());}if (!dht.readTempAndHumidity(temp_hum_val)) {SerialUSB.println(temp_hum_val[1]);}float temp_val = temp_hum_val[1];delay(2500);LTE.write("AT+CGACT=1,1\r\n");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("AT+CGACT=1,1\r\n");delay(2000);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("AT+MQTTCFG=\"183.230.40.39\",6002,\"728817855\",600,\"434575\",\"jQMUBpFbzSRe8dstkvMN87HXH70=\",0\r\n");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("AT+MQTTOPEN=1,1,0,0,0,,\r\n");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("AT+MQTTSUB=\"TEST\",1\r\n");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("AT+MQTTPUB=\"$dp\",1,0,0,23\r\n");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}int a[] = {0x03,0x00,0x14};for (int i = 0; i < 3; i++){LTE.write(a[i]);}delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("{\"TEMP\":\"");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.println(temp_val);delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("\"}");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("1");delay(1000);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("2");delay(1000);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("3");delay(1000);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("4");delay(1000);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("5");delay(1000);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("6");delay(1000);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("7");delay(1000);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("8");delay(1000);while(LTE.available()){SerialUSB.write(LTE.read());}while(1);}
在代码的77行中,将728817855替换为你的设备ID;
将434575替换为你的产品ID;
将jQMUBpFbzSRe8dstkvMN87HXH70=\替换为你的APIkey。
然后上传代码,接下来打开串口监视器查看程序运行状态:
为了防止程序运行过快出错,所以程序中加了很多2.5秒的延时,所以打开串口监视器之后需要等待几秒才可以看到数据持续输出。

如果在串口监视器中发现下图的报错,那么代表网络初始化出错。
解决方法:保持串口监视器打开的情况下,断开Wio LTE开发板的数据线,然后再重新连接数据线;之后关闭串口监视器再重新打开串口监视器,等待串口监视器中返回ok。
程序运行成功之后打开OneNET网站,在设备列表中点击数据流,进入数据流展示界面。
如果发送成功的话,你会在这里看到来自传感器的数值。
如果你想要在OneNET平台上看到其他传感器的数值,你可以先在程序中加入获取传感器数值的代码,然后将示例代码的第109行中的“TEMP”改为你的传感器数值名称, 在第115行中把“LTE.println(temp_val)”的“temp_val”改为你的传感器数值。
任务二:向手机自动报警异常信息
除了像任务一一样主动获取数据的方式之外,我们还可以被动获取一些关键信息,比如有人闯入房间,煤气泄漏或者发生火灾。在本任务中,我们将制作一个自动报警装置,当检测到危险信息,则开发板自动发短信到指定手机号提醒我们。
首先是硬件部分,按照图示正确连接PIR人体红外传感器。
然后打开Arduino IDE,新建一个程序文件,编写以下代码:
#include <SerialCommand.h>
#include <SoftwareSerial.h>
#define BAT_ENABLE 19 //Grove端口使能引脚
#define PIR_SENSOR 0 //PIR传感器连接到D0接口
int newval = 32; //定义变量
void setup() {
SerialUSB.begin(115200);
LTE.begin(115200); //Serial2
Serial1.begin(115200); //Grove
SerialUSB.println("SAMD MCU Ready");
digitalWrite(BAT_ENABLE, HIGH);//启用Grove端口
pinMode(PIR_SENSOR, INPUT);//设置PIR传感器为输入模式
pinMode(GROVE_ENABLE,OUTPUT);
digitalWrite(GROVE_ENABLE,HIGH);
pinMode(LTE_PWR,OUTPUT);
pinMode(LTE_RESET,OUTPUT);
pinMode(LTE_WAKEUP,OUTPUT);
pinMode(LTE_ENABLE,OUTPUT);
digitalWrite(LTE_PWR,HIGH);
digitalWrite(LTE_RESET,LOW);
digitalWrite(LTE_WAKEUP,LOW);
digitalWrite(LTE_ENABLE,HIGH);
SerialUSB.println("SAMD21[1] Init OK");
}
void loop() {
String ss = String(newval, DEC);
char buf[9];//>>>>转字符串
ss.toCharArray(buf, 9);
if(SerialUSB.available()){
LTE.write(SerialUSB.read());
}
if(LTE.available()){
SerialUSB.write(LTE.read());
}
delay(2500);
if(digitalRead(PIR_SENSOR)){ //如果检测到有人靠近
LTE.write("AT+CMGF=1\r\n");
delay(2500);
while(LTE.available()){
SerialUSB.write(LTE.read());
}
LTE.write("AT+CMGS=\"10086\"\r\n");
delay(2500);
while(LTE.available()){
SerialUSB.write(LTE.read());
}
// LTE.write(buf);//发送变量
LTE.write("Someone broke into the room!");//发送字符串
LTE.write(0x1A);
delay(2500);
while(LTE.available()){
SerialUSB.write(LTE.read());
}
while(1);
}
}
注意需要将代码第48行中的“10086”改为接收信息的手机号。你也可以在第55行更改要发送的字符串,或者取消54行的注释来发送变量。
上传成功程序之后,你可以在串口监视器中看到信息发送状态。
指定手机号收到的信息:
思维拓展
Wio LTE除了短信与移动网络通信的功能之外,我们还可以利用该开发板来实现打电话的功能。让我们来看看怎么做吧!
首先将套件中的喇叭安装在开发板上,注意Wio LTE有2个JST接口,分别是Speaker和电池接口,仔细观察接口旁边的丝印,不要接错在电池接口。
然后编写以下程序:
#include <SerialCommand.h>
#include <SoftwareSerial.h>
#define BAT_ENABLE 19 //Grove端口使能引脚
int a = 10;
void setup() {
SerialUSB.begin(115200);
LTE.begin(115200); //Serial2
Serial1.begin(115200); //Grove
SerialUSB.println("SAMD MCU Ready");
digitalWrite(BAT_ENABLE, HIGH);//启用Grove端口
pinMode(GROVE_ENABLE,OUTPUT);
digitalWrite(GROVE_ENABLE,HIGH);
pinMode(LTE_PWR,OUTPUT);
pinMode(LTE_RESET,OUTPUT);
pinMode(LTE_WAKEUP,OUTPUT);
pinMode(LTE_ENABLE,OUTPUT);
digitalWrite(LTE_PWR,HIGH);
digitalWrite(LTE_RESET,LOW);
digitalWrite(LTE_WAKEUP,LOW);
digitalWrite(LTE_ENABLE,HIGH);
SerialUSB.println("SAMD21[1] Init OK");
}
void loop() {
if(SerialUSB.available()){
LTE.write(SerialUSB.read());
}
if(LTE.available()){
SerialUSB.write(LTE.read());
}
delay(2500);
LTE.write("AT+CGACT=1,1\r\n");
delay(2500);
while(LTE.available()){
SerialUSB.write(LTE.read());
}
LTE.write("AT+SETVOLTE=1\r\n");
delay(2500);
while(LTE.available()){
SerialUSB.write(LTE.read());
}
LTE.write("AT+CLIP=1\r\n");
delay(2500);
while(LTE.available()){
SerialUSB.write(LTE.read());
}
LTE.write("ATD 10086\r\n");
delay(2500);
while(LTE.available()){
SerialUSB.write(LTE.read());
}
while(1);
}
注意将代码中第54行的“10086”改为接收的手机号码。上传成功之后打开串口监视器观察返回信息是否正常,如果返回ok则电话成功拨出,如果没有返回信息或者返回错误,那么在打开串口监视器的情况下断开数据线,然后重新连接数据线,再关闭串口监视器并重新打开串口监视器即可解决。

