作者:俏巴
概述
物联网平台提供NTP服务,解决嵌入式设备资源受限,系统不包含NTP服务,端上没有精确时间戳的问题。物联网平台借鉴NTP协议原理,将云端作为NTP服务器。设备端发送一个特定Topic给云端,payload中带上发送时间。云端回复时在payload中加上云端的接收时间和发送时间。设备端收到回复后,再结合自己本地当前时间,得出一共4个时间。一起计算出设备端与云端的时间差,从而得出端上当前的精确时间。本文主要演示如果使用JAVA SDK实现相关功能。
实验步骤
1、相关Topic
请求Topic:/ext/ntp/${YourProductKey}/${YourDeviceName}/request
响应Topic:/ext/ntp/${YourProductKey}/${YourDeviceName}/response
2、pom.xml
<repositories>
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.aliyun.alink.linksdk</groupId>
<artifactId>iot-linkkit-java</artifactId>
<version>1.2.0.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.40</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>iot-java-sdk</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
3、Code Sample
import com.aliyun.alink.dm.api.DeviceInfo;
import com.aliyun.alink.dm.api.InitResult;
import com.aliyun.alink.dm.api.IoTApiClientConfig;
import com.aliyun.alink.linkkit.api.ILinkKitConnectListener;
import com.aliyun.alink.linkkit.api.IoTMqttClientConfig;
import com.aliyun.alink.linkkit.api.LinkKit;
import com.aliyun.alink.linkkit.api.LinkKitInitParams;
import com.aliyun.alink.linksdk.cmp.connect.channel.MqttPublishRequest;
import com.aliyun.alink.linksdk.cmp.connect.channel.MqttSubscribeRequest;
import com.aliyun.alink.linksdk.cmp.core.base.AMessage;
import com.aliyun.alink.linksdk.cmp.core.base.ARequest;
import com.aliyun.alink.linksdk.cmp.core.base.AResponse;
import com.aliyun.alink.linksdk.cmp.core.base.ConnectState;
import com.aliyun.alink.linksdk.cmp.core.listener.IConnectNotifyListener;
import com.aliyun.alink.linksdk.cmp.core.listener.IConnectSendListener;
import com.aliyun.alink.linksdk.cmp.core.listener.IConnectSubscribeListener;
import com.aliyun.alink.linksdk.tools.AError;
public class DeviceNTPDemo {
public static void main(String[] args) {
String regionId = "cn-shanghai";
DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.productKey = "******";
deviceInfo.deviceName = "******";
deviceInfo.deviceSecret = "******";
LinkKitInitParams params = new LinkKitInitParams();
IoTMqttClientConfig config = new IoTMqttClientConfig();
config.productKey = deviceInfo.productKey;
config.deviceName = deviceInfo.deviceName;
config.deviceSecret = deviceInfo.deviceSecret;
config.channelHost = deviceInfo.productKey + ".iot-as-mqtt." + regionId + ".aliyuncs.com:1883";
params.mqttClientConfig = config;
params.connectConfig = new IoTApiClientConfig();
params.deviceInfo = deviceInfo;
/**建立连接**/
LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
@Override
public void onError(AError aError) {
System.out.println("初始化失败 " + aError.getMsg());
}
@Override
public void onInitDone(InitResult initResult) {
System.out.println("初始化成功 " + initResult.tsl);
String pd = deviceInfo.productKey + "/" + deviceInfo.deviceName;
// 1、ntp 请求 Topic
String requestNtpTopic = "/ext/ntp/"+pd+"/request";
// 2、ntp 响应 Topic
String responseNtpTopic = "/ext/ntp/"+pd+"/response";
// 订阅Topic
MqttSubscribeRequest upgradeTopicRequest = new MqttSubscribeRequest();
upgradeTopicRequest.topic = responseNtpTopic;
upgradeTopicRequest.isSubscribe = true;
LinkKit.getInstance().subscribe(upgradeTopicRequest, new IConnectSubscribeListener(){
@Override
public void onSuccess() {
System.out.println("订阅成功");
}
@Override
public void onFailure(AError aError) {
System.out.println("订阅失败" + aError.getMsg());
}
});
// 注册ota下行监听
LinkKit.getInstance().registerOnNotifyListener(new IConnectNotifyListener() {
@Override
public void onNotify(String s, String s1, AMessage aMessage) {
System.out.println("ntp监听响应:");
System.out.println(new String((byte[])aMessage.getData()));
}
@Override
public boolean shouldHandle(String s, String s1) {
return false;
}
@Override
public void onConnectStateChange(String s, ConnectState connectState) {
System.out.println("连接状态发生变化 :" + s + connectState);
}
});
// 上报设备时间
MqttPublishRequest progressTopicRequest = new MqttPublishRequest();
progressTopicRequest.topic = requestNtpTopic;
progressTopicRequest.payloadObj = "{\n" +
" \"deviceSendTime\":\"1567336250000\"\n" +
"}";
progressTopicRequest.qos = 0;
LinkKit.getInstance().publish(progressTopicRequest, new IConnectSendListener() {
@Override
public void onResponse(ARequest aRequest, AResponse aResponse) {
System.out.println("ntp请求成功 " + aResponse.getData());
}
@Override
public void onFailure(ARequest aRequest, AError aError) {
System.out.println("ntp请求失败 " + aError.getMsg());
}
});
}
});
}
}
4、请求结果
{"deviceSendTime":"1567336250000","serverSendTime":"1567336282175","serverRecvTime":"1567336282175"}
5、时间计算方法
设备端收到服务端的时间记为${deviceRecvTime},则设备上的精确时间为:(${serverRecvTime} + ${serverSendTime} + ${deviceRecvTime} - ${deviceSendTime}) / 2