From aa26e7fea722b1a6243987e9222b0f89c94b8b6f Mon Sep 17 00:00:00 2001
From: mabula <>
Date: Wed, 15 Jan 2020 19:46:11 +0000
Subject: [PATCH] 70_Viera: new command display web page on TV's browser
git-svn-id: https://svn.fhem.de/fhem/trunk@20991 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/CHANGED | 2 +
fhem/FHEM/70_VIERA.pm | 175 +++++++++++++++++++++++++++++++++++++++---
2 files changed, 167 insertions(+), 10 deletions(-)
diff --git a/fhem/CHANGED b/fhem/CHANGED
index 4d889e1d7..0293a11cd 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,7 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
+ - feature: 70_VIERA: new command display web page on TV's browser
+ web address has to start with https://
- feature: 30_HUEBridge, 31_HUEDevice: try to move fhem device to new
bridge if 'real' light is moved
- bugfix: 73_NUKIBridge: fix FHEM crashed if json empty Array
diff --git a/fhem/FHEM/70_VIERA.pm b/fhem/FHEM/70_VIERA.pm
index d3e3a5bbe..5443eafae 100644
--- a/fhem/FHEM/70_VIERA.pm
+++ b/fhem/FHEM/70_VIERA.pm
@@ -9,9 +9,12 @@
# since version 1.25 modified by mabula
#
#
-# Version = 1.30
+# Version = 1.31
#
# Version History:
+# - 1.31 - 2020-01-15 Dr. H-J Breymayer
+# -- new command display web page on TV
+#
# - 1.30 - 2020-01-10 Dr. H-J Breymayer
# -- implemented additional commands, changed definition of commands
# -- bugfix patch from Nestor
@@ -311,7 +314,8 @@ sub VIERA_Set($@) {
"remoteControl:" . join(",", sort keys %VIERA_remoteControl_args) . " " .
"remoteControlApp:" . join(",", sort keys %VIERA_remoteControl_apps) . " " .
"input:HDMI_1,HDMI_2,HDMI_3,HDMI_4,SD_card,TV ".
- "statusRequest:noArg ";
+ "statusRequest:noArg ".
+ "web ";
$usage =~ s/(NRC_|-ONOFF)//g;
my $what = $a[0];
@@ -389,6 +393,10 @@ sub VIERA_Set($@) {
Log3 $name, 3, "$name: Set statusRequest";
VIERA_GetStatus($hash, 1);
}
+ elsif ($what eq "web"){
+ Log3 $name, 3, "$name: Set web $state";
+ VIERA_webpage($hash, $state);
+ }
elsif ($what eq "?"){
return "$usage";
}
@@ -572,11 +580,11 @@ sub VIERA_connection($$) {
my $blocking = "NonBlocking-VIERA_connection()" if (AttrVal($name, "blocking", 0) == 0);
$blocking = "Blocking-VIERA_connection()" if (AttrVal($name, "blocking", 0) == 1);
- my $sock = new IO::Socket::INET (
- PeerAddr => $hash->{helper}{HOST},
- PeerPort => $hash->{helper}{PORT},
- Proto => "tcp",
- Timeout => 2
+ my $sock = new IO::Socket::INET (
+ PeerAddr => $hash->{helper}{HOST},
+ PeerPort => $hash->{helper}{PORT},
+ Proto => "tcp",
+ Timeout => 2
);
if(defined ($sock)) {
@@ -885,6 +893,141 @@ sub VIERA_GetAbortFn($) {
return;
}
+# open web page on the TV
+
+sub VIERA_webpage($$) {
+ my ($hash, $url) = @_;
+
+ my $name = $hash->{NAME};
+
+ my $i = 0;
+ my $params = "";
+ my $message = "";
+ my $answer = "";
+ my @msg ;
+ my $iS ;
+ my $iE ;
+ my $sock ;
+ my $clientsock ;
+
+# check if Encryption is ready
+ VIERA_Encrypted_Command($hash, "" , "web");
+
+#start Web Browser and open url"""
+ $params = "vc_appresource_id=1063";
+ $message = VIERA_Build_soap_message_Encrypt($hash, "X_LaunchApp", $params, "s");
+
+ $hash->{helper}{BUFFER} = "";
+ if (exists($hash->{helper}{RUNNING_PID_GET}) and $i < 5) {
+ sleep (0.1);
+ $i += 1;
+ }
+ VIERA_connection($hash, $message);
+
+ $answer = VIERA_Encrypt_Answer($hash);
+ if (!defined($answer)) {
+ Log3 $name, 3, "$name cannot start web browser";
+ return;
+ }
+
+ $iS = index($answer, "");
+ $iE = index($answer, "");
+ my $sessionId = substr($answer, $iS+13, $iE-$iS-13);
+
+# setup a server socket where URL will be served
+
+ my $localip = $hash->{helper}{mylocalIP} ;
+ my $localport = 56000 + int(rand(9000));
+
+ $sock = new IO::Socket::INET (
+ LocalAddr => $localip,
+ LocalPort => $localport,
+ Proto => 'tcp',
+ Listen => 5,
+ Reuse => 1
+ );
+
+ if(defined ($sock)) {
+ Log3 $name, 4, "$name: open socket for web page address: $localip:$localport";
+ }
+ else {
+ Log3 $name, 3, "$name: not able to open socket for web page address";
+ return undef;
+ }
+
+ $params = "vc_app$sessionId\r\n";
+ $params .= "panasonic-viera 0.2\r\n";
+ $params .= "$localip:$localport";
+ $message = VIERA_Build_soap_message_Encrypt($hash, "X_ConnectApp", $params, "s");
+
+ $hash->{helper}{BUFFER} = "";
+ if (exists($hash->{helper}{RUNNING_PID_GET}) and $i < 5) {
+ sleep (0.1);
+ $i += 1;
+ }
+ VIERA_connection($hash, $message);
+
+ $answer = VIERA_Encrypt_Answer($hash);
+ if (!defined($answer)) {
+ Log3 $name, 3, "$name: cannot transmit web address";
+ return;
+ }
+
+ $i = 0;
+ $clientsock = $sock -> accept();
+ if(!defined ($clientsock) and $i < 5) {
+ sleep 0.1;
+ $i += 1;
+ $clientsock = $sock -> accept();
+ }
+
+ if(!defined ($clientsock)) {
+ Log3 $name, 3, "$name: not able to open new socket for web page address";
+ return undef;
+ }
+
+ my $client_address = $clientsock -> peerhost();
+ my $client_port = $clientsock -> peerport();
+ Log3 $name, 3, "$name: connection from $client_address:$client_port established";
+
+ my $l1 = length($url) & 0xFF;
+ @msg = (0xf4, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, $l1);
+
+ my $l2 = @msg;
+ for($i = 0; $i < $l1; $i++) {$msg[$l2+$i] = ord(substr($url, $i, 1))}; # get unicode for characters
+ $msg[$l2+$l1] = 0x00;
+
+ my $msgH = "";
+ for ($i = 0; $i <= $l1+$l2; $i++) {$msgH .= chr($msg[$i])};
+
+# print $clientsock $msgH;
+ $clientsock->send($msgH);
+
+ shutdown($clientsock, 1);
+ close($clientsock);
+ close($sock);
+
+ return;
+}
+
+sub VIERA_get_local_ip_address ($) {
+ my ($hash) = @_;
+
+ my $socket = IO::Socket::INET->new(
+ Proto => "tcp",
+ PeerAddr => $hash->{helper}{HOST}, # "google.com",
+ PeerPort => $hash->{helper}{PORT}, # "80",
+ );
+
+ # A side-effect of making a socket connection is that our IP address
+ # is available from the 'sockhost' method
+ my $local_ip_address = $socket->sockhost;
+
+ close($socket);
+
+ return $local_ip_address;
+}
+
################ special encryption ###########################################################
######################################################################################################################
@@ -916,6 +1059,9 @@ sub VIERA_Encrypted_Command($$$) {
$params .= "product_id=$command";
$task = "X_LaunchApp";
}
+ elsif ( $type eq "web" ) {
+ return;
+ }
else {return};
$message = VIERA_Build_soap_message_Encrypt($hash, $task, $params, "u");
@@ -1082,7 +1228,6 @@ sub VIERA_encrypt_soap_payload($$$$) {
$len = length($message);
$payload .= pack("N", $len); # make big endian
-# $payload .= pack("NA*", $len, $message);
# $len = (($len & 0x000000FF) + ($len & 0x0000FF00) * 2**8 + ($len & 0x00FF0000) * 2**16 + ($len & 0xFF000000) * 2**24);
$payload .= $message;
@@ -1253,6 +1398,8 @@ sub VIERA_request_session_id($) {
my $session_IV = $hash->{helper}{session_IV};
my $session_hmac_key = $hash->{helper}{session_hmac_key};
+ $hash->{helper}{mylocalIP} = VIERA_get_local_ip_address($hash);
+
my $encinfo = VIERA_encrypt_soap_payload("$app_id", $session_key, $session_IV, $session_hmac_key);
# Send the encrypted SOAP request along with plain text X_ApplicationId
@@ -1433,13 +1580,17 @@ sub VIERA_RClayout_TV_SVG() {
Currently, the following commands are defined.
- off
+ on_off
mute [on|off]
volume [0-100]
channel [1-9999]
input [hdmi1|hdmi2|hdmi3|hdmi4|sdCard|tv]
+ statusRequest
+ web
+ For the web command, please use https:// up front. Example:
+ set <name> web https://google.de
@@ -1637,12 +1788,16 @@ sub VIERA_RClayout_TV_SVG() {
Zur Zeit sind die folgenden Befehle implementiert:
- off
+ on_off
mute [on|off]
volume [0-100]
channel [1-9999]
input [hdmi1|hdmi2|hdmi3|hdmi4|sdCard|tv]
+ statusRequest
+ web
+ Beim Kommando web, bitte immer https:// voranstellen. Beispiel:
+ set <name> web https://google.de