From fd641d01a5e2362addbced7b1e46d9d1c7900c24 Mon Sep 17 00:00:00 2001 From: Teemu R Date: Thu, 7 Jan 2021 21:26:09 +0100 Subject: [PATCH] Allow downloading miot spec files by model for miottemplate (#904) * Allow downloading miot spec files by model for miottemplate * Modify 'download' to use model instead of urn, urn can still be passed with --urn * Downloads and caches 'model_miotspec_mapping.json', if not available * Add 'list' to list all entries in the mapping file * Update readme --- devtools/README.md | 8 ++++-- devtools/containers.py | 22 +++++++++++++++ devtools/miottemplate.py | 59 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 80 insertions(+), 9 deletions(-) diff --git a/devtools/README.md b/devtools/README.md index 739fb2041..f7e18f59b 100644 --- a/devtools/README.md +++ b/devtools/README.md @@ -6,6 +6,8 @@ This directory contains tooling useful for developers This tool generates some boilerplate code for adding support for MIoT devices -1. Obtain device type from http://miot-spec.org/miot-spec-v2/instances?status=all -2. Execute `python miottemplate.py download ` to download the description file. -3. Execute `python miottemplate.py generate ` to generate pseudo-python for the device. +1. If you know the model, use `python miottemplate.py download ` to download the description file. + * This will download the model<->urn mapping file from http://miot-spec.org/miot-spec-v2/instances?status=all and store it locally + * If you know the urn, you can use `--urn` to avoid downloading the mapping file (should not be necessary) + +2. `python miottemplate.py print .json` prints out the siid/piid/aiid information from the spec file diff --git a/devtools/containers.py b/devtools/containers.py index 5c7a1fc37..c214fcd91 100644 --- a/devtools/containers.py +++ b/devtools/containers.py @@ -27,6 +27,28 @@ def indent(data, level=4): return indented +@dataclass +class InstanceInfo: + model: str + status: str + type: str + version: int + + +@dataclass +class ModelMapping(DataClassJsonMixin): + instances: List[InstanceInfo] + + def urn_for_model(self, model: str): + matches = [inst.type for inst in self.instances if inst.model == model] + if len(matches) > 1: + print( + "WARNING more than a single match for model %s: %s" % (model, matches) + ) + + return matches[0] + + @dataclass class Property(DataClassJsonMixin): iid: int diff --git a/devtools/miottemplate.py b/devtools/miottemplate.py index f13f0ad53..215bf65d1 100644 --- a/devtools/miottemplate.py +++ b/devtools/miottemplate.py @@ -1,8 +1,12 @@ import logging +from pathlib import Path import click -from containers import Device +import requests +from containers import Device, ModelMapping + +MIOTSPEC_MAPPING = Path("model_miotspec_mapping.json") _LOGGER = logging.getLogger(__name__) @@ -89,14 +93,57 @@ def print(file): @cli.command() -@click.argument("type") -def download(type): +def download_mapping(): + """Download model<->urn mapping.""" + click.echo( + "Downloading and saving model<->urn mapping to %s" % MIOTSPEC_MAPPING.name + ) + url = "http://miot-spec.org/miot-spec-v2/instances?status=all" + res = requests.get(url) + + with MIOTSPEC_MAPPING.open("w") as f: + f.write(res.text) + + +def get_mapping() -> ModelMapping: + with MIOTSPEC_MAPPING.open("r") as f: + return ModelMapping.from_json(f.read()) + + +@cli.command() +def list(): + """List all entries in the model<->urn mapping file.""" + mapping = get_mapping() + + for inst in mapping.instances: + click.echo(f"* {repr(inst)}") + + +@cli.command() +@click.option("--urn", default=None) +@click.argument("model", required=False) +@click.pass_context +def download(ctx, urn, model): """Download description file for model.""" - import requests - url = f"https://miot-spec.org/miot-spec-v2/instance?type={type}" + if urn is None: + if model is None: + click.echo("You need to specify either the model or --urn") + return + + if not MIOTSPEC_MAPPING.exists(): + click.echo( + "miotspec mapping doesn't exist, downloading to %s" + % MIOTSPEC_MAPPING.name + ) + ctx.invoke(download_mapping) + + mapping = get_mapping() + urn = mapping.urn_for_model(model) + + url = f"https://miot-spec.org/miot-spec-v2/instance?type={urn}" content = requests.get(url) - save_to = f"{type}.json" + save_to = f"{urn}.json" click.echo(f"Saving data to {save_to}") with open(save_to, "w") as f: f.write(content.text)