roborock.devices.traits.b01
Traits for B01 devices.
42class Q7PropertiesApi(Trait): 43 """API for interacting with B01 Q7 devices.""" 44 45 clean_summary: CleanSummaryTrait 46 """Trait for clean records / clean summary (Q7 `service.get_record_list`).""" 47 48 map: MapTrait 49 """Trait for map list metadata + raw map payload retrieval.""" 50 51 map_content: MapContentTrait 52 """Trait for fetching parsed current map content.""" 53 54 def __init__( 55 self, 56 rpc_channel: Q7RpcChannel, 57 map_rpc_channel: Q7MapRpcChannel, 58 device: HomeDataDevice, 59 product: HomeDataProduct, 60 ) -> None: 61 """Initialize the Q7 API.""" 62 self._rpc_channel = rpc_channel 63 self._map_rpc_channel = map_rpc_channel 64 self._device = device 65 self._product = product 66 67 if not device.sn or not product.model: 68 raise ValueError("B01 Q7 map content requires device serial number and product model metadata") 69 70 self.clean_summary = CleanSummaryTrait(rpc_channel) 71 self.map = MapTrait(rpc_channel) 72 self.map_content = MapContentTrait( 73 self._map_rpc_channel, 74 self.map, 75 ) 76 self._unsub_map_pushes: Callable[[], None] | None = None 77 78 async def start(self) -> None: 79 """Start listening for unsolicited map pushes from the device.""" 80 if self._unsub_map_pushes is not None: 81 return 82 self._unsub_map_pushes = await self._map_rpc_channel.subscribe_map_pushes(self.map_content.update_from_push) 83 84 async def close(self) -> None: 85 """Stop listening for unsolicited map pushes.""" 86 if self._unsub_map_pushes is not None: 87 self._unsub_map_pushes() 88 self._unsub_map_pushes = None 89 90 async def query_values(self, props: list[RoborockB01Props]) -> B01Props | None: 91 """Query the device for the values of the given Q7 properties.""" 92 result = await self.send( 93 RoborockB01Q7Methods.GET_PROP, 94 {"property": props}, 95 ) 96 if not isinstance(result, dict): 97 raise TypeError(f"Unexpected response type for GET_PROP: {type(result).__name__}: {result!r}") 98 return B01Props.from_dict(result) 99 100 async def set_prop(self, prop: RoborockB01Props, value: Any) -> None: 101 """Set a property on the device.""" 102 await self.send( 103 command=RoborockB01Q7Methods.SET_PROP, 104 params={prop: value}, 105 ) 106 107 async def set_fan_speed(self, fan_speed: SCWindMapping) -> None: 108 """Set the fan speed (wind).""" 109 await self.set_prop(RoborockB01Props.WIND, fan_speed.code) 110 111 async def set_water_level(self, water_level: WaterLevelMapping) -> None: 112 """Set the water level (water).""" 113 await self.set_prop(RoborockB01Props.WATER, water_level.code) 114 115 async def set_mode(self, mode: CleanTypeMapping) -> None: 116 """Set the cleaning mode (vacuum, mop, or vacuum and mop).""" 117 await self.set_prop(RoborockB01Props.MODE, mode.code) 118 119 async def set_clean_path_preference(self, preference: CleanPathPreferenceMapping) -> None: 120 """Set the cleaning path preference (route).""" 121 await self.set_prop(RoborockB01Props.CLEAN_PATH_PREFERENCE, preference.code) 122 123 async def set_repeat_state(self, repeat: CleanRepeatMapping) -> None: 124 """Set the cleaning repeat state (cycles).""" 125 await self.set_prop(RoborockB01Props.REPEAT_STATE, repeat.code) 126 127 async def set_volume(self, volume: int) -> None: 128 """Set the robot voice volume (0-100).""" 129 await self.set_prop(RoborockB01Props.VOLUME, volume) 130 131 async def set_child_lock(self, enabled: bool) -> None: 132 """Enable or disable the child lock.""" 133 await self.set_prop(RoborockB01Props.CHILD_LOCK, int(enabled)) 134 135 async def set_dust_collection(self, enabled: bool) -> None: 136 """Enable or disable automatic dust collection at the dock.""" 137 await self.set_prop(RoborockB01Props.DUST_AUTO_STATE, int(enabled)) 138 139 async def set_dust_collection_frequency(self, frequency: int) -> None: 140 """Set how often the dock auto-empties, in cleans per emptying (1 = every clean).""" 141 if frequency < 1: 142 raise ValueError(f"frequency must be a positive number of cleans, got {frequency}") 143 await self.set_prop(RoborockB01Props.DUST_FREQUENCY, frequency) 144 145 async def set_do_not_disturb(self, enabled: bool, begin_time: int, end_time: int) -> None: 146 """Configure do-not-disturb. 147 148 The device expects all three values together via ``service.set_quiet_time`` 149 (individual ``prop.set`` calls are ignored). ``begin_time``/``end_time`` are 150 minutes since midnight and must be in the range 0-1439 (inclusive). 151 152 Ranges that cross midnight are supported by passing a ``begin_time`` that is 153 greater than ``end_time`` (e.g. 22:00-07:00 is ``begin_time=1320``, 154 ``end_time=420``). 155 """ 156 for name, value in (("begin_time", begin_time), ("end_time", end_time)): 157 if not 0 <= value <= 1439: 158 raise ValueError(f"{name} must be between 0 and 1439 minutes since midnight, got {value}") 159 await self.send( 160 RoborockB01Q7Methods.SET_QUIET_TIME, 161 { 162 "is_open": int(enabled), 163 "quiet_begin_time": begin_time, 164 "quiet_end_time": end_time, 165 }, 166 ) 167 168 async def set_button_lights(self, enabled: bool) -> None: 169 """Enable or disable the button/panel lights.""" 170 await self.set_prop(RoborockB01Props.LIGHT_MODE, int(enabled)) 171 172 async def start_clean(self) -> None: 173 """Start cleaning.""" 174 await self.send( 175 command=RoborockB01Q7Methods.SET_ROOM_CLEAN, 176 params={ 177 "clean_type": CleanTaskTypeMapping.ALL.code, 178 "ctrl_value": SCDeviceCleanParam.START.code, 179 "room_ids": [], 180 }, 181 ) 182 183 async def clean_segments(self, segment_ids: list[int]) -> None: 184 """Start segment cleaning for the given ids (Q7 uses room ids).""" 185 await self.send( 186 command=RoborockB01Q7Methods.SET_ROOM_CLEAN, 187 params={ 188 "clean_type": CleanTaskTypeMapping.ROOM.code, 189 "ctrl_value": SCDeviceCleanParam.START.code, 190 "room_ids": segment_ids, 191 }, 192 ) 193 194 async def pause_clean(self) -> None: 195 """Pause cleaning.""" 196 await self.send( 197 command=RoborockB01Q7Methods.SET_ROOM_CLEAN, 198 params={ 199 "clean_type": CleanTaskTypeMapping.ALL.code, 200 "ctrl_value": SCDeviceCleanParam.PAUSE.code, 201 "room_ids": [], 202 }, 203 ) 204 205 async def stop_clean(self) -> None: 206 """Stop cleaning.""" 207 await self.send( 208 command=RoborockB01Q7Methods.SET_ROOM_CLEAN, 209 params={ 210 "clean_type": CleanTaskTypeMapping.ALL.code, 211 "ctrl_value": SCDeviceCleanParam.STOP.code, 212 "room_ids": [], 213 }, 214 ) 215 216 async def return_to_dock(self) -> None: 217 """Return to dock.""" 218 await self.send( 219 command=RoborockB01Q7Methods.START_RECHARGE, 220 params={}, 221 ) 222 223 async def find_me(self) -> None: 224 """Locate the robot.""" 225 await self.send( 226 command=RoborockB01Q7Methods.FIND_DEVICE, 227 params={}, 228 ) 229 230 async def send(self, command: CommandType, params: ParamsType) -> Any: 231 """Send a command to the device.""" 232 return await self._rpc_channel.send_command(command, params)
API for interacting with B01 Q7 devices.
54 def __init__( 55 self, 56 rpc_channel: Q7RpcChannel, 57 map_rpc_channel: Q7MapRpcChannel, 58 device: HomeDataDevice, 59 product: HomeDataProduct, 60 ) -> None: 61 """Initialize the Q7 API.""" 62 self._rpc_channel = rpc_channel 63 self._map_rpc_channel = map_rpc_channel 64 self._device = device 65 self._product = product 66 67 if not device.sn or not product.model: 68 raise ValueError("B01 Q7 map content requires device serial number and product model metadata") 69 70 self.clean_summary = CleanSummaryTrait(rpc_channel) 71 self.map = MapTrait(rpc_channel) 72 self.map_content = MapContentTrait( 73 self._map_rpc_channel, 74 self.map, 75 ) 76 self._unsub_map_pushes: Callable[[], None] | None = None
Initialize the Q7 API.
Trait for clean records / clean summary (Q7 service.get_record_list).
Trait for fetching parsed current map content.
78 async def start(self) -> None: 79 """Start listening for unsolicited map pushes from the device.""" 80 if self._unsub_map_pushes is not None: 81 return 82 self._unsub_map_pushes = await self._map_rpc_channel.subscribe_map_pushes(self.map_content.update_from_push)
Start listening for unsolicited map pushes from the device.
84 async def close(self) -> None: 85 """Stop listening for unsolicited map pushes.""" 86 if self._unsub_map_pushes is not None: 87 self._unsub_map_pushes() 88 self._unsub_map_pushes = None
Stop listening for unsolicited map pushes.
90 async def query_values(self, props: list[RoborockB01Props]) -> B01Props | None: 91 """Query the device for the values of the given Q7 properties.""" 92 result = await self.send( 93 RoborockB01Q7Methods.GET_PROP, 94 {"property": props}, 95 ) 96 if not isinstance(result, dict): 97 raise TypeError(f"Unexpected response type for GET_PROP: {type(result).__name__}: {result!r}") 98 return B01Props.from_dict(result)
Query the device for the values of the given Q7 properties.
100 async def set_prop(self, prop: RoborockB01Props, value: Any) -> None: 101 """Set a property on the device.""" 102 await self.send( 103 command=RoborockB01Q7Methods.SET_PROP, 104 params={prop: value}, 105 )
Set a property on the device.
107 async def set_fan_speed(self, fan_speed: SCWindMapping) -> None: 108 """Set the fan speed (wind).""" 109 await self.set_prop(RoborockB01Props.WIND, fan_speed.code)
Set the fan speed (wind).
111 async def set_water_level(self, water_level: WaterLevelMapping) -> None: 112 """Set the water level (water).""" 113 await self.set_prop(RoborockB01Props.WATER, water_level.code)
Set the water level (water).
115 async def set_mode(self, mode: CleanTypeMapping) -> None: 116 """Set the cleaning mode (vacuum, mop, or vacuum and mop).""" 117 await self.set_prop(RoborockB01Props.MODE, mode.code)
Set the cleaning mode (vacuum, mop, or vacuum and mop).
119 async def set_clean_path_preference(self, preference: CleanPathPreferenceMapping) -> None: 120 """Set the cleaning path preference (route).""" 121 await self.set_prop(RoborockB01Props.CLEAN_PATH_PREFERENCE, preference.code)
Set the cleaning path preference (route).
123 async def set_repeat_state(self, repeat: CleanRepeatMapping) -> None: 124 """Set the cleaning repeat state (cycles).""" 125 await self.set_prop(RoborockB01Props.REPEAT_STATE, repeat.code)
Set the cleaning repeat state (cycles).
127 async def set_volume(self, volume: int) -> None: 128 """Set the robot voice volume (0-100).""" 129 await self.set_prop(RoborockB01Props.VOLUME, volume)
Set the robot voice volume (0-100).
131 async def set_child_lock(self, enabled: bool) -> None: 132 """Enable or disable the child lock.""" 133 await self.set_prop(RoborockB01Props.CHILD_LOCK, int(enabled))
Enable or disable the child lock.
135 async def set_dust_collection(self, enabled: bool) -> None: 136 """Enable or disable automatic dust collection at the dock.""" 137 await self.set_prop(RoborockB01Props.DUST_AUTO_STATE, int(enabled))
Enable or disable automatic dust collection at the dock.
139 async def set_dust_collection_frequency(self, frequency: int) -> None: 140 """Set how often the dock auto-empties, in cleans per emptying (1 = every clean).""" 141 if frequency < 1: 142 raise ValueError(f"frequency must be a positive number of cleans, got {frequency}") 143 await self.set_prop(RoborockB01Props.DUST_FREQUENCY, frequency)
Set how often the dock auto-empties, in cleans per emptying (1 = every clean).
145 async def set_do_not_disturb(self, enabled: bool, begin_time: int, end_time: int) -> None: 146 """Configure do-not-disturb. 147 148 The device expects all three values together via ``service.set_quiet_time`` 149 (individual ``prop.set`` calls are ignored). ``begin_time``/``end_time`` are 150 minutes since midnight and must be in the range 0-1439 (inclusive). 151 152 Ranges that cross midnight are supported by passing a ``begin_time`` that is 153 greater than ``end_time`` (e.g. 22:00-07:00 is ``begin_time=1320``, 154 ``end_time=420``). 155 """ 156 for name, value in (("begin_time", begin_time), ("end_time", end_time)): 157 if not 0 <= value <= 1439: 158 raise ValueError(f"{name} must be between 0 and 1439 minutes since midnight, got {value}") 159 await self.send( 160 RoborockB01Q7Methods.SET_QUIET_TIME, 161 { 162 "is_open": int(enabled), 163 "quiet_begin_time": begin_time, 164 "quiet_end_time": end_time, 165 }, 166 )
Configure do-not-disturb.
The device expects all three values together via service.set_quiet_time
(individual prop.set calls are ignored). begin_time/end_time are
minutes since midnight and must be in the range 0-1439 (inclusive).
Ranges that cross midnight are supported by passing a begin_time that is
greater than end_time (e.g. 22:00-07:00 is begin_time=1320,
end_time=420).
172 async def start_clean(self) -> None: 173 """Start cleaning.""" 174 await self.send( 175 command=RoborockB01Q7Methods.SET_ROOM_CLEAN, 176 params={ 177 "clean_type": CleanTaskTypeMapping.ALL.code, 178 "ctrl_value": SCDeviceCleanParam.START.code, 179 "room_ids": [], 180 }, 181 )
Start cleaning.
183 async def clean_segments(self, segment_ids: list[int]) -> None: 184 """Start segment cleaning for the given ids (Q7 uses room ids).""" 185 await self.send( 186 command=RoborockB01Q7Methods.SET_ROOM_CLEAN, 187 params={ 188 "clean_type": CleanTaskTypeMapping.ROOM.code, 189 "ctrl_value": SCDeviceCleanParam.START.code, 190 "room_ids": segment_ids, 191 }, 192 )
Start segment cleaning for the given ids (Q7 uses room ids).
194 async def pause_clean(self) -> None: 195 """Pause cleaning.""" 196 await self.send( 197 command=RoborockB01Q7Methods.SET_ROOM_CLEAN, 198 params={ 199 "clean_type": CleanTaskTypeMapping.ALL.code, 200 "ctrl_value": SCDeviceCleanParam.PAUSE.code, 201 "room_ids": [], 202 }, 203 )
Pause cleaning.
205 async def stop_clean(self) -> None: 206 """Stop cleaning.""" 207 await self.send( 208 command=RoborockB01Q7Methods.SET_ROOM_CLEAN, 209 params={ 210 "clean_type": CleanTaskTypeMapping.ALL.code, 211 "ctrl_value": SCDeviceCleanParam.STOP.code, 212 "room_ids": [], 213 }, 214 )
Stop cleaning.
216 async def return_to_dock(self) -> None: 217 """Return to dock.""" 218 await self.send( 219 command=RoborockB01Q7Methods.START_RECHARGE, 220 params={}, 221 )
Return to dock.
223 async def find_me(self) -> None: 224 """Locate the robot.""" 225 await self.send( 226 command=RoborockB01Q7Methods.FIND_DEVICE, 227 params={}, 228 )
Locate the robot.
230 async def send(self, command: CommandType, params: ParamsType) -> Any: 231 """Send a command to the device.""" 232 return await self._rpc_channel.send_command(command, params)
Send a command to the device.
54class Q10PropertiesApi(Trait): 55 """API for interacting with B01 devices.""" 56 57 command: CommandTrait 58 """Trait for sending commands to Q10 devices.""" 59 60 status: StatusTrait 61 """Trait for managing the core status of Q10 devices.""" 62 63 vacuum: VacuumTrait 64 """Trait for sending vacuum related commands to Q10 devices.""" 65 66 remote: RemoteTrait 67 """Trait for sending remote control related commands to Q10 devices.""" 68 69 volume: SoundVolumeTrait 70 """Trait for reading / setting the speaker volume.""" 71 72 child_lock: ChildLockTrait 73 """Trait for reading / controlling the child lock.""" 74 75 do_not_disturb: DoNotDisturbTrait 76 """Trait for reading / controlling Do Not Disturb.""" 77 78 dust_collection: DustCollectionTrait 79 """Trait for reading / controlling dock auto-empty (dust collection).""" 80 81 button_light: ButtonLightTrait 82 """Trait for controlling the indicator / button light (LED).""" 83 84 network_info: NetworkInfoTrait 85 """Trait exposing the device's network information.""" 86 87 consumable: ConsumableTrait 88 """Trait exposing remaining life of consumables.""" 89 90 map: MapContentTrait 91 """Composed map image plus caller-facing map and trace data.""" 92 93 maps: MapsTrait 94 """Saved-map list metadata.""" 95 96 _map_dps: MapDpsTrait 97 """Private source of restricted zones and virtual walls received through DPS.""" 98 99 clean_history: CleanHistoryTrait 100 """Trait for fetching the device clean-record history (``dpCleanRecord``).""" 101 102 def __init__( 103 self, 104 channel: B01Q10Channel, 105 *, 106 map_parser_config: B01Q10MapParserConfig | None = None, 107 ) -> None: 108 """Initialize the B01Props API.""" 109 self._channel = channel 110 self.command = CommandTrait(channel) 111 self.remote = RemoteTrait(self.command) 112 self.status = StatusTrait() 113 self.volume = SoundVolumeTrait(self.command) 114 self.child_lock = ChildLockTrait(self.command) 115 self.do_not_disturb = DoNotDisturbTrait(self.command) 116 self.dust_collection = DustCollectionTrait(self.command) 117 self.button_light = ButtonLightTrait(self.command) 118 self.network_info = NetworkInfoTrait() 119 self.consumable = ConsumableTrait() 120 self._map_dps = MapDpsTrait() 121 self.maps = MapsTrait(self.command) 122 self.map = MapContentTrait( 123 self._map_dps, 124 self.command, 125 map_parser_config=map_parser_config, 126 ) 127 self.clean_history = CleanHistoryTrait(self.command) 128 self.vacuum = VacuumTrait(self.command, self.status, self.map) 129 # Read-model traits updated from the device's DPS push stream. 130 self._updatable_traits = [ 131 self.status, 132 self.volume, 133 self.child_lock, 134 self.do_not_disturb, 135 self.dust_collection, 136 self.network_info, 137 self.consumable, 138 self.clean_history, 139 self._map_dps, 140 self.maps, 141 ] 142 self._subscribe_task: asyncio.Task[None] | None = None 143 144 async def start(self) -> None: 145 """Start any necessary subscriptions for the trait.""" 146 self._subscribe_task = asyncio.create_task(self._subscribe_loop()) 147 148 async def close(self) -> None: 149 """Close any resources held by the trait.""" 150 await self.vacuum.close() 151 if self._subscribe_task is not None: 152 self._subscribe_task.cancel() 153 try: 154 await self._subscribe_task 155 except asyncio.CancelledError: 156 pass # ignore cancellation errors 157 self._subscribe_task = None 158 159 async def refresh(self) -> None: 160 """Refresh all traits.""" 161 # Sending REQUEST_DPS causes the device to publish its ordinary status 162 # values. Map-list and map-content refreshes have separate schedules. 163 await self.command.send(B01_Q10_DP.REQUEST_DPS, params={}) 164 165 async def _subscribe_loop(self) -> None: 166 """Persistent loop dispatching decoded messages to the read-model traits.""" 167 async for message in self._channel.subscribe_stream(): 168 self._handle_message(message) 169 170 def _handle_message(self, message: Q10Message) -> None: 171 """Route a single decoded message to the trait responsible for it. 172 173 Map and trace packets arrive as protocol-301 ``MAP_RESPONSE`` pushes. 174 Map-list DPS responses and other DPS updates feed the read-model traits. 175 """ 176 if isinstance(message, Q10MapPacket): 177 if message.kind is Q10MapPacketKind.CURRENT: 178 self.map.update_from_map_packet(message) 179 elif message.kind is Q10MapPacketKind.SAVED_MAP_DETAIL: 180 self.maps.update_from_map_packet(message) 181 elif isinstance(message, Q10CleanRecordDetail): 182 self.clean_history.update_from_detail(message) 183 elif isinstance(message, Q10TracePacket): 184 self.map.update_from_trace_packet(message) 185 elif isinstance(message, Q10DpsUpdate): 186 _LOGGER.debug("Received Q10 status update: %s", message.dps) 187 # Notify all read-model traits about the new message; each trait 188 # only updates the fields that it is responsible for. 189 for trait in self._updatable_traits: 190 trait.update_from_dps(message.dps) 191 192 def as_dict(self) -> dict[str, Any]: 193 """Return the trait data as a dictionary.""" 194 result: dict[str, Any] = {} 195 for name, value in self.__dict__.items(): 196 if isinstance(value, RoborockBase) and not name.startswith("_"): 197 result[name] = value.as_dict() 198 if hasattr(self, "map") and hasattr(self.map, "as_dict"): 199 result["map"] = self.map.as_dict() 200 return result
API for interacting with B01 devices.
102 def __init__( 103 self, 104 channel: B01Q10Channel, 105 *, 106 map_parser_config: B01Q10MapParserConfig | None = None, 107 ) -> None: 108 """Initialize the B01Props API.""" 109 self._channel = channel 110 self.command = CommandTrait(channel) 111 self.remote = RemoteTrait(self.command) 112 self.status = StatusTrait() 113 self.volume = SoundVolumeTrait(self.command) 114 self.child_lock = ChildLockTrait(self.command) 115 self.do_not_disturb = DoNotDisturbTrait(self.command) 116 self.dust_collection = DustCollectionTrait(self.command) 117 self.button_light = ButtonLightTrait(self.command) 118 self.network_info = NetworkInfoTrait() 119 self.consumable = ConsumableTrait() 120 self._map_dps = MapDpsTrait() 121 self.maps = MapsTrait(self.command) 122 self.map = MapContentTrait( 123 self._map_dps, 124 self.command, 125 map_parser_config=map_parser_config, 126 ) 127 self.clean_history = CleanHistoryTrait(self.command) 128 self.vacuum = VacuumTrait(self.command, self.status, self.map) 129 # Read-model traits updated from the device's DPS push stream. 130 self._updatable_traits = [ 131 self.status, 132 self.volume, 133 self.child_lock, 134 self.do_not_disturb, 135 self.dust_collection, 136 self.network_info, 137 self.consumable, 138 self.clean_history, 139 self._map_dps, 140 self.maps, 141 ] 142 self._subscribe_task: asyncio.Task[None] | None = None
Initialize the B01Props API.
Trait for sending commands to Q10 devices.
Trait for sending vacuum related commands to Q10 devices.
Trait for sending remote control related commands to Q10 devices.
Trait for reading / controlling the child lock.
Trait for reading / controlling Do Not Disturb.
Trait for reading / controlling dock auto-empty (dust collection).
Trait exposing the device's network information.
Trait exposing remaining life of consumables.
Trait for fetching the device clean-record history (dpCleanRecord).
144 async def start(self) -> None: 145 """Start any necessary subscriptions for the trait.""" 146 self._subscribe_task = asyncio.create_task(self._subscribe_loop())
Start any necessary subscriptions for the trait.
148 async def close(self) -> None: 149 """Close any resources held by the trait.""" 150 await self.vacuum.close() 151 if self._subscribe_task is not None: 152 self._subscribe_task.cancel() 153 try: 154 await self._subscribe_task 155 except asyncio.CancelledError: 156 pass # ignore cancellation errors 157 self._subscribe_task = None
Close any resources held by the trait.
159 async def refresh(self) -> None: 160 """Refresh all traits.""" 161 # Sending REQUEST_DPS causes the device to publish its ordinary status 162 # values. Map-list and map-content refreshes have separate schedules. 163 await self.command.send(B01_Q10_DP.REQUEST_DPS, params={})
Refresh all traits.
192 def as_dict(self) -> dict[str, Any]: 193 """Return the trait data as a dictionary.""" 194 result: dict[str, Any] = {} 195 for name, value in self.__dict__.items(): 196 if isinstance(value, RoborockBase) and not name.startswith("_"): 197 result[name] = value.as_dict() 198 if hasattr(self, "map") and hasattr(self.map, "as_dict"): 199 result["map"] = self.map.as_dict() 200 return result
Return the trait data as a dictionary.