Motivation
GetInformationReply (CTA-2045-B § 11.1.1.2) exposes firmware version as five separate optional fields:
fw_major: int | None
fw_minor: int | None
fw_year: int | None
fw_month: int | None
fw_day: int | None
Consumers that need a human-readable firmware string for display, logging, or republishing to another data model end up writing the same composition glue. For example, the Electrification Bus water-heater data model expects a single firmware-version string property (per water-heater.md §Example: CTA-2045 water heater, which shows firmware-version = "CEA-2045AC-0.2.22"), so any CTA-2045 → eBus proxy has to do this composition itself.
I just wrote that helper in ebus-skycentrics-proxy and the next CTA-2045 proxy (Rheem, Cala, generic UCM tooling, etc.) will too. Pushing the helper into the lib makes consumers terser and gives one canonical format.
Proposed API
A @property on GetInformationReply:
@property
def firmware_version(self) -> Optional[str]:
\"\"\"Composed firmware version string, or None if no fw fields are set.
Format: '{major}.{minor}' when only the version-number fields are present
'{major}.{minor} ({YYYY-MM-DD})' when build-date fields are also present
\"\"\"
Returns None only when all of fw_major, fw_minor, and the date fields are None (i.e. the SGD did not include the optional trailing block at all). Defaults 0 for a missing major or minor when the other is present, since that's the meaningful CTA-2045 reading of 'this field omitted'.
Out of scope
The CEA-2045AC vendor-string prefix shown in the spec example (e.g. `"CEA-2045AC-"`) is vendor-injected and not in the CTA-2045 standardized fields; the proposed property would not attempt to reconstruct it — it covers only the standardized version + date.
Alternatives considered
- Keep it in user code. Works (and is what I did), but means every consumer duplicates ~10 lines and risks per-consumer formatting drift.
- Provide a free function
format_firmware_version(reply) -> str. Equally usable but discoverability is worse — a property next to the underlying fields is where consumers will look first.
Workaround in place today
In ebus-skycentrics-proxy I have a private _format_firmware_version(reply) -> Optional[str] static method that does the composition. Happy to migrate to reply.firmware_version if/when this lands.
Motivation
GetInformationReply(CTA-2045-B § 11.1.1.2) exposes firmware version as five separate optional fields:fw_major: int | Nonefw_minor: int | Nonefw_year: int | Nonefw_month: int | Nonefw_day: int | NoneConsumers that need a human-readable firmware string for display, logging, or republishing to another data model end up writing the same composition glue. For example, the Electrification Bus water-heater data model expects a single
firmware-versionstring property (per water-heater.md §Example: CTA-2045 water heater, which showsfirmware-version = "CEA-2045AC-0.2.22"), so any CTA-2045 → eBus proxy has to do this composition itself.I just wrote that helper in
ebus-skycentrics-proxyand the next CTA-2045 proxy (Rheem, Cala, generic UCM tooling, etc.) will too. Pushing the helper into the lib makes consumers terser and gives one canonical format.Proposed API
A
@propertyonGetInformationReply:Returns
Noneonly when all offw_major,fw_minor, and the date fields areNone(i.e. the SGD did not include the optional trailing block at all). Defaults0for a missingmajororminorwhen the other is present, since that's the meaningful CTA-2045 reading of 'this field omitted'.Out of scope
The CEA-2045AC vendor-string prefix shown in the spec example (e.g. `"CEA-2045AC-"`) is vendor-injected and not in the CTA-2045 standardized fields; the proposed property would not attempt to reconstruct it — it covers only the standardized version + date.
Alternatives considered
format_firmware_version(reply) -> str. Equally usable but discoverability is worse — a property next to the underlying fields is where consumers will look first.Workaround in place today
In
ebus-skycentrics-proxyI have a private_format_firmware_version(reply) -> Optional[str]static method that does the composition. Happy to migrate toreply.firmware_versionif/when this lands.