合宙Air202模块连接阿里云物联网平台收发数据

用到的GPRS模块:合宙Air202用到的物联网平台:阿里云

GPRS模块对接阿里云物联网平台,对于新手来说还是很有难度的。在这里,我将使用合宙air202模块,连接阿里云物联网平台,最终使用自己的阿里云服务器来进行数据的双向通信。


一、阿里云物联网平台创建新设备
1、登录阿里云系统,进入阿里云物联网控制台
2、创建产品,选择高级版,输入产品名称,节点类型选择“设备”,设备类型选择“无”,数据格式选择“Alink JSON”,是否接入网关选择“否”,确认
3、进入刚刚创建的产品,添加设备,输入设备名称DeviceName,建议以无线网络模块的IMEI序列号来命名设备以避免重复,保存后,物联网系统会自动生成该设备证书,包括三个数据,如下所示:
 

二、无线网络模块连接阿里云物联网平台
阿里云物联网平台与设备端支持MQTT通信协议,因此在这里建议无线网络模块采用MQTT协议连接阿里云物联网平台。
MQTT通信协议的底层是TCP通信,因此只要无线模块支持TCP通信,原则上就可以TCP基础上移植MQTT,然而MQTT的协议自己移植的话过于复杂,因此各大无线模组供应商与阿里云合作,纷纷推出了内嵌了阿里云物联网通信协议的通信模组,例如这里使用的是AIR202模组。
air202模组是2G模组,具有较高的性价比。
1、拿到AIR202模组,先确认其固件是否是支持连接阿里云物联网平台的版本,方法是发送AT+CGRM,模块会返回当前固件版本,例如:AirM2M_V5509_AT_S_SSL。只有版本尾号为SSL的固件版本才支持接入阿里云物联网平台。
2、接下来,使用串口助手向air202依次发送一下AT指令
(1)AT //必须发送大写的AT,用来与模组进行波特率的同步。
(2)AT+CGMR//查看模块固件版本,检查尾号是否为SSL,若尾号不是SSL,则需要先使用合宙的LuaTool工具先更新固件,如下图所示:
 
(3)AT+CGATT?  //查看GPRS业务附着情况,附着成功返回1,若返回0则肯定不能联网
(4)AT+SAPBR=3,1,"CONTYPE","GPRS"  //设置网络参数
        AT+SAPBR=3,1,"APN","CMIOT" 
        AT+SAPBR=1,1
(5)AT+CGATT? //检查网络附着情况
(6)AT+HTTPINIT //使用http业务之前,先初始化http协议栈
(7)AT+HTTPPARA="URL","https://iot-auth.cn-shanghai.aliyuncs.com/auth/devicename"  //设置http参数
        AT+HTTPPARA="USER_DEFINED","Content-Type: application/x-www-form-urlencoded"
        AT+HTTPDATA=112,20000  //注意这里的数字112是下面一条数据的总字节个数
(8)productKey=a1jRE6oEtOv&sign=773c0feaab4109a153cf07f3dcef3356&clientId=869300031656865&deviceName=869300031656865
        productKey是阿里云物联网平台系统自动为你创建的产品产生的一个参数。如下所示:
 

      clientId与deviceName在这里设置为相同的数据,来自物联网平台用户添加设备时输入的设备名称,例如这里都是869300031656865,如下图所示:
 
    sign参数的来头就稍微复杂了一点,它是使用hMacMd5算法计算出来的一个哈希值。
前期测试,可以使用现成的工具来进行计算,例如使用一个在线计算器,链接:http://tool.oschina.net/encrypt?type=2
界面如下所示:
 
在上面的小工具输入明文为:clientId862991419835241deviceName862991419835241productKeyb1KCi45LcCP
注意,输入的明文里的clientId与deviceName应该与被注册的设备信息保持一致,productKey应与被注册的产品信息一致。检查一下,不要有多余的空格符。
这里要注意下,上面小工具需要输入一个密钥,该密钥为被注册的这个设备的DeviceSecret,如下图所示:
 
最终计算出一个哈希值,该值就是上面步骤(8)中的sign。
(9)AT+HTTPACTION=1 //http方式激活,该AT指令发送后稍微等几秒,模块回复+HTTPACTION: 1,200,128
(10)AT+HTTPREAD //查询http数据响应,一切正常的话,此时模块应该返回与阿里云物联网平台进行鉴权后的数据结果,其中包括iotId、iotToken和success成功提示
(11)AT+HTTPTERM //结束http服务
(12)AT+MCONFIG="869300031656865","这里输入上面步骤10返回的iotId","这里输入上面步骤10返回的iotToken"  //设置MQTT相关参数
         这里注意,每次执行步骤10后获取到的iotToken值都不一样,都需要重新更新步骤12中的iotToken。
(13)AT+SSLMIPSTART="这里应该是你产品的的ProducKey.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883   
    //例如AT+SSLMIPSTART="a1jRE6oEtOv.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883,这条指令发送完后要等几秒,模块回复“CONNECT OK”
(14)AT+MCONNECT=1,300 //客户端向服务器请求会话连接,返回CONNACK OK说明连接成功
(15)AT+MSUB="/a1jRE6oEtOv/869300031656865/user/get",0  //这条指令用于订阅一个topic,请参考自己平台下某个设备的可用topic进行修改,若            订阅成功系统返回“SUBACK”。
截止到此,采用air202的设备端就已经成功与阿里云物联网平台进行了mqtt长连接。
此时从阿里云物联网平台查看设备,会发现该设备处于“在线”状态,如下所示:
 

三、设备端发送数据至服务器设备端与阿里云物联网平台成功连接后,设备端就可以向平台的某个具备发布权限的Topic发送数据了,例如在这里,设备将向/a1jRE6oEtOv/868575026616807/user/update发布数据。

想要发布的数据为JSON格式如下所示:
{
  "cmd":"get one code"
}
然而,在使用AT指令将JSON格式的数据发送到模组时,需要对上面的JSON格式数据字符串进行相应的改变,方法是将双引号“修改为\22,
因此需要发送的AT指令为:
AT+MPUB="/a1jRE6oEtOv/868575026616807/user/update",1,0,"{\22cmd\22:\22get one code\22}"
数据发送成功后,模组会返回:“PUBACK”,这说明阿里云物联网平台已经收到数据,此时我们登录阿里云物联网平台,进入该设备所对应的产品类目下,查看“日志服务”-->"上行消息分析",可以看到通信成功的界面,如下所示: 
然而,虽然物联网平台能够接收到来自设备端上传的数据,但是我们的服务器根本是不知道设备发来的是什么数据,想要让设备端上传的数据能够发送到自己的服务器,则中间必须要用到阿里云物联网的中间件,其实就是一个阿里云的数据转发中间件,
该中间件可以按照用户需求对数据做过滤处理,并最终按照用户设置的参数将数据转发到目的地,这个数据转发服务阿里云是收费的。具体的流程如下所示:
设备端发送数据---->阿里云物联网平台接收到设备端数据---->规则引擎对接收到的数据做过滤提取------>提取出来的数据被转发到MQ消息队列---------->用户服务器监听MQ消息队列中的数据--------->监听到数据则执行回调函数进行业务处理

1、启用MQ消息队列服务,并创建一条Topic
     进入MQ消息队列控制台,点击“创建Topic”,输入Topic名称,此处的Topic需自己取名;消息类型按需选取,再此我选择普通消息。
     对刚刚创建的Topic进行授权设置,设置为授予订阅权限,这样我们的服务器就可以订阅这条Topic来监听转发过来的数据。
     为刚刚创建的Topic创建生产者与消费者,名称需要自己明明。
2、创建规则引擎并编写SQL语句
     打开阿里云物联网平台控制中的规则引擎,创建规则,输入规则名称,选择JSON格式,保存。
     点击“管理”,编辑SQL语句,如下所示:
 
字段输入为*,表明我将设备端上传的JSON数据为全部选择。
Topic处为"+/user/update",表明这条规则只处理满足+/user/update格式的数据。
条件处为空,表明没有条件限制。
保存该SQL语句.
3、配置规则引擎中的转发数据目的地
打开上面步骤中设置的那条SQL语句对应的管理界面,界面下方点击“添加操作”,
选择操作为“发送数据到消息队列”,其他配置如下图所示:
 
保存之后,启用该条转发规则,系统提示成功。
3、服务器端运行Demo进行数据监听测试
服务端采用JAVA,源码如下:

  1. package com.aliyun.iot.demo;

  2. import com.aliyun.openservices.ons.api.Action;
  3. import com.aliyun.openservices.ons.api.ConsumeContext;
  4. import com.aliyun.openservices.ons.api.Consumer;
  5. import com.aliyun.openservices.ons.api.Message;
  6. import com.aliyun.openservices.ons.api.MessageListener;
  7. import com.aliyun.openservices.ons.api.ONSFactory;
  8. import com.aliyun.openservices.ons.api.PropertyKeyConst;

  9. import java.io.UnsupportedEncodingException;
  10. import java.util.Properties;

  11. public class H2 {

  12.         public static void main(String[] args) {

  13.                 Properties properties = new Properties();
  14.                 // 这里的ConsumerId参数是你在MQ消息队列控制台创建的Topic时,你创建的消费者名称
  15.                 properties.put(PropertyKeyConst.ConsumerId, "CID_lockDevice");

  16.                 // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
  17.                 properties.put(PropertyKeyConst.AccessKey, "改成你自己的");

  18.                 // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
  19.                 properties.put(PropertyKeyConst.SecretKey,"改成你自己的");

  20.                 // 设置 TCP 接入域名(此处以公共云生产环境为例)
  21.                 // http://onsaddr-internet.aliyun.com/rocketmq/nsaddr4client-internet
  22.                 properties.put(PropertyKeyConst.ONSAddr,"http://onsaddr-internet.aliyun.com/rocketmq/nsaddr4client-internet");
  23.                 // 集群订阅方式 (默认)
  24.                 // properties.put(PropertyKeyConst.MessageModel,
  25.                 // PropertyValueConst.CLUSTERING);
  26.                 // 广播订阅方式
  27.                 // properties.put(PropertyKeyConst.MessageModel,
  28.                 // PropertyValueConst.BROADCASTING);
  29.                 Consumer consumer = ONSFactory.createConsumer(properties);
  30.                 // 下面函数中的参数qmlock_meg为MQ控制台创建的Topic名称;第二个参数为星号,表明监听所有数据
  31.                 consumer.subscribe("qmlock_meg", "*", new MessageListener() {
  32.                         @Override
  33.                         public Action consume(Message message, ConsumeContext context) {
  34.                                 System.out.println("Receive: " + message);
  35.                                 String res = null;
  36.                                 byte[] resByte = message.getBody();//获取消息体
  37.                                 try {
  38.                                         res = new String(resByte, "UTF-8");//将消息体byte型数据转换成字符串
  39.                                 } catch (UnsupportedEncodingException e) {
  40.                                         // TODO Auto-generated catch block
  41.                                         e.printStackTrace();
  42.                                 }
  43.                                 System.out.println("body: " + res);//打印消息体
  44.                                 return Action.CommitMessage;//返回消息消费结果
  45.                         }
  46.                 });
  47.                 consumer.start();
  48.                 System.out.println("Consumer Started");
  49.         }
  50. }
复制代码

服务端启动运行后,控制台显示“Consumer Started”,并处于监听状态。
此时,登录MQ控制台,查看消费者状态,如下图所示:
 
上图中,“是否在线”、“订阅关系是否一致”都显示“是”,表明服务端成功开启监听。
进入MQ消息队列控制台,打开生产者管理,发送消息里输入消息体“hello world”并发送,显示发送成功,此时查看服务端控制台,显示出已经接受到消息,如下所示:
 
   MQ控制台发送消息,服务端能够成功接收,说明服务端监听正常。
接下来,使用air202模组,发送AT+MPUB="/a1b96wWfb8u/868575026616807/user/update",1,0,"{\22cmd\22:\22get one code\22}"
服务端收到数据如下所示:
 

上次更新 2021-01-28