Skip to content

Commit 34bce78

Browse files
committed
Add nicer default output for info command
1 parent fa72185 commit 34bce78

File tree

2 files changed

+64
-10
lines changed

2 files changed

+64
-10
lines changed

README.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,39 @@ provided on PyPI.
5757
#### Info
5858

5959
```
60-
$ reolinkfw info file_or_url
60+
usage: reolinkfw info [-h] [--no-cache] [-j [indent]] file_or_url
61+
62+
positional arguments:
63+
file_or_url URL or on-disk file
64+
65+
optional arguments:
66+
-h, --help show this help message and exit
67+
--no-cache don't use cache for remote files (URLs)
68+
-j [indent], --json [indent] JSON output with optional indentation level for pretty print
6169
```
6270

6371
Example:
6472

6573
```
66-
$ reolinkfw info RLC-410-5MP_20_20052300.zip -i 2
74+
$ reolinkfw info RLC-410-5MP_20_20052300.zip
75+
IPC_51516M5M.20_20052300.RLC-410-5MP.OV05A10.5MP.REOLINK.pak
76+
Model: RLC-410-5MP
77+
Hardware info: IPC_51516M5M
78+
Device type: IPC
79+
Firmware version: v3.0.0.20_20052300
80+
Build date: 2020-05-23
81+
Architecture: MIPS
82+
OS: Linux
83+
Kernel image name: Linux-4.1.0
84+
U-Boot version: U-Boot 2014.07 (Feb 26 2019 - 18:20:07)
85+
File system: squashfs
86+
File system sections: fs
87+
```
88+
89+
Or with JSON output:
90+
91+
```
92+
$ reolinkfw info RLC-410-5MP_20_20052300.zip -j 2
6793
[
6894
{
6995
"firmware_version_prefix": "v3.0.0",

reolinkfw/__main__.py

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,50 @@
11
#!/usr/bin/env python3
22

3-
import argparse
43
import asyncio
54
import json
65
import sys
6+
from argparse import ArgumentParser, Namespace
7+
from datetime import datetime
78
from pathlib import Path, PurePath
89

910
from reolinkfw import __version__, get_info, get_paks
1011
from reolinkfw.extract import extract_pak
1112
from reolinkfw.util import sha256_pak
1213

14+
HW_FIELDS = ("board_type", "detail_machine_type", "board_name")
1315

14-
async def info(args: argparse.Namespace) -> None:
15-
info = await get_info(args.file_or_url, not args.no_cache)
16-
print(json.dumps(info, indent=args.indent, default=str))
1716

17+
async def info(args: Namespace) -> None:
18+
pak_infos = await get_info(args.file_or_url, not args.no_cache)
19+
if args.json is None:
20+
width = 21
21+
for idx, info in enumerate(pak_infos):
22+
info = Namespace(**info)
23+
fs_types = set(fs["type"] for fs in info.filesystems)
24+
fs_names = [fs["name"] for fs in info.filesystems]
25+
version = f"{info.firmware_version_prefix}.{info.version_file}"
26+
hw_names = set(getattr(info, key) for key in HW_FIELDS)
27+
build_date = datetime.strptime(info.build_date, "%y%m%d").date()
28+
print(info.pak)
29+
print(f"{'Model:':{width}}", info.display_type_info)
30+
print(f"{'Hardware info:':{width}}", ', '.join(sorted(hw_names)))
31+
print(f"{'Device type:':{width}}", info.type)
32+
print(f"{'Firmware version:':{width}}", version)
33+
print(f"{'Build date:':{width}}", build_date)
34+
print(f"{'Architecture:':{width}}", info.architecture)
35+
print(f"{'OS:':{width}}", info.os)
36+
print(f"{'Kernel image name:':{width}}", info.kernel_image_name)
37+
print(f"{'U-Boot version:':{width}}", info.uboot_version or "Unknown")
38+
print(f"{'File system:':{width}}", ', '.join(sorted(fs_types)))
39+
print(f"{'File system sections:':{width}}", ', '.join(fs_names))
40+
if idx != len(pak_infos) - 1:
41+
print()
42+
else:
43+
indent = None if args.json < 0 else args.json
44+
print(json.dumps(pak_infos, indent=indent, default=str))
1845

19-
async def extract(args: argparse.Namespace) -> None:
46+
47+
async def extract(args: Namespace) -> None:
2048
paks = await get_paks(args.file_or_url, not args.no_cache)
2149
if not paks:
2250
raise Exception("No PAKs found in ZIP file")
@@ -28,16 +56,16 @@ async def extract(args: argparse.Namespace) -> None:
2856

2957

3058
def main():
31-
parser = argparse.ArgumentParser(description="Extract information and files from Reolink firmwares")
59+
parser = ArgumentParser(description="Extract information and files from Reolink firmwares")
3260
parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {__version__}")
3361
subparsers = parser.add_subparsers(required=True)
3462

35-
pcache = argparse.ArgumentParser(add_help=False)
63+
pcache = ArgumentParser(add_help=False)
3664
pcache.add_argument("--no-cache", action="store_true", help="don't use cache for remote files (URLs)")
3765

3866
parser_i = subparsers.add_parser("info", parents=[pcache])
3967
parser_i.add_argument("file_or_url", help="URL or on-disk file")
40-
parser_i.add_argument("-i", "--indent", type=int, help="indent level for pretty print")
68+
parser_i.add_argument("-j", "--json", nargs='?', type=int, const=-1, metavar="indent", help="JSON output with optional indentation level for pretty print")
4169
parser_i.set_defaults(func=info)
4270

4371
descex = "Extract the file system from a Reolink firmware"

0 commit comments

Comments
 (0)