98_Hyperion.pm 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815
  1. #####################################################################################
  2. # $Id: 98_Hyperion.pm 15463 2017-11-19 23:42:14Z DeeSPe $
  3. #
  4. # Usage
  5. #
  6. # define <name> Hyperion <IP or HOSTNAME> <PORT> <INTERVAL>
  7. #
  8. #####################################################################################
  9. package main;
  10. use strict;
  11. use warnings;
  12. use Color;
  13. use DevIo;
  14. use JSON;
  15. use SetExtensions;
  16. use Blocking;
  17. my %Hyperion_sets =
  18. (
  19. "addEffect" => "textField",
  20. "dim" => "slider,0,1,100",
  21. "dimDown" => "textField",
  22. "dimUp" => "textField",
  23. "clear" => "textField",
  24. "clearall" => "noArg",
  25. "mode" => "clearall,effect,off,rgb",
  26. "off" => "noArg",
  27. "on" => "noArg",
  28. "reopen" => "noArg",
  29. "rgb" => "colorpicker,RGB",
  30. "toggle" => "noArg",
  31. "toggleMode" => "noArg",
  32. "valueGainDown" => "textField",
  33. "valueGainUp" => "textField"
  34. );
  35. my $Hyperion_requiredVersion = "1.03.2";
  36. my $Hyperion_serverinfo = {"command" => "serverinfo"};
  37. my $Hyperion_webCmd = "rgb:effect:mode:dimDown:dimUp:on:off";
  38. my $Hyperion_webCmd_config = "rgb:effect:configFile:mode:dimDown:dimUp:on:off";
  39. my $Hyperion_homebridgeMapping = "On=state,subtype=TV.Licht,valueOn=/rgb.*/,cmdOff=off,cmdOn=mode+rgb ".
  40. "On=state,subtype=Umgebungslicht,valueOn=clearall,cmdOff=off,cmdOn=clearall ".
  41. "On=state,subtype=Effekt,valueOn=/effect.*/,cmdOff=off,cmdOn=mode+effect ";
  42. # "On=state,subtype=Knight.Rider,valueOn=/.*Knight_rider/,cmdOff=off,cmdOn=effect+Knight_rider " .
  43. # "On=configFile,subtype=Eingang.HDMI,valueOn=hyperion-hdmi,cmdOff=configFile+hyperion,cmdOn=configFile+hyperion-hdmi ";
  44. sub Hyperion_Initialize($)
  45. {
  46. my ($hash) = @_;
  47. $hash->{AttrFn} = "Hyperion_Attr";
  48. $hash->{DefFn} = "Hyperion_Define";
  49. $hash->{GetFn} = "Hyperion_Get";
  50. $hash->{NotifyFn} = "Hyperion_Notify";
  51. $hash->{ReadFn} = "Hyperion_Read";
  52. $hash->{SetFn} = "Hyperion_Set";
  53. $hash->{UndefFn} = "Hyperion_Undef";
  54. $hash->{AttrList} = "disable:1,0 ".
  55. "disabledForIntervals ".
  56. "hyperionBin ".
  57. "hyperionConfigDir ".
  58. "hyperionCustomEffects:textField-long ".
  59. "hyperionDefaultDuration ".
  60. "hyperionDefaultPriority ".
  61. "hyperionDimStep ".
  62. "hyperionGainStep ".
  63. "hyperionNoSudo:1 ".
  64. "hyperionSshUser ".
  65. "hyperionToggleModes ".
  66. "hyperionVersionCheck:0 ".
  67. "queryAfterSet:0 ".
  68. $readingFnAttributes;
  69. FHEM_colorpickerInit();
  70. }
  71. sub Hyperion_Define($$)
  72. {
  73. my ($hash,$def) = @_;
  74. my @args = split " ",$def;
  75. return "Usage: define <name> Hyperion <IP> <PORT> [<INTERVAL>]"
  76. if (@args < 4);
  77. my ($name,$type,$host,$port,$interval) = @args;
  78. if ($interval)
  79. {
  80. $hash->{INTERVAL} = $interval;
  81. }
  82. else
  83. {
  84. delete $hash->{INTERVAL};
  85. }
  86. $hash->{IP} = $host;
  87. $hash->{PORT} = $port;
  88. $interval = 5 if ($interval && $interval < 5);
  89. $hash->{NOTIFYDEV} = "global";
  90. $hash->{DeviceName} = "$host:$port";
  91. RemoveInternalTimer($hash);
  92. if ($init_done && !defined $hash->{OLDDEF})
  93. {
  94. addToDevAttrList($name,"lightSceneParamsToSave") if (!grep /^lightSceneParamsToSave/,split(" ",$attr{"global"}{userattr}));
  95. addToDevAttrList($name,"homebridgeMapping:textField-long") if (!grep /^homebridgeMapping/,split(" ",$attr{"global"}{userattr}));
  96. $attr{$name}{alias} = "Ambilight";
  97. $attr{$name}{cmdIcon} = "on:general_an off:general_aus dimDown:dimdown dimUp:dimup";
  98. $attr{$name}{devStateIcon} = '{Hyperion_devStateIcon($name)}';
  99. $attr{$name}{homebridgeMapping} = $Hyperion_homebridgeMapping;
  100. $attr{$name}{icon} = "light_led_stripe_rgb";
  101. $attr{$name}{lightSceneParamsToSave} = "state";
  102. $attr{$name}{room} = "Hyperion";
  103. $attr{$name}{webCmd} = $Hyperion_webCmd;
  104. $attr{$name}{widgetOverride} = "dimUp:noArg dimDown:noArg";
  105. }
  106. return Hyperion_OpenDev($hash);
  107. }
  108. sub Hyperion_Notify($$)
  109. {
  110. my ($hash,$dev) = @_;
  111. my $name = $hash->{NAME};
  112. return if (IsDisabled($name));
  113. return if (!grep /^REREADCFG|MODIFIED\s$name$/,@{$dev->{CHANGED}});
  114. return Hyperion_OpenDev($hash);
  115. }
  116. sub Hyperion_OpenDev($)
  117. {
  118. my ($hash) = @_;
  119. DevIo_CloseDev($hash);
  120. DevIo_OpenDev($hash,1,DevIo_SimpleWrite($hash,encode_json($Hyperion_serverinfo),2,1),sub($$$)
  121. {
  122. my ($h,$err) = @_;
  123. InternalTimer(gettimeofday() + 5,"Hyperion_GetUpdate",$hash);
  124. if ($err)
  125. {
  126. readingsBeginUpdate($hash);
  127. readingsBulkUpdate($hash,"lastError",$err);
  128. readingsBulkUpdate($hash,"serverResponse","ERROR");
  129. readingsBulkUpdate($hash,"state","ERROR");
  130. readingsEndUpdate($hash,1);
  131. return "ERROR: $err";
  132. }
  133. else
  134. {
  135. return $hash->{DeviceName}." connected";
  136. }
  137. });
  138. }
  139. sub Hyperion_Undef($$)
  140. {
  141. my ($hash,$name) = @_;
  142. RemoveInternalTimer($hash);
  143. BlockingKill($hash->{helper}{RUNNING_PID}) if ($hash->{helper}{RUNNING_PID});
  144. DevIo_CloseDev($hash);
  145. return;
  146. }
  147. sub Hyperion_list2array($$)
  148. {
  149. my ($list,$round) = @_;
  150. my @arr;
  151. foreach my $part (split /,/,$list)
  152. {
  153. $part = sprintf($round,$part) * 1;
  154. push @arr,$part;
  155. }
  156. return \@arr;
  157. }
  158. sub Hyperion_isLocal($)
  159. {
  160. my ($ip) = @_;
  161. return ($ip =~ /^(localhost|127\.0{1,3}\.0{1,3}\.0{0,2}1|::1)$/) ? 1 : undef;
  162. }
  163. sub Hyperion_Get($@)
  164. {
  165. my ($hash,$name,$cmd) = @_;
  166. return if (IsDisabled($name) && $cmd ne "?");
  167. my $params = "devStateIcon:noArg ".
  168. "statusRequest:noArg ".
  169. "configFiles:noArg ";
  170. return "get $name needs one parameter: $params"
  171. if (!$cmd);
  172. if ($cmd eq "configFiles")
  173. {
  174. return "Work already/still in progress... Please wait for the current process to finish." if ($hash->{helper}{RUNNING_PID} && !$hash->{helper}{RUNNING_PID}{terminated});
  175. Hyperion_GetConfigs($hash);
  176. }
  177. elsif ($cmd eq "devStateIcon")
  178. {
  179. return Hyperion_devStateIcon($hash);
  180. }
  181. elsif ($cmd eq "statusRequest")
  182. {
  183. Hyperion_GetUpdate($hash);
  184. }
  185. else
  186. {
  187. return "Unknown argument $cmd for $name, choose one of $params";
  188. }
  189. }
  190. sub Hyperion_Read($)
  191. {
  192. my ($hash) = @_;
  193. my $name = $hash->{NAME};
  194. my $buf = DevIo_SimpleRead($hash);
  195. return if (!$buf);
  196. $buf =~ s/[\r\n]//gm;
  197. my $result = $hash->{PARTIAL} ? $hash->{PARTIAL}.$buf : $buf;
  198. $hash->{PARTIAL} = $result;
  199. return if ($buf !~ /(^.+"success":(true|false)\}$)/);
  200. Log3 $name,5,"$name: url $hash->{DeviceName} returned result: $result";
  201. delete $hash->{PARTIAL};
  202. if ($result =~ /^\{"success":true\}$/)
  203. {
  204. AnalyzeCommandChain(undef,"sleep 1; get $name statusRequest")
  205. if (AttrVal($name,"queryAfterSet",1) == 1 || !$hash->{INTERVAL});
  206. return;
  207. }
  208. elsif ($result =~ /^\{"info":\{.+\},"success":true\}$/)
  209. {
  210. my $obj = eval {decode_json($result)};
  211. my $data = $obj->{info};
  212. if (AttrVal($name,"hyperionVersionCheck",1) == 1)
  213. {
  214. my $error;
  215. $error = "Can't detect your version of hyperion!"
  216. if (!$data->{hyperion_build}->[0]->{version});
  217. if (!$error)
  218. {
  219. my $ver = (split /V/,(split " ",$data->{hyperion_build}->[0]->{version})[0])[1];
  220. $ver =~ s/\.//g;
  221. $ver = $ver * 1;
  222. my $rver = $Hyperion_requiredVersion;
  223. $rver =~ s/\.//g;
  224. $rver = $rver * 1;
  225. $error = "Your version of hyperion (detected version: ".$data->{hyperion_build}->[0]->{version}.") is not (longer) supported by this module!" if ($ver<$rver);
  226. }
  227. else
  228. {
  229. $error = "ATTENTION!!! $error Please update your hyperion to V$Hyperion_requiredVersion at least using HyperCon...";
  230. Log3 $name,1,$error;
  231. readingsBeginUpdate($hash);
  232. readingsBulkUpdate($hash,"serverResponse","ERROR");
  233. readingsBulkUpdate($hash,"lastError",$error);
  234. readingsBulkUpdate($hash,"state","ERROR");
  235. readingsEndUpdate($hash,1);
  236. return;
  237. }
  238. }
  239. my $vers = $data->{hyperion_build}->[0]->{version} ? $data->{hyperion_build}->[0]->{version} : "";
  240. my $prio = (defined $data->{priorities}->[0]->{priority}) ? $data->{priorities}->[0]->{priority} : "";
  241. my $duration = (defined $data->{priorities}->[0]->{duration_ms} && $data->{priorities}->[0]->{duration_ms} > 999) ? int($data->{priorities}->[0]->{duration_ms} / 1000) : 0;
  242. $duration = $duration >= 1 ? $duration : "infinite";
  243. my $adj = $data->{adjustment}->[0] ? $data->{adjustment}->[0] : undef;
  244. my $col = $data->{activeLedColor}->[0]->{"HEX Value"}->[0] ? $data->{activeLedColor}->[0]->{"HEX Value"}->[0] : "";
  245. $col = "" if ($col =~ /000000$/);
  246. my $configs = ReadingsVal($name,".configs",undef);
  247. my $corr = $data->{correction}->[0] ? $data->{correction}->[0] : undef;
  248. my $effects = $data->{effects} ? $data->{effects} : undef;
  249. if ($hash->{helper}{customeffects})
  250. {
  251. foreach my $eff (@{$hash->{helper}{customeffects}})
  252. {
  253. push @{$effects},$eff;
  254. }
  255. }
  256. my $effectList = $effects ? join(",",map {"$_->{name}"} @{$effects}) : "";
  257. $effectList =~ s/ /_/g;
  258. my $effargs = $data->{activeEffects}->[0]->{args} ? JSON->new->convert_blessed->canonical->encode($data->{activeEffects}->[0]->{args}) : undef;
  259. my $script = $data->{activeEffects}->[0]->{script} ? $data->{activeEffects}->[0]->{script} : undef;
  260. my $temp = $data->{temperature}->[0] ? $data->{temperature}->[0] : undef;
  261. my $trans = $data->{transform}->[0] ? $data->{transform}->[0] : undef;
  262. my $id = $trans->{id} ? $trans->{id} : undef;
  263. my $adjR = $adj ? join(",",@{$adj->{redAdjust}}) : undef;
  264. my $adjG = $adj ? join(",",@{$adj->{greenAdjust}}) : undef;
  265. my $adjB = $adj ? join(",",@{$adj->{blueAdjust}}) : undef;
  266. my $corS = $corr ? join(",",@{$corr->{correctionValues}}) : undef;
  267. my $temP = $temp ? join(",",@{$temp->{correctionValues}}) : undef;
  268. my $blkL = $trans->{blacklevel} ? sprintf("%.2f",$trans->{blacklevel}->[0]).",".sprintf("%.2f",$trans->{blacklevel}->[1]).",".sprintf("%.2f",$trans->{blacklevel}->[2]) : undef;
  269. my $gamM = $trans->{gamma} ? sprintf("%.2f",$trans->{gamma}->[0]).",".sprintf("%.2f",$trans->{gamma}->[1]).",".sprintf("%.2f",$trans->{gamma}->[2]) : undef;
  270. my $thrE = $trans->{threshold} ? sprintf("%.2f",$trans->{threshold}->[0]).",".sprintf("%.2f",$trans->{threshold}->[1]).",".sprintf("%.2f",$trans->{threshold}->[2]) : undef;
  271. my $whiL = $trans->{whitelevel} ? sprintf("%.2f",$trans->{whitelevel}->[0]).",".sprintf("%.2f",$trans->{whitelevel}->[1]).",".sprintf("%.2f",$trans->{whitelevel}->[2]) : undef;
  272. my $lumG = defined $trans->{luminanceGain} ? sprintf("%.2f",$trans->{luminanceGain}) : undef;
  273. my $lumM = defined $trans->{luminanceMinimum} ? sprintf("%.2f",$trans->{luminanceMinimum}) : undef;
  274. my $satG = defined $trans->{saturationGain} ? sprintf("%.2f",$trans->{saturationGain}) : undef;
  275. my $satL = defined $trans->{saturationLGain} ? sprintf("%.2f",$trans->{saturationLGain}) : undef;
  276. my $valG = defined $trans->{valueGain} ? sprintf("%.2f",$trans->{valueGain}) : undef;
  277. $hash->{hostname} = $data->{hostname} if (($data->{hostname} && !$hash->{hostname}) || ($data->{hostname} && $hash->{hostname} ne $data->{hostname}));
  278. $hash->{build_version} = $vers if (($vers && !$hash->{build_version}) || ($vers && $hash->{build_version} ne $vers));
  279. $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}));
  280. readingsBeginUpdate($hash);
  281. readingsBulkUpdate($hash,"adjustRed",$adjR);
  282. readingsBulkUpdate($hash,"adjustGreen",$adjG);
  283. readingsBulkUpdate($hash,"adjustBlue",$adjB);
  284. readingsBulkUpdate($hash,"blacklevel",$blkL);
  285. readingsBulkUpdate($hash,"colorTemperature",$temP);
  286. readingsBulkUpdate($hash,"correction",$corS);
  287. readingsBulkUpdate($hash,"effect",(split /,/,$effectList)[0]) if (!defined ReadingsVal($name,"effect",undef));
  288. readingsBulkUpdate($hash,".effects",$effectList);
  289. readingsBulkUpdate($hash,"effectArgs",$effargs);
  290. readingsBulkUpdate($hash,"duration",$duration);
  291. readingsBulkUpdate($hash,"gamma",$gamM);
  292. readingsBulkUpdate($hash,"id",$id);
  293. readingsBulkUpdate($hash,"luminanceGain",$lumG);
  294. readingsBulkUpdate($hash,"luminanceMinimum",$lumM);
  295. readingsBulkUpdate($hash,"priority",$prio);
  296. readingsBulkUpdate($hash,"rgb","ff0d0d") if (!defined ReadingsVal($name,"rgb",undef));
  297. readingsBulkUpdate($hash,"saturationGain",$satG);
  298. readingsBulkUpdate($hash,"saturationLGain",$satL);
  299. readingsBulkUpdate($hash,"threshold",$thrE);
  300. readingsBulkUpdate($hash,"valueGain",$valG);
  301. readingsBulkUpdate($hash,"whitelevel",$whiL);
  302. if ($script)
  303. {
  304. my $effname;
  305. my $tempname;
  306. foreach my $e (@$effects)
  307. {
  308. if ($e->{script} && $e->{script} eq $script)
  309. {
  310. $tempname = $e->{name};
  311. $effname = $e->{name} if (JSON->new->convert_blessed->canonical->encode($e->{args}) eq $effargs);
  312. }
  313. }
  314. if (!$effname)
  315. {
  316. foreach my $e (@{$hash->{helper}{customeffects}})
  317. {
  318. $effname = $e->{name} if (JSON->new->convert_blessed->canonical->encode($e->{args}) eq $effargs);
  319. }
  320. }
  321. $effname = $effname ? $effname : $tempname;
  322. $effname =~ s/ /_/g;
  323. readingsBulkUpdate($hash,"effect",$effname);
  324. readingsBulkUpdate($hash,"mode","effect");
  325. readingsBulkUpdate($hash,"state","effect $effname");
  326. readingsBulkUpdate($hash,"mode_before_off","effect");
  327. Log3 $name,4,"$name: effect $effname";
  328. }
  329. elsif ($col)
  330. {
  331. my $rgb = lc((split /x/,$col)[1]);
  332. my ($r,$g,$b) = Color::hex2rgb($rgb);
  333. my ($h,$s,$v) = Color::rgb2hsv($r / 255,$g / 255,$b / 255);
  334. my $dim = int($v * 100);
  335. readingsBulkUpdate($hash,"rgb",$rgb);
  336. readingsBulkUpdate($hash,"dim",$dim);
  337. readingsBulkUpdate($hash,"mode","rgb");
  338. readingsBulkUpdate($hash,"mode_before_off","rgb");
  339. readingsBulkUpdate($hash,"state","rgb $rgb");
  340. Log3 $name,4,"$name: rgb $rgb";
  341. }
  342. else
  343. {
  344. if ($prio && defined $data->{priorities}->[0]->{duration_ms} && !defined $data->{priorities}->[1]->{priority})
  345. {
  346. readingsBulkUpdate($hash,"mode","clearall");
  347. readingsBulkUpdate($hash,"mode_before_off","clearall");
  348. readingsBulkUpdate($hash,"state","clearall");
  349. Log3 $name,4,"$name: clearall";
  350. }
  351. else
  352. {
  353. readingsBulkUpdate($hash,"mode","off");
  354. readingsBulkUpdate($hash,"state","off");
  355. Log3 $name,4,"$name: off";
  356. }
  357. }
  358. readingsBulkUpdate($hash,"serverResponse","success");
  359. readingsEndUpdate($hash,1);
  360. }
  361. else
  362. {
  363. Log3 $name,4,"$name: error while requesting ".$hash->{DeviceName}." - $result";
  364. readingsBeginUpdate($hash);
  365. readingsBulkUpdate($hash,"lastError","error while requesting ".$hash->{DeviceName});
  366. readingsBulkUpdate($hash,"serverResponse","ERROR");
  367. readingsBulkUpdate($hash,"state","ERROR");
  368. readingsEndUpdate($hash,1);
  369. }
  370. return;
  371. }
  372. sub Hyperion_GetConfigs($)
  373. {
  374. my ($hash) = @_;
  375. my $name = $hash->{NAME};
  376. my $ip = $hash->{IP};
  377. my $dir = AttrVal($name,"hyperionConfigDir","/etc/hyperion/");
  378. my $com = "ls $dir";
  379. if (!Hyperion_isLocal($ip))
  380. {
  381. my $ssh = qx(which ssh);
  382. chomp $ssh;
  383. return "SSH client could NOT be found!" if (!$ssh);
  384. my $user = AttrVal($name,"hyperionSshUser","pi");
  385. $com = "$ssh $user\@$ip '$com'";
  386. }
  387. Log3 $name,4,"$name: lsCmd: $com";
  388. $com = encode_base64($com);
  389. $hash->{helper}{RUNNING_PID} = BlockingCall("Hyperion_ExecCmd","$name|$com","Hyperion_GetConfigs_finished");
  390. return "Working in background...";
  391. }
  392. sub Hyperion_GetConfigs_finished($)
  393. {
  394. my ($string) = @_;
  395. my @a = split /\|/,$string;
  396. my $name = $a[0];
  397. my @files;
  398. @files = split " ",$a[1] if ($a[1]);
  399. my $hash = $defs{$name};
  400. my $ip = $hash->{IP};
  401. my $dir = AttrVal($name,"hyperionConfigDir","/etc/hyperion/");
  402. delete $hash->{helper}{RUNNING_PID};
  403. my @filelist;
  404. foreach (@files)
  405. {
  406. my $file = $_;
  407. next if ($file !~ /^([-\.\w]+)\.config\.json$/);
  408. $file = $1;
  409. push @filelist,$file;
  410. Log3 $name,4,"$name: matching config file: \"$_\"";
  411. }
  412. if (@filelist)
  413. {
  414. my $configs = join(",",@filelist);
  415. readingsSingleUpdate($hash,".configs",$configs,0);
  416. CommandAttr(undef,"$name webCmd $Hyperion_webCmd_config") if (AttrVal($name,"webCmd","") eq $Hyperion_webCmd && @filelist > 1);
  417. CommandAttr(undef,"$name webCmd $Hyperion_webCmd") if (AttrVal($name,"webCmd","") eq $Hyperion_webCmd_config && @filelist < 2);
  418. }
  419. else
  420. {
  421. CommandDeleteReading(undef,"$name .configs") if (ReadingsVal($name,".configs",""));
  422. CommandAttr(undef,"$name webCmd $Hyperion_webCmd") if (AttrVal($name,"webCmd","") eq $Hyperion_webCmd_config);
  423. Log3 $name,3,"$name: 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)?";
  424. }
  425. Hyperion_GetUpdate($hash);
  426. return;
  427. }
  428. sub Hyperion_GetUpdate(@)
  429. {
  430. my ($hash) = @_;
  431. my $name = $hash->{NAME};
  432. RemoveInternalTimer($hash);
  433. return if (IsDisabled($name));
  434. InternalTimer(gettimeofday() + $hash->{INTERVAL},"Hyperion_GetUpdate",$hash) if ($hash->{INTERVAL});
  435. if (!$hash->{FD})
  436. {
  437. Hyperion_OpenDev($hash);
  438. return;
  439. }
  440. Hyperion_Call($hash);
  441. return;
  442. }
  443. sub Hyperion_ExecCmd($)
  444. {
  445. my ($string) = @_;
  446. my @a = split /\|/,$string;
  447. my $name = $a[0];
  448. my $cmd = decode_base64($a[1]);
  449. my $hash = $defs{$name};
  450. my @qx = qx($cmd);
  451. my @ret;
  452. my $re = "";
  453. foreach (@qx)
  454. {
  455. chomp $_;
  456. $_ =~ s/^[\s\t]{1,}/ /;
  457. push @ret,$_;
  458. }
  459. $re .= join " ",@ret if (@ret);
  460. return "$name|$re";
  461. }
  462. sub Hyperion_Kill_finished($)
  463. {
  464. my ($string) = @_;
  465. my @a = split /\|/,$string;
  466. my $name = $a[0];
  467. my $error = $a[1];
  468. my $hash = $defs{$name};
  469. delete $hash->{helper}{RUNNING_PID};
  470. if ($error)
  471. {
  472. Log3 $name,3,"$name: Not able to stop Hyperion! Error: $error";
  473. readingsSingleUpdate($hash,"lastError",$error,1);
  474. }
  475. else
  476. {
  477. Log3 $name,3,"$name: Hyperion has been stopped";
  478. RemoveInternalTimer($hash);
  479. DevIo_Disconnected($hash);
  480. }
  481. return undef;
  482. }
  483. sub Hyperion_Restart($)
  484. {
  485. my ($string) = @_;
  486. my @a = split /\|/,$string;
  487. my $name = $a[0];
  488. my $error = $a[1];
  489. my $hash = $defs{$name};
  490. delete $hash->{helper}{RUNNING_PID};
  491. if ($error)
  492. {
  493. Log3 $name,3,"$name: Not able to stop Hyperion! Error: $error";
  494. readingsSingleUpdate($hash,"lastError",$error,1);
  495. }
  496. else
  497. {
  498. my $cmd = $hash->{helper}{startCmd};
  499. $hash->{helper}{RUNNING_PID} = BlockingCall("Hyperion_ExecCmd","$name|$cmd","Hyperion_Restart_finished");
  500. }
  501. return undef;
  502. }
  503. sub Hyperion_Restart_finished($)
  504. {
  505. my ($string) = @_;
  506. my @a = split /\|/,$string;
  507. my $name = $a[0];
  508. my $error = $a[1];
  509. my $hash = $defs{$name};
  510. delete $hash->{helper}{RUNNING_PID};
  511. my $file = $hash->{helper}{configFile};
  512. delete $hash->{helper}{configFile};
  513. delete $hash->{helper}{startCmd};
  514. if ($error)
  515. {
  516. Log3 $name,3,"$name: Hyperion could not be restarted! Error: $error";
  517. readingsSingleUpdate($hash,"lastError",$error,1);
  518. }
  519. else
  520. {
  521. Log3 $name,3,"$name: Hyperion restarted with configFile $file";
  522. RemoveInternalTimer($hash);
  523. DevIo_Disconnected($hash);
  524. $file =~ s/\.config\.json$//;
  525. readingsSingleUpdate($hash,"configFile",$file,1);
  526. InternalTimer(gettimeofday() + 3,"Hyperion_OpenDev",$hash);
  527. }
  528. return undef;
  529. }
  530. sub Hyperion_Set($@)
  531. {
  532. my ($hash,$name,@aa) = @_;
  533. my ($cmd,@args) = @aa;
  534. return if (IsDisabled($name) && $cmd ne "?");
  535. my $value = (defined($args[0])) ? $args[0] : undef;
  536. return "\"set $name\" needs at least one argument and maximum five arguments" if (@aa < 1 || @aa > 5);
  537. my $duration = (defined $args[1]) ? int $args[1] : int AttrVal($name,"hyperionDefaultDuration",0);
  538. my $priority = (defined $args[2]) ? int $args[2] : int AttrVal($name,"hyperionDefaultPriority",0);
  539. my %Hyperion_sets_local = %Hyperion_sets;
  540. if (ReadingsVal($name,".configs",""))
  541. {
  542. $Hyperion_sets_local{configFile} = ReadingsVal($name,".configs","");
  543. $Hyperion_sets_local{binary} = "restart,stop";
  544. }
  545. $Hyperion_sets_local{adjustRed} = "textField" if (ReadingsVal($name,"adjustRed",""));
  546. $Hyperion_sets_local{adjustGreen} = "textField" if (ReadingsVal($name,"adjustGreen",""));
  547. $Hyperion_sets_local{adjustBlue} = "textField" if (ReadingsVal($name,"adjustBlue",""));
  548. $Hyperion_sets_local{correction} = "textField" if (ReadingsVal($name,"correction",""));
  549. $Hyperion_sets_local{effect} = ReadingsVal($name,".effects","") if (ReadingsVal($name,".effects",""));
  550. $Hyperion_sets_local{colorTemperature} = "textField" if (ReadingsVal($name,"colorTemperature",""));
  551. $Hyperion_sets_local{blacklevel} = "textField" if (ReadingsVal($name,"blacklevel",""));
  552. $Hyperion_sets_local{gamma} = "textField" if (ReadingsVal($name,"gamma",""));
  553. $Hyperion_sets_local{threshold} = "textField" if (ReadingsVal($name,"threshold",""));
  554. $Hyperion_sets_local{whitelevel} = "textField" if (ReadingsVal($name,"whitelevel",""));
  555. $Hyperion_sets_local{luminanceGain} = "slider,0,0.01,5,1" if (ReadingsVal($name,"luminanceGain",""));
  556. $Hyperion_sets_local{luminanceMinimum} = "slider,0,0.01,5,1" if (ReadingsVal($name,"luminanceMinimum",""));
  557. $Hyperion_sets_local{saturationGain} = "slider,0,0.01,5,1" if (ReadingsVal($name,"saturationGain",""));
  558. $Hyperion_sets_local{saturationLGain} = "slider,0,0.01,5,1" if (ReadingsVal($name,"saturationLGain",""));
  559. $Hyperion_sets_local{valueGain} = "slider,0,0.01,5,1" if (ReadingsVal($name,"valueGain",""));
  560. my $params = join(" ",map {"$_:$Hyperion_sets_local{$_}"} keys %Hyperion_sets_local);
  561. my %obj;
  562. Log3 $name,4,"$name: Hyperion_Set cmd: $cmd";
  563. Log3 $name,4,"$name: Hyperion_Set value: $value" if ($value);
  564. Log3 $name,4,"$name: Hyperion_Set duration: $duration, priority: $priority" if ($cmd =~ /^rgb|dim|dimUp|dimDown|effect$/);
  565. if ($cmd =~ /^configFile|binary$/)
  566. {
  567. return "Work already/still in progress... Please wait for the current process to finish." if ($hash->{helper}{RUNNING_PID} && !$hash->{helper}{RUNNING_PID}{terminated});
  568. my $binpath = AttrVal($name,"hyperionBin","/usr/bin/hyperiond");
  569. my $bin = (split "/",$binpath)[scalar(split "/",$binpath) - 1];
  570. $bin =~ s/\.sh$// if ($bin =~ /\.sh$/);
  571. my $confdir = AttrVal($name,"hyperionConfigDir","/etc/hyperion/");
  572. my $user = AttrVal($name,"hyperionSshUser","pi");
  573. my $ip = $hash->{IP};
  574. my $sudo = ($user eq "root" || int AttrVal($name,"hyperionNoSudo",0) == 1) ? "" : "sudo ";
  575. my $kill = $sudo."kill `pidof $bin`";
  576. my $ssh;
  577. if (!Hyperion_isLocal($ip))
  578. {
  579. $ssh = qx(which ssh);
  580. chomp $ssh;
  581. return "SSH client could NOT be found!" if (!$ssh);
  582. }
  583. my $com = Hyperion_isLocal($ip)?"":"$ssh $user\@$ip '";
  584. if ($cmd eq "binary")
  585. {
  586. return "Value of $cmd has to be 'stop' or 'restart'" if ($value !~ /^(stop|restart)$/);
  587. }
  588. else
  589. {
  590. return "Value of $cmd must be given and must be an available config file!" if (!$value || !grep(/^$value$/,split /,/,ReadingsVal($name,".configs","")));
  591. }
  592. if ($cmd eq "binary" && $value eq "stop")
  593. {
  594. $com .= $kill;
  595. $com .= Hyperion_isLocal($ip)?"":"'";
  596. Log3 $name,4,"$name: stopCmd: $com";
  597. $com = encode_base64($com);
  598. $hash->{helper}{RUNNING_PID} = BlockingCall("Hyperion_ExecCmd","$name|$com","Hyperion_Kill_finished");
  599. }
  600. elsif (($cmd eq "binary" && $value eq "restart") || $cmd eq "configFile")
  601. {
  602. my $file;
  603. if ($value eq "restart")
  604. {
  605. $file = ReadingsVal($name,"configFile","")?ReadingsVal($name,"configFile",""):ReadingsVal($name,".configs","")?(split /,/,ReadingsVal($name,".configs",""))[0]:"";
  606. return "No restart possible because no configFile is available." if (!$file);
  607. }
  608. else
  609. {
  610. $file = $value;
  611. }
  612. my $start = $com;
  613. $file .= ".config.json";
  614. $com .= $kill;
  615. $start .= "$sudo$binpath $confdir".$file." > /dev/null 2>&1 &";
  616. if (!Hyperion_isLocal($ip))
  617. {
  618. $com .= "'";
  619. $start .= "'";
  620. }
  621. Log3 $name,4,"$name: stopCmd: $com";
  622. Log3 $name,4,"$name: startCmd: $start";
  623. $com = encode_base64($com);
  624. $hash->{helper}{configFile} = $file;
  625. $hash->{helper}{startCmd} = encode_base64($start);
  626. $hash->{helper}{RUNNING_PID} = BlockingCall("Hyperion_ExecCmd","$name|$com","Hyperion_Restart");
  627. }
  628. return;
  629. }
  630. elsif ($cmd eq "rgb")
  631. {
  632. return "Value of $cmd has to be in RGB hex format like ffffff or 3F7D90"
  633. if ($value !~ /^[\dA-Fa-f]{6}$/);
  634. $value = lc $value;
  635. my ($r,$g,$b) = Color::hex2rgb($value);
  636. $obj{color} = [$r,$g,$b];
  637. $obj{command} = "color";
  638. $obj{priority} = $priority * 1;
  639. $obj{duration} = $duration * 1000 if ($duration > 0);
  640. }
  641. elsif ($cmd eq "dim")
  642. {
  643. return "Value of $cmd has to be between 1 and 100"
  644. if ($value !~ /^(\d+)$/ || $1 > 100 || $1 < 1);
  645. my $rgb = ReadingsVal($name,"rgb","ffffff");
  646. $value = $value + 1
  647. if ($cmd eq "dim" && $value < 100);
  648. $value = $value / 100;
  649. my ($r,$g,$b) = Color::hex2rgb($rgb);
  650. my ($h,$s,$v) = Color::rgb2hsv($r / 255,$g / 255,$b / 255);
  651. my ($rn,$gn,$bn);
  652. ($rn,$gn,$bn) = Color::hsv2rgb($h,$s,$value)
  653. if ($cmd eq "dim");
  654. $rn = int($rn * 255);
  655. $gn = int($gn * 255);
  656. $bn = int($bn * 255);
  657. $obj{color} = [$rn,$gn,$bn];
  658. $obj{command} = "color";
  659. $obj{priority} = $priority * 1;
  660. $obj{duration} = $duration * 1000
  661. if ($duration > 0);
  662. }
  663. elsif ($cmd =~ /^(dimUp|dimDown)$/)
  664. {
  665. return "Value of $cmd has to be between 1 and 99"
  666. if (defined $value && ($value !~ /^(\d+)$/ || $1 > 99 || $1 < 1));
  667. my $dim = ReadingsVal($name,"dim",100);
  668. my $dimStep = $value ? $value : AttrVal($name,"hyperionDimStep",10);
  669. my $dimUp = ($dim + $dimStep < 100) ? $dim + $dimStep : 100;
  670. my $dimDown = ($dim - $dimStep > 0) ? $dim - $dimStep : 1;
  671. my $set = $cmd eq "dimUp" ? $dimUp : $dimDown;
  672. CommandSet(undef,"$name dim $set");
  673. return;
  674. }
  675. elsif ($cmd eq "effect")
  676. {
  677. return "Effect $value is not available in the effect list of $name!"
  678. if ($value !~ /^([\w-]+)$/ || index(ReadingsVal($name,".effects",""),$value) == -1);
  679. my $arg = $args[3] ? eval{decode_json $args[3]} : "";
  680. my $ce = $hash->{helper}{customeffects};
  681. if (!$arg && $ce)
  682. {
  683. foreach my $eff (@{$ce})
  684. {
  685. if ($eff->{name} eq $value)
  686. {
  687. $value = $eff->{oname};
  688. $arg = $eff->{args};
  689. }
  690. }
  691. }
  692. $value =~ s/_/ /g;
  693. my %ef = ("name" => $value);
  694. $ef{args} = $arg if ($arg);
  695. $obj{effect} = \%ef;
  696. $obj{command} = "effect";
  697. $obj{priority} = $priority * 1;
  698. $obj{duration} = $duration * 1000 if ($duration > 0);
  699. }
  700. elsif ($cmd eq "clearall")
  701. {
  702. return "$cmd need no additional value of $value" if (defined $value);
  703. $obj{command} = $cmd;
  704. }
  705. elsif ($cmd eq "clear")
  706. {
  707. return "Value of $cmd has to be between 0 and 65536 in steps of 1"
  708. if (defined $value && $value !~ /^(\d+)$/ || $1 > 65536);
  709. $obj{command} = $cmd;
  710. $value = defined $1 ? $1 : AttrVal($name,"hyperionDefaultPriority",0);
  711. $obj{priority} = $value*1;
  712. }
  713. elsif ($cmd eq "off")
  714. {
  715. return "$cmd need no additional value of $value" if (defined $value);
  716. $obj{command} = "color";
  717. $obj{color} = [0,0,0];
  718. $obj{priority} = AttrVal($name,"hyperionDefaultPriority",0)*1;
  719. }
  720. elsif ($cmd eq "on")
  721. {
  722. return "$cmd need no additional value of $value" if (defined $value);
  723. my $rmode = ReadingsVal($name,"mode_before_off","rgb");
  724. my $rrgb = ReadingsVal($name,"rgb","");
  725. my $reffect = ReadingsVal($name,"effect","");
  726. my ($r,$g,$b) = Color::hex2rgb($rrgb);
  727. my $set = "$rmode $rrgb";
  728. $set = "$rmode $reffect" if ($rmode eq "effect");
  729. $set = $rmode if ($rmode eq "clearall");
  730. CommandSet(undef,"$name $set");
  731. return;
  732. }
  733. elsif ($cmd eq "toggle")
  734. {
  735. return "$cmd need no additional value of $value" if (defined $value);
  736. my $state = Value($name);
  737. my $nstate = $state ne "off" ? "off" : "on";
  738. CommandSet(undef,"$name $nstate");
  739. return;
  740. }
  741. elsif ($cmd eq "toggleMode")
  742. {
  743. return "$cmd need no additional value of $value" if (defined $value);
  744. my $mode = ReadingsVal($name,"mode","off");
  745. my $nmode;
  746. my @modeorder = split /,/,AttrVal($name,"hyperionToggleModes","clearall,rgb,effect,off");
  747. for (my $i = 0; $i < @modeorder; $i++)
  748. {
  749. $nmode = $i < @modeorder - 1 ? $modeorder[$i+1] : $modeorder[0] if ($modeorder[$i] eq $mode);
  750. }
  751. $nmode = $nmode ? $nmode : $modeorder[0];
  752. CommandSet(undef,"$name mode $nmode");
  753. return;
  754. }
  755. elsif ($cmd eq "mode")
  756. {
  757. return "The value of mode has to be rgb,effect,clearall,off" if ($value !~ /^(off|clearall|rgb|effect)$/);
  758. Log3 $name,4,"$name: cmd: $cmd, value: $value";
  759. my $rmode = $value;
  760. my $rrgb = ReadingsVal($name,"rgb","");
  761. my $reffect = ReadingsVal($name,"effect","");
  762. my ($r,$g,$b) = Color::hex2rgb($rrgb);
  763. my $set = "$rmode $rrgb";
  764. $set = "$rmode $reffect" if ($rmode eq "effect");
  765. $set = $rmode if ($rmode eq "clearall");
  766. $set = $rmode if ($rmode eq "off");
  767. CommandSet(undef,"$name $set");
  768. return;
  769. }
  770. elsif ($cmd =~ /^(luminanceGain|luminanceMinimum|saturationGain|saturationLGain|valueGain)$/)
  771. {
  772. return "The value of $cmd has to be from 0.00 to 5.00 in steps of 0.01."
  773. if ($value !~ /^((\d)\.(\d){1,2})?$/ || $1 > 5);
  774. $value = sprintf("%.4f",$value) * 1;
  775. my %tr = ($cmd => $value);
  776. $obj{command} = "transform";
  777. $obj{transform} = \%tr;
  778. }
  779. elsif ($cmd =~ /^(blacklevel|gamma|threshold|whitelevel)$/)
  780. {
  781. return "Each of the three comma separated values of $cmd must be from 0.00 to 1.00 in steps of 0.01"
  782. if ($cmd =~ /^blacklevel|threshold|whitelevel$/ && ($value !~ /^((\d)\.(\d){1,2}),((\d)\.(\d){1,2}),((\d)\.(\d){1,2})$/ || $1 > 1 || $4 > 1 || $7 > 1));
  783. return "Each of the three comma separated values of $cmd must be from 0.00 to 5.00 in steps of 0.01"
  784. if ($cmd eq "gamma" && ($value !~ /^((\d)\.(\d){1,2}),((\d)\.(\d){1,2}),((\d)\.(\d){1,2})$/ || $1 > 5 || $4 > 5 || $7 > 5));
  785. my $arr = Hyperion_list2array($value,"%.4f");
  786. my %ar = ($cmd => $arr);
  787. $obj{command} = "transform";
  788. $obj{transform} = \%ar;
  789. }
  790. elsif ($cmd =~ /^(correction|colorTemperature)$/)
  791. {
  792. $cmd = "temperature" if ($cmd eq "colorTemperature");
  793. return "Each of the three comma separated values of $cmd must be from 0 to 255 in steps of 1"
  794. if ($value !~ /^(\d{1,3})?,(\d{1,3})?,(\d{1,3})?$/ || $1 > 255 || $2 > 255 || $3 > 255);
  795. my $arr = Hyperion_list2array($value,"%d");
  796. my %ar = ("correctionValues" => $arr);
  797. $obj{command} = $cmd;
  798. $obj{$cmd} = \%ar;
  799. }
  800. elsif ($cmd =~ /^(adjustRed|adjustGreen|adjustBlue)$/)
  801. {
  802. return "Each of the three comma separated values of $cmd must be from 0 an 255 in steps of 1"
  803. if ($value !~ /^(\d{1,3})?,(\d{1,3})?,(\d{1,3})?$/ || $1 > 255 || $2 > 255 || $3 > 255);
  804. $cmd = "redAdjust" if ($cmd eq "adjustRed");
  805. $cmd = "greenAdjust" if ($cmd eq "adjustGreen");
  806. $cmd = "blueAdjust" if ($cmd eq "adjustBlue");
  807. my $arr = Hyperion_list2array($value,"%d");
  808. my %ar = ($cmd => $arr);
  809. $obj{command} = "adjustment";
  810. $obj{adjustment} = \%ar;
  811. }
  812. elsif ($cmd =~ /^(valueGainUp|valueGainDown)$/)
  813. {
  814. return "Value of $cmd has to be between 0.1 and 1.0 in steps of 0.1"
  815. if (defined $value && ($value !~ /^(\d\.\d)$/ || $1 > 1 || $1 < 0.1));
  816. my $gain = ReadingsNum($name,"valueGain",1);
  817. my $gainStep = $value ? $value : AttrVal($name,"hyperionGainStep",0.1);
  818. my $gainUp = ($gain + $gainStep < 5) ? $gain + $gainStep : 5;
  819. my $gainDown = ($gain - $gainStep > 0) ? $gain - $gainStep : 0.1;
  820. my $set = $cmd eq "valueGainUp" ? $gainUp : $gainDown;
  821. CommandSet(undef,"$name valueGain $set");
  822. return;
  823. }
  824. elsif ($cmd eq "addEffect")
  825. {
  826. return "$name must be in effect mode!" if (ReadingsVal($name,"mode","off") ne "effect");
  827. return "Value of $cmd has to be a name like My_custom_EffeKt1 or my-effect!" if (!defined $value || $value !~ /^[a-zA-Z0-9_-]+$/);
  828. return "Effect with name $value already defined! Please choose a different name!" if (grep(/^$value$/,split /,/,ReadingsVal($name,".effects","")));
  829. my $eff = ReadingsVal($name,"effect","");
  830. foreach my $e (@{$hash->{helper}{customeffects}})
  831. {
  832. return "The base effect can't be a custom effect! Please set a non-custom effect first!" if ($e->{name} eq $eff);
  833. }
  834. my $effs = AttrVal($name,"hyperionCustomEffects","");
  835. $effs .= " " if ($effs);
  836. $effs .= '{"name":"'.$value.'","oname":"'.$eff.'","args":'.ReadingsVal($name,"effectArgs","").'}';
  837. CommandAttr(undef,"$name hyperionCustomEffects $effs");
  838. return;
  839. }
  840. elsif ($cmd eq "reopen")
  841. {
  842. Hyperion_OpenDev($hash);
  843. return;
  844. }
  845. if (keys %obj)
  846. {
  847. Log3 $name,5,"$name: $cmd obj json: ".encode_json(\%obj);
  848. SetExtensionsCancel($hash);
  849. Hyperion_Call($hash,\%obj);
  850. return;
  851. }
  852. return SetExtensions($hash,$params,$name,@aa);
  853. }
  854. sub Hyperion_Attr(@)
  855. {
  856. my ($cmd,$name,$attr_name,$attr_value) = @_;
  857. my $hash = $defs{$name};
  858. my $err;
  859. my $local = Hyperion_isLocal($hash->{IP});
  860. if ($cmd eq "set")
  861. {
  862. if ($attr_name eq "hyperionBin")
  863. {
  864. if ($attr_value !~ /^(\/.+){2,}$/)
  865. {
  866. $err = "Invalid value $attr_value for attribute $attr_name. Must be a path like /usr/bin/hyperiond.";
  867. }
  868. elsif ($local && !-e $attr_value)
  869. {
  870. $err = "The given file $attr_value is not available.";
  871. }
  872. }
  873. elsif ($attr_name eq "hyperionCustomEffects")
  874. {
  875. if ($attr_value !~ /^\{"name":"[a-zA-Z0-9_-]+","oname":"[a-zA-Z0-9_-]+","args":\{[a-zA-Z0-9:_\[\]\.",-]+\}\}([\s(\r\n)]\{"name":"[a-zA-Z0-9_-]+","oname":"[a-zA-Z0-9_-]+","args":\{[a-zA-Z0-9:_\[\]\.",-]+\}\}){0,}$/)
  876. {
  877. $err = "Invalid value $attr_value for attribute $attr_name. Must be a space separated list of JSON strings.";
  878. }
  879. else
  880. {
  881. my @custeffs = split " ",$attr_value;
  882. my @effs;
  883. if (@custeffs > 1)
  884. {
  885. foreach my $eff (@custeffs)
  886. {
  887. push @effs,eval{decode_json $eff};
  888. }
  889. }
  890. else
  891. {
  892. push @effs,eval{decode_json $attr_value};
  893. }
  894. $hash->{helper}{customeffects} = \@effs;
  895. Hyperion_Call($hash);
  896. }
  897. }
  898. elsif ($attr_name eq "hyperionConfigDir")
  899. {
  900. if ($attr_value !~ /^\/(.+\/){2,}/)
  901. {
  902. $err = "Invalid value $attr_value for attribute $attr_name. Must be a path with trailing slash like /etc/hyperion/.";
  903. }
  904. elsif ($local && !-d $attr_value)
  905. {
  906. $err = "The given directory $attr_value is not available.";
  907. }
  908. else
  909. {
  910. Hyperion_GetConfigs($hash);
  911. Hyperion_Call($hash);
  912. }
  913. }
  914. elsif ($attr_name =~ /^hyperionDefault(Priority|Duration)$/)
  915. {
  916. $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);
  917. }
  918. elsif ($attr_name eq "hyperionDimStep")
  919. {
  920. $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);
  921. }
  922. elsif ($attr_name eq "hyperionNoSudo")
  923. {
  924. $err = "Invalid value $attr_value for attribute $attr_name. Can only be value 1." if ($attr_value !~ /^1$/);
  925. }
  926. elsif ($attr_name eq "hyperionSshUser")
  927. {
  928. if ($attr_value !~ /^\w+$/)
  929. {
  930. $err = "Invalid value $attr_value for attribute $attr_name. Must be a name like pi or fhem.";
  931. }
  932. else
  933. {
  934. Hyperion_GetConfigs($hash);
  935. Hyperion_Call($hash);
  936. }
  937. }
  938. elsif ($attr_name eq "hyperionToggleModes")
  939. {
  940. $err = "Invalid value $attr_value for attribute $attr_name. Must be a comma separated list of available modes of clearall,rgb,effect,off. Each mode only once in the list." if ($attr_value !~ /^(clearall|rgb|effect|off),(clearall|rgb|effect|off)(,(clearall|rgb|effect|off)){0,2}$/);
  941. }
  942. elsif ($attr_name eq "hyperionVersionCheck")
  943. {
  944. $err = "Invalid value $attr_value for attribute $attr_name. Can only be value 0." if ($attr_value !~ /^0$/);
  945. }
  946. elsif ($attr_name eq "queryAfterSet")
  947. {
  948. $err = "Invalid value $attr_value for attribute $attr_name. Must be 0 if set, default is 1." if ($attr_value !~ /^0$/);
  949. }
  950. elsif ($attr_name eq "disable")
  951. {
  952. $err = "Invalid value $attr_value for attribute $attr_name. Must be 1 if set, default is 0." if ($attr_value !~ /^0|1$/);
  953. return $err if ($err);
  954. if ($attr_value == 1)
  955. {
  956. RemoveInternalTimer($hash);
  957. DevIo_Disconnected($hash);
  958. }
  959. else
  960. {
  961. Hyperion_OpenDev($hash);
  962. }
  963. }
  964. }
  965. else
  966. {
  967. delete $hash->{helper}{customeffects} if ($attr_name eq "hyperionCustomEffects");
  968. Hyperion_GetUpdate($hash) if (!IsDisabled($name));
  969. Hyperion_OpenDev($hash) if ($attr_name eq "disable");
  970. }
  971. return $err if ($err);
  972. return;
  973. }
  974. sub Hyperion_Call($;$)
  975. {
  976. my ($hash,$obj) = @_;
  977. $obj = $obj ? $obj : $Hyperion_serverinfo;
  978. my $name = $hash->{NAME};
  979. my $json = encode_json($obj);
  980. return if (IsDisabled($name));
  981. Log3 $name,5,"$name: Hyperion_Call: json object: $json";
  982. DevIo_SimpleWrite($hash,$json,2,1);
  983. }
  984. sub Hyperion_devStateIcon($;$)
  985. {
  986. my ($hash,$state) = @_;
  987. $hash = $defs{$hash} if (ref $hash ne "HASH");
  988. return if (!$hash);
  989. my $name = $hash->{NAME};
  990. my $rgb = ReadingsVal($name,"rgb","");
  991. my $dim = ReadingsVal($name,"dim",10);
  992. my $val = ReadingsVal($name,"state","off");
  993. my $mode = ReadingsVal($name,"mode","");
  994. my $ico = int($dim / 10) * 10 < 10 ? 10 : int($dim / 10) * 10;
  995. return ".*:off:on"
  996. if ($val =~ /^off|rgb\s000000$/);
  997. return ".*:light_exclamation"
  998. if (($val =~ /^(ERROR|disconnected)$/ && !$hash->{INTERVAL}) || ($val eq "ERROR" && $hash->{INTERVAL}));
  999. return ".*:light_light_dim_$ico@#".$rgb.":off"
  1000. if ($val ne "off" && $mode eq "rgb");
  1001. return ".*:light_led_stripe_rgb@#FFFF00:off"
  1002. if ($val ne "off" && $mode eq "effect");
  1003. return ".*:it_television@#0000FF:off"
  1004. if ($val ne "off" && $mode eq "clearall");
  1005. return ".*:light_question";
  1006. }
  1007. 1;
  1008. =pod
  1009. =item device
  1010. =item summary provides access to the Hyperion JSON server
  1011. =item summary_DE stellt Zugang zum Hyperion JSON Server zur Verf&uuml;gung
  1012. =begin html
  1013. <a name="Hyperion"></a>
  1014. <h3>Hyperion</h3>
  1015. <ul>
  1016. With <i>Hyperion</i> it is possible to change the color or start an effect on a hyperion server.<br>
  1017. It's also possible to control the complete color calibration (changes are temorary and will not be written to the config file).<br>
  1018. The Hyperion server must have enabled the JSON server.<br>
  1019. You can also restart Hyperion with different configuration files (p.e. switch input/grabber)<br>
  1020. <br>
  1021. <a name="Hyperion_define"></a>
  1022. <p><b>Define</b></p>
  1023. <ul>
  1024. <code>define &lt;name&gt; Hyperion &lt;IP or HOSTNAME&gt; &lt;PORT&gt; [&lt;INTERVAL&gt;]</code><br>
  1025. </ul>
  1026. <br>
  1027. &lt;INTERVAL&gt; is optional for periodically polling.<br>
  1028. <br>
  1029. <i>After defining "get &lt;name&gt; statusRequest" will be called once automatically to get the list of available effects and the current state of the Hyperion server.</i><br>
  1030. <br>
  1031. Example for running Hyperion on local system:
  1032. <br><br>
  1033. <ul>
  1034. <code>define Ambilight Hyperion localhost 19444 10</code><br>
  1035. </ul>
  1036. <br>
  1037. Example for running Hyperion on remote system:
  1038. <br><br>
  1039. <ul>
  1040. <code>define Ambilight Hyperion 192.168.1.4 19444 10</code><br>
  1041. </ul>
  1042. <br><br>
  1043. To change config files on your running Hyperion server or to stop/restart your Hyperion server you have to put the following code into your sudoers file (/etc/sudoers) (visudo):
  1044. <br><br>
  1045. <ul>
  1046. <code>fhem ALL=(ALL) NOPASSWD:/usr/bin/hyperiond,/bin/kill</code>
  1047. </ul>
  1048. <br>
  1049. <a name="Hyperion_set"></a>
  1050. <p><b>set &lt;required&gt; [optional]</b></p>
  1051. <ul>
  1052. <li>
  1053. <i>addEffect &lt;custom_name&gt;</i><br>
  1054. add the current effect with the given name to the custom effects<br>
  1055. can be altered after adding in attribute hyperionCustomEffects<br>
  1056. device has to be in effect mode with a non-custom effect and given name must be a unique effect name
  1057. </li>
  1058. <li>
  1059. <i>adjustBlue &lt;0,0,255&gt;</i><br>
  1060. adjust each color of blue separately (comma separated) (R,G,B)<br>
  1061. values from 0 to 255 in steps of 1
  1062. </li>
  1063. <li>
  1064. <i>adjustGreen &lt;0,255,0&gt;</i><br>
  1065. adjust each color of green separately (comma separated) (R,G,B)<br>
  1066. values from 0 to 255 in steps of 1
  1067. </li>
  1068. <li>
  1069. <i>adjustRed &lt;255,0,0&gt;</i><br>
  1070. adjust each color of red separately (comma separated) (R,G,B)<br>
  1071. values from 0 to 255 in steps of 1
  1072. </li>
  1073. <li>
  1074. <i>binary &lt;restart/stop&gt;</i><br>
  1075. restart or stop the hyperion binary<br>
  1076. only available after successful "get &lt;name&gt; configFiles"
  1077. </li>
  1078. <li>
  1079. <i>blacklevel &lt;0.00,0.00,0.00&gt;</i><br>
  1080. adjust blacklevel of each color separately (comma separated) (R,G,B)<br>
  1081. values from 0.00 to 1.00 in steps of 0.01
  1082. </li>
  1083. <li>
  1084. <i>clear &lt;1000&gt;</i><br>
  1085. clear a specific priority channel
  1086. </li>
  1087. <li>
  1088. <i>clearall</i><br>
  1089. clear all priority channels / switch to Ambilight mode
  1090. </li>
  1091. <li>
  1092. <i>colorTemperature &lt;255,255,255&gt;</i><br>
  1093. adjust temperature of each color separately (comma separated) (R,G,B)<br>
  1094. values from 0 to 255 in steps of 1
  1095. </li>
  1096. <li>
  1097. <i>configFile &lt;filename&gt;</i><br>
  1098. restart the Hyperion server with the given configuration file (files will be listed automatically from the given directory in attribute hyperionConfigDir)<br>
  1099. please omit the double extension of the file name (.config.json)<br>
  1100. only available after successful "get &lt;name&gt; configFiles"
  1101. </li>
  1102. <li>
  1103. <i>correction &lt;255,255,255&gt;</i><br>
  1104. adjust correction of each color separately (comma separated) (R,G,B)<br>
  1105. values from 0 to 255 in steps of 1
  1106. </li>
  1107. <li>
  1108. <i>dim &lt;percent&gt; [duration] [priority]</i><br>
  1109. dim the rgb light to given percentage with optional duration in seconds and optional priority
  1110. </li>
  1111. <li>
  1112. <i>dimDown [delta]</i><br>
  1113. dim down rgb light by steps defined in attribute hyperionDimStep or by given value (default: 10)
  1114. </li>
  1115. <li>
  1116. <i>dimUp [delta]</i><br>
  1117. dim up rgb light by steps defined in attribute hyperionDimStep or by given value (default: 10)
  1118. </li>
  1119. <li>
  1120. <i>effect &lt;effect&gt; [duration] [priority] [effectargs]</i><br>
  1121. set effect (replace blanks with underscore) with optional duration in seconds and priority<br>
  1122. effectargs can also be set as very last argument - must be a JSON string without any whitespace
  1123. </li>
  1124. <li>
  1125. <i>gamma &lt;1.90,1.90,1.90&gt;</i><br>
  1126. adjust gamma of each color separately (comma separated) (R,G,B)<br>
  1127. values from 0.00 to 5.00 in steps of 0.01
  1128. </li>
  1129. <li>
  1130. <i>luminanceGain &lt;1.00&gt;</i><br>
  1131. adjust luminanceGain<br>
  1132. values from 0.00 to 5.00 in steps of 0.01
  1133. </li>
  1134. <li>
  1135. <i>luminanceMinimum &lt;0.00&gt;</i><br>
  1136. adjust luminanceMinimum<br>
  1137. values from 0.00 to 5.00 in steps of 0.01
  1138. </li>
  1139. <li>
  1140. <i>mode &lt;clearall|effect|off|rgb&gt;</i><br>
  1141. set the light in the specific mode with its previous value
  1142. </li>
  1143. <li>
  1144. <i>off</i><br>
  1145. set the light off while the color is black
  1146. </li>
  1147. <li>
  1148. <i>on</i><br>
  1149. set the light on and restore previous state
  1150. </li>
  1151. <li>
  1152. <i>reopen</i><br>
  1153. reopen the connection to the hyperion server
  1154. </li>
  1155. <li>
  1156. <i>rgb &lt;RRGGBB&gt; [duration] [priority]</i><br>
  1157. set color in RGB hex format with optional duration in seconds and priority
  1158. </li>
  1159. <li>
  1160. <i>saturationGain &lt;1.10&gt;</i><br>
  1161. adjust saturationGain<br>
  1162. values from 0.00 to 5.00 in steps of 0.01
  1163. </li>
  1164. <li>
  1165. <i>saturationLGain &lt;1.00&gt;</i><br>
  1166. adjust saturationLGain<br>
  1167. values from 0.00 to 5.00 in steps of 0.01
  1168. </li>
  1169. <li>
  1170. <i>threshold &lt;0.16,0.16,0.16&gt;</i><br>
  1171. adjust threshold of each color separately (comma separated) (R,G,B)<br>
  1172. values from 0.00 to 1.00 in steps of 0.01
  1173. </li>
  1174. <li>
  1175. <i>toggle</i><br>
  1176. toggles the light between on and off
  1177. </li>
  1178. <li>
  1179. <i>toggleMode</i><br>
  1180. toggles through all modes
  1181. </li>
  1182. <li>
  1183. <i>valueGain &lt;1.70&gt;</i><br>
  1184. adjust valueGain<br>
  1185. values from 0.00 to 5.00 in steps of 0.01
  1186. </li>
  1187. <li>
  1188. <i>whitelevel &lt;0.70,0.80,0.90&gt;</i><br>
  1189. adjust whitelevel of each color separately (comma separated) (R,G,B)<br>
  1190. values from 0.00 to 1.00 in steps of 0.01
  1191. </li>
  1192. </ul>
  1193. <br>
  1194. <a name="Hyperion_get"></a>
  1195. <p><b>Get</b></p>
  1196. <ul>
  1197. <li>
  1198. <i>configFiles</i><br>
  1199. get the available config files in directory from attribute hyperionConfigDir<br>
  1200. File names must have no spaces and must end with .config.json .<br>
  1201. For non-local Hyperion servers you have to configure passwordless SSH login for the user running fhem to the Hyperion server host (http://www.linuxproblem.org/art_9.html), with attribute hyperionSshUser you can set the SSH user for login.<br>
  1202. Please watch the log for possible errors while getting config files.
  1203. </li>
  1204. <li>
  1205. <i>devStateIcon</i><br>
  1206. get the current devStateIcon
  1207. </li>
  1208. <li>
  1209. <i>statusRequest</i><br>
  1210. get the state of the Hyperion server,<br>
  1211. get also the internals of Hyperion including available effects
  1212. </li>
  1213. </ul>
  1214. <br>
  1215. <a name="Hyperion_attr"></a>
  1216. <p><b>Attributes</b></p>
  1217. <ul>
  1218. <li>
  1219. <i>disable</i><br>
  1220. stop polling and disconnect<br>
  1221. default: 0
  1222. </li>
  1223. <li>
  1224. <i>disabledForIntervals</i><br>
  1225. stop polling in given time frames<br>
  1226. default:
  1227. </li>
  1228. <li>
  1229. <i>hyperionBin</i><br>
  1230. path to the hyperion daemon<br>
  1231. OpenELEC users may set hyperiond.sh as daemon<br>
  1232. default: /usr/bin/hyperiond
  1233. </li>
  1234. <li>
  1235. <i>hyperionConfigDir</i><br>
  1236. path to the hyperion configuration files<br>
  1237. default: /etc/hyperion/
  1238. </li>
  1239. <li>
  1240. <i>hyperionCustomEffects</i><br>
  1241. space separated list of JSON strings (without spaces - please replace spaces in effect names with underlines)<br>
  1242. must include name (as diplay name), oname (name of the base effect) and args (the different effect args), only this order is allowed (if different an error will be thrown on attribute save and the attribut value will not be saved).<br>
  1243. example: {"name":"Knight_Rider_speed_2","oname":"Knight_rider","args":{"color":[255,0,255],"speed":2}} {"name":"Knight_Rider_speed_4","oname":"Knight_rider","args":{"color":[0,0,255],"speed":4}}
  1244. </li>
  1245. <li>
  1246. <i>hyperionDefaultDuration</i><br>
  1247. default duration<br>
  1248. default: 0 = infinity
  1249. </li>
  1250. <li>
  1251. <i>hyperionDefaultPriority</i><br>
  1252. default priority<br>
  1253. default: 0 = highest priority
  1254. </li>
  1255. <li>
  1256. <i>hyperionDimStep</i><br>
  1257. dim step for dimDown/dimUp<br>
  1258. default: 10 (percent)
  1259. </li>
  1260. <li>
  1261. <i>hyperionGainStep</i><br>
  1262. valueGain step for valueGainDown/valueGainUp<br>
  1263. default: 0.1
  1264. </li>
  1265. <li>
  1266. <i>hyperionNoSudo</i><br>
  1267. disable sudo for non-root ssh user<br>
  1268. default: 0
  1269. </li>
  1270. <li>
  1271. <i>hyperionSshUser</i><br>
  1272. user name for executing SSH commands<br>
  1273. default: pi
  1274. </li>
  1275. <li>
  1276. <i>hyperionToggleModes</i><br>
  1277. modes and order of toggleMode as comma separated list (min. 2 modes, max. 4 modes, each mode only once)<br>
  1278. default: clearall,rgb,effect,off
  1279. </li>
  1280. <li>
  1281. <i>hyperionVersionCheck</i><br>
  1282. disable hyperion version check to (maybe) support prior versions<br>
  1283. DO THIS AT YOUR OWN RISK! FHEM MAY CRASH UNEXPECTEDLY!<br>
  1284. default: 1
  1285. </li>
  1286. <li>
  1287. <i>queryAfterSet</i><br>
  1288. 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>
  1289. This is only used if periodically polling is enabled, without this polling the state will be queried automatically after set.<br>
  1290. default: 1
  1291. </li>
  1292. </ul>
  1293. <br>
  1294. <a name="Hyperion_read"></a>
  1295. <p><b>Readings</b></p>
  1296. <ul>
  1297. <li>
  1298. <i>adjustBlue</i><br>
  1299. each color of blue separately (comma separated) (R,G,B)
  1300. </li>
  1301. <li>
  1302. <i>adjustGreen</i><br>
  1303. each color of green separately (comma separated) (R,G,B)
  1304. </li>
  1305. <li>
  1306. <i>adjustRed</i><br>
  1307. each color of red separately (comma separated) (R,G,B)
  1308. </li>
  1309. <li>
  1310. <i>blacklevel</i><br>
  1311. blacklevel of each color separately (comma separated) (R,G,B)
  1312. </li>
  1313. <li>
  1314. <i>colorTemperature</i><br>
  1315. temperature of each color separately (comma separated) (R,G,B)
  1316. </li>
  1317. <li>
  1318. <i>configFile</i><br>
  1319. active/previously loaded configuration file, double extension (.config.json) will be omitted
  1320. </li>
  1321. <li>
  1322. <i>correction</i><br>
  1323. correction of each color separately (comma separated) (R,G,B)
  1324. </li>
  1325. <li>
  1326. <i>dim</i><br>
  1327. active/previous dim value (rgb light)
  1328. </li>
  1329. <li>
  1330. <i>duration</i><br>
  1331. active/previous/remaining primary duration in seconds or infinite
  1332. </li>
  1333. <li>
  1334. <i>effect</i><br>
  1335. active/previous effect
  1336. </li>
  1337. <li>
  1338. <i>effectArgs</i><br>
  1339. active/previous effect arguments as JSON
  1340. </li>
  1341. <li>
  1342. <i>gamma</i><br>
  1343. gamma for each color separately (comma separated) (R,G,B)
  1344. </li>
  1345. <li>
  1346. <i>id</i><br>
  1347. id of the Hyperion server
  1348. </li>
  1349. <li>
  1350. <i>lastError</i><br>
  1351. last occured error while communicating with the Hyperion server
  1352. </li>
  1353. <li>
  1354. <i>luminanceGain</i><br>
  1355. current luminanceGain
  1356. </li>
  1357. <li>
  1358. <i>luminanceMinimum</i><br>
  1359. current luminanceMinimum
  1360. </li>
  1361. <li>
  1362. <i>mode</i><br>
  1363. current mode
  1364. </li>
  1365. <li>
  1366. <i>mode_before_off</i><br>
  1367. previous mode before off
  1368. </li>
  1369. <li>
  1370. <i>priority</i><br>
  1371. active/previous priority
  1372. </li>
  1373. <li>
  1374. <i>rgb</i><br>
  1375. active/previous rgb
  1376. </li>
  1377. <li>
  1378. <i>saturationGain</i><br>
  1379. active saturationGain
  1380. </li>
  1381. <li>
  1382. <i>saturationLGain</i><br>
  1383. active saturationLGain
  1384. </li>
  1385. <li>
  1386. <i>serverResponse</i><br>
  1387. last Hyperion server response (success/ERROR)
  1388. </li>
  1389. <li>
  1390. <i>state</i><br>
  1391. current state
  1392. </li>
  1393. <li>
  1394. <i>threshold</i><br>
  1395. threshold of each color separately (comma separated) (R,G,B)
  1396. </li>
  1397. <li>
  1398. <i>valueGain</i><br>
  1399. valueGain - gain of the Ambilight
  1400. </li>
  1401. <li>
  1402. <i>whitelevel</i><br>
  1403. whitelevel of each color separately (comma separated) (R,G,B)
  1404. </li>
  1405. </ul>
  1406. </ul>
  1407. =end html
  1408. =begin html_DE
  1409. <a name="Hyperion"></a>
  1410. <h3>Hyperion</h3>
  1411. <ul>
  1412. Mit <i>Hyperion</i> ist es m&ouml;glich auf einem Hyperion Server die Farbe oder den Effekt einzustellen.<br>
  1413. Es ist auch m&ouml;glich eine komplette Farbkalibrierung vorzunehmen (&Auml;nderungen sind tempor&auml;r und werden nicht in die Konfigurationsdatei geschrieben).<br>
  1414. Der Hyperion Server muss dem JSON Server aktiviert haben.<br>
  1415. Es ist auch m&ouml;glich Hyperion mit verschiedenen Konfigurationsdateien zu starten (z.B. mit anderem Eingang/Grabber)<br>
  1416. <br>
  1417. <a name="Hyperion_define"></a>
  1418. <p><b>Define</b></p>
  1419. <ul>
  1420. <code>define &lt;name&gt; Hyperion &lt;IP oder HOSTNAME&gt; &lt;PORT&gt; [&lt;INTERVAL&gt;]</code><br>
  1421. </ul>
  1422. <br>
  1423. &lt;INTERVAL&gt; ist optional f&uuml;r automatisches Abfragen.<br>
  1424. <br>
  1425. <i>Nach dem Definieren des Ger&auml;tes wird einmalig und automatisch "get &lt;name&gt; statusRequest" aufgerufen um den aktuellen Status und die verf&uuml;gbaren Effekte vom Hyperion Server zu holen.</i><br>
  1426. <br>
  1427. Beispiel f&uuml;r Hyperion auf dem lokalen System:
  1428. <br><br>
  1429. <ul>
  1430. <code>define Ambilight Hyperion localhost 19444 10</code><br>
  1431. </ul>
  1432. <br>
  1433. Beispiel f&uuml;r Hyperion auf einem entfernten System:
  1434. <br><br>
  1435. <ul>
  1436. <code>define Ambilight Hyperion 192.168.1.4 19444 10</code><br>
  1437. </ul>
  1438. <br>
  1439. <a name="Hyperion_set"></a>
  1440. <p><b>set &lt;ben&ouml;tigt&gt; [optional]</b></p>
  1441. <ul>
  1442. <li>
  1443. <i>addEffect &lt;eigener_name&gt;</i><br>
  1444. f&uuml;gt den aktuellen Effekt mit dem &uuml;bergebenen Namen den eigenen Effekten hinzu<br>
  1445. kann nachtr&auml;glich im Attribut hyperionCustomEffects ge&auml;ndert werden<br>
  1446. Ger&auml;t muss dazu im Effekt Modus in einen nicht-eigenen Effekt sein und der &uuml;bergebene Name muss ein einmaliger Effektname sein
  1447. </li>
  1448. <li>
  1449. <i>adjustBlue &lt;0,0,255&gt;</i><br>
  1450. Justiert jede Farbe von Blau separat (Komma separiert) (R,G,B)<br>
  1451. Werte von 0 bis 255 in Schritten von 1
  1452. </li>
  1453. <li>
  1454. <i>adjustGreen &lt;0,255,0&gt;</i><br>
  1455. Justiere jede Farbe von Gr&uuml;n separat (Komma separiert) (R,G,B)<br>
  1456. Werte von 0 bis 255 in Schritten von 1
  1457. </li>
  1458. <li>
  1459. <i>adjustRed &lt;255,0,0&gt;</i><br>
  1460. Justiert jede Farbe von Rot separat (Komma separiert) (R,G,B)<br>
  1461. Werte von 0 bis 255 in Schritten von 1
  1462. </li>
  1463. <li>
  1464. <i>blacklevel &lt;0.00,0.00,0.00&gt;</i><br>
  1465. Justiert den Schwarzwert von jeder Farbe separat (Komma separiert) (R,G,B)<br>
  1466. Werte von 0.00 bis 1.00 in Schritten von 0.01
  1467. </li>
  1468. <li>
  1469. <i>clear &lt;1000&gt;</i><br>
  1470. einen bestimmten Priorit&auml;tskanal l&ouml;schen
  1471. </li>
  1472. <li>
  1473. <i>clearall</i><br>
  1474. alle Priorit&auml;tskan&auml;le l&ouml;schen / Umschaltung auf Ambilight
  1475. </li>
  1476. <li>
  1477. <i>colorTemperature &lt;255,255,255&gt;</i><br>
  1478. Justiert die Temperatur von jeder Farbe separat (Komma separiert) (R,G,B)<br>
  1479. Werte von 0 bis 255 in Schritten von 1
  1480. </li>
  1481. <li>
  1482. <i>configFile &lt;Dateiname&gt;</i><br>
  1483. Neustart des Hyperion Servers mit der angegebenen Konfigurationsdatei (Dateien werden automatisch aufgelistet aus Verzeichnis welches im Attribut hyperionConfigDir angegeben ist)<br>
  1484. Bitte die doppelte Endung weglassen (.config.json)<br>
  1485. Nur verf&uuml;gbar nach erfolgreichem "get &lt;name&gt; configFiles"
  1486. </li>
  1487. <li>
  1488. <i>correction &lt;255,255,255&gt;</i><br>
  1489. Justiert die Korrektur von jeder Farbe separat (Komma separiert) (R,G,B)<br>
  1490. Werte von 0 bis 255 in Schritten von 1
  1491. </li>
  1492. <li>
  1493. <i>dim &lt;Prozent&gt; [Dauer] [Priorit&auml;t]</i><br>
  1494. Dimmt das RGB Licht auf angegebenen Prozentwert, mit optionaler Dauer in Sekunden und optionaler Priorit&auml;t
  1495. </li>
  1496. <li>
  1497. <i>dimDown [delta]</i><br>
  1498. Abdunkeln des RGB Lichts um angegebenen Prozentwert oder um Prozentwert der im Attribut hyperionDimStep eingestellt ist (Voreinstellung: 10)
  1499. </li>
  1500. <li>
  1501. <i>dimUp [delta]</i><br>
  1502. Aufhellen des RGB Lichts um angegebenen Prozentwert oder um Prozentwert der im Attribut hyperionDimStep eingestellt ist (Voreinstellung: 10)
  1503. </li>
  1504. <li>
  1505. <i>effect &lt;effect&gt; [Dauer] [Priorit&auml;t] [effectargs]</i><br>
  1506. Stellt gew&auml;hlten Effekt ein (ersetzte Leerzeichen mit Unterstrichen) mit optionaler Dauer in Sekunden und optionaler Priorit&auml;t<br>
  1507. effectargs k&ouml;nnen ebenfalls &uuml;bermittelt werden - muss ein JSON String ohne Leerzeichen sein
  1508. </li>
  1509. <li>
  1510. <i>gamma &lt;1.90,1.90,1.90&gt;</i><br>
  1511. Justiert Gamma von jeder Farbe separat (Komma separiert) (R,G,B)<br>
  1512. Werte von 0.00 bis 5.00 in Schritten von 0.01
  1513. </li>
  1514. <li>
  1515. <i>luminanceGain &lt;1.00&gt;</i><br>
  1516. Justiert Helligkeit<br>
  1517. Werte von 0.00 bis 5.00 in Schritten von 0.01
  1518. </li>
  1519. <li>
  1520. <i>luminanceMinimum &lt;0.00&gt;</i><br>
  1521. Justiert Hintergrundbeleuchtung<br>
  1522. Werte von 0.00 bis 5.00 in Schritten von 0.01
  1523. </li>
  1524. <li>
  1525. <i>mode &lt;clearall|effect|off|rgb&gt;</i><br>
  1526. Setzt das Licht im gew&auml;hlten Modus mit dem zuletzt f&uuml;r diesen Modus eingestellten Wert
  1527. </li>
  1528. <li>
  1529. <i>off</i><br>
  1530. Schaltet aus mit Farbe schwarz
  1531. </li>
  1532. <li>
  1533. <i>on</i><br>
  1534. Schaltet mit letztem Modus und letztem Wert ein
  1535. </li>
  1536. <li>
  1537. <i>rgb &lt;RRGGBB&gt; [Dauer] [Priorit&auml;t]</i><br>
  1538. Setzt Farbe im RGB Hex Format mit optionaler Dauer in Sekunden und optionaler Priorit&auml;t
  1539. </li>
  1540. <li>
  1541. <i>saturationGain &lt;1.10&gt;</i><br>
  1542. Justiert S&auml;ttigung<br>
  1543. Werte von 0.00 bis 5.00 in Schritten von 0.01
  1544. </li>
  1545. <li>
  1546. <i>saturationLGain &lt;1.00&gt;</i><br>
  1547. Justiert minimale S&auml;ttigung<br>
  1548. Werte von 0.00 bis 5.00 in Schritten von 0.01
  1549. </li>
  1550. <li>
  1551. <i>threshold &lt;0.16,0.16,0.16&gt;</i><br>
  1552. Justiert den Schwellenwert von jeder Farbe separat (Komma separiert) (R,G,B)<br>
  1553. Werte von 0.00 bis 1.00 in Schritten von 0.01
  1554. </li>
  1555. <li>
  1556. <i>toggle</i><br>
  1557. Schaltet zwischen an und aus hin und her
  1558. </li>
  1559. <li>
  1560. <i>toggleMode</i><br>
  1561. Schaltet alle Modi durch
  1562. </li>
  1563. <li>
  1564. <i>valueGain &lt;1.70&gt;</i><br>
  1565. Justiert Helligkeit vom Ambilight<br>
  1566. Werte von 0.00 bis 5.00 in Schritten von 0.01
  1567. </li>
  1568. <li>
  1569. <i>whitelevel &lt;0.70,0.80,0.90&gt;</i><br>
  1570. Justiert den Wei&szlig;wert von jeder Farbe separat (Komma separiert) (R,G,B)<br>
  1571. Werte von 0.00 bis 1.00 in Schritten von 0.01
  1572. </li>
  1573. </ul>
  1574. <br>
  1575. <a name="Hyperion_get"></a>
  1576. <p><b>Get</b></p>
  1577. <ul>
  1578. <li>
  1579. <i>configFiles</i><br>
  1580. Holt die verf&uuml;gbaren Konfigurationsdateien aus dem Verzeichnis vom Attribut hyperionConfigDir<br>
  1581. Es m&uuml;ssen mindestens zwei Konfigurationsdateien im Verzeichnis vorhanden sein. Die Dateien d&uuml;rfen keine Leerzeichen enthalten und m&uuml;ssen mit .config.json enden!
  1582. </li>
  1583. <li>
  1584. <i>devStateIcon</i><br>
  1585. Zeigt den Wert des aktuellen devStateIcon
  1586. </li>
  1587. <li>
  1588. <i>statusRequest</i><br>
  1589. Holt den aktuellen Status vom Hyperion Server,<br>
  1590. holt auch die Internals vom Hyperion Server inklusive verf&uuml;gbarer Effekte
  1591. </li>
  1592. </ul>
  1593. <br>
  1594. <a name="Hyperion_attr"></a>
  1595. <p><b>Attribute</b></p>
  1596. <ul>
  1597. <li>
  1598. <i>disable</i><br>
  1599. Abfragen beenden und Verbindung trennen<br>
  1600. Voreinstellung: 0
  1601. </li>
  1602. <li>
  1603. <i>hyperionBin</i><br>
  1604. Pfad zum Hyperion Daemon<br>
  1605. OpenELEC Benutzer m&uuml;ssen eventuell hyperiond.sh als Daemon einstellen<br>
  1606. Voreinstellung: /usr/bin/hyperiond
  1607. </li>
  1608. <li>
  1609. <i>hyperionConfigDir</i><br>
  1610. Pfad zu den Hyperion Konfigurationsdateien<br>
  1611. Voreinstellung: /etc/hyperion/
  1612. </li>
  1613. <li>
  1614. <i>hyperionCustomEffects</i><br>
  1615. Leerzeichen separierte Liste von JSON Strings (ohne Leerzeichen - bitte Leerzeichen in Effektnamen durch Unterstriche ersetzen)<br>
  1616. muss name (als Anzeigename), oname (Name des basierenden Effekts) und args (die eigentlichen unterschiedlichen Effekt Argumente) beinhalten (auch genau in dieser Reihenfolge, sonst kommt beim &Uuml;bernehmen des Attributs ein Fehler und das Attribut wird nicht gespeichert)<br>
  1617. Beispiel: {"name":"Knight_Rider_speed_2","oname":"Knight_rider","args":{"color":[255,0,255],"speed":2}} {"name":"Knight_Rider_speed_4","oname":"Knight_rider","args":{"color":[0,0,255],"speed":4}}
  1618. </li>
  1619. <li>
  1620. <i>hyperionDefaultDuration</i><br>
  1621. Voreinstellung f&uuml;r Dauer<br>
  1622. Voreinstellung: 0 = unendlich
  1623. </li>
  1624. <li>
  1625. <i>hyperionDefaultPriority</i><br>
  1626. Voreinstellung f&uuml;r Priorit&auml;t<br>
  1627. Voreinstellung: 0 = h&ouml;chste Priorit&auml;t
  1628. </li>
  1629. <li>
  1630. <i>hyperionDimStep</i><br>
  1631. Dimmstufen f&uuml;r dimDown/dimUp<br>
  1632. Voreinstellung: 10 (Prozent)
  1633. </li>
  1634. <li>
  1635. <i>hyperionGainStep</i><br>
  1636. valueGain Dimmstufen f&uuml;r valueGainDown/valueGainUp<br>
  1637. Voreinstellung: 0.1
  1638. </li>
  1639. <li>
  1640. <i>hyperionNoSudo</i><br>
  1641. Deaktiviert sudo f&uuml;r nicht root SSH Benutzer<br>
  1642. Voreinstellung: 0
  1643. </li>
  1644. <li>
  1645. <i>hyperionSshUser</i><br>
  1646. Benutzername mit dem SSH Befehle ausgef&uuml;hrt werden sollen<br>
  1647. Voreinstellung: pi
  1648. </li>
  1649. <li>
  1650. <i>hyperionToggleModes</i><br>
  1651. Modi und Reihenfolge von toggleMode als kommaseparierte Liste (min. 2 Werte, max. 4 Werte, jeder Mode nur 1x)<br>
  1652. Voreinstellung: clearall,rgb,effect,off
  1653. </li>
  1654. <li>
  1655. <i>hyperionVersionCheck</i><br>
  1656. Deaktiviert Hyperion Version&uuml;berpr&uuml;fung um (eventuell) &auml;ltere Hyperion Versionen zu unterst&uuml;tzen<br>
  1657. DAS GESCHIEHT AUF EIGENE VERANTWORTUNG! FHEM K&Ouml;NNTE UNERWARTET ABST&Uuml;RTZEN!<br>
  1658. Voreinstellung: 1
  1659. </li>
  1660. <li>
  1661. <i>queryAfterSet</i><br>
  1662. Wenn gesetzt auf 0 wird der Status des Hyperion Server nach einem set Befehl nicht abgerufen, stattdessen wird der Status zum n&auml;chsten eingestellten Interval abgerufen.<br>
  1663. Das wird nur verwendet wenn das priodische Abfragen aktiviert ist, ohne dieses Abfragen wird der Status automatisch nach dem set Befehl abgerufen.<br>
  1664. Voreinstellung: 1
  1665. </li>
  1666. </ul>
  1667. <br>
  1668. <a name="Hyperion_read"></a>
  1669. <p><b>Readings</b></p>
  1670. <ul>
  1671. <li>
  1672. <i>adjustBlue</i><br>
  1673. jede Farbe von Blau separat (Komma separiert) (R,G,B)
  1674. </li>
  1675. <li>
  1676. <i>adjustGreen</i><br>
  1677. jede Farbe von Gr&uuml;n separat (Komma separiert) (R,G,B)
  1678. </li>
  1679. <li>
  1680. <i>adjustRed</i><br>
  1681. jede Farbe von Rot separat (Komma separiert) (R,G,B)
  1682. </li>
  1683. <li>
  1684. <i>blacklevel</i><br>
  1685. Schwarzwert von jeder Farbe separat (Komma separiert) (R,G,B)
  1686. </li>
  1687. <li>
  1688. <i>colorTemperature</i><br>
  1689. Temperatur von jeder Farbe separat (Komma separiert) (R,G,B)
  1690. </li>
  1691. <li>
  1692. <i>configFile</i><br>
  1693. aktive/zuletzt geladene Konfigurationsdatei, doppelte Endung (.config.json) wird weggelassen
  1694. </li>
  1695. <li>
  1696. <i>correction</i><br>
  1697. Korrektur von jeder Farbe separat (Komma separiert) (R,G,B)
  1698. </li>
  1699. <li>
  1700. <i>dim</i><br>
  1701. aktive/letzte Dimmstufe (RGB Licht)
  1702. </li>
  1703. <li>
  1704. <i>duration</i><br>
  1705. aktive/letzte/verbleibende prim&auml;re Dauer in Sekunden oder infinite f&uuml;r unendlich
  1706. </li>
  1707. <li>
  1708. <i>effect</i><br>
  1709. aktiver/letzter Effekt
  1710. </li>
  1711. <li>
  1712. <i>effectArgs</i><br>
  1713. aktive/letzte Effekt Argumente als JSON
  1714. </li>
  1715. <li>
  1716. <i>gamma</i><br>
  1717. Gamma von jeder Farbe separat (Komma separiert) (R,G,B)
  1718. </li>
  1719. <li>
  1720. <i>id</i><br>
  1721. ID vom Hyperion Server
  1722. </li>
  1723. <li>
  1724. <i>lastError</i><br>
  1725. letzter aufgetretener Fehler w&auml;hrend der Kommunikation mit dem Hyperion Server
  1726. </li>
  1727. <li>
  1728. <i>luminanceGain</i><br>
  1729. aktive Helligkeit
  1730. </li>
  1731. <li>
  1732. <i>luminanceMinimum</i><br>
  1733. aktive Hintergrundbeleuchtung
  1734. </li>
  1735. <li>
  1736. <i>mode</i><br>
  1737. aktiver Modus
  1738. </li>
  1739. <li>
  1740. <i>mode_before_off</i><br>
  1741. letzter Modus vor aus
  1742. </li>
  1743. <li>
  1744. <i>priority</i><br>
  1745. aktive/letzte Priorit&auml;t
  1746. </li>
  1747. <li>
  1748. <i>rgb</i><br>
  1749. aktive/letzte RGB Farbe
  1750. </li>
  1751. <li>
  1752. <i>saturationGain</i><br>
  1753. aktive S&auml;ttigung
  1754. </li>
  1755. <li>
  1756. <i>saturationLGain</i><br>
  1757. aktive minimale S&auml;ttigung
  1758. </li>
  1759. <li>
  1760. <i>serverResponse</i><br>
  1761. letzte Hyperion Server Antwort (success/ERROR)
  1762. </li>
  1763. <li>
  1764. <i>state</i><br>
  1765. aktiver Status
  1766. </li>
  1767. <li>
  1768. <i>threshold</i><br>
  1769. Schwellenwert von jeder Farbe separat (Komma separiert) (R,G,B)
  1770. </li>
  1771. <li>
  1772. <i>valueGain</i><br>
  1773. aktive Helligkeit vom Ambilight
  1774. </li>
  1775. <li>
  1776. <i>whitelevel</i><br>
  1777. Wei&szlig;wert von jeder Farbe separat (Komma separiert) (R,G,B)
  1778. </li>
  1779. </ul>
  1780. </ul>
  1781. =end html_DE
  1782. =cut