def parse(raw: bytes, colors, drawables, texts, sizes, image_config, *args, **kwargs) -> MapData: scale = float(image_config[CONF_SCALE]) map_image_size = raw.find(bytes([127, 123])) map_image = raw[16:map_image_size + 1] map_info_raw = raw[map_image_size + 1:] map_info = json.loads(map_info_raw) width = map_info["width"] height = map_info["height"] x_min = map_info["x_min"] y_min = map_info["y_min"] resolution = map_info["resolution"] x_min_calc = x_min / resolution y_min_calc = y_min / resolution map_data = MapData(0, 1000) map_data.rooms = MapDataParserRoidmi.parse_rooms(map_info) image = MapDataParserRoidmi.parse_image(map_image, width, height, x_min_calc, y_min_calc, resolution, colors, image_config, map_data.rooms) map_data.image = image map_data.path = MapDataParserRoidmi.parse_path(map_info) map_data.vacuum_position = MapDataParserRoidmi.parse_vacuum_position(map_info) map_data.charger = MapDataParserRoidmi.parse_charger_position(map_info) map_data.no_go_areas, map_data.no_mopping_areas, map_data.walls = MapDataParserRoidmi.parse_areas(map_info) if not map_data.image.is_empty: MapDataParserRoidmi.draw_elements(colors, drawables, sizes, map_data, image_config) if len(map_data.rooms) > 0 and map_data.vacuum_position is not None: map_data.vacuum_room = MapDataParserRoidmi.get_current_vacuum_room(map_image, map_data, width) if map_data.vacuum_room is not None: map_data.vacuum_room_name = map_data.rooms[map_data.vacuum_room].name ImageHandlerRoidmi.rotate(map_data.image) ImageHandlerRoidmi.draw_texts(map_data.image, texts) return map_data
def extract_attributes(map_data: MapData, attributes_to_return: List[str], country) -> Dict[str, Any]: attributes = {} rooms = [] if map_data.rooms is not None: rooms = dict( filter(lambda x: x[0] is not None, ((x[0], x[1].name) for x in map_data.rooms.items()))) if len(rooms) == 0: rooms = list(map_data.rooms.keys()) for name, value in { ATTRIBUTE_CALIBRATION: map_data.calibration(), ATTRIBUTE_CHARGER: map_data.charger, ATTRIBUTE_CLEANED_ROOMS: map_data.cleaned_rooms, ATTRIBUTE_COUNTRY: country, ATTRIBUTE_GOTO: map_data.goto, ATTRIBUTE_GOTO_PATH: map_data.goto_path, ATTRIBUTE_GOTO_PREDICTED_PATH: map_data.predicted_path, ATTRIBUTE_IGNORED_OBSTACLES: map_data.ignored_obstacles, ATTRIBUTE_IGNORED_OBSTACLES_WITH_PHOTO: map_data.ignored_obstacles_with_photo, ATTRIBUTE_IMAGE: map_data.image, ATTRIBUTE_IS_EMPTY: map_data.image.is_empty, ATTRIBUTE_MAP_NAME: map_data.map_name, ATTRIBUTE_NO_GO_AREAS: map_data.no_go_areas, ATTRIBUTE_NO_MOPPING_AREAS: map_data.no_mopping_areas, ATTRIBUTE_OBSTACLES: map_data.obstacles, ATTRIBUTE_OBSTACLES_WITH_PHOTO: map_data.obstacles_with_photo, ATTRIBUTE_PATH: map_data.path, ATTRIBUTE_ROOM_NUMBERS: rooms, ATTRIBUTE_ROOMS: map_data.rooms, ATTRIBUTE_VACUUM_POSITION: map_data.vacuum_position, ATTRIBUTE_VACUUM_ROOM: map_data.vacuum_room, ATTRIBUTE_VACUUM_ROOM_NAME: map_data.vacuum_room_name, ATTRIBUTE_WALLS: map_data.walls, ATTRIBUTE_ZONES: map_data.zones }.items(): if name in attributes_to_return: attributes[name] = value return attributes
def parse(raw: bytes, colors, drawables, texts, sizes, image_config) -> MapData: map_data = MapData(0, 1) buf = ParsingBuffer('header', raw, 0, len(raw)) feature_flags = buf.get_uint32('feature_flags') map_id = buf.peek_uint32('map_id') _LOGGER.debug('feature_flags: 0x%x, map_id: %d', feature_flags, map_id) if feature_flags & MapDataParserViomi.FEATURE_ROBOT_STATUS != 0: MapDataParserViomi.parse_section(buf, 'robot_status', map_id) buf.skip('unknown1', 0x28) if feature_flags & MapDataParserViomi.FEATURE_IMAGE != 0: MapDataParserViomi.parse_section(buf, 'image', map_id) map_data.image, map_data.rooms, map_data.cleaned_rooms = \ MapDataParserViomi.parse_image(buf, colors, image_config, DRAWABLE_CLEANED_AREA in drawables) if feature_flags & MapDataParserViomi.FEATURE_HISTORY != 0: MapDataParserViomi.parse_section(buf, 'history', map_id) map_data.path = MapDataParserViomi.parse_history(buf) if feature_flags & MapDataParserViomi.FEATURE_CHARGE_STATION != 0: MapDataParserViomi.parse_section(buf, 'charge_station', map_id) map_data.charger = MapDataParserViomi.parse_position(buf, 'pos') foo = buf.get_float32('foo') _LOGGER.debug('pos: %s, foo: %f', map_data.charger, foo) if feature_flags & MapDataParserViomi.FEATURE_RESTRICTED_AREAS != 0: MapDataParserViomi.parse_section(buf, 'restricted_areas', map_id) map_data.walls, map_data.no_go_areas = MapDataParserViomi.parse_restricted_areas( buf) if feature_flags & MapDataParserViomi.FEATURE_CLEANING_AREAS != 0: MapDataParserViomi.parse_section(buf, 'cleaning_areas', map_id) map_data.zones = MapDataParserViomi.parse_cleaning_areas(buf) if feature_flags & MapDataParserViomi.FEATURE_NAVIGATE != 0: MapDataParserViomi.parse_section(buf, 'navigate', map_id) buf.skip('unknown1', 4) map_data.goto = MapDataParserViomi.parse_position(buf, 'pos') foo = buf.get_float32('foo') _LOGGER.debug('pos: %s, foo: %f', map_data.goto, foo) if feature_flags & MapDataParserViomi.FEATURE_REALTIME != 0: MapDataParserViomi.parse_section(buf, 'realtime', map_id) buf.skip('unknown1', 5) map_data.vacuum_position = MapDataParserViomi.parse_position( buf, 'pos') foo = buf.get_float32('foo') _LOGGER.debug('pos: %s, foo: %f', map_data.vacuum_position, foo) if feature_flags & 0x00000800 != 0: MapDataParserViomi.parse_section(buf, 'unknown1', map_id) MapDataParserViomi.parse_unknown_section(buf) if feature_flags & MapDataParserViomi.FEATURE_ROOMS != 0: MapDataParserViomi.parse_section(buf, 'rooms', map_id) MapDataParserViomi.parse_rooms(buf, map_data.rooms) if feature_flags & 0x00002000 != 0: MapDataParserViomi.parse_section(buf, 'unknown2', map_id) MapDataParserViomi.parse_unknown_section(buf) if feature_flags & 0x00004000 != 0: MapDataParserViomi.parse_section(buf, 'room_outlines', map_id) MapDataParserViomi.parse_room_outlines(buf) buf.check_empty() _LOGGER.debug('rooms: %s', [str(room) for number, room in map_data.rooms.items()]) if not map_data.image.is_empty: MapDataParserViomi.draw_elements(colors, drawables, sizes, map_data, image_config) if len(map_data.rooms ) > 0 and map_data.vacuum_position is not None: map_data.vacuum_room = MapDataParserViomi.get_current_vacuum_room( buf, map_data.vacuum_position) if map_data.vacuum_room is not None: map_data.vacuum_room_name = map_data.rooms[ map_data.vacuum_room].name _LOGGER.debug('current vacuum room: %s', map_data.vacuum_room) ImageHandlerViomi.rotate(map_data.image) ImageHandlerViomi.draw_texts(map_data.image, texts) return map_data
def create_empty(colors) -> MapData: map_data = MapData() empty_map = ImageHandler.create_empty_map_image( colors, "Vacuum not supported") map_data.image = ImageData.create_empty(empty_map) return map_data
def parse(raw: bytes, colors, drawables, texts, sizes, image_config, map_data_type: MapDataTypes = MapDataTypes.REGULAR, *args, **kwargs) -> Optional[MapData]: map_data = MapData(0, 1000) header = MapDataParserDreame.parse_header(raw) if header.frame_type != MapDataParserDreame.FrameTypes.I_FRAME: _LOGGER.error("unsupported map frame type") return if len( raw ) >= MapDataParserDreame.HEADER_SIZE + header.image_width * header.image_height: image_raw = raw[MapDataParserDreame. HEADER_SIZE:MapDataParserDreame.HEADER_SIZE + header.image_width * header.image_height] additional_data_raw = raw[MapDataParserDreame.HEADER_SIZE + header.image_width * header.image_height:] additional_data_json = json.loads( additional_data_raw.decode("utf8")) _LOGGER.debug(f'map additional_data: {additional_data_json}') map_data.charger = header.charger_position map_data.vacuum_position = header.vacuum_position map_data.image, map_data.rooms = MapDataParserDreame.parse_image( image_raw, header, colors, image_config, additional_data_json, map_data_type) if additional_data_json.get("rism") and \ additional_data_json.get("ris") and additional_data_json["ris"] == 2: rism_map_data = MapDataParserDreame.decode_map( additional_data_json["rism"], colors, drawables, texts, sizes, image_config, MapDataParserDreame.MapDataTypes.RISM) map_data.no_go_areas = rism_map_data.no_go_areas map_data.no_mopping_areas = rism_map_data.no_mopping_areas map_data.walls = rism_map_data.walls map_data.rooms = rism_map_data.rooms _LOGGER.debug(f"rooms: {map_data.rooms}") if not rism_map_data.image.is_empty: map_data.image = rism_map_data.image if additional_data_json.get("tr"): map_data.path = MapDataParserDreame.parse_path( additional_data_json["tr"]) if additional_data_json.get("vw"): if additional_data_json["vw"].get("rect"): map_data.no_go_areas = MapDataParserDreame.parse_areas( additional_data_json["vw"]["rect"]) if additional_data_json["vw"].get("mop"): map_data.no_mopping_areas = MapDataParserDreame.parse_areas( additional_data_json["vw"]["mop"]) if additional_data_json["vw"].get("line"): map_data.walls = MapDataParserDreame.parse_virtual_walls( additional_data_json["vw"]["line"]) if additional_data_json.get("sa") and isinstance( additional_data_json["sa"], list): active_segment_ids = [ sa[0] for sa in additional_data_json["sa"] ] if not map_data.image.is_empty: if map_data_type == MapDataParserDreame.MapDataTypes.REGULAR: MapDataParserDreame.draw_elements(colors, drawables, sizes, map_data, image_config) ImageHandlerDreame.rotate(map_data.image) return map_data
def create_empty(colors, text) -> MapData: map_data = MapData() empty_map = ImageHandler.create_empty_map_image(colors, text) map_data.image = ImageData.create_empty(empty_map) return map_data