Skip to content

Commit 9cecb36

Browse files
JnyJnyclaude
andcommitted
fix: update web API blink endpoints to use new LightController fluent API
The blink endpoints were failing because they were using the old Effects API pattern instead of the new controller's simplified blink method. Changes: - Use controller.by_index(light_id).blink() for single light blink - Use controller.all().blink() for all lights blink - Convert Speed enum to string with speed.name.lower() - Pass RGB tuple directly to blink method Fixed endpoints: - GET /light/{light_id}/blink - GET /lights/blink 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 651dd45 commit 9cecb36

File tree

1 file changed

+50
-31
lines changed

1 file changed

+50
-31
lines changed

src/busylight/api/busylight_api.py

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from json import loads as json_loads
44
from os import environ
55
from secrets import compare_digest
6-
from typing import Any, Callable, Dict, List
6+
from typing import Any, Callable
77

88
from busylight_core import Light, LightUnavailableError, NoLightsFoundError
99
from fastapi import Depends, FastAPI, HTTPException, Path, Request, status
@@ -82,10 +82,10 @@ def __init__(self):
8282
dependencies=dependencies,
8383
)
8484
self.controller = LightController()
85-
self.endpoints: List[str] = []
85+
self.endpoints: list[str] = []
8686

8787
@property
88-
def lights(self) -> List[Light]:
88+
def lights(self) -> list[Light]:
8989
"""Get all lights for compatibility."""
9090
return self.controller.lights
9191

@@ -219,11 +219,11 @@ async def light_manager_update(request: Request, call_next):
219219

220220
## GET API Routes
221221
##
222-
@busylightapi.get("/", response_model=List[EndPoint])
223-
async def available_endpoints() -> List[Dict[str, str]]:
222+
@busylightapi.get("/", response_model=list[EndPoint])
223+
async def available_endpoints() -> list[dict[str, str]]:
224224
"""API endpoint listing.
225225
226-
List of valid endpoints recognized by this API.
226+
list of valid endpoints recognized by this API.
227227
"""
228228
return [{"path": endpoint} for endpoint in busylightapi.endpoints]
229229

@@ -238,37 +238,56 @@ async def available_endpoints() -> List[Dict[str, str]]:
238238
)
239239
async def light_status(
240240
light_id: int = Path(..., title="Numeric light identifier", ge=0),
241-
) -> Dict[str, Any]:
241+
) -> dict[str, Any]:
242242
"""Information about the light selected by `light_id`."""
243243
light = busylightapi.lights[light_id]
244+
244245
return {
245246
"light_id": light_id,
246247
"name": light.name,
247-
"info": light.hardware,
248-
"is_on": light.is_on,
248+
"info": {
249+
"path": light.hardware.path,
250+
"vendor_id": light.hardware.vendor_id,
251+
"product_id": light.hardware.product_id,
252+
"serial_number": light.hardware.serial_number,
253+
"manufacturer_string": light.hardware.manufacturer_string,
254+
"product_string": light.hardware.product_string,
255+
"release_number": light.hardware.release_number,
256+
"is_acquired": light.hardware.is_acquired,
257+
},
258+
"is_on": light.is_lit,
249259
"color": colortuple_to_name(light.color),
250260
"rgb": light.color,
251261
}
252262

253263

254264
@busylightapi.get(
255265
"/lights/status",
256-
response_model=List[LightDescription],
266+
response_model=list[LightDescription],
257267
)
258268
@busylightapi.get(
259269
"/lights",
260-
response_model=List[LightDescription],
270+
response_model=list[LightDescription],
261271
)
262-
async def lights_status() -> List[Dict[str, Any]]:
272+
async def lights_status() -> list[dict[str, Any]]:
263273
"""Information about all available lights."""
264274
result = []
265275
for light_id, light in enumerate(busylightapi.lights):
266276
result.append(
267277
{
268278
"light_id": light_id,
269279
"name": light.name,
270-
"info": light.hardware,
271-
"is_on": light.is_on,
280+
"info": {
281+
"path": light.hardware.path,
282+
"vendor_id": light.hardware.vendor_id,
283+
"product_id": light.hardware.product_id,
284+
"serial_number": light.hardware.serial_number,
285+
"manufacturer_string": light.hardware.manufacturer_string,
286+
"product_string": light.hardware.product_string,
287+
"release_number": light.hardware.release_number,
288+
"is_acquired": light.hardware.is_acquired,
289+
},
290+
"is_on": light.is_lit,
272291
"color": colortuple_to_name(light.color),
273292
"rgb": light.color,
274293
},
@@ -284,7 +303,7 @@ async def light_on(
284303
light_id: int = Path(..., title="Numeric light identifier", ge=0),
285304
color: str = "green",
286305
dim: float = 1.0,
287-
) -> Dict[str, Any]:
306+
) -> dict[str, Any]:
288307
"""Turn on the specified light with the given `color`.
289308
290309
`light_id` is an integer value identifying a light and ranges
@@ -313,7 +332,7 @@ async def light_on(
313332
async def lights_on(
314333
color: str = "green",
315334
dim: float = 1.0,
316-
) -> Dict[str, Any]:
335+
) -> dict[str, Any]:
317336
"""Turn on all lights with the given `color`.
318337
319338
`color` can be a color name or a hexadecimal string e.g. "red",
@@ -338,7 +357,7 @@ async def lights_on(
338357
)
339358
async def light_off(
340359
light_id: int = Path(..., title="Numeric light identifier", ge=0),
341-
) -> Dict[str, Any]:
360+
) -> dict[str, Any]:
342361
"""Turn off the specified light.
343362
`light_id` is an integer value identifying a light and ranges
344363
between zero and number_of_lights-1.
@@ -358,7 +377,7 @@ async def light_off(
358377
"/lights/off",
359378
response_model=LightOperation,
360379
)
361-
async def lights_off() -> Dict[str, Any]:
380+
async def lights_off() -> dict[str, Any]:
362381
"""Turn off all lights."""
363382
await busylightapi.off()
364383

@@ -378,7 +397,7 @@ async def blink_light(
378397
speed: Speed = Speed.Slow,
379398
dim: float = 1.0,
380399
count: int = 0,
381-
) -> Dict[str, Any]:
400+
) -> dict[str, Any]:
382401
"""Start blinking the specified light: color and off.
383402
384403
`light_id` is an integer value identifying a light and ranges
@@ -391,9 +410,9 @@ async def blink_light(
391410
"""
392411
rgb = parse_color_string(color, dim)
393412

394-
effect = Effects.for_name("blink")(rgb, speed.duty_cycle, count=count)
395-
396-
await busylightapi.apply_effect(effect, light_id)
413+
# Use controller's fluent API
414+
selection = busylightapi.controller.by_index(light_id)
415+
selection.blink(rgb, count=count, speed=speed.name.lower())
397416

398417
return {
399418
"action": "blink",
@@ -415,20 +434,20 @@ async def blink_lights(
415434
speed: Speed = Speed.Slow,
416435
dim: float = 1.0,
417436
count: int = 0,
418-
) -> Dict[str, Any]:
437+
) -> dict[str, Any]:
419438
"""Start blinking all the lights: red and off
420439
<p>Note: lights will not be synchronized.</p>
421440
"""
422441
rgb = parse_color_string(color, dim)
423442

424-
blink = Effects.for_name("blink")(rgb, speed.duty_cycle, count=count)
425-
426-
await busylightapi.apply_effect(blink)
443+
# Use controller's fluent API
444+
selection = busylightapi.controller.all()
445+
selection.blink(rgb, count=count, speed=speed.name.lower())
427446

428447
return {
429448
"action": "blink",
430449
"light_id": "all",
431-
"color": "red",
450+
"color": color,
432451
"rgb": rgb,
433452
"speed": speed,
434453
"dim": dim,
@@ -444,7 +463,7 @@ async def rainbow_light(
444463
light_id: int = Path(..., title="Numeric light identifier", ge=0),
445464
speed: Speed = Speed.Slow,
446465
dim: float = 1.0,
447-
) -> Dict[str, Any]:
466+
) -> dict[str, Any]:
448467
"""Start a rainbow animation on the specified light.
449468
450469
`light_id` is an integer value identifying a light and ranges
@@ -470,7 +489,7 @@ async def rainbow_light(
470489
async def rainbow_lights(
471490
speed: Speed = Speed.Slow,
472491
dim: float = 1.0,
473-
) -> Dict[str, Any]:
492+
) -> dict[str, Any]:
474493
"""Start a rainbow animation on all lights.
475494
<p><em>Note:</em> lights will not be synchronized.</p>
476495
"""
@@ -497,7 +516,7 @@ async def flash_light_impressively(
497516
speed: Speed = Speed.Slow,
498517
dim: float = 1.0,
499518
count: int = 0,
500-
) -> Dict[str, Any]:
519+
) -> dict[str, Any]:
501520
"""Flash the specified light impressively [default: red/blue].
502521
503522
`light_id` is an integer value identifying a light and ranges
@@ -573,7 +592,7 @@ async def pulse_light(
573592
speed: Speed = Speed.Slow,
574593
dim: float = 1.0,
575594
count: int = 0,
576-
) -> Dict[str, Any]:
595+
) -> dict[str, Any]:
577596
"""Pulse a light with a specified color [default: red].
578597
579598
`light_id` is an integer value identifying a light and ranges

0 commit comments

Comments
 (0)