mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-05 18:16:44 +00:00
1219 lines
40 KiB
Perl
1219 lines
40 KiB
Perl
#####################################################################################
|
|
# $Id$
|
|
#
|
|
# Usage
|
|
#
|
|
# define <name> Hyperion <IP or HOSTNAME> <PORT> <INTERVAL>
|
|
#
|
|
#####################################################################################
|
|
|
|
package main;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Color;
|
|
|
|
use JSON;
|
|
use SetExtensions;
|
|
use DevIo;
|
|
|
|
my %Hyperion_sets =
|
|
(
|
|
"adjustRed" => "textField",
|
|
"adjustGreen" => "textField",
|
|
"adjustBlue" => "textField",
|
|
"blacklevel" => "textField",
|
|
"colorTemperature" => "textField",
|
|
"dim" => "slider,0,1,100",
|
|
"dimDown" => "noArg",
|
|
"dimUp" => "noArg",
|
|
"correction" => "textField",
|
|
"clear" => "textField",
|
|
"clearall" => "noArg",
|
|
"gamma" => "textField",
|
|
"luminanceGain" => "slider,0,0.010,1.999,1",
|
|
"luminanceMinimum" => "slider,0,0.010,1.999,1",
|
|
"mode" => "clearall,effect,off,rgb",
|
|
"off" => "noArg",
|
|
"on" => "noArg",
|
|
"rgb" => "colorpicker,RGB",
|
|
"saturationGain" => "slider,0,0.010,1.999,1",
|
|
"saturationLGain" => "slider,0,0.010,1.999,1",
|
|
"threshold" => "textField",
|
|
"toggle" => "noArg",
|
|
"valueGain" => "slider,0,0.010,1.999,1",
|
|
"whitelevel" => "textField"
|
|
);
|
|
|
|
my $Hyperion_requiredVersion = "1.03.2";
|
|
my $Hyperion_serverinfo = {"command" => "serverinfo"};
|
|
my $Hyperion_webCmd = "rgb:effect:mode:toggle:on:off";
|
|
my $Hyperion_webCmd_config = "rgb:effect:configFile:mode:toggle:on:off";
|
|
my $Hyperion_homebridgeMapping = "On=state,subtype=TV.Licht,valueOn=/rgb.*/,cmdOff=off,cmdOn=mode+rgb ".
|
|
"On=state,subtype=Umgebungslicht,valueOn=clearall,cmdOff=off,cmdOn=clearall ".
|
|
"On=state,subtype=Effekt,valueOn=/effect.*/,cmdOff=off,cmdOn=mode+effect ";
|
|
# "On=state,subtype=Knight.Rider,valueOn=/.*Knight_rider/,cmdOff=off,cmdOn=effect+Knight_rider " .
|
|
# "On=configFile,subtype=Eingang.HDMI,valueOn=hyperion-hdmi,cmdOff=configFile+hyperion,cmdOn=configFile+hyperion-hdmi ";
|
|
|
|
sub Hyperion_Initialize($)
|
|
{
|
|
my ($hash) = @_;
|
|
$hash->{AttrFn} = "Hyperion_Attr";
|
|
$hash->{DefFn} = "Hyperion_Define";
|
|
$hash->{GetFn} = "Hyperion_Get";
|
|
$hash->{NotifyFn} = "Hyperion_Notify";
|
|
$hash->{ReadFn} = "Hyperion_Read";
|
|
$hash->{SetFn} = "Hyperion_Set";
|
|
$hash->{UndefFn} = "Hyperion_Undef";
|
|
$hash->{AttrList} = "disable:1 ".
|
|
"hyperionAttrRestore:0 ".
|
|
"hyperionBin ".
|
|
"hyperionConfigDir ".
|
|
"hyperionDefaultDuration ".
|
|
"hyperionDefaultPriority ".
|
|
"hyperionDimStep ".
|
|
"hyperionNoSudo:1 ".
|
|
"hyperionSshUser ".
|
|
"hyperionVersionCheck:0 ".
|
|
"queryAfterSet:0 ".
|
|
$readingFnAttributes;
|
|
FHEM_colorpickerInit();
|
|
}
|
|
|
|
sub Hyperion_Define($$)
|
|
{
|
|
my ($hash,$def) = @_;
|
|
my @args = split("[ \t]+",$def);
|
|
return "Usage: define <name> Hyperion <IP> <PORT> [<INTERVAL>]"
|
|
if (@args < 4);
|
|
my ($name,$type,$host,$port,$interval) = @args;
|
|
if ($interval)
|
|
{
|
|
$hash->{INTERVAL} = $interval;
|
|
}
|
|
else
|
|
{
|
|
delete $hash->{INTERVAL};
|
|
}
|
|
$hash->{IP} = $host;
|
|
$hash->{PORT} = $port;
|
|
$hash->{DeviceName} = $host.":".$port;
|
|
$hash->{helper}{sets} = join(" ",map {"$_:$Hyperion_sets{$_}"} keys %Hyperion_sets);
|
|
$interval = undef unless defined $interval;
|
|
$interval = 5 if ($interval && $interval < 5);
|
|
RemoveInternalTimer($hash);
|
|
Hyperion_OpenDev($hash);
|
|
if ($init_done)
|
|
{
|
|
Hyperion_GetUpdate($hash);
|
|
}
|
|
else
|
|
{
|
|
InternalTimer(gettimeofday() + $interval,"Hyperion_GetUpdate",$hash,0);
|
|
}
|
|
$attr{$name}{room} = "Hyperion" if (!$attr{$name}{room});
|
|
return undef;
|
|
}
|
|
|
|
sub Hyperion_DoInit($)
|
|
{
|
|
my ($hash) = @_;
|
|
DevIo_SimpleWrite($hash,encode_json($Hyperion_serverinfo)."\n",2);
|
|
return undef;
|
|
}
|
|
|
|
sub Hyperion_Notify($$)
|
|
{
|
|
my ($hash,$dev) = @_;
|
|
my $name = $hash->{NAME};
|
|
return if ($dev->{NAME} ne "global");
|
|
return if (!grep(m/^INITIALIZED|REREADCFG$/, @{$dev->{CHANGED}}));
|
|
return undef if (AttrVal($name,"disable",0));
|
|
Hyperion_OpenDev($hash);
|
|
return undef;
|
|
}
|
|
|
|
sub Hyperion_OpenDev($)
|
|
{
|
|
my ($hash) = @_;
|
|
DevIo_CloseDev($hash);
|
|
$hash->{STATE} = DevIo_OpenDev($hash,0,"Hyperion_DoInit",sub($$$)
|
|
{
|
|
my ($h,$err) = @_;
|
|
readingsSingleUpdate($hash,"lastError",$err,1)
|
|
if ($err);
|
|
readingsSingleUpdate($hash,"serverResponse","ERROR",1);
|
|
readingsSingleUpdate($hash,"state","ERROR",1)
|
|
if (Value($hash->{NAME}) ne "ERROR");
|
|
return $err ? "Error: $err" : $hash->{DeviceName}." connected";
|
|
});
|
|
return undef;
|
|
}
|
|
|
|
sub Hyperion_Undef($$)
|
|
{
|
|
my ($hash,$name) = @_;
|
|
RemoveInternalTimer($hash);
|
|
DevIo_CloseDev($hash);
|
|
return undef;
|
|
}
|
|
|
|
sub Hyperion_list2array($$)
|
|
{
|
|
my ($list,$round) = @_;
|
|
my @arr;
|
|
foreach my $part (split(",",$list))
|
|
{
|
|
$part = sprintf($round,$part) * 1;
|
|
push @arr,$part;
|
|
}
|
|
return \@arr;
|
|
}
|
|
|
|
sub Hyperion_isLocal($)
|
|
{
|
|
my ($hash) = @_;
|
|
return 1 if ($hash->{IP} eq "localhost" || $hash->{IP} eq "127.0.0.1");
|
|
return undef;
|
|
}
|
|
|
|
sub Hyperion_Get($@)
|
|
{
|
|
my ($hash,$name,$cmd) = @_;
|
|
my $params = "configFiles:noArg devStateIcon:noArg statusRequest:noArg";
|
|
return "get $name needs one parameter: $params"
|
|
if (!$cmd);
|
|
if ($cmd eq "configFiles")
|
|
{
|
|
Hyperion_GetConfigs($hash);
|
|
}
|
|
elsif ($cmd eq "devStateIcon")
|
|
{
|
|
return Hyperion_devStateIcon($hash);
|
|
}
|
|
elsif ($cmd eq "statusRequest")
|
|
{
|
|
Hyperion_GetUpdate($hash);
|
|
}
|
|
else
|
|
{
|
|
return "Unknown argument $cmd for $name, choose one of $params";
|
|
}
|
|
}
|
|
|
|
sub Hyperion_Read($)
|
|
{
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $buf = DevIo_SimpleRead($hash);
|
|
return undef if (!$buf);
|
|
my $result = ($hash->{PARTIAL}) ? $hash->{PARTIAL}.$buf : $buf;
|
|
$hash->{PARTIAL} = $result;
|
|
return undef if ($buf !~ /(^.+"success":(true|false)\}$)/ );
|
|
Log3 $name,5,"$name: url ".$hash->{DeviceName}." returned result: $result";
|
|
delete $hash->{PARTIAL};
|
|
my %Hyperion_sets_local = %Hyperion_sets;
|
|
if ($result=~ /^\{"success":true\}$/)
|
|
{
|
|
fhem "sleep 1; get $name statusRequest"
|
|
if (AttrVal($name,"queryAfterSet",1) == 1 || !$hash->{INTERVAL});
|
|
return undef;
|
|
}
|
|
elsif ($result =~ /^\{"info":\{.+\},"success":true\}$/)
|
|
{
|
|
my $obj = eval {from_json($result)};
|
|
my $data = $obj->{info};
|
|
if (AttrVal($name,"hyperionVersionCheck",1) == 1)
|
|
{
|
|
my $error;
|
|
$error = "Can't detect your version of hyperion!"
|
|
if (!$data->{hyperion_build}->[0]->{version});
|
|
if (!$error)
|
|
{
|
|
my $ver = (split("V",(split(" ",$data->{hyperion_build}->[0]->{version}))[0]))[1];
|
|
$ver =~ s/\.//g;
|
|
my $rver = $Hyperion_requiredVersion;
|
|
$rver =~ s/\.//g;
|
|
$error = "Your version of hyperion (detected version: ".$data->{hyperion_build}->[0]->{version}.") is not (longer) supported by this module!"
|
|
if ($ver<$rver);
|
|
}
|
|
if ($error)
|
|
{
|
|
$error = "ATTENTION!!! $error Please update your hyperion to V$Hyperion_requiredVersion at least using HyperCon...";
|
|
Log3 $name, 1, $error;
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash,"serverResponse","ERROR");
|
|
readingsBulkUpdate($hash,"state","ERROR");
|
|
readingsBulkUpdate($hash,"lastError",$error);
|
|
readingsEndUpdate($hash,1);
|
|
return undef;
|
|
}
|
|
}
|
|
my $vers = $data->{hyperion_build}->[0]->{version};
|
|
my $prio = (defined $data->{priorities}->[0]->{priority}) ? $data->{priorities}->[0]->{priority} : undef;
|
|
my $duration = (defined $data->{priorities}->[0]->{duration_ms} && $data->{priorities}->[0]->{duration_ms} > 999) ? int($data->{priorities}->[0]->{duration_ms} / 1000) : 0;
|
|
$duration = ($duration) >= 1 ? $duration : "infinite";
|
|
my $adj = $data->{adjustment}->[0];
|
|
my $col = $data->{activeLedColor}->[0]->{'HEX Value'}->[0];
|
|
my $configs = ReadingsVal($name,".configs",undef);
|
|
my $corr = $data->{correction}->[0];
|
|
my $effects = $data->{effects};
|
|
my $effectList = join(",",map {"$_->{name}"} @{$effects});
|
|
$effectList =~ s/ /_/g;
|
|
my $script = $data->{activeEffects}->[0]->{script};
|
|
my $temp = $data->{temperature}->[0];
|
|
my $trans = $data->{transform}->[0];
|
|
my $id = $trans->{id};
|
|
my $adjR = join(",",@{$adj->{redAdjust}});
|
|
my $adjG = join(",",@{$adj->{greenAdjust}});
|
|
my $adjB = join(",",@{$adj->{blueAdjust}});
|
|
my $corS = join(",",@{$corr->{correctionValues}});
|
|
my $temP = join(",",@{$temp->{correctionValues}});
|
|
my $blkL = sprintf("%.3f",$trans->{blacklevel}->[0]).",".sprintf("%.3f",$trans->{blacklevel}->[1]).",".sprintf("%.3f",$trans->{blacklevel}->[2]);
|
|
my $gamM = sprintf("%.3f",$trans->{gamma}->[0]).",".sprintf("%.3f",$trans->{gamma}->[1]).",".sprintf("%.3f",$trans->{gamma}->[2]);
|
|
my $thrE = sprintf("%.3f",$trans->{threshold}->[0]).",".sprintf("%.3f",$trans->{threshold}->[1]).",".sprintf("%.3f",$trans->{threshold}->[2]);
|
|
my $whiL = sprintf("%.3f",$trans->{whitelevel}->[0]).",".sprintf("%.3f",$trans->{whitelevel}->[1]).",".sprintf("%.3f",$trans->{whitelevel}->[2]);
|
|
my $lumG = sprintf("%.3f",$trans->{luminanceGain});
|
|
my $lumM = (defined $trans->{luminanceMinimum}) ? sprintf("%.3f",$trans->{luminanceMinimum}) : undef;
|
|
my $satG = sprintf("%.3f",$trans->{saturationGain});
|
|
my $satL = (defined $trans->{saturationLGain}) ? sprintf("%.3f",$trans->{saturationLGain}) : undef;
|
|
my $valG = sprintf("%.3f",$trans->{valueGain});
|
|
my $attrRestore = AttrVal($name,"hyperionAttrRestore",1);
|
|
$Hyperion_sets_local{effect} = $effectList
|
|
if (length $effectList > 0);
|
|
if ($configs)
|
|
{
|
|
$Hyperion_sets_local{configFile} = $configs;
|
|
$attr{$name}{webCmd} = $Hyperion_webCmd_config
|
|
if ((!$attr{$name}{webCmd} || AttrVal($name,"webCmd","") eq $Hyperion_webCmd) && $attrRestore);
|
|
}
|
|
$attr{$name}{alias} = "Ambilight"
|
|
if (!$attr{$name}{alias} && $attrRestore);
|
|
$attr{$name}{devStateIcon} = '{(Hyperion_devStateIcon($name),"toggle")}'
|
|
if (!$attr{$name}{devStateIcon} && $attrRestore);
|
|
$attr{$name}{group} = "colordimmer"
|
|
if (!$attr{$name}{group} && $attrRestore);
|
|
$attr{$name}{homebridgeMapping} = $Hyperion_homebridgeMapping
|
|
if (!$attr{$name}{homebridgeMapping} && $attrRestore);
|
|
$attr{$name}{icon} = "light_led_stripe_rgb"
|
|
if (!$attr{$name}{icon} && $attrRestore);
|
|
$attr{$name}{lightSceneParamsToSave} = "state"
|
|
if (!$attr{$name}{lightSceneParamsToSave} && $attrRestore);
|
|
$attr{$name}{room} = "Hyperion"
|
|
if (!$attr{$name}{room} && $attrRestore);
|
|
$attr{$name}{userattr} = "lightSceneParamsToSave"
|
|
if (!$attr{$name}{userattr} && index($attr{"global"}{userattr},"lightSceneParamsToSave") == -1 && $attrRestore);
|
|
$attr{$name}{userattr} = "lightSceneParamsToSave ".$attr{$name}{userattr}
|
|
if ($attr{$name}{userattr} && index($attr{$name}{userattr},"lightSceneParamsToSave") == -1 && index($attr{"global"}{userattr},"lightSceneParamsToSave") == -1 && $attrRestore);
|
|
$attr{$name}{userattr} = "homebridgeMapping"
|
|
if (!$attr{$name}{userattr} && index($attr{"global"}{userattr},"homebridgeMapping") == -1 && $attrRestore);
|
|
$attr{$name}{userattr} = "homebridgeMapping ".$attr{$name}{userattr}
|
|
if ($attr{$name}{userattr} && index($attr{$name}{userattr},"homebridgeMapping") == -1 && index($attr{"global"}{userattr},"homebridgeMapping") == -1 && $attrRestore);
|
|
$attr{$name}{webCmd} = $Hyperion_webCmd
|
|
if ((!$attr{$name}{webCmd} || ($attr{$name}{webCmd} && !$Hyperion_sets_local{configFile})) && $attrRestore);
|
|
$attr{$name}{webCmd} = $Hyperion_webCmd_config
|
|
if ($attr{$name}{webCmd} && $Hyperion_sets_local{configFile} && $attr{$name}{webCmd} eq $Hyperion_webCmd && $attrRestore);
|
|
$hash->{helper}{sets} = join(" ",map {"$_:$Hyperion_sets_local{$_}"} keys %Hyperion_sets_local);
|
|
$hash->{hostname} = $data->{hostname}
|
|
if (($data->{hostname} && !$hash->{hostname}) || ($data->{hostname} && $hash->{hostname} ne $data->{hostname}));
|
|
$hash->{build_version} = $vers
|
|
if (($vers && !$hash->{build_version}) || ($vers && $hash->{build_version} ne $vers));
|
|
$hash->{build_time} = $data->{hyperion_build}->[0]->{time}
|
|
if (($data->{hyperion_build}->[0]->{time} && !$hash->{build_time}) || ($data->{hyperion_build}->[0]->{time} && $hash->{build_time} ne $data->{hyperion_build}->[0]->{time}));
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash,"adjustRed",$adjR);
|
|
readingsBulkUpdate($hash,"adjustGreen",$adjG);
|
|
readingsBulkUpdate($hash,"adjustBlue",$adjB);
|
|
readingsBulkUpdate($hash,"blacklevel",$blkL);
|
|
readingsBulkUpdate($hash,"colorTemperature",$temP);
|
|
readingsBulkUpdate($hash,"correction",$corS);
|
|
readingsBulkUpdate($hash,"effect",(split(",",$effectList))[0])
|
|
if (!defined ReadingsVal($name,"effect",undef));
|
|
readingsBulkUpdate($hash,".effects", $effectList)
|
|
if ($effectList);
|
|
readingsBulkUpdate($hash,"duration",$duration);
|
|
readingsBulkUpdate($hash,"gamma",$gamM);
|
|
readingsBulkUpdate($hash,"id",$id);
|
|
readingsBulkUpdate($hash,"luminanceGain",$lumG);
|
|
readingsBulkUpdate($hash,"luminanceMinimum",$lumM)
|
|
if ($lumM);
|
|
readingsBulkUpdate($hash,"priority",$prio)
|
|
if (defined $prio);
|
|
readingsBulkUpdate($hash,"rgb","ff0d0d")
|
|
if (!defined ReadingsVal($name,"rgb",undef));
|
|
readingsBulkUpdate($hash,"saturationGain",$satG);
|
|
readingsBulkUpdate($hash,"saturationLGain",$satL)
|
|
if ($satL);
|
|
readingsBulkUpdate($hash,"threshold",$thrE);
|
|
readingsBulkUpdate($hash,"valueGain",$valG);
|
|
readingsBulkUpdate($hash,"whitelevel",$whiL);
|
|
if ($script)
|
|
{
|
|
my $args = $data->{activeEffects}->[0]->{args};
|
|
foreach my $e (@$effects)
|
|
{
|
|
if ($e->{script} eq $script)
|
|
{
|
|
my $arg = $e->{args};
|
|
my $x = JSON->new->convert_blessed->canonical->encode($arg);
|
|
my $y = JSON->new->convert_blessed->canonical->encode($args);
|
|
|
|
if ("$x" eq "$y")
|
|
{
|
|
my $en = $e->{name};
|
|
$en =~ s/ /_/g;
|
|
readingsBulkUpdate($hash,"effect",$en);
|
|
readingsBulkUpdate($hash,"mode","effect");
|
|
readingsBulkUpdate($hash,"state","effect $en");
|
|
readingsBulkUpdate($hash,"mode_before_off","effect");
|
|
Log3 $name,4,"$name: effect $en";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
elsif ($col)
|
|
{
|
|
my $rgb = lc((split('x',$col))[1]);
|
|
$rgb =~ m/^(..)(..)(..)/;
|
|
my ($r,$g,$b) = Color::hex2rgb($rgb);
|
|
my ($h,$s,$v) = Color::rgb2hsv($r / 255,$g / 255,$b / 255);
|
|
my $dim = int($v * 100);
|
|
readingsBulkUpdate($hash,"rgb",$rgb);
|
|
readingsBulkUpdate($hash,"dim",$dim);
|
|
readingsBulkUpdate($hash,"mode","rgb");
|
|
readingsBulkUpdate($hash,"mode_before_off","rgb");
|
|
readingsBulkUpdate($hash,"state","rgb $rgb");
|
|
Log3 $name,4,"$name: rgb $rgb";
|
|
}
|
|
else
|
|
{
|
|
if ($prio)
|
|
{
|
|
readingsBulkUpdate($hash,"mode","clearall");
|
|
readingsBulkUpdate($hash,"mode_before_off","clearall");
|
|
readingsBulkUpdate($hash,"state","clearall");
|
|
Log3 $name,4,"$name: clearall";
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdate($hash,"mode","off");
|
|
readingsBulkUpdate($hash,"state","off");
|
|
Log3 $name,4,"$name: off";
|
|
}
|
|
}
|
|
readingsBulkUpdate($hash,"serverResponse","success");
|
|
readingsEndUpdate($hash,1);
|
|
}
|
|
else
|
|
{
|
|
Log3 $name,4,"$name: error while requesting ".$hash->{DeviceName}." - $result";
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate($hash,"lastError","error while requesting ".$hash->{DeviceName});
|
|
readingsBulkUpdate($hash,"serverResponse","ERROR");
|
|
readingsBulkUpdate($hash,"state","ERROR")
|
|
if (Value($name) ne "ERROR");
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
sub Hyperion_GetConfigs($)
|
|
{
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $ip = $hash->{IP};
|
|
my $dir = AttrVal($name,"hyperionConfigDir","/etc/hyperion/");
|
|
my $com = "ls $dir 2>/dev/null";
|
|
my @files;
|
|
if (Hyperion_isLocal($hash))
|
|
{
|
|
@files = Hyperion_listFilesInDir($hash,$com);
|
|
}
|
|
else
|
|
{
|
|
my $user = AttrVal($name,"hyperionSshUser","pi");
|
|
my $cmd = qx(which ssh);
|
|
chomp($cmd);
|
|
$cmd .= " $user\@$ip $com";
|
|
@files = Hyperion_listFilesInDir($hash,$cmd);
|
|
}
|
|
my $count = scalar @files;
|
|
return "No files found on server $ip in directory $dir. Maybe the wrong directory? If SSH is used, has the user ".AttrVal($name,"hyperionSshUser","pi")." been configured to log in without entering a password (http://www.linuxproblem.org/art_9.html)?"
|
|
if ($count == 0);
|
|
if ($count > 1)
|
|
{
|
|
my $configs = join(",",@files);
|
|
readingsSingleUpdate($hash,".configs",$configs,1)
|
|
if (ReadingsVal($name,".configs","") ne $configs);
|
|
$attr{$name}{webCmd} = $Hyperion_webCmd_config
|
|
if (AttrVal($name,"webCmd","") eq $Hyperion_webCmd);
|
|
}
|
|
else
|
|
{
|
|
fhem "deletereading $name .configs"
|
|
if (defined ReadingsVal($name,".configs",undef));
|
|
$attr{$name}{webCmd} = $Hyperion_webCmd
|
|
if (AttrVal($name,"webCmd","") eq $Hyperion_webCmd_config);
|
|
return "Found just one config file. Please add at least one more config file to properly use this function."
|
|
if ($count == 1);
|
|
return "No config files found!";
|
|
}
|
|
Hyperion_GetUpdate($hash);
|
|
return "Found $count config files. Please refresh this page to see the result.";
|
|
}
|
|
|
|
sub Hyperion_listFilesInDir($$)
|
|
{
|
|
my ($hash,$cmd) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $fh;
|
|
my @filelist;
|
|
if (open($fh,"$cmd|"))
|
|
{
|
|
my @files = <$fh>;
|
|
my $count = scalar @files;
|
|
for (my $i = 0; $i < $count; $i++)
|
|
{
|
|
my $file = $files[$i];
|
|
$file =~ s/\s+//gm;
|
|
next if ($file !~ /\w+\.config\.json$/);
|
|
$file =~ s/.config.json$//gm;
|
|
push @filelist,$file;
|
|
Log3 $name,4,"$name: Hyperion_listFilesInDir matching file: \"$file\"";
|
|
}
|
|
close $fh;
|
|
}
|
|
return @filelist;
|
|
}
|
|
|
|
sub Hyperion_GetUpdate(@)
|
|
{
|
|
my ($hash) = @_;
|
|
my $name = $hash->{NAME};
|
|
RemoveInternalTimer($hash);
|
|
if ($hash->{INTERVAL})
|
|
{
|
|
InternalTimer(gettimeofday() + $hash->{INTERVAL},"Hyperion_GetUpdate",$hash,1);
|
|
}
|
|
return undef if (IsDisabled($name) > 0);
|
|
Hyperion_Call($hash);
|
|
return undef;
|
|
}
|
|
|
|
sub Hyperion_Set($@)
|
|
{
|
|
my ($hash,$name,@aa) = @_;
|
|
my ($cmd,@args) = @aa;
|
|
my $value = (defined($args[0])) ? $args[0] : undef;
|
|
return "\"set $name\" needs at least one argument and maximum five arguments"
|
|
if (scalar @aa < 1 || scalar @aa > 4);
|
|
my $duration = (defined $args[1]) ? int $args[1] : int AttrVal($name,"hyperionDefaultDuration",0);
|
|
my $priority = (defined $args[2]) ? int $args[2] : int AttrVal($name,"hyperionDefaultPriority",0);
|
|
my $sets = $hash->{helper}{sets};
|
|
my %obj;
|
|
Log3 $name,4,"$name: Hyperion_Set cmd: $cmd" if (defined $cmd);
|
|
Log3 $name,4,"$name: Hyperion_Set value: $value" if (defined $value && $value ne "");
|
|
Log3 $name,4,"$name: Hyperion_Set duration: $duration, priority: $priority";
|
|
if ($cmd eq "configFile")
|
|
{
|
|
$value = $value.".config.json";
|
|
my $confdir = AttrVal($name,"hyperionConfigDir","/etc/hyperion/");
|
|
my $binpath = AttrVal($name,"hyperionBin","/usr/bin/hyperiond");
|
|
my $bin = (split("/",$binpath))[scalar(split("/",$binpath)) - 1];
|
|
my $user = AttrVal($name,"hyperionSshUser","pi");
|
|
my $ip = $hash->{IP};
|
|
my $sudo = ($user eq "root" || int AttrVal($name,"hyperionNoSudo",0) == 1) ? "" : "sudo ";
|
|
my $command = $sudo."killall $bin; sleep 1; ".$sudo."$binpath $confdir$value > /dev/null 2>&1 &";
|
|
my $status;
|
|
my $fh;
|
|
if (Hyperion_isLocal($hash))
|
|
{
|
|
if (open($fh,"$command|"))
|
|
{
|
|
$status = <$fh>;
|
|
close $fh;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
my $com = qx(which ssh);
|
|
chomp $com;
|
|
$com .= " $user\@$ip '$command'";
|
|
if (open($fh,"$com|"))
|
|
{
|
|
$status = <$fh>;
|
|
close $fh;
|
|
}
|
|
}
|
|
if (!$status)
|
|
{
|
|
Log3 $name,4,"$name: restarted Hyperion with $binpath $confdir$value";
|
|
$value =~ s/.config.json$//;
|
|
readingsSingleUpdate($hash,"configFile",$value,1);
|
|
return undef;
|
|
}
|
|
else
|
|
{
|
|
Log3 $name,4,"$name: NOT restarted Hyperion with $binpath $confdir$value, status: $status";
|
|
readingsSingleUpdate($hash,"lastError",$status,1);
|
|
readingsSingleUpdate($hash,"serverResponse","ERROR",1);
|
|
readingsSingleUpdate($hash,"state","ERROR",1)
|
|
if (Value($name) ne "ERROR");
|
|
return "$name NOT restarted Hyperion with $binpath $confdir$value, status: $status";
|
|
}
|
|
}
|
|
elsif ($cmd eq "rgb")
|
|
{
|
|
return "Value of $cmd has to be in RGB hex format like ffffff or 3F7D90"
|
|
if ($value !~ /^(\d|[a-f|A-F]){6}$/);
|
|
$value = lc($value);
|
|
my ($r,$g,$b) = Color::hex2rgb($value);
|
|
$obj{color} = [$r,$g,$b];
|
|
$obj{command} = "color";
|
|
$obj{priority} = $priority * 1;
|
|
$obj{duration} = $duration * 1000
|
|
if ($duration > 0);
|
|
}
|
|
elsif ($cmd eq "dim")
|
|
{
|
|
return "Value of $cmd has to be between 1 and 100"
|
|
if ($value !~ /^(\d+)$/ || int($1) > 100 || int($1) < 1);
|
|
my $rgb = ReadingsVal($name,"rgb","ffffff");
|
|
$value = $value + 1
|
|
if ($cmd eq "dim" && $value < 100);
|
|
$value = $value / 100;
|
|
my ($r,$g,$b) = Color::hex2rgb($rgb);
|
|
my ($h,$s,$v) = Color::rgb2hsv($r / 255,$g / 255,$b / 255);
|
|
my ($rn,$gn,$bn);
|
|
($rn,$gn,$bn) = Color::hsv2rgb($h,$s,$value)
|
|
if ($cmd eq "dim");
|
|
$rn = int($rn * 255);
|
|
$gn = int($gn * 255);
|
|
$bn = int($bn * 255);
|
|
$obj{color} = [$rn,$gn,$bn];
|
|
$obj{command} = "color";
|
|
$obj{priority} = $priority * 1;
|
|
$obj{duration} = $duration * 1000
|
|
if ($duration > 0);
|
|
}
|
|
elsif ($cmd =~ /^(dimUp|dimDown)$/)
|
|
{
|
|
return "Value of $cmd has to be between 1 and 99"
|
|
if (defined($value) && $value =~ /^(\d+)$/ && int($1) < 1 && int($1) > 99);
|
|
my $dim = int ReadingsVal($name,"dim",100);
|
|
my $dimStep = (defined $value) ? int $value : int AttrVal($name,"hyperionDimStep",5);
|
|
my $dimUp = ($dim + $dimStep < 100) ? $dim + $dimStep : 100;
|
|
my $dimDown = ($dim - $dimStep > 0) ? $dim - $dimStep : 0;
|
|
fhem "set $name dim $dimUp"
|
|
if ($cmd eq "dimUp");
|
|
fhem "set $name dim $dimDown"
|
|
if ($cmd eq "dimDown");
|
|
return undef;
|
|
}
|
|
elsif ($cmd eq "effect")
|
|
{
|
|
return "Effect $value is not available in the effect list of $name!"
|
|
if ($value !~ /^(\w+)?((_)\w+){0,}$/ || index(ReadingsVal($name,".effects",""),$value) == -1);
|
|
$value =~ s/_/ /g;
|
|
my %ef = ("name" => $value);
|
|
$obj{effect} = \%ef;
|
|
$obj{command} = "effect";
|
|
$obj{priority} = $priority * 1;
|
|
$obj{duration} = $duration * 1000
|
|
if ($duration > 0);
|
|
}
|
|
elsif ($cmd eq "clearall")
|
|
{
|
|
return "$cmd need no additional value of $value"
|
|
if (defined $value);
|
|
$obj{command} = $cmd;
|
|
}
|
|
elsif ($cmd eq "clear")
|
|
{
|
|
return "Value of $cmd has to be between 0 and 65536 in steps of 1"
|
|
if ($value !~ /^(\d+)$/ || int $1 < 0 || int $1 > 65536);
|
|
$value = int $value;
|
|
$obj{command} = $cmd;
|
|
$obj{priority} = $value * 1;
|
|
}
|
|
elsif ($cmd eq "off")
|
|
{
|
|
return "$cmd need no additional value of $value"
|
|
if (defined $value);
|
|
$obj{command} = "color";
|
|
$obj{color} = [0,0,0];
|
|
$obj{priority} = 0;
|
|
}
|
|
elsif ($cmd eq "on")
|
|
{
|
|
return "$cmd need no additional value of $value"
|
|
if (defined $value);
|
|
my $rmode = ReadingsVal($name,"mode_before_off","rgb");
|
|
my $rrgb = ReadingsVal($name,"rgb","");
|
|
my $reffect = ReadingsVal($name,"effect","");
|
|
my ($r,$g,$b) = Color::hex2rgb($rrgb);
|
|
if ($rmode eq "rgb")
|
|
{
|
|
fhem "set ".$name." $rmode $rrgb";
|
|
}
|
|
elsif ($rmode eq "effect")
|
|
{
|
|
fhem "set ".$name." $rmode $reffect";
|
|
}
|
|
elsif ($rmode eq "clearall")
|
|
{
|
|
fhem "set ".$name." clearall";
|
|
}
|
|
return undef;
|
|
}
|
|
elsif ($cmd eq "toggle")
|
|
{
|
|
return "$cmd need no additional value of $value"
|
|
if (defined $value);
|
|
my $rstate = Value($name);
|
|
($rstate ne "off") ? fhem "set ".$name." off" : fhem "set ".$name." on";
|
|
return undef;
|
|
}
|
|
elsif ($cmd eq "mode")
|
|
{
|
|
return "The value of mode has to be rgb,effect,clearall,off"
|
|
if ($value !~ /^(off|clearall|rgb|effect)$/);
|
|
Log3 $name,4,"$name: cmd: $cmd, value: $value";
|
|
my $rmode = $value;
|
|
my $rrgb = ReadingsVal($name,"rgb","");
|
|
my $reffect = ReadingsVal($name,"effect","");
|
|
my ($r,$g,$b) = Color::hex2rgb($rrgb);
|
|
if ($rmode eq "rgb")
|
|
{
|
|
fhem "set ".$name." $rmode $rrgb";
|
|
}
|
|
elsif ($rmode eq "effect")
|
|
{
|
|
fhem "set ".$name." $rmode $reffect";
|
|
}
|
|
elsif ($rmode eq "clearall")
|
|
{
|
|
fhem "set ".$name." clearall";
|
|
}
|
|
elsif ($rmode eq "off")
|
|
{
|
|
fhem "set ".$name." $rmode";
|
|
}
|
|
return undef;
|
|
}
|
|
elsif ($cmd =~ /^(luminanceGain|luminanceMinimum|saturationGain|saturationLGain|valueGain)$/)
|
|
{
|
|
return "The value of $cmd has to be between 0.000 an 1.999 in steps of 0.001."
|
|
if ($value !~ /^(\d)(\.\d)?(\d{1,2})?$/ || int $1 > 1);
|
|
$value = sprintf("%.3f",$value) * 1;
|
|
my %tr = ($cmd => $value);
|
|
$obj{command} = "transform";
|
|
$obj{transform} = \%tr;
|
|
}
|
|
elsif ($cmd =~ /^(blacklevel|gamma|threshold|whitelevel)$/)
|
|
{
|
|
return "Each of the three comma separated values of $cmd has to be between 0.000 an 9.999 in steps of 0.001"
|
|
if ($value !~ /^((\d)\.(\d){1,3}),((\d)\.(\d){1,3}),((\d)\.(\d){1,3})$/ || int $1 > 9 || int $4 > 9 || int $7 > 9);
|
|
my $arr = Hyperion_list2array($value,"%.3f");
|
|
my %ar = ($cmd => $arr);
|
|
$obj{command} = "transform";
|
|
$obj{transform} = \%ar;
|
|
}
|
|
elsif ($cmd =~ /^(correction|colorTemperature)$/)
|
|
{
|
|
$cmd = "temperature"
|
|
if ($cmd eq "colorTemperature");
|
|
return "Each of the three comma separated values of $cmd has to be between 0 an 255 in steps of 1"
|
|
if ($value !~ /^(\d{1,3})?,(\d{1,3})?,(\d{1,3})?$/ || int $1 > 255 || int $2 > 255 || int $3 > 255);
|
|
my $arr = Hyperion_list2array($value,"%d");
|
|
my %ar = ("correctionValues" => $arr);
|
|
$obj{command} = $cmd;
|
|
$obj{$cmd} = \%ar;
|
|
}
|
|
elsif ($cmd =~ /^(adjustRed|adjustGreen|adjustBlue)$/)
|
|
{
|
|
return "Each of the three comma separated values of $cmd has to be between 0 an 255 in steps of 1"
|
|
if ($value !~ /^(\d{1,3})?,(\d{1,3})?,(\d{1,3})?$/ || int $1 > 255 || int $2 > 255 || int $3 > 255);
|
|
$cmd = "redAdjust" if ($cmd eq "adjustRed");
|
|
$cmd = "greenAdjust" if ($cmd eq "adjustGreen");
|
|
$cmd = "blueAdjust" if ($cmd eq "adjustBlue");
|
|
my $arr = Hyperion_list2array($value,"%d");
|
|
my %ar = ($cmd => $arr);
|
|
$obj{command} = "adjustment";
|
|
$obj{adjustment} = \%ar;
|
|
}
|
|
if (scalar keys %obj)
|
|
{
|
|
Log3 $name,5,"$name: $cmd obj json: ".encode_json(\%obj);
|
|
SetExtensionsCancel($hash);
|
|
Hyperion_Call($hash,\%obj);
|
|
}
|
|
else
|
|
{
|
|
return SetExtensions($hash,$sets,$name,@aa) ;
|
|
}
|
|
}
|
|
|
|
sub Hyperion_Attr(@)
|
|
{
|
|
my ($cmd,$name,$attr_name,$attr_value) = @_;
|
|
my $hash = $defs{$name};
|
|
my $err = undef;
|
|
my $local = ($hash->{IP} eq "localhost" || $hash->{IP} eq "127.0.0.1") ? "" : undef;
|
|
if ($cmd eq "set")
|
|
{
|
|
if ($attr_name eq "hyperionBin")
|
|
{
|
|
if ($attr_value !~ /^(\/.+){2,}$/)
|
|
{
|
|
$err = "Invalid value $attr_value for attribute $attr_name. Must be a path like /usr/bin/hyperiond.";
|
|
}
|
|
elsif (defined $local && !-e $attr_value)
|
|
{
|
|
$err = "The given file $attr_value is not an available file.";
|
|
}
|
|
}
|
|
elsif ($attr_name eq "hyperionConfigDir")
|
|
{
|
|
if ($attr_value !~ /^\/(.+\/){2,}/)
|
|
{
|
|
$err = "Invalid value $attr_value for attribute $attr_name. Must be a path with trailing slash like /etc/hyperion/.";
|
|
}
|
|
elsif (defined $local && !-d $attr_value)
|
|
{
|
|
$err = "The given directory $attr_value is not an available directory.";
|
|
}
|
|
else
|
|
{
|
|
Hyperion_GetConfigs($hash);
|
|
Hyperion_Call($hash);
|
|
}
|
|
}
|
|
elsif ($attr_name eq "hyperionDefaultPriority" || $attr_name eq "hyperionDefaultDuration")
|
|
{
|
|
$err = "Invalid value $attr_value for attribute $attr_name. Must be a number between 0 and 65536."
|
|
if ($attr_value !~ /^(\d+)$/ || $1 < 0 || $1 > 65536);
|
|
}
|
|
elsif ($attr_name eq "hyperionDimStep")
|
|
{
|
|
$err = "Invalid value $attr_value for attribute $attr_name. Must be between 1 and 50 in steps of 1, default is 5."
|
|
if ($attr_value !~ /^(\d+)$/ || $1 < 1 || $1 > 50);
|
|
}
|
|
elsif ($attr_name eq "hyperionAttrRestore")
|
|
{
|
|
$err = "Invalid value $attr_value for attribute $attr_name. Can only be value 0."
|
|
if ($attr_value !~ /^0$/);
|
|
}
|
|
elsif ($attr_name eq "hyperionNoSudo")
|
|
{
|
|
$err = "Invalid value $attr_value for attribute $attr_name. Can only be value 1."
|
|
if ($attr_value !~ /^1$/);
|
|
}
|
|
elsif ($attr_name eq "hyperionSshUser")
|
|
{
|
|
if ($attr_value !~ /^\w+$/)
|
|
{
|
|
$err = "Invalid value $attr_value for attribute $attr_name. Must be a name like pi or fhem.";
|
|
}
|
|
else
|
|
{
|
|
Hyperion_GetConfigs($hash);
|
|
Hyperion_Call($hash);
|
|
}
|
|
}
|
|
elsif ($attr_name eq "hyperionVersionCheck")
|
|
{
|
|
$err = "Invalid value $attr_value for attribute $attr_name. Can only be value 0."
|
|
if ($attr_value !~ /^0$/);
|
|
}
|
|
elsif ($attr_name eq "queryAfterSet")
|
|
{
|
|
if ($attr_value !~ /^0$/)
|
|
{
|
|
$err = "Invalid value $attr_value for attribute $attr_name. Must be 0 when set, default is 1.";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Hyperion_Call($hash);
|
|
}
|
|
return $err if (defined $err);
|
|
return;
|
|
}
|
|
|
|
sub Hyperion_Call($;$)
|
|
{
|
|
my ($hash,$obj) = @_;
|
|
$obj = ($obj) ? $obj : $Hyperion_serverinfo;
|
|
my $name = $hash->{NAME};
|
|
my $json = encode_json($obj);
|
|
return undef if (IsDisabled($name) > 0);
|
|
if (!$hash->{FD})
|
|
{
|
|
Hyperion_OpenDev($hash);
|
|
return undef;
|
|
}
|
|
Log3 $name,5,"$name: Hyperion_Call: json object: $json";
|
|
DevIo_SimpleWrite($hash,$json."\n",2);
|
|
}
|
|
|
|
sub Hyperion_devStateIcon($;$)
|
|
{
|
|
my ($hash,$state) = @_;
|
|
$hash = $defs{$hash} if (ref $hash ne "HASH");
|
|
return undef if (!$hash);
|
|
my $name = $hash->{NAME};
|
|
my $rgb = ReadingsVal($name,"rgb","");
|
|
my $dim = ReadingsVal($name,"dim",10);
|
|
my $ico = (int($dim / 10) * 10 < 10) ? 10 : int($dim / 10) * 10;
|
|
return ".*:off:toggle"
|
|
if (Value($name) eq "off");
|
|
return ".*:light_exclamation"
|
|
if (Value($name) =~ /^(ERROR|disconnected)$/);
|
|
return ".*:light_question"
|
|
if (Value($name) eq "Initialized");
|
|
return ".*:light_light_dim_$ico@#".$rgb.":toggle"
|
|
if (Value($name) ne "off" && ReadingsVal($name,"mode","") eq "rgb");
|
|
return ".*:light_led_stripe_rgb@#FFFF00:toggle"
|
|
if (Value($name) ne "off" && ReadingsVal($name,"mode","") eq "effect");
|
|
return ".*:it_television@#0000FF:toggle"
|
|
if (Value($name) ne "off" && ReadingsVal($name,"mode","") eq "clearall");
|
|
}
|
|
|
|
1;
|
|
|
|
=pod
|
|
=item device
|
|
=item summary provides access to the Hyperion JSON server
|
|
=item summary_DE stellt Zugang zum Hyperion JSON Server zur Verfügung
|
|
=begin html
|
|
|
|
<a name="Hyperion"></a>
|
|
<h3>Hyperion</h3>
|
|
<ul>
|
|
With <i>Hyperion</i> it is possible to change the color or start an effect on a hyperion server.<br>
|
|
It's also possible to control the complete color calibration (changes are temorary and will not be written to the config file).<br>
|
|
The Hyperion server must have enabled the JSON server.<br>
|
|
You can also restart Hyperion with different configuration files (p.e. switch input)<br>
|
|
<br>
|
|
<a name="Hyperion_define"></a>
|
|
<p><b>Define</b></p>
|
|
<ul>
|
|
<code>define <name> Hyperion <IP or HOSTNAME> <PORT> [<INTERVAL>]</code><br>
|
|
</ul>
|
|
<br>
|
|
<INTERVAL> is optional for polling.<br>
|
|
<br>
|
|
<i>After defining "get <name> statusRequest" will be called once automatically to get the list of available effects and the current state of the Hyperion server.</i><br>
|
|
<br>
|
|
Example for running Hyperion on local system:
|
|
<br><br>
|
|
<ul>
|
|
<code>define Ambilight Hyperion localhost 19444 10</code><br>
|
|
</ul>
|
|
<br>
|
|
Example for running Hyperion on remote system:
|
|
<br><br>
|
|
<ul>
|
|
<code>define Ambilight Hyperion 192.168.1.4 19444 10</code><br>
|
|
</ul>
|
|
<br>
|
|
<a name="Hyperion_set"></a>
|
|
<p><b>set <required> [optional]</b></p>
|
|
<ul>
|
|
<li>
|
|
<i>adjustBlue <0,0,255></i><br>
|
|
adjust each color of blue separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>adjustGreen <0,255,0></i><br>
|
|
adjust each color of green separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>adjustRed <255,0,0></i><br>
|
|
adjust each color of red separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>blacklevel <0.000,0.000,0.000></i><br>
|
|
adjust blacklevel of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>clear <1000></i><br>
|
|
clear a specific priority channel
|
|
</li>
|
|
<li>
|
|
<i>clearall</i><br>
|
|
clear all priority channels / switch to Ambilight mode
|
|
</li>
|
|
<li>
|
|
<i>colorTemperature <255,255,255></i><br>
|
|
adjust temperature of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>configFile <filename></i><br>
|
|
restart the Hyperion server with the given configuration file (files will be listed automatically from the given directory in attribute hyperionConfigDir)<br>
|
|
please omit the double extension of the file name (.config.json)<br>
|
|
only available after successful "get <name> configFiles"
|
|
</li>
|
|
<li>
|
|
<i>correction <255,255,255></i><br>
|
|
adjust correction of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>dim <percent> [duration] [priority]</i><br>
|
|
dim the rgb light with optional duration in seconds and priority
|
|
</li>
|
|
<li>
|
|
<i>dimDown [delta]</i><br>
|
|
dim down rgb light by steps defined in attribute hyperionDimStep or by given value (default: 10)
|
|
</li>
|
|
<li>
|
|
<i>dimUp [delta]</i><br>
|
|
dim up rgb light by steps defined in attribute hyperionDimStep or by given value (default: 10)
|
|
</li>
|
|
<li>
|
|
<i>effect <effect> [duration] [priority]</i><br>
|
|
set effect (replace blanks with underscore) with optional duration in seconds and priority
|
|
</li>
|
|
<li>
|
|
<i>gamma <1.900,1.900,1.900></i><br>
|
|
adjust gamma of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>luminanceGain <1.000></i><br>
|
|
adjust luminanceGain (max. value 1.999)
|
|
</li>
|
|
<li>
|
|
<i>luminanceMinimum <0.000></i><br>
|
|
adjust luminanceMinimum (max. value 1.999)
|
|
</li>
|
|
<li>
|
|
<i>mode <clearall|effect|off|rgb></i><br>
|
|
set the light in the specific mode with its previous value
|
|
</li>
|
|
<li>
|
|
<i>off</i><br>
|
|
set the light off while the color is black
|
|
</li>
|
|
<li>
|
|
<i>on</i><br>
|
|
set the light on and restore previous state
|
|
</li>
|
|
<li>
|
|
<i>rgb <RRGGBB> [duration] [priority]</i><br>
|
|
set color in RGB hex format with optional duration in seconds and priority
|
|
</li>
|
|
<li>
|
|
<i>saturationGain <1.100></i><br>
|
|
adjust saturationGain (max. value 1.999)
|
|
</li>
|
|
<li>
|
|
<i>saturationLGain <1.000></i><br>
|
|
adjust saturationLGain (max. value 1.999)
|
|
</li>
|
|
<li>
|
|
<i>threshold <0.160,0.160,0.160></i><br>
|
|
adjust threshold of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>toggle</i><br>
|
|
toggles the light between on and off
|
|
</li>
|
|
<li>
|
|
<i>valueGain <1.700></i><br>
|
|
adjust valueGain (max. value 1.999)
|
|
</li>
|
|
<li>
|
|
<i>whitelevel <0.700,0.800,0.900></i><br>
|
|
adjust whitelevel of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
</ul>
|
|
<br>
|
|
<a name="Hyperion_get"></a>
|
|
<p><b>Get</b></p>
|
|
<ul>
|
|
<li>
|
|
<i>configFiles</i><br>
|
|
get the available config files in directory from attribute hyperionConfigDir<br>
|
|
will only work properly if at least two config files are found
|
|
</li>
|
|
<li>
|
|
<i>devStateIcon</i><br>
|
|
get the current devStateIcon
|
|
</li>
|
|
<li>
|
|
<i>statusRequest</i><br>
|
|
get the currently set effect or color from the Hyperion server,<br>
|
|
get the internals of Hyperion including available effects
|
|
</li>
|
|
</ul>
|
|
<br>
|
|
<a name="Hyperion_attr"></a>
|
|
<p><b>Attributes</b></p>
|
|
<ul>
|
|
<li>
|
|
<i>hyperionAttrRestore</i><br>
|
|
restore default attributes if deleted manually<br>
|
|
default: 1
|
|
</li>
|
|
<li>
|
|
<i>hyperionBin</i><br>
|
|
path to the hyperion executable<br>
|
|
default: /usr/bin/hyperiond
|
|
</li>
|
|
<li>
|
|
<i>hyperionConfigDir</i><br>
|
|
path to the hyperion configuration files<br>
|
|
default: /etc/hyperion/
|
|
</li>
|
|
<li>
|
|
<i>hyperionDefaultDuration</i><br>
|
|
default duration<br>
|
|
default: infinity
|
|
</li>
|
|
<li>
|
|
<i>hyperionDefaultPriority</i><br>
|
|
default priority<br>
|
|
default: 0
|
|
</li>
|
|
<li>
|
|
<i>hyperionDimStep</i><br>
|
|
dim step for dimDown/dimUp<br>
|
|
default: 5 (percent)
|
|
</li>
|
|
<li>
|
|
<i>hyperionNoSudo</i><br>
|
|
disable sudo for non-root users<br>
|
|
default: 0
|
|
</li>
|
|
<li>
|
|
<i>hyperionSshUser</i><br>
|
|
user for executing SSH commands
|
|
</li>
|
|
<li>
|
|
<i>hyperionVersionCheck</i><br>
|
|
disable hyperion version check to (maybe) support prior versions<br>
|
|
DO THIS AT YOUR OWN RISK! FHEM MAY CRASH UNEXPECTEDLY!<br>
|
|
default: 1
|
|
</li>
|
|
<li>
|
|
<i>queryAfterSet</i><br>
|
|
If set to 0 the state of the Hyperion server will not be queried after setting, instead the state will be queried on next interval query.<br>
|
|
This is only used when polling is enabled, without polling the state will be queried automatically after set.
|
|
</li>
|
|
</ul>
|
|
<br>
|
|
<a name="Hyperion_read"></a>
|
|
<p><b>Readings</b></p>
|
|
<ul>
|
|
<li>
|
|
<i>adjustBlue</i><br>
|
|
each color of blue separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>adjustGreen</i><br>
|
|
each color of green separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>adjustRed</i><br>
|
|
each color of red separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>blacklevel</i><br>
|
|
blacklevel of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>colorTemperature</i><br>
|
|
temperature of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>configFile</i><br>
|
|
active/previously loaded configuration file, double extension (.config.json) will be omitted
|
|
</li>
|
|
<li>
|
|
<i>correction</i><br>
|
|
correction of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>dim</i><br>
|
|
active/previous dim value (rgb light)
|
|
</li>
|
|
<li>
|
|
<i>duration</i><br>
|
|
active/previous duration in seconds or infinite
|
|
</li>
|
|
<li>
|
|
<i>effect</i><br>
|
|
active/previous effect
|
|
</li>
|
|
<li>
|
|
<i>gamma</i><br>
|
|
gamma for each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>id</i><br>
|
|
id of the Hyperion server
|
|
</li>
|
|
<li>
|
|
<i>lastError</i><br>
|
|
last occured error while communicating with the Hyperion server
|
|
</li>
|
|
<li>
|
|
<i>luminanceGain</i><br>
|
|
luminanceGain
|
|
</li>
|
|
<li>
|
|
<i>luminanceMinimum</i><br>
|
|
luminanceMinimum
|
|
</li>
|
|
<li>
|
|
<i>mode</i><br>
|
|
current mode
|
|
</li>
|
|
<li>
|
|
<i>mode_before_off</i><br>
|
|
previous mode before off
|
|
</li>
|
|
<li>
|
|
<i>priority</i><br>
|
|
active/previous priority
|
|
</li>
|
|
<li>
|
|
<i>rgb</i><br>
|
|
active/previous rgb
|
|
</li>
|
|
<li>
|
|
<i>saturationGain</i><br>
|
|
active/previous saturationGain
|
|
</li>
|
|
<li>
|
|
<i>saturationLGain</i><br>
|
|
active/previous saturationLGain
|
|
</li>
|
|
<li>
|
|
<i>serverResponse</i><br>
|
|
last Hyperion server response (success/ERROR)
|
|
</li>
|
|
<li>
|
|
<i>state</i><br>
|
|
current state
|
|
</li>
|
|
<li>
|
|
<i>threshold</i><br>
|
|
threshold of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
<li>
|
|
<i>valueGain</i><br>
|
|
valueGain - gain of the Ambilight
|
|
</li>
|
|
<li>
|
|
<i>whitelevel</i><br>
|
|
whitelevel of each color separately (comma separated) (R,G,B)
|
|
</li>
|
|
</ul>
|
|
</ul>
|
|
|
|
=end html
|
|
=cut
|