Some improvements and fixes, and test file
This commit is contained in:
parent
8323c7a4be
commit
4f346f7534
3 changed files with 203 additions and 11 deletions
|
@ -52,7 +52,7 @@ class Engine:
|
||||||
)
|
)
|
||||||
del self.fixtures[id]
|
del self.fixtures[id]
|
||||||
|
|
||||||
def next(self, step_size: Decimal):
|
def step(self, step_size: Decimal):
|
||||||
"""Calculate light values for next step in time. Step size in seconds."""
|
"""Calculate light values for next step in time. Step size in seconds."""
|
||||||
if not self.is_running:
|
if not self.is_running:
|
||||||
raise BaseException("Cannot render next step, already finished all tracks.")
|
raise BaseException("Cannot render next step, already finished all tracks.")
|
||||||
|
@ -69,10 +69,10 @@ class Engine:
|
||||||
# Move track forward
|
# Move track forward
|
||||||
t.step(step_size)
|
t.step(step_size)
|
||||||
if t.current is None:
|
if t.current is None:
|
||||||
raise BaseException(f"Track has no current keyframe.")
|
continue # Track is not ready yet
|
||||||
|
|
||||||
# Interpolate and update value
|
# Interpolate and update value
|
||||||
interpolated_value = self.get_current_value(t)
|
interpolated_value = self._get_current_value(t)
|
||||||
|
|
||||||
# Update values of relevant fixtures
|
# Update values of relevant fixtures
|
||||||
for f in self.fixtures.values():
|
for f in self.fixtures.values():
|
||||||
|
@ -90,7 +90,7 @@ class Engine:
|
||||||
api = self.apis[f.fixture.api]
|
api = self.apis[f.fixture.api]
|
||||||
api.update_fixture(f)
|
api.update_fixture(f)
|
||||||
|
|
||||||
def get_current_value(self, track: EngineTrack) -> KeyframeValue:
|
def _get_current_value(self, track: EngineTrack) -> KeyframeValue:
|
||||||
"""Interpolate between current keyframes of track and return the interpolated value."""
|
"""Interpolate between current keyframes of track and return the interpolated value."""
|
||||||
current = track.current
|
current = track.current
|
||||||
if current is None:
|
if current is None:
|
||||||
|
@ -106,11 +106,11 @@ class Engine:
|
||||||
current.delta.copy_abs() + next.delta.copy_abs()
|
current.delta.copy_abs() + next.delta.copy_abs()
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.interpolate_value(
|
return self._interpolate_value(
|
||||||
current.frame.value, next.frame.value, t, current.frame.interpolation
|
current.frame.value, next.frame.value, t, current.frame.interpolation
|
||||||
)
|
)
|
||||||
|
|
||||||
def interpolate_value(
|
def _interpolate_value(
|
||||||
self,
|
self,
|
||||||
start: KeyframeValue,
|
start: KeyframeValue,
|
||||||
end: KeyframeValue,
|
end: KeyframeValue,
|
||||||
|
@ -150,9 +150,9 @@ class Engine:
|
||||||
case Interpolation.SMOOTHSTEP:
|
case Interpolation.SMOOTHSTEP:
|
||||||
f = t * t * (3 - 2 * t)
|
f = t * t * (3 - 2 * t)
|
||||||
case Interpolation.BOUNCE:
|
case Interpolation.BOUNCE:
|
||||||
f = self.bounce_out(float(t))
|
f = self._bounce_out(float(t))
|
||||||
case Interpolation.ELASTIC:
|
case Interpolation.ELASTIC:
|
||||||
f = self.elastic_out(t)
|
f = self._elastic_out(t)
|
||||||
case _:
|
case _:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
f"Unhandled interpolation type [{interpolation}]. Using STEP."
|
f"Unhandled interpolation type [{interpolation}]. Using STEP."
|
||||||
|
@ -161,7 +161,7 @@ class Engine:
|
||||||
|
|
||||||
raise BaseException("Unreachable code reached.")
|
raise BaseException("Unreachable code reached.")
|
||||||
|
|
||||||
def bounce_out(self, t: float) -> float:
|
def _bounce_out(self, t: float) -> float:
|
||||||
"""CHATGPT. Bounce easing function (out)."""
|
"""CHATGPT. Bounce easing function (out)."""
|
||||||
n1, d1 = 7.5625, 2.75
|
n1, d1 = 7.5625, 2.75
|
||||||
if t < 1 / d1:
|
if t < 1 / d1:
|
||||||
|
@ -176,7 +176,7 @@ class Engine:
|
||||||
t -= 2.625 / d1
|
t -= 2.625 / d1
|
||||||
return n1 * t * t + 0.984375
|
return n1 * t * t + 0.984375
|
||||||
|
|
||||||
def elastic_out(self, t: Decimal) -> float:
|
def _elastic_out(self, t: Decimal) -> float:
|
||||||
"""CHATGPT. Elastic easing function (out)."""
|
"""CHATGPT. Elastic easing function (out)."""
|
||||||
c4 = (2 * math.pi) / 3
|
c4 = (2 * math.pi) / 3
|
||||||
if t == 0:
|
if t == 0:
|
||||||
|
|
|
@ -26,7 +26,7 @@ class HueApi(FlickrApiInterface):
|
||||||
command["sat"] = fixture.brightness * 255
|
command["sat"] = fixture.brightness * 255
|
||||||
command["hue"] = fixture.hue * 65535
|
command["hue"] = fixture.hue * 65535
|
||||||
if fixture.fixture.capabilities in [Capabilities.TEMPERATURE]:
|
if fixture.fixture.capabilities in [Capabilities.TEMPERATURE]:
|
||||||
command["ct"] = fixture.temperature
|
command["ct"] = fixture.temperature / 10
|
||||||
|
|
||||||
# Apply update
|
# Apply update
|
||||||
self.bridge.set_light(fixture.fixture.api_id, command)
|
self.bridge.set_light(fixture.fixture.api_id, command)
|
||||||
|
|
192
src/test.ipynb
Normal file
192
src/test.ipynb
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 13,
|
||||||
|
"id": "1177b81b",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from phue import Bridge, Light\n",
|
||||||
|
"\n",
|
||||||
|
"ip = \"192.168.178.85\"\n",
|
||||||
|
"b = Bridge(ip)\n",
|
||||||
|
"b.connect()\n",
|
||||||
|
"# b.get_api()\n",
|
||||||
|
"\n",
|
||||||
|
"l: Light = b.get_light_objects(\"id\")[1]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 23,
|
||||||
|
"id": "1171ac4d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"l.brightness = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "03e74b50",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from models import Flickr, Interpolation, Space, Fixture, Capabilities, SpaceVector, Sequence, Track, Parameter, Keyframe\n",
|
||||||
|
"from decimal import Decimal\n",
|
||||||
|
"\n",
|
||||||
|
"f = Flickr(\n",
|
||||||
|
" [\n",
|
||||||
|
" Space(\n",
|
||||||
|
" \"max\",\n",
|
||||||
|
" \"Max' Room\",\n",
|
||||||
|
" [\n",
|
||||||
|
" Fixture(\n",
|
||||||
|
" \"stehlampe\",\n",
|
||||||
|
" \"Stehlampe\",\n",
|
||||||
|
" \"hue\",\n",
|
||||||
|
" \"1\",\n",
|
||||||
|
" Capabilities.COLOR,\n",
|
||||||
|
" SpaceVector(),\n",
|
||||||
|
" SpaceVector(),\n",
|
||||||
|
" SpaceVector(),\n",
|
||||||
|
" 0.5,\n",
|
||||||
|
" )\n",
|
||||||
|
" ],\n",
|
||||||
|
" )\n",
|
||||||
|
" ],\n",
|
||||||
|
" [\n",
|
||||||
|
" Sequence(\n",
|
||||||
|
" \"test\",\n",
|
||||||
|
" \"test\",\n",
|
||||||
|
" [\n",
|
||||||
|
" Track(\n",
|
||||||
|
" \"switch\",\n",
|
||||||
|
" \"Switch\",\n",
|
||||||
|
" Parameter.ON,\n",
|
||||||
|
" [\"1\"],\n",
|
||||||
|
" [Keyframe(Decimal.from_float(0), True)],\n",
|
||||||
|
" ),\n",
|
||||||
|
" Track(\n",
|
||||||
|
" \"bri\",\n",
|
||||||
|
" \"Brightness\",\n",
|
||||||
|
" Parameter.BRIGHTNESS,\n",
|
||||||
|
" [\"1\"],\n",
|
||||||
|
" [\n",
|
||||||
|
" Keyframe(Decimal.from_float(0), 1),\n",
|
||||||
|
" Keyframe(Decimal.from_float(1), 0),\n",
|
||||||
|
" Keyframe(Decimal.from_float(2), 0, Interpolation.LINEAR),\n",
|
||||||
|
" Keyframe(Decimal.from_float(3), 1, Interpolation.LINEAR),\n",
|
||||||
|
" Keyframe(Decimal.from_float(4), 0, Interpolation.EASE_IN_OUT),\n",
|
||||||
|
" Keyframe(Decimal.from_float(5), 1, Interpolation.EASE_IN_OUT),\n",
|
||||||
|
" Keyframe(Decimal.from_float(6), 0, Interpolation.EXPONENTIAL),\n",
|
||||||
|
" Keyframe(Decimal.from_float(7), 1, Interpolation.EXPONENTIAL),\n",
|
||||||
|
" Keyframe(Decimal.from_float(8), 0),\n",
|
||||||
|
" Keyframe(Decimal.from_float(9), 0.5),\n",
|
||||||
|
" ],\n",
|
||||||
|
" ),\n",
|
||||||
|
" Track(\n",
|
||||||
|
" \"hue\",\n",
|
||||||
|
" \"Hue\",\n",
|
||||||
|
" Parameter.HUE,\n",
|
||||||
|
" [\"1\"],\n",
|
||||||
|
" [\n",
|
||||||
|
" Keyframe(Decimal.from_float(0), 0),\n",
|
||||||
|
" Keyframe(Decimal.from_float(9), 0, Interpolation.LINEAR),\n",
|
||||||
|
" Keyframe(Decimal.from_float(15), 1),\n",
|
||||||
|
" ],\n",
|
||||||
|
" ),\n",
|
||||||
|
" Track(\n",
|
||||||
|
" \"sat\",\n",
|
||||||
|
" \"Sat\",\n",
|
||||||
|
" Parameter.SATURATION,\n",
|
||||||
|
" [\"1\"],\n",
|
||||||
|
" [\n",
|
||||||
|
" Keyframe(Decimal.from_float(0), 0),\n",
|
||||||
|
" Keyframe(Decimal.from_float(9), 1),\n",
|
||||||
|
" ],\n",
|
||||||
|
" )\n",
|
||||||
|
" ],\n",
|
||||||
|
" )\n",
|
||||||
|
" ],\n",
|
||||||
|
" )"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 24,
|
||||||
|
"id": "c51314e4",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"WARNING:phue:ERROR: resource, /lights/False/state, not available for light 1\n",
|
||||||
|
"WARNING:phue:ERROR: resource, /lights/False/state, not available for light 1\n",
|
||||||
|
"WARNING:phue:ERROR: resource, /lights/False/state, not available for light 1\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Done.\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"from engine import Engine\n",
|
||||||
|
"from hue import HueApi\n",
|
||||||
|
"from models import FlickrApiInterface\n",
|
||||||
|
"from time import time, sleep\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"apis: dict[str, FlickrApiInterface] = {\n",
|
||||||
|
" \"hue\": HueApi(ip)\n",
|
||||||
|
"}\n",
|
||||||
|
"\n",
|
||||||
|
"engine = Engine(f, apis)\n",
|
||||||
|
"\n",
|
||||||
|
"engine.load_sequence(\"test\")\n",
|
||||||
|
"\n",
|
||||||
|
"previous_time = None\n",
|
||||||
|
"while engine.is_running:\n",
|
||||||
|
" curr_time = time()\n",
|
||||||
|
" if previous_time is None:\n",
|
||||||
|
" previous_time = curr_time\n",
|
||||||
|
" step = curr_time - previous_time\n",
|
||||||
|
" previous_time = curr_time\n",
|
||||||
|
" \n",
|
||||||
|
" engine.step(Decimal.from_float(step))\n",
|
||||||
|
" engine.propagate()\n",
|
||||||
|
" sleep(0.2)\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Done.\") \n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": ".venv",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.12.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
Loading…
Reference in a new issue