From 1a1dd17436547d46795e6d3fa5147a5a01b16f56 Mon Sep 17 00:00:00 2001 From: yj <913944315@qq.com> Date: Wed, 3 Jul 2024 15:30:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AD=E5=B1=B1=E7=AB=99=E5=B0=9D=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E7=A8=8B=E5=BA=8F=E9=87=87=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device_gather/pom.xml | 169 +++ .../xr/device/DeviceGatherApplication.java | 19 + .../common/configvalue/StaticPropProxy.java | 11 + .../common/configvalue/StaticProperties.java | 26 + .../xr/device/common/utils/CharsetKit.java | 85 ++ .../com/xr/device/common/utils/Convert.java | 1000 +++++++++++++++++ .../com/xr/device/common/utils/Files.java | 435 +++++++ .../xr/device/common/utils/ModbusUtils.java | 167 +++ .../device/common/utils/PythonExecutor.java | 205 ++++ .../xr/device/common/utils/SpringUtils.java | 151 +++ .../device/common/utils/StaticPropUtil.java | 26 + .../xr/device/common/utils/StrFormatter.java | 90 ++ .../xr/device/common/utils/StringUtils.java | 607 ++++++++++ .../xr/device/common/utils/UploadUtil.java | 187 +++ .../device/common/utils/ValueFormatUtil.java | 80 ++ .../xr/device/model/entity/DeviceCamera.java | 126 +++ .../model/entity/FocalLengthConfig.java | 141 +++ .../xr/device/model/entity/MeterConfig.java | 183 +++ .../model/entity/MeterInitialization.java | 50 + .../model/entity/MeterReadingRecord.java | 97 ++ .../com/xr/device/model/entity/MeterType.java | 86 ++ .../model/mapper/DeviceCameraMapper.java | 20 + .../model/mapper/FocalLengthConfigMapper.java | 20 + .../model/mapper/MeterConfigMapper.java | 24 + .../mapper/MeterInitializationMapper.java | 20 + .../mapper/MeterReadingRecordMapper.java | 20 + .../device/model/mapper/MeterTypeMapper.java | 20 + .../model/service/DeviceCameraService.java | 13 + .../service/FocalLengthConfigService.java | 13 + .../model/service/MeterConfigService.java | 17 + .../service/MeterInitializationService.java | 13 + .../service/MeterReadingRecordService.java | 13 + .../model/service/MeterTypeService.java | 13 + .../service/impl/DeviceCameraServiceImpl.java | 24 + .../impl/FocalLengthConfigServiceImpl.java | 24 + .../service/impl/MeterConfigServiceImpl.java | 30 + .../impl/MeterInitializationServiceImpl.java | 24 + .../impl/MeterReadingRecordServiceImpl.java | 24 + .../service/impl/MeterTypeServiceImpl.java | 24 + .../xr/device/schedule/GetMeterSchedule.java | 204 ++++ .../src/main/resources/application-dev.yml | 80 ++ .../src/main/resources/application-prod.yml | 80 ++ .../src/main/resources/application.yml | 82 ++ device_gather/src/main/resources/banner.txt | 23 + device_gather/src/main/resources/logback.xml | 51 + .../resources/mapper/DeviceCameraMapper.xml | 40 + .../mapper/FocalLengthConfigMapper.xml | 43 + .../resources/mapper/MeterConfigMapper.xml | 59 + .../mapper/MeterInitializationMapper.xml | 20 + .../mapper/MeterReadingRecordMapper.xml | 32 + .../main/resources/mapper/MeterTypeMapper.xml | 30 + 51 files changed, 5041 insertions(+) create mode 100644 device_gather/pom.xml create mode 100644 device_gather/src/main/java/com/xr/device/DeviceGatherApplication.java create mode 100644 device_gather/src/main/java/com/xr/device/common/configvalue/StaticPropProxy.java create mode 100644 device_gather/src/main/java/com/xr/device/common/configvalue/StaticProperties.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/CharsetKit.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/Convert.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/Files.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/ModbusUtils.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/PythonExecutor.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/SpringUtils.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/StaticPropUtil.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/StrFormatter.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/StringUtils.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/UploadUtil.java create mode 100644 device_gather/src/main/java/com/xr/device/common/utils/ValueFormatUtil.java create mode 100644 device_gather/src/main/java/com/xr/device/model/entity/DeviceCamera.java create mode 100644 device_gather/src/main/java/com/xr/device/model/entity/FocalLengthConfig.java create mode 100644 device_gather/src/main/java/com/xr/device/model/entity/MeterConfig.java create mode 100644 device_gather/src/main/java/com/xr/device/model/entity/MeterInitialization.java create mode 100644 device_gather/src/main/java/com/xr/device/model/entity/MeterReadingRecord.java create mode 100644 device_gather/src/main/java/com/xr/device/model/entity/MeterType.java create mode 100644 device_gather/src/main/java/com/xr/device/model/mapper/DeviceCameraMapper.java create mode 100644 device_gather/src/main/java/com/xr/device/model/mapper/FocalLengthConfigMapper.java create mode 100644 device_gather/src/main/java/com/xr/device/model/mapper/MeterConfigMapper.java create mode 100644 device_gather/src/main/java/com/xr/device/model/mapper/MeterInitializationMapper.java create mode 100644 device_gather/src/main/java/com/xr/device/model/mapper/MeterReadingRecordMapper.java create mode 100644 device_gather/src/main/java/com/xr/device/model/mapper/MeterTypeMapper.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/DeviceCameraService.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/FocalLengthConfigService.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/MeterConfigService.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/MeterInitializationService.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/MeterReadingRecordService.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/MeterTypeService.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/impl/DeviceCameraServiceImpl.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/impl/FocalLengthConfigServiceImpl.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/impl/MeterConfigServiceImpl.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/impl/MeterInitializationServiceImpl.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/impl/MeterReadingRecordServiceImpl.java create mode 100644 device_gather/src/main/java/com/xr/device/model/service/impl/MeterTypeServiceImpl.java create mode 100644 device_gather/src/main/java/com/xr/device/schedule/GetMeterSchedule.java create mode 100644 device_gather/src/main/resources/application-dev.yml create mode 100644 device_gather/src/main/resources/application-prod.yml create mode 100644 device_gather/src/main/resources/application.yml create mode 100644 device_gather/src/main/resources/banner.txt create mode 100644 device_gather/src/main/resources/logback.xml create mode 100644 device_gather/src/main/resources/mapper/DeviceCameraMapper.xml create mode 100644 device_gather/src/main/resources/mapper/FocalLengthConfigMapper.xml create mode 100644 device_gather/src/main/resources/mapper/MeterConfigMapper.xml create mode 100644 device_gather/src/main/resources/mapper/MeterInitializationMapper.xml create mode 100644 device_gather/src/main/resources/mapper/MeterReadingRecordMapper.xml create mode 100644 device_gather/src/main/resources/mapper/MeterTypeMapper.xml diff --git a/device_gather/pom.xml b/device_gather/pom.xml new file mode 100644 index 0000000..7388ac8 --- /dev/null +++ b/device_gather/pom.xml @@ -0,0 +1,169 @@ + + + 4.0.0 + + com.xr.device_net + device_car + 1.0.1 + + device_gather + ${project.artifactId} + + 1.8 + + + + + false + + + true + + ias-snapshots + Infinite Automation Snapshot Repository + https://maven.mangoautomation.net/repository/ias-snapshot/ + + + + true + + + false + + ias-releases + Infinite Automation Release Repository + https://maven.mangoautomation.net/repository/ias-release/ + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + + + org.freemarker + freemarker + 2.3.28 + + + mysql + mysql-connector-java + 8.0.27 + + + com.baomidou + mybatis-plus-boot-starter + 3.4.1 + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + org.springframework.boot + spring-boot-starter-websocket + + + com.alibaba + fastjson + 1.2.78 + compile + + + commons-discovery + commons-discovery + 0.2 + + + commons-io + commons-io + 2.6 + + + com.baomidou + mybatis-plus-generator + 3.4.1 + + + com.baomidou + dynamic-datasource-spring-boot-starter + 3.4.1 + + + io.github.java-native + jssc + 2.9.4 + + + com.infiniteautomation + modbus4j + 3.0.4 + + + org.rxtx + rxtx + 2.1.7 + + + org.scream3r + jssc + 2.8.0 + + + org.bouncycastle + bcprov-jdk15on + 1.59 + + + com.xr + onvif-hk + 3.1.0 + + + + + + + src/main/resources + false + + **/* + **/*.fxml + **/fxml/*.fxml + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.0.8.RELEASE + + + + repackage + + + + + + + + diff --git a/device_gather/src/main/java/com/xr/device/DeviceGatherApplication.java b/device_gather/src/main/java/com/xr/device/DeviceGatherApplication.java new file mode 100644 index 0000000..26f8c70 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/DeviceGatherApplication.java @@ -0,0 +1,19 @@ +package com.xr.device; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.scheduling.annotation.EnableScheduling; + +@EnableScheduling//开启定时任务 +@SpringBootApplication +@EnableDiscoveryClient +@EnableFeignClients +public class DeviceGatherApplication { + + public static void main(String[] args) { + SpringApplication.run(DeviceGatherApplication.class, args); + } + +} diff --git a/device_gather/src/main/java/com/xr/device/common/configvalue/StaticPropProxy.java b/device_gather/src/main/java/com/xr/device/common/configvalue/StaticPropProxy.java new file mode 100644 index 0000000..5285d81 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/configvalue/StaticPropProxy.java @@ -0,0 +1,11 @@ +package com.xr.device.common.configvalue; + +import com.xr.device.common.utils.StaticPropUtil; +import org.springframework.stereotype.Component; + +@Component +public class StaticPropProxy { + public StaticPropProxy(StaticProperties staticProperties){ + StaticPropUtil.initDingDingProp(staticProperties); + } +} diff --git a/device_gather/src/main/java/com/xr/device/common/configvalue/StaticProperties.java b/device_gather/src/main/java/com/xr/device/common/configvalue/StaticProperties.java new file mode 100644 index 0000000..d45a945 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/configvalue/StaticProperties.java @@ -0,0 +1,26 @@ +package com.xr.device.common.configvalue; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Data +public class StaticProperties { + + @Value("${upload.img.url}") + private String imgUrl; + + @Value("${upload.img.path}") + private String imgPath; + + @Value("${python.path}") + private String pythonPath; + + @Value("${python.modelPath}") + private String modelPath; + + @Value("${station.id}") + private Integer stationId; + +} diff --git a/device_gather/src/main/java/com/xr/device/common/utils/CharsetKit.java b/device_gather/src/main/java/com/xr/device/common/utils/CharsetKit.java new file mode 100644 index 0000000..f8fccbd --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/CharsetKit.java @@ -0,0 +1,85 @@ +package com.xr.device.common.utils; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * 字符集工具类 + * + * @author + */ +public class CharsetKit +{ + /** ISO-8859-1 */ + public static final String ISO_8859_1 = "ISO-8859-1"; + /** UTF-8 */ + public static final String UTF_8 = "UTF-8"; + /** GBK */ + public static final String GBK = "GBK"; + + /** ISO-8859-1 */ + public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); + /** UTF-8 */ + public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); + /** GBK */ + public static final Charset CHARSET_GBK = Charset.forName(GBK); + + /** + * 转换为Charset对象 + * + * @param charset 字符集,为空则返回默认字符集 + * @return Charset + */ + public static Charset charset(String charset) + { + return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, String srcCharset, String destCharset) + { + return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, Charset srcCharset, Charset destCharset) + { + if (null == srcCharset) + { + srcCharset = StandardCharsets.ISO_8859_1; + } + + if (null == destCharset) + { + destCharset = StandardCharsets.UTF_8; + } + + if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) + { + return source; + } + return new String(source.getBytes(srcCharset), destCharset); + } + + /** + * @return 系统字符集编码 + */ + public static String systemCharset() + { + return Charset.defaultCharset().name(); + } +} diff --git a/device_gather/src/main/java/com/xr/device/common/utils/Convert.java b/device_gather/src/main/java/com/xr/device/common/utils/Convert.java new file mode 100644 index 0000000..3853bda --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/Convert.java @@ -0,0 +1,1000 @@ +package com.xr.device.common.utils; + +import org.apache.commons.lang3.ArrayUtils; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.text.NumberFormat; +import java.util.Set; + +/** + * 类型转换器 + * + * @author ruoyi + */ +public class Convert +{ + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static String toStr(Object value, String defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof String) + { + return (String) value; + } + return value.toString(); + } + + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static String toStr(Object value) + { + return toStr(value, null); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Character toChar(Object value, Character defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof Character) + { + return (Character) value; + } + + final String valueStr = toStr(value, null); + return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Character toChar(Object value) + { + return toChar(value, null); + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Byte toByte(Object value, Byte defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Byte) + { + return (Byte) value; + } + if (value instanceof Number) + { + return ((Number) value).byteValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Byte.parseByte(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Byte toByte(Object value) + { + return toByte(value, null); + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Short toShort(Object value, Short defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Short) + { + return (Short) value; + } + if (value instanceof Number) + { + return ((Number) value).shortValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Short.parseShort(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Short toShort(Object value) + { + return toShort(value, null); + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Number toNumber(Object value, Number defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Number) + { + return (Number) value; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return NumberFormat.getInstance().parse(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Number toNumber(Object value) + { + return toNumber(value, null); + } + + /** + * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Integer toInt(Object value, Integer defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Integer) + { + return (Integer) value; + } + if (value instanceof Number) + { + return ((Number) value).intValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Integer.parseInt(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为int
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Integer toInt(Object value) + { + return toInt(value, null); + } + + /** + * 转换为Integer数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String str) + { + return toIntArray(",", str); + } + + /** + * 转换为Long数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String str) + { + return toLongArray(",", str); + } + + /** + * 转换为Integer数组
+ * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Integer[] {}; + } + String[] arr = str.split(split); + final Integer[] ints = new Integer[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Integer v = toInt(arr[i], 0); + ints[i] = v; + } + return ints; + } + + /** + * 转换为Long数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Long[] {}; + } + String[] arr = str.split(split); + final Long[] longs = new Long[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Long v = toLong(arr[i], null); + longs[i] = v; + } + return longs; + } + + /** + * 转换为String数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String str) + { + return toStrArray(",", str); + } + + /** + * 转换为String数组
+ * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) + { + return str.split(split); + } + + /** + * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Long toLong(Object value, Long defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Long) + { + return (Long) value; + } + if (value instanceof Number) + { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为long
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Long toLong(Object value) + { + return toLong(value, null); + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Double toDouble(Object value, Double defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Double) + { + return (Double) value; + } + if (value instanceof Number) + { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Double toDouble(Object value) + { + return toDouble(value, null); + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Float toFloat(Object value, Float defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Float) + { + return (Float) value; + } + if (value instanceof Number) + { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Float.parseFloat(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Float toFloat(Object value) + { + return toFloat(value, null); + } + + /** + * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Boolean toBool(Object value, Boolean defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Boolean) + { + return (Boolean) value; + } + String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + valueStr = valueStr.trim().toLowerCase(); + switch (valueStr) + { + case "true": + case "yes": + case "ok": + case "1": + return true; + case "false": + case "no": + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Boolean toBool(Object value) + { + return toBool(value, null); + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value, E defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) + { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Enum.valueOf(clazz, valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * + * @param clazz Enum的Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) + { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigInteger) + { + return (BigInteger) value; + } + if (value instanceof Long) + { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigInteger(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) + { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigDecimal) + { + return (BigDecimal) value; + } + if (value instanceof Long) + { + return new BigDecimal((Long) value); + } + if (value instanceof Double) + { + return BigDecimal.valueOf((Double) value); + } + if (value instanceof Integer) + { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigDecimal(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) + { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) + { + return str(obj, CharsetKit.CHARSET_UTF_8); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) + { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(Object obj, Charset charset) + { + if (null == obj) + { + return null; + } + + if (obj instanceof String) + { + return (String) obj; + } + else if (obj instanceof byte[]) + { + return str((byte[]) obj, charset); + } + else if (obj instanceof Byte[]) + { + byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj); + return str(bytes, charset); + } + else if (obj instanceof ByteBuffer) + { + return str((ByteBuffer) obj, charset); + } + return obj.toString(); + } + + /** + * 将byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(byte[] bytes, String charset) + { + return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 解码后的字符串 + */ + public static String str(byte[] data, Charset charset) + { + if (data == null) + { + return null; + } + + if (null == charset) + { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, String charset) + { + if (data == null) + { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, Charset charset) + { + if (null == charset) + { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + // ----------------------------------------------------------------------- 全角半角转换 + /** + * 半角转全角 + * + * @param input String. + * @return 全角字符串. + */ + public static String toSBC(String input) + { + return toSBC(input, null); + } + + /** + * 半角转全角 + * + * @param input String + * @param notConvertSet 不替换的字符集合 + * @return 全角字符串. + */ + public static String toSBC(String input, Set notConvertSet) + { + char[] c = input.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == ' ') + { + c[i] = '\u3000'; + } + else if (c[i] < '\177') + { + c[i] = (char) (c[i] + 65248); + + } + } + return new String(c); + } + + /** + * 全角转半角 + * + * @param input String. + * @return 半角字符串 + */ + public static String toDBC(String input) + { + return toDBC(input, null); + } + + /** + * 替换全角为半角 + * + * @param text 文本 + * @param notConvertSet 不替换的字符集合 + * @return 替换后的字符 + */ + public static String toDBC(String text, Set notConvertSet) + { + char[] c = text.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == '\u3000') + { + c[i] = ' '; + } + else if (c[i] > '\uFF00' && c[i] < '\uFF5F') + { + c[i] = (char) (c[i] - 65248); + } + } + String returnString = new String(c); + + return returnString; + } + + /** + * 数字金额大写转换 先写个完整的然后将如零拾替换成零 + * + * @param n 数字 + * @return 中文大写数字 + */ + public static String digitUppercase(double n) + { + String[] fraction = { "角", "分" }; + String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; + String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } }; + + String head = n < 0 ? "负" : ""; + n = Math.abs(n); + + String s = ""; + for (int i = 0; i < fraction.length; i++) + { + s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); + } + if (s.length() < 1) + { + s = "整"; + } + int integerPart = (int) Math.floor(n); + + for (int i = 0; i < unit[0].length && integerPart > 0; i++) + { + String p = ""; + for (int j = 0; j < unit[1].length && n > 0; j++) + { + p = digit[integerPart % 10] + unit[1][j] + p; + integerPart = integerPart / 10; + } + s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; + } + return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整"); + } +} diff --git a/device_gather/src/main/java/com/xr/device/common/utils/Files.java b/device_gather/src/main/java/com/xr/device/common/utils/Files.java new file mode 100644 index 0000000..8c1c161 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/Files.java @@ -0,0 +1,435 @@ +package com.xr.device.common.utils; + +import org.apache.commons.io.FileUtils; +import org.springframework.web.multipart.MultipartFile; +import sun.misc.BASE64Encoder; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.*; +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Date; + +public class Files { + + /** + * 根据文件路径获取文件字节流 + * @return + * filePath 文件路径 + * @throws IOException + */ + public static byte[] toByteArray(String filePath) throws IOException { + File f = new File(filePath); + if (!f.exists()) { + throw new FileNotFoundException("文件不存在"); + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length()); + BufferedInputStream in = null; + try { + in = new BufferedInputStream(new FileInputStream(f)); + int buf_size = 1024; + byte[] buffer = new byte[buf_size]; + int len = 0; + while (-1 != (len = in.read(buffer, 0, buf_size))) { + bos.write(buffer, 0, len); + } + return bos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + throw e; + } finally { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + bos.close(); + } + } + public static File multipartFileToFile(MultipartFile file) throws Exception { + File toFile = null; + if (file.equals("") || file.getSize() <= 0) { + file = null; + } else { + InputStream ins = null; + ins = file.getInputStream(); + toFile = new File(file.getOriginalFilename()); + inputStreamToFile(ins, toFile); + ins.close(); + } + return toFile; + + } + public static BufferedImage bytesTobufferedImage(byte[] bytes){ + BufferedImage image = null; + + try { + // 利用ByteArrayInputStream将字节数据转换成InputStream + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + + // 使用ImageIO读取InputStream中的数据转换为BufferedImage + image = ImageIO.read(bais); + + // 关闭ByteArrayInputStream + bais.close(); + // 此时,image就是转换后的BufferedImage对象,可以进行显示或其他处理 + // 例如显示图像: + // ImageIcon icon=new ImageIcon(image); + // JOptionPane.showMessageDialog(null, icon); + + } catch (IOException e) { + e.printStackTrace(); + } + return image; + } + + public static String uploadImage(BufferedImage bufferedImage, Integer configId) throws Exception { + // 构建完整的路径 + String fileName = configId+new Date().getTime()+".jpg"; + SimpleDateFormat sim=new SimpleDateFormat("yyyy-MM-dd"); + String date = sim.format(new Date()); + String dates[] = date.split("-"); + + String year = dates[0]; + String month = dates[1]; + String day = dates[2]; + //String fullPath = StaticPropUtil.imgPath + configId + File.separator + year + File.separator + month + File.separator + day + File.separator + fileName; + String fullPath = StaticPropUtil.imgPath + File.separator + fileName; + // 创建目录结构 + //Path directoryPath = Paths.get(StaticPropUtil.imgPath, configId.toString(), year, month, day); + Path directoryPath = Paths.get(StaticPropUtil.imgPath); + if (!java.nio.file.Files.exists(directoryPath)) { + java.nio.file.Files.createDirectories(directoryPath); + } + + // 创建文件并写入图像 + File file = new File(fullPath); + ImageIO.write(bufferedImage, "jpg", file); + + // 构建URL + String url = StaticPropUtil.imgUrl + configId + "/" + year + "/"+ month + "/" + day + "/" + fileName; + return url; + } + + + + private static void inputStreamToFile(InputStream ins, File file) { + try { + OutputStream os = new FileOutputStream(file); + int bytesRead = 0; + byte[] buffer = new byte[8192]; + while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { + os.write(buffer, 0, bytesRead); + } + os.close(); + ins.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static BufferedImage urlByImage(String url,String username,String password) throws IOException { + BufferedImage bimg=null; + try { + // 设置身份验证 + Authenticator.setDefault(new Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password.toCharArray()); + } + }); + + // 创建URL对象并打开连接 + URL uri = new URL(url); + URLConnection connection = uri.openConnection(); + + // 获取输入流 + InputStream inputStream = connection.getInputStream(); + bimg= ImageIO.read(inputStream); + // 关闭流 + inputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return bimg; + } + + public static BufferedImage urlByImage(String url) throws IOException { + URL urlfile = new URL(url); + InputStream is2 = urlfile.openStream(); + BufferedImage uImg= ImageIO.read(is2); + return uImg; + } + + public static String TransformPhotoToBase64Data(String path){ + Base64.Encoder encoder= Base64.getEncoder(); //获取Base64编码器 + byte [] ImgContainer = null ; //数据集缓存器 + FileInputStream fileInputStream = null; //文件输入流 + try { + System.out.println(path); + File file=new File(path); + fileInputStream = new FileInputStream(file); //到指定路径寻找文件 + ImgContainer = new byte[fileInputStream.available()]; //设置图片字节数据缓冲区大小 + fileInputStream.read(ImgContainer); //将数据流中的图片数据读进缓冲区 + String Base64ImgData =encoder.encodeToString(ImgContainer); //将图片编码转换成Base64格式的数据集 + fileInputStream.close(); //关闭数据流 + return Base64ImgData; //将缓冲区数据转换成字符数据返回 + } catch (FileNotFoundException e) { + return "找不到指定文件!"; + } catch (IOException e) { + e.printStackTrace(); + } + return "null"; + } + + public static String getBase64String(MultipartFile multiPartFile) throws IOException { + String baseStr = null; + + //把MultipartFile转化为File + File file = new File(multiPartFile.getOriginalFilename()); + FileUtils.copyInputStreamToFile(multiPartFile.getInputStream(), file); + + /* System.out.println("文件名:"+file.getOriginalFilename( )); + System.out.println("文件类型:"+file.getContentType()); + System.out.println("文件大小: "+file.getSize( )); + String dateDir = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + ClassPathResource PATHS = new ClassPathResource("static/files/"); + File paths=new File(PATHS.getPath()+file.getOriginalFilename()); + if (paths.getParentFile() != null && !paths.getParentFile().exists()) { + System.out.println("创建父路径"); + paths.getParentFile().mkdirs(); + } + com.xr.projsystem.common.utils.Base64Utils.decodeFile( + com.xr.projsystem.common.utils.Base64Utils.encode(file.getBytes()),paths); + mapData.put("url",serverConfig.getUrl()+paths.getPath().substring(paths.getPath().indexOf("files"))); + System.out.println(serverConfig.getUrl()+paths.getPath().substring(paths.getPath().indexOf("files")));*/ + try {//file转base64 + FileInputStream inputStream = new FileInputStream(file); + byte[] buffer = new byte[(int) file.length()]; + inputStream.read(buffer); + inputStream.close(); + baseStr = new BASE64Encoder().encode(buffer); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + //删除临时文件 + if (file.exists()) { + file.delete(); + } + baseStr = baseStr.replaceAll("\r\n", ""); + return baseStr; + } + + + public static String BufferedImageToBase64(BufferedImage bufferedImage) { + ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流 + try { + ImageIO.write(bufferedImage, "png", baos);//写入流中 + } catch (IOException e) { + e.printStackTrace(); + } + byte[] bytes = baos.toByteArray();//转换成字节 + BASE64Encoder encoder = new BASE64Encoder(); + String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串 + png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n + System.out.println("值为:" + "data:image/jpg;base64," + png_base64); + return "data:image/jpg;base64," + png_base64; + } + + public static String ImageToBase64(BufferedImage bufferedImage) { + ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流 + try { + ImageIO.write(bufferedImage, "png", baos);//写入流中 + } catch (IOException e) { + e.printStackTrace(); + } + byte[] bytes = baos.toByteArray();//转换成字节 + BASE64Encoder encoder = new BASE64Encoder(); + String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串 + png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n + return png_base64; + } + + /** *//** + * 旋转图片为指定角度 + * + * @param file + * 目标图像 + * @param degree + * 旋转角度 + * @return + */ + public static BufferedImage rotateImage(File file, + int degree) throws Exception{ +// if(degree<0){ +// degree=Math.abs(degree); +// }else{ +// degree=0-degree; +// } + BufferedImage bufferedimage = ImageIO.read(file); + int w= bufferedimage.getWidth();// 得到图片宽度。 + int h= bufferedimage.getHeight();// 得到图片高度。 + int type= bufferedimage.getColorModel().getTransparency();// 得到图片透明度。 + BufferedImage img;// 空的图片。 + Graphics2D graphics2d;// 空的画笔。 + (graphics2d= (img= new BufferedImage(w, h, type)) + .createGraphics()).setRenderingHint( + RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + graphics2d.rotate(Math.toRadians(degree),w/2,h/2);// 旋转,degree是整型,度数,比如垂直90度。 + graphics2d.drawImage(bufferedimage, 0, 0, null);// 从bufferedimagecopy图片至img,0,0是img的坐标。 + graphics2d.dispose(); + return img;// 返回复制好的图片,原图片依然没有变,没有旋转,下次还可以使用。 + } + + public static BufferedImage rotateImage(BufferedImage bufferedimage,int degree){ + int w= bufferedimage.getWidth();// 得到图片宽度。 + int h= bufferedimage.getHeight();// 得到图片高度。 + int type= bufferedimage.getColorModel().getTransparency();// 得到图片透明度。 + BufferedImage img;// 空的图片。 + Graphics2D graphics2d;// 空的画笔。 + (graphics2d= (img= new BufferedImage(w, h, type)) + .createGraphics()).setRenderingHint( + RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);// 旋转,degree是整型,度数,比如垂直90度。 + graphics2d.drawImage(bufferedimage, 0, 0, null);// 从bufferedimagecopy图片至img,0,0是img的坐标。 + graphics2d.dispose(); + return img;// 返回复制好的图片,原图片依然没有变,没有旋转,下次还可以使用。 + } + + public static BufferedImage scaledImage(BufferedImage bufferedimage,Double scaled){ + int width =bufferedimage.getWidth(); + int height = bufferedimage.getHeight(); + return new BufferedImage(Double.valueOf(scaled*width).intValue(),Double.valueOf(scaled*height).intValue(),BufferedImage.TYPE_INT_RGB); + } + + public static byte[] bufferedImageToByte(BufferedImage bufferedImage) throws IOException{ + ByteArrayOutputStream os =new ByteArrayOutputStream(); + ImageIO.write(bufferedImage,"jpg",os); + return os.toByteArray(); + } + + + public static void savePathForImage(BufferedImage bufferedImage,String path){ + + File file=new File(path); + // 创建文件输出流 + try { + ImageIO.write(bufferedImage, "png", file); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + public static String uploadImageForUrl(BufferedImage bufferedImage,String imgPath,String rqImg) throws IOException { + File file =new File(imgPath+rqImg); + if(!file.getParentFile().exists()){ + file.getParentFile().mkdirs(); + } + ImageIO.write(bufferedImage,"jpg",file); + rqImg=rqImg.replaceAll("\\\\","/"); + return StaticPropUtil.imgUrl+rqImg; + } + + public static String uploadImageForPath(BufferedImage bufferedImage,String imgPath,String rqImg) throws IOException { + File file =new File(imgPath+rqImg); + if(!file.getParentFile().exists()){ + file.getParentFile().mkdirs(); + } + ImageIO.write(bufferedImage,"jpg",file); + rqImg=(imgPath+rqImg).replace("\\","\\\\"); + return rqImg; + } + + public static BufferedImage drawRectangleAndText(BufferedImage image, double x1, double y1,double x2, double wid, double hei, String text1, String text2) { + // 创建一个Graphics2D对象 + Graphics2D g2d = image.createGraphics(); + + + // 设置抗锯齿 + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + + // 创建一个Rectangle2D.Double对象 + Rectangle2D.Double rect = new Rectangle2D.Double(x1, y1, wid, hei); + + // 绘制红色框 + g2d.setColor(Color.RED); + g2d.draw(rect); + // 设置粗线条 + g2d.setStroke(new BasicStroke(3.0f * 30)); // 设置线条宽度为3.0f + + // 设置字体和颜色 + g2d.setFont(new Font("微软雅黑", Font.BOLD, 38)); // 使用支持中文的字体,增加字体大小 + + // 获取当前时间 + String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); + // 获取文本的宽度和高度 + FontMetrics fm = g2d.getFontMetrics(); + + // 绘制当前时间的背景矩形 + int padding = 20; + int currentTimeWidth = fm.stringWidth(currentTime); + int currentTimeHeight = fm.getHeight(); + int rectPadding = 5; // 背景矩形内边距 + g2d.setColor(new Color(0, 0, 0, 50)); // 黑色半透明背景 + g2d.fillRect(padding, padding, currentTimeWidth + 2 * rectPadding, currentTimeHeight + 2 * rectPadding); + + // 绘制当前时间在左上角,内边距为20px + g2d.setColor(Color.WHITE); + int currentTimeX = padding + rectPadding + (currentTimeWidth + rectPadding - currentTimeWidth) / 2; + int currentTimeY = padding + rectPadding + fm.getAscent(); + g2d.drawString(currentTime, currentTimeX, currentTimeY); + + // 绘制文本2的背景矩形 + int text2Width = fm.stringWidth(text2); + int text2Height = fm.getHeight(); + g2d.setColor(new Color(0, 0, 0, 50)); // 黑色半透明背景 + g2d.fillRect(padding, padding + currentTimeHeight + rectPadding * 2, text2Width + 2 * rectPadding, text2Height + 2 * rectPadding); + + // 绘制文本2在时间的下面,内边距为20px + g2d.setColor(Color.WHITE); + int text2X = padding + rectPadding + (text2Width + rectPadding - text2Width) / 2; + int text2Y = padding + currentTimeHeight + rectPadding * 3 + fm.getAscent(); + g2d.drawString(text2, text2X, text2Y); + + // 计算文本1的右上角位置 + int text1Width = fm.stringWidth(text1); + int text1X = (int) (x1 + wid); // 框的右上角位置 + int text1Y = (int) (y1 + fm.getAscent()); // 框的右上角紧挨着框 + g2d.setColor(Color.RED); + + g2d.drawString(text1, text1X, text1Y); + + + // 释放资源 + g2d.dispose(); + + return image; + } + + public static void delFile(String url){ + String filePath = url.replace(StaticPropUtil.imgUrl,StaticPropUtil.imgPath).replace("/","\\"); + File file = new File(filePath); + if(file.exists()){ + file.delete(); + } + } + +} diff --git a/device_gather/src/main/java/com/xr/device/common/utils/ModbusUtils.java b/device_gather/src/main/java/com/xr/device/common/utils/ModbusUtils.java new file mode 100644 index 0000000..7bd0a16 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/ModbusUtils.java @@ -0,0 +1,167 @@ +package com.xr.device.common.utils; + +import com.serotonin.modbus4j.BatchRead; +import com.serotonin.modbus4j.BatchResults; +import com.serotonin.modbus4j.ModbusFactory; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import com.serotonin.modbus4j.ip.IpParameters; +import com.serotonin.modbus4j.locator.BaseLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +import static java.lang.Thread.sleep; + +public class ModbusUtils { + private static Logger log = LoggerFactory.getLogger(ModbusUtils.class); + private static Map map=new HashMap<>(); + /** + * 工厂。 + */ + static ModbusFactory modbusFactory; + + static { + if (modbusFactory == null) { + modbusFactory = new ModbusFactory(); + } + } + + /** + * 获取master + * + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getMaster(String host, int port) throws ModbusInitException { + IpParameters params = new IpParameters(); + params.setHost(host); + params.setPort(port); + // + // modbusFactory.createRtuMaster(wapper); //RTU 协议 + // modbusFactory.createUdpMaster(params);//UDP 协议 + // modbusFactory.createAsciiMaster(wrapper);//ASCII 协议 + ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 + master.init(); + + return master; + } + + public static ModbusMaster getRtuIpMaster(String host, int port) throws ModbusInitException { + IpParameters params = new IpParameters(); + params.setHost(host); + params.setPort(port); + params.setEncapsulated(true); + ModbusMaster master = modbusFactory.createTcpMaster(params, false); + try { + //设置超时时间 + master.setTimeout(2000); + //设置重连次数 + master.setRetries(2); + //初始化 + master.init(); + } catch (ModbusInitException e) { + e.printStackTrace(); + } + return master; + } + + /** + * 读取[01 Coil Status 0x]类型 开关数据 + * + * @param slaveId 主机地址 + * @param offset 寄存器地址 + * @return 读取值 + * @throws ModbusTransportException 异常 + * @throws ErrorResponseException 异常 + * @throws ModbusInitException 异常 + */ + public static Boolean readCoilStatus(ModbusMaster master, int slaveId, int offset) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 01 Coil Status + BaseLocator loc = BaseLocator.coilStatus(slaveId, offset); + Boolean value = master.getValue(loc); + return value; + } + /** + * 读取[03 Holding Register类型 2x]模拟量数据 + * + * @param slaveId 主机地址 + * @param offset 寄存器地址 + * @param dataType 数据类型,来自com.serotonin.modbus4j.code.DataType + * @return + * @throws ModbusTransportException 异常 + * @throws ErrorResponseException 异常 + * @throws ModbusInitException 异常 + */ + public static Number readHoldingRegister(ModbusMaster master, int slaveId, int offset, int dataType) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 03 Holding Register类型数据读取 + BaseLocator loc = BaseLocator.holdingRegister(slaveId, offset, dataType); + Number value = master.getValue(loc); + return value; + } + + /** + * 读取[04 Input Registers 3x]类型 模拟量数据 + * + * @param slaveId 主机地址 + * @param offset 寄存器地址 + * @param dataType 数据类型,来自com.serotonin.modbus4j.code.DataType + * @return 返回结果 + * @throws ModbusTransportException 异常 + * @throws ErrorResponseException 异常 + * @throws ModbusInitException 异常 + */ + public static Number readInputRegisters(ModbusMaster master, int slaveId, int offset, int dataType) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 04 Input Registers类型数据读取 + BaseLocator loc = BaseLocator.inputRegister(slaveId, offset, dataType); + Number value = master.getValue(loc); + return value; + } + + /** + * 批量读取使用寄存器数据 + * @param master ModbusMaster对象 + * @param batchRead 批量读取集合 + * @throws ModbusTransportException + * @throws ErrorResponseException + * @throws ModbusInitException + */ + public static BatchResults batchRead(ModbusMaster master, BatchRead batchRead)throws Exception { + try { + batchRead.setContiguousRequests(false); + BatchResults results = master.send(batchRead); + return results; + } catch (Exception e) { + log.error("批量读取使用寄存器数据出现异常"+e); + e.printStackTrace(); + } + return null; + } + + public static ModbusMaster getModbusMaster(String portName){ + return map.get(portName); + } + + + public static void main(String[] args) { + try{ + ModbusMaster modbusMaster= ModbusUtils.getMaster("192.168.1.105",1502); + while (true){ + Number n = ModbusUtils.readHoldingRegister(modbusMaster, 1, 0, 4); + System.out.println(n); + sleep(1000); + } + + }catch (Exception e){ + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/device_gather/src/main/java/com/xr/device/common/utils/PythonExecutor.java b/device_gather/src/main/java/com/xr/device/common/utils/PythonExecutor.java new file mode 100644 index 0000000..e43330c --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/PythonExecutor.java @@ -0,0 +1,205 @@ +package com.xr.device.common.utils; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.xr.device.model.entity.MeterInitialization; +import com.xr.device.model.service.MeterInitializationService; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class PythonExecutor { + + + public static void main(String[] args) throws Exception { + try { + String pythonPath = StaticPropUtil.pythonPath; + + ProcessBuilder processBuilder = new ProcessBuilder(pythonPath); + // 启动子进程 + Process process = processBuilder.start(); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); + bw.write("import sys\n"); + bw.write("sys.path.append(\"D:\\smartGrid\\smartGrid\\models\")\n"); + bw.write("import indicatorLightStatus as ils\n"); + bw.write("import switchRecognition as sr\n"); + bw.write("import liquidLevel as ll\n"); + bw.write("liquid_level_image_path = 'D:\\smartGrid\\smartGrid\\weights\\DIGITAL_METER (41).JPG'\n"); + bw.write("ll.calculate_rgb_min_max([[112,\"D:\\smartGrid\\smartGrid\\weights\\DIGITAL_METER (41).JPG\"]])\n"); + bw.write("print(\"Liquid level weights initialized.\")\n"); + bw.write("liquid_level_image_path = 'D:\\smartGrid\\smartGrid\\weights\\DIGITAL_METER (10).JPG'\n"); + bw.write("liquid_level = ll.calculate_liquid_level([112,liquid_level_image_path])\n"); + bw.write("print(f\"Liquid level: {liquid_level}\")\n"); + + bw.close(); + + + // 获取子进程的输出流 + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + + String line; + // 读取输出 + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + + // 等待进程执行完成 + int exitCode = process.waitFor(); + System.out.println("Exit Code: " + exitCode); + + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + + } + + private static boolean meterInit(String code) throws Exception { + String pythonPath = StaticPropUtil.pythonPath; + String modelPath = StaticPropUtil.modelPath; + + ProcessBuilder processBuilder = new ProcessBuilder(pythonPath); + // 启动子进程 + Process process = processBuilder.start(); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); + bw.write("import sys\n"); + String imports = "sys.path.append(\"%s\")\n"; + bw.write(String.format(imports, modelPath)); + bw.write("import indicatorLightStatus as ils\n"); + bw.write("import switchRecognition as sr\n"); + bw.write("import liquidLevel as ll\n"); + bw.write(code); + bw.write("print(\"success\")\n"); + bw.close(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + + List list = new ArrayList<>(); + String line; + // 读取输出 + while ((line = reader.readLine()) != null) { + list.add(line); + } + + // 等待进程执行完成 + int exitCode = process.waitFor(); + System.out.println("Exit Code: " + exitCode); + if (list.contains("success")) { + return true; + } + return false; + } + + /** + * 初始化算法 + * id 表计配置ID + * sfType 4 灯光 3 开关 5 液位计 + */ + public static boolean meterInit(Integer id, String sfType) throws Exception { + MeterInitializationService meterInitializationService = SpringUtils.getBean(MeterInitializationService.class); + QueryWrapper query = new QueryWrapper<>(); + query.eq("meter_id", id); + query.orderByAsc("serial"); + List list = meterInitializationService.list(query); + List path = list.stream().map(n -> n.getImgAddress()).collect(Collectors.toList()); + String ph = ""; + for (String str : path) { + str = str.replace("\\", "\\\\"); + ph += "\"" + str + "\"" + ","; + } + ph = ph.substring(0, ph.length() - 1); + String code = ""; + if (sfType.equals("4")) { + List> list1 = new ArrayList<>(); + List list2 = new ArrayList<>(); + list2.add(id); + List list3 = new ArrayList<>(); + list3.add(ph); + list2.add(list3); + list1.add(list2); + code = "ils.calculate_luminance_threshold(" + Arrays.toString(list1.toArray()) + ")\n"; + } + if (sfType.equals("3")) { + List list1 = new ArrayList<>(); + path.add(0, id + ""); + list1.add(ph); + code = "sr.initialize(" + Arrays.toString(list1.toArray()) + ")\n"; + } + if (sfType.equals("5")) { + List list1 = new ArrayList<>(); + path.add(0, id + ""); + list1.add(ph); + code = "ll.calculate_rgb_min_max(" + Arrays.toString(list1.toArray()) + ")\n"; + } + return meterInit(code); + + } + + /** + * 读取结果 + * id 表计id + * path 图片路径 + * sfType 1 灯光 2 开关 3 液位计 4 指针 + */ + public static String readNumber(Integer id, String path, String sfType) throws Exception { + String pythonPath = StaticPropUtil.pythonPath; + String modelPath = StaticPropUtil.modelPath; + + ProcessBuilder processBuilder = new ProcessBuilder(pythonPath); + // 启动子进程 + Process process = processBuilder.start(); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); + bw.write("import sys\n"); + String imports = "sys.path.append(\"%s\")\n"; + bw.write(String.format(imports, modelPath)); + bw.write("import indicatorLightStatus as ils\n"); + bw.write("import switchRecognition as sr\n"); + bw.write("import liquidLevel as ll\n"); + bw.write("indicator_light_image_path = '" + path + "'\n"); + if (sfType.equals("4")) { + bw.write("value = ils.check_indicator_light_status(" + id + ",indicator_light_image_path)\n"); + } + if (sfType.equals("3")) { + bw.write("value = sr.read_numbers(" + id + ",indicator_light_image_path)\n"); + } + if (sfType.equals("5")) { + bw.write("value = ll.calculate_liquid_level([" + id + ",indicator_light_image_path])\n"); + } + if (sfType.equals("0")) { + bw.write("rotate_angle, value = pr.getPointerAngleAndNum(" + id + ", indicator_light_image_path)\n"); + } + bw.write("print(f\"value:{value}\")"); + bw.close(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + List list = new ArrayList<>(); + String line; + // 读取输出 + while ((line = reader.readLine()) != null) { + list.add(line); + } +// if(list.contains("value")){ +// String value = list.get(list.indexOf("value")).split(":")[1]; +// File file = new File(path); +// if(file.exists()){ +// file.delete(); +// } +// return value; +// } + for (String element : list) { + if (element.contains("value")) { + String[] parts = element.split(":"); + File file = new File(path); + if (file.exists()) { + file.delete(); + } + if (parts.length > 1) { + String result = parts[1].trim(); + return result; + } + } + } + return null; + } + + +} diff --git a/device_gather/src/main/java/com/xr/device/common/utils/SpringUtils.java b/device_gather/src/main/java/com/xr/device/common/utils/SpringUtils.java new file mode 100644 index 0000000..2400a94 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/SpringUtils.java @@ -0,0 +1,151 @@ +package com.xr.device.common.utils; + +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware { + /** Spring应用上下文环境 */ + private static ConfigurableListableBeanFactory beanFactory; + + private static ApplicationContext applicationContext; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException + { + SpringUtils.beanFactory = beanFactory; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + SpringUtils.applicationContext = applicationContext; + } + + /** + * 获取对象 + * + * @param name + * @return Object 一个以所给名字注册的bean的实例 + * @throws BeansException + * + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException + { + return (T) beanFactory.getBean(name); + } + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws BeansException + * + */ + public static T getBean(Class clz) throws BeansException + { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true + * + * @param name + * @return boolean + */ + public static boolean containsBean(String name) + { + return beanFactory.containsBean(name); + } + + /** + * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + * @throws NoSuchBeanDefinitionException + * + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + * @throws NoSuchBeanDefinitionException + * + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + * + * @param name + * @return + * @throws NoSuchBeanDefinitionException + * + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getAliases(name); + } + + /** + * 获取aop代理对象 + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) + { + return (T) AopContext.currentProxy(); + } + + /** + * 获取当前的环境配置,无配置返回null + * + * @return 当前的环境配置 + */ + public static String[] getActiveProfiles() + { + return applicationContext.getEnvironment().getActiveProfiles(); + } + + /** + * 获取当前的环境配置,当有多个环境配置时,只获取第一个 + * + * @return 当前的环境配置 + */ + public static String getActiveProfile() + { + final String[] activeProfiles = getActiveProfiles(); + return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null; + } + + /** + * 获取配置文件中的值 + * + * @param key 配置文件的key + * @return 当前的配置文件的值 + * + */ + public static String getRequiredProperty(String key) + { + return applicationContext.getEnvironment().getRequiredProperty(key); + } +} diff --git a/device_gather/src/main/java/com/xr/device/common/utils/StaticPropUtil.java b/device_gather/src/main/java/com/xr/device/common/utils/StaticPropUtil.java new file mode 100644 index 0000000..0c746ce --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/StaticPropUtil.java @@ -0,0 +1,26 @@ +package com.xr.device.common.utils; + + +import com.xr.device.common.configvalue.StaticProperties; + +public class StaticPropUtil { + + public static String imgUrl; + + public static String imgPath; + + public static String pythonPath; + + public static String modelPath; + + public static Integer stationId; + + public static void initDingDingProp(StaticProperties dingProperties){ + imgUrl = dingProperties.getImgUrl(); + imgPath = dingProperties.getImgPath(); + pythonPath = dingProperties.getPythonPath(); + modelPath = dingProperties.getModelPath(); + stationId = dingProperties.getStationId(); + } + +} diff --git a/device_gather/src/main/java/com/xr/device/common/utils/StrFormatter.java b/device_gather/src/main/java/com/xr/device/common/utils/StrFormatter.java new file mode 100644 index 0000000..40ebf67 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/StrFormatter.java @@ -0,0 +1,90 @@ +package com.xr.device.common.utils; + +/** + * 字符串格式化 + * + * @author ruoyi + */ +public class StrFormatter +{ + public static final String EMPTY_JSON = "{}"; + public static final char C_BACKSLASH = '\\'; + public static final char C_DELIM_START = '{'; + public static final char C_DELIM_END = '}'; + + /** + * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param strPattern 字符串模板 + * @param argArray 参数列表 + * @return 结果 + */ + public static String format(final String strPattern, final Object... argArray) + { + if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) + { + return strPattern; + } + final int strPatternLength = strPattern.length(); + + // 初始化定义好的长度以获得更好的性能 + StringBuilder sbuf = new StringBuilder(strPatternLength + 50); + + int handledPosition = 0; + int delimIndex;// 占位符所在位置 + for (int argIndex = 0; argIndex < argArray.length; argIndex++) + { + delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); + if (delimIndex == -1) + { + if (handledPosition == 0) + { + return strPattern; + } + else + { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 + sbuf.append(strPattern, handledPosition, strPatternLength); + return sbuf.toString(); + } + } + else + { + if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) + { + if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) + { + // 转义符之前还有一个转义符,占位符依旧有效 + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + else + { + // 占位符被转义 + argIndex--; + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(C_DELIM_START); + handledPosition = delimIndex + 1; + } + } + else + { + // 正常占位符 + sbuf.append(strPattern, handledPosition, delimIndex); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + } + } + // 加入最后一个占位符后所有的字符 + sbuf.append(strPattern, handledPosition, strPattern.length()); + + return sbuf.toString(); + } +} diff --git a/device_gather/src/main/java/com/xr/device/common/utils/StringUtils.java b/device_gather/src/main/java/com/xr/device/common/utils/StringUtils.java new file mode 100644 index 0000000..d8f34ac --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/StringUtils.java @@ -0,0 +1,607 @@ +package com.xr.device.common.utils; + + +import org.springframework.util.AntPathMatcher; + +import java.util.*; + +/** + * 字符串工具类 + * + * @author ruoyi + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils +{ + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** 下划线 */ + private static final char SEPARATOR = '_'; + + /** + * 获取参数不为空值 + * + * @param value defaultValue 要判断的value + * @return value 返回值 + */ + public static T nvl(T value, T defaultValue) + { + return value != null ? value : defaultValue; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是否非空,包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Collection coll) + { + return !isEmpty(coll); + } + + /** + * * 判断一个对象数组是否为空 + * + * @param objects 要判断的对象数组 + ** @return true:为空 false:非空 + */ + public static boolean isEmpty(Object[] objects) + { + return isNull(objects) || (objects.length == 0); + } + + /** + * * 判断一个对象数组是否非空 + * + * @param objects 要判断的对象数组 + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Object[] objects) + { + return !isEmpty(objects); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Map map) + { + return isNull(map) || map.isEmpty(); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Map map) + { + return !isEmpty(map); + } + + /** + * * 判断一个字符串是否为空串 + * + * @param str String + * @return true:为空 false:非空 + */ + public static boolean isEmpty(String str) + { + return isNull(str) || NULLSTR.equals(str.trim()); + } + + /** + * * 判断一个字符串是否为非空串 + * + * @param str String + * @return true:非空串 false:空串 + */ + public static boolean isNotEmpty(String str) + { + return !isEmpty(str); + } + + /** + * * 判断一个对象是否为空 + * + * @param object Object + * @return true:为空 false:非空 + */ + public static boolean isNull(Object object) + { + return object == null; + } + + /** + * * 判断一个对象是否非空 + * + * @param object Object + * @return true:非空 false:空 + */ + public static boolean isNotNull(Object object) + { + return !isNull(object); + } + + /** + * * 判断一个对象是否是数组类型(Java基本型别的数组) + * + * @param object 对象 + * @return true:是数组 false:不是数组 + */ + public static boolean isArray(Object object) + { + return isNotNull(object) && object.getClass().isArray(); + } + + /** + * 去空格 + */ + public static String trim(String str) + { + return (str == null ? "" : str.trim()); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @return 结果 + */ + public static String substring(final String str, int start) + { + if (str == null) + { + return NULLSTR; + } + + if (start < 0) + { + start = str.length() + start; + } + + if (start < 0) + { + start = 0; + } + if (start > str.length()) + { + return NULLSTR; + } + + return str.substring(start); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end 结束 + * @return 结果 + */ + public static String substring(final String str, int start, int end) + { + if (str == null) + { + return NULLSTR; + } + + if (end < 0) + { + end = str.length() + end; + } + if (start < 0) + { + start = str.length() + start; + } + + if (end > str.length()) + { + end = str.length(); + } + + if (start > end) + { + return NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param template 文本模板,被替换的部分用 {} 表示 + * @param params 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... params) + { + if (isEmpty(params) || isEmpty(template)) + { + return template; + } + return StrFormatter.format(template, params); + } + + /** + * 是否为http(s)://开头 + * + * @param link 链接 + * @return 结果 + */ + public static boolean ishttp(String link) + { + return StringUtils.startsWithAny(link,"http://", "https://"); + } + + /** + * 字符串转set + * + * @param str 字符串 + * @param sep 分隔符 + * @return set集合 + */ + public static final Set str2Set(String str, String sep) + { + return new HashSet(str2List(str, sep, true, false)); + } + + /** + * 字符串转list + * + * @param str 字符串 + * @param sep 分隔符 + * @param filterBlank 过滤纯空白 + * @param trim 去掉首尾空白 + * @return list集合 + */ + public static final List str2List(String str, String sep, boolean filterBlank, boolean trim) + { + List list = new ArrayList(); + if (StringUtils.isEmpty(str)) + { + return list; + } + + // 过滤空白字符串 + if (filterBlank && StringUtils.isBlank(str)) + { + return list; + } + String[] split = str.split(sep); + for (String string : split) + { + if (filterBlank && StringUtils.isBlank(string)) + { + continue; + } + if (trim) + { + string = string.trim(); + } + list.add(string); + } + + return list; + } + + /** + * 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value + * @param array 给定的数组 + * @return boolean 结果 + */ + public static boolean containsAny(Collection collection, String... array) + { + if (isEmpty(collection) || isEmpty(array)) + { + return false; + } + else + { + for (String str : array) + { + if (collection.contains(str)) + { + return true; + } + } + return false; + } + } + + /** + * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 + * + * @param cs 指定字符串 + * @param searchCharSequences 需要检查的字符串数组 + * @return 是否包含任意一个字符串 + */ + public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) + { + if (isEmpty(cs) || isEmpty(searchCharSequences)) + { + return false; + } + for (CharSequence testStr : searchCharSequences) + { + if (containsIgnoreCase(cs, testStr)) + { + return true; + } + } + return false; + } + + /** + * 驼峰转下划线命名 + */ + public static String toUnderScoreCase(String str) + { + if (str == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + // 前置字符是否大写 + boolean preCharIsUpperCase = true; + // 当前字符是否大写 + boolean curreCharIsUpperCase = true; + // 下一字符是否大写 + boolean nexteCharIsUpperCase = true; + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (i > 0) + { + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); + } + else + { + preCharIsUpperCase = false; + } + + curreCharIsUpperCase = Character.isUpperCase(c); + + if (i < (str.length() - 1)) + { + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); + } + + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) + { + sb.append(SEPARATOR); + } + else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) + { + sb.append(SEPARATOR); + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必要转换 + return ""; + } + else if (!name.contains("_")) + { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) + { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + /** + * 驼峰式命名法 + * 例如:user_name->userName + */ + public static String toCamelCase(String s) + { + if (s == null) + { + return null; + } + if (s.indexOf(SEPARATOR) == -1) + { + return s; + } + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + if (c == SEPARATOR) + { + upperCase = true; + } + else if (upperCase) + { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } + else + { + sb.append(c); + } + } + return sb.toString(); + } + + /** + * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, List strs) + { + if (isEmpty(str) || isEmpty(strs)) + { + return false; + } + for (String pattern : strs) + { + if (isMatch(pattern, str)) + { + return true; + } + } + return false; + } + + /** + * 判断url是否与规则配置: + * ? 表示单个字符; + * * 表示一层路径内的任意字符串,不可跨层级; + * ** 表示任意层路径; + * + * @param pattern 匹配规则 + * @param url 需要匹配的url + * @return + */ + public static boolean isMatch(String pattern, String url) + { + AntPathMatcher matcher = new AntPathMatcher(); + return matcher.match(pattern, url); + } + + @SuppressWarnings("unchecked") + public static T cast(Object obj) + { + return (T) obj; + } + + /** + * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 + * + * @param num 数字对象 + * @param size 字符串指定长度 + * @return 返回数字的字符串格式,该字符串为指定长度。 + */ + public static final String padl(final Number num, final int size) + { + return padl(num.toString(), size, '0'); + } + + /** + * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 + * + * @param s 原始字符串 + * @param size 字符串指定长度 + * @param c 用于补齐的字符 + * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 + */ + public static final String padl(final String s, final int size, final char c) + { + final StringBuilder sb = new StringBuilder(size); + if (s != null) + { + final int len = s.length(); + if (s.length() <= size) + { + for (int i = size - len; i > 0; i--) + { + sb.append(c); + } + sb.append(s); + } + else + { + return s.substring(len - size, len); + } + } + else + { + for (int i = size; i > 0; i--) + { + sb.append(c); + } + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/device_gather/src/main/java/com/xr/device/common/utils/UploadUtil.java b/device_gather/src/main/java/com/xr/device/common/utils/UploadUtil.java new file mode 100644 index 0000000..2133dfa --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/UploadUtil.java @@ -0,0 +1,187 @@ +package com.xr.device.common.utils; + +import org.apache.poi.ss.usermodel.Workbook; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class UploadUtil { + + public static String uploadExcel(Workbook workbook,String path,String url1,String fileName) throws Exception{ + FileOutputStream outputStream =new FileOutputStream(path+fileName); + workbook.write(outputStream); + outputStream.close(); + String url = url1+fileName; + return url; + } + + + public static String uploadImage(String clentIp,Integer configId,String fileName) throws Exception { + // 构建完整的路径 + String url = "http://"+clentIp+":8080/tao/snapshot"; + SimpleDateFormat sim=new SimpleDateFormat("yyyy-MM-dd-HH"); + String date = sim.format(new Date()); + String dates[] = date.split("-"); + + String year = dates[0]; + String month = dates[1]; + String day = dates[2]; + String ho = dates[3]; + String fullPath = StaticPropUtil.imgPath+configId + File.separator + year + File.separator + month + File.separator + day + File.separator +ho+File.separator+ fileName; + + // 创建目录结构 + Path directoryPath = Paths.get(StaticPropUtil.imgPath,configId.toString(), year, month, day,ho); + if (!Files.exists(directoryPath)) { + Files.createDirectories(directoryPath); + } + + downloadImage(url,fullPath); + + // 构建URL + String url1 = StaticPropUtil.imgUrl+ configId + "/" + year + "/"+ month + "/" + day + "/" +ho+"/"+ fileName; + return url1; + } + + public static String uploadImage(BufferedImage buffer,Integer configId,String fileName) throws Exception { + // 构建完整的路径 + SimpleDateFormat sim=new SimpleDateFormat("yyyy-MM-dd-HH"); + String date = sim.format(new Date()); + String dates[] = date.split("-"); + + String year = dates[0]; + String month = dates[1]; + String day = dates[2]; + String ho = dates[3]; + String fullPath = StaticPropUtil.imgPath+configId + File.separator + year + File.separator + month + File.separator + day + File.separator +ho+File.separator+ fileName; + + // 创建目录结构 + Path directoryPath = Paths.get(StaticPropUtil.imgPath,configId.toString(), year, month, day,ho); + if (!Files.exists(directoryPath)) { + Files.createDirectories(directoryPath); + } + + downloadImage(buffer,fullPath); + + // 构建URL + String url1 = StaticPropUtil.imgUrl+ configId + "/" + year + "/"+ month + "/" + day + "/" +ho+"/"+ fileName; + return url1; + } + + + public static BufferedImage urlByImage(String url) throws IOException { + URL urlfile = new URL(url); + InputStream is2 = urlfile.openStream(); + BufferedImage uImg= ImageIO.read(is2); + return uImg; + } + + public static void delFile(String path,String url,String fileUrl){ + String filePath = fileUrl.replace(url,path).replace("/","\\"); + File file = new File(filePath); + if(file.exists()){ + file.delete(); + } + } + + public static void downloadImage(String imageUrl, String destinationPath) throws IOException { + URL url = new URL(imageUrl); + try (InputStream in = url.openStream(); + FileOutputStream out = new FileOutputStream(destinationPath)) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = in.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + } + } + + public static void downloadImage(BufferedImage bufferedImage, String destinationPath) throws IOException { + File file = new File(destinationPath); + ImageIO.write(bufferedImage,"jpg",file); + } + + public static BufferedImage drawRectangleAndText(BufferedImage image, double x1, double y1,double x2, double wid, double hei, String text1, String text2) { + // 创建一个Graphics2D对象 + Graphics2D g2d = image.createGraphics(); + + + // 设置抗锯齿 + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + + // 创建一个Rectangle2D.Double对象 + Rectangle2D.Double rect = new Rectangle2D.Double(x1, y1, wid, hei); + + // 绘制红色框 + g2d.setColor(Color.RED); + g2d.draw(rect); + // 设置粗线条 + g2d.setStroke(new BasicStroke(3.0f * 30)); // 设置线条宽度为3.0f + + // 设置字体和颜色 + g2d.setFont(new Font("微软雅黑", Font.BOLD, 38)); // 使用支持中文的字体,增加字体大小 + + // 获取当前时间 + String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); + // 获取文本的宽度和高度 + FontMetrics fm = g2d.getFontMetrics(); + + // 绘制当前时间的背景矩形 + int padding = 20; + int currentTimeWidth = fm.stringWidth(currentTime); + int currentTimeHeight = fm.getHeight(); + int rectPadding = 5; // 背景矩形内边距 + g2d.setColor(new Color(0, 0, 0, 50)); // 黑色半透明背景 + g2d.fillRect(padding, padding, currentTimeWidth + 2 * rectPadding, currentTimeHeight + 2 * rectPadding); + + // 绘制当前时间在左上角,内边距为20px + g2d.setColor(Color.WHITE); + int currentTimeX = padding + rectPadding + (currentTimeWidth + rectPadding - currentTimeWidth) / 2; + int currentTimeY = padding + rectPadding + fm.getAscent(); + g2d.drawString(currentTime, currentTimeX, currentTimeY); + + // 绘制文本2的背景矩形 + if(text2!=null){ + int text2Width = fm.stringWidth(text2); + int text2Height = fm.getHeight(); + g2d.setColor(new Color(0, 0, 0, 50)); // 黑色半透明背景 + g2d.fillRect(padding, padding + currentTimeHeight + rectPadding * 2, text2Width + 2 * rectPadding, text2Height + 2 * rectPadding); + // 绘制文本2在时间的下面,内边距为20px + g2d.setColor(Color.WHITE); + int text2X = padding + rectPadding + (text2Width + rectPadding - text2Width) / 2; + int text2Y = padding + currentTimeHeight + rectPadding * 3 + fm.getAscent(); + g2d.drawString(text2, text2X, text2Y); + } + + + + // 计算文本1的右上角位置 + int text1X = (int) (x1 + wid); // 框的右上角位置 + int text1Y = (int) (y1 + fm.getAscent()); // 框的右上角紧挨着框 + g2d.setColor(Color.RED); + + g2d.drawString(text1, text1X, text1Y); + + + // 释放资源 + g2d.dispose(); + + return image; + } + + + + +} diff --git a/device_gather/src/main/java/com/xr/device/common/utils/ValueFormatUtil.java b/device_gather/src/main/java/com/xr/device/common/utils/ValueFormatUtil.java new file mode 100644 index 0000000..9bce9ca --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/common/utils/ValueFormatUtil.java @@ -0,0 +1,80 @@ +package com.xr.device.common.utils; + + +import com.xr.device.model.entity.MeterConfig; +import com.xr.device.model.service.MeterConfigService; + +public class ValueFormatUtil { + + /* + * 处理AI分析的计数器数值,针对可以识别到,但偶尔有错误结果出现的情况 + * 1.抄写基准值 + * 2.与基准值比较,如果比基准值大于1,可能计数器跳1,更新基准值,并返回结果 + * 反之返回基准值结果为识别结果 + * 3.如果未设基准值,去0后保存结果 + * */ + public static String getNumBerJx(float getVal, MeterConfig config, MeterConfigService meterConfigService){ + int s = (int) getVal; + Integer jz = Integer.valueOf(config.getJzVal())+1; + if(StringUtils.isNotEmpty(config.getJzVal())){ + if(s==jz){ + config.setJzVal(jz+""); + meterConfigService.updateById(config); + return jz+""; + }else{ + return config.getJzVal(); + } + }else{ + return s+""; + } + } + + public static String getYwj(float f,MeterConfig config){//处理液位计识别结果 + if((f == 0 || f>1)&& StringUtils.isNotEmpty(config.getJzVal())){ + return config.getJzVal(); + }else{ + return String.format("%.2f", f*100)+"%"; + } + } + + public static String getZZl(float f,MeterConfig config){//处理指针类识别结果 + if(f ==0 && StringUtils.isNotEmpty(config.getJzVal())){ + return config.getJzVal(); + }else{ + return String.format("%.2f", f); + } + } + + public static String getDw(float f){ + int s = Math.round(f); + if(s>8){ + int t = s-8; + if(t<9){ + return t+""; + } + if(t == 9){ + return "9A"; + } + if(t == 10){ + return "9B"; + } + if(t == 11){ + return "9C"; + } + if(t>11){ + return t-2+""; + } + } + return s+""; + } + + public static String getfdjsq(float f){ + int s = Math.round(f); + if(s>=10){ + return 0+""; + }else { + return s+""; + } + } + +} diff --git a/device_gather/src/main/java/com/xr/device/model/entity/DeviceCamera.java b/device_gather/src/main/java/com/xr/device/model/entity/DeviceCamera.java new file mode 100644 index 0000000..bda6a89 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/entity/DeviceCamera.java @@ -0,0 +1,126 @@ +package com.xr.device.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * + * @TableName device_camera + */ +@TableName(value ="device_camera") +@Data +public class DeviceCamera implements Serializable { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 摄像头编号 + */ + private String deviceNo; + + /** + * 类型(1 usb 2 mipi 3 球机 4 枪机) + */ + private String deviceType; + + /** + * IP + */ + private String deviceIp; + + /** + * 端口 + */ + private String devicePort; + + /** + * 账号 + */ + private String account; + + /** + * 密码 + */ + private String password; + + /** + * x轴 + */ + private String x; + + /** + * y轴 + */ + private String y; + + /** + * z轴 + */ + private String z; + + /** + * 摄像头型号 + */ + private String deviceModel; + + /** + * 安装位置 + */ + private String position; + + /** + * 品牌 + */ + private String brand; + + /** + * 备注 + */ + private String remarks; + + /** + * 状态(0未使用 1已使用) + */ + private String status; + + /** + * 创建人 + */ + private String createUser; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateUser; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 传输间隔 + */ + private Integer transmissionInterval; + + /** + * 对焦时间 + */ + private Integer warmup; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/device_gather/src/main/java/com/xr/device/model/entity/FocalLengthConfig.java b/device_gather/src/main/java/com/xr/device/model/entity/FocalLengthConfig.java new file mode 100644 index 0000000..31bab4e --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/entity/FocalLengthConfig.java @@ -0,0 +1,141 @@ +package com.xr.device.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * + * @TableName focal_length_config + */ +@TableName(value ="focal_length_config") +@Data +public class FocalLengthConfig implements Serializable { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 表计配置编号 + */ + private Integer configId; + + /** + * 焦距名称 + */ + private String focalName; + + /** + * 焦距tabs下标 + */ + private String focalIndex; + + /** + * 截图框宽 + */ + private Double copperWid; + + /** + * 截图框高 + */ + private Double copperHei; + + /** + * 截图框X坐标 + */ + private Double copperX; + + /** + * + */ + private Double copperX2; + + /** + * 截图框Y坐标 + */ + private Double copperY; + + /** + * + */ + private Double copperY2; + + /** + * 1指针表计,2数字表计,3状态类 + */ + private String configType; + + /** + * 指针最小值 + */ + private Double meterMin; + + /** + * 指针最大值 + */ + private Double meterMax; + + /** + * 旋转角度 + */ + private Integer rotate; + + /** + * 缩放倍数 + */ + private Double scale; + + /** + * 状态类状态数量 + */ + private Integer stateNum; + + /** + * 保存状态类多个状态的结果集 + */ + private String parameter; + + /** + * 解析得测试结果 + */ + private String result; + + /** + * 算法:0圆形表计1扇形表计 + */ + private Integer algorithm; + + /** + * 创建人 + */ + private String createUser; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateUser; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 焦距图片 + */ + private byte[] focalPicture; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/device_gather/src/main/java/com/xr/device/model/entity/MeterConfig.java b/device_gather/src/main/java/com/xr/device/model/entity/MeterConfig.java new file mode 100644 index 0000000..d3137f1 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/entity/MeterConfig.java @@ -0,0 +1,183 @@ +package com.xr.device.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import lombok.Data; + +/** + * + * @TableName meter_config + */ +@TableName(value ="meter_config") +@Data +public class MeterConfig implements Serializable { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * ids5000表id + */ + private Integer ids5000Id; + + /** + * 间隔类型 1 分钟 2 小时 3 天 + */ + private Integer intervalType; + + /** + * 电压等级(1安全电压2低压3高压4超高压5特高压) + */ + private String voltageClass; + + /** + * 所属间隔 + */ + private String owningInterval; + + /** + * 识别间隔 + */ + private String identificationInterval; + + /** + * 所属设备 + */ + private String deviceName; + + /** + * y坐标 + */ + private Double locationY; + + /** + * x坐标 + */ + private Double locationX; + + /** + * 设备类型 + */ + private String deviceType; + + /** + * 表计编号 + */ + private String meterCode; + + /** + * 表计名称 + */ + private String meterName; + + /** + * 所属摄像头 + */ + private Integer cameraId; + + /** + * 告警最小值 + */ + private Double warningMax; + + /** + * 告警最大值 + */ + private Double warningMin; + + /** + * 表计类型配置编号 + */ + private Integer typeId; + + /** + * 状态(0停用1启用) + */ + private Integer status; + + /** + * 首次识别时间 + */ + private Date firstTime; + + /** + * 算法类型 1usb2mipi 3内部算法 + */ + private String algorithmType; + + /** + * 执行间隔时间 + */ + private Integer intervalTime; + + /** + * 焦距数量 + */ + private Integer focalNumber; + + /** + * 超参配置 + */ + private String parameterConfig; + + /** + * 备注 + */ + private String remarks; + + /** + * 61850读数模型 + */ + private String iec61850mx; + + /** + * 1校准 其他不校准 + */ + private Integer isJz; + + /** + * 校准值 + */ + private String jzVal; + + /** + * 0 未初始化 1已初始化 + */ + private String initStatus; + + /** + * 创建人 + */ + private String createUser; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 修改人 + */ + private String updateUser; + + /** + * 修改时间 + */ + private Date updateTime; + + @TableField(exist = false) + private String deviceIp; + + @TableField(exist = false) + private String meterType; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/device_gather/src/main/java/com/xr/device/model/entity/MeterInitialization.java b/device_gather/src/main/java/com/xr/device/model/entity/MeterInitialization.java new file mode 100644 index 0000000..d6d3274 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/entity/MeterInitialization.java @@ -0,0 +1,50 @@ +package com.xr.device.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; + +/** + * 表计算法初始化 + * @TableName meter_initialization + */ +@TableName(value ="meter_initialization") +@Data +public class MeterInitialization implements Serializable { + /** + * id + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 请求图片路径 + */ + private String img; + + /** + * 盘符路径 + */ + private String imgAddress; + + /** + * 常量值 + */ + private String value; + + /** + * 表计id + */ + private Integer meterId; + + /** + * 序号(从0开始) + */ + private Integer serial; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/device_gather/src/main/java/com/xr/device/model/entity/MeterReadingRecord.java b/device_gather/src/main/java/com/xr/device/model/entity/MeterReadingRecord.java new file mode 100644 index 0000000..756860b --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/entity/MeterReadingRecord.java @@ -0,0 +1,97 @@ +package com.xr.device.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import lombok.Data; + +/** + * + * @TableName meter_reading_record + */ +@TableName(value ="meter_reading_record") +@Data +public class MeterReadingRecord implements Serializable { + /** + * 主键id + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 表计id + */ + private Integer meterId; + + /** + * 表计编号 + */ + private String meterCode; + + /** + * 表计类型id + */ + private Integer meterTypeId; + + /** + * 表计类型名称 + */ + private String meterTypeName; + + /** + * 所属间隔 + */ + private String owningInterval; + + /** + * 读数时间 + */ + private Date readingTime; + + /** + * 读数类型(1 一体化电源 2 AI摄像头 3 串口) + */ + private Integer readingType; + + /** + * 0 遥控 1遥信 2遥测 + */ + private Integer dataType; + + /** + * 读数值 + */ + private String readingValue; + + /** + * 表计照片 + */ + private String readingUrl; + + /** + * 创建人 + */ + private String createUser; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 修改人 + */ + private String updateUser; + + /** + * 修改时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/device_gather/src/main/java/com/xr/device/model/entity/MeterType.java b/device_gather/src/main/java/com/xr/device/model/entity/MeterType.java new file mode 100644 index 0000000..e594108 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/entity/MeterType.java @@ -0,0 +1,86 @@ +package com.xr.device.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * 表计类型表 + * @TableName meter_type + */ +@TableName(value ="meter_type") +@Data +public class MeterType implements Serializable { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 表计类型名称 + */ + private String meterType; + + /** + * 表计形状(0圆形指针1扇形指针2数字类表计3开关类表计4灯类表计5液位计) + */ + private String meterShape; + + /** + * 表计超参(对应的参数) + */ + private String typeDescription; + + /** + * 表计类型传输标识 + */ + private String typeIdentification; + + /** + * 备注 + */ + private String remarks; + + /** + * 读数单位 + */ + private String readingUnit; + + /** + * 表计类型别名 + */ + private String typeAlias; + + /** + * 0停用1启用 + */ + private String status; + + /** + * 创建人 + */ + private String createUser; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateUser; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/device_gather/src/main/java/com/xr/device/model/mapper/DeviceCameraMapper.java b/device_gather/src/main/java/com/xr/device/model/mapper/DeviceCameraMapper.java new file mode 100644 index 0000000..bf8070e --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/mapper/DeviceCameraMapper.java @@ -0,0 +1,20 @@ +package com.xr.device.model.mapper; + +import com.xr.device.model.entity.DeviceCamera; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** +* @author 范亚杰 +* @description 针对表【device_camera】的数据库操作Mapper +* @createDate 2024-06-25 17:30:54 +* @Entity com.xr.device.model.entity.DeviceCamera +*/ +@Mapper +public interface DeviceCameraMapper extends BaseMapper { + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/mapper/FocalLengthConfigMapper.java b/device_gather/src/main/java/com/xr/device/model/mapper/FocalLengthConfigMapper.java new file mode 100644 index 0000000..8e5e2f3 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/mapper/FocalLengthConfigMapper.java @@ -0,0 +1,20 @@ +package com.xr.device.model.mapper; + +import com.xr.device.model.entity.FocalLengthConfig; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** +* @author 范亚杰 +* @description 针对表【focal_length_config】的数据库操作Mapper +* @createDate 2024-06-25 17:31:06 +* @Entity com.xr.device.model.entity.FocalLengthConfig +*/ +@Mapper +public interface FocalLengthConfigMapper extends BaseMapper { + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/mapper/MeterConfigMapper.java b/device_gather/src/main/java/com/xr/device/model/mapper/MeterConfigMapper.java new file mode 100644 index 0000000..6c92c59 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/mapper/MeterConfigMapper.java @@ -0,0 +1,24 @@ +package com.xr.device.model.mapper; + +import com.xr.device.model.entity.MeterConfig; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** +* @author 范亚杰 +* @description 针对表【meter_config】的数据库操作Mapper +* @createDate 2024-06-25 17:30:43 +* @Entity com.xr.device.model.entity.MeterConfig +*/ +@Mapper +public interface MeterConfigMapper extends BaseMapper { + + List getMeterList(Integer stationId); + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/mapper/MeterInitializationMapper.java b/device_gather/src/main/java/com/xr/device/model/mapper/MeterInitializationMapper.java new file mode 100644 index 0000000..0827cb5 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/mapper/MeterInitializationMapper.java @@ -0,0 +1,20 @@ +package com.xr.device.model.mapper; + +import com.xr.device.model.entity.MeterInitialization; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** +* @author 范亚杰 +* @description 针对表【meter_initialization(表计算法初始化)】的数据库操作Mapper +* @createDate 2024-07-02 17:22:01 +* @Entity com.xr.device.model.entity.MeterInitialization +*/ +@Mapper +public interface MeterInitializationMapper extends BaseMapper { + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/mapper/MeterReadingRecordMapper.java b/device_gather/src/main/java/com/xr/device/model/mapper/MeterReadingRecordMapper.java new file mode 100644 index 0000000..e85c5a7 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/mapper/MeterReadingRecordMapper.java @@ -0,0 +1,20 @@ +package com.xr.device.model.mapper; + +import com.xr.device.model.entity.MeterReadingRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** +* @author 范亚杰 +* @description 针对表【meter_reading_record】的数据库操作Mapper +* @createDate 2024-06-25 17:30:30 +* @Entity com.xr.device.model.entity.MeterReadingRecord +*/ +@Mapper +public interface MeterReadingRecordMapper extends BaseMapper { + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/mapper/MeterTypeMapper.java b/device_gather/src/main/java/com/xr/device/model/mapper/MeterTypeMapper.java new file mode 100644 index 0000000..c127edd --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/mapper/MeterTypeMapper.java @@ -0,0 +1,20 @@ +package com.xr.device.model.mapper; + +import com.xr.device.model.entity.MeterType; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** +* @author 范亚杰 +* @description 针对表【meter_type(表计类型表)】的数据库操作Mapper +* @createDate 2024-07-02 17:29:04 +* @Entity com.xr.device.model.entity.MeterType +*/ +@Mapper +public interface MeterTypeMapper extends BaseMapper { + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/service/DeviceCameraService.java b/device_gather/src/main/java/com/xr/device/model/service/DeviceCameraService.java new file mode 100644 index 0000000..a77b6bb --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/DeviceCameraService.java @@ -0,0 +1,13 @@ +package com.xr.device.model.service; + +import com.xr.device.model.entity.DeviceCamera; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author 范亚杰 +* @description 针对表【device_camera】的数据库操作Service +* @createDate 2024-06-25 17:30:54 +*/ +public interface DeviceCameraService extends IService { + +} diff --git a/device_gather/src/main/java/com/xr/device/model/service/FocalLengthConfigService.java b/device_gather/src/main/java/com/xr/device/model/service/FocalLengthConfigService.java new file mode 100644 index 0000000..67bf60f --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/FocalLengthConfigService.java @@ -0,0 +1,13 @@ +package com.xr.device.model.service; + +import com.xr.device.model.entity.FocalLengthConfig; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author 范亚杰 +* @description 针对表【focal_length_config】的数据库操作Service +* @createDate 2024-06-25 17:31:06 +*/ +public interface FocalLengthConfigService extends IService { + +} diff --git a/device_gather/src/main/java/com/xr/device/model/service/MeterConfigService.java b/device_gather/src/main/java/com/xr/device/model/service/MeterConfigService.java new file mode 100644 index 0000000..34a48dc --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/MeterConfigService.java @@ -0,0 +1,17 @@ +package com.xr.device.model.service; + +import com.xr.device.model.entity.MeterConfig; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** +* @author 范亚杰 +* @description 针对表【meter_config】的数据库操作Service +* @createDate 2024-06-25 17:30:43 +*/ +public interface MeterConfigService extends IService { + + List getMeterList(Integer station); + +} diff --git a/device_gather/src/main/java/com/xr/device/model/service/MeterInitializationService.java b/device_gather/src/main/java/com/xr/device/model/service/MeterInitializationService.java new file mode 100644 index 0000000..b71feac --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/MeterInitializationService.java @@ -0,0 +1,13 @@ +package com.xr.device.model.service; + +import com.xr.device.model.entity.MeterInitialization; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author 范亚杰 +* @description 针对表【meter_initialization(表计算法初始化)】的数据库操作Service +* @createDate 2024-07-02 17:22:01 +*/ +public interface MeterInitializationService extends IService { + +} diff --git a/device_gather/src/main/java/com/xr/device/model/service/MeterReadingRecordService.java b/device_gather/src/main/java/com/xr/device/model/service/MeterReadingRecordService.java new file mode 100644 index 0000000..5adce52 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/MeterReadingRecordService.java @@ -0,0 +1,13 @@ +package com.xr.device.model.service; + +import com.xr.device.model.entity.MeterReadingRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author 范亚杰 +* @description 针对表【meter_reading_record】的数据库操作Service +* @createDate 2024-06-25 17:30:30 +*/ +public interface MeterReadingRecordService extends IService { + +} diff --git a/device_gather/src/main/java/com/xr/device/model/service/MeterTypeService.java b/device_gather/src/main/java/com/xr/device/model/service/MeterTypeService.java new file mode 100644 index 0000000..6386b5e --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/MeterTypeService.java @@ -0,0 +1,13 @@ +package com.xr.device.model.service; + +import com.xr.device.model.entity.MeterType; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author 范亚杰 +* @description 针对表【meter_type(表计类型表)】的数据库操作Service +* @createDate 2024-07-02 17:29:04 +*/ +public interface MeterTypeService extends IService { + +} diff --git a/device_gather/src/main/java/com/xr/device/model/service/impl/DeviceCameraServiceImpl.java b/device_gather/src/main/java/com/xr/device/model/service/impl/DeviceCameraServiceImpl.java new file mode 100644 index 0000000..100cfe0 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/impl/DeviceCameraServiceImpl.java @@ -0,0 +1,24 @@ +package com.xr.device.model.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.xr.device.model.entity.DeviceCamera; +import com.xr.device.model.service.DeviceCameraService; +import com.xr.device.model.mapper.DeviceCameraMapper; +import org.springframework.stereotype.Service; + +/** +* @author 范亚杰 +* @description 针对表【device_camera】的数据库操作Service实现 +* @createDate 2024-06-25 17:30:54 +*/ +@Service +@DS("db2") +public class DeviceCameraServiceImpl extends ServiceImpl + implements DeviceCameraService{ + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/service/impl/FocalLengthConfigServiceImpl.java b/device_gather/src/main/java/com/xr/device/model/service/impl/FocalLengthConfigServiceImpl.java new file mode 100644 index 0000000..1ccbbd3 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/impl/FocalLengthConfigServiceImpl.java @@ -0,0 +1,24 @@ +package com.xr.device.model.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.xr.device.model.entity.FocalLengthConfig; +import com.xr.device.model.service.FocalLengthConfigService; +import com.xr.device.model.mapper.FocalLengthConfigMapper; +import org.springframework.stereotype.Service; + +/** +* @author 范亚杰 +* @description 针对表【focal_length_config】的数据库操作Service实现 +* @createDate 2024-06-25 17:31:06 +*/ +@Service +@DS("db2") +public class FocalLengthConfigServiceImpl extends ServiceImpl + implements FocalLengthConfigService{ + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/service/impl/MeterConfigServiceImpl.java b/device_gather/src/main/java/com/xr/device/model/service/impl/MeterConfigServiceImpl.java new file mode 100644 index 0000000..3bc38cb --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/impl/MeterConfigServiceImpl.java @@ -0,0 +1,30 @@ +package com.xr.device.model.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.xr.device.model.entity.MeterConfig; +import com.xr.device.model.service.MeterConfigService; +import com.xr.device.model.mapper.MeterConfigMapper; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** +* @author 范亚杰 +* @description 针对表【meter_config】的数据库操作Service实现 +* @createDate 2024-06-25 17:30:43 +*/ +@Service +@DS("db2") +public class MeterConfigServiceImpl extends ServiceImpl + implements MeterConfigService{ + + @Override + public List getMeterList(Integer stationId) { + return ((MeterConfigMapper)this.baseMapper).getMeterList(stationId); + } +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/service/impl/MeterInitializationServiceImpl.java b/device_gather/src/main/java/com/xr/device/model/service/impl/MeterInitializationServiceImpl.java new file mode 100644 index 0000000..7838135 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/impl/MeterInitializationServiceImpl.java @@ -0,0 +1,24 @@ +package com.xr.device.model.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.xr.device.model.entity.MeterInitialization; +import com.xr.device.model.service.MeterInitializationService; +import com.xr.device.model.mapper.MeterInitializationMapper; +import org.springframework.stereotype.Service; + +/** +* @author 范亚杰 +* @description 针对表【meter_initialization(表计算法初始化)】的数据库操作Service实现 +* @createDate 2024-07-02 17:22:01 +*/ +@Service +@DS("db2") +public class MeterInitializationServiceImpl extends ServiceImpl + implements MeterInitializationService{ + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/service/impl/MeterReadingRecordServiceImpl.java b/device_gather/src/main/java/com/xr/device/model/service/impl/MeterReadingRecordServiceImpl.java new file mode 100644 index 0000000..deb8651 --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/impl/MeterReadingRecordServiceImpl.java @@ -0,0 +1,24 @@ +package com.xr.device.model.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.xr.device.model.entity.MeterReadingRecord; +import com.xr.device.model.service.MeterReadingRecordService; +import com.xr.device.model.mapper.MeterReadingRecordMapper; +import org.springframework.stereotype.Service; + +/** +* @author 范亚杰 +* @description 针对表【meter_reading_record】的数据库操作Service实现 +* @createDate 2024-06-25 17:30:30 +*/ +@Service +@DS("db2") +public class MeterReadingRecordServiceImpl extends ServiceImpl + implements MeterReadingRecordService{ + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/model/service/impl/MeterTypeServiceImpl.java b/device_gather/src/main/java/com/xr/device/model/service/impl/MeterTypeServiceImpl.java new file mode 100644 index 0000000..d3978ed --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/model/service/impl/MeterTypeServiceImpl.java @@ -0,0 +1,24 @@ +package com.xr.device.model.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.xr.device.model.entity.MeterType; +import com.xr.device.model.service.MeterTypeService; +import com.xr.device.model.mapper.MeterTypeMapper; +import org.springframework.stereotype.Service; + +/** +* @author 范亚杰 +* @description 针对表【meter_type(表计类型表)】的数据库操作Service实现 +* @createDate 2024-07-02 17:29:04 +*/ +@Service +@DS("db2") +public class MeterTypeServiceImpl extends ServiceImpl + implements MeterTypeService{ + +} + + + + diff --git a/device_gather/src/main/java/com/xr/device/schedule/GetMeterSchedule.java b/device_gather/src/main/java/com/xr/device/schedule/GetMeterSchedule.java new file mode 100644 index 0000000..eff8cea --- /dev/null +++ b/device_gather/src/main/java/com/xr/device/schedule/GetMeterSchedule.java @@ -0,0 +1,204 @@ +package com.xr.device.schedule; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import com.serotonin.modbus4j.ip.IpParameters; +import com.xr.device.common.utils.*; +import com.xr.device.model.entity.*; +import com.xr.device.model.service.*; +import com.xr.onvifhk.entity.BallheadPT; +import com.xr.onvifhk.entity.DeviceInfo; +import com.xr.onvifhk.util.HkComUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +@Component +@RequiredArgsConstructor +@Slf4j +public class GetMeterSchedule { + + private final MeterConfigService meterConfigService; + + private final FocalLengthConfigService focalLengthConfigService; + + private final MeterReadingRecordService meterReadingRecordService; + + private final DeviceCameraService deviceCameraService; + + private final MeterTypeService meterTypeService; + + @Scheduled(cron = "0 0 9,15 * * ?")//每天9点和下午三点执行 + public void getMeterSchedule(){ + List configs = meterConfigService.getMeterList(StaticPropUtil.stationId); + int pageSize = 10; // 每页的设备数量 + int totalDevices = configs.size(); // 总设备数量 + int totalPages = (int) Math.ceil((double) totalDevices / pageSize); // 总页数 + for (int pageNumber = 0; pageNumber < totalPages; pageNumber++) { + List devices = new ArrayList<>(); + for (int i = pageNumber * pageSize; i < (pageNumber + 1) * pageSize && i < totalDevices; i++) { + devices.add(configs.get(i)); + } + + ExecutorService executorService = Executors.newFixedThreadPool(pageSize); + + for (MeterConfig device : devices) { + executorService.submit(() -> collectDataFromDevice(device)); + } + + // 关闭线程池,等待所有任务完成 + executorService.shutdown(); + try { + if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { + executorService.shutdownNow(); + } + } catch (InterruptedException e) { + executorService.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + } + + //采集方法 + private void collectDataFromDevice(MeterConfig config) { + // 实现采集逻辑 + try { + MeterType meterType=meterTypeService.getById(config.getTypeId()); + float f = 0; + if(config.getAlgorithmType().equals("3")){ + DeviceCamera deviceCamera=deviceCameraService.getById(config.getCameraId()); + QueryWrapper query=new QueryWrapper<>(); + query.eq("config_id",config.getId()); + FocalLengthConfig config1 = focalLengthConfigService.getOne(query); + BallheadPT ball=null; + if(deviceCamera.getDeviceType().equals("3")){ + ball=new BallheadPT(); + ball.setX(deviceCamera.getX()); + ball.setY(deviceCamera.getY()); + ball.setZ(deviceCamera.getZ()); + } + DeviceInfo deviceInfo=new DeviceInfo(); + deviceInfo.setPort(1502); + deviceInfo.setIp(deviceCamera.getDeviceIp()); + deviceInfo.setAccount(deviceCamera.getAccount()); + deviceInfo.setPassword(deviceCamera.getPassword()); + String url = HkComUtil.getBole(deviceInfo,null); + BufferedImage image = Files.urlByImage(url); + //获取已截图的图片 + String path = getAnalysis(config1,image); + String value=PythonExecutor.readNumber(config.getId(),path,meterType.getMeterShape()); + f = Float.valueOf(value); + }else{ + ModbusMaster master= ModbusUtils.getMaster(config.getDeviceIp(),1502); + master.init(); + MeterReadingRecord meterReadingRecord=new MeterReadingRecord(); + meterReadingRecord.setMeterId(config.getId()); + meterReadingRecord.setReadingType(2); + if(config.getTypeId() == 5 || config.getTypeId() == 7 || config.getTypeId() == 3 || config.getTypeId() == 8 || config.getTypeId() == 10){ + Number number = ModbusUtils.readHoldingRegister(master,1,0, DataType.FOUR_BYTE_INT_SIGNED); + f = number.floatValue()*0.0001f; + } + if(config.getTypeId() == 4 ){//开关计数器 + Number number = ModbusUtils.readHoldingRegister(master,1,0, DataType.TWO_BYTE_INT_SIGNED); + f = number.floatValue(); + } + if(config.getTypeId() == 11){//泄漏电流表数字 + Number number = ModbusUtils.readHoldingRegister(master,1,10, DataType.TWO_BYTE_INT_SIGNED); + f = number.floatValue(); + } + master.destroy(); + } + saveMeterReading(config,f); + } catch (Exception e) { + e.printStackTrace(); + log.error(e.getMessage()); + } + } + + + public void saveMeterReading(MeterConfig config,float f) throws Exception { + MeterReadingRecord meterReadingRecord=new MeterReadingRecord(); + meterReadingRecord.setMeterId(config.getId()); + meterReadingRecord.setReadingType(2); + String value = ""; + if(config.getTypeId() == 5 || config.getTypeId() == 7){ + value = ValueFormatUtil.getZZl(f,config); + } + if(config.getTypeId() == 3 ){ + value = ValueFormatUtil.getYwj(f,config); + } + if(config.getTypeId() == 4 || config.getTypeId() == 11){//开关计数器 + value= ValueFormatUtil.getNumBerJx(f,config,meterConfigService); + } + if(config.getTypeId() == 8){//档位数据处理 + //处理为整数 + value = ValueFormatUtil.getDw(f); + } + if(config.getTypeId() == 10){//放电计数器 + value=ValueFormatUtil.getfdjsq(f); + } + if(config.getIsJz()!=null && config.getIsJz() == 1){ + value = config.getJzVal(); + } + meterReadingRecord.setReadingValue(value); + QueryWrapper query=new QueryWrapper<>(); + query.eq("config_id",config.getId()); + FocalLengthConfig fa= focalLengthConfigService.getOne(query); + String fileName = config.getId()+new Date().getTime()+".jpg"; + String url = "http://"+config.getDeviceIp()+":8080/tao/snapshot"; + BufferedImage bufferedImage = UploadUtil.urlByImage(url); + BufferedImage buffer = UploadUtil.drawRectangleAndText(bufferedImage, + fa.getCopperX(),fa.getCopperY(),fa.getCopperX2(),fa.getCopperWid(),fa.getCopperHei(),meterReadingRecord.getReadingValue(),config.getMeterName()); + String url1 = UploadUtil.uploadImage(buffer,config.getId(),fileName); + meterReadingRecord.setMeterTypeName(config.getMeterType()); + meterReadingRecord.setMeterCode(config.getMeterCode()); + meterReadingRecord.setReadingTime(new Date()); + meterReadingRecord.setCreateUser("SYSTEM"); + meterReadingRecord.setCreateTime(new Date()); + meterReadingRecord.setReadingUrl(url1); + meterReadingRecord.setMeterTypeId(config.getTypeId()); + meterReadingRecord.setOwningInterval(config.getOwningInterval()); + meterReadingRecordService.save(meterReadingRecord); + + } + + + + //截取图片并保存为url + public String getAnalysis(FocalLengthConfig focal,BufferedImage pic) throws IOException { + Date date = new Date(); + SimpleDateFormat sfm = new SimpleDateFormat("yyyy-MM-dd"); + if(focal.getRotate()!=null && focal.getRotate()!=0){ + pic= Files.rotateImage(pic,focal.getRotate()); + } + int widthInt = (int) Math.round(focal.getCopperWid()); + int heightInt = (int) Math.round(focal.getCopperHei()); + double copperx = focal.getCopperX(); + double coppery = focal.getCopperY(); + BufferedImage pic2 = pic.getSubimage((int) copperx, (int) coppery, widthInt, heightInt); + //将截取的子图另行存储 + Image _img = pic2.getScaledInstance(widthInt, heightInt, Image.SCALE_DEFAULT); + BufferedImage image = new BufferedImage(widthInt, heightInt, BufferedImage.TYPE_INT_RGB); + Graphics2D graphics = image.createGraphics(); + graphics.drawImage(_img, 0, 0, null); + graphics.dispose(); + return Files.uploadImageForPath(image, StaticPropUtil.imgPath,sfm.format(date)+"\\\\"+date.getTime()+".jpg"); + } + +} diff --git a/device_gather/src/main/resources/application-dev.yml b/device_gather/src/main/resources/application-dev.yml new file mode 100644 index 0000000..5ee98fe --- /dev/null +++ b/device_gather/src/main/resources/application-dev.yml @@ -0,0 +1,80 @@ +server: + port: 8173 + servlet: + context-path: /cars-api + #context-path: / + +spring: + datasource: + dynamic: + primary: db1 + strict: false + datasource: + db1: + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:mysql://116.196.120.81:3306/device_system?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false + username: root + password: 5ea47c0bdd7146ebbd53020eca@672307 + db2: + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:mysql://116.196.120.81:3306/image_analysix_wz?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false + username: root + password: 5ea47c0bdd7146ebbd53020eca@672307 + #Hikari连接池配置 + hikari: + #池中维护的最小空闲连接数 + minimum-idle: 5 + #池中最大连接数,包括闲置和使用中的连接 + maximum-pool-size: 15 + #自动提交从池中返回的连接 + auto-commit: true + #连接允许在池中闲置的最长时间 + idle-timeout: 30000 + #连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置 + pool-name: DatebookHikariCP + #池中连接最长生命周期 + max-lifetime: 18000000 + #等待来自池的连接的最大毫秒数 + connection-timeout: 30000 + #验证该连接是否是有效的查询语句 + connection-test-query: select 1 from dual + cloud: + inetutils: + timeout-seconds: 1000 + config: + enabled: false + # redis 相关 + redis: + host: ${REDIS_URL:localhost} + port: ${REDIS_PORT:6379} + password: ${REDIS_PWD:111111} + timeout: 10000 + jedis: + pool: + max-active: 1000 + max-wait: -1ms + max-idle: 10 + min-idle: 5 +swagger: + show: true +analysis: + url: http://192.168.1.123:9000/vi/syncrec + +upload: + img: + url: http://192.168.1.83:18081/file/img/zs/ + path: D:\\service\\fileService\\img\\zs\\ +python: + path: C:\\Users\\admin\\Anaconda3\\envs\\myconda310\\python.exe + modelPath: D:\\smartGrid\\smartGrid\\models +eureka: + instance: + instance-id: ${spring.cloud.client.ip-address}:${server.port} + prefer-ip-address: true + client: + healthcheck: + enabled: true + service-url: + defaultZone: http://localhost:8084/eureka \ No newline at end of file diff --git a/device_gather/src/main/resources/application-prod.yml b/device_gather/src/main/resources/application-prod.yml new file mode 100644 index 0000000..934e6c4 --- /dev/null +++ b/device_gather/src/main/resources/application-prod.yml @@ -0,0 +1,80 @@ +server: + port: 8173 + servlet: + context-path: /cars-api + #context-path: / + +spring: + datasource: + dynamic: + primary: db1 + strict: false + datasource: + db1: + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:mysql://192.168.1.94:3306/device_system?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false + username: root + password: 123456 + db2: + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:mysql://192.168.1.94:3306/image_analysix_wz?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false + username: root + password: 123456 + #Hikari连接池配置 + hikari: + #池中维护的最小空闲连接数 + minimum-idle: 5 + #池中最大连接数,包括闲置和使用中的连接 + maximum-pool-size: 15 + #自动提交从池中返回的连接 + auto-commit: true + #连接允许在池中闲置的最长时间 + idle-timeout: 30000 + #连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置 + pool-name: DatebookHikariCP + #池中连接最长生命周期 + max-lifetime: 18000000 + #等待来自池的连接的最大毫秒数 + connection-timeout: 30000 + #验证该连接是否是有效的查询语句 + connection-test-query: select 1 from dual + cloud: + inetutils: + timeout-seconds: 1000 + config: + enabled: false + # redis 相关 + redis: + host: ${REDIS_URL:localhost} + port: ${REDIS_PORT:6379} + password: ${REDIS_PWD:111111} + timeout: 10000 + jedis: + pool: + max-active: 1000 + max-wait: -1ms + max-idle: 10 + min-idle: 5 +swagger: + show: true +analysis: + url: http://192.168.1.123:9000/vi/syncrec + +upload: + img: + url: http://192.168.1.94:18081/file/img/zs/ + path: D:\\service\\fileService\\img\\zs\\ +python: + path: C:\\Users\\admin\\Anaconda3\\envs\\myconda310\\python.exe + modelPath: D:\\smartGrid\\smartGrid\\models +eureka: + instance: + instance-id: ${spring.cloud.client.ip-address}:${server.port} + prefer-ip-address: true + client: + healthcheck: + enabled: true + service-url: + defaultZone: http://localhost:8084/eureka \ No newline at end of file diff --git a/device_gather/src/main/resources/application.yml b/device_gather/src/main/resources/application.yml new file mode 100644 index 0000000..ef59b2b --- /dev/null +++ b/device_gather/src/main/resources/application.yml @@ -0,0 +1,82 @@ +spring: + profiles: + #active: dev #开发环境 + # active: test #测试环境5 + active: dev + # active: prod #生产环境 + application: + name: gather + + devtools: + restart: + log-condition-evaluation-delta: false + security: + user: + name: admin + password: admin + servlet: + multipart: + max-file-size: 500MB + max-request-size: 500MB + jackson: + date-format: yyyy-MM-dd + time-zone: GMT+8 + default-property-inclusion: non_null +mybatis-plus: + mapper-locations: classpath:mapper/*Mapper.xml + type-aliases-package: com.xr.device + # 在查询语句的是否,对Map或者是entity进行映射赋值的时候null也进行映射。默认false,不进行映射 + configuration: + map-underscore-to-camel-case: true + call-setters-on-nulls: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + # 设置更新或者修改的时候的策略,不进行校验,否则如果是null则不会进行更新或者插入,当然在@TableField注解进行指定单个字段 + global-config: + db-config: + insert-strategy: ignored + update-strategy: ignored +logging: + level: + root: info + com.xr: debug + org: + springframework: + boot: + autoconfigure: error + +### Ribbon 配置 +ribbon: + # 连接超时 + ConnectTimeout: 100000 + # 响应超时 + ReadTimeout: 100000 +### Feign 配置 +feign: + # 开启断路器(熔断器) + hystrix: + enabled: true +### Hystrix 配置 +hystrix: + # 这样将会自动配置一个 Hystrix 并发策略插件的 hook,这个 hook 会将 SecurityContext 从主线程传输到 Hystrix 的命令。 + # 因为 Hystrix 不允许注册多个 Hystrix 策略,所以可以声明 HystrixConcurrencyStrategy + # 为一个 Spring bean 来实现扩展。Spring Cloud 会在 Spring 的上下文中查找你的实现,并将其包装在自己的插件中。 + shareSecurityContext: true + command: + default: + circuitBreaker: + # 当在配置时间窗口内达到此数量的失败后,进行短路。默认20个 + requestVolumeThreshold: 100 + # 触发短路的时间值,当该值设为5000时,则当触发 circuit break 后的5000毫秒内都会拒绝request + # 也就是5000毫秒后才会关闭circuit。默认5000 + sleepWindowInMilliseconds: 5000 + # 强制打开熔断器,如果打开这个开关,那么拒绝所有request,默认false + forceOpen: false + # 强制关闭熔断器 如果这个开关打开,circuit将一直关闭且忽略,默认false + forceClosed: false + execution: + isolation: + thread: + # 熔断器超时时间,默认:1000/毫秒 + timeoutInMilliseconds: 20000 + + diff --git a/device_gather/src/main/resources/banner.txt b/device_gather/src/main/resources/banner.txt new file mode 100644 index 0000000..1b8480c --- /dev/null +++ b/device_gather/src/main/resources/banner.txt @@ -0,0 +1,23 @@ +================================================================== +// _ooOoo_ // +// o8888888o // +// 88" . "88 // +// (| ^_^ |) // +// O\ = /O // +// ____/`---'\____ // +// .' \\| |// `. // +// / \\||| : |||// \ // +// / _||||| -:- |||||- \ // +// | | \\\ - /// | | // +// | \_| ''\---/'' | | // +// \ .-\__ `-` ___/-. / // +// ___`. .' /--.--\ `. . ___ // +// ."" '< `.___\_<|>_/___.' >'"". // +// | | : `- \`.;`\ _ /`;.`/ - ` : | | // +// \ \ `-. \_ __\ /__ _/ .-` / / // +// ========`-.____`-.___\_____/___.-`____.-'======== // +// `=---=' // +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // +// 佛祖保佑 永不宕机 永无BUG // + \\\\ //// + ============================================================= \ No newline at end of file diff --git a/device_gather/src/main/resources/logback.xml b/device_gather/src/main/resources/logback.xml new file mode 100644 index 0000000..05ba33e --- /dev/null +++ b/device_gather/src/main/resources/logback.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + + + + + ${LOG_HOME}/deviceCar.log.%d{yyyy-MM-dd}.log + + 30 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + 10MB + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/device_gather/src/main/resources/mapper/DeviceCameraMapper.xml b/device_gather/src/main/resources/mapper/DeviceCameraMapper.xml new file mode 100644 index 0000000..7758a04 --- /dev/null +++ b/device_gather/src/main/resources/mapper/DeviceCameraMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id,device_no,device_type, + device_ip,device_port,account, + password,x,y, + z,device_model,position, + brand,remarks,status, + create_user,create_time,update_user, + update_time,transmission_interval,warmup + + diff --git a/device_gather/src/main/resources/mapper/FocalLengthConfigMapper.xml b/device_gather/src/main/resources/mapper/FocalLengthConfigMapper.xml new file mode 100644 index 0000000..57aeaf0 --- /dev/null +++ b/device_gather/src/main/resources/mapper/FocalLengthConfigMapper.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id,config_id,focal_name, + focal_index,copper_wid,copper_hei, + copper_x,copper_x2,copper_y, + copper_y2,config_type,meter_min, + meter_max,rotate,scale, + state_num,parameter,result, + algorithm,create_user,create_time, + update_user,update_time,focal_picture + + diff --git a/device_gather/src/main/resources/mapper/MeterConfigMapper.xml b/device_gather/src/main/resources/mapper/MeterConfigMapper.xml new file mode 100644 index 0000000..dc17080 --- /dev/null +++ b/device_gather/src/main/resources/mapper/MeterConfigMapper.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id,ids5000_id,interval_type, + voltage_class,owning_interval,identification_interval, + device_name,location_y,location_x, + device_type,meter_code,meter_name, + camera_id,warning_max,warning_min, + type_id,status,first_time, + algorithm_type,interval_time,focal_number, + parameter_config,remarks,iec61850mx, + is_jz,jz_val,init_status, + create_user,create_time,update_user, + update_time + + + + diff --git a/device_gather/src/main/resources/mapper/MeterInitializationMapper.xml b/device_gather/src/main/resources/mapper/MeterInitializationMapper.xml new file mode 100644 index 0000000..49af66c --- /dev/null +++ b/device_gather/src/main/resources/mapper/MeterInitializationMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + id,img,img_address, + value,meter_id,serial + + diff --git a/device_gather/src/main/resources/mapper/MeterReadingRecordMapper.xml b/device_gather/src/main/resources/mapper/MeterReadingRecordMapper.xml new file mode 100644 index 0000000..e2a466c --- /dev/null +++ b/device_gather/src/main/resources/mapper/MeterReadingRecordMapper.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + id,meter_id,meter_code, + meter_type_id,meter_type_name,owning_interval, + reading_time,reading_type,data_type, + reading_value,reading_url,create_user, + create_time,update_user,update_time + + diff --git a/device_gather/src/main/resources/mapper/MeterTypeMapper.xml b/device_gather/src/main/resources/mapper/MeterTypeMapper.xml new file mode 100644 index 0000000..71d7eaa --- /dev/null +++ b/device_gather/src/main/resources/mapper/MeterTypeMapper.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + id,meter_type,meter_shape, + type_description,type_identification,remarks, + reading_unit,type_alias,status, + create_user,create_time,update_user, + update_time + +