From e574d9203fb1af81f6f3b177eb2bec78f0fbe08d Mon Sep 17 00:00:00 2001 From: Brett Rowan <121075405+b-rowan@users.noreply.github.com> Date: Thu, 30 Oct 2025 09:16:07 -0600 Subject: [PATCH] feature: support IPv6 in the devices table --- goosebit/device_manager.py | 6 ++++-- goosebit/schema/devices.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/goosebit/device_manager.py b/goosebit/device_manager.py index ba4703d0..e42729dc 100644 --- a/goosebit/device_manager.py +++ b/goosebit/device_manager.py @@ -99,10 +99,12 @@ async def update_last_connection(device: Device, last_seen: int, last_ip: str | await DeviceManager.save_device(device, update_fields=["last_seen"]) elif ":" in last_ip: device.last_ipv6 = last_ip - await DeviceManager.save_device(device, update_fields=["last_seen", "last_ipv6"]) + device.last_ip = None + await DeviceManager.save_device(device, update_fields=["last_seen", "last_ipv6", "last_ip"]) else: device.last_ip = last_ip - await DeviceManager.save_device(device, update_fields=["last_seen", "last_ip"]) + device.last_ipv6 = None + await DeviceManager.save_device(device, update_fields=["last_seen", "last_ip", "last_ipv6"]) @staticmethod async def update_update(device: Device, update_mode: UpdateModeEnum, software: Software | None) -> None: diff --git a/goosebit/schema/devices.py b/goosebit/schema/devices.py index 0ca5e5e0..b8a9f523 100644 --- a/goosebit/schema/devices.py +++ b/goosebit/schema/devices.py @@ -5,7 +5,7 @@ from enum import Enum, IntEnum, StrEnum from typing import Annotated -from pydantic import BaseModel, BeforeValidator, ConfigDict, computed_field +from pydantic import BaseModel, BeforeValidator, ConfigDict, Field, computed_field from goosebit.db.models import UpdateModeEnum, UpdateStateEnum from goosebit.schema.software import HardwareSchema, SoftwareSchema @@ -42,7 +42,8 @@ class DeviceSchema(BaseModel): last_state: Annotated[UpdateStateSchema, BeforeValidator(UpdateStateSchema.convert)] # type: ignore[valid-type] update_mode: Annotated[UpdateModeSchema, BeforeValidator(UpdateModeSchema.convert)] # type: ignore[valid-type] force_update: bool - last_ip: str | None + last_ipv4: str | None = Field(validation_alias="last_ip") + last_ipv6: str | None last_seen: Annotated[ int | None, BeforeValidator(lambda last_seen: round(time.time() - last_seen) if last_seen is not None else None) ] @@ -53,6 +54,11 @@ class DeviceSchema(BaseModel): def polling(self) -> bool | None: return self.last_seen < (self.poll_seconds + 10) if self.last_seen is not None else None + @computed_field # type: ignore[prop-decorator] + @property + def last_ip(self) -> str | None: + return self.last_ipv4 or self.last_ipv6 + @computed_field # type: ignore[prop-decorator] @property def poll_seconds(self) -> int: