1919from miio .miot_device import MiotMapping
2020from miio .miot_models import DeviceModel , MiotAction , MiotProperty , MiotService
2121
22+ from .meta import Metadata
23+
2224_LOGGER = logging .getLogger (__name__ )
2325
2426
25- def pretty_status (result : "GenericMiotStatus" ):
27+ def pretty_status (result : "GenericMiotStatus" , verbose = False ):
2628 """Pretty print status information."""
2729 out = ""
2830 props = result .property_dict ()
@@ -46,6 +48,9 @@ def pretty_status(result: "GenericMiotStatus"):
4648 f" (min: { prop .range [0 ]} , max: { prop .range [1 ]} , step: { prop .range [2 ]} )"
4749 )
4850
51+ if verbose :
52+ out += f" ({ prop .full_name } )"
53+
4954 out += "\n "
5055
5156 return out
@@ -127,6 +132,8 @@ class GenericMiot(MiotDevice):
127132 "*"
128133 ] # we support all devices, if not, it is a responsibility of caller to verify that
129134
135+ _meta = Metadata .load ()
136+
130137 def __init__ (
131138 self ,
132139 ip : str = None ,
@@ -167,8 +174,16 @@ def initialize_model(self):
167174 _LOGGER .debug ("Initialized: %s" , self ._miot_model )
168175 self ._create_descriptors ()
169176
170- @command (default_output = format_output (result_msg_fmt = pretty_status ))
171- def status (self ) -> GenericMiotStatus :
177+ @command (
178+ click .option (
179+ "-v" ,
180+ "--verbose" ,
181+ is_flag = True ,
182+ help = "Output full property path for metadata " ,
183+ ),
184+ default_output = format_output (result_msg_fmt = pretty_status ),
185+ )
186+ def status (self , verbose = False ) -> GenericMiotStatus :
172187 """Return status based on the miot model."""
173188 properties = []
174189 for prop in self ._properties :
@@ -190,28 +205,50 @@ def status(self) -> GenericMiotStatus:
190205
191206 return GenericMiotStatus (response , self )
192207
208+ def get_extras (self , miot_entity ):
209+ """Enriches descriptor with extra meta data from yaml definitions."""
210+ extras = miot_entity .extras
211+ extras ["urn" ] = miot_entity .urn
212+ extras ["siid" ] = miot_entity .siid
213+
214+ # TODO: ugly way to detect the type
215+ if getattr (miot_entity , "aiid" , None ):
216+ extras ["aiid" ] = miot_entity .aiid
217+ if getattr (miot_entity , "piid" , None ):
218+ extras ["piid" ] = miot_entity .piid
219+
220+ meta = self ._meta .get_metadata (miot_entity )
221+ if meta :
222+ extras .update (meta )
223+ else :
224+ _LOGGER .warning (
225+ "Unable to find extras for %s %s" ,
226+ miot_entity .service ,
227+ repr (miot_entity .urn ),
228+ )
229+
230+ return extras
231+
193232 def _create_action (self , act : MiotAction ) -> Optional [ActionDescriptor ]:
194233 """Create action descriptor for miot action."""
195234 if act .inputs :
196235 # TODO: need to figure out how to expose input parameters for downstreams
197236 _LOGGER .warning (
198- "Got inputs for action, skipping as handling is unknown: %s" , act
237+ "Got inputs for action, skipping %s for %s" , act , act . service
199238 )
200239 return None
201240
202241 call_action = partial (self .call_action_by , act .siid , act .aiid )
203242
204243 id_ = act .name
205244
206- # TODO: move extras handling to the model
207- extras = act .extras
208- extras ["urn" ] = act .urn
209- extras ["siid" ] = act .siid
210- extras ["aiid" ] = act .aiid
245+ extras = self .get_extras (act )
246+ # TODO: ugly name override
247+ name = extras .pop ("description" , act .description )
211248
212249 return ActionDescriptor (
213250 id = id_ ,
214- name = act . description ,
251+ name = name ,
215252 method = call_action ,
216253 extras = extras ,
217254 )
@@ -223,10 +260,9 @@ def _create_actions(self, serv: MiotService):
223260 if act_desc is None : # skip actions we cannot handle for now..
224261 continue
225262
226- if (
227- act_desc .name in self ._actions
228- ): # TODO: find a way to handle duplicates, suffix maybe?
229- _LOGGER .warning ("Got used name name, ignoring '%s': %s" , act .name , act )
263+ # TODO: find a way to handle duplicates, suffix maybe?
264+ if act_desc .name in self ._actions :
265+ _LOGGER .warning ("Got a duplicate, ignoring '%s': %s" , act .name , act )
230266 continue
231267
232268 self ._actions [act_desc .name ] = act_desc
@@ -250,7 +286,7 @@ def _create_sensors_and_settings(self, serv: MiotService):
250286 _LOGGER .debug ("Skipping notify-only property: %s" , prop )
251287 continue
252288 if "read" not in prop .access : # TODO: handle write-only properties
253- _LOGGER .warning ("Skipping write-only: %s" , prop )
289+ _LOGGER .warning ("Skipping write-only: %s for %s " , prop , serv )
254290 continue
255291
256292 desc = self ._descriptor_for_property (prop )
@@ -266,16 +302,18 @@ def _create_sensors_and_settings(self, serv: MiotService):
266302 def _descriptor_for_property (self , prop : MiotProperty ):
267303 """Create a descriptor based on the property information."""
268304 desc : SettingDescriptor
269- name = prop .description
305+ orig_name = prop .description
270306 property_name = prop .name
271307
272308 setter = partial (self .set_property_by , prop .siid , prop .piid , name = property_name )
273309
274- # TODO: move extras handling to the model
275- extras = prop .extras
276- extras ["urn" ] = prop .urn
277- extras ["siid" ] = prop .siid
278- extras ["piid" ] = prop .piid
310+ extras = self .get_extras (prop )
311+
312+ # TODO: ugly name override, refactor
313+ name = extras .pop ("description" , orig_name )
314+ prop .description = name
315+ if name != orig_name :
316+ _LOGGER .debug ("Renamed %s to %s" , orig_name , name )
279317
280318 # Handle settable ranged properties
281319 if prop .range is not None :
@@ -310,7 +348,7 @@ def _create_choices_setting(
310348 choices = Enum (
311349 prop .description , {c .description : c .value for c in prop .choices }
312350 )
313- _LOGGER .debug ("Created enum %s" , choices )
351+ _LOGGER .debug ("Created enum %s for %s " , choices , prop )
314352 except ValueError as ex :
315353 _LOGGER .error ("Unable to create enum for %s: %s" , prop , ex )
316354 raise
0 commit comments