Skip to content

Commit

Permalink
OTA index file generation (#28)
Browse files Browse the repository at this point in the history
* Create the `ota generate-index` command

* Move the root logger object into its own variable

* Document in README
  • Loading branch information
puddly authored Feb 14, 2023
1 parent de9b462 commit 125b537
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ repos:
- id: black
args: ["--safe", "--quiet"]
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.0.244'
rev: 'v0.0.246'
hooks:
- id: ruff
args: ["--fix"]
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,25 @@ $ zigpy ota dump-firmware 10047227-1.2-TRADFRI-cv-cct-unified-2.3.050.ota.ota.si
Ember Version: 6.3.1.1
```

## Generate OTA index files

Create a JSON index for a given directory of firmwares:

```console
$ zigpy ota generate-index --ota-url-root="https://example.org/fw" path/to/firmwares/**/*.ota
2023-02-14 12:02:03.532 ubuntu zigpy_cli.ota INFO Parsing path/to/firmwares/fw/test.ota
2023-02-14 12:02:03.533 ubuntu zigpy_cli.ota INFO Writing path/to/firmwares/fw/test.ota
[
{
"binary_url": "https://example.org/fw/test.ota",
"file_version": 1762356,
"image_type": 1234,
"manufacturer_id": 5678,
"changelog": "",
"checksum": "sha3-256:1ddaa649eb920dea9e5f002fe0d1443cc903ac0c1b26e7ad2c97b928edec2786"
},
...
```

# PCAP
## Re-calculate the FCS on a packet capture
Expand Down
5 changes: 3 additions & 2 deletions zigpy_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from zigpy_cli.const import LOG_LEVELS

LOGGER = logging.getLogger(__name__)
ROOT_LOGGER = logging.getLogger()


def click_coroutine(cmd):
Expand All @@ -31,7 +32,7 @@ def cli(verbose):
level_styles["trace"] = level_styles["spam"]

LOGGER.setLevel(log_level)
logging.getLogger().setLevel(log_level)
ROOT_LOGGER.setLevel(log_level)

coloredlogs.install(
fmt=(
Expand All @@ -42,5 +43,5 @@ def cli(verbose):
),
level=log_level,
level_styles=level_styles,
logger=logging.getLogger(),
logger=ROOT_LOGGER,
)
60 changes: 60 additions & 0 deletions zigpy_cli/ota.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

import hashlib
import json
import logging
import pathlib

Expand Down Expand Up @@ -65,3 +67,61 @@ def dump_firmware(input, output):
break
else:
LOGGER.warning("Image has no UPGRADE_IMAGE subelements")


@ota.command()
@click.pass_context
@click.option("--ota-url-root", type=str, default=None)
@click.option("--output", type=click.File("w"), default="-")
@click.argument("files", nargs=-1, type=pathlib.Path)
def generate_index(ctx, ota_url_root, output, files):
if ctx.parent.parent.params["verbose"] == 0:
cli.callback(verbose=1)

ota_metadata = []

for f in files:
if not f.is_file():
continue

LOGGER.info("Parsing %s", f)
contents = f.read_bytes()

try:
image, rest = parse_ota_image(contents)
except Exception as e:
LOGGER.error("Failed to parse: %s", e)
continue

if rest:
LOGGER.error("Image has trailing data: %r", rest)
continue

try:
validate_ota_image(image)
except Exception as e:
LOGGER.error("Image is invalid: %s", e)

if ota_url_root is not None:
url = f"{ota_url_root.rstrip('/')}/{f.name}"
else:
url = None

metadata = {
"binary_url": url,
"file_version": image.header.file_version,
"image_type": image.header.image_type,
"manufacturer_id": image.header.manufacturer_id,
"changelog": "",
"checksum": f"sha3-256:{hashlib.sha3_256(contents).hexdigest()}",
}

if image.header.hardware_versions_present:
metadata["min_hardware_version"] = image.header.minimum_hardware_version
metadata["max_hardware_version"] = image.header.maximum_hardware_version

LOGGER.info("Writing %s", f)
ota_metadata.append(metadata)

json.dump(ota_metadata, output, indent=4)
output.write("\n")

0 comments on commit 125b537

Please sign in to comment.