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
@@ -131,6 +136,8 @@ class GenericMiot(MiotDevice):
131136 "*"
132137 ] # we support all devices, if not, it is a responsibility of caller to verify that
133138
139+ _meta = Metadata .load ()
140+
134141 def __init__ (
135142 self ,
136143 ip : Optional [str ] = None ,
@@ -171,8 +178,16 @@ def initialize_model(self):
171178 _LOGGER .debug ("Initialized: %s" , self ._miot_model )
172179 self ._create_descriptors ()
173180
174- @command (default_output = format_output (result_msg_fmt = pretty_status ))
175- def status (self ) -> GenericMiotStatus :
181+ @command (
182+ click .option (
183+ "-v" ,
184+ "--verbose" ,
185+ is_flag = True ,
186+ help = "Output full property path for metadata " ,
187+ ),
188+ default_output = format_output (result_msg_fmt = pretty_status ),
189+ )
190+ def status (self , verbose = False ) -> GenericMiotStatus :
176191 """Return status based on the miot model."""
177192 properties = []
178193 for prop in self ._properties :
@@ -194,28 +209,50 @@ def status(self) -> GenericMiotStatus:
194209
195210 return GenericMiotStatus (response , self )
196211
212+ def get_extras (self , miot_entity ):
213+ """Enriches descriptor with extra meta data from yaml definitions."""
214+ extras = miot_entity .extras
215+ extras ["urn" ] = miot_entity .urn
216+ extras ["siid" ] = miot_entity .siid
217+
218+ # TODO: ugly way to detect the type
219+ if getattr (miot_entity , "aiid" , None ):
220+ extras ["aiid" ] = miot_entity .aiid
221+ if getattr (miot_entity , "piid" , None ):
222+ extras ["piid" ] = miot_entity .piid
223+
224+ meta = self ._meta .get_metadata (miot_entity )
225+ if meta :
226+ extras .update (meta )
227+ else :
228+ _LOGGER .warning (
229+ "Unable to find extras for %s %s" ,
230+ miot_entity .service ,
231+ repr (miot_entity .urn ),
232+ )
233+
234+ return extras
235+
197236 def _create_action (self , act : MiotAction ) -> Optional [ActionDescriptor ]:
198237 """Create action descriptor for miot action."""
199238 if act .inputs :
200239 # TODO: need to figure out how to expose input parameters for downstreams
201240 _LOGGER .warning (
202- "Got inputs for action, skipping as handling is unknown: %s" , act
241+ "Got inputs for action, skipping %s for %s" , act , act . service
203242 )
204243 return None
205244
206245 call_action = partial (self .call_action_by , act .siid , act .aiid )
207246
208247 id_ = act .name
209248
210- # TODO: move extras handling to the model
211- extras = act .extras
212- extras ["urn" ] = act .urn
213- extras ["siid" ] = act .siid
214- extras ["aiid" ] = act .aiid
249+ extras = self .get_extras (act )
250+ # TODO: ugly name override
251+ name = extras .pop ("description" , act .description )
215252
216253 return ActionDescriptor (
217254 id = id_ ,
218- name = act . description ,
255+ name = name ,
219256 method = call_action ,
220257 extras = extras ,
221258 )
@@ -227,10 +264,9 @@ def _create_actions(self, serv: MiotService):
227264 if act_desc is None : # skip actions we cannot handle for now..
228265 continue
229266
230- if (
231- act_desc .name in self ._actions
232- ): # TODO: find a way to handle duplicates, suffix maybe?
233- _LOGGER .warning ("Got used name name, ignoring '%s': %s" , act .name , act )
267+ # TODO: find a way to handle duplicates, suffix maybe?
268+ if act_desc .name in self ._actions :
269+ _LOGGER .warning ("Got a duplicate, ignoring '%s': %s" , act .name , act )
234270 continue
235271
236272 self ._actions [act_desc .name ] = act_desc
@@ -254,7 +290,7 @@ def _create_sensors_and_settings(self, serv: MiotService):
254290 _LOGGER .debug ("Skipping notify-only property: %s" , prop )
255291 continue
256292 if "read" not in prop .access : # TODO: handle write-only properties
257- _LOGGER .warning ("Skipping write-only: %s" , prop )
293+ _LOGGER .warning ("Skipping write-only: %s for %s " , prop , serv )
258294 continue
259295
260296 desc = self ._descriptor_for_property (prop )
@@ -269,16 +305,18 @@ def _create_sensors_and_settings(self, serv: MiotService):
269305
270306 def _descriptor_for_property (self , prop : MiotProperty ):
271307 """Create a descriptor based on the property information."""
272- name = prop .description
308+ orig_name = prop .description
273309 property_name = prop .name
274310
275311 setter = partial (self .set_property_by , prop .siid , prop .piid , name = property_name )
276312
277- # TODO: move extras handling to the model
278- extras = prop .extras
279- extras ["urn" ] = prop .urn
280- extras ["siid" ] = prop .siid
281- extras ["piid" ] = prop .piid
313+ extras = self .get_extras (prop )
314+
315+ # TODO: ugly name override, refactor
316+ name = extras .pop ("description" , orig_name )
317+ prop .description = name
318+ if name != orig_name :
319+ _LOGGER .debug ("Renamed %s to %s" , orig_name , name )
282320
283321 # Handle settable ranged properties
284322 if prop .range is not None :
@@ -313,7 +351,7 @@ def _create_choices_setting(
313351 choices = Enum (
314352 prop .description , {c .description : c .value for c in prop .choices }
315353 )
316- _LOGGER .debug ("Created enum %s" , choices )
354+ _LOGGER .debug ("Created enum %s for %s " , choices , prop )
317355 except ValueError as ex :
318356 _LOGGER .error ("Unable to create enum for %s: %s" , prop , ex )
319357 raise
0 commit comments