diff --git a/pom.xml b/pom.xml index a5d18f9..0901ec0 100644 --- a/pom.xml +++ b/pom.xml @@ -213,6 +213,13 @@ ${ruoyi.version} + + + com.ruoyi + hw-api-tdengine + ${ruoyi.version} + + diff --git a/ruoyi-api/hw-api-tdengine/src/main/java/com/ruoyi/tdengine/api/domain/DeviceStatus.java b/ruoyi-api/hw-api-tdengine/src/main/java/com/ruoyi/tdengine/api/domain/DeviceStatus.java new file mode 100644 index 0000000..08f3edb --- /dev/null +++ b/ruoyi-api/hw-api-tdengine/src/main/java/com/ruoyi/tdengine/api/domain/DeviceStatus.java @@ -0,0 +1,63 @@ +package com.ruoyi.tdengine.api.domain; + +import com.ruoyi.common.core.web.domain.BaseEntity; + +/** + * @Description: 设备状态对象 + * @ClassName: DeviceStatus + * @Author : xins + * @Date :2023-09-05 11:35 + * @Version :1.0 + */ +public class DeviceStatus extends BaseEntity { + + private Long ts; + + private String deviceCode; + + private int deviceType; + + private int onlineStatus; + + private Long sceneId; + + public Long getTs() { + return ts; + } + + public void setTs(Long ts) { + this.ts = ts; + } + + public String getDeviceCode() { + return deviceCode; + } + + public void setDeviceCode(String deviceCode) { + this.deviceCode = deviceCode; + } + + public int getDeviceType() { + return deviceType; + } + + public void setDeviceType(int deviceType) { + this.deviceType = deviceType; + } + + public int getOnlineStatus() { + return onlineStatus; + } + + public void setOnlineStatus(int onlineStatus) { + this.onlineStatus = onlineStatus; + } + + public Long getSceneId() { + return sceneId; + } + + public void setSceneId(Long sceneId) { + this.sceneId = sceneId; + } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HwDictConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HwDictConstants.java index 00417ac..cc2f169 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HwDictConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HwDictConstants.java @@ -18,4 +18,12 @@ public class HwDictConstants { public static final String DEFAULT_FUNCTION_LONGITUDE_IDENTIFIER = "longitude";//经度标识符 public static final String DEFAULT_FUNCTION_LATITUDE_IDENTIFIER = "latitude";//纬度标识符 + public static final String ELECTRONIC_FENCE_TRIGGER_STATUS_EXIT = "1";//电子围栏触发状态:出界 + public static final String ELECTRONIC_FENCE_TRIGGER_STATUS_ENTRY = "2";//电子围栏触发状态:入界 + + public static final String ALARM_INFO_TYPE_DEVICE = "1";//设备报警 + public static final String ALARM_INFO_TYPE_MONITOR_UNIT = "2";//监控单元 + public static final String ALARM_INFO_TYPE_OFFLINE = "3";//离线报警 + public static final String ALARM_INFO_TYPE_ELECTRONIC_FENCE = "4";//电子围栏 + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TdEngineConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TdEngineConstants.java index e5c87b8..17e136d 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TdEngineConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/TdEngineConstants.java @@ -1,8 +1,76 @@ package com.ruoyi.common.core.constant; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description: TdEngine服务常量 + * @ClassName: TdEngineConstants + * @Author : xins + * @Date :2023-09-05 9:47 + * @Version :1.0 + */ public class TdEngineConstants { - public static final String DEFAULT_FIRST_FIELD_NAME = "ts"; + public static final String DEFAULT_FIRST_FIELD_NAME = "ts";//timestamp格式首字段,必须 + + public static final String DEFAULT_ORDER_BY_MODE = "desc";//默认排序方式,逆序 + + public static final String PAYLOAD_TS = "timestamp";//协议上传ts的key + + public static final String PAYLOAD_PARAM = "param";//协议上传的param key + + public static final String PAYLOAD_DATAVALUE = "datavalue";//协议上传数据的key + + public static final String PAYLOAD_DEVICE_CODE = "uid";//协议上传设备编号的key + + public static final String DEFAULT_DB_NAME_PREFIX = "db_scene_";//数据库名称前缀 + + public static final String DEFAULT_TABLE_NAME_PREFIX = "t_device_";//数据表名称前缀 + + public static final String DEFAULT_DEVICE_STATUS_SUPER_TABLE_NAME_PREFIX = "st_ds";//设备状态超级表名称 + public static final String DEFAULT_DEVICE_STATUS_TABLE_NAME_PREFIX = "t_ds_";//设备状态数据表名称前缀 + + /** + * 需要转换的key + */ + public static final Map TDENGINE_KEY_TRANSFER_MAP = new HashMap(); + + static { + TDENGINE_KEY_TRANSFER_MAP.put("value", "value1"); + } + + /** + * @return String + * @param: sceneId + * @description 获取数据库名称 + * @author xins + * @date 2023-09-05 9:42 + */ + public static String getDatabaseName(Long sceneId) { + return DEFAULT_DB_NAME_PREFIX + sceneId; + } + + /** + * @param: deviceId + * @return String + * @description 获取设备数据子表名称 + * @author xins + * @date 2023-09-05 9:42 + */ + public static String getDeviceDataTableName(Long deviceId) { + return DEFAULT_TABLE_NAME_PREFIX + deviceId; + } + + /** + * @param: sceneId + * @return String + * @description 获取设备状态超级表名称 + * @author xins + * @date 2023-09-05 9:42 + */ + public static String getDeviceStatusSuperTableName(Long sceneId) { + return DEFAULT_DEVICE_STATUS_SUPER_TABLE_NAME_PREFIX + sceneId; + } - public static final String DEFAULT_ORDER_BY_MODE = "desc"; } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/ResultEnums.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/ResultEnums.java new file mode 100644 index 0000000..2c0b4c1 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/ResultEnums.java @@ -0,0 +1,35 @@ +package com.ruoyi.common.core.enums; +/** + * @Description: 返回结果枚举 + * @ClassName: ResultEnums + * @Author : xins + * @Date :2023-09-01 13:40 + * @Version :1.0 + */ +public enum ResultEnums { + + SUCCESS(200,"成功"),FAIL(500,"失败"); + public Integer code; + public String message; + + ResultEnums(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/ruoyi-modules/hw-data-process/pom.xml b/ruoyi-modules/hw-data-process/pom.xml new file mode 100644 index 0000000..d2f099a --- /dev/null +++ b/ruoyi-modules/hw-data-process/pom.xml @@ -0,0 +1,120 @@ + + + + com.ruoyi + ruoyi-modules + 3.6.3 + + 4.0.0 + + ruoyi-modules-dataprocess + + + ruoyi-modules-dataprocess数据处理模块 + + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.springfox + springfox-swagger-ui + ${swagger.fox.version} + + + + + com.mysql + mysql-connector-j + + + + + com.ruoyi + ruoyi-common-datasource + + + + + com.ruoyi + ruoyi-common-datascope + + + + + com.ruoyi + ruoyi-common-log + + + + + com.ruoyi + ruoyi-common-swagger + + + + + net.dreamlu + mica-mqtt-client-spring-boot-starter + 2.1.0 + + + + + com.ruoyi + hw-api-tdengine + + + + org.locationtech.jts + jts-core + 1.19.0 + + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + + \ No newline at end of file diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/HwDataProcessApplication.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/HwDataProcessApplication.java new file mode 100644 index 0000000..3e10315 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/HwDataProcessApplication.java @@ -0,0 +1,34 @@ +package com.ruoyi.dataprocess; + +import com.ruoyi.common.security.annotation.EnableCustomConfig; +import com.ruoyi.common.security.annotation.EnableRyFeignClients; +import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * 系统模块 + * + * @author xins + */ +@EnableCustomConfig +@EnableCustomSwagger2 +@EnableRyFeignClients +@SpringBootApplication +public class HwDataProcessApplication +{ + public static void main(String[] args) + { + SpringApplication.run(HwDataProcessApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 数据处理模块启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/amap/LocationVo.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/amap/LocationVo.java new file mode 100644 index 0000000..728eb6d --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/amap/LocationVo.java @@ -0,0 +1,46 @@ +package com.ruoyi.dataprocess.amap; + +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +/** + * @Description: 区域实体类(多边形还是圆形)。多边形记录多个多边形的list,圆形记录中心点的经纬度和半径 + * @ClassName: LocationVo + * @Author : xins + * @Date :2023-09-02 11:22 + * @Version :1.0 + */ +@Data +public class LocationVo implements Serializable { + private static final long serialVersionUID = 1L; + public static final int MARKER_TYPE_POLYGON = 1;//多边形 + public static final int MARKER_TYPE_CIRCULAR = 2;//圆形 + + //经度 + private Double longitude; + + //纬度 + private Double latitude; + + /** + * 半径,单位米 + */ +// @ApiModelProperty(value = "半径") + private Double radius; + + /** + * 标记类型:1圆,2多边形 + */ +// @ApiModelProperty(value = "标记类型:1圆,2多边形") + private int markerType; + + /** + * 多边形区域 + */ + private List> polygonList; +} + + diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/amap/PositionUtils.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/amap/PositionUtils.java new file mode 100644 index 0000000..fa634c4 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/amap/PositionUtils.java @@ -0,0 +1,185 @@ +package com.ruoyi.dataprocess.amap; + +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.Polygon; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +public class PositionUtils { + + /** + * @return boolean + * @param: locationVo 区域 + * @param: lng 要判断的点的经度 + * @param: lat 要判断的点的纬度 + * @description 判断定位是否在区域LocationVo内 + * @author xins + * @date 2023-09-02 12:47 + */ + public static boolean checkAddressInLocation(LocationVo locationVo, Double lng, Double lat) { + if (locationVo == null) { + return false; + } + if (lng != null && lat != null && lng.compareTo(0.000000000000) > 0 && lat.compareTo(0.000000000000) > 0) { + if (locationVo.getMarkerType() == LocationVo.MARKER_TYPE_CIRCULAR) {//如果是圆 + double distance = calculateLineDistance(lng,lat,locationVo.getLongitude(), locationVo.getLatitude()); + System.out.println("dis:"+distance); + return (distance - locationVo.getRadius()) <=0; + } else if (locationVo.getMarkerType() == LocationVo.MARKER_TYPE_POLYGON) { + //多个多边形点集合字符串 + List> coordinates = locationVo.getPolygonList(); + if (coordinates == null || coordinates.isEmpty()) { + return false; + } + //可以传好几个多边形 + for (List positionVos : coordinates) { + Coordinate[] coordinates1 = new Coordinate[positionVos.size() + 1]; + for (int i = 0; i < positionVos.size(); i++) { + BigDecimal longitudeB = positionVos.get(i).getLongitude(); + BigDecimal latitudeB = positionVos.get(i).getLatitude(); + if (longitudeB == null || latitudeB == null) {//数据异常 + return false; + } + + Double longitude = longitudeB.doubleValue(); + Double latitude = latitudeB.doubleValue(); + + Coordinate coordinate = new Coordinate(longitude, latitude); + coordinates1[i] = coordinate; + } + //是起点也是终点 + coordinates1[positionVos.size()] = new Coordinate(positionVos.get(0).getLongitude().doubleValue(), + positionVos.get(0).getLatitude().doubleValue()); + if (isPointInPolygon(lat.doubleValue(), lng.doubleValue(), coordinates1)) { + return true;//只需要定位在其中一个的多边形范围内 + } + } + return false; + } + return false; + } else { + return false; + } + } + + +// public static boolean checkWithinTheCircula(LocationVo circulaVo, Double lng, Double lat) {//判断点与圆心之间的距离和圆半径的关系 +// +// System.out.println(lng.subtract(circulaVo.getLongitude()).doubleValue()); +// System.out.println(lat.subtract(circulaVo.getLatitude()).doubleValue()); +// double d2 = Math.hypot(lng.subtract(circulaVo.getLongitude()), lat.subtract(circulaVo.getLatitude()).doubleValue()); +// +// System.out.println("d2==" + d2); +// +// double r = circulaVo.getRadius(); +// //圆外 +// if (d2 > r) { +// return false; +// } else {//圆内或圆上 +// return true; +// } +// } + + /** + * 判断坐标之间的距离 + * (高德地图Android库的反编译源码) + * + * @param longitude 待判断经度 + * @param latitude 待判断纬度 + * @param centerLon 中心点经度 + * @param centerLat 中心点纬度 + * @return 返回的距离,单位米 + */ + public static Double calculateLineDistance(double longitude, double latitude, double centerLon, double centerLat) { + if (longitude == 0 || latitude == 0 || centerLat == 0 || centerLon == 0) { + return -1.0; + } + longitude *= 0.01745329251994329; + latitude *= 0.01745329251994329; + centerLon *= 0.01745329251994329; + centerLat *= 0.01745329251994329; + double var10 = Math.sin(longitude); + double var12 = Math.sin(latitude); + double var14 = Math.cos(longitude); + double var16 = Math.cos(latitude); + double var18 = Math.sin(centerLon); + double var20 = Math.sin(centerLat); + double var22 = Math.cos(centerLon); + double var24 = Math.cos(centerLat); + double[] var28 = new double[3]; + double[] var29 = new double[3]; + var28[0] = var16 * var14; + var28[1] = var16 * var10; + var28[2] = var12; + var29[0] = var24 * var22; + var29[1] = var24 * var18; + var29[2] = var20; + double distance = Math.asin(Math.sqrt((var28[0] - var29[0]) * (var28[0] - var29[0]) + (var28[1] - var29[1]) * (var28[1] - var29[1]) + (var28[2] - var29[2]) * (var28[2] - var29[2])) / 2.0) * 1.27420015798544E7; + return distance; + } + + + /** + * 判断是否在多边形区域内 + * + * @param latitude 经度 + * @param longitude 纬度 + * @param polygonCoordinates 多边形点集合 + * @return + */ + public static boolean isPointInPolygon(double latitude, double longitude, Coordinate[] polygonCoordinates) { + GeometryFactory geometryFactory = new GeometryFactory(); + Point point = geometryFactory.createPoint(new Coordinate(longitude, latitude)); + Polygon polygon = geometryFactory.createPolygon(polygonCoordinates); + + return polygon.touches(point) || polygon.contains(point); + } + + + public static void main(String[] args) { + LocationVo locationVo = new LocationVo(); + locationVo.setMarkerType(LocationVo.MARKER_TYPE_POLYGON); + + List> polygonList = new ArrayList<>(); + List postionList = new ArrayList<>(); + //林和西地铁站 + postionList.add(new PositionVo(new BigDecimal("113.323947"), new BigDecimal("23.141525"))); + //五羊邨地铁站 + postionList.add(new PositionVo(new BigDecimal(113.314119), new BigDecimal(23.119977))); + //体育中心南地铁站 + postionList.add(new PositionVo(new BigDecimal(113.324247), new BigDecimal(23.134501))); + //猎德地铁站 + postionList.add(new PositionVo(new BigDecimal(113.331972), new BigDecimal(23.118477))); + polygonList.add(postionList); + locationVo.setPolygonList(polygonList); + + +// boolean check1 = checkAddressInLocation(locationVo,new BigDecimal(113.323239),new BigDecimal(23.135428)); +// System.out.println(check1); +// check1 = checkAddressInLocation(locationVo,new BigDecimal(113.321522),new BigDecimal(23.13381)); +// System.out.println(check1); +// check1 = checkAddressInLocation(locationVo,new BigDecimal(113.324462),new BigDecimal(23.127002)); +// System.out.println(check1); +// check1 = checkAddressInLocation(locationVo,new BigDecimal(113.324247),new BigDecimal(23.116188)); +// System.out.println(check1); +// check1 = checkAddressInLocation(locationVo,new BigDecimal(113.319773),new BigDecimal(23.121664)); +// System.out.println(check1); +// check1 = checkAddressInLocation(locationVo,new BigDecimal(113.307757),new BigDecimal(23.127249)); +// System.out.println(check1); + + + LocationVo circulrVo = new LocationVo(); + circulrVo.setRadius(9.0056); + circulrVo.setLongitude(116.404172); + circulrVo.setLatitude(39.916605); + circulrVo.setMarkerType(LocationVo.MARKER_TYPE_CIRCULAR); + + boolean check2 = checkAddressInLocation(circulrVo, 116.404072, 39.916605); + System.out.println(check2); + + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/amap/PositionVo.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/amap/PositionVo.java new file mode 100644 index 0000000..1af05fb --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/amap/PositionVo.java @@ -0,0 +1,24 @@ +package com.ruoyi.dataprocess.amap; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @Description: 要判断的点的实体类 + * @ClassName: PositionUtils.Postion + * @Author : xins + * @Date :2023-09-02 12:11 + * @Version :1.0 + */ +@Data +public class PositionVo{ + private BigDecimal longitude; + + private BigDecimal latitude; + + public PositionVo(BigDecimal longitude, BigDecimal latitude) { + this.longitude = longitude; + this.latitude = latitude; + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/common/ImageUtils.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/common/ImageUtils.java new file mode 100644 index 0000000..457f2b7 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/common/ImageUtils.java @@ -0,0 +1,155 @@ +package com.ruoyi.dataprocess.common; + +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.core.utils.uuid.UUID; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Date; + +/** + * @Description: 图片工具类 + * @ClassName: ImageUtils + * @Author : xins + * @Date :2023-09-04 15:57 + * @Version :1.0 + */ +public class ImageUtils { + + public static final String BASE64_PREFIX = "data:image/";//base64图片前缀 + public static final String BASE64_SUFFIX = ";base64";//base64图片后缀 + + /** + * @param imagePatternArr + * @return String + * @param: base64Str + * @description 校验base64字符串是否是图片, 并且返回图片类型 + * @author xins + * @date 2023-09-04 16:05 + */ + public static String getImageType(String base64Str, String[] imagePatternArr) { + for (String imagePattern : imagePatternArr) { + String base64Pattern = BASE64_PREFIX + imagePattern + BASE64_SUFFIX; + if (base64Str.indexOf(base64Pattern) > -1) { + return imagePattern; + } + } + return ""; + } + + /** + * @return String + * @param: imageFileName + * @description 图片转base64 + * @author xins + * @date 2023-09-04 15:58 + */ + public static String convertImageToBase64(String imageFileName) { + ByteArrayOutputStream baos = null; + try { + //获取图片类型 + String suffix = imageFileName.substring(imageFileName.lastIndexOf(".") + 1); + //构建文件 + File imageFile = new File(imageFileName); + //通过ImageIO把文件读取成BufferedImage对象 + BufferedImage bufferedImage = ImageIO.read(imageFile); + //构建字节数组输出流 + baos = new ByteArrayOutputStream(); + //写入流 + ImageIO.write(bufferedImage, suffix, baos); + //通过字节数组流获取字节数组 + byte[] bytes = baos.toByteArray(); + //获取JDK8里的编码器Base64.Encoder转为base64字符 + return Base64.getEncoder().encodeToString(bytes); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (baos != null) { + baos.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } + + + /** + * @param: base64 + * @param: imageFileName + * @description base64字符串转图片 + * @author xins + * @date 2023-09-04 15:59 + */ + public static String convertBase64ToImage(String base64Str, String imagePath, String imageType, Long deviceId) { + // 解密 + try { + String fileName = UUID.randomUUID().toString().concat(".").concat(imageType); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd"); + Date date = new Date(); + String dateStr = format.format(date); + + String fullPath = imagePath + File.separator + deviceId + + File.separator + dateStr; + File file = new File(fullPath); + if (!file.exists()) { + file.mkdirs(); + } + + // 去掉base64前缀 data:image/jpeg;base64, + String imageFileName = fullPath + File.separator + fileName; + base64Str = base64Str.substring(base64Str.indexOf(",", 1) + 1); + // 解密,解密的结果是一个byte数组 + Base64.Decoder decoder = Base64.getDecoder(); + byte[] imgbytes = decoder.decode(base64Str); + for (int i = 0; i < imgbytes.length; ++i) { + if (imgbytes[i] < 0) { + imgbytes[i] += 256; + } + } + + // 保存图片 + OutputStream out = new FileOutputStream(imageFileName); + out.write(imgbytes); + out.flush(); + out.close(); + // 返回图片的相对路径 = 图片分类路径+图片名+图片后缀 + return imageFileName; + } catch (IOException e) { + return null; + } + + } + + + public static String getFileContent(FileInputStream fis, String encoding) throws IOException { + try (BufferedReader br = new BufferedReader(new InputStreamReader(fis, encoding))) { + StringBuilder sb = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + sb.append(line); + } + return sb.toString(); + } + } + + + public static void main(String[] args) throws IOException { + // 从txt文件中读取base64字符串 + FileInputStream fis = new FileInputStream("e://base64test/base64test5.txt"); + String base64Str = getFileContent(fis, "UTF-8"); + String[] imagePatternArr = {"png", "jpg", "jpeg"}; + String imageType = ImageUtils.getImageType(base64Str, imagePatternArr); + ImageUtils.convertBase64ToImage(base64Str,"images",imageType,2L); + + // 将base64字符串翻译成图片 + + + } + +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/common/SpringBeanUtils.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/common/SpringBeanUtils.java new file mode 100644 index 0000000..2893d94 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/common/SpringBeanUtils.java @@ -0,0 +1,77 @@ +package com.ruoyi.dataprocess.common; + +import org.springframework.beans.factory.DisposableBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Service; + +@Service +public class SpringBeanUtils implements ApplicationContextAware, DisposableBean { + private static ApplicationContext applicationContext = null; + + + /** + * 取得存储在静态变量中的ApplicationContext. + */ + public static ApplicationContext getApplicationContext() { + assertContextInjected(); + return applicationContext; + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) { +// log.debug("从SpringContextHolder中取出Bean:" + name); + assertContextInjected(); + return (T) applicationContext.getBean(name); + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + public static T getBean(Class requiredType) { + assertContextInjected(); + return applicationContext.getBean(requiredType); + } + + /** + * 清除SpringContextHolder中的ApplicationContext为Null. + */ + public static void clearHolder() { +// log.debug("清除SpringContextHolder中的ApplicationContext:" +// + applicationContext); + applicationContext = null; + } + + /** + * 实现ApplicationContextAware接口, 注入Context到静态变量中. + */ + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + + if (SpringBeanUtils.applicationContext != null) { +// log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); + } + + SpringBeanUtils.applicationContext = applicationContext; // NOSONAR + } + + /** + * 实现DisposableBean接口, 在Context关闭时清理静态变量. + */ + @Override + public void destroy() throws Exception { + SpringBeanUtils.clearHolder(); + } + + /** + * 检查ApplicationContext不为空. + */ + private static void assertContextInjected() { + if (applicationContext == null) { + throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringBeanUtils."); + } + } +} \ No newline at end of file diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/config/RedisMessageListenerConfig.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/config/RedisMessageListenerConfig.java new file mode 100644 index 0000000..067e31a --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/config/RedisMessageListenerConfig.java @@ -0,0 +1,38 @@ +package com.ruoyi.dataprocess.config; + +import com.ruoyi.dataprocess.listener.RedisMessageListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.listener.PatternTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; + +import java.util.Arrays; +import java.util.List; + +@Configuration +public class RedisMessageListenerConfig { + + @Autowired + private RedisMessageListener redisMessageListener; + @Autowired + private RedisConnectionFactory redisConnectionFactory; + + /** + * 配置订阅关系 + */ + @Bean + public RedisMessageListenerContainer container() { + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); + container.setConnectionFactory(redisConnectionFactory); + + //订阅频道 + List topicList = Arrays.asList(new PatternTopic("life.*"),new PatternTopic("*.life")); + container.addMessageListener(redisMessageListener, topicList); + + return container; + } + +} + diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/domain/HwAlarmInfo.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/domain/HwAlarmInfo.java new file mode 100644 index 0000000..b666f6e --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/domain/HwAlarmInfo.java @@ -0,0 +1,257 @@ +package com.ruoyi.dataprocess.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.core.annotation.Excel; +import com.ruoyi.common.core.web.domain.BaseEntity; + +/** + * 报警信息对象 hw_alarm_info + * + * @author xins + * @date 2023-09-04 + */ +public class HwAlarmInfo extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 报警信息ID */ + private Long alarmInfoId; + + /** 报警信息类型(1、设备报警,2、监控单元报警,3、离线报警,4、电子围栏) */ + @Excel(name = "报警信息类型", readConverterExp = "1=、设备报警,2、监控单元报警,3、离线报警,4、电子围栏") + private String alarmInfoType; + + /** 报警信息类型是1关联表alarm_rule的字段alarm_rule_id; + 报警信息类型是3关联表hw_offline_rule的字段offline_rule_id; + 报警信息类型是4关联表hw_electronic_fence的字段electronic_fence_id。 */ + @Excel(name = "报警信息类型是1关联表alarm_rule的字段alarm_rule_id;" + + "报警信息类型是3关联表hw_offline_rule的字段offline_rule_id; " + + "报警信息类型是4关联表hw_electronic_fence的字段electronic_fence_id。") + private Long alarmReleatedId; + + /** 报警设备ID,关联hw_device表的device_id字段 */ + @Excel(name = "报警设备ID,关联hw_device表的device_id字段") + private Long deviceId; + + /** 所属监控单元Id,关联表hw_monitor_unit字段monitor_unit_id */ + @Excel(name = "所属监控单元Id,关联表hw_monitor_unit字段monitor_unit_id") + private Long monitorUnitId; + + /** 所属场景ID,关联hw_scene的scene_id */ + @Excel(name = "所属场景ID,关联hw_scene的scene_id") + private Long sceneId; + + /** 报警级别,关联hw_alarm_level的字段alarm_level_id,报警信息类型为1、2和3时保存 */ + @Excel(name = "报警级别,关联hw_alarm_level的字段alarm_level_id,报警信息类型为1、2和3时保存") + private Long alarmLevelId; + + /** 报警类型,关联hw_alarm_type的字段alarm_type_id,报警信息类型为1和2时保存 */ + @Excel(name = "报警类型,关联hw_alarm_type的字段alarm_type_id,报警信息类型为1和2时保存") + private Long alarmTypeId; + + /** 设备模型功能ID */ + @Excel(name = "设备模型功能ID") + private Long modeFunctionId; + + /** 功能名称 */ + @Excel(name = "功能名称") + private String functionName; + + /** 标识符 */ + @Excel(name = "标识符") + private String functionIdentifier; + + /** 最新的值,如果是电子围栏则存经度_纬度 */ + @Excel(name = "最新的值,如果是电子围栏则存经度_纬度") + private String functionValue; + + /** 触发状态(1、出界,2、入界,3、双向),报警信息类型为4时保存 */ + @Excel(name = "触发状态", readConverterExp = "1=、出界,2、入界,3、双向") + private String triggerStatus; + + /** 处理状态(0、未处理 1、已处理) */ + @Excel(name = "处理状态", readConverterExp = "0=、未处理,1=、已处理") + private String handleStatus; + + /** 实际报警时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "实际报警时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date alarmTime; + + /** 预留字段 */ + @Excel(name = "预留字段") + private String alarmInfoField; + + public void setAlarmInfoId(Long alarmInfoId) + { + this.alarmInfoId = alarmInfoId; + } + + public Long getAlarmInfoId() + { + return alarmInfoId; + } + public void setAlarmInfoType(String alarmInfoType) + { + this.alarmInfoType = alarmInfoType; + } + + public String getAlarmInfoType() + { + return alarmInfoType; + } + public void setAlarmReleatedId(Long alarmReleatedId) + { + this.alarmReleatedId = alarmReleatedId; + } + + public Long getAlarmReleatedId() + { + return alarmReleatedId; + } + public void setDeviceId(Long deviceId) + { + this.deviceId = deviceId; + } + + public Long getDeviceId() + { + return deviceId; + } + public void setMonitorUnitId(Long monitorUnitId) + { + this.monitorUnitId = monitorUnitId; + } + + public Long getMonitorUnitId() + { + return monitorUnitId; + } + public void setSceneId(Long sceneId) + { + this.sceneId = sceneId; + } + + public Long getSceneId() + { + return sceneId; + } + public void setAlarmLevelId(Long alarmLevelId) + { + this.alarmLevelId = alarmLevelId; + } + + public Long getAlarmLevelId() + { + return alarmLevelId; + } + public void setAlarmTypeId(Long alarmTypeId) + { + this.alarmTypeId = alarmTypeId; + } + + public Long getAlarmTypeId() + { + return alarmTypeId; + } + public void setModeFunctionId(Long modeFunctionId) + { + this.modeFunctionId = modeFunctionId; + } + + public Long getModeFunctionId() + { + return modeFunctionId; + } + public void setFunctionName(String functionName) + { + this.functionName = functionName; + } + + public String getFunctionName() + { + return functionName; + } + public void setFunctionIdentifier(String functionIdentifier) + { + this.functionIdentifier = functionIdentifier; + } + + public String getFunctionIdentifier() + { + return functionIdentifier; + } + public void setFunctionValue(String functionValue) + { + this.functionValue = functionValue; + } + + public String getFunctionValue() + { + return functionValue; + } + public void setTriggerStatus(String triggerStatus) + { + this.triggerStatus = triggerStatus; + } + + public String getTriggerStatus() + { + return triggerStatus; + } + public void setHandleStatus(String handleStatus) + { + this.handleStatus = handleStatus; + } + + public String getHandleStatus() + { + return handleStatus; + } + public void setAlarmTime(Date alarmTime) + { + this.alarmTime = alarmTime; + } + + public Date getAlarmTime() + { + return alarmTime; + } + public void setAlarmInfoField(String alarmInfoField) + { + this.alarmInfoField = alarmInfoField; + } + + public String getAlarmInfoField() + { + return alarmInfoField; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("alarmInfoId", getAlarmInfoId()) + .append("alarmInfoType", getAlarmInfoType()) + .append("alarmReleatedId", getAlarmReleatedId()) + .append("deviceId", getDeviceId()) + .append("monitorUnitId", getMonitorUnitId()) + .append("sceneId", getSceneId()) + .append("alarmLevelId", getAlarmLevelId()) + .append("alarmTypeId", getAlarmTypeId()) + .append("modeFunctionId", getModeFunctionId()) + .append("functionName", getFunctionName()) + .append("functionIdentifier", getFunctionIdentifier()) + .append("functionValue", getFunctionValue()) + .append("triggerStatus", getTriggerStatus()) + .append("handleStatus", getHandleStatus()) + .append("alarmTime", getAlarmTime()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("alarmInfoField", getAlarmInfoField()) + .toString(); + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/domain/HwDevice.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/domain/HwDevice.java new file mode 100644 index 0000000..46d25c5 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/domain/HwDevice.java @@ -0,0 +1,341 @@ +package com.ruoyi.dataprocess.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.core.annotation.Excel; +import com.ruoyi.common.core.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.Date; + +/** + * 设备信息对象 hw_device + * + * @author xins + * @date 2023-08-24 + */ +public class HwDevice extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 设备ID */ + private Long deviceId; + + /** 设备编号 */ + @Excel(name = "设备编号") + private String deviceCode; + + /** 设备名称 */ + @Excel(name = "设备名称") + private String deviceName; + + /** 所属场景,关联hw_scene表的scene_id字段 */ + @Excel(name = "所属场景,关联hw_scene表的scene_id字段") + private Long sceneId; + + /** 所属监控单元,关联表hw_monitor_unit字段monitor_unit_id */ + @Excel(name = "所属监控单元,关联表hw_monitor_unit字段monitor_unit_id") + private Long monitorUnitId; + + /** 设备类型(1:网关设备,2:网关子设备,3:直连设备) */ + @Excel(name = "设备类型", readConverterExp = "1=:网关设备,2:网关子设备,3:直连设备") + private String deviceType; + + /** 联网方式(1:Wi-Fi,2、蜂窝(2G/3G/4G/5G),3、以太网,4、其他) */ + @Excel(name = "联网方式(1:Wi-Fi,2、蜂窝(2G/3G/4G/5G),3、以太网,4、其他)") + private String networkingMode; + + /** 接入协议(1、MQTT) */ + @Excel(name = "接入协议", readConverterExp = "1=、MQTT") + private Long accessProtocol; + + /** 数据格式(1、Json) */ + @Excel(name = "数据格式", readConverterExp = "1=、Json") + private Long dataFormat; + + /** 关联设备,hw_device表中国的device_id */ + @Excel(name = "关联设备,hw_device表中国的device_id") + private Long releatedDeviceId; + + /** 设备模型,关联表hw_device_mode的字段device_mode_id */ + @Excel(name = "设备模型,关联表hw_device_mode的字段device_mode_id") + private Long deviceModeId; + + /** 接入网关协议(1、Modbus) + OPC-UA,Modbus,北向接入(阿里云、小度接入),南向接入,视频类接入,通道类接入,自定义接入 */ + @Excel(name = "接入网关协议", readConverterExp = "1=、Modbus") + private Long accessGwProtocol; + + /** 激活状态(1、激活,0、未激活) */ + @Excel(name = "激活状态", readConverterExp = "1=、激活,0、未激活") + private String activeStatus; + + /** 设备状态(0、测试,1、发布,9、删除) */ + @Excel(name = "设备状态", readConverterExp = "0=、测试,1、发布,9、删除") + private String deviceStatus; + + /** 设备激活时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "设备激活时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date activeTime; + + /** 设备图片地址(如果为空则可以使用设备模型图片) */ + @Excel(name = "设备图片地址", readConverterExp = "如=果为空则可以使用设备模型图片") + private String devicePic; + + /** 网络地址 */ + @Excel(name = "网络地址") + private String ipAddress; + + /** 预留字段,设备所在区域ID,关联表hw_area字段area_id) */ + @Excel(name = "预留字段,设备所在区域ID,关联表hw_area字段area_id)") + private Long areaId; + + /** 预留字段,设备位置(手动定位(在地图上选择设备所在的固定位置),自动定位(设备自动定位位置,关联网关自动定位位置。目前仅G780V2(固件版本V2.2.0之后)、PLCNET510、G800 V2和ModbusRTU(云端轮询)定位型变量支持选择自动定位功能)) */ + @Excel(name = "预留字段,设备位置", readConverterExp = "手=动定位(在地图上选择设备所在的固定位置") + private String deviceLocation; + + /** 当前固件版本(Linux系统) */ + @Excel(name = "当前固件版本(Linux系统)") + private String currentModuleVersion; + + /** 当前单片机固件版本 */ + @Excel(name = "当前单片机固件版本") + private String currentSinglechipVersion; + + /** 预留字段 */ + @Excel(name = "预留字段") + private String deviceField; + + public void setDeviceId(Long deviceId) + { + this.deviceId = deviceId; + } + + public Long getDeviceId() + { + return deviceId; + } + public void setDeviceCode(String deviceCode) + { + this.deviceCode = deviceCode; + } + + public String getDeviceCode() + { + return deviceCode; + } + public void setDeviceName(String deviceName) + { + this.deviceName = deviceName; + } + + public String getDeviceName() + { + return deviceName; + } + public void setSceneId(Long sceneId) + { + this.sceneId = sceneId; + } + + public Long getSceneId() + { + return sceneId; + } + public void setMonitorUnitId(Long monitorUnitId) + { + this.monitorUnitId = monitorUnitId; + } + + public Long getMonitorUnitId() + { + return monitorUnitId; + } + public void setDeviceType(String deviceType) + { + this.deviceType = deviceType; + } + + public String getDeviceType() + { + return deviceType; + } + public void setNetworkingMode(String networkingMode) + { + this.networkingMode = networkingMode; + } + + public String getNetworkingMode() + { + return networkingMode; + } + public void setAccessProtocol(Long accessProtocol) + { + this.accessProtocol = accessProtocol; + } + + public Long getAccessProtocol() + { + return accessProtocol; + } + public void setDataFormat(Long dataFormat) + { + this.dataFormat = dataFormat; + } + + public Long getDataFormat() + { + return dataFormat; + } + public void setReleatedDeviceId(Long releatedDeviceId) + { + this.releatedDeviceId = releatedDeviceId; + } + + public Long getReleatedDeviceId() + { + return releatedDeviceId; + } + public void setDeviceModeId(Long deviceModeId) + { + this.deviceModeId = deviceModeId; + } + + public Long getDeviceModeId() + { + return deviceModeId; + } + public void setAccessGwProtocol(Long accessGwProtocol) + { + this.accessGwProtocol = accessGwProtocol; + } + + public Long getAccessGwProtocol() + { + return accessGwProtocol; + } + public void setActiveStatus(String activeStatus) + { + this.activeStatus = activeStatus; + } + + public String getActiveStatus() + { + return activeStatus; + } + public void setDeviceStatus(String deviceStatus) + { + this.deviceStatus = deviceStatus; + } + + public String getDeviceStatus() + { + return deviceStatus; + } + public void setActiveTime(Date activeTime) + { + this.activeTime = activeTime; + } + + public Date getActiveTime() + { + return activeTime; + } + public void setDevicePic(String devicePic) + { + this.devicePic = devicePic; + } + + public String getDevicePic() + { + return devicePic; + } + public void setIpAddress(String ipAddress) + { + this.ipAddress = ipAddress; + } + + public String getIpAddress() + { + return ipAddress; + } + public void setAreaId(Long areaId) + { + this.areaId = areaId; + } + + public Long getAreaId() + { + return areaId; + } + public void setDeviceLocation(String deviceLocation) + { + this.deviceLocation = deviceLocation; + } + + public String getDeviceLocation() + { + return deviceLocation; + } + public void setCurrentModuleVersion(String currentModuleVersion) + { + this.currentModuleVersion = currentModuleVersion; + } + + public String getCurrentModuleVersion() + { + return currentModuleVersion; + } + public void setCurrentSinglechipVersion(String currentSinglechipVersion) + { + this.currentSinglechipVersion = currentSinglechipVersion; + } + + public String getCurrentSinglechipVersion() + { + return currentSinglechipVersion; + } + public void setDeviceField(String deviceField) + { + this.deviceField = deviceField; + } + + public String getDeviceField() + { + return deviceField; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("deviceId", getDeviceId()) + .append("deviceCode", getDeviceCode()) + .append("deviceName", getDeviceName()) + .append("sceneId", getSceneId()) + .append("monitorUnitId", getMonitorUnitId()) + .append("deviceType", getDeviceType()) + .append("networkingMode", getNetworkingMode()) + .append("accessProtocol", getAccessProtocol()) + .append("dataFormat", getDataFormat()) + .append("releatedDeviceId", getReleatedDeviceId()) + .append("deviceModeId", getDeviceModeId()) + .append("accessGwProtocol", getAccessGwProtocol()) + .append("activeStatus", getActiveStatus()) + .append("deviceStatus", getDeviceStatus()) + .append("activeTime", getActiveTime()) + .append("devicePic", getDevicePic()) + .append("ipAddress", getIpAddress()) + .append("areaId", getAreaId()) + .append("deviceLocation", getDeviceLocation()) + .append("currentModuleVersion", getCurrentModuleVersion()) + .append("currentSinglechipVersion", getCurrentSinglechipVersion()) + .append("remark", getRemark()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("deviceField", getDeviceField()) + .toString(); + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/domain/HwElectronicFence.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/domain/HwElectronicFence.java new file mode 100644 index 0000000..13ead56 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/domain/HwElectronicFence.java @@ -0,0 +1,205 @@ +package com.ruoyi.dataprocess.domain; + +import com.ruoyi.common.core.annotation.Excel; +import com.ruoyi.common.core.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class HwElectronicFence extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 电子围栏ID */ + private Long electronicFenceId; + + /** 电子围栏名称 */ + @Excel(name = "电子围栏名称") + private String electronicFenceName; + + /** 所属场景 */ + @Excel(name = "所属场景") + private Long sceneId; + + /** 规则类型 */ + @Excel(name = "规则类型") + private Long fenceType; + + /** 生效时间标识 */ + @Excel(name = "生效时间标识") + private String effectiveTimeFlag; + + /** 生效时间:开始时间_结束时间_状态,多个用|隔开(例如00:00_05:00_1|06:00_08:00_0),状态:(1、开启、2、关闭) */ + @Excel(name = "生效时间:开始时间_结束时间_状态,多个用|隔开", readConverterExp = "例=如00:00_05:00_1|06:00_08:00_0") + private String effectiveTime; + + /** 触发状态(0、关闭,1、出界,2、入界,3、双向) */ + @Excel(name = "触发状态", readConverterExp = "0=、关闭,1、出界,2、入界,3、双向") + private String triggerStatus; + + /** 区域形状(1、多边形,2、圆形) */ + @Excel(name = "区域形状", readConverterExp = "1=、多边形,2、圆形") + private String areaShapeFlag; + + /** 区域范围:为多边形时保存格式,经度_纬度,多个以|隔开;为圆形时的中心点和半径,下划线隔开 */ + @Excel(name = "区域范围", readConverterExp = "为多边形时保存格式为经度_纬度,多个以|隔开;为圆形时的中心点和半径,下划线") + private String areaRange; + + /** 报警推送标识(1、是,0、否) */ + @Excel(name = "报警推送标识(1、是,0、否)") + private Long fencePushFlag; + + /** 报警推送内容 */ + @Excel(name = "报警推送内容") + private String fencePushContent; + + /** 恢复正常推送内容 */ + @Excel(name = "恢复正常推送内容") + private String fenceRecoverContent; + + /** 预留字段 */ + @Excel(name = "预留字段") + private String fenceField; + + public void setElectronicFenceId(Long electronicFenceId) + { + this.electronicFenceId = electronicFenceId; + } + + public Long getElectronicFenceId() + { + return electronicFenceId; + } + public void setElectronicFenceName(String electronicFenceName) + { + this.electronicFenceName = electronicFenceName; + } + + public String getElectronicFenceName() + { + return electronicFenceName; + } + public void setSceneId(Long sceneId) + { + this.sceneId = sceneId; + } + + public Long getSceneId() + { + return sceneId; + } + public void setFenceType(Long fenceType) + { + this.fenceType = fenceType; + } + + public Long getFenceType() + { + return fenceType; + } + public void setEffectiveTimeFlag(String effectiveTimeFlag) + { + this.effectiveTimeFlag = effectiveTimeFlag; + } + + public String getEffectiveTimeFlag() + { + return effectiveTimeFlag; + } + public void setEffectiveTime(String effectiveTime) + { + this.effectiveTime = effectiveTime; + } + + public String getEffectiveTime() + { + return effectiveTime; + } + public void setTriggerStatus(String triggerStatus) + { + this.triggerStatus = triggerStatus; + } + + public String getTriggerStatus() + { + return triggerStatus; + } + public void setAreaShapeFlag(String areaShapeFlag) + { + this.areaShapeFlag = areaShapeFlag; + } + + public String getAreaShapeFlag() + { + return areaShapeFlag; + } + public void setAreaRange(String areaRange) + { + this.areaRange = areaRange; + } + + public String getAreaRange() + { + return areaRange; + } + + public void setFencePushFlag(Long fencePushFlag) + { + this.fencePushFlag = fencePushFlag; + } + + public Long getFencePushFlag() + { + return fencePushFlag; + } + public void setFencePushContent(String fencePushContent) + { + this.fencePushContent = fencePushContent; + } + + public String getFencePushContent() + { + return fencePushContent; + } + public void setFenceRecoverContent(String fenceRecoverContent) + { + this.fenceRecoverContent = fenceRecoverContent; + } + + public String getFenceRecoverContent() + { + return fenceRecoverContent; + } + public void setFenceField(String fenceField) + { + this.fenceField = fenceField; + } + + public String getFenceField() + { + return fenceField; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("electronicFenceId", getElectronicFenceId()) + .append("electronicFenceName", getElectronicFenceName()) + .append("sceneId", getSceneId()) + .append("fenceType", getFenceType()) + .append("effectiveTimeFlag", getEffectiveTimeFlag()) + .append("effectiveTime", getEffectiveTime()) + .append("triggerStatus", getTriggerStatus()) + .append("areaShapeFlag", getAreaShapeFlag()) + .append("areaRange", getAreaRange()) + .append("fencePushFlag", getFencePushFlag()) + .append("fencePushContent", getFencePushContent()) + .append("fenceRecoverContent", getFenceRecoverContent()) + .append("remark", getRemark()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("fenceField", getFenceField()) + .toString(); + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/listener/RedisMessageListener.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/listener/RedisMessageListener.java new file mode 100644 index 0000000..d31516a --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/listener/RedisMessageListener.java @@ -0,0 +1,30 @@ +package com.ruoyi.dataprocess.listener; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +public class RedisMessageListener implements MessageListener { + + @Autowired + private RedisTemplate redisTemplate; + + @Override + public void onMessage(Message message, byte[] pattern) { + + RedisSerializer keySerializer = redisTemplate.getKeySerializer(); + RedisSerializer valueSerializer = redisTemplate.getValueSerializer(); + + log.info("----------Life接收到发布者消息----------"); + log.info("|频道:{}",keySerializer.deserialize(message.getChannel())); + log.info("|当前监听器绑定的pattern:{}",new String(pattern)); + log.info("|消息内容:{}",valueSerializer.deserialize(message.getBody())); + log.info("---------------------------------"); + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mapper/HwAlarmInfoMapper.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mapper/HwAlarmInfoMapper.java new file mode 100644 index 0000000..9c8c387 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mapper/HwAlarmInfoMapper.java @@ -0,0 +1,20 @@ +package com.ruoyi.dataprocess.mapper; + +import com.ruoyi.dataprocess.domain.HwAlarmInfo; + +/** + * 报警信息Mapper接口 + * + * @author xins + * @date 2023-09-04 + */ +public interface HwAlarmInfoMapper { + /** + * 新增报警信息 + * + * @param hwAlarmInfo 报警信息 + * @return 结果 + */ + public int insertHwAlarmInfo(HwAlarmInfo hwAlarmInfo); + +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mapper/HwDeviceMapper.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mapper/HwDeviceMapper.java new file mode 100644 index 0000000..6f60e55 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mapper/HwDeviceMapper.java @@ -0,0 +1,25 @@ +package com.ruoyi.dataprocess.mapper; + + +import com.ruoyi.dataprocess.domain.HwDevice; + +import java.util.List; + +/** + * 设备信息Mapper接口 + * + * @author xins + * @date 2023-08-24 + */ +public interface HwDeviceMapper +{ + /** + * 查询设备信息 + * + * @param deviceCode 设备编号,唯一 + * @return 设备信息 + */ + public HwDevice selectHwDeviceByDeviceCode(String deviceCode); + + +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mapper/HwElectronicFenceMapper.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mapper/HwElectronicFenceMapper.java new file mode 100644 index 0000000..0375416 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mapper/HwElectronicFenceMapper.java @@ -0,0 +1,50 @@ +package com.ruoyi.dataprocess.mapper; + + +import com.ruoyi.dataprocess.domain.HwElectronicFence; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: 电子围栏实体类 + * @ClassName: HwElectronicFenceMapper + * @Author : xins + * @Date :2023-09-03 11:48 + * @Version :1.0 + */ +public interface HwElectronicFenceMapper { + + public List selectSuitableElectronicFenceList(@Param("deviceId") Long deviceId, + @Param("monitorUnitId") Long monitorUnitId, + @Param("sceneId") Long sceneId); + + /** + * @param: deviceId + * @description 根据设备ID获取电子围栏配置 + * @author xins + * @date 2023-09-03 12:10 + * @return List + */ + public List selectElectronicFencesByDeviceId(Long deviceId); + + /** + * @param: monitorUnitId + * @description 根据监控单元ID获取电子围栏配置 + * @author xins + * @date 2023-09-03 12:11 + * @return List + */ + public List selectElectronicFencesByMonitorUnitId(Long monitorUnitId); + + /** + * @param: sceneId + * @description 根据场景Id获取电子围栏配置 + * @author xins + * @date 2023-09-03 12:11 + * @return List + */ + public List selectElectronicFencesBySceneId(Long sceneId); + + +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/config/MqttConfiguration.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/config/MqttConfiguration.java new file mode 100644 index 0000000..7f9b9ce --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/config/MqttConfiguration.java @@ -0,0 +1,239 @@ +package com.ruoyi.dataprocess.mqtt.client.config; + +import com.ruoyi.dataprocess.mqtt.client.listener.MqttClientConnectListener; +import com.ruoyi.dataprocess.service.IDataProcessService; +import com.ruoyi.dataprocess.service.IDeviceStatusService; +import net.dreamlu.iot.mqtt.codec.MqttPublishMessage; +import net.dreamlu.iot.mqtt.codec.MqttQoS; +import net.dreamlu.iot.mqtt.codec.MqttSubAckMessage; +import net.dreamlu.iot.mqtt.core.client.IMqttClientMessageListener; +import net.dreamlu.iot.mqtt.core.client.MqttClient; +import net.dreamlu.iot.mqtt.core.client.MqttClientCreator; +import net.dreamlu.iot.mqtt.spring.client.MqttClientCustomizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.tio.core.ChannelContext; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +//mqtt: +// client: +// enabled: true # 是否开启客户端,默认:false 使用到的场景有限,非必要请不要启用 +// ip: 127.0.0.1 # 连接的服务端 ip ,默认:127.0.0.1 +// port: 1883 # 端口:默认:1883 +// name: Mica-Mqtt-Client # 名称,默认:Mica-Mqtt-Client +// clientId: 000001 # 客户端Id(非常重要,一般为设备 sn,不可重复) +// user-name: mica # 认证的用户名 +// password: 123456 # 认证的密码 +// timeout: 5 # 超时时间,单位:秒,默认:5秒 +// reconnect: true # 是否重连,默认:true +// re-interval: 5000 # 重连时间,默认 5000 毫秒 +// version: MQTT_5 # mqtt 协议版本,默认:3.1.1 +// read-buffer-size: 8KB # 接收数据的 buffer size,默认:8k +// max-bytes-in-message: 10MB # 消息解析最大 bytes 长度,默认:10M +// buffer-allocator: heap # 堆内存和堆外内存,默认:堆内存 +// keep-alive-secs: 60 # keep-alive 时间,单位:秒 +// clean-session: true # mqtt clean session,默认:true +// use-ssl: false # 是否启用 ssl,默认:false + +//todo:read-buffer-size +@Configuration +public class MqttConfiguration { + private static final Logger logger = LoggerFactory.getLogger(MqttConfiguration.class); + + @Value("${mqtt.client.ip}") + String ip; + @Value("${mqtt.client.port}") + int port; + @Value("${mqtt.client.username}") + String username; + @Value("${mqtt.client.password}") + String password; + @Value("${mqtt.client.clientId}") + String clientId; + @Value("${mqtt.client.timeout}") + int timeOut; + @Value("${mqtt.client.keepalive}") + int keepAlive; + @Value("${mqtt.client.qos}") + int qos; + @Value("${mqtt.client.dataTopicFilter}") + String dataTopicFilter; + @Value("${mqtt.client.deviceStatusTopic}") + String deviceStatusTopic; + @Value("${mqtt.client.imagePath}") + String imagePath; + @Value("${mqtt.client.imagePatterns}") + String imagePatterns; + + @Autowired + private IDataProcessService dataProcessService; + + @Autowired + private IDeviceStatusService deviceStatusService; + + @Bean//注入spring + public MqttClientCustomizer mqttClientCustomizer() { + return new MqttClientCustomizer() { + @Override + public void customize(MqttClientCreator creator) { + // 此处可自定义配置 creator,会覆盖 yml 中的配置 + System.out.println("----------------MqttServerCustomizer-----------------"); + MqttClient client = creator.ip(ip) + .port(port) + .username(username) + .password(password) + .timeout(timeOut) + .keepAliveSecs(keepAlive) +// 如果包体过大,建议将此参数设置和 maxBytesInMessage 一样大 +// .readBufferSize(1024 * 10) +// 最大包体长度,如果包体过大需要设置此参数 +// .maxBytesInMessage(1024 * 10) +// .version(MqttVersion.MQTT_5) +// 连接监听 + .connectListener(new MqttClientConnectListener()) + .willMessage(builder -> { + builder.topic("/test/offline") + .messageText("down") + .retain(false) + .qos(MqttQoS.AT_MOST_ONCE); // 遗嘱消息 + }) + // 同步连接,也可以使用 connect() 异步(可以避免 broker 没启动照成启动卡住),但是下面的订阅和发布可能还没连接成功。 + .connectSync(); + String[] topicArr = {dataTopicFilter, deviceStatusTopic}; + + client.subscribe(topicArr, MqttQoS.valueOf(qos), new IMqttClientMessageListener() { + @Override + public void onSubscribed(ChannelContext context, String topicFilter, MqttQoS mqttQoS, MqttSubAckMessage message) { + IMqttClientMessageListener.super.onSubscribed(context, topicFilter, mqttQoS, message); + } + + @Override + public void onSubscribed(ChannelContext context, String topicFilter, MqttQoS mqttQoS) { + IMqttClientMessageListener.super.onSubscribed(context, topicFilter, mqttQoS); + } + + @Override + public void onMessage(ChannelContext channelContext, String topic, MqttPublishMessage mqttPublishMessage, ByteBuffer payload) { + System.out.println("dataprocessservice:" + dataProcessService); + String payloadString = new String(payload.array(), StandardCharsets.UTF_8); + System.out.println("paa:" + topic); + logger.info("topic:{} payload:{}", topic, payloadString); + System.out.println(topic+"----"+dataTopicFilter); + System.out.println(topic.startsWith(dataTopicFilter)); + if (topic.startsWith(dataTopicFilter.replace("#",""))) { + dataProcessService.processBusinessData(payloadString, imagePath, imagePatterns); + } else if (topic.equals(deviceStatusTopic)) { + deviceStatusService.handleDeviceStatus(); + } + } + }); + +// client.subscribe(topicArr,MqttQoS.valueOf(1),new MqttClientMessageListener()); +// client.subQos0(dataTopic,new MqttClientMessageListener()); + } + }; + } + + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public int getTimeOut() { + return timeOut; + } + + public void setTimeOut(int timeOut) { + this.timeOut = timeOut; + } + + public int getKeepAlive() { + return keepAlive; + } + + public void setKeepAlive(int keepAlive) { + this.keepAlive = keepAlive; + } + + public int getQos() { + return qos; + } + + public void setQos(int qos) { + this.qos = qos; + } + + public String getDataTopicFilter() { + return dataTopicFilter; + } + + public void setDataTopicFilter(String dataTopicFilter) { + this.dataTopicFilter = dataTopicFilter; + } + + public String getDeviceStatusTopic() { + return deviceStatusTopic; + } + + public void setDeviceStatusTopic(String deviceStatusTopic) { + this.deviceStatusTopic = deviceStatusTopic; + } + + public String getImagePath() { + return imagePath; + } + + public void setImagePath(String imagePath) { + this.imagePath = imagePath; + } + + public String getImagePatterns() { + return imagePatterns; + } + + public void setImagePatterns(String imagePatterns) { + this.imagePatterns = imagePatterns; + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/controller/ClientController.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/controller/ClientController.java new file mode 100644 index 0000000..bcc85f2 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/controller/ClientController.java @@ -0,0 +1,29 @@ +//package com.ruoyi.dataprocess.mqtt.client.controller; +// +//import com.ruoyi.dataprocess.mqtt.client.service.ClientService; +//import io.swagger.v3.oas.annotations.Operation; +//import io.swagger.v3.oas.annotations.tags.Tag; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.web.bind.annotation.*; +// +//@Tag(name = "Mqtt::客户端") +//@RequestMapping("/mqtt/client") +//@RestController +//public class ClientController { +// +// @Autowired +// private ClientService service; +// +// @Operation(summary = "publish") +// @PostMapping("/publish") +// public boolean publish(@RequestBody String body) { +// return service.publish(body); +// } +// +// @Operation(summary = "sub") +// @GetMapping("/sub") +// public boolean sub() { +// return service.sub(); +// } +// +//} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/listener/MqttClientConnectListener.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/listener/MqttClientConnectListener.java new file mode 100644 index 0000000..ba274d6 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/listener/MqttClientConnectListener.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & dreamlu.net). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ruoyi.dataprocess.mqtt.client.listener; + +import net.dreamlu.iot.mqtt.core.client.IMqttClientConnectListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.tio.core.ChannelContext; + +/** + * 客户端连接状态监听 + * + * @author L.cm + */ +@Service +public class MqttClientConnectListener implements IMqttClientConnectListener { + private static final Logger logger = LoggerFactory.getLogger(MqttClientConnectListener.class); + + @Override + public void onConnected(ChannelContext context, boolean isReconnect) { + if (isReconnect) { + logger.info("重连 mqtt 服务器重连成功..."); + } else { + logger.info("连接 mqtt 服务器成功..."); + } + } + + @Override + public void onDisconnect(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) { + logger.error("mqtt 链接断开 remark:{} isRemove:{}", remark, isRemove, throwable); + } + +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/listener/MqttClientMessageListener.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/listener/MqttClientMessageListener.java new file mode 100644 index 0000000..fd8f22c --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/listener/MqttClientMessageListener.java @@ -0,0 +1,67 @@ +//package com.ruoyi.dataprocess.mqtt.client.listener; +// +//import com.alibaba.fastjson.JSONArray; +//import com.alibaba.fastjson.JSONObject; +//import com.ruoyi.common.core.constant.TdEngineConstants; +//import com.ruoyi.common.core.domain.R; +//import com.ruoyi.common.core.enums.ResultEnums; +//import com.ruoyi.common.core.utils.SpringUtils; +//import com.ruoyi.common.core.utils.StringUtils; +//import com.ruoyi.dataprocess.common.SpringBeanUtils; +//import com.ruoyi.dataprocess.mapper.HwDeviceMapper; +//import com.ruoyi.dataprocess.mqtt.client.config.MqttConfiguration; +//import com.ruoyi.dataprocess.service.IDataProcessService; +//import com.ruoyi.system.api.RemoteFileService; +//import com.ruoyi.system.api.factory.RemoteFileFallbackFactory; +//import com.ruoyi.tdengine.api.RemoteTdEngineService; +//import com.ruoyi.tdengine.api.domain.TdField; +//import net.dreamlu.iot.mqtt.codec.MqttPublishMessage; +//import net.dreamlu.iot.mqtt.core.client.IMqttClientMessageListener; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Component; +//import org.springframework.stereotype.Controller; +//import org.springframework.stereotype.Service; +//import org.tio.core.ChannelContext; +// +//import javax.annotation.PostConstruct; +//import javax.annotation.Resource; +//import java.nio.ByteBuffer; +//import java.nio.charset.StandardCharsets; +//import java.util.List; +// +///** +// * 客户端消息监听的另一种方式 +// * +// * @author L.cm +// */ +//@Service +//public class MqttClientMessageListener implements IMqttClientMessageListener { +// private static final Logger logger = LoggerFactory.getLogger(MqttClientMessageListener.class); +// +// private IDataProcessService dataProcessService; +// +//// @PostConstruct +//// public void init() { +//// remoteTdEngineService = SpringBeanUtils.getBean(RemoteTdEngineService.class); +//// System.out.println("--***-"+remoteTdEngineService); +//// +//// } +// +// @Override +// public void onMessage(ChannelContext context, String topic, MqttPublishMessage message, ByteBuffer payload) { +// String payloadString = new String(payload.array(), StandardCharsets.UTF_8); +// System.out.println("paa:" + topic); +//// System.out.println("data"+dataProcessService); +// if(dataProcessService == null){ +// dataProcessService = SpringBeanUtils.getBean(IDataProcessService.class); +// } +//// if(topic.startsWith(MqttConfiguration)) +// dataProcessService.processBusinessData(payloadString); +// logger.info("topic:{} payload:{}", topic, payloadString); +// } +// +// +//} +// diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/service/ClientService.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/service/ClientService.java new file mode 100644 index 0000000..480a783 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/mqtt/client/service/ClientService.java @@ -0,0 +1,45 @@ +//package com.ruoyi.dataprocess.mqtt.client.service; +// +//import com.ruoyi.dataprocess.mqtt.client.config.MqttConfiguration; +//import com.ruoyi.dataprocess.mqtt.client.listener.MqttClientConnectListener; +//import com.ruoyi.dataprocess.mqtt.client.listener.MqttClientMessageListener; +//import net.dreamlu.iot.mqtt.codec.MqttQoS; +//import net.dreamlu.iot.mqtt.core.client.MqttClient; +//import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Component; +//import org.springframework.stereotype.Service; +// +//import javax.annotation.PostConstruct; +//import java.nio.charset.StandardCharsets; +//import java.util.Arrays; +// +///** +// * @Description: MQTT客户端服务 +// * @ClassName: ClientService +// * @Author : xins +// * @Date :2023-08-31 14:33 +// * @Version :1.0 +// */ +//public class ClientService { +// private static final Logger logger = LoggerFactory.getLogger(ClientService.class); +// +// private MqttClientTemplate client; +// +// public boolean publish(String body) { +// client.publish("/test/client", body.getBytes(StandardCharsets.UTF_8)); +// return true; +// } +// +// public boolean sub(String topic) { +// client.subQos0(topic, new MqttClientMessageListener()); +//// String[] topicsArr = topics.split(","); +//// Arrays.asList(topicsArr).forEach(topicFilter -> +//// client.subQos0(topicFilter, new MqttClientMessageListener()) +//// ); +// return true; +// } +// +//} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/IDataProcessService.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/IDataProcessService.java new file mode 100644 index 0000000..18fe45e --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/IDataProcessService.java @@ -0,0 +1,15 @@ +package com.ruoyi.dataprocess.service; + +public interface IDataProcessService { + + /** + * @param: jsonData + * @param imagePath + * @param imagePatterns + * @description 处理业务数据 + * @author xins + * @date 2023-08-31 16:16 + */ + public void processBusinessData(String jsonData,String imagePath,String imagePatterns); + +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/IDeviceStatusService.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/IDeviceStatusService.java new file mode 100644 index 0000000..99f5a34 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/IDeviceStatusService.java @@ -0,0 +1,13 @@ +package com.ruoyi.dataprocess.service; + +/** + * @Description: 设备状态处理接口 + * @ClassName: IDeviceStatusService + * @Author : xins + * @Date :2023-09-04 15:32 + * @Version :1.0 + */ +public interface IDeviceStatusService { + + public void handleDeviceStatus(); +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/impl/DataProcessServiceImpl.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/impl/DataProcessServiceImpl.java new file mode 100644 index 0000000..759ebec --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/impl/DataProcessServiceImpl.java @@ -0,0 +1,294 @@ +package com.ruoyi.dataprocess.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.core.constant.HwDictConstants; +import com.ruoyi.common.core.constant.TdEngineConstants; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.enums.ResultEnums; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.dataprocess.amap.LocationVo; +import com.ruoyi.dataprocess.amap.PositionUtils; +import com.ruoyi.dataprocess.amap.PositionVo; +import com.ruoyi.dataprocess.common.ImageUtils; +import com.ruoyi.dataprocess.domain.HwAlarmInfo; +import com.ruoyi.dataprocess.domain.HwDevice; +import com.ruoyi.dataprocess.domain.HwElectronicFence; +import com.ruoyi.dataprocess.mapper.HwAlarmInfoMapper; +import com.ruoyi.dataprocess.mapper.HwDeviceMapper; +import com.ruoyi.dataprocess.mapper.HwElectronicFenceMapper; +import com.ruoyi.dataprocess.service.IDataProcessService; +import com.ruoyi.tdengine.api.RemoteTdEngineService; +import com.ruoyi.tdengine.api.domain.TdField; +import com.ruoyi.tdengine.api.domain.TdTableVo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Description: 数据处理业务类 + * @ClassName: DataProcessServiceImpl + * @Author : xins + * @Date :2023-09-04 8:58 + * @Version :1.0 + */ +@Service +public class DataProcessServiceImpl implements IDataProcessService { + + private static final Logger logger = LoggerFactory.getLogger(DataProcessServiceImpl.class); + @Resource + private RemoteTdEngineService remoteTdEngineService; + + @Autowired + private HwDeviceMapper hwDeviceMapper; + + @Autowired + private HwElectronicFenceMapper hwElectronicFenceMapper; + + @Autowired + private HwAlarmInfoMapper hwAlarmInfoMapper; + + /** + * @param imagePath + * @param imagePatterns + * @param: jsonData + * @description 处理业务数据 + * @author xins + * @date 2023-08-31 16:16 + */ + @Override + public void processBusinessData(String jsonData, String imagePath, String imagePatterns) { + JSONObject json = JSON.parseObject(jsonData); + Long ts = json.getLong(TdEngineConstants.PAYLOAD_TS); + String tsStr = String.valueOf(ts); + if (tsStr.length() == 10) { + ts = ts * 1000; + } + JSONArray paramArr = json.getJSONArray(TdEngineConstants.PAYLOAD_PARAM); +// System.out.println(this.hwDeviceMapper); +// System.out.println(this.remoteTdEngineService); + for (int i = 0; i < paramArr.size(); i++) { + JSONObject paramJson = paramArr.getJSONObject(i); + JSONObject dataValueJson = paramJson.getJSONObject(TdEngineConstants.PAYLOAD_DATAVALUE); + String deviceCode = dataValueJson.getString(TdEngineConstants.PAYLOAD_DEVICE_CODE); + HwDevice hwDevice = hwDeviceMapper.selectHwDeviceByDeviceCode(deviceCode); + Long sceneId = hwDevice.getSceneId(); + Long deviceId = hwDevice.getDeviceId(); + Long monitorUnitId = hwDevice.getMonitorUnitId(); + String databaseName = TdEngineConstants.DEFAULT_DB_NAME_PREFIX + sceneId; + String tableName = TdEngineConstants.DEFAULT_TABLE_NAME_PREFIX + deviceId; + + dataValueJson.remove(TdEngineConstants.PAYLOAD_DEVICE_CODE); + TdTableVo tdTableVo = new TdTableVo(); + List schemaFields = new ArrayList<>(); + + //添加timestamp字段,默认字段名称是ts,协议上传的key是timestamp + TdField firstTdField = new TdField(); + firstTdField.setFieldName(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME); + firstTdField.setFieldValue(ts); + schemaFields.add(firstTdField); + + Object longitude = null; + Object latitude = null; + + for (Map.Entry entry : dataValueJson.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + /** + * 先对key进行转换,例如对于key是value的需要转换成value1; + */ + key = TdEngineConstants.TDENGINE_KEY_TRANSFER_MAP.get(key) == null ? key + : TdEngineConstants.TDENGINE_KEY_TRANSFER_MAP.get(key); + System.out.println(key + "---" + value); + + if (value instanceof String) { + String valueStr = (String) value; + if (StringUtils.isNotBlank(valueStr)) { + /** + * 先判读是否是图片,并获取图片名称, 获取到证明是图片 + */ + String[] imagePatternArr = imagePatterns.split(","); + String imageType = ImageUtils.getImageType(valueStr, imagePatternArr); + if (StringUtils.isNotBlank(imageType)) { + //保存图片,并返回图片详细地址进行赋值保存 + String imageFileName = ImageUtils.convertBase64ToImage(valueStr, imagePath, imageType, deviceId); + if (StringUtils.isNotBlank(imageFileName)) { + value = imageFileName; + } else { + continue; + } + } + + TdField tdField = new TdField(); + tdField.setFieldName(key); + tdField.setFieldValue(value); + schemaFields.add(tdField); + } + } else { + TdField tdField = new TdField(); + tdField.setFieldName(key); + tdField.setFieldValue(value); + schemaFields.add(tdField); + + //经纬度判断 + if (key.equalsIgnoreCase(HwDictConstants.DEFAULT_FUNCTION_LONGITUDE_IDENTIFIER)) { + longitude = value; + } else if (key.equalsIgnoreCase(HwDictConstants.DEFAULT_FUNCTION_LATITUDE_IDENTIFIER)) { + latitude = value; + } + } + } + + System.out.println(databaseName + "---" + tableName); + tdTableVo.setDatabaseName(databaseName); + tdTableVo.setTableName(tableName); + tdTableVo.setSchemaFields(schemaFields); + + System.out.println("longtitude:" + longitude + "latit:" + latitude); + + final R insertResult = this.remoteTdEngineService.insertTable(tdTableVo); + if (insertResult.getCode() == ResultEnums.SUCCESS.getCode()) { + logger.info("Insert data result: {}", insertResult.getMsg()); + } else { + logger.error("Insert data Exception: {},data:{}", insertResult.getMsg(), jsonData); + } + + if (longitude != null && latitude != null) { + checkElectronicFence(deviceId, monitorUnitId, sceneId, longitude, latitude, ts); + } + } + } + + /** + * @param: deviceId + * @param: monitorUnitId + * @param: sceneId + * @param: longitude + * @param: latitude + * @param: ts + * @description 校验此设备电子围栏 + * @author xins + * @date 2023-09-04 14:04 + */ + private void checkElectronicFence(Long deviceId, Long monitorUnitId, Long sceneId, Object longitude, Object latitude, Long ts) { + List hwElectronicFences = hwElectronicFenceMapper.selectElectronicFencesByDeviceId(deviceId); + if (StringUtils.isEmpty(hwElectronicFences)) { + System.out.println("---------"); + hwElectronicFences = hwElectronicFenceMapper.selectElectronicFencesByMonitorUnitId(monitorUnitId); + } + if (StringUtils.isEmpty(hwElectronicFences)) { + hwElectronicFences = hwElectronicFenceMapper.selectElectronicFencesBySceneId(sceneId); + System.out.println("---------33333"); + } + + if (StringUtils.isNotEmpty(hwElectronicFences)) { + hwElectronicFences.forEach(hwElectronicFence -> { + String effectiveTimeFlag = hwElectronicFence.getEffectiveTimeFlag(); + String triggerStatus = hwElectronicFence.getTriggerStatus(); + boolean isAlarmed = false;//是否报警 + if (effectiveTimeFlag.equals(HwDictConstants.EFFECTIVE_TIME_FLAG_LONG)) { + String areaShapeFlag = hwElectronicFence.getAreaShapeFlag(); + String areaRange = hwElectronicFence.getAreaRange(); + if (areaShapeFlag.equals(HwDictConstants.AREA_SHAPE_FLAG_POLYGN)) { + LocationVo polygonVo = new LocationVo(); + polygonVo.setMarkerType(LocationVo.MARKER_TYPE_POLYGON); + List> polygonList = new ArrayList<>(); + List postionList = new ArrayList<>(); + String[] areaRangeArr = areaRange.split("_");//多个点,每个点的经纬度信息(经度_纬度) + for (String areaRange1 : areaRangeArr) { + String[] areaRange1Arr = areaRange1.split(","); + String longitudeStr = areaRange1Arr[0]; + String latitudeStr = areaRange1Arr[1]; + postionList.add(new PositionVo(new BigDecimal(longitudeStr), new BigDecimal(latitudeStr))); + polygonList.add(postionList); + } + + polygonVo.setPolygonList(polygonList); + + /** + * 传入的longitude和latitude是object类型,本身有可能是BigDecimal,Double,Long和Integer,先转成String再转成Double + */ + boolean isWithin = PositionUtils.checkAddressInLocation(polygonVo, Double.valueOf(String.valueOf(longitude)), Double.valueOf(String.valueOf(latitude))); + if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_EXIT) && !isWithin) {//如果电子围栏配置是出界,而此设备出界则报警 + isAlarmed = true; + } else if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_ENTRY) && isWithin) {//如果电子围栏配置是入界,而此设备入界则报警 + isAlarmed = true; + } + System.out.println("iswithin" + isWithin); + + } else if (areaShapeFlag.equals(HwDictConstants.AREA_SHAPE_FLAG_CIRCULA)) { + String[] areaRangeArr = areaRange.split(","); + String longitudeStr = areaRangeArr[0]; + String latitudeStr = areaRangeArr[1]; + String radiusStr = areaRangeArr[2]; + LocationVo circulrVo = new LocationVo(); + circulrVo.setRadius(Double.valueOf(radiusStr)); + circulrVo.setLongitude(Double.valueOf(longitudeStr)); + circulrVo.setLatitude(Double.valueOf(latitudeStr)); + circulrVo.setMarkerType(LocationVo.MARKER_TYPE_CIRCULAR); + boolean isWithin = PositionUtils.checkAddressInLocation(circulrVo, Double.valueOf(String.valueOf(longitude)), Double.valueOf(String.valueOf(latitude))); + System.out.println("iswithin:" + isWithin); + if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_EXIT) && !isWithin) {//如果电子围栏配置是出界,而此设备出界则报警 + isAlarmed = true; + } else if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_ENTRY) && isWithin) {//如果电子围栏配置是入界,而此设备入界则报警 + isAlarmed = true; + } + } + } + + if (isAlarmed) { + HwAlarmInfo hwAralmInfo = new HwAlarmInfo(); + hwAralmInfo.setAlarmInfoType(HwDictConstants.ALARM_INFO_TYPE_ELECTRONIC_FENCE); + hwAralmInfo.setAlarmReleatedId(hwElectronicFence.getElectronicFenceId()); + hwAralmInfo.setDeviceId(deviceId); + hwAralmInfo.setMonitorUnitId(monitorUnitId); + hwAralmInfo.setSceneId(sceneId); + hwAralmInfo.setFunctionValue(longitude + "_" + latitude); + hwAralmInfo.setTriggerStatus(triggerStatus); + hwAralmInfo.setAlarmTime(new Date(ts)); + hwAralmInfo.setCreateTime(new Date()); + hwAlarmInfoMapper.insertHwAlarmInfo(hwAralmInfo); + } + }); + } + } + + public static void main(String[] args) { + System.out.println(System.currentTimeMillis()); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd"); + Date date = new Date(); + System.out.println(format.format(date)); + Object jsonData = "{\n" + + "\n" + + " \"timestamp\": 1689814424,\"type\": \"CMD_REPORTDATA\",\n" + + " \"param\": [\n{\n" + + " \"datatype\": \"cttemperature\",\n" + + "\"datavalue\": {\n" + + " \"uid\": \"0009340109040126\", \"alias\": \"\",\n" + + " \"value\": 25.6,\n" + + " \"voltage\": 3.76,\n" + + " \"rssi\": -80\n" + + " } },\n" + + " {\"datatype\": \"cttemperature\",\n" + + " \"datavalue\": {\n" + + " \"uid1\": \"00093440109040924\",\n" + + " \"alias\": \"\",\n" + + " \"value\": 25.6,\n" + + " \"voltage\": 3.64,\n" + + " \"rssi\": -87\n" + + " }\n" + + " }]}"; + + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/impl/DeviceStatusServiceImpl.java b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/impl/DeviceStatusServiceImpl.java new file mode 100644 index 0000000..c90474f --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/java/com/ruoyi/dataprocess/service/impl/DeviceStatusServiceImpl.java @@ -0,0 +1,27 @@ +package com.ruoyi.dataprocess.service.impl; + +import com.ruoyi.dataprocess.service.IDeviceStatusService; +import com.ruoyi.tdengine.api.RemoteTdEngineService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * @Description: 设备状态处理服务 + * @ClassName: DeviceStatusServiceImpl + * @Author : xins + * @Date :2023-09-04 15:31 + * @Version :1.0 + */ +@Service +public class DeviceStatusServiceImpl implements IDeviceStatusService { + + @Resource + private RemoteTdEngineService remoteTdEngineService; + + @Override + public void handleDeviceStatus(){ + + System.out.println("handleDeviceStatus"); + } +} diff --git a/ruoyi-modules/hw-data-process/src/main/resources/ClientService.java b/ruoyi-modules/hw-data-process/src/main/resources/ClientService.java new file mode 100644 index 0000000..ba43d31 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/resources/ClientService.java @@ -0,0 +1,32 @@ +package com.ruoyi.dataprocess.mqtt.client.service; + +import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.nio.charset.StandardCharsets; + +/** + * @author wsq + */ +@Service +public class ClientService { + private static final Logger logger = LoggerFactory.getLogger(ClientService.class); + @Autowired + private MqttClientTemplate client; + + public boolean publish(String body) { + client.publish("/test/client", body.getBytes(StandardCharsets.UTF_8)); + return true; + } + + public boolean sub() { + client.subQos0("/test/#", (context, topic, message, payload) -> { + logger.info(topic + '\t' + new String(payload, StandardCharsets.UTF_8)); + }); + return true; + } + +} diff --git a/ruoyi-modules/hw-data-process/src/main/resources/MqttClientConnectListener.java b/ruoyi-modules/hw-data-process/src/main/resources/MqttClientConnectListener.java new file mode 100644 index 0000000..e4f1ecc --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/resources/MqttClientConnectListener.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & dreamlu.net). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ruoyi.dataprocess.mqtt.client.listener; + +import net.dreamlu.iot.mqtt.core.client.MqttClientCreator; +import net.dreamlu.iot.mqtt.spring.client.event.MqttConnectedEvent; +import net.dreamlu.iot.mqtt.spring.client.event.MqttDisconnectEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +/** + * 客户端连接状态监听 + * + * @author L.cm + */ +@Service +public class MqttClientConnectListener { + private static final Logger logger = LoggerFactory.getLogger(MqttClientConnectListener.class); + + @Autowired + private MqttClientCreator mqttClientCreator; + + @EventListener + public void onConnected(MqttConnectedEvent event) { + logger.info("MqttConnectedEvent:{}", event); + } + + @EventListener + public void onDisconnect(MqttDisconnectEvent event) { + logger.info("MqttDisconnectEvent:{}", event); + // 在断线时更新 clientId、username、password + mqttClientCreator.clientId("newClient" + System.currentTimeMillis()) + .username("newUserName") + .password("newPassword"); + } + +} diff --git a/ruoyi-modules/hw-data-process/src/main/resources/banner.txt b/ruoyi-modules/hw-data-process/src/main/resources/banner.txt new file mode 100644 index 0000000..fbd45f5 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/resources/banner.txt @@ -0,0 +1,10 @@ +Spring Boot Version: ${spring-boot.version} +Spring Application Name: ${spring.application.name} + _ _ + (_) | | + _ __ _ _ ___ _ _ _ ______ ___ _ _ ___ | |_ ___ _ __ ___ +| '__|| | | | / _ \ | | | || ||______|/ __|| | | |/ __|| __| / _ \| '_ ` _ \ +| | | |_| || (_) || |_| || | \__ \| |_| |\__ \| |_ | __/| | | | | | +|_| \__,_| \___/ \__, ||_| |___/ \__, ||___/ \__| \___||_| |_| |_| + __/ | __/ | + |___/ |___/ \ No newline at end of file diff --git a/ruoyi-modules/hw-data-process/src/main/resources/bootstrap.yml b/ruoyi-modules/hw-data-process/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..856d7d0 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/resources/bootstrap.yml @@ -0,0 +1,25 @@ +# Tomcat +server: + port: 9603 + +# Spring +spring: + application: + # 应用名称 + name: hw-data-process + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 127.0.0.1:8848 + config: + # 配置中心地址 + server-addr: 127.0.0.1:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/ruoyi-modules/hw-data-process/src/main/resources/logback.xml b/ruoyi-modules/hw-data-process/src/main/resources/logback.xml new file mode 100644 index 0000000..4554898 --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/resources/logback.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-modules/hw-data-process/src/main/resources/mapper/dataprocess/HwAlarmInfoMapper.xml b/ruoyi-modules/hw-data-process/src/main/resources/mapper/dataprocess/HwAlarmInfoMapper.xml new file mode 100644 index 0000000..15aa31f --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/resources/mapper/dataprocess/HwAlarmInfoMapper.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into hw_alarm_info + + alarm_info_type, + alarm_releated_id, + device_id, + monitor_unit_id, + scene_id, + alarm_level_id, + alarm_type_id, + mode_function_id, + function_name, + function_identifier, + function_value, + trigger_status, + handle_status, + alarm_time, + create_time, + update_by, + update_time, + alarm_info_field, + + + #{alarmInfoType}, + #{alarmReleatedId}, + #{deviceId}, + #{monitorUnitId}, + #{sceneId}, + #{alarmLevelId}, + #{alarmTypeId}, + #{modeFunctionId}, + #{functionName}, + #{functionIdentifier}, + #{functionValue}, + #{triggerStatus}, + #{handleStatus}, + #{alarmTime}, + #{createTime}, + #{updateBy}, + #{updateTime}, + #{alarmInfoField}, + + + + + \ No newline at end of file diff --git a/ruoyi-modules/hw-data-process/src/main/resources/mapper/dataprocess/HwDeviceMapper.xml b/ruoyi-modules/hw-data-process/src/main/resources/mapper/dataprocess/HwDeviceMapper.xml new file mode 100644 index 0000000..d192fcf --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/resources/mapper/dataprocess/HwDeviceMapper.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select device_id, device_code, scene_id, monitor_unit_id, device_type, device_mode_id, device_status from hw_device + + + + + + \ No newline at end of file diff --git a/ruoyi-modules/hw-data-process/src/main/resources/mapper/dataprocess/HwElectronicFenceMapper.xml b/ruoyi-modules/hw-data-process/src/main/resources/mapper/dataprocess/HwElectronicFenceMapper.xml new file mode 100644 index 0000000..01f3d5a --- /dev/null +++ b/ruoyi-modules/hw-data-process/src/main/resources/mapper/dataprocess/HwElectronicFenceMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + select electronic_fence_id, electronic_fence_name, scene_id, fence_type, effective_time_flag, effective_time, trigger_status, area_shape_flag, + area_range, fence_push_flag, fence_push_content, fence_recover_content + from hw_electronic_fence hef + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/controller/TdEngineController.java b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/controller/TdEngineController.java index b16b57a..f6069c7 100644 --- a/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/controller/TdEngineController.java +++ b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/controller/TdEngineController.java @@ -4,6 +4,7 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.hw.validated.tdengine.AddTdSTableColumn; import com.ruoyi.common.core.hw.validated.tdengine.InsertTdTable; import com.ruoyi.tdengine.api.domain.*; +import com.ruoyi.tdengine.service.IDeviceStatusService; import com.ruoyi.tdengine.service.ITdEngineService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * @ClassDescription: TdEngine Controller @@ -32,6 +34,9 @@ public class TdEngineController { @Autowired private ITdEngineService tdEngineService; + @Autowired + private IDeviceStatusService deviceStatusService; + private static final Logger log = LoggerFactory.getLogger(TdEngineController.class); /* @description 创建数据库 @@ -257,7 +262,6 @@ public class TdEngineController { } } - /** * @return R * @param: tdSelectDto @@ -368,4 +372,37 @@ public class TdEngineController { } } + + /** + * @return R + * @param: tdSelectDto + * @description 获取每天在线设备信息 + * @author xins + * @date 2023-08-29 11:26 + */ + @PostMapping("/getOnlineDevicesGroupByDay") + public R getOnlineDevicesGroupByDay(@RequestBody DeviceStatus queryDeviceStatus) { + try { + List deviceStatuses = this.deviceStatusService.getOnlineDevicesGroupByDay(queryDeviceStatus); + Map> deviceStatusMap = deviceStatuses.stream() + .collect(Collectors.groupingBy(DeviceStatus::getTs)); + deviceStatusMap.forEach((k,v)->{ + System.out.println(k+"----"+v); + }); + + return R.ok(deviceStatusMap); + } catch (UncategorizedSQLException e) { + String message = e.getCause().getMessage(); + try { + message = message.substring(message.lastIndexOf("invalid operation")); + } catch (Exception ex) { + } + log.error(message); + return R.fail(message); + } catch (Exception e) { + log.error(e.getMessage()); + return R.fail(e.getMessage()); + } + } + } diff --git a/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/mapper/DeviceStatusMapper.java b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/mapper/DeviceStatusMapper.java new file mode 100644 index 0000000..c306225 --- /dev/null +++ b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/mapper/DeviceStatusMapper.java @@ -0,0 +1,24 @@ +package com.ruoyi.tdengine.mapper; + +import com.ruoyi.tdengine.api.domain.DeviceStatus; + +import java.util.List; + +/** + * @Description:TDengine设备状态信息交互接口 + * @ClassName: DeviceStatusMapper + * @Author : xins + * @Date :2023-09-05 13:20 + * @Version :1.0 + */ +public interface DeviceStatusMapper { + + /** + * @param: deviceStatus + * @description 获取每天在线设备列表 + * @author xins + * @date 2023-09-05 11:43 + * @return List + */ + List getOnlineDevicesGroupByDay(DeviceStatus deviceStatus); +} diff --git a/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/mapper/TdEngineMapper.java b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/mapper/TdEngineMapper.java index 05b0a11..98e0e4d 100644 --- a/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/mapper/TdEngineMapper.java +++ b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/mapper/TdEngineMapper.java @@ -7,7 +7,7 @@ import java.util.List; import java.util.Map; /** - * @ClassDescription: + * @ClassDescription:TDengine数据库交互接口 * @ClassName: TdEngineMapper * @Author: thinglinks * @Date: 2021-12-27 14:52:34 diff --git a/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/IDeviceStatusService.java b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/IDeviceStatusService.java new file mode 100644 index 0000000..b039129 --- /dev/null +++ b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/IDeviceStatusService.java @@ -0,0 +1,17 @@ +package com.ruoyi.tdengine.service; + +import com.ruoyi.tdengine.api.domain.DeviceStatus; + +import java.util.List; + +public interface IDeviceStatusService { + + /** + * @param: DeviceStatus + * @description 获取时间范围内每天的在线设备 + * @author xins + * @date 2023-09-05 13:23 + * @return List + */ + public List getOnlineDevicesGroupByDay(DeviceStatus queryDeviceStatus); +} diff --git a/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/impl/DeviceStatusServiceImpl.java b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/impl/DeviceStatusServiceImpl.java new file mode 100644 index 0000000..7538eaf --- /dev/null +++ b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/impl/DeviceStatusServiceImpl.java @@ -0,0 +1,52 @@ +package com.ruoyi.tdengine.service.impl; + +import com.ruoyi.common.core.constant.TdEngineConstants; +import com.ruoyi.tdengine.api.domain.DeviceStatus; +import com.ruoyi.tdengine.mapper.DeviceStatusMapper; +import com.ruoyi.tdengine.service.IDeviceStatusService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +/** + * @Description: 设备状态信息业务服务 + * @ClassName: DeviceStatusServiceImpl + * @Author : xins + * @Date :2023-09-05 13:27 + * @Version :1.0 + */ +@Service +public class DeviceStatusServiceImpl implements IDeviceStatusService { + + @Autowired + private DeviceStatusMapper deviceStatusMapper; + + /** + * @param: DeviceStatus + * @description 获取时间范围内每天的在线设备 + * @author xins + * @date 2023-09-05 13:23 + * @return List + */ + @Override + public List getOnlineDevicesGroupByDay(DeviceStatus queryDeviceStatus) { +// Map params = new HashMap<>(); +// DeviceStatus queryDeviceStatus = new DeviceStatus(); +// String databaseName = TdEngineConstants.getDatabaseName(sceneId); +// String superTableName = TdEngineConstants.getDeviceStatusSuperTableName(sceneId); +// params.put("databaseName", databaseName); +// params.put("superTableName", superTableName); +// params.put("beginTime", beginTime); +// params.put("endTime", endTime); +// queryDeviceStatus.setParams(params); +// if (sceneId != null) { +// queryDeviceStatus.setSceneId(sceneId); +// } + + List deviceStatuses = deviceStatusMapper.getOnlineDevicesGroupByDay(queryDeviceStatus); + + return deviceStatuses; + } +} diff --git a/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/impl/TdEngineServiceImpl.java b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/impl/TdEngineServiceImpl.java index 8f0875c..8571556 100644 --- a/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/impl/TdEngineServiceImpl.java +++ b/ruoyi-modules/hw-tdengine/src/main/java/com/ruoyi/tdengine/service/impl/TdEngineServiceImpl.java @@ -1,10 +1,8 @@ package com.ruoyi.tdengine.service.impl; import com.ruoyi.common.core.constant.TdEngineConstants; -import com.ruoyi.tdengine.api.domain.TdField; -import com.ruoyi.tdengine.api.domain.TdFieldVo; -import com.ruoyi.tdengine.api.domain.TdHistorySelectDto; -import com.ruoyi.tdengine.api.domain.TdSelectDto; +import com.ruoyi.tdengine.api.domain.*; +import com.ruoyi.tdengine.mapper.DeviceStatusMapper; import com.ruoyi.tdengine.mapper.TdEngineMapper; import com.ruoyi.tdengine.service.ITdEngineService; import org.apache.commons.lang3.StringUtils; @@ -32,6 +30,7 @@ public class TdEngineServiceImpl implements ITdEngineService { @Autowired private TdEngineMapper tdEngineMapper; + // @Autowired // private RedisService redisService; @@ -114,8 +113,8 @@ public class TdEngineServiceImpl implements ITdEngineService { * @date 2023-08-30 11:03 */ @Override - public void alterTableTag(String databaseName,String tableName,String tagName,Object tagValue){ - this.tdEngineMapper.alterTableTag(databaseName,tableName,tagName,tagValue); + public void alterTableTag(String databaseName, String tableName, String tagName, Object tagValue) { + this.tdEngineMapper.alterTableTag(databaseName, tableName, tagName, tagValue); } /** @@ -208,11 +207,11 @@ public class TdEngineServiceImpl implements ITdEngineService { /** + * @return Long * @param: tdHistorySelectDto * @description 获取历史记录的数量 * @author xins * @date 2023-08-29 16:54 - * @return Long */ @Override public Long getCountOfHistoryData(TdHistorySelectDto tdHistorySelectDto) throws Exception { @@ -223,9 +222,6 @@ public class TdEngineServiceImpl implements ITdEngineService { return countMap.get("dataCount"); } - - - // // /** // * 检查数据库表是否存在 diff --git a/ruoyi-modules/hw-tdengine/src/main/resources/mapper/tdengine/DeviceStatusMapper.xml b/ruoyi-modules/hw-tdengine/src/main/resources/mapper/tdengine/DeviceStatusMapper.xml new file mode 100644 index 0000000..6698952 --- /dev/null +++ b/ruoyi-modules/hw-tdengine/src/main/resources/mapper/tdengine/DeviceStatusMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/ruoyi-modules/hw-tdengine/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/ruoyi-modules/hw-tdengine/src/main/resources/mapper/tdengine/TdEngineMapper.xml index 7aedf0e..c4132ab 100644 --- a/ruoyi-modules/hw-tdengine/src/main/resources/mapper/tdengine/TdEngineMapper.xml +++ b/ruoyi-modules/hw-tdengine/src/main/resources/mapper/tdengine/TdEngineMapper.xml @@ -260,6 +260,17 @@ + + diff --git a/ruoyi-modules/pom.xml b/ruoyi-modules/pom.xml index b5a5a35..2207434 100644 --- a/ruoyi-modules/pom.xml +++ b/ruoyi-modules/pom.xml @@ -27,6 +27,7 @@ hw-business hw-basic hw-tdengine + hw-data-process ruoyi-modules