ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/MonitorController.java
New file @@ -0,0 +1,38 @@ package com.ruoyi.web.controller.api; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.core.domain.R; import com.ruoyi.system.query.DevicePageListQuery; import com.ruoyi.web.controller.tool.monitor.DeviceLiveQuery; import com.ruoyi.web.controller.tool.monitor.DeviceQuery; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @Api(tags = "监控对接") @RestController @RequestMapping("/monitor") public class MonitorController { @Autowired private DeviceQuery deviceQuery; @Autowired private DeviceLiveQuery deviceLiveQuery; @ApiOperation(value = "获取监控设备分页列表") @PostMapping("/devicePageList") public R<JSONObject> devicePageList(@RequestBody DevicePageListQuery query) { JSONObject deviceList = deviceQuery.getDeviceList(query.getPage(), query.getPageSize(), query.getOnlineStatus()); return R.ok(deviceList); } @ApiOperation(value = "获取监控直播链接") @GetMapping("/getLiveUrlByDeviceId") public R<JSONObject> getLiveUrlByDeviceId(@RequestParam String deviceId) { JSONObject deviceLiveUrl = deviceLiveQuery.getDeviceLiveList(deviceId); return R.ok(deviceLiveUrl); } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/monitor/DeviceLiveQuery.java
New file @@ -0,0 +1,107 @@ package com.ruoyi.web.controller.tool.monitor; import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.redis.service.RedisService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.LinkedHashMap; import java.util.Map; /** * 设备直播链接查询封装 */ @Slf4j @Component public class DeviceLiveQuery { @Value("${qianliyan.config.appId}") private String appId; @Value("${qianliyan.config.deviceLiveUrl}") private String deviceLiveUrl; @Value("${qianliyan.config.privateKey}") private String privateKey; private static final String TOKEN_KEY = "token_key:"; @Autowired private RedisService redisService; @Autowired private TokenFetcher tokenFetcher; public JSONObject getDeviceLiveList(String deviceId) { try { String token = redisService.getCacheObject(TOKEN_KEY); if(!org.springframework.util.StringUtils.hasLength(token)){ token = tokenFetcher.getToken(); } String timestamp = String.valueOf(System.currentTimeMillis()); JSONObject requestBody = new JSONObject(); requestBody.put("page", deviceId); String requestBodyStr = requestBody.toString(); // 2. 计算请求体MD5 String md5 = DigestUtils.md5Hex(String.valueOf(requestBody)); // 3. 构建签名字符串 Map signParams = new LinkedHashMap(); signParams.put("appid", appId); signParams.put("md5", md5); signParams.put("timestamp", timestamp); signParams.put("token", token); signParams.put("version", "1.0.0"); String jsonString = JSONUtil.toJsonStr(signParams); // 4. RSA签名 byte[] keyBytes = Base64.getDecoder().decode(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initSign(priKey); signature.update(jsonString.getBytes("UTF-8")); String signatureString = Base64.getEncoder().encodeToString(signature.sign()); // 5. 发送请求 String response = HttpRequest.post(deviceLiveUrl) .header("content-type", "application/json") .header("appid", appId) .header("md5", md5) .header("timestamp", timestamp) .header("version", "1.0.0") .header("signature", signatureString) .header("token", token) .body(requestBodyStr) .execute().body(); System.err.println("Response: " + response); JSONObject jsonObject = JSONObject.parseObject(response); if ("000000".equals(jsonObject.getString("resultCode"))) { log.info("获取直播链接成功"); JSONObject data = jsonObject.getJSONObject("data"); return data; } else { log.error("获取直播链接失败"); } } catch (Exception e) { e.printStackTrace(); } JSONObject jsonObject1 = new JSONObject(); jsonObject1.put("expiresIn", 0); jsonObject1.put("url", ""); return jsonObject1; } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/monitor/DeviceQuery.java
New file @@ -0,0 +1,128 @@ package com.ruoyi.web.controller.tool.monitor; import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.redis.service.RedisService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.StringUtils; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.security.KeyFactory; import java.security.MessageDigest; import java.security.PrivateKey; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.TimeUnit; /** * 设备查询封装 */ @Slf4j @Component public class DeviceQuery { @Value("${qianliyan.config.appId}") private String appId; @Value("${qianliyan.config.deviceUrl}") private String deviceUrl; @Value("${qianliyan.config.privateKey}") private String privateKey; private static final String TOKEN_KEY = "token_key:"; @Autowired private RedisService redisService; @Autowired private TokenFetcher tokenFetcher; @Autowired private DeviceThumbnailQuery deviceThumbnailQuery; public JSONObject getDeviceList(Integer page, Integer pageSize,Integer onlineStatus) { try { String token = redisService.getCacheObject(TOKEN_KEY); if(!org.springframework.util.StringUtils.hasLength(token)){ token = tokenFetcher.getToken(); } String timestamp = String.valueOf(System.currentTimeMillis()); JSONObject requestBody = new JSONObject(); requestBody.put("page", page); requestBody.put("pageSize", pageSize); requestBody.put("onlineStatus", onlineStatus); String requestBodyStr = requestBody.toString(); // 2. 计算请求体MD5 String md5 = DigestUtils.md5Hex(String.valueOf(requestBody)); // 3. 构建签名字符串 Map signParams = new LinkedHashMap(); signParams.put("appid", appId); signParams.put("md5", md5); signParams.put("timestamp", timestamp); signParams.put("token", token); signParams.put("version", "1.0.0"); String jsonString = JSONUtil.toJsonStr(signParams); // 4. RSA签名 byte[] keyBytes = Base64.getDecoder().decode(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initSign(priKey); signature.update(jsonString.getBytes("UTF-8")); String signatureString = Base64.getEncoder().encodeToString(signature.sign()); // 5. 发送请求 String response = HttpRequest.post(deviceUrl) .header("content-type", "application/json") .header("appid", appId) .header("md5", md5) .header("timestamp", timestamp) .header("version", "1.0.0") .header("signature", signatureString) .header("token", token) .body(requestBodyStr) .execute().body(); System.err.println("Response: " + response); JSONObject jsonObject = JSONObject.parseObject(response); if ("000000".equals(jsonObject.getString("resultCode"))) { log.info("获取列表成功"); JSONArray data = jsonObject.getJSONArray("data"); for (int i = 0; i < data.size(); i++) { JSONObject item = data.getJSONObject(i); String deviceId = item.getString("deviceId"); // 查询缩略图 String deviceThumbnailUrl = deviceThumbnailQuery.getDeviceThumbnailUrl(deviceId); item.put("deviceThumbnailUrl", deviceThumbnailUrl); } return jsonObject; } else { log.error("获取列表失败"); } } catch (Exception e) { e.printStackTrace(); } JSONObject jsonObject1 = new JSONObject(); jsonObject1.put("resultCode", "000000"); jsonObject1.put("resultMsg", "成功"); jsonObject1.put("data", new JSONArray()); jsonObject1.put("total", 0); jsonObject1.put("page", 1); jsonObject1.put("pageSize", 10); return jsonObject1; } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/monitor/DeviceThumbnailQuery.java
New file @@ -0,0 +1,105 @@ package com.ruoyi.web.controller.tool.monitor; import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.redis.service.RedisService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.LinkedHashMap; import java.util.Map; /** * 设备缩略图查询封装 */ @Slf4j @Component public class DeviceThumbnailQuery { @Value("${qianliyan.config.appId}") private String appId; @Value("${qianliyan.config.deviceThumbnailUrl}") private String deviceThumbnailUrl; @Value("${qianliyan.config.privateKey}") private String privateKey; private static final String TOKEN_KEY = "token_key:"; @Autowired private RedisService redisService; @Autowired private TokenFetcher tokenFetcher; public String getDeviceThumbnailUrl(String deviceId) { try { String token = redisService.getCacheObject(TOKEN_KEY); if(!org.springframework.util.StringUtils.hasLength(token)){ token = tokenFetcher.getToken(); } String timestamp = String.valueOf(System.currentTimeMillis()); JSONObject requestBody = new JSONObject(); requestBody.put("deviceId", deviceId); String requestBodyStr = requestBody.toString(); // 2. 计算请求体MD5 String md5 = DigestUtils.md5Hex(String.valueOf(requestBody)); // 3. 构建签名字符串 Map signParams = new LinkedHashMap(); signParams.put("appid", appId); signParams.put("md5", md5); signParams.put("timestamp", timestamp); signParams.put("token", token); signParams.put("version", "1.0.0"); String jsonString = JSONUtil.toJsonStr(signParams); // 4. RSA签名 byte[] keyBytes = Base64.getDecoder().decode(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initSign(priKey); signature.update(jsonString.getBytes("UTF-8")); String signatureString = Base64.getEncoder().encodeToString(signature.sign()); // 5. 发送请求 String response = HttpRequest.post(deviceThumbnailUrl) .header("content-type", "application/json") .header("appid", appId) .header("md5", md5) .header("timestamp", timestamp) .header("version", "1.0.0") .header("signature", signatureString) .header("token", token) .body(requestBodyStr) .execute().body(); System.err.println("Response: " + response); JSONObject jsonObject = JSONObject.parseObject(response); if ("000000".equals(jsonObject.getString("resultCode"))) { log.info("获取缩略图成功"); JSONObject data = jsonObject.getJSONObject("data"); String url = data.getString("url"); return url; } else { log.error("获取缩略图失败"); } } catch (Exception e) { e.printStackTrace(); } return null; } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/monitor/TokenFetcher.java
New file @@ -0,0 +1,112 @@ package com.ruoyi.web.controller.tool.monitor; import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.redis.service.RedisService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.StringUtils; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.TimeUnit; /** * 获取token */ @Slf4j @Component public class TokenFetcher { @Value("${qianliyan.config.appId}") private String appId; @Value("${qianliyan.config.secret}") private String secret; @Value("${qianliyan.config.tokenUrl}") private String tokenUrl; @Value("${qianliyan.config.privateKey}") private String privateKey; private static final String TOKEN_KEY = "token_key:"; @Autowired private RedisService redisService; /** * 获取token * @return token */ public String getToken() { try { String token = redisService.getCacheObject(TOKEN_KEY); if(org.springframework.util.StringUtils.hasLength(token)){ return token; } String timestamp = String.valueOf(System.currentTimeMillis()); String sig = Hex.encodeHexString(MessageDigest.getInstance("MD5").digest(StringUtils.getBytesUtf8(appId+secret))); JSONObject requestBody = new JSONObject(); requestBody.put("operatorType", 1); requestBody.put("sig", sig); String requestBodyStr = requestBody.toString(); // 2. 计算请求体MD5 String md5 = DigestUtils.md5Hex(String.valueOf(requestBody)); // 3. 构建签名字符串 Map signParams = new LinkedHashMap(); signParams.put("appid", appId); signParams.put("md5", md5); signParams.put("timestamp", timestamp); signParams.put("version", "1.0.0"); String jsonString = JSONUtil.toJsonStr(signParams); // 4. RSA签名 byte[] keyBytes = Base64.getDecoder().decode(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initSign(priKey); signature.update(jsonString.getBytes("UTF-8")); String signatureString = Base64.getEncoder().encodeToString(signature.sign()); // 5. 发送请求 String response = HttpRequest.post(tokenUrl) .header("content-type", "application/json") .header("appid", appId) .header("md5", md5) .header("timestamp", timestamp) .header("version", "1.0.0") .header("signature", signatureString) .body(requestBodyStr) .execute().body(); System.err.println("Response: " + response); JSONObject jsonObject = JSONObject.parseObject(response); if ("000000".equals(jsonObject.getString("resultCode"))) { log.info("获取token成功"); JSONObject data = jsonObject.getJSONObject("data"); Long expiresIn = data.getLong("expires_in"); token = data.getString("token"); redisService.setCacheObject(TOKEN_KEY, token, expiresIn, TimeUnit.SECONDS); return token; }else { log.error("获取token失败"); } } catch (Exception e) { e.printStackTrace(); } return null; } } ruoyi-admin/src/main/resources/application-prod.yml
@@ -225,3 +225,12 @@ notifyPayUrl: https://rhljsq.pzhsoar.com/applet/wx/pay/notify # 支付退款回调地址 notifyRefundUrl: https://rhljsq.pzhsoar.com/applet/wx/refund/notify qianliyan: config: appId: d0cccb14f4f74f46a8f6eb274008acc4 secret: oUdsm2tgyX0PpQ6Z privateKey: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKvXn8eu9MnvYBwDCKVfT+G5HssGBnC4q5SQ5nz3p1v24vY4JlFEXsQkPJkM7AU8O9JLYcnOX4SLLRSrv+hQDEvOV+lDxSgLw2mvg7yQplsb5WXj0MpJvOrmKVqSuTA79/SQ6NzJ+j+CsnAEzTzA1cTF7ld6mWJcQSwLin3kOGePAgMBAAECgYBdhW0kzJfWaptgw1nqPnQIAaq7jVzl7esbYLy/2DxR9YxRuf9IjTASCTKdjQXKV5yq93GR1enwBZqUPGCl+yKlGzcyneeQ6BqczsLtaKFJY6eUw/X/Xi0Rjtt8akHILfZoDHeXqbzaO5dCoCAF4lAVyqhoIrDVg71GgU7fHs7MwQJBAPmPGIVT3RHA2HDqKJqzV6obbV6FgDKOGQ4ITaIAReC7Q2Uox2ziHYhhqpzwmcVeiyxPAKShtvAICHX+e/A9HOECQQCwRwhyoehPUW80xMVd3gpoNuETN3D2cXNLqGqSnAexU7epB28fhZ5agxV3zj0PMJGkJKmth5WR//nBtRatQyJvAkEAxDHmgjM7UpC82JCOmYizO83SPwRPk+847VpDxj/Wr+YpBud3WTevJiA6ZKWXDp7UZWI6zDNCwhReqn0GbQluoQJAe8S0IsCZey+jVDqglUK0re1yZOq1buPDXyjWAzB4mkI8nvqwREKuJ8EIDsGIz6R7bfOsC0I6e3NuKlr6nBaaEwJAcXyxkmW5XXLMMn8jxQr0WUCMtKi3eWWD6M+WzTVcolkJjmewTQGSLDEyAm0AnTbdcJpoEGm9BtNXWaZEfkpbDQ== tokenUrl: https://open.qly.cmviot.cn/v3/open/api/token deviceUrl: https://open.qly.cmviot.cn/v3/open/api/device/list deviceThumbnailUrl: https://open.qly.cmviot.cn/v3/open/api/camera/thumbnail/realtime deviceLiveUrl: https://open.qly.cmviot.cn/v3/open/api/websdk/live ruoyi-admin/src/main/resources/application-test.yml
@@ -218,3 +218,12 @@ notifyPayUrl: http://221.182.45.100:9100/wx/pay/notify # 支付退款回调地址 notifyRefundUrl: http://221.182.45.100:9100/wx/refund/notify qianliyan: config: appId: d0cccb14f4f74f46a8f6eb274008acc4 secret: oUdsm2tgyX0PpQ6Z privateKey: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKvXn8eu9MnvYBwDCKVfT+G5HssGBnC4q5SQ5nz3p1v24vY4JlFEXsQkPJkM7AU8O9JLYcnOX4SLLRSrv+hQDEvOV+lDxSgLw2mvg7yQplsb5WXj0MpJvOrmKVqSuTA79/SQ6NzJ+j+CsnAEzTzA1cTF7ld6mWJcQSwLin3kOGePAgMBAAECgYBdhW0kzJfWaptgw1nqPnQIAaq7jVzl7esbYLy/2DxR9YxRuf9IjTASCTKdjQXKV5yq93GR1enwBZqUPGCl+yKlGzcyneeQ6BqczsLtaKFJY6eUw/X/Xi0Rjtt8akHILfZoDHeXqbzaO5dCoCAF4lAVyqhoIrDVg71GgU7fHs7MwQJBAPmPGIVT3RHA2HDqKJqzV6obbV6FgDKOGQ4ITaIAReC7Q2Uox2ziHYhhqpzwmcVeiyxPAKShtvAICHX+e/A9HOECQQCwRwhyoehPUW80xMVd3gpoNuETN3D2cXNLqGqSnAexU7epB28fhZ5agxV3zj0PMJGkJKmth5WR//nBtRatQyJvAkEAxDHmgjM7UpC82JCOmYizO83SPwRPk+847VpDxj/Wr+YpBud3WTevJiA6ZKWXDp7UZWI6zDNCwhReqn0GbQluoQJAe8S0IsCZey+jVDqglUK0re1yZOq1buPDXyjWAzB4mkI8nvqwREKuJ8EIDsGIz6R7bfOsC0I6e3NuKlr6nBaaEwJAcXyxkmW5XXLMMn8jxQr0WUCMtKi3eWWD6M+WzTVcolkJjmewTQGSLDEyAm0AnTbdcJpoEGm9BtNXWaZEfkpbDQ== tokenUrl: https://open.qly.cmviot.cn/v3/open/api/token deviceUrl: https://open.qly.cmviot.cn/v3/open/api/device/list deviceThumbnailUrl: https://open.qly.cmviot.cn/v3/open/api/camera/thumbnail/realtime deviceLiveUrl: https://open.qly.cmviot.cn/v3/open/api/websdk/live ruoyi-system/src/main/java/com/ruoyi/system/query/DevicePageListQuery.java
New file @@ -0,0 +1,20 @@ package com.ruoyi.system.query; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @Data @ApiModel(value = "设备列表查询参数DevicePageListQuery") public class DevicePageListQuery implements Serializable { @ApiModelProperty(value = "当前页") private Integer page; @ApiModelProperty(value = "页面数量") private Integer pageSize; @ApiModelProperty(value = "状态 1=在线 0=离线") private Integer onlineStatus=1; } ruoyi-system/src/main/java/com/ruoyi/system/query/TLargeKeyGridUserQuery.java
@@ -20,6 +20,9 @@ @ApiModelProperty(value = "类型名称") private String typeName; @ApiModelProperty(value = "小区名称") private String communityName; @ApiModelProperty(value = "类型id") private String typeId; ruoyi-system/src/main/resources/mapper/system/TLargeKeyGridUserMapper.xml
@@ -44,6 +44,9 @@ <if test="query.contactNumber != null and query.contactNumber != ''"> and tlkgu.contact_number like concat('%', #{query.contactNumber}, '%') </if> <if test="query.communityName != null and query.communityName != ''"> and tlkgu.community_name like concat('%', #{query.communityName}, '%') </if> <if test="query.typeName != null and query.typeName != ''"> and tlkpt.type_name like concat('%', #{query.typeName}, '%') </if>