Skip to content

Commit

Permalink
Syncing 2020 changes
Browse files Browse the repository at this point in the history
  • Loading branch information
hplato committed Dec 29, 2020
1 parent 18470d0 commit 2601dae
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 80 deletions.
129 changes: 114 additions & 15 deletions lib/Nanoleaf_Aurora.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package Nanoleaf_Aurora;

# v1.1.01
# v2.0

#if any effect is changed, by definition the static child should be set to off.
#cmd data returns, need to check by command
Expand Down Expand Up @@ -43,6 +43,17 @@ use IO::Socket::INET;
# $aurora_static1 = new Nanoleaf_Aurora_Static($aurora, "effect string");
# $aurora_comm = new Nanoleaf_Aurora_Comm($aurora);

#Set static string, ie "3 82 1 255 0 255 0 20 60 1 0 255 255 0 20 118 1 0 0 0 0 20",

#<nPanels> = 3
#<numFrames> = 1
#Panel 1:
#PanelId: 82, R:255, G:0, B:255, W:0, TransitionTime:20*0.1s
#Panel 2:
#PanelId: 60, R:0, G:255, B:255, W:0, TransitionTime:20*0.1s
#Panel 3:
#PanelId:118, R:0, G:0, B:0, W:0, TransitionTime:20*0.1s

# MH.INI settings
# If the token is auto generated, it will be written to the mh.ini. MH.INI settings can be used
# instead of object definitions
Expand Down Expand Up @@ -88,27 +99,32 @@ $rest{off} = "state";
#$rest{set_effect} = "effects/select";
$rest{set_effect} = "effects";
$rest{set_static} = "effects";
$rest{set_hsb} = "effects";
#$rest{brightness} = "state/brightness";
#$rest{brightness2} = "state/brightness";
$rest{brightness} = "state";
$rest{brightness2} = "state";
$rest{get_static} = "effects";
$rest{get_hsb} = "effects";
$rest{identify} = "identify";

our %opts;
$opts{info} = "-ua";
$opts{auth} = "-json -post '{}'";
$opts{on} = "-response_code -json -put '{\"on\":true}'";
$opts{off} = "-response_code -json -put '{\"on\":false}'";
$opts{on} = "-response_code -json -put '{\"on\":{\"value\":true}}'";
$opts{off} = "-response_code -json -put '{\"on\":{\"value\":false}}'";
$opts{set_effect} = "-response_code -json -put '{\"select\":";
$opts{set_static} = "-response_code -json -put '{\"write\":{\"command\":\"display\",\"version\":\"1.0\",\"animType\":\"static\",\"animData\":";
$opts{set_hsb} = "-response_code -json -put '{\"write\":{\"command\":\"display\",\"version\":\"1.0\",\"animType\":\"solid\",\"palette\":";
#$opts{brightness} = "-response_code -json -put '{\"value\":";
#$opts{brightness2} = "-response_code -json -put '{\"increment\":";
$opts{brightness} = "-response_code -json -put '{\"brightness\":{\"value\":";
$opts{brightness2} = "-response_code -json -put '{\"brightness\":{\"increment\":";
$opts{get_static} = "-response_code -json -put '{\"write\":{\"command\":\"request\",\"version\":\"1.0\",\"animName\":\"*Static*\"}}'";
$opts{get_hsb} = "-response_code -json -put '{\"write\":{\"command\":\"request\",\"version\":\"1.0\",\"animName\":\"*Solid*\"}}'";
$opts{identify} = "-response_code -json -put '{}'";


my $api_path = "/api/v1";
our %active_auroras = ();

Expand All @@ -129,7 +145,7 @@ sub new {
$self->{updating} = 0;
$self->{data}->{retry} = 0;
$self->{status} = "";
$self->{module_version} = "v1.1.01";
$self->{module_version} = "v1.2.01";
$self->{ssdp_timeout} = 4000;
$self->{last_static} = "";

Expand Down Expand Up @@ -164,7 +180,7 @@ sub new {
$self->{poll_process}->set_output( $self->{poll_data_file} );
@{ $self->{cmd_queue} } = ();
$self->{cmd_data_file} = "$::config_parms{data_dir}/Aurora_cmd_" . $self->{name} . ".data";
unlink "$::config_parms{data_dir}/Auroroa_cmd_" . $self->{name} . ".data";
unlink "$::config_parms{data_dir}/Aurora_cmd_" . $self->{name} . ".data";
$self->{cmd_process} = new Process_Item;
$self->{cmd_process}->set_output( $self->{cmd_data_file} );
$self->{init} = 0;
Expand Down Expand Up @@ -369,7 +385,7 @@ sub process_check {
main::print_log( "[Aurora:" . $self->{name} . "] Background Command " . $self->{cmd_process_mode} . " process completed" )
if ( $self->{debug} );
$self->get_data(); #poll since the command is done to get a new state

$self->{data}->{info}->{palette} = 0; #assume this is not a solid effect change.
my $file_data = &main::file_read( $self->{cmd_data_file} );

my ($responsecode) = $file_data =~ /^RESPONSECODE:(\d+)\n/;
Expand All @@ -379,7 +395,7 @@ sub process_check {
#print "success\n\n" if (($responsecode == 204) or ($responsecode == 200));
my $com_status = "offline";

if ( ( $responsecode == 204 ) or ( $responsecode == 200 ) ) {
if ( ( $responsecode == 204 ) or ( $responsecode == 200 ) or ( $responsecode == 404) ) { #added 404 since a few calls can generate 404 if the data isn't present (like querying static without a static scene active)
$com_status = "online";

# Successful commands should be [200 OK, 204 No Content]
Expand Down Expand Up @@ -422,6 +438,24 @@ sub process_check {
}

}
if ( $self->{cmd_process_mode} eq "get_hsb" ) {
main::print_log( "[Aurora:" . $self->{name} . "] get_hsb returned" );
#strangely, this query has proper hue/sat/brightness information and the general query doesn't
#TODO, figure out brightness when a solid
#print Dumper $data->{palette};
for ( my $i = 0; $i < @{$data->{palette}}; $i++ ) {
$self->{data}->{info}->{brightness}->{value2} .= ${$data->{palette}}[$i]->{brightness} . ",";
$self->{data}->{info}->{saturation}->{value2} .= ${$data->{palette}}[$i]->{saturation} . ",";
$self->{data}->{info}->{hue}->{value2} = ${$data->{palette}}[$i]->{hue} . ",";
}
chop($self->{data}->{info}->{brightness}->{value2});
chop($self->{data}->{info}->{saturation}->{value2});
chop($self->{data}->{info}->{hue}->{value2});
#print "B=".$self->{data}->{info}->{brightness}->{value2}." S=".$self->{data}->{info}->{saturation}->{value2}."H=".$self->{data}->{info}->{hue}->{value2} ."\n";
$self->{data}->{info}->{palette} = 1;

}

}

$self->poll;
Expand Down Expand Up @@ -721,7 +755,6 @@ sub print_info {
} else {
main::print_log( "[Aurora:" . $self->{name} . "] Rhythm Module: Not Present");
}
main::print_log( "[Aurora:" . $self->{name} . "] Firmware: " . $self->{data}->{info}->{firmwareVersion} );

main::print_log( "[Aurora:" . $self->{name} . "] Connected Panels: " . $self->{data}->{panels} );
main::print_log( "[Aurora:" . $self->{name} . "] Panel Size: " . $self->{data}->{panel_size} );
Expand All @@ -737,8 +770,22 @@ sub print_info {
else {
main::print_log( "[Aurora:" . $self->{name} . "] State:\t OFF" );
}
main::print_log(
"[Aurora:" . $self->{name} . "] Mode:\t " . $self->{data}->{info}->{state}->{colorMode} . " " . $self->{data}->{info}->{effects}->{select} );
main::print_log("[Aurora:" . $self->{name} . "] Mode:\t " . $self->{data}->{info}->{state}->{colorMode} . " " . $self->{data}->{info}->{effects}->{select} );

if ($self->{data}->{info}->{palette} == 1) {
main::print_log( "[Aurora:"
. $self->{name}
. "] Brightness:\t "
. $self->{data}->{info}->{state}->{brightness}->{value2});
main::print_log( "[Aurora:"
. $self->{name}
. "] Hue:\t\t "
. $self->{data}->{info}->{state}->{hue}->{value2});
main::print_log( "[Aurora:"
. $self->{name}
. "] Saturation:\t "
. $self->{data}->{info}->{state}->{sat}->{value2});
} else {
main::print_log( "[Aurora:"
. $self->{name}
. "] Brightness:\t "
Expand All @@ -760,12 +807,13 @@ sub print_info {
. $self->{data}->{info}->{state}->{sat}->{min} . "-"
. $self->{data}->{info}->{state}->{sat}->{max}
. "]" );
}
main::print_log( "[Aurora:"
. $self->{name}
. "] Color Temp:\t "
. $self->{data}->{info}->{state}->{brightness}->{value} . "\t["
. $self->{data}->{info}->{state}->{brightness}->{min} . "-"
. $self->{data}->{info}->{state}->{brightness}->{max}
. $self->{data}->{info}->{state}->{ct}->{value} . "\t["
. $self->{data}->{info}->{state}->{ct}->{min} . "-"
. $self->{data}->{info}->{state}->{ct}->{max}
. "]" );
main::print_log( "[Aurora:" . $self->{name} . "] -- Active Effects --" );
if ( defined $self->{data}->{info}->{effects}->{list} ) {
Expand Down Expand Up @@ -838,7 +886,11 @@ sub process_data {
}
$self->{init_data} = 1;
}

if (( lc $self->{data}->{info}->{effects}->{select} eq "*dynamic*" ) or ( lc $self->{data}->{info}->{effects}->{select} eq "*solid*" )) {
$self->{data}->{info}->{palette} = 1;
} else {
$self->{data}->{info}->{palette} = 0;
}
if ( $self->{previous}->{info}->{firmwareVersion} ne $self->{data}->{info}->{firmwareVersion} ) {
main::print_log(
"[Aurora:" . $self->{name} . "] Firmware changed from $self->{previous}->{info}->{firmwareVersion} to $self->{data}->{info}->{firmwareVersion}" );
Expand Down Expand Up @@ -1051,6 +1103,17 @@ sub set_static {

}

#TODO set hue and Saturation directly
sub set_hsb {
my ( $self, $hue, $saturation, $brightness ) = @_;

my $params = $opts{set_hsb} . '[{ "hue":' . $hue . ',"saturation":' . $saturation . ',"brightness":' . $brightness . "}],";
$params .= '"colorType": "HSB"}}' . "'";

$self->_push_JSON_data( 'set_hsb', $params );
return ('1');
}

sub check_static {
my ( $self, $string, $prev_effect ) = @_;

Expand Down Expand Up @@ -1083,6 +1146,39 @@ sub get_static {
return ('1');
}

sub get_hsb {
my ($self) = @_;

$self->_push_JSON_data('get_hsb');
return ('1');
}

sub hue {
my ( $self) = @_;
my $return = $self->{data}->{info}->{state}->{hue}->{value};
$return = $self->{data}->{info}->{state}->{hue}->{value2} if ($self->{data}->{info}->{palette} == 1);
return $return;
}

sub saturation {
my ( $self) = @_;
my $return = $self->{data}->{info}->{state}->{sat}->{value};
$return = $self->{data}->{info}->{state}->{sat}->{value2} if ($self->{data}->{info}->{palette} == 1);
return $return;
}

sub brightness {
my ( $self) = @_;
my $return = $self->{data}->{info}->{state}->{brightness}->{value};
$return = $self->{data}->{info}->{state}->{brightness}->{value2} if ($self->{data}->{info}->{palette} == 1);
return $return;
}

sub ct {
my ( $self) = @_;
return $self->{data}->{info}->{state}->{brightness}->{value}
}

sub print_discovery_info {
my ($self) = @_;

Expand Down Expand Up @@ -1227,6 +1323,7 @@ sub new {
$$self{loop} = 0;
$$self{string} = $static_string if ( defined $static_string );
$object->register( $self, 'static' );
$self->SUPER::set('off'); #turn off at initialization and then set when data comes in.
return $self;

}
Expand Down Expand Up @@ -1331,4 +1428,6 @@ sub set {
# v1.0.13 - ability to print and purge the command queue in case a network error prevents clearing, empty poll queue if max reached
# v1.0.14 - commands now queue properly
# v1.0.15 - fixed polling
# v1.1.01 - firmware v2.2.0 and rhythm module
# v1.1.01 - firmware v2.2.0 and rhythm module
# v1.1.03 - fixed a few typos
# v2.0.00 - added in hue/Saturation ability
9 changes: 7 additions & 2 deletions lib/http_server.pl
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,11 @@ sub http_process_request {

# print "Error, no SET argument: $header\n" unless $get_arg;

#allow setby to be passed in URL. Objects can then take a setby argument if there is an alternative action.
#used for RGB. Downside is that the true setby (web) would be lost.
my $get_arg_setby = "";
($get_arg_setby) = $get_arg =~ /select_setby=(\S+)/;
$get_arg =~ s/select_setby=(\S+)// if ($get_arg_setby);
# Change select_item=$item&select_state=abc to $item=abc
$get_arg =~ s/select_item=(\S+)\&&select_state=/$1=/;

Expand Down Expand Up @@ -758,10 +763,10 @@ sub http_process_request {

# Can be a scalar or a object
$state =~ tr/\"/\'/; # So we can use "" to quote it

$get_arg_setby = "web [$client_ip_address]" unless $get_arg_setby;
# my $eval_cmd = qq[($item and ref($item) and UNIVERSAL::isa($item, 'Generic_Item')) ?
my $eval_cmd = qq[($item and ref($item) ne '' and ref($item) ne 'SCALAR' and $item->can('set')) ?
($item->set("$state", "web [$client_ip_address]")) : ($item = "$state")];
($item->set("$state", "$get_arg_setby")) : ($item = "$state")];
print "SET eval: $eval_cmd\n" if $main::Debug{http};
eval $eval_cmd;
print "SET eval error. cmd=$eval_cmd error=$@\n" if $@;
Expand Down
48 changes: 37 additions & 11 deletions lib/json_server.pl
Original file line number Diff line number Diff line change
Expand Up @@ -883,34 +883,52 @@ sub json_get {
}

if ( $path[0] eq 'security' ) {
#check if $Authorized
if (defined $path[1] and $path[1] eq 'authorize') {
print "IN AUTHORIZE\n";
# Passwords are stored as MD5 hashes in the user data file
# Take that MD5, then take the current date (in YYYYDDMM format) and then calculate
# an authorization MD5 value. Adding in the current date means that the lifespan of a compromised
# password token is at most 1 day.
my $status = "";
if ($args{user} && $args{user}[0] eq "") {
$status = "Empty Username";
$status = "fail";
&main::print_log("json_server.pl: ERROR, authorize attempt with no username");
} elsif ($args{password} && $args{password}[0] eq "") {
$status = "Empty Password";
$status = "fail";
&main::print_log("json_server.pl: ERROR, authorize attempt with no password");

} else {
my $password = &Groups('getpw','',$args{user}[0]);
my $time_seed = &main::time_date_stamp('18',$Time);
my $time_seedY = &main::time_date_stamp('18',$Time - 86400);
my $time_seedT = &main::time_date_stamp('18',$Time + 86400);

#to account for clock drift, check today and tomorrow values around midnight
#if time is between 11:55 and midnight then also check tomorrow
#if time is between midnight and 00:05 then also check yesterday
print "PW=$password, time_seed=$time_seed, $time_seedY, $time_seedT\n";
if (time_greater_than("11:55 PM")) {
my $time_seedT = &main::time_date_stamp('18',$Time + 86400);
my $pwdcheck1 = md5_hex($password . $time_seedT);
$status = "success" if (lc $args{password}[0] eq lc $pwdcheck1);
}
if (time_less_than("00:05 AM")) {
my $time_seedY = &main::time_date_stamp('18',$Time - 86400);
my $pwdcheck2 = md5_hex($password . $time_seedY);
$status = "success" if (lc $args{password}[0] eq lc $pwdcheck2);
}
#print "PW=$password, time_seed=$time_seed";
my $pwdcheck = md5_hex($password . $time_seed);
print "PWC=$pwdcheck\n";
#print "PWC=$pwdcheck\n";

if (lc $args{password}[0] eq lc $pwdcheck) {
if ($status eq "" and (lc $args{password}[0] eq lc $pwdcheck)) {
$status = "success";
&main::print_log("json_server.pl: INFO, user $args{user}[0] successfully authenticated");

} else {
$status = "fail";
&main::print_log("json_server.pl: WARNING, user $args{user}[0] authentication attempt failed");

}
}
$json_data{security}->{authorize} = $status;
} else {
#check if $Authorized
my $ref;
my $users;
my $found = 0;
Expand Down Expand Up @@ -1508,7 +1526,7 @@ sub json_object_detail {
my %json_complete_object;
my @f = qw( category filename measurement rf_id set_by members
state states state_log type label sort_order groups hidden parents schedule logger_status
idle_time text html seconds_remaining fp_location fp_icons fp_icon_set img link level);
idle_time text html seconds_remaining fp_location fp_icons fp_icon_set img link level rgb);

# Build list of fields based on those requested.
foreach my $f ( sort @f ) {
Expand Down Expand Up @@ -1551,6 +1569,14 @@ sub json_object_detail {
$value = $a if ( defined $a and $a ne "" ); #don't return a null value
}

elsif ( $f eq 'rgb' ) {
my ($a,$b,$c) = $object->$method;

$value = "$a,$b,$c" if (( defined $a and $a ne "" ) #don't return a null value
and ( defined $b and $b ne "" )
and ( defined $c and $c ne "" ));
}

#if ( $f eq 'hidden' ) {
# my $a = $object->$method;
# if ($a == 1 or $a eq "1") {
Expand Down
Loading

0 comments on commit 2601dae

Please sign in to comment.