{"id":28392765,"url":"https://github.com/zigpy/zigpy-cli","last_synced_at":"2025-06-26T07:30:48.208Z","repository":{"id":40452064,"uuid":"385369950","full_name":"zigpy/zigpy-cli","owner":"zigpy","description":"Command line interface for zigpy","archived":false,"fork":false,"pushed_at":"2025-01-23T01:05:20.000Z","size":78,"stargazers_count":56,"open_issues_count":12,"forks_count":13,"subscribers_count":8,"default_branch":"dev","last_synced_at":"2025-06-01T02:08:17.566Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zigpy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-12T20:06:36.000Z","updated_at":"2025-05-27T14:37:37.000Z","dependencies_parsed_at":"2024-08-08T17:23:58.018Z","dependency_job_id":null,"html_url":"https://github.com/zigpy/zigpy-cli","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/zigpy/zigpy-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zigpy%2Fzigpy-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zigpy%2Fzigpy-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zigpy%2Fzigpy-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zigpy%2Fzigpy-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zigpy","download_url":"https://codeload.github.com/zigpy/zigpy-cli/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zigpy%2Fzigpy-cli/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262022037,"owners_count":23246239,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-31T15:08:07.641Z","updated_at":"2025-06-26T07:30:48.201Z","avatar_url":"https://github.com/zigpy.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `zigpy-cli`\n\nA unified command line interface for zigpy radios. The goal of this project is to allow\nlow-level network management from an intuitive command line interface and to group useful\nZigbee tools into a single binary.\n\n## Installation\n\n```console\n$ pip install zigpy-cli\n```\n\n## Usage\n\n```console\n$ zigpy --help\nUsage: zigpy [OPTIONS] COMMAND [ARGS]...\n\nOptions:\n  -v, --verbose\n  --help         Show this message and exit.\n\nCommands:\n  ota\n  radio\n  pcap\n```\n\n**Make sure ZHA, Zigbee2MQTT, deCONZ, etc. are disabled.** Any software controlling your\nradio requires exclusive access to the hardware: if both are running at once, neither will work.\n\n# Network commands\nNetwork commands require the radio type to be specified. See `zigpy radio --help` for the list of supported types.\nIf your radio requires a different baudrate than the radio library default (mainly EZSP), you must specify it as a command line option. For example, `zigpy radio --baudrate 115200 ezsp backup -`.\n\n## Network backup\n\n```console\n$ zigpy radio deconz /dev/ttyUSB0 backup deconz-backup.json\n```\n\n## Network restore\n\n```console\n$ zigpy radio znp /dev/ttyUSB1 restore deconz-backup.json\n```\n\n## Reading network information\n\n```console\n$ zigpy radio znp /dev/ttyUSB0 info\nPAN ID:                0x718B\nExtended PAN ID:       33:29:33:5e:30:42:64:48\nChannel:               15\nChannel mask:          [15]\nNWK update ID:         0\nDevice IEEE:           00:12:4b:00:1c:ce:33:85\nDevice NWK:            0x0000\nNetwork key:           cc:44:a6:4e:23:82:30:9e:35:0f:c6:6a:89:c8:dd:7d\nNetwork key sequence:  0\n```\n\n## Forming a network\n\n```console\n$ zigpy -vvvv radio znp /dev/cu.usb* form\n2021-07-12 13:24:54.764 host asyncio DEBUG Using selector: KqueueSelector\n2021-07-12 13:24:54.933 host zigpy_znp.uart DEBUG Connecting to /dev/ttyUSB0 at 115200 baud\n2021-07-12 13:24:54.940 host zigpy_znp.uart DEBUG Opened /dev/ttyUSB0 serial port\n2021-07-12 13:24:54.941 host zigpy_znp.uart DEBUG Toggling RTS/CTS to skip CC2652R bootloader\n2021-07-12 13:24:55.404 host zigpy_znp.uart DEBUG Connected to /dev/ttyUSB0 at 115200 baud\n2021-07-12 13:24:55.404 host zigpy_znp.api DEBUG Waiting 1s before sending anything\n2021-07-12 13:24:56.409 host zigpy_znp.api DEBUG Sending bootloader skip byte\n...\nPAN ID:                0xAA8A\nExtended PAN ID:       35:8f:dc:b6:7a:19:33:c3\nChannel:               15\nChannel mask:          [15]\nNWK update ID:         0\nDevice IEEE:           00:12:4b:00:1c:ce:33:85\nDevice NWK:            0x0000\nNetwork key:           8c:2d:2d:a6:ca:95:30:04:11:6b:d5:dd:32:9e:b6:a8\nNetwork key sequence:  0\n2021-07-12 13:25:15.316 host zigpy_znp.uart DEBUG Closing serial port\n```\n\n## Performing an energy scan\n\n```console\n$ zigpy radio znp /dev/cu.usbserial-1420 energy-scan\n\nChannel energy (mean of 1 / 5):\n------------------------------------------------\n + Lower energy is better\n + Active Zigbee networks on a channel may still cause congestion\n + TX on 26 in North America may be with lower power due to regulations\n + Zigbee channels 15, 20, 25 fall between WiFi channels 1, 6, 11\n + Some Zigbee devices only join networks on channels 15, 20, and 25\n------------------------------------------------\n - 11    80.00%  ################################################################################\n - 12    83.53%  ###################################################################################\n - 13    83.14%  ###################################################################################\n - 14    78.82%  ##############################################################################\n - 15    76.47%  ############################################################################\n - 16    72.16%  ########################################################################\n - 17    76.47%  ############################################################################\n - 18    75.69%  ###########################################################################\n - 19    72.16%  ########################################################################\n - 20    65.49%  #################################################################\n - 21    66.67%  ##################################################################\n - 22    70.59%  ######################################################################\n - 23    80.00%  ################################################################################\n - 24    64.31%  ################################################################\n - 25    77.25%  #############################################################################\n - 26*   81.96%  #################################################################################\n```\n\n## Reset a radio\n\n```console\n$ zigpy radio --baudrate 115200 ezsp /dev/serial/by-id/some-radio reset\n```\n\n## Permit joins\n\nMainly useful for testing requests.\n\n```console\n$ zigpy radio deconz /dev/ttyUSB0 permit -t 60\n```\n\n## Changing the network channel\n\nSome devices (like older Aqara sensors) may not migrate.\n\n```console\n$ zigpy radio znp /dev/ttyUSB0 change-channel --channel 25\n```\n\n## Network scan\n\nOn supported radios, you can perform an active beacon scan for nearby 802.15.4 networks:\n\n```console\n$ zigpy radio ezsp /dev/ttyUSB0 network-scan --channels 11,15,20,25 --duration-exponent 3\nchannel: 11, network: 0x1D13 (00:07:81:00:0e:e9:d8:9f), permitting joins: 1, nwk update id: 0, lqi:  180, rssi: -66\nchannel: 11, network: 0x2857 (00:07:81:00:fc:9e:ef:95), permitting joins: 0, nwk update id: 0, lqi:  224, rssi: -55\nchannel: 11, network: 0x08C7 (00:07:81:00:50:d2:be:2e), permitting joins: 0, nwk update id: 0, lqi:  216, rssi: -57\nchannel: 15, network: 0x2ABB (00:07:81:00:c5:10:10:4b), permitting joins: 0, nwk update id: 0, lqi:  212, rssi: -58\nScanning channel 15\n```\n\n## Packet capture\n\nOn supported radios, you can capture packets and pipe the PCAP output to Wireshark:\n\n```console\n$ zigpy radio ezsp /dev/cu.SLAB_USBtoUART14 packet-capture -c 12,13,14,26 --interleave --channel-hop-period 1 -o - | wireshark -k -S -i -\n```\n\nIf you have multiple adapters, you can capture with multiple interfaces concurrently:\n\n```console\n(\n    zigpy radio ezsp /dev/cu.SLAB_USBtoUART   packet-capture -c 11 --interleave -o -  \u0026\n    zigpy radio ezsp /dev/cu.SLAB_USBtoUART8  packet-capture -c 15 --interleave -o -  \u0026\n    zigpy radio ezsp /dev/cu.SLAB_USBtoUART10 packet-capture -c 20 --interleave -o -  \u0026\n    zigpy radio ezsp /dev/cu.SLAB_USBtoUART13 packet-capture -c 25 --interleave -o -  \u0026\n    zigpy radio ezsp /dev/cu.SLAB_USBtoUART14 packet-capture -c 12,13,14,26 --interleave --channel-hop-period 1 -o -  \u0026\n    zigpy radio ezsp /dev/cu.SLAB_USBtoUART17 packet-capture -c 16,17,18,19 --interleave --channel-hop-period 1 -o -  \u0026\n    zigpy radio ezsp /dev/cu.SLAB_USBtoUART18 packet-capture -c 21,22,23,24 --interleave --channel-hop-period 1 -o -  \u0026\n    wait\n) | zigpy pcap interleave-combine -o - | wireshark -k -S -i -\n```\n\n# OTA\n## Display basic information about OTA files\n```console\n$ zigpy ota info 10047227-1.2-TRADFRI-cv-cct-unified-2.3.050.ota.ota.signed\nHeader: OTAImageHeader(upgrade_file_id=200208670, header_version=256, header_length=56, field_control=\u003cFieldControl.0: 0\u003e, manufacturer_id=4476, image_type=16902, file_version=587531825, stack_version=2, header_string='GBL GBL_tradfri_cv_cct_unified', image_size=208766, *device_specific_file=False, *hardware_versions_present=False, *key=ImageKey(manufacturer_id=4476, image_type=16902), *security_credential_version_present=False)\nNumber of subelements: 1\nValidation result: ValidationResult.VALID\n```\n\n## Dump embedded firmware for further analysis\n\n```console\n$ zigpy ota dump-firmware 10047227-1.2-TRADFRI-cv-cct-unified-2.3.050.ota.ota.signed - \\\n      | commander ebl print /dev/stdin \\\n      | grep 'Ember Version'\nEmber Version:    6.3.1.1\n```\n\n## Generate OTA index files\n\nCreate a JSON index for a given directory of firmwares:\n\n```console\n$ zigpy ota generate-index --ota-url-root=\"https://example.org/fw\" path/to/firmwares/**/*.ota\n2023-02-14 12:02:03.532 ubuntu zigpy_cli.ota INFO Parsing path/to/firmwares/fw/test.ota\n2023-02-14 12:02:03.533 ubuntu zigpy_cli.ota INFO Writing path/to/firmwares/fw/test.ota\n[\n    {\n        \"binary_url\": \"https://example.org/fw/test.ota\",\n        \"file_version\": 1762356,\n        \"image_type\": 1234,\n        \"manufacturer_id\": 5678,\n        \"changelog\": \"\",\n        \"checksum\": \"sha3-256:1ddaa649eb920dea9e5f002fe0d1443cc903ac0c1b26e7ad2c97b928edec2786\"\n    },\n...\n```\n\n## Reconstruct an OTA image from a series of packet captures\n\nRequires the `tshark` binary to be available.\n\n```console\n$ zigpy ota reconstruct-from-pcaps --add-network-key aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99 --output-root ./extracted/ *.pcap\nConstructing image type=0x298b, version=0x00000005, manuf_code=0x115f: 157424 bytes\n2023-02-22 03:39:51.406 ubuntu zigpy_cli.ota ERROR Missing 48 bytes starting at offset 0x0000ADA0: filling with 0xAB\n2023-02-22 03:39:51.406 ubuntu zigpy_cli.ota ERROR Missing 48 bytes starting at offset 0x000106B0: filling with 0xAB\nConstructing image type=0x298b, version=0x00000009, manuf_code=0x115f: 163136 bytes\n```\n\n\n# PCAP\n## Re-calculate the FCS on a packet capture\n\nFixes a bug in current EmberZNet SDK releases:\n```console\n$ # Fix an existing capture\n$ zigpy pcap fix-fcs input.pcap fixed.pcap\n$ # Fix a capture from stdin and send it to stdout\n$ bellows -d /dev/cu.GoControl_zigbee dump -w /dev/stdout | zigpy pcap fix-fcs - - | wireshark -k -S -i -\n```\n\n# Database\nAttempt to recover a corrupted `zigbee.db` database:\n\n```console\n$ zigpy -v db recover broken.db fixed.db\n2022-05-07 13:01:22.907 host zigpy_cli.database ERROR Failed to insert INSERT INTO \"attributes_cache_v7\"(\"_rowid_\", \"ieee\", \"endpoint_id\", \"cluster\", \"attrid\", \"value\") VALUES( 14507477, '00:15:8d:00:02:5e:f9:ff', 1, 1027, 0, 1001.78 );: IntegrityError('UNIQUE constraint failed: attributes_cache_v7.ieee, attributes_cache_v7.endpoint_id, attributes_cache_v7.cluster, attributes_cache_v7.attrid')\n2022-05-07 13:01:22.916 host zigpy_cli.database INFO Done\n```\n\nThe final database will have no invalid constraints but data will likely be lost.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzigpy%2Fzigpy-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzigpy%2Fzigpy-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzigpy%2Fzigpy-cli/lists"}