Build Pigway Frame Flow with bilingual UI, complete KoKonna driver and safe automation
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
from pigway_frame_flow.models import (
|
||||
CurrentContent,
|
||||
Device,
|
||||
DisplayGeometry,
|
||||
GalleryImage,
|
||||
Power,
|
||||
)
|
||||
|
||||
|
||||
class KokonnaDriver:
|
||||
def __init__(self, client, device_id, sanitize=lambda v: v):
|
||||
self.client, self.device_id, self.sanitize = client, device_id, sanitize
|
||||
self.cached: Device | None = None
|
||||
self.cached_at = 0.0
|
||||
|
||||
def device(self, refresh=False):
|
||||
import time
|
||||
|
||||
if not refresh and self.cached and time.monotonic() - self.cached_at < 60:
|
||||
return self.cached
|
||||
d = self.sanitize(self.client.get_device())
|
||||
result = Device(
|
||||
id=self.device_id,
|
||||
name=d.get("nickname", "KoKonna"),
|
||||
status="online" if d.get("online") else "offline",
|
||||
model=d.get("model", "13.3-inch"),
|
||||
model_code=d.get("modelCode", "B101"),
|
||||
firmware=d.get("firmware"),
|
||||
display=DisplayGeometry(
|
||||
**{
|
||||
"width": d.get("screenWidth", 1200),
|
||||
"height": d.get("screenHeight", 1600),
|
||||
"rotation": d.get("screenRotate", 270),
|
||||
}
|
||||
),
|
||||
power=Power(
|
||||
**{
|
||||
"battery_percent": d.get("batteryLevel"),
|
||||
"charging": bool(d.get("isCharging")),
|
||||
}
|
||||
),
|
||||
current_content=CurrentContent(
|
||||
**{
|
||||
"id": d.get("imageId"),
|
||||
"cover_id": d.get("coverId"),
|
||||
"synced": bool(d.get("synced")),
|
||||
}
|
||||
),
|
||||
slideshow={
|
||||
"mode": d.get("switchType"),
|
||||
"interval_minutes": d.get("switchMinute"),
|
||||
"members_available": False,
|
||||
"editable": False,
|
||||
},
|
||||
storage_used_bytes=d.get("sdUsedSize"),
|
||||
model_verified=bool(d.get("model") and d.get("modelCode")),
|
||||
last_seen_at=d.get("lastHeartbeat"),
|
||||
timezone=d.get("timezone", "Asia/Shanghai"),
|
||||
)
|
||||
|
||||
self.cached = result
|
||||
self.cached_at = time.monotonic()
|
||||
return result
|
||||
|
||||
def get_current_image(self):
|
||||
return self.device().current_content.id
|
||||
|
||||
def health(self):
|
||||
return bool(self.device())
|
||||
|
||||
def invalidate(self):
|
||||
self.cached_at = 0.0
|
||||
|
||||
def display_by_name(self, name):
|
||||
return self.client.display_by_name(name)
|
||||
|
||||
def images(self):
|
||||
data = self.sanitize(self.client.list_images())
|
||||
return [
|
||||
GalleryImage(
|
||||
image_id=d["id"],
|
||||
width=d.get("width"),
|
||||
height=d.get("height"),
|
||||
size_bytes=d.get("size"),
|
||||
media_type=d.get("type"),
|
||||
name=d.get("name", "image"),
|
||||
created_at=d.get("createdAt"),
|
||||
current=bool(d.get("current")),
|
||||
url=f"/api/v1/devices/{self.device_id}/images/{d['id']}/file",
|
||||
)
|
||||
for d in data.get("list", [])
|
||||
]
|
||||
|
||||
def upload(self, path, name):
|
||||
return self.client.upload(path, name)
|
||||
|
||||
def display(self, image_id):
|
||||
return self.client.display(image_id)
|
||||
|
||||
def delete(self, image_id):
|
||||
return self.client.delete(image_id)
|
||||
|
||||
def download(self, image_id):
|
||||
return self.client.download(image_id)
|
||||
Reference in New Issue
Block a user