mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-26 15:21:41 +01:00
[miio] add new map elements (#8637)
* [miio] add new map elements Add newly found mapelements for obstacles Signed-off-by: Marcel Verpaalen marcel@verpaalen.com
This commit is contained in:
parent
bd4528dcf3
commit
9c6c80d41f
@ -33,6 +33,10 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
@ -78,8 +82,8 @@ public class RRMapDraw {
|
|||||||
private static final Color ROOM9 = new Color(0xFc, 0xD4, 0x51);
|
private static final Color ROOM9 = new Color(0xFc, 0xD4, 0x51);
|
||||||
private static final Color ROOM10 = new Color(72, 201, 176);
|
private static final Color ROOM10 = new Color(72, 201, 176);
|
||||||
private static final Color ROOM11 = new Color(84, 153, 199);
|
private static final Color ROOM11 = new Color(84, 153, 199);
|
||||||
private static final Color ROOM12 = new Color(133, 193, 233);
|
private static final Color ROOM12 = new Color(255, 213, 209);
|
||||||
private static final Color ROOM13 = new Color(245, 176, 65);
|
private static final Color ROOM13 = new Color(228, 228, 215);
|
||||||
private static final Color ROOM14 = new Color(82, 190, 128);
|
private static final Color ROOM14 = new Color(82, 190, 128);
|
||||||
private static final Color ROOM15 = new Color(72, 201, 176);
|
private static final Color ROOM15 = new Color(72, 201, 176);
|
||||||
private static final Color ROOM16 = new Color(165, 105, 189);
|
private static final Color ROOM16 = new Color(165, 105, 189);
|
||||||
@ -132,6 +136,7 @@ public class RRMapDraw {
|
|||||||
*/
|
*/
|
||||||
private void drawMap(Graphics2D g2d, float scale) {
|
private void drawMap(Graphics2D g2d, float scale) {
|
||||||
Stroke stroke = new BasicStroke(1.1f * scale);
|
Stroke stroke = new BasicStroke(1.1f * scale);
|
||||||
|
Set<Integer> roomIds = new HashSet<Integer>();
|
||||||
g2d.setStroke(stroke);
|
g2d.setStroke(stroke);
|
||||||
for (int y = 0; y < rmfp.getImgHeight() - 1; y++) {
|
for (int y = 0; y < rmfp.getImgHeight() - 1; y++) {
|
||||||
for (int x = 0; x < rmfp.getImgWidth() + 1; x++) {
|
for (int x = 0; x < rmfp.getImgWidth() + 1; x++) {
|
||||||
@ -160,7 +165,8 @@ public class RRMapDraw {
|
|||||||
g2d.setColor(Color.BLACK);
|
g2d.setColor(Color.BLACK);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
g2d.setColor(ROOM_COLORS[Math.round(mapId / 2)]);
|
g2d.setColor(ROOM_COLORS[mapId % 15]);
|
||||||
|
roomIds.add(mapId);
|
||||||
multicolor = true;
|
multicolor = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -173,6 +179,13 @@ public class RRMapDraw {
|
|||||||
g2d.draw(new Line2D.Float(xPos, yP, xPos, yP));
|
g2d.draw(new Line2D.Float(xPos, yP, xPos, yP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (logger.isDebugEnabled() && roomIds.size() > 0) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Integer r : roomIds) {
|
||||||
|
sb.append(" " + r.toString());
|
||||||
|
}
|
||||||
|
logger.debug("Identified rooms in map:{}", sb.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -275,20 +288,44 @@ public class RRMapDraw {
|
|||||||
g2d.setColor(COLOR_CHARGER_HALO);
|
g2d.setColor(COLOR_CHARGER_HALO);
|
||||||
final float chargerX = toXCoord(rmfp.getChargerX()) * scale;
|
final float chargerX = toXCoord(rmfp.getChargerX()) * scale;
|
||||||
final float chargerY = toYCoord(rmfp.getChargerY()) * scale;
|
final float chargerY = toYCoord(rmfp.getChargerY()) * scale;
|
||||||
drawCircle(g2d, chargerX, chargerY, radius);
|
drawCircle(g2d, chargerX, chargerY, radius, false);
|
||||||
drawCenteredImg(g2d, scale / 8, "charger.png", chargerX, chargerY);
|
drawCenteredImg(g2d, scale / 8, "charger.png", chargerX, chargerY);
|
||||||
radius = 3 * scale;
|
radius = 3 * scale;
|
||||||
g2d.setColor(COLOR_ROBO);
|
g2d.setColor(COLOR_ROBO);
|
||||||
final float roboX = toXCoord(rmfp.getRoboX()) * scale;
|
final float roboX = toXCoord(rmfp.getRoboX()) * scale;
|
||||||
final float roboY = toYCoord(rmfp.getRoboY()) * scale;
|
final float roboY = toYCoord(rmfp.getRoboY()) * scale;
|
||||||
drawCircle(g2d, roboX, roboY, radius);
|
drawCircle(g2d, roboX, roboY, radius, false);
|
||||||
if (scale > 1.5) {
|
if (scale > 1.5) {
|
||||||
drawCenteredImg(g2d, scale / 15, "robo.png", roboX, roboY);
|
drawCenteredImg(g2d, scale / 15, "robo.png", roboX, roboY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawCircle(Graphics2D g2d, float x, float y, float radius) {
|
private void drawObstacles(Graphics2D g2d, float scale) {
|
||||||
g2d.draw(new Ellipse2D.Double(x - radius, y - radius, 2.0 * radius, 2.0 * radius));
|
float radius = 2 * scale;
|
||||||
|
Stroke stroke = new BasicStroke(3 * scale);
|
||||||
|
g2d.setStroke(stroke);
|
||||||
|
g2d.setColor(Color.MAGENTA);
|
||||||
|
|
||||||
|
Map<Integer, ArrayList<int[]>> obstacleMap = rmfp.getObstacles();
|
||||||
|
for (ArrayList<int[]> obstacles : obstacleMap.values()) {
|
||||||
|
obstacles.forEach(obstacle -> {
|
||||||
|
final float obstacleX = toXCoord(obstacle[0]) * scale;
|
||||||
|
final float obstacleY = toYCoord(obstacle[1]) * scale;
|
||||||
|
drawCircle(g2d, obstacleX, obstacleY, radius, true);
|
||||||
|
if (scale > 1.0) {
|
||||||
|
drawCenteredImg(g2d, scale / 3, "obstacle-" + obstacle[2] + ".png", obstacleX, obstacleY + 15);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawCircle(Graphics2D g2d, float x, float y, float radius, boolean fill) {
|
||||||
|
Ellipse2D.Double circle = new Ellipse2D.Double(x - radius, y - radius, 2.0 * radius, 2.0 * radius);
|
||||||
|
if (fill) {
|
||||||
|
g2d.fill(circle);
|
||||||
|
} else {
|
||||||
|
g2d.draw(circle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawCenteredImg(Graphics2D g2d, float scale, String imgFile, float x, float y) {
|
private void drawCenteredImg(Graphics2D g2d, float scale, String imgFile, float x, float y) {
|
||||||
@ -296,10 +333,10 @@ public class RRMapDraw {
|
|||||||
try {
|
try {
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
BufferedImage addImg = ImageIO.read(image);
|
BufferedImage addImg = ImageIO.read(image);
|
||||||
int xpos = Math.round(x - (addImg.getWidth() / 2 * scale));
|
int xpos = Math.round(x + (addImg.getWidth() / 2 * scale));
|
||||||
int ypos = Math.round(y - (addImg.getHeight() / 2 * scale));
|
int ypos = Math.round(y + (addImg.getHeight() / 2 * scale));
|
||||||
AffineTransform at = new AffineTransform();
|
AffineTransform at = new AffineTransform();
|
||||||
at.scale(scale, scale);
|
at.scale(-scale, -scale);
|
||||||
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
|
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
|
||||||
g2d.drawImage(addImg, scaleOp, xpos, ypos);
|
g2d.drawImage(addImg, scaleOp, xpos, ypos);
|
||||||
} else {
|
} else {
|
||||||
@ -410,6 +447,7 @@ public class RRMapDraw {
|
|||||||
drawPath(g2d, scale);
|
drawPath(g2d, scale);
|
||||||
drawRobo(g2d, scale);
|
drawRobo(g2d, scale);
|
||||||
drawGoTo(g2d, scale);
|
drawGoTo(g2d, scale);
|
||||||
|
drawObstacles(g2d, scale);
|
||||||
g2d = bi.createGraphics();
|
g2d = bi.createGraphics();
|
||||||
drawOpenHabRocks(g2d, width, height, scale);
|
drawOpenHabRocks(g2d, width, height, scale);
|
||||||
return bi;
|
return bi;
|
||||||
|
@ -52,6 +52,11 @@ public class RRMapFileParser {
|
|||||||
public static final int BLOCKS = 11;
|
public static final int BLOCKS = 11;
|
||||||
public static final int MFBZS_AREA = 12;
|
public static final int MFBZS_AREA = 12;
|
||||||
public static final int OBSTACLES = 13;
|
public static final int OBSTACLES = 13;
|
||||||
|
public static final int IGNORED_OBSTACLES = 14;
|
||||||
|
public static final int OBSTACLES2 = 15;
|
||||||
|
public static final int IGNORED_OBSTACLES2 = 16;
|
||||||
|
public static final int CARPET_MAP = 17;
|
||||||
|
|
||||||
public static final int DIGEST = 1024;
|
public static final int DIGEST = 1024;
|
||||||
public static final int HEADER = 0x7272;
|
public static final int HEADER = 0x7272;
|
||||||
|
|
||||||
@ -84,8 +89,9 @@ public class RRMapFileParser {
|
|||||||
private Map<Integer, ArrayList<float[]>> areas = new HashMap<>();
|
private Map<Integer, ArrayList<float[]>> areas = new HashMap<>();
|
||||||
private ArrayList<float[]> walls = new ArrayList<>();
|
private ArrayList<float[]> walls = new ArrayList<>();
|
||||||
private ArrayList<float[]> zones = new ArrayList<>();
|
private ArrayList<float[]> zones = new ArrayList<>();
|
||||||
private ArrayList<int[]> obstacles = new ArrayList<>();
|
private Map<Integer, ArrayList<int[]>> obstacles = new HashMap<>();
|
||||||
private byte[] blocks = new byte[0];
|
private byte[] blocks = new byte[0];
|
||||||
|
private int[] carpetMap = {};
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(RRMapFileParser.class);
|
private final Logger logger = LoggerFactory.getLogger(RRMapFileParser.class);
|
||||||
|
|
||||||
@ -192,12 +198,62 @@ public class RRMapFileParser {
|
|||||||
areas.put(Integer.valueOf(blocktype & 0xFF), area);
|
areas.put(Integer.valueOf(blocktype & 0xFF), area);
|
||||||
break;
|
break;
|
||||||
case OBSTACLES:
|
case OBSTACLES:
|
||||||
|
case IGNORED_OBSTACLES:
|
||||||
int obstaclePairs = getUInt16(header, 0x08);
|
int obstaclePairs = getUInt16(header, 0x08);
|
||||||
|
ArrayList<int[]> obstacle = new ArrayList<>();
|
||||||
for (int obstaclePair = 0; obstaclePair < obstaclePairs; obstaclePair++) {
|
for (int obstaclePair = 0; obstaclePair < obstaclePairs; obstaclePair++) {
|
||||||
int x0 = getUInt16(data, obstaclePair * 5 + 0);
|
int x0 = getUInt16(data, obstaclePair * 5 + 0);
|
||||||
int y0 = getUInt16(data, obstaclePair * 5 + 2);
|
int y0 = getUInt16(data, obstaclePair * 5 + 2);
|
||||||
int u = data[obstaclePair * 5 + 0] & 0xFF;
|
int u = data[obstaclePair * 5 + 0] & 0xFF;
|
||||||
obstacles.add(new int[] { x0, y0, u });
|
obstacle.add(new int[] { x0, y0, u });
|
||||||
|
}
|
||||||
|
obstacles.put(Integer.valueOf(blocktype & 0xFF), obstacle);
|
||||||
|
break;
|
||||||
|
case OBSTACLES2:
|
||||||
|
int obstacle2Pairs = getUInt16(header, 0x08);
|
||||||
|
if (obstacle2Pairs == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int obstacleDataLenght = blockDataLength / obstacle2Pairs;
|
||||||
|
logger.trace("block 15 records lenght: {}", obstacleDataLenght);
|
||||||
|
ArrayList<int[]> obstacle2 = new ArrayList<>();
|
||||||
|
for (int obstaclePair = 0; obstaclePair < obstacle2Pairs; obstaclePair++) {
|
||||||
|
int x0 = getUInt16(data, obstaclePair * obstacleDataLenght + 0);
|
||||||
|
int y0 = getUInt16(data, obstaclePair * obstacleDataLenght + 2);
|
||||||
|
int u0 = getUInt16(data, obstaclePair * obstacleDataLenght + 4);
|
||||||
|
int u1 = getUInt16(data, obstaclePair * obstacleDataLenght + 6);
|
||||||
|
int u2 = getUInt32LE(data, obstaclePair * obstacleDataLenght + 8);
|
||||||
|
if (obstacleDataLenght == 28) {
|
||||||
|
if ((data[obstaclePair * obstacleDataLenght + 12] & 0xFF) == 0) {
|
||||||
|
logger.trace("obstacle with photo: No text");
|
||||||
|
} else {
|
||||||
|
byte[] txt = getBytes(data, obstaclePair * obstacleDataLenght + 12, 16);
|
||||||
|
logger.trace("obstacle with photo: {}", new String(txt));
|
||||||
|
}
|
||||||
|
obstacle2.add(new int[] { x0, y0, u0, u1, u2 });
|
||||||
|
} else {
|
||||||
|
int u3 = getUInt32LE(data, obstaclePair * obstacleDataLenght + 12);
|
||||||
|
obstacle2.add(new int[] { x0, y0, u0, u1, u2, u3 });
|
||||||
|
logger.trace("obstacle without photo.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obstacles.put(Integer.valueOf(blocktype & 0xFF), obstacle2);
|
||||||
|
break;
|
||||||
|
case IGNORED_OBSTACLES2:
|
||||||
|
int ignoredObstaclePairs = getUInt16(header, 0x08);
|
||||||
|
ArrayList<int[]> ignoredObstacle = new ArrayList<>();
|
||||||
|
for (int obstaclePair = 0; obstaclePair < ignoredObstaclePairs; obstaclePair++) {
|
||||||
|
int x0 = getUInt16(data, obstaclePair * 6 + 0);
|
||||||
|
int y0 = getUInt16(data, obstaclePair * 6 + 2);
|
||||||
|
int u = getUInt16(data, obstaclePair * 6 + 4);
|
||||||
|
ignoredObstacle.add(new int[] { x0, y0, u });
|
||||||
|
}
|
||||||
|
obstacles.put(Integer.valueOf(blocktype & 0xFF), ignoredObstacle);
|
||||||
|
break;
|
||||||
|
case CARPET_MAP:
|
||||||
|
carpetMap = new int[blockDataLength];
|
||||||
|
for (int carpetNode = 0; carpetNode < blockDataLength; carpetNode++) {
|
||||||
|
carpetMap[carpetNode] = data[carpetNode] & 0xFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BLOCKS:
|
case BLOCKS:
|
||||||
@ -285,7 +341,10 @@ public class RRMapFileParser {
|
|||||||
printAreaDetails(walls, pw);
|
printAreaDetails(walls, pw);
|
||||||
pw.printf("Zones:\t%d\r\n", zones.size());
|
pw.printf("Zones:\t%d\r\n", zones.size());
|
||||||
printAreaDetails(zones, pw);
|
printAreaDetails(zones, pw);
|
||||||
pw.printf("Obstacles:\t%d\r\n", obstacles.size());
|
for (Integer obstacleType : obstacles.keySet()) {
|
||||||
|
pw.printf("Obstacles Type (%d):\t%d\r\n", obstacleType, obstacles.get(obstacleType).size());
|
||||||
|
printObstacleDetails(obstacles.get(obstacleType), pw);
|
||||||
|
}
|
||||||
pw.printf("Blocks:\t%d\r\n", blocks.length);
|
pw.printf("Blocks:\t%d\r\n", blocks.length);
|
||||||
pw.print("Paths:");
|
pw.print("Paths:");
|
||||||
for (Integer p : pathsDetails.keySet()) {
|
for (Integer p : pathsDetails.keySet()) {
|
||||||
@ -301,7 +360,7 @@ public class RRMapFileParser {
|
|||||||
|
|
||||||
private void printAreaDetails(ArrayList<float[]> areas, PrintWriter pw) {
|
private void printAreaDetails(ArrayList<float[]> areas, PrintWriter pw) {
|
||||||
areas.forEach(area -> {
|
areas.forEach(area -> {
|
||||||
pw.printf("\tArea coordinates:");
|
pw.print("\tArea coordinates:");
|
||||||
for (int i = 0; i < area.length; i++) {
|
for (int i = 0; i < area.length; i++) {
|
||||||
pw.printf("\t%.0f", area[i]);
|
pw.printf("\t%.0f", area[i]);
|
||||||
}
|
}
|
||||||
@ -309,6 +368,16 @@ public class RRMapFileParser {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void printObstacleDetails(ArrayList<int[]> obstacle, PrintWriter pw) {
|
||||||
|
obstacle.forEach(area -> {
|
||||||
|
pw.print("\tObstacle coordinates:");
|
||||||
|
for (int i = 0; i < area.length; i++) {
|
||||||
|
pw.printf("\t%d", area[i]);
|
||||||
|
}
|
||||||
|
pw.println();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute SHA-1 hash value for the byte array
|
* Compute SHA-1 hash value for the byte array
|
||||||
*
|
*
|
||||||
@ -416,11 +485,15 @@ public class RRMapFileParser {
|
|||||||
return areas;
|
return areas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<int[]> getObstacles() {
|
public Map<Integer, ArrayList<int[]>> getObstacles() {
|
||||||
return obstacles;
|
return obstacles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBlocks() {
|
public byte[] getBlocks() {
|
||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final int[] getCarpetMap() {
|
||||||
|
return carpetMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user