# $Id$ ############################################################################ # 2019-01-20, v1.0.13 # # v1.0.13 # - BUFIX: main::readingsBulkUpdateIfChanged called by ./FHEM/70_NEUTRINO.pm (1191) # # v1.0.12 # - BUFIX: $_ ersetzt durch $uResult # # v1.0.11 # - BUFIX: Code Optimierungen # # v1.0.10 # - BUFIX: Code Optimierungen # # v1.0.9 # - BUFIX: BUG EPG Info https://forum.fhem.de/index.php/topic,54481.msg665959.html#msg665959 # Change Volume # - CHANGE Readings für EPG zurücksetzen wenn keine Infos vorhanden sind # # v1.0.8 # - BUFIX: Code Optimierungen # Zeilenumbruch in EPG Informationen entfernt # NEUTRINO BUG Umschalten wenn EGP und CHANNEL_ID nicht passen! # BUG leeres EPG https://forum.fhem.de/index.php/topic,54481.msg665355.html#msg665355 # # v1.0.7 erste SVN Version # - FEATURE: Reading Model hinzugefügt # - CHANGE CommandRef ergänzt # - BUFIX: Optimierung Neutrino Version/Model auslesen bei # Änderung Power # Initialisierung Device # # v1.0.6 # - FEATURE: CommandRef hinzugefügt (DE/EN) # - BUFIX: Optimierung Refresh Infos Senderwechsel (EPGInfos, input, Bouquetliste) # Optimierung Refresh EGPInfos (Wenn Sendung vorbei) # Optimierung Neutrino Version nur auslesen wenn sich das Reading "power" ändert! # Optimierung Reading time_now / time_raw_now (Wird vom FHEM Server verwendet/ Infos kommen nicht mehr von Neutrino) # Probleme beim Umschalten von Kanälen mit + Zeichen # Logeinträge überarbeitet # div. Codeoptimierungen # - CHANGE HTTP Standardtimout auf 2 gesetzt # NEUTRINO_HD_HandleCmdQueue hinzugefügt # NEUTRINO_HD_SendCommand hinzugefügt # Nicht verwendete Attribute entfernt # bouquet-tv # bouquet-radio # remotecontrol # lightMode # macaddr # wakeupCmd # http_method # # v1.0.5 BETA5 - 20160626 # - BUGFIX: clear readings timerlist # # v1.0.4 BETA4 - 20160624 # - BUGFIX: Not an ARRAY reference at ./FHEM/70_NEUTRINO.pm line 1237 # # v1.0.3 BETA3 - 20160614 # - FEATURE: add recordchannel reading # add recordtitel reading # # v1.0.2 BETA2 - 20160613 # - FEATURE: add timer readings # # v1.0.0 BETA1 - 20160612 # - FEATURE: add recordmode reading # # 70_NEUTRINO.pm # An FHEM Perl module for controlling NEUTRINO based TV receivers # via network connection. # # Copyright by Michael Winkler # e-mail: michael.winkler at online.de # # This file is part of fhem. # # Fhem is free software: you can redistribute it andor modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # Fhem is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with fhem. If not, see . # ############################################################################## package main; use strict; use warnings; use HttpUtils; use Encode; use Time::Piece; no warnings "all"; sub NEUTRINO_Set($@); sub NEUTRINO_Get($@); sub NEUTRINO_GetStatus($;$); sub NEUTRINO_Define($$); sub NEUTRINO_Undefine($$); ################################### sub NEUTRINO_Initialize($) { my ($hash) = @_; Log3 $hash, 5, "NEUTRINO_Initialize: Entering"; $hash->{GetFn} = "NEUTRINO_Get"; $hash->{AttrFn} = "NEUTRINO_Attr"; $hash->{SetFn} = "NEUTRINO_Set"; $hash->{DefFn} = "NEUTRINO_Define"; $hash->{UndefFn} = "NEUTRINO_Undefine"; $hash->{AttrList} = "https:0,1 http-method:absolete http-noshutdown:1,0 disable:0,1 timeout " . $readingFnAttributes; return; } ##################################### # AttrFn ##################################### sub NEUTRINO_Attr(@) { my ( $cmd, $name, $attrName, $attrVal ) = @_; my $hash = $defs{$name}; my $orig = $attrVal; if( $attrName eq "bouquet-tv" || $attrName eq "bouquet-radio" || $attrName eq "remotecontrol" || $attrName eq "http-method" || $attrName eq "wakeupCmd" || $attrName eq "macaddr" || $attrName eq "lightMode" ) { if( $cmd eq "set" ) { Log3 $name, 3, "NEUTRINO $name [NEUTRINO_Attr] [$attrName] - !!! Attention, the attribut is absolete and will delete in the future"; return "NEUTRINO $name [NEUTRINO_Attr] [$attrName] - !!! Attention, the attribut is absolete and will delete in the future"; } } } ##################################### # Get Status ##################################### sub NEUTRINO_GetStatus($;$) { my ( $hash, $update ) = @_; my $name = $hash->{NAME}; my $interval = $hash->{INTERVAL}; Log3 $name, 5, "NEUTRINO $name [NEUTRINO_GetStatus] called function"; if ($update ne '') {Log3 $name, 5, "NEUTRINO $name [NEUTRINO_GetStatus] Update = $update";} #RemoveInternalTimer($hash); InternalTimer( gettimeofday() + $interval, "NEUTRINO_GetStatus", $hash, 0 ); return if ( AttrVal( $name, "disable", 0 ) == 1 ); if ( !$update ) {NEUTRINO_SendCommand( $hash, "powerstate" );} return; } ################################### sub NEUTRINO_SendCommand($$;$$) { my ( $hash, $service, $cmd, $type ) = @_; my $name = $hash->{NAME}; my $address = $hash->{helper}{ADDRESS}; my $port = $hash->{helper}{PORT}; my $serviceurl; my $channelid = ReadingsVal( $name, "channel_id", "" ); my $param; # Cannelname my $channelname = ReadingsVal( $name, "recordchannel", "" ); $channelname =~ s/_/%20/g; #$cmd = ( defined($cmd) ) ? $cmd : ""; Log3 $name, 5, "NEUTRINO $name [NEUTRINO_SendCommand] called function CMD = $cmd "; my $http_proto; if ( $port eq "443" ) { $http_proto = "https"; Log3 $name, 5, "NEUTRINO $name [NEUTRINO_SendCommand] port 443 implies using HTTPS"; } elsif ( AttrVal( $name, "https", "0" ) eq "1" ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_SendCommand] explicit use of HTTPS"; $http_proto = "https"; if ( $port eq "80" ) { $port = "443"; Log3 $name, 5, "NEUTRINO $name [NEUTRINO_SendCommand] implicit change of from port 80 to 443"; } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_SendCommand] using unencrypted connection via HTTP"; $http_proto = "http"; } my $http_user = ""; my $http_passwd = ""; if ( defined( $hash->{helper}{USER} ) && defined( $hash->{helper}{PASSWORD} ) ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_SendCommand] using BasicAuth"; $http_user = $hash->{helper}{USER}; $http_passwd = $hash->{helper}{PASSWORD}; } if ( defined( $hash->{helper}{USER} ) ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_SendCommand] using BasicAuth (username only)"; $http_user = $hash->{helper}{USER}; } my $URL; my $response; my $return; if ( !defined($cmd) || $cmd eq "" ) { Log3 $name, 4, "NEUTRINO $name [NEUTRINO_SendCommand] SERVICE = $service"; } else { #2017-07-14 - http_method deaktiviert $cmd = "?" . $cmd; # if ( $http_method eq "GET" || $http_method eq "" ); Log3 $name, 4, "NEUTRINO $name [NEUTRINO_SendCommand] SERVICE = $service/" . urlDecode($cmd); } # Check Service and change serviceurl if ($service eq "epginfo") { #2017.07.12 - $channelid entfernt! '$serviceurl = "epg?xml=true&channelid=" . $channelid . "&details=true&max=6";' $serviceurl = "epg?xml=true&details=true&max=6"; } elsif ($service eq "epginforecord") { $serviceurl = "epg?xml=true&channelname=" . $channelname . "&max=6"; } elsif ($service eq "timerlist") { $serviceurl = "timer"; } elsif ($service eq "mutestate") { $serviceurl = "volume?status"; } elsif ($service eq "mute") { $serviceurl = "volume?mute"; } elsif ($service eq "unmute") { $serviceurl = "volume?unmute"; } elsif ($service eq "recordmode") { $serviceurl = "setmode?status"; } elsif ($service eq "powerstate") { $serviceurl = "standby"; } elsif ($service eq "model") { $serviceurl = "info"; } elsif ($service eq "bouquet") { $serviceurl = "getbouquet?actual"; } elsif ($service eq "bouquet_list") { my $bouquet = ReadingsVal( $name, "bouquetnr", "0" ); my $bouquetset = ReadingsVal( $name, "bouquetnr_set", "73482423648726384726384" ); my $bouquetmode = ReadingsVal( $name, "input", "tv" ); if (!($bouquet eq $bouquetset)) { $serviceurl = "getbouquet?bouquet=" . $bouquet . "&mode=" . $bouquetmode; } else{ return "bouguet schon vorhanden!"; } } else{ $serviceurl = $service; } if ( $http_user ne "" && $http_passwd ne "" ) { $URL = $http_proto . "://" . $http_user . ":" . $http_passwd . "@" . $address . ":" . $port . "/control/" . $serviceurl; #2017-07-14 - http_method deaktiviert $URL .= $cmd; #if ( $http_method eq "GET" || $http_method eq "" ); } elsif ( $http_user ne "" ) { $URL = $http_proto . "://" . $http_user . "@" . $address . ":" . $port . "/control/" . $serviceurl; #2017-07-14 - http_method deaktiviert $URL .= $cmd; #if ( $http_method eq "GET" || $http_method eq "" ); } else { $URL = $http_proto . "://" . $address . ":" . $port . "/control/" . $serviceurl; #2017-07-14 - http_method deaktiviert $URL .= $cmd; #if ( $http_method eq "GET" || $http_method eq "" ); } #2017.07.19 - Übergabe SendCommandQuery $param = { url => $URL, service => $service, cmd => $cmd, type => $type, callback => \&NEUTRINO_ReceiveCommand, }; NEUTRINO_HD_SendCommand($hash,$param); return; } ############################# # pushes new command to cmd queue sub NEUTRINO_HD_SendCommand($$) { my ($hash, $param) = @_; my $name = $hash->{NAME}; Log3 $name, 5, "NEUTRINO $name [NEUTRINO_HD_SendCommand] - append to queue " .$param->{url}; # In case any URL changes must be made, this part is separated in this function". push @{$hash->{helper}{CMD_QUEUE}}, $param; NEUTRINO_HD_HandleCmdQueue($hash); } ############################# # starts http requests from cmd queue sub NEUTRINO_HD_HandleCmdQueue($) { my ($hash, $param) = @_; my $name = $hash->{NAME}; my $http_noshutdown = AttrVal( $name, "http-noshutdown", "0" ); my $http_timeout = AttrVal( $name, "timeout", "2" ); if(not($hash->{helper}{RUNNING_REQUEST}) and @{$hash->{helper}{CMD_QUEUE}}) { my $params = { url => $param->{url}, timeout => $http_timeout, noshutdown => $http_noshutdown, keepalive => 0, hash => $hash, callback => \&NEUTRINO_ReceiveCommand }; my $request = pop @{$hash->{helper}{CMD_QUEUE}}; map {$hash->{helper}{HTTP_CONNECTION}{$_} = $params->{$_}} keys %{$params}; map {$hash->{helper}{HTTP_CONNECTION}{$_} = $request->{$_}} keys %{$request}; $hash->{helper}{RUNNING_REQUEST} = 1; Log3 $name, 5, "NEUTRINO $name [NEUTRINO_HD_HandleCmdQueue] - send command " .$params->{url}; HttpUtils_NonblockingGet($hash->{helper}{HTTP_CONNECTION}); } } ################################### sub NEUTRINO_Get($@) { my ( $hash, @a ) = @_; my $name = $hash->{NAME}; my $what; return "argument is missing" if ( int(@a) < 2 ); $what = $a[1]; #2017.07.21 - Log nur schreiben wenn get nicht initialisiert wird if ($what ne '?') { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Get] [$what] called function"; } if ( $what =~ /^(power|input|volume|mute|channel|currentTitle|channel_url)$/ ) { if ( ReadingsVal( $name, $what, "" ) ne "" ) { return ReadingsVal( $name, $what, "" ); } else { return "no such reading: $what"; } } else { return "Unknown argument $what, choose one of power:noArg input:noArg volume:noArg mute:noArg channel:noArg currentTitle:noArg channel_url:noArg "; } } ################################### sub NEUTRINO_Set($@) { my ( $hash, @a ) = @_; my $name = $hash->{NAME}; my $state = ReadingsVal( $name, "state", "absent" ); my $presence = ReadingsVal( $name, "presence", "absent" ); my $input = ReadingsVal( $name, "input", "" ); my $channel = ReadingsVal( $name, "channel", "" ); my $channels = ""; #2017.07.21 - Log nur schreiben wenn get nicht initialisiert wird if ($a[1] ne '?') { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Set] called function"; Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Set] [" . $a[1] . "] set"; } return "No Argument given" if ( !defined( $a[1] ) ); # load channel list if ( defined($input) && defined($channel) && $input ne "" && $channel ne "" && ( !defined( $hash->{helper}{channels}{$input} ) || !defined( $hash->{helper}{channels}{$input} ) ) ) { $channels = $channel . ","; } if ( $input ne "" && defined( $hash->{helper}{channels}{$input} ) && ref( $hash->{helper}{channels}{$input} ) eq "ARRAY" ) { $channels = join( ',', @{ $hash->{helper}{channels}{$input} } ); } my $usage = "Unknown argument " . $a[1] . ", choose one of toggle:noArg on:noArg off:noArg volume:slider,0,1,100 remoteControl showText showtextwithbutton channel:" . $channels; $usage .= " mute:-,on,off" if ( ReadingsVal( $name, "mute", "-" ) eq "-" ); $usage .= " mute:on,off" if ( ReadingsVal( $name, "mute", "-" ) ne "-" ); $usage .= " reboot:noArg"; $usage .= " shutdown:noArg"; $usage .= " statusRequest:noArg"; my $cmd = ''; my $result; # statusRequest if ( lc( $a[1] ) eq "statusrequest" ) { NEUTRINO_GetStatus($hash); } # toggle elsif ( lc( $a[1] ) eq "toggle" ) { if ( $state ne "on" ) { return NEUTRINO_Set( $hash, $name, "on" ); } else { return NEUTRINO_Set( $hash, $name, "off" ); } } # shutdown elsif ( lc( $a[1] ) eq "shutdown" ) { if ( $state ne "absent" ) { $cmd = "shutdown"; $result = NEUTRINO_SendCommand( $hash, "shutdown"); } else { return "Device needs to be ON to be set to standby mode."; } } # reboot elsif ( lc( $a[1] ) eq "reboot" ) { if ( $state ne "absent" ) { $result = NEUTRINO_SendCommand( $hash, "reboot"); } else { return "Device needs to be reachable to be rebooted."; } } # on elsif ( lc( $a[1] ) eq "on" ) { if ( $state eq "standby" ) { $cmd = "off"; $result = NEUTRINO_SendCommand( $hash, "powerstate", $cmd, "off" ); } else { return "Device needs to be reachable to be set to standby mode."; } } # off elsif ( lc( $a[1] ) eq "off" ) { if ( $state ne "absent" ) { $cmd = "on"; NEUTRINO_SendCommand( $hash, "powerstate", $cmd, "on" ); } else { return "Device needs to be reachable to be set to standby mode."; } } # volume elsif ( lc( $a[1] ) eq "volume" ) { if ( !defined( $a[2] ) ) {return "No argument given";} Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Set] [" . $a[1] . "] " . $a[2]; if ( $state eq "on" ) { my $uResult = $a[2]; if ( $uResult =~ m/^\d+$/ && $uResult >= 0 && $uResult <= 100 ) { $cmd = $a[2]; } else { return "Argument does not seem to be a valid integer between 0 and 100"; } $result = NEUTRINO_SendCommand( $hash, "volume", $cmd ); } else { return "Device needs to be ON to adjust volume."; } } # mute elsif ( lc( $a[1] ) eq "mute" || lc( $a[1] ) eq "mutet" ) { if ( $state eq "on" ) { if ( defined( $a[2] ) ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Set] [" . $a[1] . "] " . $a[2]; } if ( lc( $a[2] ) eq "off" ) { NEUTRINO_SendCommand( $hash, "unmute", $cmd ); } elsif ( lc( $a[2] ) eq "on" ) { NEUTRINO_SendCommand( $hash, "mute", $cmd ); } else { return "Unknown argument " . $a[2]; } } else { return "Device needs to be ON to mute/unmute audio."; } } # remoteControl elsif ( lc( $a[1] ) eq "remotecontrol" ) { if ( !defined( $a[2] ) ){return "No argument given.";} Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Set] [" . $a[1] . "] " . $a[2]; if ( defined( $a[2] )){ $result = NEUTRINO_SendCommand( $hash, "rcem", $a[2] ); return $result; } } # channel elsif ( lc( $a[1] ) eq "channel" ) { if ( !defined( $a[2] ) ) {return "No argument given, choose one of channel channelNumber servicereference ";} if ( defined( $a[2] ) && $presence eq "present" && $state ne "on" ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Set] [" . $a[1] . "] indirect switching request to ON"; NEUTRINO_Set( $hash, $name, "on" ); } if ( defined( $a[3] ) ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Set] [" . $a[1] . "] " . $a[2] . "+" . $a[3]; } else{ Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Set] [" . $a[1] . "] " . $a[2]; } if ( $state eq "on" ) { my $uResult = $a[2]; my $channellistname; #2017.07.19 - Plus Zeichen im Name erkennen if ( defined( $a[3] ) ) { # + Zeichen im Name erkannt! $channellistname = $a[2] . "%2B" . $a[3]; } else {$channellistname = $a[2];} $channellistname =~ s/_/%20/g; NEUTRINO_SendCommand( $hash, "zapto", "name=$channellistname" ); } else { return "Device needs to be present to switch to a specific channel."; } } # showText elsif ( lc( $a[1] ) eq "showtext" ) { if ( $state ne "absent" ) { if ( !defined( $a[2] ) ) {return "No argument given, choose one of messagetext ";} my $i = 2; my $text = $a[$i]; $i++; if ( defined( $a[$i] ) ) { my $arr_size = @a; while ( $i < $arr_size ) { $text = $text . " " . $a[$i]; $i++; } } $cmd = "popup=" . urlEncode($text) ."&timeout=10"; $result = NEUTRINO_SendCommand( $hash, "message", $cmd ); } else { return "Device needs to be reachable to send a message to screen."; } } # showTextwithbutton elsif ( lc( $a[1] ) eq "showtextwithbutton" ) { if ( $state ne "absent" ) { if ( !defined( $a[2] ) ) {return "No argument given, choose one of messagetext";} my $i = 2; my $text = $a[$i]; $i++; if ( defined( $a[$i] ) ) { my $arr_size = @a; while ( $i < $arr_size ) { $text = $text . " " . $a[$i]; $i++; } } $cmd = "nmsg=" . urlEncode($text); $result = NEUTRINO_SendCommand( $hash, "message", $cmd ); } else { return "Device needs to be reachable to send a message to screen."; } } # return usage hint else { return $usage; } return; } ################################### sub NEUTRINO_Define($$) { my ( $hash, $def ) = @_; my @a = split( "[ \t][ \t]*", $def ); my $name = $hash->{NAME}; Log3 $name, 0, "NEUTRINO $name [NEUTRINO_Define] start device"; eval { require XML::Simple; }; return "Please install Perl XML::Simple to use module NEUTRINO" if ($@); if ( int(@a) < 3 ) { my $msg = "Wrong syntax: define NEUTRINO [] [] []"; Log3 $name, 4, $msg; return $msg; } $hash->{TYPE} = "NEUTRINO"; my $address = $a[2]; $hash->{helper}{ADDRESS} = $address; # use port 80 if not defined my $port = $a[3] || 80; $hash->{helper}{PORT} = $port; # use interval of 45sec if not defined my $interval = $a[4] || 45; $hash->{INTERVAL} = $interval; # set http user if defined my $http_user = $a[5]; $hash->{helper}{USER} = $http_user if $http_user; # set http password if defined my $http_passwd = $a[6]; $hash->{helper}{PASSWORD} = $http_passwd if $http_passwd; $hash->{helper}{CMD_QUEUE} = (); delete($hash->{helper}{HTTP_CONNECTION}) if(exists($hash->{helper}{HTTP_CONNECTION})); # set default settings on first define if ($init_done) { # use http-method POST for FritzBox environment as GET does not seem to # work properly. Might restrict use to newer # NEUTRINO Webif versions or use of OWIF only. if ( exists $ENV{CONFIG_PRODUKT_NAME} && defined $ENV{CONFIG_PRODUKT_NAME} ) { #2017-07-14 - http_method deaktiviert #$attr{$name}{"http-method"} = 'POST'; } # default method is GET and should be compatible to most # NEUTRINO Webif versions else { #2017-07-14 - http_method deaktiviert #$attr{$name}{"http-method"} = 'GET'; } $attr{$name}{webCmd} = 'channel'; $attr{$name}{devStateIcon} = 'on:rc_GREEN:off off:rc_RED:on standby:rc_YELLOW:on'; $attr{$name}{icon} = 'dreambox'; } # start the status update timer #RemoveInternalTimer($hash); InternalTimer( gettimeofday() + 2, "NEUTRINO_GetStatus", $hash, 1 ); return; } ############################################################################################################ # # Begin of helper functions # ############################################################################################################ ################################### sub NEUTRINO_ReceiveCommand($$$) { my ( $param, $err, $data ) = @_; my $hash = $param->{hash}; my $name = $hash->{NAME}; my $service = $param->{service}; my $cmd = $param->{cmd}; my $state = ReadingsVal( $name, "state", "off" ); my $presence = ReadingsVal( $name, "presence", "absent" ); my $type = ( $param->{type} ) ? $param->{type} : ""; my $return; my $line; my $UnixDate = time(); Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] called function"; Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] Data = $data"; $hash->{helper}{RUNNING_REQUEST} = 0; delete($hash->{helper}{HTTP_CONNECTION}) unless($param->{keepalive}); readingsBeginUpdate($hash); # mute data = 0 then data = off if ($service eq "mutestate" && $data == 0){ $data = "off"; } # empty timerlist if ($service eq "timerlist" && $data == 0){ $data = "empty"; } # volume data = 0 then data = off if ($service eq "volume" && $data eq '0'){ $data = "off"; } # device not reachable if ($err) { # powerstate if ( $service eq "powerstate" ) { $state = "absent"; if ( !defined($cmd) || $cmd eq "" ) { Log3 $name, 4, "NEUTRINO $name RCV TIMEOUT $service"; } else { Log3 $name, 4, "NEUTRINO $name RCV TIMEOUT $service/" . urlDecode($cmd); } $presence = "absent"; readingsBulkUpdateIfChanged( $hash, "power", "off" ); readingsBulkUpdateIfChanged( $hash, "state", "off" ); readingsBulkUpdateIfChanged( $hash, "presence", $presence ) if ( ReadingsVal( $name, "presence", "" ) ne $presence ); } } # data received elsif ($data) { $presence = "present"; $state = "on"; readingsBulkUpdateIfChanged( $hash, "presence", $presence ) if ( ReadingsVal( $name, "presence", "" ) ne $presence ); #2017.07.21 - Log anzeigen wenn $cmd befüllt ist if ($cmd ne "" ) {Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] URL = " . urlDecode($cmd);} # split date (non XML services) my @ans = split (/\n/s, $data); ####################### # process return data ####################### # XML services if ($service eq "epginfo" || $service eq "epginforecord") { $data = '' . "\n" . $data; if ( $data =~ /<\?xml/ && $data !~ /<\/html>/ ) { my $parser = XML::Simple->new( NormaliseSpace => 2, KeepRoot => 0, ForceArray => 0, SuppressEmpty => 1, KeyAttr => {} ); eval '$return = $parser->XMLin( Encode::encode_utf8($data) ); 1'; if ($@) { if ( !defined($cmd) || $cmd eq "" ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] - unable to parse malformed XML: $@\n" . $data; } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] " . urlDecode($cmd) . " - unable to parse malformed XML: $@\n" . $data; } return undef; } undef $parser; } else { if ( !defined($cmd) || $cmd eq "" ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] - not in XML format\n" . $data; } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] " . urlDecode($cmd) . " - not in XML format\n" . $data; } return undef; } $return = Encode::encode_utf8($data) if ( $return && ref($return) ne "HASH" ); } # powerstate if ( $service eq "powerstate" ) { if (@ans[0]) { if (index(lc(@ans[0]), "on") != -1) { readingsBulkUpdateIfChanged( $hash, "power","off"); readingsBulkUpdateIfChanged( $hash, "state", "standby" ); $state = "off"; } elsif(index(lc(@ans[0]), "off") != -1) { # 2017.07.12 - Aenderungen nur durchfuehren wenn power vorher ungleich "on" war if (ReadingsVal( $name, "power", "unbekannt" ) ne 'on' ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] detect change"; readingsBulkUpdateIfChanged( $hash, "power","on"); readingsBulkUpdateIfChanged( $hash, "state", "on" ); delete($hash->{helper}{FIRSTSTART}); } #2017.07.25 - Erste Start: NUTRINO Version auslesen if ($hash->{helper}{FIRSTSTART} eq '') { NEUTRINO_SendCommand( $hash, "version" ); NEUTRINO_SendCommand( $hash, "model" ); $hash->{helper}{FIRSTSTART} = '1'; } #2017.07.12 - time_raw_now/time_now vom FHEM-Server verwenden readingsSingleUpdate( $hash, "time_raw_now", $UnixDate ,0); readingsSingleUpdate( $hash, "time_now", localtime() ,0); #2017.07.12 - Pruefen ob die bouquet_list aktualisiert werden muss if ($hash->{helper}{channels}{ReadingsVal( $name, "input", "-" )} eq '') { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] bouquet_list detect change!"; NEUTRINO_SendCommand( $hash, "bouquet_list" ); } #2017.07.12 - Folgendes wird alle INTERVAL abgefragt NEUTRINO_SendCommand( $hash, "zapto" ); # aktuellen channel_id auslesen NEUTRINO_SendCommand( $hash, "bouquet" ); # aktuelles Bouguet auslesen NEUTRINO_SendCommand( $hash, "volume" ); # aktuelles Volumen auslesen NEUTRINO_SendCommand( $hash, "mutestate" ); # mutestate 0 = off 1 = on NEUTRINO_SendCommand( $hash, "signal" ); # SIG, SNR und BER NEUTRINO_SendCommand( $hash, "recordmode" ); # 0 = off 1 = on NEUTRINO_SendCommand( $hash, "timerlist" ); # aktuelle Timerliste #2017.07.12 - deaktivert bzw. verschoben # MOVE --> NEUTRINO_SendCommand( $hash, "bouquet" ); #CHANGE bei Senderwechsel # MOVE --> NEUTRINO_SendCommand( $hash, "version" ); #CHANGE bei Powerstat wechsel # MOVE --> NEUTRINO_SendCommand( $hash, "build_live_url" ); #CHANGE bei Senderwechsel # MOVE --> NEUTRINO_SendCommand( $hash, "getmode" ); #CHANGE bei Senderwechsel # DEL --> NEUTRINO_SendCommand( $hash, "gettime" ); #FHEM Zeit verwenden # DEL --> NEUTRINO_SendCommand( $hash, "getrawtime" ); #FHEM Zeit verwenden } elsif(index(lc(@ans[0]), "ok") != -1) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] TYP = $type"; if (index($type, "off") != -1) { Log3 $name, 5, "NEUTRINO $name TYP = OFF"; readingsBulkUpdateIfChanged( $hash, "power", "on"); readingsBulkUpdateIfChanged( $hash, "state", "on" ); } elsif(index($type, "on") != -1) { Log3 $name, 5, "NEUTRINO $name TYP = ON"; readingsBulkUpdateIfChanged( $hash, "power", "off"); readingsBulkUpdateIfChanged( $hash, "state", "standby" ); } else { readingsBulkUpdateIfChanged( $hash, "power", "off"); readingsBulkUpdateIfChanged( $hash, "state", "standby" ); $state = "off"; } NEUTRINO_SendCommand( $hash, "recordmode" ); } else{ readingsBulkUpdateIfChanged( $hash, "power", "undefined" ); readingsBulkUpdateIfChanged( $hash, "state", "undefined" ); } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no powerstate could be extracted"; } } # bouquet elsif ( $service eq "bouquet" ) { if (@ans[0]) { #2017.07.17 - Liste nur bei aenderung aktualisieren if (ReadingsVal( $name, "bouquetnr", "99999" ) ne @ans[0] ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] detect change"; readingsBulkUpdateIfChanged( $hash, "bouquetnr", @ans[0] ); NEUTRINO_SendCommand( $hash, "bouquet_list" ); } } else { readingsBulkUpdateIfChanged( $hash, "bouquetnr", "0" ); Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no bouquetnr could be extracted"; } } # bouquet_list elsif ( $service eq "bouquet_list" ) { my $channellistname; my $i = 0; my $input = ReadingsVal( $name, "input", "-" ); #2017.07.19 - Nur durchführen wenn $input <> '-' ist if ($input ne '-') { $hash->{helper}{channels}{$input} = (); foreach $line (@ans) { if (index($line, "",6) != -1) { $channellistname = substr($line,index($line," ", 6 )+1); $channellistname =~ s/\s/_/g; if (substr($channellistname, 0, 1) ne "" && substr($channellistname, 0, 1) ne "_") { $hash->{helper}{channels}{$input}[$i] = $channellistname ; $i++; } } } } } # volume elsif ( $service eq "volume" ) { if (index(lc(@ans[0]), "ok") != -1) { #2017.07.12 - Nur bei einer Aenderung schreiben readingsBulkUpdateIfChanged( $hash, "volume", substr($cmd,1) ); } elsif (index(lc(@ans[0]), "off") != -1) { #2017.07.12 - Nur bei einer Aenderung schreiben readingsBulkUpdateIfChanged( $hash, "volume", "0" ); } elsif (@ans[0]) { #2017.07.12 - Nur bei einer Aenderung schreiben readingsBulkUpdateIfChanged( $hash, "volume", @ans[0] ); } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no volume could be extracted"; } } # mutestate elsif ( $service eq "mutestate" ) { if (@ans[0]) { if (index(lc(@ans[0]), "1") != -1) { #2017.07.12 - Änderung schreiben readingsBulkUpdateIfChanged( $hash, "mute","on"); } else{ readingsBulkUpdateIfChanged( $hash, "mute","off"); } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no mute could be extracted"; } } # mute elsif ( $service eq "mute" ) { if (@ans[0]) { if (index(lc(@ans[0]), "ok") != -1) { readingsBulkUpdateIfChanged( $hash, "mute","on"); } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no mute could be extracted"; } } # unmute elsif ( $service eq "unmute" ) { if (@ans[0]) { if (index(lc(@ans[0]), "ok") != -1) { readingsBulkUpdateIfChanged( $hash, "mute","off"); } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no mute could be extracted"; } } # model elsif ( $service eq "model" ) { if (@ans[0]) { readingsBulkUpdateIfChanged( $hash, "model",@ans[0]); } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no model could be extracted"; } } # timerlist elsif ( $service eq "timerlist" ) { my $channellistname; my $timernumber; my $timerrepeat; my $timertyp; my $timerannounceTime; my $timerstartTime; my $timerstopTime; my $timername; my $i = 0; my $c = 0; my $d = 0; my $timermaxcount = ReadingsVal( $name, "timer_maxcount", 1 ); my $neutrinotime = ReadingsVal( $name, "time_raw_now", "" ); if ($data ne "empty") { foreach $line (@ans) { if (index($line, "",6) != -1) { my @timerlist = split (/ /s, $line); $timernumber = @timerlist[0]; $timertyp = @timerlist[1]; $timerrepeat = @timerlist[2]; $timerannounceTime = @timerlist[4]; $timerstartTime = @timerlist[5]; $timerstopTime = @timerlist[6]; #2017.07.12 - Nur Änderungen schreiben if (ReadingsVal( $name, "timer$i", "0" ) ne $line ) { readingsBulkUpdateIfChanged( $hash, "timer$i", $line ); readingsBulkUpdateIfChanged( $hash, "timer$i" . "number", $timernumber ); # timertyp if ($timertyp eq "1") {$timertyp = "shutdown"} elsif ($timertyp eq "2") {$timertyp = "nextprogram"} elsif ($timertyp eq "3") {$timertyp = "zapto"} elsif ($timertyp eq "4") {$timertyp = "standby"} elsif ($timertyp eq "5") {$timertyp = "record"} elsif ($timertyp eq "6") {$timertyp = "remind"} elsif ($timertyp eq "7") {$timertyp = "sleeptimer"} elsif ($timertyp eq "8") {$timertyp = "exec_plugin"} else {$timertyp = "unknown"} readingsBulkUpdateIfChanged( $hash, "timer$i" . "typ", $timertyp ); # timer repeat if ($timerrepeat eq "0") {$timerrepeat = "once"} elsif ($timerrepeat eq "1") {$timerrepeat = "daily"} elsif ($timerrepeat eq "2") {$timerrepeat = "weekly"} elsif ($timerrepeat eq "3") {$timerrepeat = "biweekly"} elsif ($timerrepeat eq "4") {$timerrepeat = "fourweekly"} elsif ($timerrepeat eq "5") {$timerrepeat = "monthly"} elsif ($timerrepeat eq "6") {$timerrepeat = "beeventdescription"} else {$timerrepeat = "weekdays"} readingsBulkUpdateIfChanged( $hash, "timer$i" . "repeat", $timerrepeat ); # timer repcount readingsBulkUpdateIfChanged( $hash, "timer$i" . "repcount", @timerlist[3] ); # announceTime if ($timerannounceTime eq "0") {readingsBulkUpdateIfChanged( $hash, "timer$i" . "manualrecord", "" );} else { my $date = localtime($timerannounceTime)->strftime('%F %T'); readingsBulkUpdateIfChanged( $hash, "timer$i" . "announceTime", $date ); } # startTime my $date = localtime($timerstartTime)->strftime('%F %T'); readingsBulkUpdateIfChanged( $hash, "timer$i" . "startTime", $date ); # stopTime my $date = localtime($timerstopTime)->strftime('%F %T'); readingsBulkUpdateIfChanged( $hash, "timer$i" . "stopTime", $date ); # timer name $timername = ""; $c = 0; foreach (@timerlist) { if ($c > 6){ if ($timername ne "") {$timername = $timername . " " . @timerlist[$c]} else {$timername = @timerlist[$c]} } $c++; } readingsBulkUpdateIfChanged( $hash, "timer$i" . "name", $timername ); } # find running record if ($timername ne "") { if ($neutrinotime > $timerstartTime && $neutrinotime < $timerstopTime) { readingsBulkUpdateIfChanged( $hash, "recordchannel", $timername ); NEUTRINO_SendCommand( $hash, "epginforecord",""); } } $i++; } } } # timer count #2017.07.12 - Nur Änderungen schreiben readingsBulkUpdateIfChanged( $hash, "timer_count", $i ); # timer maxcount if ($timermaxcount <= $i) { #2017.07.12 - Nur Änderungen schreiben readingsBulkUpdateIfChanged( $hash, "timer_maxcount", $i ); } else { # detele not used timer while ($d < $timermaxcount) { if ($d > $i -1 ) { foreach ( "","announceTime","name","number","repcount","repeat","startTime","stopTime","typ", ) { readingsBulkUpdateIfChanged( $hash, "timer" . $d . $_, "-" ); } } $d++; } } } # EPG informations (record) elsif ( $service eq "epginforecord" ) { my $readvalue; my $neutrinotime = ReadingsVal( $name, "time_raw_now", "" ); my $readnumber = 0; my $line; if ( ref($return) eq "HASH" && defined( $return->{channel_id} ) ) { if (defined( $return->{prog} ) ) { #egp stop time serach my $arr_size = @{ $return->{prog} }; my $i = 0; while ( $i < $arr_size ) { $readvalue = $return->{prog}[$i]{stop_sec}; if ($readvalue > $neutrinotime){ $readnumber = $i; last; } $i++; } # recordtitle $readvalue = $return->{prog}[$readnumber]{description}; readingsBulkUpdateIfChanged( $hash, "recordtitle",$readvalue); } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no record epg information could be found"; } } # channel (ID) elsif ( $service eq "zapto" ) { if (@ans[0]) { if (@ans[0] eq 'ok') { # Umschalten eines Sender erkannt / Aktuellen Sender abfragen! Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] detect switch channel"; NEUTRINO_SendCommand( $hash, "zapto" ); } else { # Prüfen ob div. Informationen aktualisiert werden müssen if (ReadingsVal( $name, "channel_id", "0" ) ne @ans[0] ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] detect change OLD " . ReadingsVal( $name, "channel_id", "0" ); Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] detect change NEW @ans[0]"; readingsBulkUpdateIfChanged( $hash, "channel_id", @ans[0] ); NEUTRINO_SendCommand( $hash, "epginfo" ); NEUTRINO_SendCommand( $hash, "build_live_url" ); #2017.07.12 - channel_url wird nur beim Senderwechsel aktualisiert! NEUTRINO_SendCommand( $hash, "getmode" ); #2017.07.12 - Mode wird nur beim Senderwechsel aktualisiert! } else { # 2017.07.12 - EPGInfo aktualisieren wenn die aktuelle Sendeung zu ende ist if ($UnixDate > ReadingsVal( $name, "egp_current_stop_sec", "0" ) ) { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] epginfo detect change"; NEUTRINO_SendCommand( $hash, "epginfo" ); } } } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no ID could be extracted"; } } # stream URL elsif ( $service eq "build_live_url" ) { if (@ans[0]) { readingsBulkUpdateIfChanged( $hash, "channel_url", @ans[0] ); } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no build_live_url could be extracted"; } } # Mode TV/Radio elsif ( $service eq "getmode" ) { if (@ans[0]) { if (index(lc(@ans[0]), "tv") != -1) { readingsBulkUpdateIfChanged( $hash, "input","tv"); } elsif(index(lc(@ans[0]), "radio") != -1) { readingsBulkUpdateIfChanged( $hash, "input","radio"); } else{ readingsBulkUpdateIfChanged( $hash, "input", "-" ) } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no inputmode could be extracted"; } } # Mode TV/Radio elsif ( $service eq "recordmode" ) { if (@ans[0]) { if (index(lc(@ans[0]), "on") != -1) { #2017.07.12 - Nur bei einer Aenderung schreiben readingsBulkUpdateIfChanged( $hash, "recordmode","on"); } elsif(index(lc(@ans[0]), "off") != -1) { #2017.07.12 - Nur bei einer Aenderung schreiben readingsBulkUpdateIfChanged( $hash, "recordmode","off"); } else{ readingsBulkUpdateIfChanged( $hash, "recordmode", "-" ) } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no recordmode could be extracted"; } } # EPG informations elsif ( $service eq "epginfo" ) { my $reading; my $readingname; my $readvalue; my $neutrinotime = ReadingsVal( $name, "time_raw_now", "" ); my $readnumber = 0; if ( ref($return) eq "HASH" && defined( $return->{channel_id} ) ) { # channel_Name $readvalue = $return->{channel_name}; readingsBulkUpdateIfChanged( $hash, "channel_name",$readvalue); # channel displayname $readvalue =~ s/\s/_/g; readingsBulkUpdateIfChanged( $hash, "channel",$readvalue); if(ref($return->{prog}) eq 'ARRAY') { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ARRAY!!!" . ref($return->{prog}); }else {Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ARRAY!!! NOT" . ref($return->{prog});} Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] Data = $data"; if (defined( $return->{prog} ) && ref($return->{prog}) eq 'ARRAY' ) { #egp stop time serach my $arr_size = @{ $return->{prog} }; my $i = 0; while ( $i < $arr_size ) { $readvalue = $return->{prog}[$i]{stop_sec}; if ($readvalue > $neutrinotime){ $readnumber = $i; readingsBulkUpdateIfChanged( $hash, "egp_current_number", $readnumber); last; } $i++; } # 2017.07.27 - BUG NEUTRINO / Umschalten wenn EGP und CHANNEL_ID nicht passen! if (ReadingsVal( $name, "channel_id", "" ) ne $return->{prog}[$readnumber]{channel_id}) { Log3 $name, 0, "NEUTRINO [BUG NEUTRINO] EPG channel_id = " . $return->{prog}[$readnumber]{channel_id} ; NEUTRINO_SendCommand( $hash, "zapto", $return->{prog}[$readnumber]{channel_id} ); } # currentTitel $readvalue = $return->{prog}[$readnumber]{description}; readingsBulkUpdateIfChanged( $hash, "currentTitle",$readvalue); foreach ( "eventid","description","info1","info2","start_t","stop_t","duration_min","date","channel_id","stop_sec","start_sec", ) { $reading = $_; if ($_ eq "eventid") {$readingname = $reading ;} else {$readingname = "egp_current_" . $_;} if ( defined( $return->{prog}[$readnumber]{$reading} ) && lc( $return->{prog}[$readnumber]{$reading} ) ne "n/a" ) { $readvalue = $return->{prog}[$readnumber]{$reading}; $readvalue =~ s/\n//g; if ($readvalue) { readingsBulkUpdateIfChanged( $hash, $readingname, $readvalue ); } else { readingsBulkUpdateIfChanged( $hash, $readingname, "-" ); } } else { readingsBulkUpdateIfChanged( $hash, $readingname, "-" ); } } }else{ readingsBulkUpdateIfChanged( $hash, "eventid", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_description", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_info1", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_info2", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_start_t", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_stop_t", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_duration_min", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_date", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_channel_id", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_stop_sec", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_start_sec", "-" ); readingsBulkUpdateIfChanged( $hash, "egp_current_number", "-" ); readingsBulkUpdateIfChanged( $hash, "currentTitle", "-" ); } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no epg information could be found"; } } # signal elsif ( $service eq "signal" ) { my $signalvalue; if (@ans[0]) { foreach $line (@ans) { foreach ("sig","snr","ber",) { if (index(lc($line), $_) != -1) { $signalvalue = substr($line,index($line,":")+1); #2017.07.12 - Nur bei einer Aenderung schreiben readingsBulkUpdateIfChanged( $hash, "$_",$signalvalue); } } } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no signal could be extracted"; } } # Boxinformations elsif ( $service eq "version" ) { my $versionvalue; my $versionname; if (@ans[0]) { foreach $line (@ans) { if (index(lc($line), "=") != -1) { $versionvalue = substr($line,index($line,"=")+1); $versionname = substr($line,0,index($line,"=")); readingsBulkUpdateIfChanged( $hash, "image_" . "$versionname",$versionvalue); } } } else { Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] ERROR: no signal could be extracted"; } } # all other command results else { NEUTRINO_GetStatus( $hash, 1 ); } } else{ Log3 $name, 5, "NEUTRINO $name [NEUTRINO_ReceiveCommand] [$service] no data!"; } readingsEndUpdate( $hash, 1 ); NEUTRINO_HD_HandleCmdQueue($hash); undef $return; return; } ################################### sub NEUTRINO_Undefine($$) { my ( $hash, $arg ) = @_; my $name = $hash->{NAME}; Log3 $name, 5, "NEUTRINO $name [NEUTRINO_Undefine] called function"; # Stop the internal GetStatus-Loop and exit RemoveInternalTimer($hash); return; } 1; =pod =item device =item summary control for NEUTRINO based receivers via network connection =item summary_DE Steuerung von NEUTRINO basierte Receiver über das Netzwerk =begin html

NEUTRINO

    Define
      define <name> NEUTRINO <ip-address-or-hostname> [[[[<port>] [<poll-interval>]] [<http-user>]] [<http-password>]]

      This module controls NEUTRINO based devices like Coolstream receiver via network connection.

      Defining an NEUTRINO device will schedule an internal task (interval can be set with optional parameter <poll-interval> in seconds, if not set, the value is 45 seconds), which periodically reads the status of the device and triggers notify/filelog commands.

      Example:
        define SATReceiver NEUTRINO 192.168.0.10

        # With custom port
        define SATReceiver NEUTRINO 192.168.0.10 8080

        # With custom interval of 20 seconds
        define SATReceiver NEUTRINO 192.168.0.10 80 20

        # With HTTP user credentials
        define SATReceiver NEUTRINO 192.168.0.10 80 20 root secret


    Set
      set <name> <command> [<parameter>]

      Currently, the following commands are defined.
      • on   -   powers on the device (standby mode)
      • off   -   turns the device in standby mode
      • toggle   -   switch between on and off (standby mode)
      • shutdown   -   poweroff the device
      • reboot   -  reboots the device
      • channel   -   zap to specific channel
      • volume 0...100   -   set the volume level in percentage
      • mute on,off,toggle   -   controls volume to mute
      • statusRequest   -   requests the current status of the device
      • remoteControl UP,DOWN,...   -   sends remote control command
      • showText text   -   sends info messages to be displayed on screen
      • showtextwithbutton   -   sends info messagees to be displayed on screen with OK button



    Get
      get <name> <what>

      Currently, the following commands are defined:

        channel
        channelurl
        currentTitle
        input
        mute
        power
        volume


    Attributes
      • disable - Disable polling (true/false)
      • http-noshutdown - Set FHEM-internal HttpUtils connection close behaviour (defaults=0)
      • https - Access box via secure HTTP (true/false)
      • timeout - Set different polling timeout in seconds (default=2)



    Generated Readings:
      • ber - Shows Bit Error Rate for current channel
      • bouquetnr - Shows bouquet number for current channel
      • channel - Shows the service name of current channel
      • channel_id - Shows the channel id of current channel
      • channel_name - Shows the channel name of current channel
      • channel_url - Shows the channel url of current channel (use with vlc player)
      • currentTitle - Shows the title of the running event
      • epg_current_channel_id - Shows the channel id of epg information
      • epg_current_date - Shows the date of epg information
      • egp_current_description - Shows the current description of the current program
      • egp_current_duration_min - Shows the current duration of the current program
      • egp_current_info1 - Displays the current information of the current program
      • egp_current_info2 - Displays the current information of the current program
      • egp_current_number - Displays the current number(epg) of the current program
      • egp_current_start_sec - Shows the current start time of the current program (ticks)
      • egp_current_start_t - Shows the current start time of the current program
      • egp_current_stop_sec - Shows the current stop time of the current program (ticks)
      • egp_current_stop_t - Shows the current stop time of the current program
      • eventid - Shows the current event id of the current program
      • image_* - Shows image information of NEUTRINO
      • input - Shows currently used input
      • mute - Reports the mute status of the device (can be "on" or "off")
      • power - Reports the power status of the device (can be "on" or "off")
      • presence - Reports the presence status of the receiver (can be "absent" or "present").
      • recordmode - Reports the record mode of the device (can be "on" or "off")
      • recordmodetitle - Reports the last record title
      • sig - Shows signal for current channel in percent
      • snr - Shows signal to noise for current channel in percent
      • state - Reports current power state and an absence of the device (can be "on", "off" or "standby")
      • time_now - Reports current time
      • time_raw_now - Reports current time (ticks)
      • timerX - Shows complete timer (Report from NEUTRINO)
      • timerXannounceTime - Shows announce time of the timer
      • timerXname - Shows channel name of the timer
      • timerXnumber - Shows timer number
      • timerXrepcount - Shows rep count of the timer
      • timerXrepeat - Shows repeat time of the timer
      • timerXstartTime - Shows start time of the timer
      • timerXstopTime - Shows stop time of the timer
      • timerXtyp - Shows type of the timer
      • timer_count - Shows the number of timers
      • timer_count - Shows the maximum number of timers
      • volume - Reports current volume level of the receiver in percentage values (between 0 and 100 %)
=end html =begin html_DE

NEUTRINO

    Define
      define <name> NEUTRINO <ip-address-or-hostname> [[[[<port>] [<poll-interval>]] [<http-user>]] [<http-password>]]

      Dieses Modul steuert NEUTRINO basierte Geräte wie die Coolstream über eine Netzwerkverbindung.

      Für definierte NEUTRINO Geräte wird ein interner Task angelegt, welcher periodisch die Readings aktualisiert. Der Standartpollintervall ist 45 Sekunden.

      Beispiele:
        define SATReceiver NEUTRINO 192.168.0.10

        # Alternativer Port
        define SATReceiver NEUTRINO 192.168.0.10 8080

        # Alternativer poll intervall von 20 seconds
        define SATReceiver NEUTRINO 192.168.0.10 80 20

        # Mit HTTP Benutzer Zugangsdaten
        define SATReceiver NEUTRINO 192.168.0.10 80 20 root secret


    Set
      set <name> <command> [<parameter>]

      Aktuell gibt es folgende Befehle.
      • on   -   Schaltet das Gerät aus dem Standby wieder an
      • off   -   Schaltet das Gerät in den Standby
      • toggle   -   Ein- und Ausschalten zwischen Standby
      • shutdown   -   Schaltet das Gerät aus
      • reboot   -  Neustart des Gerätes
      • channel   -  Schaltet auf den angegebenen Kanal
      • volume 0...100   -   Ändert die Lautstärke in Prozent
      • mute on,off,toggle   -   Steuert Lautstärke "stumm"
      • statusRequest   -   Fordert den aktuellen Status des Gerätes an
      • remoteControl UP,DOWN,...   -   Sendet Fernsteuerungsbefehle
      • showText text   -   Sendet eine Textnachricht
      • showtextwithbutton   -   Sendet eine Textnachricht mit OK Button



    Get
      get <name> <what>

      Aktuell gibt es folgende Befehle.

        channel
        channelurl
        currentTitle
        input
        mute
        power
        volume


    Attributes
      • disable - Schaltet das Polling aus (true/false)
      • http-noshutdown - Setzt FHEM-internal HttpUtils Verbindung offen halten (defaults=0)
      • https - Zugriff über HTTPS aktivieren (true/false)
      • timeout - Setzen des Timeout der HTTP Verbindung (default=2)



    Generelle Readings:
      • ber - Zeigt die Bit Error Rate vom aktuellen Kanal
      • bouquetnr - Zeigt die aktuelle Bouquet Nummer vom aktuellen Kanal
      • channel - Zeigt den aktuellen Servicenamen vom aktuellen Kanal
      • channel_id - Zeigt die aktuelle Kanal ID vom aktuellen Kanal
      • channel_name - Zeigt den aktuellen Kanal Namen
      • channel_url - Zeigt die aktuelle Kanal URL, welche im Vlc Player zum Streamen verwendet werden kann
      • currentTitle - Zeigt den aktuellen Titel der aktuellen Sendung an
      • epg_current_channel_id - Zeigt die Kanal ID von aktuellen EPG an
      • epg_current_date - Zeigt das Datum des aktuellen EPGs an
      • egp_current_description - Zeigt die aktuelle Beschreibung der aktuellen Sendung an
      • egp_current_duration_min - Zeigt die Dauer der aktuellen Sendung an
      • egp_current_info1 - Zeigt die Information Teil 1 der aktuellen Sendung an
      • egp_current_info2 - Zeigt die Information Teil 2 der aktuellen Sendung an
      • egp_current_number - Zeigt die EPG Nummer der aktuellen Sendung an
      • egp_current_start_sec - Zeigt die Startzeit der aktuellen Sendung an (ticks)
      • egp_current_start_t - Zeigt die Startzeit der aktuellen Sendung an
      • egp_current_stop_sec - Zeigt die Stopzeit der aktuellen Sendung an (ticks)
      • egp_current_stop_t - Zeigt die Stopzeit der aktuellen Sendung an
      • eventid - Zeigt die aktuelle Event ID von der aktuellen Sendung an
      • image_* - Zeigt Image Informationen von NEUTRINO
      • input - Zeigt den aktuellen Input an (TV/Radio)
      • mute - Zeigt aktuellen Mute Status ("on" oder "off")
      • power - Zeigt aktuellen Power Status ("on" oder "off")
      • presence - Zeigt den aktuellen presence Status an ("absent" oder "present").
      • recordmode - Zeigt an ob die Box gerade eine Aufnahme macht ("on" oder "off")
      • recordmodetitle - Zeigt den letzten Aufnahme Titel an
      • sig - Zeigt Signalstärke vom aktuellen Sender an
      • snr - Zeigt Singal Noise vom aktuellen Sender an
      • state - Zeigt den aktuellen Status an ("on", "off" oder "standby")
      • time_now - Aktuelle Uhrzeit
      • time_raw_now - Aktuelle Uhrzeit (ticks)
      • timerX - Zeigt den kompletten Timer an (Report from NEUTRINO)
      • timerXannounceTime - Zeigt die Ankündigungszeit des Timers an
      • timerXname - Zeigt den Aufnahmekanal des Timers an
      • timerXnumber - Zeigt die Timernummer an
      • timerXrepcount - Zeigt den Rep. Counter des Timers an
      • timerXrepeat - Zeigt die Wiederholungszeit an
      • timerXstartTime - Zeigt die Startzeit des Timers an
      • timerXstopTime - Zeigt die Stopzeit des Timers an
      • timerXtyp - Zeigt den Typ des Timers an
      • timer_count - Zeigt die Anzahl der aktuellen Timer an
      • timer_count - Zeitg die max. Anzahl der Timer an (wird intern verwendet)
      • volume - Zeit die aktuelle Lautstärke an (zwischen 0 und 100 %)
=end html_DE =cut