-
Notifications
You must be signed in to change notification settings - Fork 23
Add basic controller firmware update information #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,52 @@ | ||||||
| """Implementation for 'firmware' command""" | ||||||
|
|
||||||
| from argparse import ArgumentParser | ||||||
| from .config import get_target_config, to_omada_connection | ||||||
| from .util import dump_raw_data, get_target_argument | ||||||
|
|
||||||
|
|
||||||
| async def command_firmware(args) -> int: | ||||||
| """Executes 'firmware' command""" | ||||||
| controller = get_target_argument(args) | ||||||
| config = get_target_config(controller) | ||||||
|
|
||||||
| async with to_omada_connection(config) as client: | ||||||
| controller_updates = await client.check_firmware_updates() | ||||||
| if controller_updates.hardware: | ||||||
| hardware_update = controller_updates.hardware | ||||||
| status = "\u2757 UPDATE" if hardware_update.upgrade else "\u2713 UP-TO-DATE" | ||||||
| print(f"{'Controller':<30} {hardware_update.current_version:<36} {hardware_update.latest_version:<36} {status}") | ||||||
| if hardware_update.upgrade and hardware_update.release_notes and args["release_notes"]: | ||||||
| print(f" Release Notes: {hardware_update.release_notes}") | ||||||
| else: | ||||||
| print("No controller firmware updates available.") | ||||||
|
|
||||||
| dump_raw_data(args, controller_updates) | ||||||
|
|
||||||
| site_client = await client.get_site_client(config.site) | ||||||
| devices = await site_client.get_devices() | ||||||
| if not devices: | ||||||
| print("No devices found in the specified site.") | ||||||
| return 0 | ||||||
|
|
||||||
| for device in devices: | ||||||
| firmware = await site_client.get_firmware_details(device) | ||||||
| status = "\u2757 UPDATE" if firmware.current_version != firmware.latest_version else "\u2713 UP-TO-DATE" | ||||||
| print(f"{device.name:<30} {firmware.current_version:<36} {firmware.latest_version:<36} {status}") | ||||||
| if firmware.current_version != firmware.latest_version and firmware.release_notes and args["release_notes"]: | ||||||
| print(f" Release Notes: {firmware.release_notes}") | ||||||
|
|
||||||
| dump_raw_data(args, firmware) | ||||||
|
|
||||||
| return 0 | ||||||
|
|
||||||
|
|
||||||
| def arg_parser(subparsers) -> None: | ||||||
| """Configures arguments parser for 'firmware' command""" | ||||||
| firmware_parser: ArgumentParser = subparsers.add_parser( | ||||||
| "firmware", help="Shows firmware information and update availability for the specified device" | ||||||
|
||||||
| "firmware", help="Shows firmware information and update availability for the specified device" | |
| "firmware", help="Shows controller and device firmware information and update availability for the configured site" |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -277,3 +277,65 @@ class LedSetting(IntEnum): | |||||
| @classmethod | ||||||
| def _missing_(cls, _): | ||||||
| return LedSetting.UNKNOWN | ||||||
|
|
||||||
|
|
||||||
| class OmadaHardwareUpdateInfo(OmadaApiData): | ||||||
| """Information about available hardware firmware updates.""" | ||||||
|
|
||||||
| @property | ||||||
| def upgrade(self) -> bool: | ||||||
| """Whether a firmware upgrade is available.""" | ||||||
| return self._data["upgrade"] | ||||||
|
|
||||||
| @property | ||||||
| def latest_version(self) -> str: | ||||||
| """The latest available firmware version.""" | ||||||
| return self._data.get("latestVersion", self.current_version) | ||||||
|
|
||||||
| @property | ||||||
| def current_version(self) -> str: | ||||||
| """The currently installed firmware version.""" | ||||||
| return self._data["currentVersion"] | ||||||
|
|
||||||
| @property | ||||||
| def release_notes(self) -> str | None: | ||||||
| """Release notes for the latest firmware version.""" | ||||||
| return self._data.get("fwReleaseLog", None) | ||||||
|
|
||||||
|
|
||||||
| class OmadaControllerUpdateInfo(OmadaApiData): | ||||||
| """Information about available controller and device firmware updates.""" | ||||||
|
|
||||||
| @property | ||||||
| def hardware(self) -> OmadaHardwareUpdateInfo | None: | ||||||
| """Information about available hardware controller firmware updates.""" | ||||||
| return OmadaHardwareUpdateInfo(self._data["hardware"]) if "hardware" in self._data else None | ||||||
|
|
||||||
|
|
||||||
| class OmadaHardwareUpgradeStatus(OmadaApiData): | ||||||
| """Information about the status of a hardware controller firmware upgrade.""" | ||||||
|
|
||||||
| @property | ||||||
| def upgrade_status(self) -> int: | ||||||
| """The current status of the firmware upgrade process.""" | ||||||
| return self._data["upgradeStatus"] | ||||||
|
|
||||||
| @property | ||||||
| def upgrade_msg(self) -> str: | ||||||
| """Any message associated with the current firmware upgrade status.""" | ||||||
| return self._data.get("upgradeMsg", "") | ||||||
|
|
||||||
| @property | ||||||
| def upgrade_time(self) -> int: | ||||||
| """How often to refresh to watch the download progress?""" | ||||||
| return self._data.get("upgradeTime", 0) | ||||||
|
|
||||||
| @property | ||||||
| def download_progress(self) -> int: | ||||||
| """The current progress of the firmware download, as a percentage.""" | ||||||
| return self._data.get("downloadProgress", 0) | ||||||
|
|
||||||
| @property | ||||||
| def reboot_time(self) -> int: | ||||||
| """How long after the donwload completes before we expect the controller to come back online, in seconds.""" | ||||||
|
||||||
| """How long after the donwload completes before we expect the controller to come back online, in seconds.""" | |
| """How long after the download completes before we expect the controller to come back online, in seconds.""" |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |||||||||||||||||||||||
| from awesomeversion import AwesomeVersion | ||||||||||||||||||||||||
| from multidict import CIMultiDict | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| from .definitions import OmadaControllerUpdateInfo, OmadaHardwareUpgradeStatus | ||||||||||||||||||||||||
| from .omadasiteclient import OmadaSiteClient | ||||||||||||||||||||||||
| from .omadaapiconnection import OmadaApiConnection | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
@@ -141,3 +142,25 @@ async def set_certificate(self, file: str, cert_password: str): | |||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| url = self._api.format_url("controller/setting") | ||||||||||||||||||||||||
| await self._api.request("patch", url, json=payload) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| async def check_firmware_updates(self) -> OmadaControllerUpdateInfo: | ||||||||||||||||||||||||
| """Check if firmware updates are available for the Omada hardware controller | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Software Controller updates are probably not available via this API | ||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||
| result = await self._api.request("get", self._api.format_url("controller/notification/updateInfo")) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| return OmadaControllerUpdateInfo(result) | ||||||||||||||||||||||||
|
Comment on lines
+146
to
+153
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| async def upgrade_controller_firmware(self, target_version: str) -> bool: | ||||||||||||||||||||||||
| """Upgrade the Omada hardware controller firmware to the specified version.""" | ||||||||||||||||||||||||
| url = self._api.format_url("cmd/upgradeFirmware") | ||||||||||||||||||||||||
| payload = {"targetVersion": target_version} | ||||||||||||||||||||||||
| await self._api.request("post", url, json=payload) | ||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||
|
Comment on lines
+155
to
+160
|
||||||||||||||||||||||||
| async def upgrade_controller_firmware(self, target_version: str) -> bool: | |
| """Upgrade the Omada hardware controller firmware to the specified version.""" | |
| url = self._api.format_url("cmd/upgradeFirmware") | |
| payload = {"targetVersion": target_version} | |
| await self._api.request("post", url, json=payload) | |
| return True | |
| async def upgrade_controller_firmware(self, target_version: str) -> None: | |
| """Upgrade the Omada hardware controller firmware to the specified version.""" | |
| url = self._api.format_url("cmd/upgradeFirmware") | |
| payload = {"targetVersion": target_version} | |
| await self._api.request("post", url, json=payload) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
firmware.release_notescan raiseKeyErrorbecauseOmadaFirmwareUpdate.release_notesindexesself._data["fwReleaseLog"]directly. Since this command accessesfirmware.release_notes, it can crash when the API omits that field. Consider usingfirmware.raw_data.get("fwReleaseLog")here, or updatingOmadaFirmwareUpdate.release_notesto returnstr | Nonevia.get()and then checking forNone.