Created
January 22, 2021 08:40
-
-
Save tobyink/62a6d7a994573f3f7dc83acc5754d4d7 to your computer and use it in GitHub Desktop.
Cycles a list of Philips Hue light bulbs through a gradient of colours
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use v5.16; | |
use warnings; | |
package ColourSet { | |
use Moo; | |
use Types::Standard -types; | |
has initial => ( | |
is => 'ro', | |
isa => ArrayRef, | |
required => 1, | |
); | |
has colours => ( | |
is => 'lazy', | |
isa => ArrayRef, | |
); | |
sub _build_colours { | |
my ( $self ) = ( shift ); | |
my @colours = @{ $self->initial }; | |
for my $depth ( 0 .. 4 ) { | |
push @colours, $self->initial->[0]; | |
my @temp; | |
for my $ix ( 0 .. $#colours - 1 ) { | |
my $x = $colours[$ix]; | |
my $y = $colours[$ix+1]; | |
push @temp, $x, $self->_blend( $x, $y ); | |
} | |
@colours = @temp; | |
} | |
\@colours; | |
} | |
sub _blend { | |
my ( $self, $alpha, $beta ) = ( shift, @_ ); | |
my @hexStart = ( $alpha =~ /^#?(..)(..)(..)$/i ); | |
my @hexEnd = ( $beta =~ /^#?(..)(..)(..)$/i ); | |
my @decStart = ( | |
hex( "0x" . $hexStart[0] ), | |
hex( "0x" . $hexStart[1] ), | |
hex( "0x" . $hexStart[2] ), | |
); | |
my @decEnd = ( | |
hex( "0x" . $hexEnd[0] ), | |
hex( "0x" . $hexEnd[1] ), | |
hex( "0x" . $hexEnd[2] ), | |
); | |
my $avRed = int( ( $decStart[0] + $decEnd[0] ) / 2 ); | |
my $avGrn = int( ( $decStart[1] + $decEnd[1] ) / 2 ); | |
my $avBlu = int( ( $decStart[2] + $decEnd[2] ) / 2 ); | |
# And convert the averages back into hex. | |
sprintf '#%02x%02x%02x', $avRed, $avGrn, $avBlu; | |
} | |
} | |
package Light { | |
use Moo; | |
use Types::Standard -types; | |
has id => ( | |
is => 'ro', | |
isa => Int, | |
required => 1, | |
); | |
sub on { | |
my ( $self ) = ( shift ); | |
system 'hueadm', 'light', $self->id, 'on'; | |
} | |
sub off { | |
my ( $self ) = ( shift ); | |
system 'hueadm', 'light', $self->id, 'off'; | |
} | |
sub colour { | |
my ( $self, $colour, $brightness ) = ( shift, @_ ); | |
$brightness //= '254'; | |
$brightness = "=$brightness" unless $brightness =~ /^[+=-]/; | |
system 'hueadm', 'light', $self->id, $colour, "bri$brightness"; | |
} | |
} | |
package MyEffect { | |
use Moo; | |
use Types::Standard -types; | |
has lights => ( | |
is => 'ro', | |
isa => ArrayRef, | |
required => 1, | |
); | |
has colours => ( | |
is => 'ro', | |
isa => Object->plus_coercions( | |
ArrayRef, sub { 'ColourSet'->new( initial => $_ ) }, | |
), | |
required => 1, | |
coerce => 1, | |
); | |
sub do_cycle { | |
my ( $self, $brightness, $pause, $gap ) = ( shift, @_ ); | |
my $length = @{ $self->colours->colours }; | |
$gap //= ( $length / 10 ); | |
my @indices = map { $gap * $_ } 0 .. $#{ $self->lights }; | |
while ( 1 ) { | |
@indices = map $_ % $length, @indices; | |
for my $ix ( 0 .. $#indices ) { | |
my $colour = $self->colours->colours->[ $indices[$ix] ]; | |
say "Setting light $ix to $colour..."; | |
$self->lights->[$ix]->colour( $colour, $brightness ); | |
} | |
++$_ for @indices; | |
sleep $pause; | |
} | |
} | |
} | |
'MyEffect'->new( | |
lights => [ | |
'Light'->new( id => 8 ), | |
'Light'->new( id => 4 ), | |
'Light'->new( id => 13 ), | |
], | |
colours => [ | |
'#FFEFAE', | |
'#F50002', | |
'#FFA8F3', | |
'#C70271', | |
'#FFB6AE', | |
], | |
)->do_cycle( '=64', 2 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment