From 8a0a546e4409dfb8d515d07e9ca0744eb6657688 Mon Sep 17 00:00:00 2001 From: Frank <3224536684@qq.com> Date: Mon, 17 Jul 2023 17:01:22 +0800 Subject: [PATCH] :sparkles: v1.0.0 --- .gitignore | 35 ++ pom.xml | 104 +++++ .../javase/onenet/annotation/ApiParam.java | 38 ++ .../net/javase/onenet/api/ApiRequest.java | 272 ++++++++++++ .../net/javase/onenet/api/ApiResponse.java | 33 ++ .../net/javase/onenet/api/DataPointApi.java | 75 ++++ .../java/net/javase/onenet/api/DeviceApi.java | 364 ++++++++++++++++ .../java/net/javase/onenet/api/NbIotApi.java | 403 ++++++++++++++++++ .../java/net/javase/onenet/api/TSLApi.java | 237 ++++++++++ .../java/net/javase/onenet/config/Config.java | 44 ++ .../java/net/javase/onenet/enums/ApiEnum.java | 363 ++++++++++++++++ .../net/javase/onenet/enums/OneNetDomain.java | 26 ++ .../net/javase/onenet/enums/SignMethod.java | 26 ++ .../javase/onenet/exception/ApiException.java | 28 ++ .../onenet/model/DataPointQueryModel.java | 73 ++++ .../javase/onenet/model/NbInstantModel.java | 103 +++++ .../javase/onenet/model/NbOfflineModel.java | 97 +++++ .../javase/onenet/model/SyncCmdsModel.java | 43 ++ .../javase/onenet/model/base/BaseModel.java | 98 +++++ .../model/device/DeviceEventLogModel.java | 73 ++++ .../model/device/DeviceGroupListModel.java | 53 +++ .../onenet/model/device/DeviceGroupModel.java | 43 ++ .../model/device/DeviceGroupOptModel.java | 40 ++ .../onenet/model/device/DeviceModel.java | 78 ++++ .../onenet/model/device/DeviceMoveModel.java | 37 ++ .../model/device/DeviceResetSecKeyModel.java | 43 ++ .../device/DeviceStatusHistoryModel.java | 61 +++ .../javase/onenet/model/tsl/ThingModel.java | 52 +++ .../model/tsl/ThingQueryHistoryModel.java | 62 +++ .../onenet/model/tsl/ThingQueryModel.java | 35 ++ src/main/java/net/javase/onenet/utils/Kv.java | 31 ++ .../net/javase/onenet/utils/RequestUtil.java | 81 ++++ .../net/javase/onenet/utils/SignUtil.java | 93 ++++ .../java/net/javase/onenet/test/TestSign.java | 47 ++ 34 files changed, 3291 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/net/javase/onenet/annotation/ApiParam.java create mode 100644 src/main/java/net/javase/onenet/api/ApiRequest.java create mode 100644 src/main/java/net/javase/onenet/api/ApiResponse.java create mode 100644 src/main/java/net/javase/onenet/api/DataPointApi.java create mode 100644 src/main/java/net/javase/onenet/api/DeviceApi.java create mode 100644 src/main/java/net/javase/onenet/api/NbIotApi.java create mode 100644 src/main/java/net/javase/onenet/api/TSLApi.java create mode 100644 src/main/java/net/javase/onenet/config/Config.java create mode 100644 src/main/java/net/javase/onenet/enums/ApiEnum.java create mode 100644 src/main/java/net/javase/onenet/enums/OneNetDomain.java create mode 100644 src/main/java/net/javase/onenet/enums/SignMethod.java create mode 100644 src/main/java/net/javase/onenet/exception/ApiException.java create mode 100644 src/main/java/net/javase/onenet/model/DataPointQueryModel.java create mode 100644 src/main/java/net/javase/onenet/model/NbInstantModel.java create mode 100644 src/main/java/net/javase/onenet/model/NbOfflineModel.java create mode 100644 src/main/java/net/javase/onenet/model/SyncCmdsModel.java create mode 100644 src/main/java/net/javase/onenet/model/base/BaseModel.java create mode 100644 src/main/java/net/javase/onenet/model/device/DeviceEventLogModel.java create mode 100644 src/main/java/net/javase/onenet/model/device/DeviceGroupListModel.java create mode 100644 src/main/java/net/javase/onenet/model/device/DeviceGroupModel.java create mode 100644 src/main/java/net/javase/onenet/model/device/DeviceGroupOptModel.java create mode 100644 src/main/java/net/javase/onenet/model/device/DeviceModel.java create mode 100644 src/main/java/net/javase/onenet/model/device/DeviceMoveModel.java create mode 100644 src/main/java/net/javase/onenet/model/device/DeviceResetSecKeyModel.java create mode 100644 src/main/java/net/javase/onenet/model/device/DeviceStatusHistoryModel.java create mode 100644 src/main/java/net/javase/onenet/model/tsl/ThingModel.java create mode 100644 src/main/java/net/javase/onenet/model/tsl/ThingQueryHistoryModel.java create mode 100644 src/main/java/net/javase/onenet/model/tsl/ThingQueryModel.java create mode 100644 src/main/java/net/javase/onenet/utils/Kv.java create mode 100644 src/main/java/net/javase/onenet/utils/RequestUtil.java create mode 100644 src/main/java/net/javase/onenet/utils/SignUtil.java create mode 100644 src/test/java/net/javase/onenet/test/TestSign.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b425f09 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..2000fb3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,104 @@ + + + 4.0.0 + + net.javase.iot + onenet-api + 1.0.0 + + + 1.8 + UTF-8 + UTF-8 + 4.13.1 + 1.18.26 + 5.8.20 + 2.0.23 + 1.7.30 + + + + + + junit + junit + ${junit.version} + test + + + org.projectlombok + lombok + ${lombok.version} + compile + + + + cn.hutool + hutool-http + ${hutool.version} + + + + com.alibaba + fastjson + ${fastjson.version} + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + + org.slf4j + slf4j-simple + ${slf4j.version} + test + + + + + onenet-api + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + + package + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + nexus-release + package + + jar-no-fork + + + + + + + \ No newline at end of file diff --git a/src/main/java/net/javase/onenet/annotation/ApiParam.java b/src/main/java/net/javase/onenet/annotation/ApiParam.java new file mode 100644 index 0000000..b086f85 --- /dev/null +++ b/src/main/java/net/javase/onenet/annotation/ApiParam.java @@ -0,0 +1,38 @@ +package net.javase.onenet.annotation; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * API参数注解 + * + * @author Frank + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface ApiParam { + + /** + * 自定义参数名 + * + * @return name + */ + String name() default ""; + + /** + * 是否为query参数 + * + * @return true | false + */ + boolean isQuery() default false; + + /** + * 忽略参数 + * + * @return true | false + */ + boolean ignore() default false; +} diff --git a/src/main/java/net/javase/onenet/api/ApiRequest.java b/src/main/java/net/javase/onenet/api/ApiRequest.java new file mode 100644 index 0000000..d5961e4 --- /dev/null +++ b/src/main/java/net/javase/onenet/api/ApiRequest.java @@ -0,0 +1,272 @@ +package net.javase.onenet.api; + +import cn.hutool.http.ContentType; +import cn.hutool.http.Method; +import net.javase.onenet.enums.OneNetDomain; +import net.javase.onenet.enums.SignMethod; +import net.javase.onenet.model.base.BaseModel; +import net.javase.onenet.utils.RequestUtil; + +import java.util.Map; + +/** + * ApiRequest + * + * @author Frank + */ +public class ApiRequest { + + /** + * 参数组版本号 + */ + private String version; + + /** + * 资源信息 + */ + private String res; + + /** + * 接口api + */ + private String api; + + /** + * 指定请求方法 + */ + private Method method; + + /** + * 指定请求头 + */ + private ContentType contentType; + + /** + * domain + */ + private OneNetDomain domain; + + /** + * 签名方式 + */ + private SignMethod signMethod; + + /** + * query参数 + */ + private Map query; + + /** + * body参数 + */ + private Map body; + + /** + * 发送请求 + * + * @param accessKey accessKey + * @return {@link ApiResponse} + */ + public ApiResponse send(String accessKey) { + return RequestUtil.doRequest(this, accessKey); + } + + /** + * 发送请求 + * + * @param accessKey accessKey + * @param clazz clazz + * @param T + * @return T + */ + public T send(String accessKey, Class clazz) { + return RequestUtil.doRequest(this, accessKey, clazz); + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getRes() { + return res; + } + + public void setRes(String res) { + this.res = res; + } + + public String getApi() { + return this.api; + } + + public String url() { + return this.api; + } + + public void setApi(String api) { + this.api = api; + } + + public Method getMethod() { + return this.method; + } + + public void setMethod(Method method) { + this.method = method; + } + + public ContentType getContentType() { + return this.contentType; + } + + public void setContentType(ContentType contentType) { + this.contentType = contentType; + } + + public OneNetDomain getDomain() { + return this.domain == null ? OneNetDomain.IOT_API : this.domain; + } + + public void setDomain(OneNetDomain domain) { + this.domain = domain; + } + + public SignMethod getSignMethod() { + return this.signMethod == null ? SignMethod.SHA256 : this.signMethod; + } + + public void setSignMethod(SignMethod signMethod) { + this.signMethod = signMethod; + } + + public Map getQuery() { + return this.query; + } + + public void setQuery(Map query) { + this.query = query; + } + + public Map getBody() { + return this.body; + } + + public void setBody(Map body) { + this.body = body; + } + + ApiRequest(String version, String res, String api, Method method, ContentType contentType, + OneNetDomain domain, SignMethod signMethod, Map query, Map body) { + this.version = version; + this.res = res; + this.api = api; + this.method = method; + this.contentType = contentType; + this.domain = domain; + this.signMethod = signMethod; + this.query = query; + this.body = body; + } + + public static ApiRequestBuilder builder() { + return new ApiRequestBuilder(); + } + + public static class ApiRequestBuilder { + + /** + * 参数组版本号 + */ + private String version = "2022-05-01"; + + /** + * 资源信息 + */ + private String res; + private String api; + private Method method; + private ContentType contentType; + private OneNetDomain domain; + private SignMethod signMethod; + private Map query; + private Map body; + + ApiRequestBuilder() { + } + + public ApiRequestBuilder version(String version) { + this.version = version; + return this; + } + + public ApiRequestBuilder res(String res) { + this.res = res; + return this; + } + + public ApiRequestBuilder api(String api) { + this.api = api; + return this; + } + + public ApiRequestBuilder method(Method method) { + this.method = method; + return this; + } + + public ApiRequestBuilder contentType(ContentType contentType) { + this.contentType = contentType; + return this; + } + + public ApiRequestBuilder domain(OneNetDomain domain) { + this.domain = domain; + return this; + } + + public ApiRequestBuilder signMethod(SignMethod signMethod) { + this.signMethod = signMethod; + return this; + } + + public ApiRequestBuilder query(Map query) { + this.query = query; + return this; + } + + public ApiRequestBuilder body(Map body) { + this.body = body; + return this; + } + + public ApiRequestBuilder userid(String userid) { + this.res = "userid/" + userid; + return this; + } + + /** + * 设置请求参数 + * + * @param model model + * @param T + * @return {@link ApiRequestBuilder} + */ + public ApiRequestBuilder model(T model) { + Map> params = model.paramsMap(); + this.query = params.get("query"); + this.body = params.get("body"); + return this; + } + + public ApiRequest build() { + return new ApiRequest(this.version, this.res, this.api, this.method, + this.contentType, this.domain, this.signMethod, this.query, this.body); + } + + } + +} diff --git a/src/main/java/net/javase/onenet/api/ApiResponse.java b/src/main/java/net/javase/onenet/api/ApiResponse.java new file mode 100644 index 0000000..5874d1d --- /dev/null +++ b/src/main/java/net/javase/onenet/api/ApiResponse.java @@ -0,0 +1,33 @@ +package net.javase.onenet.api; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Map; + +/** + * ApiResponse + * + * @author Frank + */ +@Getter +@Setter +public class ApiResponse implements Serializable { + + private Integer code; + + private String msg; + + private Map data; + + @JSONField(name = "request_id") + private String requestId; + + @Override + public String toString() { + return JSONObject.toJSONString(this); + } +} diff --git a/src/main/java/net/javase/onenet/api/DataPointApi.java b/src/main/java/net/javase/onenet/api/DataPointApi.java new file mode 100644 index 0000000..163936e --- /dev/null +++ b/src/main/java/net/javase/onenet/api/DataPointApi.java @@ -0,0 +1,75 @@ +package net.javase.onenet.api; + +import cn.hutool.http.ContentType; +import cn.hutool.http.Method; +import net.javase.onenet.config.Config; +import net.javase.onenet.enums.ApiEnum; +import net.javase.onenet.enums.SignMethod; +import net.javase.onenet.model.DataPointQueryModel; +import net.javase.onenet.model.SyncCmdsModel; + +/** + * DataPointApi + *

+ * 数据流API + * + * @author Frank + */ +public class DataPointApi { + + /** + * 查询设备数据点 + * + * @param config {@link Config} + * @param model {@link DataPointQueryModel} + * @return {@link ApiResponse} + */ + public static ApiResponse historyDataPoints(Config config, DataPointQueryModel model) { + return ApiRequest.builder() + .api(ApiEnum.DATAPOINT_HISTORY.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(model.toMap()) + .build() + .send(config.getAccessKey()); + } + + /** + * 批量查询产品下设备最新数据点 + * + * @param config {@link Config} + * @param model {@link DataPointQueryModel} + * @return {@link ApiResponse} + */ + public static ApiResponse currentDataPoints(Config config, DataPointQueryModel model) { + return ApiRequest.builder() + .api(ApiEnum.DATAPOINT_CURRENT.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(model.toMap()) + .build() + .send(config.getAccessKey()); + } + + /** + * MQTT命令下发 + * + * @param config {@link Config} + * @param model 请求参数对象 + * @return {@link ApiResponse} + */ + public static ApiResponse syncCmds(Config config, SyncCmdsModel model) { + return ApiRequest.builder() + .api(ApiEnum.DATAPOINT_SYNCCMDS.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .body(model.getArgs()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } +} diff --git a/src/main/java/net/javase/onenet/api/DeviceApi.java b/src/main/java/net/javase/onenet/api/DeviceApi.java new file mode 100644 index 0000000..300ceac --- /dev/null +++ b/src/main/java/net/javase/onenet/api/DeviceApi.java @@ -0,0 +1,364 @@ +package net.javase.onenet.api; + +import cn.hutool.http.ContentType; +import cn.hutool.http.Method; +import net.javase.onenet.config.Config; +import net.javase.onenet.enums.ApiEnum; +import net.javase.onenet.enums.SignMethod; +import net.javase.onenet.model.device.*; + +import java.util.HashMap; +import java.util.Map; + +/** + * DeviceApi 设备API + * + * @author Frank + */ +public class DeviceApi { + + /** + * 创建设备 + * + * @param config {@link Config} + * @param model model + * @return {@link ApiResponse} + */ + public static ApiResponse deviceCreate(Config config, net.javase.onenet.model.device.DeviceModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_CREATE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .model(model) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 编辑设备 + * + * @param config {@link Config} + * @param model model + * @return {@link ApiResponse} + */ + public static ApiResponse deviceUpdate(Config config, net.javase.onenet.model.device.DeviceModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_UPDATE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .model(model) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备详情 + * + * @param config {@link Config} + * @param model model + * @return {@link ApiResponse} + */ + public static ApiResponse deviceDetail(Config config, DeviceModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_DETAIL.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 删除设备 + * + * @param config {@link Config} + * @param model model + * @return {@link ApiResponse} + */ + public static ApiResponse deviceDelete(Config config, DeviceModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_DELETE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 更新设备sec_key + * + * @param config {@link Config} + * @param model model + * @return {@link ApiResponse} + */ + public static ApiResponse deviceResetSecKey(Config config, DeviceResetSecKeyModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_REST_SECKEY.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备状态变更记录 + * + * @param config {@link Config} + * @param model model + * @return {@link ApiResponse} + */ + public static ApiResponse deviceStatusHistory(Config config, DeviceStatusHistoryModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_STATUS_HISTORY.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备事件记录查询 + * + * @param config {@link Config} + * @param model model + * @return {@link ApiResponse} + */ + public static ApiResponse deviceEventLog(Config config, DeviceEventLogModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_EVENT_LOG.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备操作记录查询 + * + * @param config {@link Config} + * @param model model + * @return {@link ApiResponse} + */ + public static ApiResponse deviceOperationLog(Config config, DeviceStatusHistoryModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_OPERATION_LOG.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备服务记录查询 + * + * @param config {@link Config} + * @param traceId 调用服务后的request_id + * @return {@link ApiResponse} + */ + public static ApiResponse deviceServiceLog(Config config, String traceId) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("trace_id", traceId); + return ApiRequest.builder() + .api(ApiEnum.DEVICE_SERVICE_LOG.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(query) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备转移 + * + * @param config {@link Config} + * @param model model + * @return {@link ApiResponse} + */ + public static ApiResponse deviceMove(Config config, DeviceMoveModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_MOVE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + + /** + * 设备分组列表 + * + * @param config {@link Config} + * @param model 请求参数 + * @return {@link ApiResponse} + */ + public static ApiResponse deviceGroupList(Config config, DeviceGroupListModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_GROUP_LIST.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + + /** + * 设备分组详情 + * + * @param config {@link Config} + * @param groupId 分组ID + * @return {@link ApiResponse} + */ + public static ApiResponse deviceGroupDetail(Config config, String groupId) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("group_id", groupId); + return ApiRequest.builder() + .api(ApiEnum.DEVICE_GROUP_DETAIL.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(query) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 新建设备分组 + * + * @param config {@link Config} + * @param model 请求参数 + * @return {@link ApiResponse} + */ + public static ApiResponse deviceGroupCreate(Config config, DeviceGroupModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_GROUP_CREATE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 编辑设备分组 + * + * @param config {@link Config} + * @param model 请求参数 + * @return {@link ApiResponse} + */ + public static ApiResponse deviceGroupUpdate(Config config, DeviceGroupModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_GROUP_UPDATE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 删除设备分组 + * + * @param config {@link Config} + * @param groupId 分组ID + * @return {@link ApiResponse} + */ + public static ApiResponse deviceGroupDelete(Config config, String groupId) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("group_id", groupId); + return ApiRequest.builder() + .api(ApiEnum.DEVICE_GROUP_DELETE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(query) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备分组-添加设备 + * + * @param config {@link Config} + * @param model 请求参数 + * @return {@link ApiResponse} + */ + public static ApiResponse deviceGroupAddDevices(Config config, DeviceGroupOptModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_GROUP_ADD_DEVICES.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + + /** + * 设备分组-删除设备 + * + * @param config {@link Config} + * @param model 请求参数 + * @return {@link ApiResponse} + */ + public static ApiResponse deviceGroupDelDevices(Config config, DeviceGroupOptModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_GROUP_DEL_DEVICES.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备分组-删除设备 + * + * @param config {@link Config} + * @param model 请求参数 + * @return {@link ApiResponse} + */ + public static ApiResponse deviceGroupDevices(Config config, DeviceGroupListModel model) { + return ApiRequest.builder() + .api(ApiEnum.DEVICE_GROUP_DEL_DEVICES.api()) + .method(Method.GET) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + +} diff --git a/src/main/java/net/javase/onenet/api/NbIotApi.java b/src/main/java/net/javase/onenet/api/NbIotApi.java new file mode 100644 index 0000000..0b874b0 --- /dev/null +++ b/src/main/java/net/javase/onenet/api/NbIotApi.java @@ -0,0 +1,403 @@ +package net.javase.onenet.api; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.ContentType; +import cn.hutool.http.Method; +import net.javase.onenet.config.Config; +import net.javase.onenet.enums.ApiEnum; +import net.javase.onenet.enums.SignMethod; +import net.javase.onenet.model.NbInstantModel; +import net.javase.onenet.model.NbOfflineModel; + +import java.util.HashMap; +import java.util.Map; + +/** + * NbIotApi + * + * @author Frank + */ +public class NbIotApi { + + /** + * 获取资源列表 + * + * @param config {@link Config} + * @param imei nbiot设备的身份码 + * @return {@link ApiResponse} + */ + public static ApiResponse resources(Config config, String imei) { + return resources(config, imei, null); + } + + /** + * 获取资源列表 + * + * @param config {@link Config} + * @param imei nbiot设备的身份码 + * @param objId 设备objectId,根据终端SDK确定 + * @return {@link ApiResponse} + */ + public static ApiResponse resources(Config config, String imei, String objId) { + Map query = new HashMap<>(); + query.put("imei", imei); + if (StrUtil.isNotBlank(objId)) { + query.put("obj_id", objId); + } + return ApiRequest.builder() + .api(ApiEnum.NBIOT_RESOURCES.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(query) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 即时命令-资源发现 + * + * @param config {@link Config} + * @param model {@link NbInstantModel} + * @return {@link ApiResponse} + */ + public static ApiResponse discover(Config config, NbInstantModel model) { + return ApiRequest.builder() + .api(ApiEnum.NBIOT_DISCOVER.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 即时命令-资源订阅 + * + * @param config {@link Config} + * @param model {@link NbInstantModel} + * @return {@link ApiResponse} + */ + public static ApiResponse observe(Config config, NbInstantModel model) { + return ApiRequest.builder() + .api(ApiEnum.NBIOT_OBSERVE.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 即时命令-读设备资源 + * + * @param config {@link Config} + * @param model {@link NbInstantModel} + * @return {@link ApiResponse} + */ + public static ApiResponse readResource(Config config, NbInstantModel model) { + return ApiRequest.builder() + .api(ApiEnum.NBIOT.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 即时命令-写设备资源 + * + * @param config {@link Config} + * @param model {@link NbInstantModel} + * @return {@link ApiResponse} + */ + public static ApiResponse writeResource(Config config, NbInstantModel model) { + return ApiRequest.builder() + .api(ApiEnum.NBIOT.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .model(model) + .build() + .send(config.getAccessKey()); + } + + /** + * 即时命令-即时命令下发 + * + * @param config {@link Config} + * @param model {@link NbInstantModel} + * @return {@link ApiResponse} + */ + public static ApiResponse execute(Config config, NbInstantModel model) { + return ApiRequest.builder() + .api(ApiEnum.NBIOT_EXECUTE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .model(model) + .build() + .send(config.getAccessKey()); + } + + + // 缓存命令 + + /** + * 缓存命令-读设备资源 + * + * @param config {@link Config} + * @param model {@link NbOfflineModel} + * @return {@link ApiResponse} + */ + public static ApiResponse readOfflineResource(Config config, NbOfflineModel model) { + return ApiRequest.builder() + .api(ApiEnum.NBIOT_OFFLINE.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 缓存命令-写设备资源 + * + * @param config {@link Config} + * @param model {@link NbOfflineModel} + * @return {@link ApiResponse} + */ + public static ApiResponse writeOfflineResource(Config config, NbOfflineModel model) { + return ApiRequest.builder() + .api(ApiEnum.NBIOT_OFFLINE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 缓存命令下发 + * + * @param config {@link Config} + * @param model {@link NbOfflineModel} + * @return {@link ApiResponse} + */ + public static ApiResponse executeOffline(Config config, NbOfflineModel model) { + return ApiRequest.builder() + .api(ApiEnum.NBIOT_OFFLINE_EXECUTE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .model(model) + .build() + .send(config.getAccessKey()); + } + + /** + * 查看缓存命令详情 + * + * @param config {@link Config} + * @param uuid 缓存命令ID + * @param imei nbiot设备的身份码 + * @return {@link ApiResponse} + */ + public static ApiResponse offlineHistory(Config config, String uuid, String imei) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("imei", imei); + return ApiRequest.builder() + .api(ApiEnum.NBIOT_OFFLINE_HISTORY_UUID.api(uuid)) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(query) + .build() + .send(config.getAccessKey()); + } + + /** + * 取消缓存命令 + * + * @param config {@link Config} + * @param uuid 缓存命令ID + * @param imei nbiot设备的身份码 + * @return {@link ApiResponse} + */ + public static ApiResponse offlineCancel(Config config, String uuid, String imei) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("imei", imei); + return ApiRequest.builder() + .api(ApiEnum.NBIOT_OFFLINE_CANCEL_UUID.api(uuid)) + .method(Method.PUT) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(query) + .build() + .send(config.getAccessKey()); + } + + /** + * 取消所有未下发缓存命令 + * + * @param config {@link Config} + * @param imei nbiot设备的身份码 + * @return {@link ApiResponse} + */ + public static ApiResponse offlineCancelAll(Config config, String imei) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("imei", imei); + return ApiRequest.builder() + .api(ApiEnum.NBIOT_OFFLINE_CANCEL_ALL.api()) + .method(Method.PUT) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(query) + .build() + .send(config.getAccessKey()); + } + + /** + * 全链路日志查询 + * + * @param config {@link Config} + * @param uuid 缓存命令ID + * @param imei nbiot设备的身份码 + * @return {@link ApiResponse} + */ + public static ApiResponse offlineHistoryPiecewise(Config config, String uuid, String imei) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("imei", imei); + return ApiRequest.builder() + .api(ApiEnum.NBIOT_OFFLINE_HISTORY_PIECEWISE.api(uuid)) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(query) + .build() + .send(config.getAccessKey()); + } + + /** + * 查看bs_psk + * + * @param config {@link Config} + * @param imei nbiot设备的身份码 + * @return {@link ApiResponse} + */ + public static ApiResponse devicePskQuery(Config config, String imei) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("imei", imei); + return ApiRequest.builder() + .api(ApiEnum.NBIOT_DEVICE_PSK.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(query) + .build() + .send(config.getAccessKey()); + } + + /** + * 更新bs_psk + * + * @param config {@link Config} + * @param imei nbiot设备的身份码 + * @param key 修改连接引导机的PSK,长度8-16个字节,字母或数字组成 + * @return {@link ApiResponse} + */ + public static ApiResponse devicePskUpdate(Config config, String imei, String key) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("imei", imei); + Map body = new HashMap<>((int) ((1 / 0.75f) + 1)); + body.put("key", key); + return ApiRequest.builder() + .api(ApiEnum.NBIOT_DEVICE_PSK.api()) + .method(Method.PUT) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(query) + .body(body) + .build() + .send(config.getAccessKey()); + } + + /** + * 查看acc_psk + * + * @param config {@link Config} + * @param imei nbiot设备的身份码 + * @return {@link ApiResponse} + */ + public static ApiResponse deviceAccPskQuery(Config config, String imei) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("imei", imei); + return ApiRequest.builder() + .api(ApiEnum.NBIOT_DEVICE_ACCPSK.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(query) + .build() + .send(config.getAccessKey()); + } + + /** + * 新增acc_psk + * + * @param config {@link Config} + * @param imei nbiot设备的身份码 + * @param key 修改连接引导机的PSK,长度8-16个字节,字母或数字组成 + * @return {@link ApiResponse} + */ + public static ApiResponse deviceAccPskAdd(Config config, String imei, String key) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("imei", imei); + Map body = new HashMap<>((int) ((1 / 0.75f) + 1)); + body.put("key", key); + return ApiRequest.builder() + .api(ApiEnum.NBIOT_DEVICE_ACCPSK.api()) + .method(Method.POST) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(query) + .body(body) + .build() + .send(config.getAccessKey()); + } + + /** + * 更新acc_psk + * + * @param config {@link Config} + * @param imei nbiot设备的身份码 + * @param key 修改连接引导机的PSK,长度8-16个字节,字母或数字组成 + * @return {@link ApiResponse} + */ + public static ApiResponse deviceAccPskUpdate(Config config, String imei, String key) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("imei", imei); + Map body = new HashMap<>((int) ((1 / 0.75f) + 1)); + body.put("key", key); + return ApiRequest.builder() + .api(ApiEnum.NBIOT_DEVICE_ACCPSK.api()) + .method(Method.PUT) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .query(query) + .body(body) + .build() + .send(config.getAccessKey()); + } + +} diff --git a/src/main/java/net/javase/onenet/api/TSLApi.java b/src/main/java/net/javase/onenet/api/TSLApi.java new file mode 100644 index 0000000..72a2550 --- /dev/null +++ b/src/main/java/net/javase/onenet/api/TSLApi.java @@ -0,0 +1,237 @@ +package net.javase.onenet.api; + +import cn.hutool.http.ContentType; +import cn.hutool.http.Method; +import net.javase.onenet.config.Config; +import net.javase.onenet.enums.ApiEnum; +import net.javase.onenet.enums.SignMethod; +import net.javase.onenet.model.tsl.ThingModel; +import net.javase.onenet.model.tsl.ThingQueryHistoryModel; +import net.javase.onenet.model.tsl.ThingQueryModel; + +import java.util.HashMap; +import java.util.Map; + +/** + * TSLApi 物模型API + * + * @author Frank + */ +public class TSLApi { + + /** + * 物模型系统功能点列表 + * + * @param config {@link Config} + * @return {@link ApiResponse} + */ + public static ApiResponse querySystemThingModel(Config config) { + return ApiRequest.builder() + .api(ApiEnum.TSL_QUERY_SYSTEM_THING_MODEL.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 物模型查询 + * + * @param config {@link Config} + * @param productId 产品ID + * @return {@link ApiResponse} + */ + public static ApiResponse queryThingModel(Config config, String productId) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("product_id", productId); + return ApiRequest.builder() + .api(ApiEnum.QUERY_THING_MODEL.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(query) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设置设备属性 + * + * @param config {@link Config} + * @param model 请求参数对象 + * @return {@link ApiResponse} + */ + public static ApiResponse setDeviceProperty(Config config, ThingModel model) { + return ApiRequest.builder() + .api(ApiEnum.SET_DEVICE_PROPERTY.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 获取设备属性详情 + * + * @param config {@link Config} + * @param model 请求参数对象 + * @return {@link ApiResponse} + */ + public static ApiResponse queryDevicePropertyDetail(Config config, ThingQueryModel model) { + return ApiRequest.builder() + .api(ApiEnum.QUERY_DEVICE_PROPERTY_DETAIL.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备属性最新数据查询 + * + * @param config {@link Config} + * @param productId 产品ID + * @param deviceName 设备名称 + * @return {@link ApiResponse} + */ + public static ApiResponse queryDeviceProperty(Config config, + String productId, String deviceName) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("product_id", productId); + query.put("device_name", deviceName); + return ApiRequest.builder() + .api(ApiEnum.QUERY_DEVICE_PROPERTY.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(query) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备属性最新数据查询 + * + * @param config {@link Config} + * @param productId 产品ID + * @param deviceName 设备名称 + * @param clazz clazz + * @param T + * @return T + */ + public static T queryDeviceProperty(Config config, String productId, String deviceName, Class clazz) { + Map query = new HashMap<>((int) ((1 / 0.75f) + 1)); + query.put("product_id", productId); + query.put("device_name", deviceName); + return ApiRequest.builder() + .api(ApiEnum.QUERY_DEVICE_PROPERTY.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(query) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey(), clazz); + } + + /** + * 设备属性最新数据查询 + * + * @param config {@link Config} + * @param model {@link ThingQueryHistoryModel} + * @return {@link ApiResponse} + */ + public static ApiResponse queryDevicePropertyHistory(Config config, ThingQueryHistoryModel model) { + return ApiRequest.builder() + .api(ApiEnum.QUERY_DEVICE_PROPERTY_HISTORY.api()) + .method(Method.GET) + .signMethod(SignMethod.MD5) + .query(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备服务调用 + * + * @param config {@link Config} + * @param model 请求参数对象 + * @return {@link ApiResponse} + */ + public static ApiResponse callService(Config config, ThingModel model) { + return ApiRequest.builder() + .api(ApiEnum.CALL_SERVICE.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备属性期望设置 + * + * @param config {@link Config} + * @param model 请求参数对象 + * @return {@link ApiResponse} + */ + public static ApiResponse setDeviceDesiredProperty(Config config, ThingModel model) { + return ApiRequest.builder() + .api(ApiEnum.SET_DEVICE_DESIRED_PROPERTY.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备属性期望查询 + * + * @param config {@link Config} + * @param model 请求参数对象 + * @return {@link ApiResponse} + */ + public static ApiResponse queryDeviceDesiredProperty(Config config, ThingQueryModel model) { + return ApiRequest.builder() + .api(ApiEnum.QUERY_DEVICE_DESIRED_PROPERTY.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + + /** + * 设备属性期望删除 + * + * @param config {@link Config} + * @param model 请求参数对象 + * @return {@link ApiResponse} + */ + public static ApiResponse delDeviceDesiredProperty(Config config, ThingModel model) { + return ApiRequest.builder() + .api(ApiEnum.DELETE_DEVICE_DESIRED_PROPERTY.api()) + .method(Method.POST) + .contentType(ContentType.JSON) + .signMethod(SignMethod.MD5) + .body(model.toMap()) + .userid(config.getUserid()) + .build() + .send(config.getAccessKey()); + } + +} diff --git a/src/main/java/net/javase/onenet/config/Config.java b/src/main/java/net/javase/onenet/config/Config.java new file mode 100644 index 0000000..de2d2b7 --- /dev/null +++ b/src/main/java/net/javase/onenet/config/Config.java @@ -0,0 +1,44 @@ +package net.javase.onenet.config; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; + +/** + * Config + * + * @author Frank + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class Config implements Serializable { + + private static final long serialVersionUID = 2864466266722905367L; + + /** + * 用户ID + */ + private String userid; + + /** + * 用户accessKey + */ + private String accessKey; + + /** + * 创建配置对象 + * + * @param userid 用户ID + * @param accessKey 用户accessKey + * @return {@link Config} + */ + public static Config create(String userid, String accessKey) { + return new Config(userid, accessKey); + } + +} diff --git a/src/main/java/net/javase/onenet/enums/ApiEnum.java b/src/main/java/net/javase/onenet/enums/ApiEnum.java new file mode 100644 index 0000000..7f972f3 --- /dev/null +++ b/src/main/java/net/javase/onenet/enums/ApiEnum.java @@ -0,0 +1,363 @@ +package net.javase.onenet.enums; + +import cn.hutool.core.util.StrUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * ApiEnum + * + * @author Frank + */ +@Getter +@AllArgsConstructor +public enum ApiEnum { + + // 设备管理 + /** + * 创建设备 + */ + DEVICE_CREATE("/device/create"), + + /** + * 设备详情 + */ + DEVICE_DETAIL("/device/detail"), + + /** + * 更新设备 + */ + DEVICE_UPDATE("/device/update"), + + /** + * 删除设备 + */ + DEVICE_DELETE("/device/delete"), + + /** + * 重置设备接入鉴权key + */ + DEVICE_REST_SECKEY("/device/reset-seckey"), + + /** + * 设备状态历史变更记录 + */ + DEVICE_STATUS_HISTORY("/device/status-history"), + + /** + * 设备操作记录查询 + */ + DEVICE_OPERATION_LOG("/device/operation-log"), + + /** + * 设备服务记录查询 + */ + DEVICE_SERVICE_LOG("/device/service-log"), + + /** + * 设备事件记录查询 + */ + DEVICE_EVENT_LOG("/device/event-log"), + + /** + * 设备转移 + */ + DEVICE_MOVE("/device/movedevice"), + + /** + * 设备分组列表 + */ + DEVICE_GROUP_LIST("/devicegroup/list"), + + /** + * 设备分组详情 + */ + DEVICE_GROUP_DETAIL("/devicegroup/detail"), + + /** + * 新建设备分组 + */ + DEVICE_GROUP_CREATE("/devicegroup/create"), + + /** + * 编辑设备分组 + */ + DEVICE_GROUP_UPDATE("/devicegroup/update"), + + /** + * 删除设备分组 + */ + DEVICE_GROUP_DELETE("/devicegroup/delete"), + + /** + * 设备分组-添加设备 + */ + DEVICE_GROUP_ADD_DEVICES("/devicegroup/add-devices"), + + /** + * 设备分组-删除设备 + */ + DEVICE_GROUP_DEL_DEVICES("/devicegroup/del-devices"), + + /** + * 设备分组-设备列表 + */ + DEVICE_GROUP_DEVICES("/devicegroup/devices"), + + + // 设备文件管理 + /** + * 账户文件列表查询 + */ + DEVICE_FILE_LIST("/device/file-list"), + + /** + * 设备文件上传 + */ + DEVICE_FILE_UPLOAD("/device/file-upload"), + + /** + * 设备文件删除 + */ + DEVICE_FILE_DELETE("/device/file-delete"), + + /** + * 设备文件下载 + */ + DEVICE_FILE_DOWNLOAD("/device/file-download"), + + /** + * 账户文件存储空间查询 + */ + DEVICE_FILE_SPACE("/device/file-space"), + + /** + * 设备文件数量查询 + */ + DEVICE_FILE_DEVICE_COUNT("/device/file-device-count"), + + // 物模型管理 + /** + * 物模型系统功能点列表 + */ + TSL_QUERY_SYSTEM_THING_MODEL("/thingmodel/query-system-thing-model"), + + /** + * 物模型查询 + */ + QUERY_THING_MODEL("/thingmodel/query-thing-model"), + + /** + * 设置设备属性 + */ + SET_DEVICE_PROPERTY("/thingmodel/set-device-property"), + + /** + * 获取设备属性详情 + */ + QUERY_DEVICE_PROPERTY_DETAIL("/thingmodel/query-device-property-detail"), + + /** + * 设备属性最新数据查询 + */ + QUERY_DEVICE_PROPERTY("/thingmodel/query-device-property"), + + /** + * 设备属性记录查询 + */ + QUERY_DEVICE_PROPERTY_HISTORY("/thingmodel/query-device-property-history"), + + /** + * 设备服务调用 + */ + CALL_SERVICE("/thingmodel/call-service"), + + /** + * 设备属性期望设置 + */ + SET_DEVICE_DESIRED_PROPERTY("/thingmodel/set-device-desired-property"), + + /** + * 设备属性期望查询 + */ + QUERY_DEVICE_DESIRED_PROPERTY("/thingmodel/query-device-desired-property"), + + /** + * 设备属性期望删除 + */ + DELETE_DEVICE_DESIRED_PROPERTY("/thingmodel/delete-device-desired-property"), + + // 数据流使用 + /** + * 查询设备数据点 + */ + DATAPOINT_HISTORY("/datapoint/history-datapoints"), + + /** + * 批量查询产品下设备最新数据点 + */ + DATAPOINT_CURRENT("/datapoint/current-datapoints"), + + /** + * 设备下发命令 + */ + DATAPOINT_SYNCCMDS("/datapoint/synccmds"), + + // LwM2M-即时命令 + + /** + * 获取资源列表 + */ + NBIOT_RESOURCES("/nb-iot/resources"), + + /** + * 即时命令-资源发现 + */ + NBIOT_DISCOVER("/nb-iot/discover"), + + /** + * 即时命令-资源订阅 + */ + NBIOT_OBSERVE("/nb-iot/observe"), + + /** + * 即时命令-读取/写入 设备资源 + */ + NBIOT("/nb-iot"), + + /** + * 即时命令-设备命令下发 + */ + NBIOT_EXECUTE("/nb-iot/execute"), + + // LwM2M-缓存命令 + + /** + * 缓存命令- 写入/读取 设备资源 + */ + NBIOT_OFFLINE("/nb-iot/offline"), + + /** + * 缓存命令-设备命令下发 + */ + NBIOT_OFFLINE_EXECUTE("/nb-iot/execute/offline"), + + /** + * 缓存命令-查询指定设备缓存命令列表 + */ + NBIOT_OFFLINE_HISTORY("/nb-iot/offline/history"), + + /** + * 缓存命令-查询指定缓存命令详情 + */ + NBIOT_OFFLINE_HISTORY_UUID("/nb-iot/offline/history/{}"), + + + /** + * 缓存命令-取消指定的缓存命令 + */ + NBIOT_OFFLINE_CANCEL_UUID("/nb-iot/offline/cancel/{}"), + + /** + * 缓存命令-取消设备所有未下发的缓存命令 + */ + NBIOT_OFFLINE_CANCEL_ALL("/nb-iot/offline/cancel/all"), + + /** + * 缓存命令-全链路日志查询 + */ + NBIOT_OFFLINE_HISTORY_PIECEWISE("/nb-iot/offline/history/{}/piecewise"), + + // LwM2M-DTLS + + /** + * 查看/更新 指定设备bs_psk信息 + */ + NBIOT_DEVICE_PSK("/nb-iot/device/psk"), + + /** + * 查看/新增/编辑 指定设备acc_psk信息 + */ + NBIOT_DEVICE_ACCPSK("/nb-iot/device/accpsk"), + + // 工业标识管理 + + /** + * 工业标识管理-设备批量自动注册标识接口 + */ + FUSE_IDENTITY_DEVICE("/fuse-identity-device/batch-auto-regist-device-identity"), + + // LBS位置能力 + + /** + * 基站定位获取最新位置接口 + */ + LBS_LATEST_LOCATION("/fuse-lbs/latest-location"), + + /** + * 基站定位历史轨迹查询接口 + */ + LBS_GET_TRAIL("/fuse-lbs/get-trail"), + + /** + * WIFI定位获取最新位置接口 + */ + LBS_LATEST_WIFI_LOCATION("/fuse-lbs/latest-wifi-location"), + + /** + * WIFI定位历史轨迹查询接口 + */ + LBS_GET_WIFI_TRAIL("/fuse-lbs/get-wifi-trail"), + + // OTA南向 + + /** + * 检测升级任务 + */ + OTA_CHECK("/fuse-ota/{}/{}/check"), + + /** + * 下载升级包 + */ + OTA_DOWNLOAD("/fuse-ota/{}/{}/{}/download"), + + /** + * 上报升级状态 + */ + OTA_STATUS("/fuse-ota/{}/{}/{}/status"), + + /** + * 检测任务状态 + */ + OTA_TID_CHECK("/fuse-ota/{}/{}/{}/check"), + + /** + * 上报/查看 版本号 + */ + OTA_VERSION("/fuse-ota/{}/{}/version"), + + // 语音能力 + + /** + * 语音通知接口 + */ + VOICE_NOTIFY("/fuse-voice/voiceNotify"), + + ; + + /** + * api url + */ + private final String url; + + /** + * 获取api, 用于处理带占位符url参数的api + * + * @param params 参数 + * @return 完整url + */ + public String api(Object... params) { + return StrUtil.format(url, params); + } + +} diff --git a/src/main/java/net/javase/onenet/enums/OneNetDomain.java b/src/main/java/net/javase/onenet/enums/OneNetDomain.java new file mode 100644 index 0000000..35c154b --- /dev/null +++ b/src/main/java/net/javase/onenet/enums/OneNetDomain.java @@ -0,0 +1,26 @@ +package net.javase.onenet.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * OneNetDomain + * + * @author Frank + */ +@Getter +@AllArgsConstructor +public enum OneNetDomain { + + /** + * 新版物联网平台api + */ + IOT_API("https://iot-api.heclouds.com"), + + ; + + /** + * domain + */ + private final String domain; +} diff --git a/src/main/java/net/javase/onenet/enums/SignMethod.java b/src/main/java/net/javase/onenet/enums/SignMethod.java new file mode 100644 index 0000000..246df0d --- /dev/null +++ b/src/main/java/net/javase/onenet/enums/SignMethod.java @@ -0,0 +1,26 @@ +package net.javase.onenet.enums; + +/** + * SignMethod + * + * @author Frank + */ + +public enum SignMethod { + + /** + * SHA1 + */ + SHA1, + + /** + * MD5 + */ + MD5, + + /** + * SHA256 + */ + SHA256, + ; +} diff --git a/src/main/java/net/javase/onenet/exception/ApiException.java b/src/main/java/net/javase/onenet/exception/ApiException.java new file mode 100644 index 0000000..82bdc37 --- /dev/null +++ b/src/main/java/net/javase/onenet/exception/ApiException.java @@ -0,0 +1,28 @@ +package net.javase.onenet.exception; + +/** + * ApiException + * + * @author Frank + */ +public class ApiException extends RuntimeException { + + public ApiException() { + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable cause) { + super(message, cause); + } + + public ApiException(Throwable cause) { + super(cause); + } + + public ApiException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/net/javase/onenet/model/DataPointQueryModel.java b/src/main/java/net/javase/onenet/model/DataPointQueryModel.java new file mode 100644 index 0000000..e8a0848 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/DataPointQueryModel.java @@ -0,0 +1,73 @@ +package net.javase.onenet.model; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +/** + * DataPointQueryModel + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class DataPointQueryModel extends BaseModel { + + /** + * 数据流ID,多个id之间用逗号分开,缺省时取数据流或数据流模板100条为缺省数据流id条件 + */ + @ApiParam(name = "datastream_id") + private String dataStreamId; + + /** + * 产品名称 + */ + @ApiParam(name = "product_id") + private String productId; + + /** + * 设备名称 + */ + @ApiParam(name = "device_name") + private String deviceName; + + /** + * lwm2m协议时传,设备imei + */ + private String imei; + + /** + * 提取数据点的开始时间,精确到秒,示例:2015-01-10T08:00:35 + */ + private String start; + + /** + * 提取数据点的结束时间,精确到秒,示例:2015-01-10T08:00:35 + */ + private String end; + + /** + * 查询时间区间,单位为秒 + */ + private Integer duration; + + /** + * 限定本次请求最多返回的数据点数,默认100,范围为(0,6000] + */ + private Integer limit; + + /** + * 指定本次请求继续从cursor位置开始提取数据 + */ + private String cursor; + + /** + * 时间排序方式,DESC:倒序,ASC:升序,默认为DESC + */ + private String sort; + + +} diff --git a/src/main/java/net/javase/onenet/model/NbInstantModel.java b/src/main/java/net/javase/onenet/model/NbInstantModel.java new file mode 100644 index 0000000..13f0563 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/NbInstantModel.java @@ -0,0 +1,103 @@ +package net.javase.onenet.model; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +import java.util.Map; + +/** + * NbInstantModel + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class NbInstantModel extends BaseModel { + + /** + * nbiot设备的身份码,必填 + */ + @ApiParam(isQuery = true) + private String imei; + + /** + * true为取消订阅,false为订阅,必填 + */ + @ApiParam(isQuery = true) + private Boolean cancel; + + /** + * nbiot设备的object id , 对应到平台模型中为数据流id,必填 + */ + @ApiParam(name = "obj_id", isQuery = true) + private Integer objId; + + /** + * 设备object下具体一个instance的id ,对应到平台模型中数据点key值的一部分,选填 + */ + @ApiParam(name = "obj_inst_id", isQuery = true) + private Integer objInstId; + + /** + * nbiot设备的资源id,选填 + */ + @ApiParam(name = "res_id", isQuery = true) + private Integer resId; + + /** + * 上传数据的最小时间间隔,默认为0,此时有数据就上传 + */ + @ApiParam(isQuery = true) + private Integer pmin; + + /** + * 上传数据的最大时间间隔 + */ + @ApiParam(isQuery = true) + private Integer pmax; + + /** + * 当数据值大于该值时上传 + */ + @ApiParam(isQuery = true) + private Double gt; + + /** + * 当数据值小于该值时上传 + */ + @ApiParam(isQuery = true) + private Double lt; + + /** + * 当前后两个数据点值相差大于或者等于该值时 + */ + @ApiParam(isQuery = true) + private Double st; + + /** + * 超时时间,可选,默认25秒,取值范围[5,40] + */ + @ApiParam(isQuery = true) + private Integer timeout; + + /** + * write模式,只能为1或者2 + */ + @ApiParam(isQuery = true) + private Integer mode; + + /** + * 写设备资源的json数组,通过HTTP BODY提交,大小限制2k + */ + private Map data; + + /** + * 命令字符串,大小限制2KB + */ + private String args; + +} diff --git a/src/main/java/net/javase/onenet/model/NbOfflineModel.java b/src/main/java/net/javase/onenet/model/NbOfflineModel.java new file mode 100644 index 0000000..3b4e497 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/NbOfflineModel.java @@ -0,0 +1,97 @@ +package net.javase.onenet.model; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +import java.util.Map; + +/** + * NbOfflineModel 缓存命令 + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class NbOfflineModel extends BaseModel { + + /** + * nbiot设备的身份码,必填 + */ + @ApiParam(isQuery = true) + private String imei; + + /** + * nbiot设备的object id , 对应到平台模型中为数据流id,必填 + */ + @ApiParam(name = "obj_id", isQuery = true) + private Integer objId; + + /** + * 设备object下具体一个instance的id ,对应到平台模型中数据点key值的一部分,选填 + */ + @ApiParam(name = "obj_inst_id", isQuery = true) + private Integer objInstId; + + /** + * nbiot设备的资源id,选填 + */ + @ApiParam(name = "res_id", isQuery = true) + private Integer resId; + + /** + * 1:直接替换;2:局部更新 + */ + @ApiParam(isQuery = true) + private Integer mode; + + /** + * 命令开始生效时间,可选(不填时默认为OneNET当前时间),填写必须大于OneNET服务器的当前时间 + */ + @ApiParam(name = "valid_time", isQuery = true) + private String validTime; + + /** + * 命令过期时间,必须大于valid_time + */ + @ApiParam(name = "expired_time", isQuery = true) + private String expiredTime; + + /** + * 表示失败重试次数(等待下一次设备update或者上线),可选(不填时默认为3),填写时必须在[0, 10]之间 + */ + @ApiParam(isQuery = true) + private Integer retry; + + /** + * 命令触发的上行消息类型,填写时必须在[1,7]之间;不填写默认为7 + */ + @ApiParam(name = "trigger_msg", isQuery = true) + private Integer triggerMsg; + + /** + * 命令触发的上行消息类型,填写时必须在[1,7]之间;不填写默认为7 + */ + @ApiParam(isQuery = true) + private Boolean bin2hex; + + /** + * true/false,默认false,如果bin2hex为true,资源类型为Opaque的值将被转换成十六进制字符串返回 + */ + @ApiParam(isQuery = true) + private Integer timeout; + + /** + * 写设备资源的json,大小限制2k + */ + private Map data; + + /** + * 命令字符串,大小限制2KB + */ + private String args; + +} diff --git a/src/main/java/net/javase/onenet/model/SyncCmdsModel.java b/src/main/java/net/javase/onenet/model/SyncCmdsModel.java new file mode 100644 index 0000000..771baea --- /dev/null +++ b/src/main/java/net/javase/onenet/model/SyncCmdsModel.java @@ -0,0 +1,43 @@ +package net.javase.onenet.model; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +import java.util.Map; + +/** + * SyncCmdsModel + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class SyncCmdsModel extends BaseModel { + + /** + * 产品名称 + */ + @ApiParam(name = "product_id") + private String productId; + + /** + * 设备名称 + */ + @ApiParam(name = "device_name") + private String deviceName; + + /** + * 同步API最长等待时间,取值范围 5-30, 单位秒 + */ + private String timeout; + + /** + * 命令字符串,大小限制20KB + */ + @ApiParam(ignore = true) + private Map args; +} diff --git a/src/main/java/net/javase/onenet/model/base/BaseModel.java b/src/main/java/net/javase/onenet/model/base/BaseModel.java new file mode 100644 index 0000000..0a5f2d2 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/base/BaseModel.java @@ -0,0 +1,98 @@ +package net.javase.onenet.model.base; + +import cn.hutool.core.util.StrUtil; +import net.javase.onenet.annotation.ApiParam; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * BaseModel + * + * @author Frank + */ +public class BaseModel { + + /** + * This To Map + * + * @return {@link Map} + */ + public Map toMap() { + Map map = new HashMap<>(); + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + Object obj; + try { + field.setAccessible(true); + obj = field.get(this); + if (obj != null) { + ApiParam apiParam = field.getAnnotation(ApiParam.class); + if (apiParam != null) { + if (apiParam.ignore()) { + continue; + } + if (StrUtil.isNotBlank(apiParam.name())) { + map.put(apiParam.name(), obj); + continue; + } + } + map.put(field.getName(), obj); + } + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + return map; + } + + /** + * 获取参数map + * + * @return Map + */ + public Map> paramsMap() { + Map> params = new HashMap<>((int) ((2 / 0.75f) + 1)); + Map bodyMap = new HashMap<>(); + Map queryMap = new HashMap<>(); + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + Object obj; + try { + field.setAccessible(true); + obj = field.get(this); + if (obj != null) { + ApiParam apiParam = field.getAnnotation(ApiParam.class); + if (apiParam != null) { + if (apiParam.ignore()) { + continue; + } + if (StrUtil.isNotBlank(apiParam.name())) { + if (apiParam.isQuery()) { + queryMap.put(apiParam.name(), obj); + } else { + bodyMap.put(apiParam.name(), obj); + } + } else { + if (apiParam.isQuery()) { + queryMap.put(field.getName(), obj); + } else { + bodyMap.put(field.getName(), obj); + } + } + } else { + bodyMap.put(field.getName(), obj); + } + } + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + params.put("body", bodyMap); + params.put("query", queryMap); + return params; + } + + +} diff --git a/src/main/java/net/javase/onenet/model/device/DeviceEventLogModel.java b/src/main/java/net/javase/onenet/model/device/DeviceEventLogModel.java new file mode 100644 index 0000000..aa65132 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/device/DeviceEventLogModel.java @@ -0,0 +1,73 @@ +package net.javase.onenet.model.device; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +/** + * DeviceEventLogModel 设备事件记录查询 + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class DeviceEventLogModel extends BaseModel { + + /** + * 产品ID + */ + @ApiParam(name = "product_id") + protected String productId; + + /** + * 设备名称 + */ + @ApiParam(name = "device_name") + protected String deviceName; + + /** + * 设备imei (当设备来自于老平台下NB套件产品时,imei必填,且device_name应当为空) + */ + protected String imei; + + /** + * 查询起始时间-毫秒时间戳 + */ + @ApiParam(name = "start_time", isQuery = true) + private String startTime; + + /** + * 查询截止时间-毫秒时间戳 + */ + @ApiParam(name = "end_time", isQuery = true) + private String endTime; + + /** + * 事件功能点标识 + */ + @ApiParam(isQuery = true) + private String identifier; + + /** + * 事件类型,1-信息,2-告警,3-故障 + */ + @ApiParam(name = "event_type", isQuery = true) + private Integer eventType; + + /** + * 请求起始位置,默认0 + */ + @ApiParam(isQuery = true) + private Integer offset; + + /** + * 每次请求记录数,默认10,范围[1,100] + */ + @ApiParam(isQuery = true) + private Integer limit; + +} diff --git a/src/main/java/net/javase/onenet/model/device/DeviceGroupListModel.java b/src/main/java/net/javase/onenet/model/device/DeviceGroupListModel.java new file mode 100644 index 0000000..25e1ccc --- /dev/null +++ b/src/main/java/net/javase/onenet/model/device/DeviceGroupListModel.java @@ -0,0 +1,53 @@ +package net.javase.onenet.model.device; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +/** + * DeviceGroupListModel + *

+ * 设备分组列表
+ * 设备分组-设备列表 + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class DeviceGroupListModel extends BaseModel { + + /** + * 分组名称,从左模糊匹配 + */ + private String name; + + /** + * 设备分组标签key,必须与value一起出现,否则无效 + */ + private String key; + + /** + * 设备分组标签value,必须与key一起出现,否则无效 + */ + private String value; + + /** + * 分组ID + */ + @ApiParam(name = "group_id") + private String groupId; + + /** + * 请求起始位置,默认0 + */ + private String offset; + + /** + * 每次请求记录数,默认10,范围[1,100] + */ + private String limit; + +} diff --git a/src/main/java/net/javase/onenet/model/device/DeviceGroupModel.java b/src/main/java/net/javase/onenet/model/device/DeviceGroupModel.java new file mode 100644 index 0000000..8b544d7 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/device/DeviceGroupModel.java @@ -0,0 +1,43 @@ +package net.javase.onenet.model.device; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +import java.util.Map; + +/** + * DeviceGroupModel
+ * 新建设备分组和编辑设备分组 + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class DeviceGroupModel extends BaseModel { + + /** + * 分组ID, 编辑时必传 + */ + @ApiParam(name = "group_id") + private String groupId; + + /** + * 分组名称,由中英文、数字、短横线-、下划线_组成,开头首位必须是中英文,长度不超过64位 + */ + private String name; + + /** + * 分组描述,长度不超过100位 + */ + private String desc; + + /** + * 分组标签,格式为字典,字典key只能为1-16位英文数字,value长度不超过50 + */ + private Map tags; + +} diff --git a/src/main/java/net/javase/onenet/model/device/DeviceGroupOptModel.java b/src/main/java/net/javase/onenet/model/device/DeviceGroupOptModel.java new file mode 100644 index 0000000..36f3a00 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/device/DeviceGroupOptModel.java @@ -0,0 +1,40 @@ +package net.javase.onenet.model.device; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +/** + * DeviceGroupModel + *
+ * 设备分组-添加和删除设备 + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class DeviceGroupOptModel extends BaseModel { + + /** + * 分组ID + */ + @ApiParam(name = "group_id") + private String groupId; + + /** + * 产品ID + */ + @ApiParam(name = "product_id") + private String productId; + + /** + * 设备名称列表 + */ + @ApiParam(name = "device_name_list") + private String[] deviceNameList; + + +} diff --git a/src/main/java/net/javase/onenet/model/device/DeviceModel.java b/src/main/java/net/javase/onenet/model/device/DeviceModel.java new file mode 100644 index 0000000..3506088 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/device/DeviceModel.java @@ -0,0 +1,78 @@ +package net.javase.onenet.model.device; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +import java.util.List; + +/** + * DeviceModel + * + * @author Frank + */ +@Getter +@Setter +@Builder +@AllArgsConstructor +public class DeviceModel extends BaseModel { + + /** + * 产品名称 + */ + @ApiParam(name = "product_id") + private String productId; + + /** + * 设备名称 + */ + @ApiParam(name = "device_name") + private String deviceName; + + /** + * 设备描述 + */ + private String desc; + + /** + * 经度 + */ + private String lon; + + /** + * 纬度 + */ + private String lat; + + /** + * 设备标签,字符串数组 + */ + private List tags; + + /** + * LwM2M设备专有,当接入协议为LwM2M时必填,15位数字 + */ + private String imei; + + /** + * LwM2M设备专有,必填,1-15位数字 + */ + private String imsi; + + /** + * LwM2M设备专有,允许为空,当接入协议为LwM2M时该属性有效,
+ * 格式为英文字母、数字,长度为8-16位,若不传/传空则平台自动生成一个随机字符串作为psk + */ + private String psk; + + /** + * LwM2M设备专有,允许为空,格式为英文字母、数字,长度不超过16位 + */ + @ApiParam(name = "auth_code") + private String authCode; + +} diff --git a/src/main/java/net/javase/onenet/model/device/DeviceMoveModel.java b/src/main/java/net/javase/onenet/model/device/DeviceMoveModel.java new file mode 100644 index 0000000..193378d --- /dev/null +++ b/src/main/java/net/javase/onenet/model/device/DeviceMoveModel.java @@ -0,0 +1,37 @@ +package net.javase.onenet.model.device; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +/** + * DeviceMoveModel + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class DeviceMoveModel extends BaseModel { + + /** + * 产品ID + */ + @ApiParam(name = "product_id") + private String productId; + + /** + * 接收人账户,可以是手机号或者用户名 + */ + @ApiParam(name = "target_user_tel") + private String targetUserTel; + + /** + * 被转移设备的名称数组(对于NB设备只能是imei数组),
+ * 如["name_1", "name_2"],每个元素名称最长限制64位,数组元素不超过1000个 + */ + @ApiParam(name = "device_name") + private String[] deviceName; +} diff --git a/src/main/java/net/javase/onenet/model/device/DeviceResetSecKeyModel.java b/src/main/java/net/javase/onenet/model/device/DeviceResetSecKeyModel.java new file mode 100644 index 0000000..f03cb2c --- /dev/null +++ b/src/main/java/net/javase/onenet/model/device/DeviceResetSecKeyModel.java @@ -0,0 +1,43 @@ +package net.javase.onenet.model.device; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +/** + * DeviceResetSecKeyModel 更新设备sec_key + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class DeviceResetSecKeyModel extends BaseModel { + + /** + * 产品ID + */ + @ApiParam(name = "product_id") + protected String productId; + + /** + * 设备名称 + */ + @ApiParam(name = "device_name") + protected String deviceName; + + /** + * 设备imei (当设备来自于老平台下NB套件产品时,imei必填,且device_name应当为空) + */ + protected String imei; + + /** + * 设备最新sec_key,值格式为base64 encode后的字符串,
+ * 原始内容格式只能包含英文和数字,长度不超过32位,若不传则会随机生成 + */ + @ApiParam(name = "sec_key") + private String secKey; + +} diff --git a/src/main/java/net/javase/onenet/model/device/DeviceStatusHistoryModel.java b/src/main/java/net/javase/onenet/model/device/DeviceStatusHistoryModel.java new file mode 100644 index 0000000..df8d23b --- /dev/null +++ b/src/main/java/net/javase/onenet/model/device/DeviceStatusHistoryModel.java @@ -0,0 +1,61 @@ +package net.javase.onenet.model.device; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +/** + * DeviceStatusHistoryModel 设备状态变更记录 + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class DeviceStatusHistoryModel extends BaseModel { + + /** + * 产品ID + */ + @ApiParam(name = "product_id") + protected String productId; + + /** + * 设备名称 + */ + @ApiParam(name = "device_name") + protected String deviceName; + + /** + * 设备imei (当设备来自于老平台下NB套件产品时,imei必填,且device_name应当为空) + */ + protected String imei; + + /** + * 查询起始时间-毫秒时间戳 + */ + @ApiParam(name = "start_time", isQuery = true) + private String startTime; + + /** + * 查询截止时间-毫秒时间戳 + */ + @ApiParam(name = "end_time", isQuery = true) + private String endTime; + + /** + * 请求起始位置,默认0 + */ + @ApiParam(isQuery = true) + private Integer offset; + + /** + * 每次请求记录数,默认10,范围[1,100] + */ + @ApiParam(isQuery = true) + private Integer limit; + +} diff --git a/src/main/java/net/javase/onenet/model/tsl/ThingModel.java b/src/main/java/net/javase/onenet/model/tsl/ThingModel.java new file mode 100644 index 0000000..10a3cd6 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/tsl/ThingModel.java @@ -0,0 +1,52 @@ +package net.javase.onenet.model.tsl; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +import java.util.Map; + +/** + * ThingModel + *

+ * 设置设备属性 + *

+ * 设备服务调用 + *

+ * 设备属性期望设置 + *

+ * 设备属性期望删除 + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class ThingModel extends BaseModel { + + /** + * 产品名称 + */ + @ApiParam(name = "product_id") + private String productId; + + /** + * 设备名称 + */ + @ApiParam(name = "device_name") + private String deviceName; + + /** + * 属性功能点标识 + */ + private String identifier; + + /** + * 设置的属性值, 数据格式为json对象,形式为key:value,
+ * key为属性功能点标识, value为属性值,取值符合物模型定义的数据类型和取值范围, 例如{ "switch": true } + */ + private Map params; + +} diff --git a/src/main/java/net/javase/onenet/model/tsl/ThingQueryHistoryModel.java b/src/main/java/net/javase/onenet/model/tsl/ThingQueryHistoryModel.java new file mode 100644 index 0000000..887eed1 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/tsl/ThingQueryHistoryModel.java @@ -0,0 +1,62 @@ +package net.javase.onenet.model.tsl; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +/** + * ThingQueryHistoryModel + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class ThingQueryHistoryModel extends BaseModel { + + /** + * 产品名称 + */ + @ApiParam(name = "product_id") + private String productId; + + /** + * 设备名称 + */ + @ApiParam(name = "device_name") + private String deviceName; + + /** + * 属性功能点标识 + */ + private String identifier; + + /** + * 查询起始时间-毫秒时间戳 + */ + @ApiParam(name = "start_time") + private String startTime; + + /** + * 查询截止时间-毫秒时间戳 + */ + @ApiParam(name = "end_time") + private String endTime; + + /** + * 排序参数 1-正序 2-倒序 默认倒叙 + */ + private String sort; + + /** + * 请求起始位置,默认0 + */ + private String offset; + + /** + * 每次请求记录数,默认10,范围[1,100] + */ + private String limit; +} diff --git a/src/main/java/net/javase/onenet/model/tsl/ThingQueryModel.java b/src/main/java/net/javase/onenet/model/tsl/ThingQueryModel.java new file mode 100644 index 0000000..09f03f6 --- /dev/null +++ b/src/main/java/net/javase/onenet/model/tsl/ThingQueryModel.java @@ -0,0 +1,35 @@ +package net.javase.onenet.model.tsl; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.javase.onenet.annotation.ApiParam; +import net.javase.onenet.model.base.BaseModel; + +/** + * ThingQueryModel + * + * @author Frank + */ +@Getter +@Setter +@Builder +public class ThingQueryModel extends BaseModel { + + /** + * 产品名称 + */ + @ApiParam(name = "product_id") + private String productId; + + /** + * 设备名称 + */ + @ApiParam(name = "device_name") + private String deviceName; + + /** + * 功能点标识数组,expample: ["light","model"] + */ + private String[] params; +} diff --git a/src/main/java/net/javase/onenet/utils/Kv.java b/src/main/java/net/javase/onenet/utils/Kv.java new file mode 100644 index 0000000..11a1e7d --- /dev/null +++ b/src/main/java/net/javase/onenet/utils/Kv.java @@ -0,0 +1,31 @@ +package net.javase.onenet.utils; + +import java.util.HashMap; +import java.util.Map; + +/** + * Kv + * + * @author Frank + */ +public class Kv { + + private Map map; + + public Kv() { + this.map = new HashMap<>(); + } + + public Kv put(K key, V value) { + this.map.put(key, value); + return this; + } + + public Map build() { + return this.map; + } + + public static Kv create(K key, V value) { + return new Kv().put(key, value); + } +} diff --git a/src/main/java/net/javase/onenet/utils/RequestUtil.java b/src/main/java/net/javase/onenet/utils/RequestUtil.java new file mode 100644 index 0000000..b701b54 --- /dev/null +++ b/src/main/java/net/javase/onenet/utils/RequestUtil.java @@ -0,0 +1,81 @@ +package net.javase.onenet.utils; + +import cn.hutool.core.util.URLUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.Method; +import com.alibaba.fastjson.JSONObject; +import net.javase.onenet.api.ApiRequest; +import net.javase.onenet.api.ApiResponse; +import net.javase.onenet.exception.ApiException; + +import java.nio.charset.StandardCharsets; + +/** + * 请求工具 + * + * @author Frank + */ +public class RequestUtil { + + /** + * 发送请求 + * + * @param req request + * @param accessKey accessKey + * @return {@link ApiResponse} + */ + public static ApiResponse doRequest(ApiRequest req, String accessKey) { + return doRequest(req, accessKey, ApiResponse.class); + } + + /** + * 发送请求 + * + * @param req req + * @param accessKey accessKey + * @param clazz clazz + * @param T + * @return T + */ + public static T doRequest(ApiRequest req, String accessKey, Class clazz) { + Method method = req.getMethod(); + String url = req.getDomain().getDomain() + req.url(); + if (req.getQuery() != null && req.getQuery().size() > 0) { + String query = URLUtil.buildQuery(req.getQuery(), StandardCharsets.UTF_8); + url += "?" + query; + } + HttpRequest request = HttpRequest.of(url).method(method); + if (req.getContentType() != null) { + request.contentType(req.getContentType().toString()); + } + if (req.getBody() != null && req.getBody().size() > 0) { + request.body(JSONObject.toJSONString(req.getBody())); + } + + String expirationTime = String.valueOf((System.currentTimeMillis() / 1000) + 600); + String token = SignUtil.assembleToken(req.getVersion(), + req.getRes(), expirationTime, req.getSignMethod(), accessKey); + request.header("authorization", token); + return doRequest(request, clazz); + } + + + /** + * 发送请求 + * + * @param request {@link HttpRequest} + * @param clazz response class + * @param T + * @return response + */ + public static T doRequest(HttpRequest request, Class clazz) { + try (HttpResponse response = request.execute()) { + String body = response.body(); + System.out.println(body); + return JSONObject.parseObject(body, clazz); + } catch (Exception ex) { + throw new ApiException("请求异常", ex); + } + } +} diff --git a/src/main/java/net/javase/onenet/utils/SignUtil.java b/src/main/java/net/javase/onenet/utils/SignUtil.java new file mode 100644 index 0000000..498ec18 --- /dev/null +++ b/src/main/java/net/javase/onenet/utils/SignUtil.java @@ -0,0 +1,93 @@ +package net.javase.onenet.utils; + +import cn.hutool.core.util.URLUtil; +import net.javase.onenet.enums.SignMethod; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; + +/** + * SignUtil 签名工具 + * + * @author Frank + */ +public class SignUtil { + + /** + * 默认版本号 + */ + public static final String DEFAULT_VERSION = "2022-05-01"; + + /** + * 构建token + * + * @param version version + * @param resourceName resourceName + * @param expirationTime expirationTime + * @param signMethod signMethod + * @param accessKey accessKey + * @return token {@link String} + */ + public static String assembleToken(String version, + String resourceName, + String expirationTime, + SignMethod signMethod, + String accessKey) { + StringBuilder sb = new StringBuilder(); + String res = URLUtil.encodeAll(resourceName, StandardCharsets.UTF_8); + String sign = generatorSignature(version, resourceName, expirationTime, accessKey, signMethod.name().toLowerCase()); + sb.append("version=").append(version) + .append("&res=").append(res) + .append("&et=").append(expirationTime) + .append("&method=").append(signMethod.name().toLowerCase()) + .append("&sign=").append(URLUtil.encodeAll(sign, StandardCharsets.UTF_8)); + return sb.toString(); + } + + /** + * 生成sign + * + * @param version version + * @param resourceName resourceName + * @param expirationTime expirationTime + * @param accessKey accessKey + * @param signatureMethod signatureMethod + * @return sign + */ + public static String generatorSignature(String version, + String resourceName, + String expirationTime, + String accessKey, + String signatureMethod) { + String encryptText = expirationTime + "\n" + signatureMethod + "\n" + resourceName + "\n" + version; + byte[] bytes = hmacEncrypt(encryptText, accessKey, signatureMethod); + return Base64.getEncoder().encodeToString(bytes); + } + + /** + * 加密 + * + * @param data data + * @param key key + * @param signatureMethod signatureMethod + * @return 加密后数据 + */ + public static byte[] hmacEncrypt(String data, String key, String signatureMethod) { + String instanceName = "Hmac" + signatureMethod.toUpperCase(); + SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), instanceName); + try { + Mac mac = Mac.getInstance(instanceName); + mac.init(secretKey); + return mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("不支持的签名算法", e); + } catch (InvalidKeyException e) { + throw new RuntimeException("无效秘钥", e); + } + } + +} diff --git a/src/test/java/net/javase/onenet/test/TestSign.java b/src/test/java/net/javase/onenet/test/TestSign.java new file mode 100644 index 0000000..d2156e8 --- /dev/null +++ b/src/test/java/net/javase/onenet/test/TestSign.java @@ -0,0 +1,47 @@ +package net.javase.onenet.test; + +import net.javase.onenet.enums.SignMethod; +import net.javase.onenet.utils.SignUtil; +import org.junit.Test; + +/** + * TestSign sign生成测试 + * + * @author Frank + */ +public class TestSign { + + /** + * accessKey + */ + static String KEY = ""; + + /** + * 用户ID + */ + static String USERID = ""; + + /** + * sign生成 + */ + @Test + public void testSign() { + String resourceName = "userid/" + USERID; + String expirationTime = String.valueOf((System.currentTimeMillis() / 1000) + 600); + String sign = SignUtil.generatorSignature(SignUtil.DEFAULT_VERSION, + resourceName, expirationTime, KEY, SignMethod.MD5.name().toLowerCase()); + System.out.println(sign); + } + + /** + * token生成 + */ + @Test + public void testToken() { + String resourceName = "userid/" + USERID; + String expirationTime = String.valueOf((System.currentTimeMillis() / 1000) + 600); + String token = SignUtil.assembleToken(SignUtil.DEFAULT_VERSION, + resourceName, expirationTime, SignMethod.MD5, KEY); + System.out.println("authorization: " + token); + } +}