diff --git a/src/main/java/com/example/zxweb/common/constant/enums/IotApiPathsEnum.java b/src/main/java/com/example/zxweb/common/constant/enums/IotApiPathsEnum.java new file mode 100644 index 0000000..609fde4 --- /dev/null +++ b/src/main/java/com/example/zxweb/common/constant/enums/IotApiPathsEnum.java @@ -0,0 +1,121 @@ +package com.example.zxweb.common.constant.enums; + + +/** + * @Description: IOT设备API接口路径 + * @author: ZhouWenTao + * @date: 2023/9/8 12:05 + */ +public enum IotApiPathsEnum { + + /** + * 获取单个设备信息 GET,query + */ + get_devices("/devices", "获取单个设备信息"), + + /** + * 获取设备列表 GET,query + */ + get_devices_list("/devices/list", "获取设备列表"), + + /** + * 向设备发送消息 POST,body + */ + post_devices_datastreams("/devices/datastreams", "向设备发送消息"), + + /** + * 查询设备历史数据 GET + */ + get_devices_datastreams("/devices/datastreams", "查询设备历史数据"), + + /** + * 查询消息是否下达到设备 GET + */ + get_devices_datastreams_state("/devices/datastreams/state", "查询消息是否下达到设备"), + + /** + * 查询事件历史数据 GET + */ + get_devices_events("/devices/events", "查询事件历史数据"), + + /** + * 向设备发送方法 POST,body + */ + post_devices_methods("/devices/methods", "向设备发送方法"), + + /** + * 查询方法历史数据 GET + */ + get_devices_methods("/devices/methods", "查询方法历史数据"), + + + ; + + + /** + * 地址 + */ + String path; + /** + * 描述 + */ + String text; + + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getText(){ + return text; + } + + public void setText(String text) { + this.text = text; + } + + /** + * 构造器 + * + * @param path 地址 + * @param text 描述 + */ + IotApiPathsEnum(String path, String text) { + this.path = path; + this.text = text; + } + + + /** + * 根据描述匹配 + * + * @param path 请求地址 + * @return String 描述 + */ + public static String getTextByPath(String path){ + for (IotApiPathsEnum e : IotApiPathsEnum.values()) { + if (path.startsWith(e.getPath())) { + return e.getText(); + } + } + return null; + } + + /** + * 根据路径描述获取路径 + * @param text 描述 + * @return + */ + public static String getPathByText(String text){ + for (IotApiPathsEnum e : IotApiPathsEnum.values()) { + if (text.startsWith(e.getText())) { + return e.getPath(); + } + } + return null; + } +} diff --git a/src/main/java/com/example/zxweb/common/constant/enums/RmsApiEnum.java b/src/main/java/com/example/zxweb/common/constant/enums/RmsApiEnum.java new file mode 100644 index 0000000..52fa104 --- /dev/null +++ b/src/main/java/com/example/zxweb/common/constant/enums/RmsApiEnum.java @@ -0,0 +1,92 @@ +package com.example.zxweb.common.constant.enums; + + +/** + * @Description: IOT设备API接口路径 + * @author: ZhouWenTao + * @date: 2023/9/8 13:05 + */ +public enum RmsApiEnum { + //https://docs.qq.com/doc/DVWxxY0hOdkxYaEJH + + /** + * 系统登陆 + * 本接口用于系统启用token验证功能调用,登陆成功即可,其它接口无须传token值,token1小时有效,账号和密码可联系技术人员获取。 + */ + post_auth_login("/rms/auth/login","系统登陆"), + + /** + * 访客查询 + * 本接口用于访客信息查询,查询出访客登记的所有信息,建议查询条件为当天时间+状态查询,不易跨月,多天的频繁调用,对服务压力大,查询结果为倒序排序。 + */ + post_fkterminal_findAccessRecord("/rms/fkterminal/findAccessRecord","访客查询"), + ; + + + /** + * 接口地址 + */ + String api; + /** + * 描述 + */ + String text; + + + public String getApi() { + return api; + } + + public void setApi(String api) { + this.api = api; + } + + public String getText(){ + return text; + } + + public void setText(String text) { + this.text = text; + } + + /** + * 构造器 + * + * @param api 地址 + * @param text 描述 + */ + RmsApiEnum(String api, String text) { + this.api = api; + this.text = text; + } + + + /** + * 根据 接口地址 匹配 + * + * @param api 接口地址 + * @return String 描述 + */ + public static String getTextByApi(String api){ + for (RmsApiEnum e : RmsApiEnum.values()) { + if (api.startsWith(e.getApi())) { + return e.getText(); + } + } + return null; + } + + /** + * 根据 描述 匹配 + * @param text 描述 + * @return + */ + public static String getApiByText(String text){ + for (RmsApiEnum e : RmsApiEnum.values()) { + if (text.startsWith(e.getText())) { + return e.getApi(); + } + } + return null; + } +} diff --git a/src/main/java/com/example/zxweb/controller/IotController.java b/src/main/java/com/example/zxweb/controller/IotController.java new file mode 100644 index 0000000..b640af1 --- /dev/null +++ b/src/main/java/com/example/zxweb/controller/IotController.java @@ -0,0 +1,40 @@ +package com.example.zxweb.controller; + +import com.example.zxweb.common.api.vo.Result; +import com.example.zxweb.common.constant.enums.IotApiPathsEnum; +import com.example.zxweb.utils.AssertUtils; +import com.example.zxweb.utils.IotUtils; +import com.example.zxweb.utils.RestUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @Description + * @Author ZhouWenTao + * @Date 2023/9/8 11:43 + */ +@RestController +@RequestMapping("/iot") +@Slf4j +@Api(tags = "设备管理") +public class IotController { + + @ApiOperation(value = "获取单个设备信息") + @GetMapping(value = "/devices") + public Result devices(@RequestParam(value = "serial",defaultValue = "")String serial,@RequestParam(value = "productId",defaultValue = "")String productId){ + AssertUtils.notEmpty(serial,"请输入-[serial]");AssertUtils.notEmpty(productId,"请输入-[productId]"); + Map queryData=new LinkedHashMap<>(); + queryData.put("serial",serial); + queryData.put("productId",productId); + //请求数据 + return Result.OK(IotUtils.getApi(IotApiPathsEnum.getPathByText("获取单个设备信息"),queryData)); + } +} diff --git a/src/main/java/com/example/zxweb/controller/RmsController.java b/src/main/java/com/example/zxweb/controller/RmsController.java new file mode 100644 index 0000000..72ccf32 --- /dev/null +++ b/src/main/java/com/example/zxweb/controller/RmsController.java @@ -0,0 +1,57 @@ +package com.example.zxweb.controller; + +import com.alibaba.fastjson.JSONObject; +import com.example.zxweb.common.api.vo.Result; +import com.example.zxweb.common.constant.enums.IotApiPathsEnum; +import com.example.zxweb.utils.AssertUtils; +import com.example.zxweb.utils.IotUtils; +import com.example.zxweb.utils.RmsUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @Description 访客机 + * @Author ZhouWenTao + * @Date 2023/9/8 13:16 + */ +@RestController +@RequestMapping("/rms") +@Slf4j +@Api(tags = "访客机") +public class RmsController { + @ApiOperation(value = "访客查询") + @PostMapping(value = "/fkterminal/findAccessRecord") + public Result fkterminalFindAccessRecord(@RequestBody JSONObject requestBody){ + JSONObject responseBody = RmsUtils.fkterminalFindAccessRecord(requestBody); + responseBody.remove("msg"); + responseBody.remove("code"); + responseBody.remove("success"); + return Result.OK(responseBody); + } + + @ApiOperation(value = "访客预约") + @PostMapping(value = "/sync/orderrecord") + public Result syncOrderrecord(@RequestBody JSONObject requestBody){ + JSONObject responseBody = RmsUtils.syncOrderrecord(requestBody); + responseBody.remove("msg"); + responseBody.remove("code"); + responseBody.remove("success"); + return Result.OK(responseBody); + } + + @ApiOperation(value = "访客注销") + @PostMapping(value = "/fkterminal/recoverCard") + public Result fkterminalRecoverCard(@RequestBody JSONObject requestBody){ + JSONObject responseBody = RmsUtils.fkterminalRecoverCard(requestBody); + responseBody.remove("msg"); + responseBody.remove("code"); + responseBody.remove("success"); + return Result.OK(responseBody); + } + +} diff --git a/src/main/java/com/example/zxweb/exception/Business401Exception.java b/src/main/java/com/example/zxweb/exception/Business401Exception.java new file mode 100644 index 0000000..33a2ae3 --- /dev/null +++ b/src/main/java/com/example/zxweb/exception/Business401Exception.java @@ -0,0 +1,24 @@ +package com.example.zxweb.exception; + +/** + * @Description: bussiness自定义401异常 + * @Author ZhouWenTao + * @Date 2023/9/8 11:46 + */ +public class Business401Exception extends RuntimeException { + private static final long serialVersionUID = 1L; + + public Business401Exception(String message){ + super(message); + } + + public Business401Exception(Throwable cause) + { + super(cause); + } + + public Business401Exception(String message, Throwable cause) + { + super(message,cause); + } +} diff --git a/src/main/java/com/example/zxweb/exception/BusinessException.java b/src/main/java/com/example/zxweb/exception/BusinessException.java new file mode 100644 index 0000000..c82ef46 --- /dev/null +++ b/src/main/java/com/example/zxweb/exception/BusinessException.java @@ -0,0 +1,24 @@ +package com.example.zxweb.exception; + +/** + * @Description: 自定义异常 + * @Author ZhouWenTao + * @Date 2023/9/8 11:46 + */ +public class BusinessException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public BusinessException(String message){ + super(message); + } + + public BusinessException(Throwable cause) + { + super(cause); + } + + public BusinessException(String message, Throwable cause) + { + super(message,cause); + } +} diff --git a/src/main/java/com/example/zxweb/exception/BusinessExceptionHandler.java b/src/main/java/com/example/zxweb/exception/BusinessExceptionHandler.java new file mode 100644 index 0000000..a3d4d0c --- /dev/null +++ b/src/main/java/com/example/zxweb/exception/BusinessExceptionHandler.java @@ -0,0 +1,130 @@ +package com.example.zxweb.exception; + +import com.example.zxweb.common.api.vo.Result; +import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.http.HttpStatus; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.multipart.MaxUploadSizeExceededException; +import org.springframework.web.servlet.NoHandlerFoundException; + +/** + * 异常处理器 + * @Description + * @Author ZhouWenTao + * @Date 2023/9/8 11:46 + */ +@RestControllerAdvice +@Slf4j +public class BusinessExceptionHandler { + + /** + * 处理自定义异常 + */ + @ExceptionHandler(BusinessException.class) + public Result handleBusinessException(BusinessException e){ + log.error(e.getMessage(), e); + return Result.error(e.getMessage()); + } + + /** + * 处理自定义微服务异常 + */ + /*@ExceptionHandler(JeecgCloudException.class) + public Result handleJeecgCloudException(JeecgCloudException e){ + log.error(e.getMessage(), e); + return Result.error(e.getMessage()); + }*/ + + /** + * 处理自定义异常 + */ + @ExceptionHandler(Business401Exception.class) + @ResponseStatus(HttpStatus.UNAUTHORIZED) + public Result handleJeecgBoot401Exception(Business401Exception e){ + log.error(e.getMessage(), e); + return new Result(401,e.getMessage()); + } + + @ExceptionHandler(NoHandlerFoundException.class) + public Result handlerNoFoundException(Exception e) { + log.error(e.getMessage(), e); + return Result.error(404, "路径不存在,请检查路径是否正确"); + } + + @ExceptionHandler(DuplicateKeyException.class) + public Result handleDuplicateKeyException(DuplicateKeyException e){ + log.error(e.getMessage(), e); + return Result.error("数据库中已存在该记录"); + } + + /*@ExceptionHandler({UnauthorizedException.class, AuthorizationException.class}) + public Result handleAuthorizationException(AuthorizationException e){ + log.error(e.getMessage(), e); + return Result.noauth("没有权限,请联系管理员授权"); + }*/ + + /*@ExceptionHandler(Exception.class) + public Result handleException(Exception e){ + log.error(e.getMessage(), e); + //update-begin---author:zyf ---date:20220411 for:处理Sentinel限流自定义异常 + Throwable throwable = e.getCause(); + SentinelErrorInfoEnum errorInfoEnum = SentinelErrorInfoEnum.getErrorByException(throwable); + if (ObjectUtil.isNotEmpty(errorInfoEnum)) { + return Result.error(errorInfoEnum.getError()); + } + //update-end---author:zyf ---date:20220411 for:处理Sentinel限流自定义异常 + return Result.error("操作失败,"+e.getMessage()); + }*/ + + /** + * @Author 政辉 + * @param e + * @return + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public Result httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){ + StringBuffer sb = new StringBuffer(); + sb.append("不支持"); + sb.append(e.getMethod()); + sb.append("请求方法,"); + sb.append("支持以下"); + String [] methods = e.getSupportedMethods(); + if(methods!=null){ + for(String str:methods){ + sb.append(str); + sb.append("、"); + } + } + log.error(sb.toString(), e); + //return Result.error("没有权限,请联系管理员授权"); + return Result.error(405,sb.toString()); + } + + /** + * spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException + */ + @ExceptionHandler(MaxUploadSizeExceededException.class) + public Result handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) { + log.error(e.getMessage(), e); + return Result.error("文件大小超出10MB限制, 请压缩或降低文件质量! "); + } + + @ExceptionHandler(DataIntegrityViolationException.class) + public Result handleDataIntegrityViolationException(DataIntegrityViolationException e) { + log.error(e.getMessage(), e); + //【issues/3624】数据库执行异常handleDataIntegrityViolationException提示有误 #3624 + return Result.error("执行数据库异常,违反了完整性例如:违反惟一约束、违反非空限制、字段内容超出长度等"); + } + + /*@ExceptionHandler(PoolException.class) + public Result handlePoolException(PoolException e) { + log.error(e.getMessage(), e); + return Result.error("Redis 连接异常!"); + }*/ + +} diff --git a/src/main/java/com/example/zxweb/utils/AssertUtils.java b/src/main/java/com/example/zxweb/utils/AssertUtils.java new file mode 100644 index 0000000..fce3952 --- /dev/null +++ b/src/main/java/com/example/zxweb/utils/AssertUtils.java @@ -0,0 +1,87 @@ +package com.example.zxweb.utils; + +import com.example.zxweb.exception.BusinessException; +import org.apache.commons.lang.StringUtils; + +import java.util.List; +/** + * @Description 变量校验工具 + * @Author ZhouWenTao + * @Date 2023/6/26 19:14 + */ +public abstract class AssertUtils { + /** + * 判断真假值 + * @param flag + * @param message + */ + public static void isTrue(boolean flag, String message) { + if (!flag) { + throw new BusinessException(message); + } + } + + /** + * true时拦截 + * @param flag + * @param message + */ + public static void notTrue(boolean flag, String message) { + if (flag) { + throw new BusinessException(message); + } + } + + public static void notNull(Object object, String message) { + if (object == null) { + throw new BusinessException(message); + } + } + + public static void isEmpty(String str, String message) { + if (StringUtils.isNotBlank(str)) { + throw new BusinessException(message); + } + } + + public static void notEmpty(String str, String message) { + if (StringUtils.isBlank(str)) { + throw new BusinessException(message); + } + } + + /** + * 校验Array 不可为空/不可空数据 + * @param list + * @param message + */ + public static void hasSize(List list,String message){ + if (list==null || list.size()==0) { + throw new BusinessException(message); + } + } + + /** + * 校验Array 不可为空/不可空数据 + * @param list + * @param message + */ + public static void hasSize(Object[] list,String message){ + if (list==null || list.length==0) { + throw new BusinessException(message); + } + } + + /** + * 判断字符串长度 + * @param o 判读对象 + * @param len 字符串长度,不可超过 + * @param message 异常提示 + */ + public static void checkLength(Object o,Integer len,String message){ + notNull(o,"<"+message+">判断之前参数不可空!"); + if (o.toString().length()>len) { + throw new BusinessException(message); + } + } +} diff --git a/src/main/java/com/example/zxweb/utils/IotUtils.java b/src/main/java/com/example/zxweb/utils/IotUtils.java new file mode 100644 index 0000000..8c38241 --- /dev/null +++ b/src/main/java/com/example/zxweb/utils/IotUtils.java @@ -0,0 +1,31 @@ +package com.example.zxweb.utils; + +import com.alibaba.fastjson.JSONObject; +import com.example.zxweb.common.constant.enums.IotApiPathsEnum; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @Description ios 设备请求工具 + * @Author ZhouWenTao + * @Date 2023/9/8 11:59 + */ +@Component +public class IotUtils { + //请求服务地址 + private static final String API_PREFIX = "https://10.0.10.153:2443/api/iot/v1"; + + public static JSONObject getApi(String apiUrl,Map queryData) { + StringBuilder sb=new StringBuilder(); + int i=0; + for (String field : queryData.keySet()) { + String value = (String) queryData.get(field); + sb.append(i==0?"?":"&"); + sb.append(field).append("=").append(value); + i++; + } + JSONObject jsonObject = RestUtil.get(API_PREFIX+apiUrl + sb); + return jsonObject; + } +} diff --git a/src/main/java/com/example/zxweb/utils/RestUtil.java b/src/main/java/com/example/zxweb/utils/RestUtil.java new file mode 100644 index 0000000..2053a0a --- /dev/null +++ b/src/main/java/com/example/zxweb/utils/RestUtil.java @@ -0,0 +1,320 @@ +package com.example.zxweb.utils; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.springframework.http.*; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Iterator; +import java.util.Map; + +/** + * 调用 Restful 接口 Util + * + * @author sunjianlei + */ +@Slf4j +public class RestUtil { + + private static String domain = null; + private static String path = null; + + /*private static String getDomain() { + if (domain == null) { + domain = SpringContextUtils.getDomain(); + // issues/2959 + // 微服务版集成企业微信单点登录 + // 因为微服务版没有端口号,导致 SpringContextUtils.getDomain() 方法获取的域名的端口号变成了:-1所以出问题了,只需要把这个-1给去掉就可以了。 + String port=":-1"; + if (domain.endsWith(port)) { + domain = domain.substring(0, domain.length() - 3); + } + } + return domain; + } + + private static String getPath() { + if (path == null) { + path = SpringContextUtils.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path"); + } + return oConvertUtils.getString(path); + } + + public static String getBaseUrl() { + String basepath = getDomain() + getPath(); + log.info(" RestUtil.getBaseUrl: " + basepath); + return basepath; + }*/ + + /** + * RestAPI 调用器 + */ + private static RestTemplate RT; + + static { + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setConnectTimeout(30*1000); + requestFactory.setReadTimeout(30*1000); + RT = new RestTemplate(requestFactory); + // 解决乱码问题 + RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + } + + public static RestTemplate getRestTemplate() { + return RT; + } + + /** + * 发送 get 请求 + */ + public static JSONObject get(String url) { + return getNative(url, null, null).getBody(); + } + + /** + * 发送 get 请求 + */ + public static JSONObject get(String url, JSONObject variables) { + return getNative(url, variables, null).getBody(); + } + + /** + * 发送 get 请求 + */ + public static JSONObject get(String url, JSONObject variables, JSONObject params) { + return getNative(url, variables, params).getBody(); + } + + /** + * 发送 get 请求,返回原生 ResponseEntity 对象 + */ + public static ResponseEntity getNative(String url, JSONObject variables, JSONObject params) { + return request(url, HttpMethod.GET, variables, params,null); + } + + /** + * 发送 Post 请求 + */ + public static JSONObject post(String url) { + return postNative(url, null, null,null).getBody(); + } + + /** + * 发送 Post 请求 + */ + public static JSONObject post(String url, JSONObject params,JSONObject headers) { + return postNative(url, null, params,headers).getBody(); + } + + /** + * 发送 Post 请求 + */ + public static JSONObject post(String url, JSONObject variables, JSONObject params,JSONObject headers) { + return postNative(url, variables, params,headers).getBody(); + } + + /** + * 发送 POST 请求,返回原生 ResponseEntity 对象 + */ + public static ResponseEntity postNative(String url, JSONObject variables, JSONObject params,JSONObject headers) { + return request(url, HttpMethod.POST, variables, params,headers); + } + + /** + * 发送 put 请求 + */ + public static JSONObject put(String url) { + return putNative(url, null, null,null).getBody(); + } + + /** + * 发送 put 请求 + */ + public static JSONObject put(String url, JSONObject params) { + return putNative(url, null, params,null).getBody(); + } + + /** + * 发送 put 请求 + */ + public static JSONObject put(String url, JSONObject variables, JSONObject params,JSONObject headers) { + return putNative(url, variables, params,headers).getBody(); + } + + /** + * 发送 put 请求,返回原生 ResponseEntity 对象 + */ + public static ResponseEntity putNative(String url, JSONObject variables, JSONObject params,JSONObject headers) { + return request(url, HttpMethod.PUT, variables, params,headers); + } + + /** + * 发送 delete 请求 + */ + public static JSONObject delete(String url) { + return deleteNative(url, null, null).getBody(); + } + + /** + * 发送 delete 请求 + */ + public static JSONObject delete(String url, JSONObject variables, JSONObject params) { + return deleteNative(url, variables, params).getBody(); + } + + /** + * 发送 delete 请求,返回原生 ResponseEntity 对象 + */ + public static ResponseEntity deleteNative(String url, JSONObject variables, JSONObject params) { + return request(url, HttpMethod.DELETE, null, variables, params, JSONObject.class); + } + + /** + * 发送请求 + */ + public static ResponseEntity request(String url, HttpMethod method, JSONObject variables, JSONObject params,JSONObject header) { + HttpHeaders headers=null; + if (header==null) { + headers = getHeaderApplicationJson(); + }else{ + headers= new HttpHeaders(); + for (String s : header.keySet()) { + /*if ("Authorization".equals(s)) { + JSONObject jsonObject = header.getJSONObject(s); + String username = jsonObject.getString("username"); + String password = jsonObject.getString("password"); + String auth = username + ":" + password; + String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8)); + headers.add(org.apache.hc.core5.http.HttpHeaders.AUTHORIZATION,"Basic " + encodedAuth); + continue; + }*/ + headers.add(s,header.getString(s)); + } + } + return request(url, method, headers, variables, params, JSONObject.class); + } + + /** + * 发送请求 + * + * @param url 请求地址 + * @param method 请求方式 + * @param headers 请求头 可空 + * @param variables 请求url参数 可空 + * @param params 请求body参数 可空 + * @param responseType 返回类型 + * @return ResponseEntity + */ + public static ResponseEntity request(String url, HttpMethod method, HttpHeaders headers, JSONObject variables, Object params, Class responseType) { + log.info(" RestUtil --- request --- url = "+ url); + if (StringUtils.isEmpty(url)) { + throw new RuntimeException("url 不能为空"); + } + if (method == null) { + throw new RuntimeException("method 不能为空"); + } + if (headers == null) { + headers = new HttpHeaders(); + } + // 请求体 + String body = ""; + if (params != null) { + if (params instanceof JSONObject) { + body = ((JSONObject) params).toJSONString(); + + } else { + body = params.toString(); + } + } + // 拼接 url 参数 + if (variables != null && !variables.isEmpty()) { + url += ("?" + asUrlVariables(variables)); + } + /* + try { + SslUtils.ignoreSsl(); + } catch (Exception e) { + e.printStackTrace(); + }*/ + // 发送请求 + HttpEntity request = new HttpEntity<>(body, headers); + //回调接口 + if (url.contains("callback")) { + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setConnectTimeout(30000); + requestFactory.setReadTimeout(30000); + RT = new RestTemplate(requestFactory); + }else{ + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setConnectTimeout(300 *1000); + requestFactory.setReadTimeout(300* 1000); + RT = new RestTemplate(requestFactory); + } + // 解决乱码问题 + RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + return RT.exchange(url, method, request, responseType); + } + + /** + * 获取JSON请求头 + */ + public static HttpHeaders getHeaderApplicationJson() { + return getHeader(MediaType.APPLICATION_JSON_UTF8_VALUE); + } + + /** + * 获取请求头 + */ + public static HttpHeaders getHeader(String mediaType) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.parseMediaType(mediaType)); + headers.add("Accept", mediaType); + return headers; + } + + /** + * 将 JSONObject 转为 a=1&b=2&c=3...&n=n 的形式 + */ + public static String asUrlVariables(JSONObject variables) { + Map source = variables.getInnerMap(); + Iterator it = source.keySet().iterator(); + StringBuilder urlVariables = new StringBuilder(); + while (it.hasNext()) { + String key = it.next(); + String value = ""; + Object object = source.get(key); + if (object != null) { + if (!StringUtils.isEmpty(object.toString())) { + value = object.toString(); + } + } + urlVariables.append("&").append(key).append("=").append(value); + } + // 去掉第一个& + return urlVariables.substring(1); + } + + /*public static JSONObject postTest(String httpUrl,JSONObject requestBodyJson){ + RestTemplate restTemplate = null; + try { + restTemplate = new RestTemplate(RestTemplateConfig.generateHttpRequestFactory()); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (KeyManagementException e) { + e.printStackTrace(); + } catch (KeyStoreException e) { + e.printStackTrace(); + } + String result = HttpUtil.post(httpUrl, requestBodyJson.toJSONString()); + //打开建立连接 + log.debug("post_responseBody:"); + log.debug(result); + //获取返回结果 + return JSONObject.parseObject(result); + }*/ +} diff --git a/src/main/java/com/example/zxweb/utils/RmsUtils.java b/src/main/java/com/example/zxweb/utils/RmsUtils.java new file mode 100644 index 0000000..2901979 --- /dev/null +++ b/src/main/java/com/example/zxweb/utils/RmsUtils.java @@ -0,0 +1,104 @@ +package com.example.zxweb.utils; + +import com.alibaba.fastjson.JSONObject; +import com.example.zxweb.common.constant.enums.RmsApiEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; +import springfox.documentation.spring.web.json.Json; + +/** + * @Description 访客机工具类 + * @Author ZhouWenTao + * @Date 2023/9/8 13:18 + */ +@Component +@Slf4j +public class RmsUtils { + private static String TOKEN; + private static JSONObject header=new JSONObject(); + static { + //请求头 + header=new JSONObject(); + header.put("AppCode","42142fd0jkbf4515853b7fcec64748f6"); + header.put("devid","68EDA45C54F3"); + //获取TOKEN + //getToken(); + //header.put("TOKEN",TOKEN); + } + + + public static void getToken() { + JSONObject requestBody = JSONObject.parseObject("{\"email\":\"admin\", \"pswd\":\"cf79ae6addba60ad018347359bd144d2\"}"); + JSONObject responseBody = RestUtil.post(RmsApiEnum.getApiByText("系统登陆"), requestBody, header); + AssertUtils.notNull(responseBody,"获取TOKEN失败"); + String code = responseBody.getString("code"); + String msg = responseBody.getString("msg"); + AssertUtils.isTrue("0".equals(code),"获取TOKEN出错:"+msg); + JSONObject content = responseBody.getJSONObject("content"); + TOKEN = content.getString("token"); + } + + /** + * 访客查询 + * 本接口用于访客信息查询,查询出访客登记的所有信息,建议查询条件为当天时间+状态查询,不易跨月,多天的频繁调用,对服务压力大,查询结果为倒序排序。 + * @param requestBody {"starttime":"2022-11-09","status":"0","num":1,"pageNum":1,"endtime":"2022-11-09"} + * @return {"code":0,"msg":"成功","pagecount":2,"pageNum":1,"content":[{"id":85,"rcode":"1486300085","parentid":null,"vid":88,"visitor":{"id":88,"name":"王麻子","sex":"男","nation":"汉","birthday":null,"idnum":"a543546aef4bdd46ac957554f3c4f8cd222498dd2c2d56d1a9e5939469930619","idnumAdd":"123456123456","idnumCipher":"04e08e6ebddced2dd94b588e039096a2111f8be98f9eb79e365a3443c697d699ac9f08b892821e2b3b4e22b54203084b4e111329918b810c2fc480637c830e2fe909a7b4e75c18c91da3a163441ea36123ca105526b68c11e570e6869bc4c6121825f116905de9107c1d7832b7","photo":null,"sitePhoto":null,"issuing":null,"validitydatestart":null,"validitydateend":null,"phone":"84537d95e88ce687e4efab251a746c7318dbe7cc2f6cecbb0840ce4889e7a2a5","phoneAdd":"13900074111","phoneCipher":"04d176b602a7ad1c6b9784adc7adef54e90c7e771f04aba9ca66c3cf3abfa0cc6163203fb4c1017381a7ccc6a396150af3070efa193cfc22d128294bc58a52705077cbba29dc322072e95815d5ed19e92ee7b2f2c0470e4e15ae0eb15fa8540df61b07dfd4a1256955bbd019","startTime":null,"endTime":null,"pinYin":"wmz","syncId":null,"companyCode":null,"isbindfinger":0,"isbindface":0,"wltPhoto":null,"tabTime":null,"uploadTime":null,"isVip":0,"sheetSize":null,"idphoto":null},"uid":20653,"user":{"id":20653,"nickname":"张三","userpinyin":null,"email":"abc10110","pswd":null,"terminalpswd":null,"createTime":null,"lastLoginTime":null,"status":1,"sex":1,"nation":null,"nations":null,"birthday":null,"address":null,"idNum":"1304331989111111","photo":"\\image\\idpic\\1304331989111111_20221108143849677.png","issuing":null,"validityDateStart":null,"validityDateEnd":null,"phone":"13931021490","dep":null,"depID":1049,"depSyncId":null,"depName":null,"telephone":"010123456","ecardNum":"12345678","ecardEndTime":"2042-11-30 00:00:00","pinYin":null,"syncId":"abc10110","companyNum":null,"sta":null,"imIP":null,"imTime":null,"entranceGuards":null,"isbindface":null,"visitable":null,"tabTime":null,"uploadTime":null,"idphoto":null,"plateNo":null,"plateTime":null,"plateIssue":null},"dept":{"id":1049,"value":"子级部门1","pinyin":"zjbm1","parentId":null,"syncId":"abc123","syncParentId":null,"companyNum":null,"sta":null,"visitable":null,"sortnum":null,"tabTime":null,"uploadTime":null},"createtime":"2022-11-09 13:44:46","starttime":"2022-11-09 13:44:00","endtime":"2022-11-09 23:59:00","logofftime":null,"status":0,"reasons":"访问","unit":"公司名称","num":1,"type":0,"isprintvoucher":0,"ispullcard":1,"cardtype":0,"cardnum":"1234512345","sitephoto":null,"headphoto":null,"vCar":{"id":180,"cardnum":"京A99999","cardcolor":null,"num":null,"arid":85,"companyCode":null,"tabTime":null,"uploadTime":null},"drList":[],"trList":[],"isUpload":0,"pageNum":null,"yyID":null,"companyCode":"000000","terminalCode":"1000002","terminalManagerId":1038,"zhuxiaoManagerId":null,"tabTime":"2022-11-09 13:44:46","uploadTime":null,"syncId":null,"tiwen":35.0,"terminalManagerName":null,"zhuxiaoManagerName":null,"zhuxiaoTerminalCode":null,"channels":"","comment":"","xckStatus":0,"xckvisitedArea":null,"xckPhone":null,"xckUpdateTime":null,"xckPhoto":null,"jkbPhoto":null,"healthStatus":null,"lastRNATime":null,"lastRNAResult":null,"travelStatus":null,"tel":null,"vcar":{"id":180,"cardnum":"京A99999","cardcolor":null,"num":null,"arid":85,"companyCode":null,"tabTime":null,"uploadTime":null}}],"success":true} + */ + public static JSONObject fkterminalFindAccessRecord(JSONObject requestBody){ + String starttime = requestBody.getString("starttime");//开始时间* + String status = requestBody.getString("status");//状态:-1超时未注销、0登记中、1已注销3预约 + String pageNum = requestBody.getString("pageNum");//页数 + String num = requestBody.getString("num");//查询条数 + String endtime = requestBody.getString("endtime");//结束时间* + AssertUtils.notEmpty(starttime,"请输入开始时间-[starttime]"); + AssertUtils.notEmpty(endtime,"请输入结束时间-[endtime]"); + JSONObject responseBody = RestUtil.post(RmsApiEnum.getApiByText("访客查询"), requestBody, header); + AssertUtils.notNull(responseBody,"请求失败"); + Integer code = responseBody.getInteger("code"); + AssertUtils.isTrue(0==code,"请求异常:"+responseBody.getString("msg")); + return responseBody; + } + + /** + * 访客预约 + * @param requestBody {"reason":"拜访","synId":"abc10110","visitorBeginTime":"2022-11-08 10:00:00","visitorEndTime":"2022-11-08 18:00:00","visitorCmp":"访客部","visitorIdNum":"1234567890123","visitorName":"访客","visitorPhone":"1300000000"} + * @return {"code":0,"msg":"预约成功","pagecount":null,"pageNum":null,"content":null,"success":true} + */ + public static JSONObject syncOrderrecord(JSONObject requestBody){ + String reason = requestBody.getString("reason");//状态 + String synId = requestBody.getString("synId");//被访人ID* + String visitorBeginTime = requestBody.getString("visitorBeginTime");//来访时间 yyyy-MM-dd HH:mm:ss yyyy* + String visitorEndTime = requestBody.getString("visitorEndTime");//结束时间 yyyy-MM-dd HH:mm:ss* + String visitorCmp = requestBody.getString("visitorCmp");//访客单位 + String visitorIdNum = requestBody.getString("visitorIdNum");//访客证件号码* + String visitorName = requestBody.getString("visitorName");//访客姓名* + String visitorPhone = requestBody.getString("visitorPhone");//访客手机号 + AssertUtils.notEmpty(synId,"请输入被访客ID-[synId]"); + AssertUtils.notEmpty(visitorBeginTime,"请输入来访时间-[visitorBeginTime]"); + AssertUtils.notEmpty(visitorEndTime,"请输入结束时间-[visitorEndTime]"); + AssertUtils.notEmpty(visitorIdNum,"请输入访客证件号-[visitorIdNum]"); + AssertUtils.notEmpty(visitorName,"请输入访客姓名-[visitorName]"); + JSONObject responseBody = RestUtil.post(RmsApiEnum.getApiByText("访客预约"), requestBody, header); + AssertUtils.notNull(responseBody,"请求接口异常"); + Integer code = responseBody.getInteger("code"); + AssertUtils.isTrue(code==0,"请求访客预约接口异常:"+requestBody.getOrDefault("msg","")); + return responseBody; + } + + /** + * 访客注销 + * 本接口用于主动调用访客系统注销,针对于发卡用户使用,比如:访客登记发放门禁卡,出门注销时可调用此接口 + * @param requestBody {"cardNum":"1234567888"} + * @return {"code":0,"msg":"成功","pagecount":null,"pageNum":null,"content":null,"success":true} + */ + public static JSONObject fkterminalRecoverCard(JSONObject requestBody) { + String cardNum = requestBody.getString("cardNum"); + AssertUtils.notEmpty(cardNum,"清输入访客证件号-[cardNum]"); + JSONObject responseBody = RestUtil.post(RmsApiEnum.getApiByText("访客注销"), requestBody, header); + AssertUtils.notNull(responseBody,"请求失败"); + Integer code = responseBody.getInteger("code"); + AssertUtils.isTrue(0==code,"请求异常:"+responseBody.getString("msg")); + return responseBody; + } +} diff --git a/src/main/java/com/example/zxweb/vo/QueryDevicesVO.java b/src/main/java/com/example/zxweb/vo/QueryDevicesVO.java new file mode 100644 index 0000000..d26415a --- /dev/null +++ b/src/main/java/com/example/zxweb/vo/QueryDevicesVO.java @@ -0,0 +1,29 @@ +package com.example.zxweb.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @Description + * @Author ZhouWenTao + * @Date 2023/9/8 11:46 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@ApiModel(value="获取单个设备信息入参", description="获取单个设备信息入参") +public class QueryDevicesVO implements Serializable { + @ApiModelProperty(value = "设备序列号") + public String serial; + @ApiModelProperty(value = "产品序列号") + public String productId; +} diff --git a/word/swagger-inone-api.json b/word/swagger-inone-api.json new file mode 100644 index 0000000..4a90761 --- /dev/null +++ b/word/swagger-inone-api.json @@ -0,0 +1,510 @@ +{ + "swagger": "2.0", + "info": { + "version": "v1", + "title": "设备管理" + }, + "tags": [], + "basePath": "", + "paths": { + "/api/iot/v1/devices": { + "get": { + "summary": "获取单个设备信息", + "description": "", + "parameters": [{ + "name": "serial", + "in": "query", + "description": "设备序列号", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "productId", + "description": "产品序列号", + "required": false, + "type": "string" + }], + "responses": { + "200": { + "description": "成功" + }, + "400": { + "description": "失败,请求不合法" + }, + "422": { + "description": "失败,请求参数不合法" + }, + "444": { + "description": "失败,出现了业务错误" + } + } + } + }, + "/api/iot/v1/devices/list": { + "get": { + "summary": "获取设备列表", + "description": "", + "parameters": [{ + "name": "serial", + "in": "query", + "description": "产品序列号", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "modelCode", + "description": "设备类型", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "authority", + "description": "设备属性", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "pageSize", + "description": "分页大小", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "pageNo", + "description": "分页序号", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "startTime", + "description": "开始时间", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "endTime", + "description": "结束时间", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "sort", + "description": "排序", + "required": false, + "type": "string" + }], + "responses": { + "200": { + "description": "成功" + }, + "400": { + "description": "失败,请求不合法" + }, + "422": { + "description": "失败,请求参数不合法" + }, + "444": { + "description": "失败,出现了业务错误" + } + } + } + }, + "/api/iot/v1/devices/datastreams": { + "post": { + "summary": "向设备发送消息", + "description": "", + "parameters": [{ + "in": "body", + "name": "body", + "required": false, + "schema": { + "type": "object", + "required": ["dataStreamInfo"], + "properties": { + "dataStreamInfo": { + "type": "object", + "required": ["productId", + "serial", + "dataStreams"], + "properties": { + "productId": { + "type": "string", + "description": "产品序列号" + }, + "serial": { + "type": "string", + "description": "设备序列号" + }, + "dataStreams": { + "type": "array", + "items": { + "type": "object", + "required": ["streamName", + "streamValue"], + "properties": { + "streamName": { + "type": "string", + "description": "数据流名称" + }, + "streamValue": { + "type": "string", + "description": "数据流值" + } + } + } + } + } + } + } + } + }], + "responses": { + "201": { + "description": "成功" + }, + "400": { + "description": "失败,请求不合法" + }, + "422": { + "description": "失败,请求参数不合法" + }, + "444": { + "description": "失败,出现了业务错误" + } + } + }, + "get": { + "summary": "查询设备历史数据", + "description": "", + "parameters": [{ + "in": "query", + "name": "serial", + "description": "设备序列号", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "dataStreamName", + "description": "数据流能力名称", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "productId", + "description": "产品序列号", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "pageSize", + "description": "分页大小", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "pageNo", + "description": "分页序列号", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "startTime", + "description": "开始时间", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "endTime", + "description": "结束时间", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "sort", + "description": "排序", + "required": false, + "type": "string" + }], + "responses": { + "200": { + "description": "成功" + }, + "400": { + "description": "失败,请求不合法" + }, + "422": { + "description": "失败,请求参数不合法" + }, + "444": { + "description": "失败,出现了业务错误" + } + } + } + }, + "/api/iot/v1/devices/datastreams/state": { + "get": { + "summary": "查询消息是否下达到设备", + "description": "", + "parameters": [{ + "in": "query", + "name": "serial", + "description": "设备序列号", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "streamCinId", + "description": "能力实例序列号", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "productId", + "description": "产品序列号", + "required": false, + "type": "string" + }], + "responses": { + "200": { + "description": "成功" + }, + "400": { + "description": "失败,请求不合法" + }, + "422": { + "description": "失败,请求参数不合法" + }, + "444": { + "description": "失败,出现了业务错误" + } + } + } + }, + "/api/iot/v1/devices/events": { + "get": { + "summary": "查询事件历史数据", + "description": "", + "parameters": [{ + "in": "query", + "name": "serial", + "description": "设备序列号", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "dataStreamName", + "description": "数据流能力名称", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "productId", + "description": "产品序列号", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "pageSize", + "description": "分页大小", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "pageNo", + "description": "分页序列号", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "startTime", + "description": "开始时间", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "endTime", + "description": "结束时间", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "sort", + "description": "排序", + "required": false, + "type": "string" + }], + "responses": { + "200": { + "description": "成功" + }, + "400": { + "description": "失败,请求不合法" + }, + "422": { + "description": "失败,请求参数不合法" + }, + "444": { + "description": "失败,出现了业务错误" + } + } + } + }, + "/api/iot/v1/devices/methods": { + "post": { + "summary": "向设备发送方法", + "description": "", + "parameters": [{ + "in": "body", + "name": "body", + "required": false, + "schema": { + "type": "object", + "required": ["serial", + "methodName", + "inputData"], + "properties": { + "serial": { + "type": "string", + "description": "设备序列号" + }, + "productId": { + "type": "string", + "description": "产品序列号" + }, + "methodName": { + "type": "string", + "description": "方法名称" + }, + "inputData": { + "type": "object", + "description": "方法参数" + } + } + } + }], + "responses": { + "201": { + "description": "success" + }, + "400": { + "description": "error, request is invalid." + }, + "422": { + "description": "error, request parameter is invalid." + }, + "444": { + "description": "error, exception occurred." + } + } + }, + "get": { + "summary": "查询方法历史数据", + "description": "", + "parameters": [{ + "in": "query", + "name": "serial", + "description": "设备序列号", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "methodName", + "description": "方法名称", + "required": true, + "type": "string" + }, + { + "in": "query", + "name": "productId", + "description": "产品序列号", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "pageSize", + "description": "分页大小", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "pageNo", + "description": "分页序列号", + "required": false, + "type": "integer", + "format": "int32" + }, + { + "in": "query", + "name": "startTime", + "description": "开始时间", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "endTime", + "description": "结束时间", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "sort", + "description": "排序", + "required": false, + "type": "string" + }], + "responses": { + "200": { + "description": "成功" + }, + "400": { + "description": "失败,请求不合法" + }, + "422": { + "description": "失败,请求参数不合法" + }, + "444": { + "description": "失败,出现了业务错误" + } + } + } + } + + }, + "definitions": {} +} \ No newline at end of file