Browse Source

市北5个站采集程序

dev-shibei
yj 1 year ago
parent
commit
434a7595e6
  1. 5
      device_gather/pom.xml
  2. 6
      device_gather/src/main/java/com/xr/device/common/configvalue/StaticProperties.java
  3. 435
      device_gather/src/main/java/com/xr/device/common/utils/Files.java
  4. 205
      device_gather/src/main/java/com/xr/device/common/utils/PythonExecutor.java
  5. 151
      device_gather/src/main/java/com/xr/device/common/utils/SpringUtils.java
  6. 6
      device_gather/src/main/java/com/xr/device/common/utils/StaticPropUtil.java
  7. 50
      device_gather/src/main/java/com/xr/device/model/entity/MeterInitialization.java
  8. 86
      device_gather/src/main/java/com/xr/device/model/entity/MeterType.java
  9. 20
      device_gather/src/main/java/com/xr/device/model/mapper/MeterInitializationMapper.java
  10. 20
      device_gather/src/main/java/com/xr/device/model/mapper/MeterTypeMapper.java
  11. 13
      device_gather/src/main/java/com/xr/device/model/service/MeterInitializationService.java
  12. 13
      device_gather/src/main/java/com/xr/device/model/service/MeterTypeService.java
  13. 24
      device_gather/src/main/java/com/xr/device/model/service/impl/MeterInitializationServiceImpl.java
  14. 24
      device_gather/src/main/java/com/xr/device/model/service/impl/MeterTypeServiceImpl.java
  15. 202
      device_gather/src/main/java/com/xr/device/schedule/GetMeterSchedule.java
  16. 20
      device_gather/src/main/resources/mapper/MeterInitializationMapper.xml
  17. 30
      device_gather/src/main/resources/mapper/MeterTypeMapper.xml

5
device_gather/pom.xml

@ -131,6 +131,11 @@
<artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>com.xr</groupId>
<artifactId>onvif-hk</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<build>

6
device_gather/src/main/java/com/xr/device/common/configvalue/StaticProperties.java

@ -14,4 +14,10 @@ public class StaticProperties {
@Value("${upload.img.path}")
private String imgPath;
@Value("${python.path}")
private String pythonPath;
@Value("${python.modelPath}")
private String modelPath;
}

435
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();
}
}
}

205
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<String> 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<MeterInitialization> query = new QueryWrapper<>();
query.eq("meter_id", id);
query.orderByAsc("serial");
List<MeterInitialization> list = meterInitializationService.list(query);
List<String> 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<List<Object>> list1 = new ArrayList<>();
List<Object> list2 = new ArrayList<>();
list2.add(id);
List<String> 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<String> list1 = new ArrayList<>();
path.add(0, id + "");
list1.add(ph);
code = "sr.initialize(" + Arrays.toString(list1.toArray()) + ")\n";
}
if (sfType.equals("5")) {
List<String> 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<String> 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;
}
}

151
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> T getBean(String name) throws BeansException
{
return (T) beanFactory.getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws BeansException
*
*/
public static <T> T getBean(Class<T> 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> 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);
}
}

6
device_gather/src/main/java/com/xr/device/common/utils/StaticPropUtil.java

@ -9,9 +9,15 @@ public class StaticPropUtil {
public static String imgPath;
public static String pythonPath;
public static String modelPath;
public static void initDingDingProp(StaticProperties dingProperties){
imgUrl = dingProperties.getImgUrl();
imgPath = dingProperties.getImgPath();
pythonPath = dingProperties.getPythonPath();
modelPath=dingProperties.getModelPath();
}
}

50
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;
}

86
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;
}

20
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<MeterInitialization> {
}

20
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<MeterType> {
}

13
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<MeterInitialization> {
}

13
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<MeterType> {
}

24
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<MeterInitializationMapper, MeterInitialization>
implements MeterInitializationService{
}

24
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<MeterTypeMapper, MeterType>
implements MeterTypeService{
}

202
device_gather/src/main/java/com/xr/device/schedule/GetMeterSchedule.java

@ -7,21 +7,21 @@ 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.ModbusUtils;
import com.xr.device.common.utils.StringUtils;
import com.xr.device.common.utils.UploadUtil;
import com.xr.device.common.utils.ValueFormatUtil;
import com.xr.device.model.entity.FocalLengthConfig;
import com.xr.device.model.entity.MeterConfig;
import com.xr.device.model.entity.MeterReadingRecord;
import com.xr.device.model.service.FocalLengthConfigService;
import com.xr.device.model.service.MeterConfigService;
import com.xr.device.model.service.MeterReadingRecordService;
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;
@ -31,6 +31,7 @@ import java.util.concurrent.TimeUnit;
@Component
@RequiredArgsConstructor
@Slf4j
public class GetMeterSchedule {
private final MeterConfigService meterConfigService;
@ -39,6 +40,10 @@ public class GetMeterSchedule {
private final MeterReadingRecordService meterReadingRecordService;
private final DeviceCameraService deviceCameraService;
private final MeterTypeService meterTypeService;
@Scheduled(cron = "0 0 0/3 * * ?")
public void getMeterSchedule(){
List<MeterConfig> configs = meterConfigService.getMeterList();
@ -74,66 +79,129 @@ public class GetMeterSchedule {
private void collectDataFromDevice(MeterConfig config) {
// 实现采集逻辑
try {
ModbusMaster master= ModbusUtils.getMaster(config.getDeviceIp(),1502);
master.init();
MeterReadingRecord meterReadingRecord=new MeterReadingRecord();
meterReadingRecord.setMeterId(config.getId());
meterReadingRecord.setReadingType(2);
String value = "";
if(config.getTypeId() == 5 || config.getTypeId() == 7){
Number number = ModbusUtils.readHoldingRegister(master,1,0, DataType.FOUR_BYTE_INT_SIGNED);
float f = number.floatValue()*0.0001f;
value = ValueFormatUtil.getZZl(f,config);
}
if(config.getTypeId() == 3 ){
Number number = ModbusUtils.readHoldingRegister(master,1,0, DataType.FOUR_BYTE_INT_SIGNED);
float f = number.floatValue()*0.0001f;
value = ValueFormatUtil.getYwj(f,config);
}
if(config.getTypeId() == 4 || config.getTypeId() == 11){//开关计数器
Number number = ModbusUtils.readHoldingRegister(master,1,0, DataType.TWO_BYTE_INT_SIGNED);
float f = number.floatValue();
value= ValueFormatUtil.getNumBerJx(f,config,meterConfigService);
}
if(config.getTypeId() == 8){//档位数据处理
//处理为整数
Number number = ModbusUtils.readHoldingRegister(master,1,0, DataType.FOUR_BYTE_INT_SIGNED);
float f = number.floatValue()*0.0001f;
value = ValueFormatUtil.getDw(f);
}
if(config.getTypeId() == 10){//放电计数器
Number number = ModbusUtils.readHoldingRegister(master,1,0, DataType.FOUR_BYTE_INT_SIGNED);
float f = number.floatValue()*0.0001f;
ValueFormatUtil.getfdjsq(f);
}
if(config.getIsJz() == 1){
value = config.getJzVal();
MeterType meterType=meterTypeService.getById(config.getTypeId());
float f = 0;
if(config.getAlgorithmType().equals("3")){
DeviceCamera deviceCamera=deviceCameraService.getById(config.getCameraId());
QueryWrapper<FocalLengthConfig> 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();
}
meterReadingRecord.setReadingValue(value);
QueryWrapper<FocalLengthConfig> 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);
master.destroy();
saveMeterReading(config,f);
} catch (Exception e) {
// 处理设备不在线或通信错误的情况
System.err.println("Error communicating with " + config.getDeviceIp() + ": " + e.getMessage());
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){
}
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() == 1){
value = config.getJzVal();
}
if(config.getIsJz() == 1){
value = config.getJzVal();
}
meterReadingRecord.setReadingValue(value);
QueryWrapper<FocalLengthConfig> 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");
}
}

20
device_gather/src/main/resources/mapper/MeterInitializationMapper.xml

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xr.device.model.mapper.MeterInitializationMapper">
<resultMap id="BaseResultMap" type="com.xr.device.model.entity.MeterInitialization">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="img" column="img" jdbcType="VARCHAR"/>
<result property="imgAddress" column="img_address" jdbcType="VARCHAR"/>
<result property="value" column="value" jdbcType="VARCHAR"/>
<result property="meterId" column="meter_id" jdbcType="INTEGER"/>
<result property="serial" column="serial" jdbcType="INTEGER"/>
</resultMap>
<sql id="Base_Column_List">
id,img,img_address,
value,meter_id,serial
</sql>
</mapper>

30
device_gather/src/main/resources/mapper/MeterTypeMapper.xml

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xr.device.model.mapper.MeterTypeMapper">
<resultMap id="BaseResultMap" type="com.xr.device.model.entity.MeterType">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="meterType" column="meter_type" jdbcType="VARCHAR"/>
<result property="meterShape" column="meter_shape" jdbcType="VARCHAR"/>
<result property="typeDescription" column="type_description" jdbcType="VARCHAR"/>
<result property="typeIdentification" column="type_identification" jdbcType="VARCHAR"/>
<result property="remarks" column="remarks" jdbcType="VARCHAR"/>
<result property="readingUnit" column="reading_unit" jdbcType="VARCHAR"/>
<result property="typeAlias" column="type_alias" jdbcType="VARCHAR"/>
<result property="status" column="status" jdbcType="VARCHAR"/>
<result property="createUser" column="create_user" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateUser" column="update_user" jdbcType="VARCHAR"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,meter_type,meter_shape,
type_description,type_identification,remarks,
reading_unit,type_alias,status,
create_user,create_time,update_user,
update_time
</sql>
</mapper>
Loading…
Cancel
Save