This commit is contained in:
2026-04-30 15:25:58 +08:00
parent 5afb8233d5
commit 5559ee0673
169 changed files with 1091 additions and 5993 deletions

View File

@@ -1,5 +1,6 @@
package com.maibu.common;
import com.maibu.core.enums.ConnectionCloseReason;
import io.netty.util.AttributeKey;
import lombok.Data;
@@ -8,4 +9,9 @@ public class Constant {
public static final AttributeKey<String> ATT_DEVICE_ID = AttributeKey.valueOf("deviceId");
public static final AttributeKey<ConnectionCloseReason> ATT_CLOSE_REASON = AttributeKey.valueOf("closeReason");
public static final AttributeKey<String> ATT_ORG_ID = AttributeKey.valueOf("orgId");
public static final AttributeKey<String> ATT_SITE_ID = AttributeKey.valueOf("siteId");
}

View File

@@ -3,7 +3,7 @@ package com.maibu.controller;
import com.maibu.common.CommandConstant;
import com.maibu.core.controller.BaseController;
import com.maibu.core.domain.AjaxResult;
import com.maibu.dto.NettyDevice;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.dto.ObstacleData;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.utils.CommandUtils;
@@ -11,7 +11,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;
import org.apache.commons.lang3.StringUtils;
import org.java_websocket.WebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

View File

@@ -1,9 +1,9 @@
package com.maibu.controller;
import com.maibu.core.business.DevicePlan;
import com.maibu.core.controller.BaseController;
import com.maibu.core.domain.AjaxResult;
import com.maibu.core.domain.model.LoginUser;
import com.maibu.domain.DevicePlan;
import com.maibu.dto.DeviceTaskQueryDTO;
import com.maibu.service.DeviceTaskService;
import com.maibu.utils.SecurityUtils;

View File

@@ -1,10 +1,10 @@
package com.maibu.controller;
import com.maibu.core.business.DeviceRunningStatusHistory;
import com.maibu.core.controller.BaseController;
import com.maibu.core.domain.AjaxResult;
import com.maibu.core.page.TableDataInfo;
import com.maibu.domain.DeviceRunningStatusHistory;
import com.maibu.entity.ErrorIdentificationStandard;
import com.maibu.core.business.ErrorIdentificationStandard;
import com.maibu.service.NettyDeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

View File

@@ -1,69 +0,0 @@
package com.maibu.dto;
import com.maibu.enums.ConnectorStatus;
import io.netty.channel.Channel;
import lombok.Data;
import java.util.HashSet;
import java.util.Set;
@Data
public class Connector {
// 获取设备ID
private final String connectorId;
// 设备ID
private ConnectorStatus connectorStatus; // 设备状态(可用、禁言、不可用)
// 获取连接的设备列表
private Set<Connector> connectedConnectors; // 连接的设备列表 主机绑定从机 从机无绑定
private Channel channel;
// 无参构造函数,解决Lombok需要默认构造函数的问题
public Connector() {
this.connectorId = "";
this.connectorStatus = ConnectorStatus.ACTIVE;
this.connectedConnectors = new HashSet<>();
}
// 构造器
public Connector(String connectorId) {
this.connectorId = connectorId;
this.connectorStatus = ConnectorStatus.ACTIVE; // 默认状态为完全可用
this.connectedConnectors = new HashSet<>();
}
//
public void addConnectedDevice(Connector connector) {
connectedConnectors.add(connector);
}
// 移除连接的设备,确保双向移除
public void removeConnectedDevice(Connector connector) {
// 从当前设备的连接列表中移除
connectedConnectors.remove(connector);
}
public boolean isOnline() {
return channel != null && channel.isActive();
}
public boolean canSend() {
return connectorStatus == ConnectorStatus.ACTIVE;
}
public boolean canReceive() {
return connectorStatus != ConnectorStatus.DISABLED;
}
// 打印设备信息
public void printConnectorInfo() {
System.out.println("Device ID: " + connectorId);
System.out.println("Device Status: " + connectorStatus);
System.out.println("Connected Devices: ");
for (Connector connectedDevice : connectedConnectors) {
System.out.println("- " + connectedDevice.getConnectorId());
}
}
}

View File

@@ -1,6 +1,6 @@
package com.maibu.dto;
import com.maibu.enums.RespondCode;
import com.maibu.core.enums.RespondCode;
import lombok.Data;
import java.util.List;

View File

@@ -1,6 +1,6 @@
package com.maibu.dto;
import com.maibu.enums.RespondCode;
import com.maibu.core.enums.RespondCode;
import lombok.Data;
@Data

View File

@@ -1,6 +1,6 @@
package com.maibu.dto;
import com.maibu.enums.CommandRequestType;
import com.maibu.core.enums.CommandRequestType;
import lombok.Data;
@Data

View File

@@ -1,6 +1,6 @@
package com.maibu.dto;
import com.maibu.enums.RespondCode;
import com.maibu.core.enums.RespondCode;
import lombok.Data;
@Data

View File

@@ -1,6 +1,6 @@
package com.maibu.dto;
import com.maibu.enums.DeviceTaskStaus;
import com.maibu.core.enums.DeviceTaskStaus;
import lombok.Data;
import java.time.LocalDateTime;

View File

@@ -1,42 +0,0 @@
package com.maibu.dto;
import com.maibu.domain.DeviceRunStatistics;
import com.maibu.entity.path.LatAndLngEntity;
import com.maibu.enums.ConnectorType;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.LinkedList;
import java.util.Queue;
@EqualsAndHashCode(callSuper = true)
@Data
public class NettyDevice extends Connector {
private ConnectorType deviceType; // 设备角色类型:MASTER、SLAVE、GENERAL
private String currentSlaveId;// 当前对应的下位机 master
private Long currentTaskId; //当前执行的任务;
private Integer onlineStatus; //在线状态 0 离线 1在线
private Queue<LatAndLngEntity> locationQueue = new LinkedList<>();
private DeviceRunStatistics latestStatus;
private Long latestLoginTime;
public NettyDevice(String connectorId) {
super(connectorId);
this.deviceType = ConnectorType.MASTER; // 默认上位机角色
}
public NettyDevice(String connectorId, ConnectorType deviceType) {
super(connectorId);
this.deviceType = deviceType;
}
}

View File

@@ -1,23 +0,0 @@
package com.maibu.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.maibu.enums.CompareEnum;
import lombok.Data;
import org.springframework.data.annotation.Id;
import java.util.List;
@Data
@TableName("error_identification")
public class ErrorIdentificationStandard {
@TableId(type = IdType.AUTO)
private Long id;
private String field;
private String compareValues;
private CompareEnum compareType;
private String errorDescription;
private String errorName;
}

View File

@@ -1,14 +0,0 @@
package com.maibu.entity.path;
import lombok.Data;
@Data
public class LatAndLngEntity {
private double lat;
private double lng;
@Override
public String toString() {
return "{" + lat + "," + lng + '}';
}
}

View File

@@ -1,554 +0,0 @@
package com.maibu.entity.path;
import com.maibu.utils.json.JsonUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MowingPathGenerator {
public static final double M_PI = 3.14159265358979323846;
public static final double Earth_Radius = 6378137.0;
public static final double EPSILON = 1e-6;
public static final double REL_EPSILON = 1e-8;
public static final double ABS_EPSILON = 1e-12;
public static class Point {
public double x, y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
public static class PathPoint {
public double lat, lon;
public PathPoint(double lat, double lon) {
this.lat = lat;
this.lon = lon;
}
}
public static class Polygon {
public Point[] vertices;
public int num_vertices;
public Polygon(Point[] vertices, int num_vertices) {
this.vertices = vertices;
this.num_vertices = num_vertices;
}
}
public static class PolygonWithHoles {
public Polygon outer;
public Polygon[] holes;
public int num_holes;
public PolygonWithHoles(Polygon outer, Polygon[] holes, int num_holes) {
this.outer = outer;
this.holes = holes;
this.num_holes = num_holes;
}
}
public static class ProjectedPoint {
public Point pt;
public double proj;
public ProjectedPoint(Point pt, double proj) {
this.pt = pt;
this.proj = proj;
}
}
public static boolean isEqual(double a, double b) {
double diff = Math.abs(a - b);
double max_ab = Math.max(Math.abs(a), Math.abs(b));
double tolerance = REL_EPSILON * max_ab + ABS_EPSILON;
return diff <= tolerance;
}
public static double cross(Point a, Point b) {
return a.x * b.y - a.y * b.x;
}
public static boolean getLineIntersection(Point p1, Point p2, Point q1, Point q2, Point intersection) {
Point r = new Point(p2.x - p1.x, p2.y - p1.y);
Point s = new Point(q2.x - q1.x, q2.y - q1.y);
double rxs = cross(r, s);
Point qp = new Point(q1.x - p1.x, q1.y - p1.y);
double q_p_cross_r = cross(qp, r);
if (Math.abs(rxs) < EPSILON) {
return false;
}
double t = cross(qp, s) / rxs;
double u = q_p_cross_r / rxs;
if (t >= 0.0 - EPSILON && t <= 1.0 + EPSILON && u >= 0.0 - EPSILON && u <= 1.0 + EPSILON) {
intersection.x = p1.x + t * r.x;
intersection.y = p1.y + t * r.y;
return true;
}
return false;
}
public static boolean isPointOnSegment(Point pt, Point p1, Point p2) {
if (pt.x < Math.min(p1.x, p2.x) - EPSILON || pt.x > Math.max(p1.x, p2.x) + EPSILON) {
return false;
}
if (pt.y < Math.min(p1.y, p2.y) - EPSILON || pt.y > Math.max(p1.y, p2.y) + EPSILON) {
return false;
}
double cross = (p2.x - p1.x) * (pt.y - p1.y) - (p2.y - p1.y) * (pt.x - p1.x);
if (Math.abs(cross) > EPSILON) {
return false;
}
return true;
}
public static void makeScanline(PolygonWithHoles field, Point lineStart, Point lineEnd, Point normal, double min_proj, Point dir) {
double min_x = Double.POSITIVE_INFINITY, max_x = Double.NEGATIVE_INFINITY;
double min_y = Double.POSITIVE_INFINITY, max_y = Double.NEGATIVE_INFINITY;
for (int i = 0; i < field.outer.num_vertices; i++) {
Point p = field.outer.vertices[i];
if (p.x < min_x) min_x = p.x;
if (p.x > max_x) max_x = p.x;
if (p.y < min_y) min_y = p.y;
if (p.y > max_y) max_y = p.y;
}
double dx = max_x - min_x, dy = max_y - min_y;
double len_scan = Math.sqrt(dx * dx + dy * dy) * 1.1;
Point lineOrigin = new Point(normal.x * min_proj, normal.y * min_proj);
lineStart.x = lineOrigin.x - dir.x * len_scan;
lineStart.y = lineOrigin.y - dir.y * len_scan;
lineEnd.x = lineOrigin.x + dir.x * len_scan;
lineEnd.y = lineOrigin.y + dir.y * len_scan;
}
public static void collectHoleIntersections(PolygonWithHoles poly, Point q1, Point q2, List<ProjectedPoint> intersections, Point dir) {
intersections.clear();
for (int h = 0; h < poly.num_holes; h++) {
for (int i = 0; i < poly.holes[h].num_vertices; i++) {
Point p1 = poly.holes[h].vertices[i];
Point p2 = poly.holes[h].vertices[(i + 1) % poly.holes[h].num_vertices];
Point inter = new Point(0, 0);
if (getLineIntersection(p1, p2, q1, q2, inter)) {
double proj = inter.x * dir.x + inter.y * dir.y;
intersections.add(new ProjectedPoint(new Point(inter.x, inter.y), proj));
}
}
}
}
public static void collectOuterIntersections(PolygonWithHoles poly, Point q1, Point q2, List<ProjectedPoint> intersections, Point dir) {
intersections.clear();
for (int i = 0; i < poly.outer.num_vertices; i++) {
Point p1 = poly.outer.vertices[i];
Point p2 = poly.outer.vertices[(i + 1) % poly.outer.num_vertices];
Point inter = new Point(0, 0);
if (getLineIntersection(p1, p2, q1, q2, inter)) {
double proj = inter.x * dir.x + inter.y * dir.y;
intersections.add(new ProjectedPoint(new Point(inter.x, inter.y), proj));
}
}
}
public static void generateMowingPath(PolygonWithHoles field, double width, Point scanStart, Point scanEnd, List<Point> pathPoints) {
pathPoints.clear();
Point dir = new Point(scanEnd.x - scanStart.x, scanEnd.y - scanStart.y);
double len = Math.sqrt(dir.x * dir.x + dir.y * dir.y);
dir.x /= len;
dir.y /= len;
Point normal = new Point(-dir.y, dir.x);
double min_proj = Double.POSITIVE_INFINITY, max_proj = Double.NEGATIVE_INFINITY;
for (int i = 0; i < field.outer.num_vertices; i++) {
Point p = field.outer.vertices[i];
double proj = p.x * normal.x + p.y * normal.y;
if (proj < min_proj) min_proj = proj;
if (proj > max_proj) max_proj = proj;
}
int lines = (int) ((max_proj - min_proj) / width + 1);
int max_outer_points = lines * field.outer.num_vertices * 2;
int max_hole_points = lines * field.num_holes * 10 * 2;
System.out.printf("dir = (%.4f, %.4f)\n", dir.x, dir.y);
System.out.printf("normal = (%.4f, %.4f)\n", normal.x, normal.y);
System.out.printf("Projection range: %.4f ~ %.4f (%.4f)\n", min_proj, max_proj, max_proj - min_proj);
System.out.printf("lines = %d\n", lines);
Point lineStart = new Point(0, 0);
Point lineEnd = new Point(0, 0);
makeScanline(field, lineStart, lineEnd, normal, min_proj, dir);
int direction = 1;
List<List<ProjectedPoint>> outerIntersections = new ArrayList<>();
List<List<ProjectedPoint>> holeIntersections = new ArrayList<>();
List<Integer> numHole = new ArrayList<>();
List<Integer> numOuter = new ArrayList<>();
for (int l = 0; l < lines; l++) {
List<ProjectedPoint> outerInts = new ArrayList<>();
collectOuterIntersections(field, lineStart, lineEnd, outerInts, dir);
List<ProjectedPoint> holeInts = new ArrayList<>();
collectHoleIntersections(field, lineStart, lineEnd, holeInts, dir);
holeInts.sort(Comparator.comparingDouble(p -> p.proj));
if (direction == -1) {
Collections.reverse(holeInts);
}
outerIntersections.add(outerInts);
holeIntersections.add(holeInts);
numHole.add(holeInts.size());
numOuter.add(outerInts.size());
lineStart.x += normal.x * width;
lineStart.y += normal.y * width;
lineEnd.x += normal.x * width;
lineEnd.y += normal.y * width;
direction *= -1;
}
direction = 1;
for (int l = 0; l < lines; l++) {
List<ProjectedPoint> intersections = new ArrayList<>();
intersections.addAll(outerIntersections.get(l));
intersections.addAll(holeIntersections.get(l));
intersections.sort(Comparator.comparingDouble(p -> p.proj));
if (direction == -1) {
Collections.reverse(intersections);
}
boolean isHoleStart = false;
int layerHoleNum = numHole.get(l);
if (layerHoleNum > 0) {
ProjectedPoint holeStart = holeIntersections.get(l).get(0);
ProjectedPoint holeEnd = holeIntersections.get(l).get(layerHoleNum - 1);
for (int i = 0; i < intersections.size(); i++) {
ProjectedPoint testPoint = intersections.get(i);
if (isEqual(testPoint.proj, holeStart.proj)) {
isHoleStart = true;
}
if (isHoleStart) {
pathPoints.add(holeStart.pt);
int holeId = -1;
int startIndex = -1, endIndex = -1;
boolean isHoleVertices = false;
for (int h = 0; h < field.num_holes; h++) {
Polygon hole = field.holes[h];
for (int j = 0; j < hole.num_vertices; j++) {
Point p1 = hole.vertices[j];
Point p2 = hole.vertices[(j + 1) % hole.num_vertices];
if (isEqual(holeStart.pt.x, p1.x) && isEqual(holeStart.pt.y, p1.y)) {
isHoleVertices = true;
break;
}
if (isPointOnSegment(holeStart.pt, p1, p2)) {
holeId = h;
startIndex = (j + 1) % hole.num_vertices;
}
if (isPointOnSegment(holeEnd.pt, p1, p2)) {
endIndex = j;
}
}
}
if (!isHoleVertices) {
if (holeId >= 0 && startIndex >= 0 && endIndex >= 0) {
Polygon hole = field.holes[holeId];
int index = startIndex;
int indexHoleIntersections = 1;
boolean forward = true;
for (int step = 0; step < hole.num_vertices; step++) {
if (indexHoleIntersections < layerHoleNum - 1) {
Point current = hole.vertices[index];
Point next = hole.vertices[(index + 1) % hole.num_vertices];
Point intersectionPt = holeIntersections.get(l).get(indexHoleIntersections).pt;
if (forward && !isPointOnSegment(intersectionPt, current, next)) {
forward = false;
index = (index - 1 + hole.num_vertices) % hole.num_vertices;
endIndex = (endIndex + 1) % hole.num_vertices;
System.out.println("is_point_on_segment");
}
if (indexHoleIntersections % 2 != 0) {
pathPoints.add(hole.vertices[index]);
}
pathPoints.add(holeIntersections.get(l).get(indexHoleIntersections).pt);
indexHoleIntersections++;
i++;
} else {
pathPoints.add(hole.vertices[index]);
}
if (index == endIndex) break;
if (forward) {
index = (index + 1) % hole.num_vertices;
} else {
index = (index - 1 + hole.num_vertices) % hole.num_vertices;
}
}
}
}
pathPoints.add(holeEnd.pt);
i++;
isHoleStart = false;
continue;
}
pathPoints.add(intersections.get(i).pt);
}
} else {
for (ProjectedPoint pp : intersections) {
pathPoints.add(pp.pt);
}
}
direction *= -1;
}
}
public static void latlonToXY(double lat0, double lon0, double lat, double lon, Point result) {
double d_lat = Math.toRadians(lat - lat0);
double d_lon = Math.toRadians(lon - lon0);
double lat0_rad = Math.toRadians(lat0);
result.x = Earth_Radius * d_lon * Math.cos(lat0_rad);
result.y = Earth_Radius * d_lat;
}
public static void xyToLatlon(double lat0, double lon0, double x, double y, PathPoint result) {
double lat0_rad = Math.toRadians(lat0);
result.lat = lat0 + (y / Earth_Radius) * (180.0 / M_PI);
result.lon = lon0 + (x / (Earth_Radius * Math.cos(lat0_rad))) * (180.0 / M_PI);
}
public static void getCoord(PathPoint[] gps, Point[] points, PathPoint start, int cnt) {
for (int i = 0; i < cnt; i++) {
latlonToXY(start.lat, start.lon, gps[i].lat, gps[i].lon, points[i]);
}
}
public static void getLatlon(PathPoint[] gps, Point[] points, PathPoint start, int cnt) {
for (int i = 0; i < cnt; i++) {
xyToLatlon(start.lat, start.lon, points[i].x, points[i].y, gps[i]);
}
}
public static void parseJson(String json) {
RPPathData data = JsonUtils.parseObject(json,RPPathData.class);
PathPoint refPoint = data.refPoint;
PathPoint[] outer = data.Polygon.outer.toArray(new PathPoint[0]);
PathPoint start = data.scanLine.start;
PathPoint end = data.scanLine.end;
PathPoint[] holes = data.Polygon.holes.toArray(new PathPoint[0]);
// 打印验证
System.out.println("Ref Point: " + refPoint);
System.out.println("Start: " + start);
System.out.println("End: " + end);
System.out.println("Outer:");
for (PathPoint p : outer) {
System.out.println(" " + p);
}
System.out.println("Holes:");
for (PathPoint p : holes) {
System.out.println(" " + p);
}
}
public static List<LatAndLngEntity> generateMowingPath(String json) {
RPPathData data = JsonUtils.parseObject(json,RPPathData.class);
PathPoint refPoint = data.refPoint;
PathPoint[] outer = data.Polygon.outer.toArray(new PathPoint[0]);
PathPoint start = data.scanLine.start;
PathPoint end = data.scanLine.end;
List<PathPoint> allHolePoints = new ArrayList<>();
for (List<PathPoint> hole : data.Polygon.holes) {
allHolePoints.addAll(hole);
}
PathPoint[] holes = allHolePoints.toArray(new PathPoint[0]);
Point[] outerPoint = new Point[outer.length];
Point startPoint = new Point(0, 0);
Point endPoint = new Point(0, 0);
Point[] holesPoint = new Point[holes.length];
latlonToXY(refPoint.lat, refPoint.lon, start.lat, start.lon, startPoint);
latlonToXY(refPoint.lat, refPoint.lon, end.lat, end.lon, endPoint);
for (int i = 0; i < outer.length; i++) {
outerPoint[i] = new Point(0, 0);
latlonToXY(refPoint.lat, refPoint.lon, outer[i].lat, outer[i].lon, outerPoint[i]);
System.out.printf("(%.14f, %.14f)\n", outerPoint[i].x, outerPoint[i].y);
// Log.d("MowingPathGenerator", "Outer Point: " + "(" + outerPoint[i].x + ", " + outerPoint[i].y + " )");
}
if (holes.length > 0) {
for (int i = 0; i < holes.length; i++) {
holesPoint[i] = new Point(0, 0);
latlonToXY(refPoint.lat, refPoint.lon, holes[i].lat, holes[i].lon, holesPoint[i]);
// Log.d("MowingPathGenerator", "holes Point: " + "(" + holesPoint[i].x + ", " + holesPoint[i].y + " )");
System.out.printf("(%.14f, %.14f)\n", holesPoint[i].x, holesPoint[i].y);
}
}
Polygon outerPolygon = new Polygon(outerPoint, outer.length);
// Polygon holesPolygon[] = {new Polygon(holesPoint, holesPoint.length)};
// PolygonWithHoles field = new PolygonWithHoles(outerPolygon, holesPolygon,holesPoint.length);
Polygon[] holesPolygons = new Polygon[data.Polygon.holes.size()];
for (int i = 0; i < data.Polygon.holes.size(); i++) {
List<PathPoint> hole = data.Polygon.holes.get(i);
Point[] holePoints = new Point[hole.size()];
for (int j = 0; j < hole.size(); j++) {
holePoints[j] = new Point(0, 0);
latlonToXY(refPoint.lat, refPoint.lon, hole.get(j).lat, hole.get(j).lon, holePoints[j]);
}
holesPolygons[i] = new Polygon(holePoints, holePoints.length);
}
PolygonWithHoles field = new PolygonWithHoles(outerPolygon, holesPolygons, holesPolygons.length);
// PolygonWithHoles field = new PolygonWithHoles(outerPolygon, null,0);
double width = 0.8;
List<Point> path = new ArrayList<>();
generateMowingPath(field, width, startPoint, endPoint, path);
PathPoint[] gpsout = new PathPoint[path.size()];
for (int i = 0; i < gpsout.length; i++) {
gpsout[i] = new PathPoint(0, 0);
}
for (int i = 0; i < path.size(); i++) {
if (i >= gpsout.length) break;
xyToLatlon(start.lat, start.lon, path.get(i).x, path.get(i).y, gpsout[i]);
}
List<LatAndLngEntity> Points = new ArrayList<>();
System.out.printf("Generated %d path points:\n", path.size());
for (int i = 0; i < path.size(); i++) {
if (i >= gpsout.length) break;
System.out.printf("[%.14f, %.14f]\n", gpsout[i].lon, gpsout[i].lat);
// Log.d("MowingPathGenerator", "gpsout Point: " + "(" + gpsout[i].lon + ", " + gpsout[i].lat + " )");
LatAndLngEntity latAndLngEntity = new LatAndLngEntity();
latAndLngEntity.setLat(gpsout[i].lat);
latAndLngEntity.setLng(gpsout[i].lon);
Points.add(latAndLngEntity);
}
return Points;
}
}
// public static void main(String[] args) {
//
// PathPoint start = new PathPoint(32.08599985199932, 120.77586450935124);
// PathPoint[] gpsout = new PathPoint[1024];
// PathPoint[] gpsin = {
// new PathPoint(32.08599985199932, 120.77586450935124),
// new PathPoint(32.08624992154597, 120.77670803771835),
// new PathPoint(32.08568874374706, 120.77710241458807),
// new PathPoint(32.0854398968189, 120.77615838649545)
// };
//
// PathPoint scanStart = new PathPoint(32.08599985199932, 120.77586450935124);
// PathPoint scanEnd = new PathPoint(32.08624992154597, 120.77670803771835);
// Point startPoint = new Point(0,0);
// Point endPoint = new Point(0,0);
//
// latlonToXY(start.lat, start.lon, scanStart.lat, scanStart.lon, startPoint);
// latlonToXY(start.lat, start.lon, scanEnd.lat, scanEnd.lon, endPoint);
//
// Point[] outerVertices = new Point[4];
// for (int i = 0; i < 4; i++) {
// outerVertices[i] = new Point(0, 0);
// latlonToXY(start.lat, start.lon, gpsin[i].lat, gpsin[i].lon, outerVertices[i]);
// System.out.printf("(%.14f, %.14f)\n", outerVertices[i].x, outerVertices[i].y);
// }
//
// Polygon outer = new Polygon(outerVertices, 4);
// Point[] hole1Vertices = {
// new Point(40, -10), new Point(80, -10), new Point(80, -40),
// new Point(60, -28), new Point(40, -40)
// };
// Polygon[] holes = {
// new Polygon(hole1Vertices, 5)
// };
// PolygonWithHoles field = new PolygonWithHoles(outer, holes, 1);
//
// double width = 0.8;
// List<Point> path = new ArrayList<>();
//
// generateMowingPath(field, width, startPoint, endPoint, path);
//
// for (int i = 0; i < gpsout.length; i++) {
// gpsout[i] = new PathPoint(0, 0);
// }
//
// for (int i = 0; i < path.size(); i++) {
// if (i >= gpsout.length) break;
// xyToLatlon(start.lat, start.lon, path.get(i).x, path.get(i).y, gpsout[i]);
// }
//
// System.out.printf("Generated %d path points:\n", path.size());
// for (int i = 0; i < path.size(); i++) {
// if (i >= gpsout.length) break;
// System.out.printf("{%.14f, %.14f}\n", gpsout[i].lon, gpsout[i].lat);
// }
// }
//}

View File

@@ -1,20 +0,0 @@
package com.maibu.entity.path;
import java.util.List;
import com.maibu.entity.path.MowingPathGenerator.*;
public class RPPathData {
public ScanLine scanLine;
public PathPoint refPoint;
public PolygonData Polygon;
public static class ScanLine {
public PathPoint start;
public PathPoint end;
}
public static class PolygonData {
public List<PathPoint> outer;
public List<List<PathPoint>> holes;
}
}

View File

@@ -1,30 +0,0 @@
package com.maibu.entity.path;
import lombok.Data;
@Data
public class RoutePlanRecEntity {
private byte header1;
private byte header2;
private byte commandType;
private short pointNum;
private byte status;
private short crc16;
private byte endFlag1;
private byte endFlag2;
@Override
public String toString() {
return "RoutePlanRecEntity{" +
"header1=" + header1 +
", header2=" + header2 +
", commandType=" + commandType +
", pointNum=" + pointNum +
", status=" + status +
", crc16=" + crc16 +
", endFlag1=" + endFlag1 +
", endFlag2=" + endFlag2 +
'}';
}
}

View File

@@ -1,78 +0,0 @@
package com.maibu.entity.path;
import lombok.Data;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@Data
public class RoutePlanSendEntity {
public RoutePlanSendEntity() {
header1 = (byte) 0xAB;
header2 = (byte) 0xAA;
commandType = 0x01;
pointCounts = 1;
targetLatitude = 0;
targetLongitude = 0;
speed = 0x3E8;
crc16 = 0;
endFlag1 = (byte) 0xAA;
endFlag2 = (byte) 0xAB;
}
@Override
public String toString() {
return "RoutePlanSendEntity{" +
"header1=" + header1 +
", header2=" + header2 +
", commandType=" + commandType +
", pointCounts=" + pointCounts +
", targetLatitude=" + targetLatitude +
", targetLongitude=" + targetLongitude +
", speed=" + speed +
", crc16=" + crc16 +
", endFlag1=" + endFlag1 +
", endFlag2=" + endFlag2 +
'}';
}
public byte[] toBytes() {
ByteBuffer buffer = ByteBuffer.allocate(27); // 修改为27字节
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.put((byte) 0xAB);
buffer.put((byte) 0xAA);
buffer.put((byte) 0x01);
buffer.putShort(pointCounts);
long latitudeBits = Double.doubleToLongBits(targetLatitude);
buffer.putLong(latitudeBits);
long longitudeBits = Double.doubleToLongBits(targetLongitude);
buffer.putLong(longitudeBits);
buffer.putShort(speed);
buffer.putShort(crc16);
buffer.put((byte) 0xAA);
buffer.put((byte) 0xAB);
return buffer.array();
}
private byte header1;
private byte header2;
private byte commandType;
private short pointCounts;
private double targetLatitude; // 改为 double
private double targetLongitude; // 改为 double
private short speed;
private short crc16;
private byte endFlag1;
private byte endFlag2;
}

View File

@@ -1,5 +0,0 @@
package com.maibu.enums;
public enum CommandRequestType {
switch_control
}

View File

@@ -1,94 +0,0 @@
package com.maibu.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
/**
* 比较操作符枚举类
* 用于标准化管理比较类型,如>、<、between等
* 基于项目现有的使用模式实现
*/
@Getter
@AllArgsConstructor
public enum CompareEnum {
/** 等于 */
EQ("=", "等于", "=", true),
/** 不等于 */
NEQ("!=", "不等于", "!=", true),
/** 大于 */
GT(">", "大于", ">", true),
/** 小于 */
LT("<", "小于", "<", true),
/** 大于等于 */
GTE(">=", "大于等于", ">=", true),
/** 小于等于 */
LTE("<=", "小于等于", "<=", true),
/** 在之间 */
BETWEEN("between", "在之间", "between", false),
/** 不在之间 */
NOT_BETWEEN("notBetween", "不在之间", "notBetween", false),
/** 包含 */
CONTAIN("contain", "包含", "contain", true),
/** 不包含 */
NOT_CONTAIN("notContain", "不包含", "notContain", true);
/** 操作符值(存储在数据库中) */
private final String value;
/** 操作符名称(用于前端显示) */
private final String name;
/** 表达式符号(用于计算表达式) */
private final String symbol;
/** 是否为单值比较(true:单值, false:范围值) */
private final boolean singleValue;
/**
* 根据值获取比较操作符枚举
* @param value 操作符值
* @return 比较操作符枚举
*/
public static CompareEnum getByValue(String value) {
if (value == null) {
return null;
}
for (CompareEnum operator : CompareEnum.values()) {
if (operator.getValue().equals(value)) {
return operator;
}
}
return null;
}
/**
* 获取所有比较操作符列表
* @return 比较操作符列表
*/
public static List<CompareEnum> getAll() {
return Arrays.asList(CompareEnum.values());
}
/**
* 判断是否为范围比较操作符
* @param value 操作符值
* @return 是否为范围比较
*/
public static boolean isRangeOperator(String value) {
CompareEnum operator = getByValue(value);
return operator != null && !operator.isSingleValue();
}
}

View File

@@ -1,7 +0,0 @@
package com.maibu.enums;
public enum ConnectionCloseReason {
NROMAL,
TIMEOUT,
REPEAT
}

View File

@@ -1,7 +0,0 @@
package com.maibu.enums;
public enum ConnectorStatus {
ACTIVE, // 完全可用
RECEIVER, // 禁言(不可发送但可以接收)
DISABLED // 完全不可用
}

View File

@@ -1,7 +0,0 @@
package com.maibu.enums;
public enum ConnectorType {
MASTER, // 上位机(主动绑定别人)
SLAVE, // 下位机(只能被动绑定)
GENERAL // 不区分角色(将来扩展用)
}

View File

@@ -1,35 +0,0 @@
package com.maibu.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum DeviceStatus {
online(1, "online", "在线"),
offline(0, "offline", "离线");
private int type;
private String code;
private String description;
public static DeviceStatus convert(int type) {
for (DeviceStatus value : DeviceStatus.values()) {
if (value.type == type) {
return value;
}
}
return null;
}
public static DeviceStatus convert(String code) {
for (DeviceStatus value : DeviceStatus.values()) {
if (value.code.equals(code)) {
return value;
}
}
return null;
}
}

View File

@@ -1,17 +0,0 @@
package com.maibu.enums;
public enum RespondCode {
/**
* 账号已登录
*/
have_logged_in,
/**
* 设备状态改变
*/
device_status_changed,
/**
* 设备错误推送
*/
device_error_push
}

View File

@@ -1,11 +1,11 @@
package com.maibu.init;
import com.maibu.constant.FastBeeConstant;
import com.maibu.domain.DevicePlan;
import com.maibu.enums.DeviceTaskStaus;
import com.maibu.core.business.DevicePlan;
import com.maibu.core.enums.DeviceTaskStaus;
import com.maibu.mapper.DevicePlanMapper;
import com.maibu.mapper.SysUserClientMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
import com.maibu.mybatis.LambdaQueryWrapperX;
import com.maibu.service.DevicePlanTaskMonitorService;
import com.maibu.service.DeviceThreadService;
@@ -92,7 +92,7 @@ public class InitThread implements ApplicationRunner {
query.in(DevicePlan::getTaskStaus, list);
List<DevicePlan> devicePlanList = devicePlanMapper.selectList(query);
if(!CollectionUtils.isEmpty(devicePlanList)){
devicePlanList.forEach(GlobalMemory::addDevicePlan);
devicePlanList.forEach(SiteMemory::addDevicePlan);
}
}
}

View File

@@ -2,10 +2,10 @@ package com.maibu.manager;
import cn.hutool.core.util.ObjectUtil;
import com.maibu.dto.Connector;
import com.maibu.dto.NettyDevice;
import com.maibu.enums.ConnectorStatus;
import com.maibu.enums.ConnectorType;
import com.maibu.core.enums.ConnectorStatus;
import com.maibu.core.enums.ConnectorType;
import com.maibu.core.business.device.Connector;
import com.maibu.core.business.device.NettyDevice;
import io.netty.channel.Channel;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

View File

@@ -1,6 +1,6 @@
package com.maibu.mapper;
import com.maibu.entity.ErrorIdentificationStandard;
import com.maibu.core.business.ErrorIdentificationStandard;
import com.maibu.mybatis.mapper.BaseMapperX;
import org.springframework.stereotype.Repository;

View File

@@ -1,96 +0,0 @@
package com.maibu.memory;
import com.maibu.domain.DevicePlan;
import com.maibu.domain.DevicePlanTask;
import com.maibu.entity.ErrorIdentificationStandard;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Data
public class GlobalMemory {
public List<ErrorIdentificationStandard> standard = null;
//key deviceId
public static ConcurrentHashMap<String, List<DevicePlan>> devicePlanMap = new ConcurrentHashMap<>();
//key deviceId prepare
public static ConcurrentHashMap<String, List<DevicePlanTask>> devicePlanTaskPrepareMap = new ConcurrentHashMap<>();
//key deviceId execute
public static ConcurrentHashMap<String, DevicePlanTask> devicePlanTaskExecuteMap = new ConcurrentHashMap<>();
// 设备当前控制权在哪里key->deviceId value:userName:app/web/pc:token
// public static final ConcurrentHashMap<String, String> controlLockMap = new ConcurrentHashMap<>();
public static void addDevicePlan(DevicePlan devicePlan) {
if (devicePlan != null && !StringUtils.isEmpty(devicePlan.getDeviceId())) {
String deviceId = devicePlan.getDeviceId();
List<DevicePlan> list = devicePlanMap.get(deviceId);
if (CollectionUtils.isEmpty(list)) {
list = new ArrayList<>();
}
boolean exists = list.stream()
.anyMatch(l -> Objects.equals(l.getId(), devicePlan.getId()));
if (!exists) {
list.add(devicePlan);
}
devicePlanMap.put(deviceId, list);
}
}
public static void removeDevicePlan(DevicePlan devicePlan) {
if (devicePlan != null && !StringUtils.isEmpty(devicePlan.getDeviceId())) {
String deviceId = devicePlan.getDeviceId();
List<DevicePlan> list = devicePlanMap.get(deviceId);
if (!CollectionUtils.isEmpty(list)) {
list.removeIf(x -> x.getId().equals(devicePlan.getId()));
}
}
}
public static void addDevicePlanPrepare(DevicePlanTask devicePlanTask) {
if (devicePlanTask != null && !StringUtils.isEmpty(devicePlanTask.getDeviceId())) {
String deviceId = devicePlanTask.getDeviceId();
List<DevicePlanTask> list = devicePlanTaskPrepareMap.get(deviceId);
if (CollectionUtils.isEmpty(list)) {
list = new ArrayList<>();
}
list.add(devicePlanTask);
devicePlanTaskPrepareMap.put(deviceId, list);
}
}
public static void removeDevicePlanPrepare(DevicePlanTask devicePlanTask) {
if (devicePlanTask != null && !StringUtils.isEmpty(devicePlanTask.getDeviceId())) {
String deviceId = devicePlanTask.getDeviceId();
List<DevicePlanTask> list = devicePlanTaskPrepareMap.get(deviceId);
if (!CollectionUtils.isEmpty(list)) {
list.removeIf(x -> x.getId().equals(devicePlanTask.getId()));
}
}
}
public static void addDevicePlanExecute(DevicePlanTask devicePlanTask) {
if (devicePlanTask != null && !StringUtils.isEmpty(devicePlanTask.getDeviceId())) {
String deviceId = devicePlanTask.getDeviceId();
devicePlanTaskExecuteMap.put(deviceId, devicePlanTask);
}
}
public static void removeDevicePlanExecute(String deviceId) {
if (!StringUtils.isEmpty(deviceId)) {
devicePlanTaskExecuteMap.remove(deviceId);
}
}
}

View File

@@ -1,10 +1,11 @@
package com.maibu.netty.handler;
import com.maibu.common.CommandConstant;
import com.maibu.dto.Connector;
import com.maibu.dto.NettyDevice;
import com.maibu.enums.ConnectorType;
import com.maibu.core.enums.ConnectorType;
import com.maibu.core.business.device.Connector;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.memory.GlobalMemory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
@@ -35,6 +36,7 @@ public class CommandForwardHandler extends SimpleChannelInboundHandler<String> {
Channel currentChannel = ctx.channel();
byte[] bytes = Hex.decodeHex(msg.toCharArray());
if (bytes.length > 3 && (bytes[2] == CommandConstant.remoteControl || bytes[2] == CommandConstant.path || bytes[2] == CommandConstant.status)) {
String senderDeviceId = deviceSessionManager.getDeviceIdByChannel(currentChannel);
NettyDevice senderNettyDevice =
senderDeviceId != null ? deviceSessionManager.getDevice(senderDeviceId) : null;

View File

@@ -2,11 +2,11 @@ package com.maibu.netty.handler;
import com.maibu.common.CommandConstant;
import com.maibu.common.NettyCacheKey;
import com.maibu.core.business.DeviceRunStatistics;
import com.maibu.core.business.DeviceRunningStatusHistory;
import com.maibu.core.business.DeviceStatusRecordDTO;
import com.maibu.core.redis.RedisCache;
import com.maibu.domain.DeviceRunStatistics;
import com.maibu.domain.DeviceRunningStatusHistory;
import com.maibu.domain.DeviceStatusRecordDTO;
import com.maibu.dto.NettyDevice;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.manager.DeviceSessionManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;

View File

@@ -1,11 +1,14 @@
package com.maibu.netty.handler;
import com.maibu.common.CommandConstant;
import com.maibu.common.Constant;
import com.maibu.core.business.Device;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.core.domain.entity.SysUser;
import com.maibu.core.domain.entity.UserClient;
import com.maibu.domain.Device;
import com.maibu.core.enums.*;
import com.maibu.core.enums.DeviceStatus;
import com.maibu.dto.*;
import com.maibu.enums.*;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.mapper.DeviceRunStatisticsMapper;
import com.maibu.service.IDeviceService;
@@ -32,9 +35,7 @@ import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
@Component
@@ -43,9 +44,6 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
private static final Logger logger = LoggerFactory.getLogger(DeviceConnectHandler.class);
public static final AttributeKey<String> ATT_DEVICE_ID = AttributeKey.valueOf("deviceId");
public static final AttributeKey<ConnectionCloseReason> ATT_CLOSE_REASON = AttributeKey.valueOf("closeReason");
//记录切换控制权请求来源 key 是请求的masterId,value是控制当前设备的主机
private final ConcurrentHashMap<String, String> controlRequestMap = new ConcurrentHashMap<>();
@@ -80,8 +78,8 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
@Override
public void channelInactive(ChannelHandlerContext ctx) {
Channel channel = ctx.channel();
ConnectionCloseReason reason = channel.attr(ATT_CLOSE_REASON).get();
String deviceId = channel.attr(ATT_DEVICE_ID).get();
ConnectionCloseReason reason = channel.attr(Constant.ATT_CLOSE_REASON).get();
String deviceId = channel.attr(Constant.ATT_DEVICE_ID).get();
if (reason == ConnectionCloseReason.REPEAT) {
logger.warn("重复连接断开: {}", channel.remoteAddress());
@@ -120,7 +118,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
Device device = deviceService.selectDeviceBySerialNumber(deviceId);
if (device != null) {
device.setOnlineStatus(DeviceStatus.offline.getType());
device.setUpdateTime(new Date());
device.setUpdateTime(LocalDateTime.now());
deviceService.updateDeviceBySelf(device);
//todo 更新历史作业消息
}
@@ -253,13 +251,13 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
device.setTenantId(-1L);
device.setFirmwareVersion(BigDecimal.valueOf(1.0));
device.setProductName("割草机产品MC700");
device.setCreateTime(new Date());
device.setUpdateTime(new Date());
device.setCreateTime(LocalDateTime.now());
device.setUpdateTime(LocalDateTime.now());
deviceService.insertDeviceBySelf(device);
} else {
device.setStatus(3);
device.setOnlineStatus(DeviceStatus.online.getType());
device.setUpdateTime(new Date());
device.setUpdateTime(LocalDateTime.now());
deviceService.updateDeviceBySelf(device);
}
NettyDevice slaveDevice = sessionManager.getDevice(data);
@@ -444,12 +442,12 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
}
private void handleSlaveConnect(ChannelHandlerContext ctx, String slaveId) {
ctx.channel().attr(ATT_DEVICE_ID).set(slaveId);
ctx.channel().attr(Constant.ATT_DEVICE_ID).set(slaveId);
sessionManager.registerDevice(slaveId, ctx.channel(), ConnectorType.SLAVE, ConnectorStatus.ACTIVE, null);
}
private void handleMasterConnect(ChannelHandlerContext ctx, String masterId, String slaveId, ConnectorStatus status) {
ctx.channel().attr(ATT_DEVICE_ID).set(masterId);
ctx.channel().attr(Constant.ATT_DEVICE_ID).set(masterId);
sessionManager.registerDevice(masterId, ctx.channel(), ConnectorType.MASTER, status, slaveId);
// sessionManager.bindConnector(masterId, slaveId);
}
@@ -457,7 +455,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
String deviceId = ctx.channel().attr(ATT_DEVICE_ID).get();
String deviceId = ctx.channel().attr(Constant.ATT_DEVICE_ID).get();
logger.error("异常设备 {} 出现错误: {}", deviceId, cause.getMessage(), cause);
ctx.close();
}

View File

@@ -1,11 +1,11 @@
package com.maibu.scheduled;
import com.maibu.common.NettyCacheKey;
import com.maibu.core.business.DevicePlan;
import com.maibu.core.business.DeviceStatusRecordDTO;
import com.maibu.core.redis.RedisCache;
import com.maibu.domain.DevicePlan;
import com.maibu.domain.DeviceStatusRecordDTO;
import com.maibu.mapper.DeviceStatusHistoryMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@@ -57,7 +57,7 @@ public class ScheduledTask {
@Scheduled(cron = "0 0 0 * * ?")
public void refreshDevicePlanTask() {
System.out.println("0点定时刷新状态");
Map<String, List<DevicePlan>> map = GlobalMemory.devicePlanMap;
Map<String, List<DevicePlan>> map = SiteMemory.devicePlanMap;
if (!CollectionUtils.isEmpty(map.keySet())) {
map.values().forEach(x -> {
if (!CollectionUtils.isEmpty(x)) {

View File

@@ -1,18 +1,18 @@
package com.maibu.service;
import com.maibu.domain.DevicePlan;
import com.maibu.domain.DevicePlanTask;
import com.maibu.domain.DeviceTaskPlanRule;
import com.maibu.dto.NettyDevice;
import com.maibu.enums.DeviceTaskPlanRepeatType;
import com.maibu.enums.DeviceTaskStaus;
import com.maibu.core.business.DevicePlan;
import com.maibu.core.business.DevicePlanTask;
import com.maibu.core.business.DeviceTaskPlanRule;
import com.maibu.core.business.WorkRecord;
import com.maibu.core.enums.DeviceTaskPlanRepeatType;
import com.maibu.core.enums.DeviceTaskStaus;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.mapper.DevicePlanMapper;
import com.maibu.mapper.DevicePlanTaskMapper;
import com.maibu.mapper.WorkRecordMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.model.WorkRecord;
import com.maibu.memory.SiteMemory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,7 +34,7 @@ public class DevicePlanTaskMonitorService {
@Autowired
private GlobalMemory globalMemory;
private SiteMemory siteMemory;
@Autowired
private DevicePlanTaskMapper devicePlanTaskMapper;
@@ -57,7 +57,7 @@ public class DevicePlanTaskMonitorService {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(() -> {
try {
Map<String, List<DevicePlan>> planMap = GlobalMemory.devicePlanMap;
Map<String, List<DevicePlan>> planMap = SiteMemory.devicePlanMap;
if (!CollectionUtils.isEmpty(planMap.values())) {
Iterator<String> iterator = planMap.keySet().iterator();
while (iterator.hasNext()) {
@@ -109,7 +109,7 @@ public class DevicePlanTaskMonitorService {
devicePlanTask.setCreateTime(LocalDateTime.now());
devicePlanTask.setTaskType("");//待拓展任务类型
devicePlanTaskMapper.insert(devicePlanTask);
globalMemory.addDevicePlanPrepare(devicePlanTask);
siteMemory.addDevicePlanPrepare(devicePlanTask);
//啥时候重置?每日0点?
devicePlan.setDayTriggerFlag(true);
devicePlan.setUpdateTime(LocalDateTime.now());
@@ -120,7 +120,7 @@ public class DevicePlanTaskMonitorService {
if (endTime != null && endTime.isEqual(today)) {
devicePlan.setFinishTime(LocalDateTime.now());
devicePlan.setTaskStaus(DeviceTaskStaus.FINISH);
GlobalMemory.removeDevicePlan(devicePlan);
SiteMemory.removeDevicePlan(devicePlan);
}
devicePlanMapper.updateById(devicePlan);
}
@@ -143,7 +143,7 @@ public class DevicePlanTaskMonitorService {
devicePlanTask.setCreateTime(LocalDateTime.now());
devicePlanTask.setTaskType("");//待拓展任务类型
devicePlanTaskMapper.insert(devicePlanTask);
globalMemory.addDevicePlanPrepare(devicePlanTask);
siteMemory.addDevicePlanPrepare(devicePlanTask);
//啥时候重置?每日0点?
devicePlan.setDayTriggerFlag(true);
devicePlan.setUpdateTime(LocalDateTime.now());
@@ -153,7 +153,7 @@ public class DevicePlanTaskMonitorService {
if (endTime != null && endTime.isEqual(today)) {
devicePlan.setFinishTime(LocalDateTime.now());
devicePlan.setTaskStaus(DeviceTaskStaus.FINISH);
GlobalMemory.removeDevicePlan(devicePlan);
SiteMemory.removeDevicePlan(devicePlan);
}
devicePlanMapper.updateById(devicePlan);
}
@@ -175,7 +175,7 @@ public class DevicePlanTaskMonitorService {
devicePlanTask.setCreateTime(LocalDateTime.now());
devicePlanTask.setTaskType("");//待拓展任务类型
devicePlanTaskMapper.insert(devicePlanTask);
globalMemory.addDevicePlanPrepare(devicePlanTask);
siteMemory.addDevicePlanPrepare(devicePlanTask);
//啥时候重置?每日0点?
devicePlan.setDayTriggerFlag(true);
devicePlan.setUpdateTime(LocalDateTime.now());
@@ -185,7 +185,7 @@ public class DevicePlanTaskMonitorService {
if (endTime != null && endTime.isEqual(today)) {
devicePlan.setFinishTime(LocalDateTime.now());
devicePlan.setTaskStaus(DeviceTaskStaus.FINISH);
GlobalMemory.removeDevicePlan(devicePlan);
SiteMemory.removeDevicePlan(devicePlan);
}
devicePlanMapper.updateById(devicePlan);
}
@@ -202,7 +202,7 @@ public class DevicePlanTaskMonitorService {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(() -> {
try {
Map<String, List<DevicePlanTask>> planMap = GlobalMemory.devicePlanTaskPrepareMap;
Map<String, List<DevicePlanTask>> planMap = SiteMemory.devicePlanTaskPrepareMap;
if (!CollectionUtils.isEmpty(planMap.keySet())) {
planMap.keySet().forEach(key -> {
NettyDevice device = deviceSessionManager.getDevice(key);
@@ -221,9 +221,9 @@ public class DevicePlanTaskMonitorService {
DevicePlanTask devicePlanTask = list.get(0);
String deviceId = devicePlanTask.getDeviceId();
if (!StringUtils.isEmpty(deviceId) && deviceId.equals(key)) {
GlobalMemory.addDevicePlanExecute(devicePlanTask);
SiteMemory.addDevicePlanExecute(devicePlanTask);
device.setCurrentTaskId(devicePlanTask.getId());
GlobalMemory.removeDevicePlanPrepare(devicePlanTask);
SiteMemory.removeDevicePlanPrepare(devicePlanTask);
}
}
}
@@ -241,7 +241,7 @@ public class DevicePlanTaskMonitorService {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(() -> {
try {
Map<String, DevicePlanTask> planMap = GlobalMemory.devicePlanTaskExecuteMap;
Map<String, DevicePlanTask> planMap = SiteMemory.devicePlanTaskExecuteMap;
if (!CollectionUtils.isEmpty(planMap.keySet())) {
planMap.keySet().forEach(key -> {
NettyDevice device = deviceSessionManager.getDevice(key);

View File

@@ -1,22 +1,18 @@
package com.maibu.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.maibu.core.business.*;
import com.maibu.core.domain.model.LoginUser;
import com.maibu.domain.Device;
import com.maibu.domain.DevicePlan;
import com.maibu.domain.DevicePlanTask;
import com.maibu.domain.DeviceTaskPlanRule;
import com.maibu.core.enums.DeviceTaskStaus;
import com.maibu.dto.DevicePlanStatisticsDTO;
import com.maibu.dto.DevicePlanTaskStatisticsDTO;
import com.maibu.dto.DeviceTaskQueryDTO;
import com.maibu.dto.DeviceWorkStatisticsDTO;
import com.maibu.enums.DeviceTaskStaus;
import com.maibu.mapper.DeviceMapper;
import com.maibu.mapper.DevicePlanMapper;
import com.maibu.mapper.DevicePlanTaskMapper;
import com.maibu.mapper.WorkRecordMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.model.WorkRecord;
import com.maibu.memory.SiteMemory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -55,7 +51,7 @@ public class DeviceTaskService {
devicePlan.setUpdateTime(LocalDateTime.now());
transferDays(devicePlan);
int i = devicePlanMapper.updateById(devicePlan);
GlobalMemory.addDevicePlan(devicePlan);
SiteMemory.addDevicePlan(devicePlan);
return i;
} else {
devicePlan.setTaskStaus(DeviceTaskStaus.NEW);
@@ -63,7 +59,7 @@ public class DeviceTaskService {
devicePlan.setCreateBy(loginUser.getUsername());
transferDays(devicePlan);
int i = devicePlanMapper.insert(devicePlan);
GlobalMemory.addDevicePlan(devicePlan);
SiteMemory.addDevicePlan(devicePlan);
return i;
}
}
@@ -148,7 +144,7 @@ public class DeviceTaskService {
DevicePlan planTask = devicePlanMapper.selectById(id);
if (planTask != null) {
planTask.setDelFlag(1);
GlobalMemory.removeDevicePlan(planTask);
SiteMemory.removeDevicePlan(planTask);
return devicePlanMapper.updateById(planTask);
}
return 0;
@@ -308,8 +304,8 @@ public class DeviceTaskService {
public List<DevicePlanTask> deviceTaskPool(DeviceTaskQueryDTO dto) {
List<DevicePlanTask> list = new ArrayList<>();
GlobalMemory.devicePlanTaskPrepareMap.values().forEach(list::addAll);
list.addAll(GlobalMemory.devicePlanTaskExecuteMap.values());
SiteMemory.devicePlanTaskPrepareMap.values().forEach(list::addAll);
list.addAll(SiteMemory.devicePlanTaskExecuteMap.values());
if (dto != null) {
if (dto.getTaskStaus() != null) {
list = list.stream().filter(x -> x.getTaskStaus().equals(dto.getTaskStaus())).collect(Collectors.toList());

View File

@@ -5,18 +5,18 @@ import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson2.JSON;
import com.maibu.common.CommandConstant;
import com.maibu.common.NettyCacheKey;
import com.maibu.core.business.DeviceRunningStatusHistory;
import com.maibu.core.business.DeviceStatusRecordDTO;
import com.maibu.core.enums.CompareEnum;
import com.maibu.core.enums.RespondCode;
import com.maibu.core.redis.RedisCache;
import com.maibu.domain.DeviceRunningStatusHistory;
import com.maibu.domain.DeviceStatusRecordDTO;
import com.maibu.dto.DeviceErrorPushDTO;
import com.maibu.dto.DeviceErrorPushDetail;
import com.maibu.dto.NettyDevice;
import com.maibu.entity.ErrorIdentificationStandard;
import com.maibu.enums.CompareEnum;
import com.maibu.enums.RespondCode;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.core.business.ErrorIdentificationStandard;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.mapper.ErrorIdentificationStandardMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
import com.maibu.utils.CommandUtils;
import com.maibu.utils.CompareUtils;
import io.netty.buffer.ByteBuf;
@@ -47,7 +47,7 @@ public class DeviceThreadService {
private ResourceLoader resourceLoader;
@Autowired
private GlobalMemory globalMemory;
private SiteMemory siteMemory;
@Autowired
private RedisCache redisCache;
@@ -73,7 +73,7 @@ public class DeviceThreadService {
if (recordDTO != null && !CollectionUtils.isEmpty(recordDTO.getHistories())) {
recordDTO.getHistories().sort(Comparator.comparing(DeviceRunningStatusHistory::getCreateTime).reversed());
DeviceRunningStatusHistory history = recordDTO.getHistories().get(0);
List<DeviceErrorPushDetail> compared = compareErrorStandard(history, globalMemory.standard);
List<DeviceErrorPushDetail> compared = compareErrorStandard(history, siteMemory.standard);
String[] parts = k.split(":");
String deviceId = parts[1];
@@ -95,16 +95,16 @@ public class DeviceThreadService {
}
public void initStandard() throws IOException {
if (globalMemory.standard == null) {
if (siteMemory.standard == null) {
List<ErrorIdentificationStandard> standards = standardMapper.selectList();
if (CollectionUtils.isEmpty(standards)) {
// 读取resource目录下的device-config.json文件
Resource resource = resourceLoader.getResource("classpath:errorStandard.json");
// 使用fastjson2转换为DeviceConfig对象
String jsonContent = IoUtil.readUtf8(resource.getInputStream());
globalMemory.standard = JSON.parseArray(jsonContent, ErrorIdentificationStandard.class);
siteMemory.standard = JSON.parseArray(jsonContent, ErrorIdentificationStandard.class);
} else {
globalMemory.standard = standards;
siteMemory.standard = standards;
}
}
}

View File

@@ -1,8 +1,8 @@
package com.maibu.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.maibu.domain.DeviceRunningStatusHistory;
import com.maibu.entity.ErrorIdentificationStandard;
import com.maibu.core.business.DeviceRunningStatusHistory;
import com.maibu.core.business.ErrorIdentificationStandard;
import com.maibu.mapper.DeviceStatusHistoryMapper;
import com.maibu.mapper.ErrorIdentificationStandardMapper;
import lombok.extern.slf4j.Slf4j;

View File

@@ -1,21 +1,22 @@
package com.maibu.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.maibu.core.business.Device;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.core.domain.AjaxResult;
import com.maibu.core.domain.entity.UserClient;
import com.maibu.core.domain.model.LoginUser;
import com.maibu.domain.Device;
import com.maibu.dto.*;
import com.maibu.enums.ConnectorStatus;
import com.maibu.core.enums.ConnectorStatus;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.mapper.DeviceMapper;
import com.maibu.mapper.SysUserClientMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import com.maibu.dto.*;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Set;
@@ -57,7 +58,7 @@ public class TransferDeviceService {
}
device.setTenantId(user.getUserId());
device.setTenantName(user.getUsername());
device.setUpdateTime(new Date());
device.setUpdateTime(LocalDateTime.now());
device.setDeviceAlias(deviceAlias);
device.setActiveTime(new Date());
iDeviceService.updateDeviceBySelf(device);
@@ -87,7 +88,7 @@ public class TransferDeviceService {
}
device.setTenantId(-1L);
device.setTenantName("");
device.setUpdateTime(new Date());
device.setUpdateTime(LocalDateTime.now());
device.setDeviceAlias("");
// deviceMapper.updateById(device);
iDeviceService.updateDeviceBySelf(device);
@@ -109,7 +110,7 @@ public class TransferDeviceService {
//删除从的连接关系
NettyDevice oldSlaveDevice = sessionManager.getDevice(oldSlave);
if (oldSlaveDevice != null && !CollectionUtils.isEmpty(oldSlaveDevice.getConnectedConnectors())) {
Set<Connector> connectedDevices = oldSlaveDevice.getConnectedConnectors();
Set<com.maibu.core.business.device.Connector> connectedDevices = oldSlaveDevice.getConnectedConnectors();
connectedDevices.removeIf(x -> x.getConnectorId().equals(masterId));
}
}
@@ -143,7 +144,7 @@ public class TransferDeviceService {
return AjaxResult.error("无操作权限");
}
device.setDeviceAlias(bindDTO.getDeviceAlias());
device.setUpdateTime(new Date());
device.setUpdateTime(LocalDateTime.now());
device.setCreateBy(user.getUsername());
iDeviceService.updateDeviceBySelf(device);
return AjaxResult.success(true);

View File

@@ -1,6 +1,6 @@
package com.maibu.utils;
import com.maibu.enums.CompareEnum;
import com.maibu.core.enums.CompareEnum;
import lombok.extern.slf4j.Slf4j;
/**