Berry animation update dec 23 (#24250)

* Remove tab from json

* Berry animation updates
This commit is contained in:
s-hadinger 2025-12-23 18:39:13 +01:00 committed by GitHub
parent cf99f647f7
commit 7536fb7eb6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 4988 additions and 5131 deletions

View File

@ -22,7 +22,9 @@ The DSL **transpiles to standard Berry code**, so you get the best of both world
Test and create animations without a Tasmota device using the online emulator:
**[https://tasmota.github.io/docs/Tasmota-Berry-emulator/](https://tasmota.github.io/docs/Tasmota-Berry-emulator/index.html)**
[![Tasmota_Berry_LED_emulator](berry_animation_docs/emulator_screenshot.png){width=353}](https://tasmota.github.io/docs/Tasmota-Berry-emulator/index.html){target=_blank}
**[https://tasmota.github.io/docs/Tasmota-Berry-emulator/](https://tasmota.github.io/docs/Tasmota-Berry-emulator/index.html){target=_blank}**
The emulator runs **entirely in your browser** with no server required. It includes:

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

View File

@ -64,15 +64,6 @@ class RichPaletteAnimation : animation.animation
self.color_provider.start(start_time)
return self
end
# String representation
def tostring()
try
return f"RichPaletteAnimation(cycle_period={self.cycle_period}, brightness={self.brightness})"
except ..
return "RichPaletteAnimation(uninitialized)"
end
end
end
return {'rich_palette_animation': RichPaletteAnimation}

View File

@ -156,7 +156,7 @@ class Animation : animation.parameterized_object
# String representation of the animation
def tostring()
return f"Animation(priority={self.priority}, duration={self.duration}, loop={self.loop}, running={self.is_running})"
return f"{classname(self)}(priority={self.priority})"
end
end

View File

@ -20,13 +20,7 @@ class ColorCycleColorProvider : animation.color_provider
# Parameter definitions
static var PARAMS = animation.enc_params({
"palette": {"type": "bytes", "default":
bytes( # Palette bytes in AARRGGBB format
"FF0000FF" # Blue
"FF00FF00" # Green
"FFFF0000" # Red
)
},
"palette": {"type": "bytes", "default":nil},
"cycle_period": {"min": 0, "default": 5000}, # 0 = manual only, >0 = auto cycle time in ms
"next": {"default": 0}, # Write `<n>` to move to next <n> colors
"palette_size": {"type": "int", "default": 3} # Read-only: number of colors in palette
@ -38,8 +32,10 @@ class ColorCycleColorProvider : animation.color_provider
def init(engine)
super(self).init(engine) # Initialize parameter system
# Set the default palette
self.palette = animation.PALETTE_RAINBOW
# Initialize non-parameter instance variables
var palette_bytes = self.palette
self.current_index = 0 # Start at first color
# Initialize palette_size parameter

View File

@ -62,6 +62,9 @@ class RichPaletteColorProvider : animation.color_provider
import global
self._light_state = global.light_state(global.light_state.RGB)
# Set default palette to animation.PALETTE_RAINBOW
self.palette = animation.PALETTE_RAINBOW
# We need to register this value provider to receive 'update()'
engine.add(self)
end
@ -524,29 +527,4 @@ class RichPaletteColorProvider : animation.color_provider
end
end
# Factory function for rainbow palette (reusing format from Animate_palette)
#
# @param engine: AnimationEngine - Animation engine reference
# @return RichPaletteColorProvider - A new rich palette color provider instance with rainbow palette
def rich_palette_rainbow(engine)
# Standard rainbow palette (exact format from Animate_palette examples)
var palette_bytes = bytes(
"00FF0000" # Red (value 0)
"24FFA500" # Orange (value 36)
"49FFFF00" # Yellow (value 73)
"6E00FF00" # Green (value 110)
"920000FF" # Blue (value 146)
"B74B0082" # Indigo (value 183)
"DBEE82EE" # Violet (value 219)
"FFFF0000" # Red (value 255)
)
# Create provider with rainbow palette and default parameters
var provider = animation.rich_palette(engine)
provider.palette = palette_bytes
return provider
end
return {'rich_palette': RichPaletteColorProvider,
'rich_palette_rainbow': rich_palette_rainbow}
return {'rich_palette': RichPaletteColorProvider}

File diff suppressed because it is too large Load Diff

View File

@ -28,16 +28,7 @@ def test_color_cycle_bytes_format()
# Test 2: Check default palette
var default_size = provider._get_palette_size()
assert(default_size == 3, f"Default palette should have 3 colors, got {default_size}")
# Test 3: Test colors from default palette (AARRGGBB format)
var color0 = provider._get_color_at_index(0) # Should be FF0000FF (blue)
var color1 = provider._get_color_at_index(1) # Should be FF00FF00 (green)
var color2 = provider._get_color_at_index(2) # Should be FFFF0000 (red)
assert(color0 == 0xFF0000FF, f"First color should be blue (0xFF0000FF), got 0x{color0:08X}")
assert(color1 == 0xFF00FF00, f"Second color should be green (0xFF00FF00), got 0x{color1:08X}")
assert(color2 == 0xFFFF0000, f"Third color should be red (0xFFFF0000), got 0x{color2:08X}")
assert(default_size == 7, f"Default palette should have 7 colors, got {default_size}")
# Test 4: Set custom bytes palette
var custom_palette = bytes(
@ -146,10 +137,6 @@ def test_bytes_parameter_validation()
assert(caught_error, f"Should reject {type(invalid_val)}: {invalid_val}")
end
# Test 3: Nil should be accepted (uses default)
provider.palette = nil
assert(provider.palette_size == 3, "Nil should use default palette")
print("✓ All bytes parameter validation tests passed!")
end

View File

@ -47,7 +47,6 @@ class RichPaletteAnimationTest
self.test_initialization()
self.test_update_and_render()
self.test_factory_method()
self.test_palette_properties()
self.test_css_gradient()
self.test_cycle_period_zero()
@ -165,30 +164,6 @@ class RichPaletteAnimationTest
self.assert_equal(middle_color != 0, true, "Middle color is valid")
end
def test_factory_method()
# Test the rainbow factory method
var provider = animation.rich_palette_rainbow(mock_engine)
provider.cycle_period = 5000
provider.brightness = 255
var anim = animation.solid(mock_engine)
anim.color = provider
anim.priority = 10 # Priority 10
# Check that the animation was created correctly
self.assert_equal(anim != nil, true, "Animation was created")
self.assert_equal(anim.render != nil, true, "Animation has render method")
self.assert_equal(type(anim.color) == 'int', true, "Color is resolved to integer")
# Check provider properties directly on the provider object
self.assert_equal(provider.cycle_period, 5000, "Cycle period is 5000ms")
self.assert_equal(provider.transition_type, animation.LINEAR, "Default transition type is linear")
self.assert_equal(provider.brightness, 255, "Brightness is 255")
# Check animation properties
self.assert_equal(anim.priority, 10, "Priority is 10")
end
def test_palette_properties()
# Test palette properties and value-based color generation
var palette = bytes("00FF0000" "80FFFF00" "FF0000FF") # Red to Yellow to Blue