def parse_header(raw: bytes) -> Optional[MapDataHeader]: header = MapDataHeader() if not raw or len(raw) < MapDataParserDreame.HEADER_SIZE: _LOGGER.error("wrong header size for map") return header.map_index = MapDataParserDreame.read_int_16_le(raw) header.frame_type = MapDataParserDreame.read_int_8(raw, 4) header.vacuum_position = Point( MapDataParserDreame.read_int_16_le(raw, 5), MapDataParserDreame.read_int_16_le(raw, 7), MapDataParserDreame.read_int_16_le(raw, 9)) header.charger_position = Point( MapDataParserDreame.read_int_16_le(raw, 11), MapDataParserDreame.read_int_16_le(raw, 13), MapDataParserDreame.read_int_16_le(raw, 15)) header.image_pixel_size = MapDataParserDreame.read_int_16_le(raw, 17) header.image_width = MapDataParserDreame.read_int_16_le(raw, 19) header.image_height = MapDataParserDreame.read_int_16_le(raw, 21) header.image_left = round( MapDataParserDreame.read_int_16_le(raw, 23) / header.image_pixel_size) header.image_top = round( MapDataParserDreame.read_int_16_le(raw, 25) / header.image_pixel_size) _LOGGER.debug(f'decoded map header : {header.__dict__}') return header
def parse_vacuum_position(map_info: dict) -> Point: vacuum_position = None if "robotPos" in map_info and "robotPhi" in map_info: vacuum_position = Point(map_info["robotPos"][0], map_info["robotPos"][1], map_info["robotPhi"]) elif "posX" in map_info and "posY" in map_info and "posPhi" in map_info: vacuum_position = Point(map_info["posX"], map_info["posY"], map_info["posPhi"]) return vacuum_position
def parse_image(map_image: bytes, width: int, height: int, min_x: float, min_y: float, resolution: float, colors: Dict, image_config: Dict, rooms: Dict[int, Room]) -> ImageData: image_top = 0 image_left = 0 room_numbers = list(rooms.keys()) image, rooms_raw = ImageHandlerRoidmi.parse(map_image, width, height, colors, image_config, room_numbers) for number, room in rooms_raw.items(): pf = lambda p: MapDataParserRoidmi.image_to_map(p, resolution, min_x, min_y) p1 = pf(Point(room[0] + image_left, room[1] + image_top)) p2 = pf(Point(room[2] + image_left, room[3] + image_top)) rooms[number].x0 = p1.x rooms[number].y0 = p1.y rooms[number].x1 = p2.x rooms[number].y1 = p2.y return ImageData(width * height, image_top, image_left, height, width, image_config, image, lambda p: MapDataParserRoidmi.map_to_image(p, resolution, min_x, min_y))
def parse_path(map_info: dict) -> Path: path_points = [] if "posArray" in map_info: raw_points = json.loads(map_info["posArray"]) for raw_point in raw_points: point = Point(raw_point[0], raw_point[1]) path_points.append(point) return Path(None, None, None, path_points)
def parse_position(buf: ParsingBuffer, name: str, with_angle: bool = False) -> Optional[Point]: x = buf.get_float32(name + '.x') y = buf.get_float32(name + '.y') if x == MapDataParserViomi.POSITION_UNKNOWN or y == MapDataParserViomi.POSITION_UNKNOWN: return None a = None if with_angle: a = buf.get_float32(name + '.a') * 180 / math.pi return Point(x, y, a)
def parse_path(path_string: str) -> Path: r = re.compile(MapDataParserDreame.PATH_REGEX) matches = [m.groupdict() for m in r.finditer(path_string)] current_path = [] path_points = [] current_position = Point(0, 0) for match in matches: if match["operator"] == MapDataParserDreame.PathOperators.START: current_path = [] path_points.append(current_path) current_position = Point(int(match["x"]), int(match["y"])) elif match[ "operator"] == MapDataParserDreame.PathOperators.RELATIVE_LINE: current_position = Point(current_position.x + int(match["x"]), current_position.y + int(match["y"])) else: _LOGGER.error(f'invalid path operator {match["operator"]}') current_path.append(current_position) return Path(None, None, None, path_points)
def parse_position(map_info: dict, x_label: str, y_label: str, a_label: str) -> Optional[Point]: position = None if x_label not in map_info or y_label not in map_info: return position x = map_info[x_label] y = map_info[y_label] a = None if x_label == y_label: x = x[0] y = y[1] if a_label in map_info: a = map_info[a_label] / 1000 * 180 / math.pi position = Point(x, y, a) return position
def parse_position(buf: ParsingBuffer, name: str) -> Optional[Point]: x = buf.get_float32(name + '.x') y = buf.get_float32(name + '.y') if x == MapDataParserViomi.POSITION_UNKNOWN or y == MapDataParserViomi.POSITION_UNKNOWN: return None return Point(x, y)
def map_to_image(p: Point, image_pixel_size: int) -> Point: return Point(p.x / image_pixel_size, p.y / image_pixel_size)
def image_to_map(p: Point, resolution, min_x, min_y) -> Point: return Point((p.x + min_x) * resolution * 1000, (p.y + min_y) * resolution * 1000)
def map_to_image(p: Point, resolution, min_x, min_y) -> Point: return Point(p.x / 1000 / resolution - min_x, p.y / 1000 / resolution - min_y)
def parse_charger_position(map_info: dict) -> Point: charger_position = None if "chargeHandlePos" in map_info: charger_position = Point(map_info["chargeHandlePos"][0], map_info["chargeHandlePos"][1]) return charger_position
def map_to_image(p: Point) -> Point: return Point(p.x * 20 + 400, p.y * 20 + 400)