From 134698bada55fe2dce1ed395ac3a88ca68605482 Mon Sep 17 00:00:00 2001 From: hofrichter <> Date: Tue, 24 Jun 2014 22:26:20 +0000 Subject: [PATCH] zone devices are autocreated (delete the zone devices first!) git-svn-id: https://svn.fhem.de/fhem/trunk@6162 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/70_PIONEERAVR.pm | 269 +++++++++++---------------------- fhem/FHEM/71_PIONEERAVRZONE.pm | 44 +++--- 2 files changed, 118 insertions(+), 195 deletions(-) diff --git a/fhem/FHEM/70_PIONEERAVR.pm b/fhem/FHEM/70_PIONEERAVR.pm index 06713606f..5764d2aa3 100644 --- a/fhem/FHEM/70_PIONEERAVR.pm +++ b/fhem/FHEM/70_PIONEERAVR.pm @@ -23,14 +23,14 @@ # # This module handles the communication with a Pioneer AVR and controls the main zone. -# this is the physical module - it opens the device (via rs232 or TCP), and its ReadFn is called after the global select reports, -# that data is available. +# this is the module for the communication interface and to control the main zone - +# it opens the device (via rs232 or TCP), and its ReadFn is called after the global select reports, that data is available. # - on Windows select does not work for devices not connected via TCP, here is a ReadyFn function necessary, which polls the device 10 times # a second, and returns true if data is available. # - ReadFn makes sure, that a message is complete and correct, and calls the global Dispatch() with one message -# - Dispatch() searches for a matching logical module (by checking $hash->{Clients} or $hash->{MatchList} in the physical module, and -# $hash->{Match} in all matching logical modules), and calls the ParseFn of the logical module -# (we use this mechanism to pass informations to the PIONEERAVR_ZONE device(s) ) +# - Dispatch() searches for a matching logical module (by checking $hash->{Clients} or $hash->{MatchList} in this device, and +# $hash->{Match} in all matching zone devices), and calls the ParseFn of the zone devices +# (This mechanism is used to pass information to the PIONEERAVRZONE device(s) ) # # See also: # Elite & Pioneer FY14AVR IP & RS-232 7-31-13.xlsx @@ -50,38 +50,19 @@ # added set extension to documentation # 21.6.2014:version # fixed RC_layout -# 10.6.2014:version 0007 -# unified logging texts -# added "verbose 5" log messages for all reads (messages coming from the PioneerAVR) -# added "verbose 5" log messages for all set (commands sent to the PioneerAVR) -# added "verbose 5" log messages for all get (commands sent to the PioneerAVR) -# fixed set listeningMode -# fixed get raw - this sends to the PioneerAVR (e.g. to power off the Pioneer AVR: get mypioneerAvr raw PF ) -# get raw (without further arguments) sends only a new line command -> this should wakeup the connection if the PioneerAVR is in standby -# removed unneeded functions, RESTART OF FHEM NEEDED (reload PIONEERAVR is not enough) -# updated set on -- to be even more Pioneer documentation conform (sending now additionally \n\r immediately before PO\n\r) -# 9.6.2014: all commands end now with "\r\n" -# The command for PowerOn (PO) is now send twice -# "blink" (part of setextensions) does not make much sense for a Pioneer AVR - set blink returns this information ;-) -# Added support for module 95_remotecontrol -# New functions: sub RC_layout_PioneerAVR(); sub PIONEERAVR_RCmakenotify($$); -# Updated PIONEERAVR_Initialize for remotecontrol -# added reading "networkStandby" [on|off] -> "on" indicates that the Pioneer AVR can be turned on from standby -# added reading "tunerFrequency" -# version 0008 -# fixed get tunerFrequency package main; use strict; use warnings; +use SetExtensions; use Time::HiRes qw(gettimeofday); if( $^O =~ /Win/ ) { require Win32::SerialPort; } else { require Device::SerialPort; } -use SetExtensions qw/ :all /; + ######################### # Forward declaration sub PIONEERAVR_Set($@); @@ -182,138 +163,41 @@ PIONEERAVR_Define($$) { $attr{$name}{webCmd} = 'volume:mute:input'; } unless ( exists( $attr{$name}{devStateIcon} ) ) { - $attr{$name}{devStateIcon} = - 'on:rc_GREEN:off off:rc_STOP:on absent:rc_RED'; + $attr{$name}{devStateIcon} = 'on:rc_GREEN:off off:rc_STOP:on absent:rc_RED'; } $hash->{helper}{receiver} = undef; - unless ( exists( $hash->{helper}{AVAILABLE} ) - and ( $hash->{helper}{AVAILABLE} == 0 )) + unless ( exists( $hash->{helper}{AVAILABLE} ) and ( $hash->{helper}{AVAILABLE} == 0 )) { $hash->{helper}{AVAILABLE} = 1; readingsSingleUpdate( $hash, "presence", "present", 1 ); } $hash->{helper}{INPUTNAMES} = { - "00" => { - "name" => "phono", - "aliasName" => "", - "enabled" => "1" - }, - "01" => { - "name" => "cd", - "aliasName" => "", - "enabled" => "1" - }, - "02" => { - "name" => "tuner", - "aliasName" => "", - "enabled" => "1" - }, - "03" => { - "name" => "cdrTape", - "aliasName" => "", - "enabled" => "1" - }, - "04" => { - "name" => "dvd", - "aliasName" => "", - "enabled" => "1" - }, - "05" => { - "name" => "tvSat", - "aliasName" => "", - "enabled" => "1" - }, - "06" => { - "name" => "CblSat", - "aliasName" => "", - "enabled" => "1" - }, - "10" => { - "name" => "video1", - "aliasName" => "", - "enabled" => "1" - }, - "12" => { - "name" => "multiChIn", - "aliasName" => "", - "enabled" => "1" - }, - "14" => { - "name" => "video2", - "aliasName" => "", - "enabled" => "1" - }, - "15" => { - "name" => "dvrBdr", - "aliasName" => "", - "enabled" => "1" - }, - "17" => { - "name" => "iPodUsb", - "aliasName" => "", - "enabled" => "1" - }, - "18" => { - "name" => "xmRadio", - "aliasName" => "", - "enabled" => "1" - }, - "19" => { - "name" => "hdmi1", - "aliasName" => "", - "enabled" => "1" - }, - "20" => { - "name" => "hdmi2", - "aliasName" => "", - "enabled" => "1" - }, - "21" => { - "name" => "hdmi3", - "aliasName" => "", - "enabled" => "1" - }, - "22" => { - "name" => "hdmi4", - "aliasName" => "", - "enabled" => "1" - }, - "23" => { - "name" => "hdmi5", - "aliasName" => "", - "enabled" => "1" - }, - "25" => { - "name" => "bd", - "aliasName" => "", - "enabled" => "1" - }, - "26" => { - "name" => "homeMediaGallery", - "aliasName" => "", - "enabled" => "1" - }, - "27" => { - "name" => "sirius", - "aliasName" => "", - "enabled" => "1" - }, - "31" => { - "name" => "hdmiCyclic", - "aliasName" => "", - "enabled" => "1" - }, - "33" => { - "name" => "adapterPort", - "aliasName" => "", - "enabled" => "1" - } + "00" => {"name" => "phono", "aliasName" => "", "enabled" => "1"}, + "01" => {"name" => "cd", "aliasName" => "", "enabled" => "1"}, + "02" => {"name" => "tuner", "aliasName" => "", "enabled" => "1"}, + "03" => {"name" => "cdrTape", "aliasName" => "", "enabled" => "1"}, + "04" => {"name" => "dvd", "aliasName" => "", "enabled" => "1"}, + "05" => {"name" => "tvSat", "aliasName" => "", "enabled" => "1"}, + "06" => {"name" => "CblSat", "aliasName" => "", "enabled" => "1"}, + "10" => {"name" => "video1", "aliasName" => "", "enabled" => "1"}, + "12" => {"name" => "multiChIn", "aliasName" => "", "enabled" => "1"}, + "14" => {"name" => "video2", "aliasName" => "", "enabled" => "1"}, + "15" => {"name" => "dvrBdr", "aliasName" => "", "enabled" => "1"}, + "17" => {"name" => "iPodUsb", "aliasName" => "", "enabled" => "1"}, + "18" => {"name" => "xmRadio", "aliasName" => "", "enabled" => "1"}, + "19" => {"name" => "hdmi1", "aliasName" => "", "enabled" => "1"}, + "20" => {"name" => "hdmi2", "aliasName" => "", "enabled" => "1"}, + "21" => {"name" => "hdmi3", "aliasName" => "", "enabled" => "1"}, + "22" => {"name" => "hdmi4", "aliasName" => "", "enabled" => "1"}, + "23" => {"name" => "hdmi5", "aliasName" => "", "enabled" => "1"}, + "25" => {"name" => "bd", "aliasName" => "", "enabled" => "1"}, + "26" => {"name" => "homeMediaGallery", "aliasName" => "", "enabled" => "1"}, + "27" => {"name" => "sirius", "aliasName" => "", "enabled" => "1"}, + "31" => {"name" => "hdmiCyclic", "aliasName" => "", "enabled" => "1"}, + "33" => {"name" => "adapterPort", "aliasName" => "", "enabled" => "1"} }; - - PIONEERAVR_askForInputNames($hash,5); - # ----------------Human Readable command mapping table----------------------- $hash->{helper}{SETS} = { 'main' => { @@ -696,6 +580,8 @@ PIONEERAVR_Define($$) { "0f01"=>"MULTI CH IN" }; #### statusRequest + #### Update Input alias names, available Inputs + PIONEERAVR_askForInputNames($hash,5); #### we execute all 'get XXX' foreach my $zone ( keys %{$hash->{helper}{GETS}} ) { foreach my $key ( keys %{$hash->{helper}{GETS}{$zone}} ) { @@ -730,7 +616,6 @@ PIONEERAVR_Undef($$) delete $defs{$d}{IODev}; } } - DevIo_CloseDev($hash); return undef; } @@ -793,7 +678,7 @@ dq($) return "\"" . escapeLogLine($s) . "\""; } -#PIONEER_Log() is used to show the data sent end received from/to the PioneerAVR if attr logTraffic is set +#PIONEERAVR_Log() is used to show the data sent end received from/to the PioneerAVR if attr logTraffic is set sub PIONEERAVR_Log($$$) { @@ -1145,6 +1030,7 @@ sub PIONEERAVR_Read($) my $name = $hash->{NAME}; my $state=''; my $buf = ''; + my $msgForZone = ""; #include previous partial message if(defined($hash->{PARTIAL}) && $hash->{PARTIAL}) { $buf = $hash->{PARTIAL} . DevIo_SimpleRead($hash); @@ -1394,30 +1280,55 @@ sub PIONEERAVR_Read($) readingsBulkUpdate($hash, "networkStandby", "off" ); Log3 $hash,5,"PIONEERAVR $name: ".dq($line) ." interpreted as: networkStandby is off"; } - # dispatch "zone" - commands to other zones - # Volume, mute, power - } elsif ($line =~ m/^[Y|Z]V(\d\d)$|^Z[2|3]MUT(\d)$|^Z[2|3]F(\d\d)$|^[A|B]PR(0|1)$|^ZEA(\d\d)$|^ZEP(0|1)$/) { - Dispatch($hash, $line, undef); # dispatch result to PIONEERAVRZONEs - Log3 $hash,5,"PIONEERAVR $name: ".dq($line) ." interpreted as: not for the Main zone -> dispatch to PIONEERAVRZONEs"; + # commands for other zones (Volume, mute, power) + #} elsif ($line =~ m/^[Y|Z]V(\d\d)$|^Z[2|3]MUT(\d)$|^Z[2|3]F(\d\d)$|^[A|B]PR(0|1)$|^ZEA(\d\d)$|^ZEP(0|1)$/) { + # Zone 2 command + + } elsif ($line =~ m/^ZV(\d\d)$|^Z2MUT(\d)$|^Z2F(\d\d)$|^APR(0|1)$/) { + $msgForZone="zone2"; + Log3 $hash, 5, "PIONEERAVR $name: received $line - message for zone2!"; + # Zone 3 command + } elsif ($line =~ m/^YV(\d\d)$|^Z3MUT(\d)$|^Z3F(\d\d)$|^BPR(0|1)$/) { + $msgForZone="zone3"; + Log3 $hash, 5, "PIONEERAVR $name: received $line - message for zone3!"; + # hdZone command + } elsif ($line =~ m/^ZEA(\d\d)$|^ZEP(0|1)$/) { + $msgForZone="hdZone"; + Log3 $hash, 5, "PIONEERAVR $name: received $line - message for hdZone!"; } else { Log3 $hash, 5, "PIONEERAVR $name: received $line - don't know what this means - help me!"; } + + # if PIONEERAVRZONE device exists for that zone, dispatch the command + # otherwise try to autocreate the device + unless($msgForZone eq "") { + my $hashZone = $modules{PIONEERAVRZONE}{defptr}{$msgForZone}; + Log3 $hash, 5, "PIONEERAVR $name: received message for Zone: ".$msgForZone; + if(!$hashZone) { + my $ret = "UNDEFINED PIONEERAVRZONE_$msgForZone PIONEERAVRZONE $msgForZone"; + Log3 $name, 3, "PIONEERAVR $ret, please define it"; + DoTrigger("global", $ret); + return ""; + } + # dispatch "zone" - commands to other zones + Dispatch($hash, $line, undef); # dispatch result to PIONEERAVRZONEs + Log3 $hash,5,"PIONEERAVR $name: ".dq($line) ." interpreted as: not for the Main zone -> dispatch to PIONEERAVRZONEs"; + + } + } readingsEndUpdate($hash, 1); $hash->{PARTIAL} = $buf; } - ######################################################### - sub PIONEERAVR_askForInputNames($$) { my ($hash, $loglevel) = @_; my $name = $hash->{NAME}; my $comstr = ''; # we ask for the inputs 1 to 49 if an input name exists (command: ?RGB00 ... ?RGB49) - # we ask for the inputs 1 to 49 if the input is disabled (command: ?SSC0003 ... ?SSC4903) - # + # and if the input is disabled (command: ?SSC0003 ... ?SSC4903) for ( my $i=0; $i<50; $i++ ) { select(undef, undef, undef, 0.1); $comstr = sprintf '?RGB%02d', $i; @@ -1456,7 +1367,6 @@ RC_layout_PioneerAVR() { } ##################################### - 1; =pod @@ -1497,8 +1407,9 @@ RC_layout_PioneerAVR() { define <name> PIONEERAVR serial <SerialDevice>[<@BaudRate>]

- Defines a physical PIONEERAVR device. The keywords telnet or - serial are fixed. Default port on Pioneer AV receivers is 23 (according to the above mentioned Pioneer documetation)

+ Defines a Pioneer AV receiver device (communication interface and main zone control). The keywords telnet or + serial are fixed. Default port on Pioneer AV receivers is 23 (according to the above mentioned Pioneer documetation)
+ Note: devices to control zone2, zone3 and/or HD-zone are autocreated on reception of the first message for those zones.

Examples:
    @@ -1516,7 +1427,7 @@ RC_layout_PioneerAVR() {

    where <what> is one of
  • reopen
    Tries to reopen the data connection
  • -
  • statusRequest
    gets some information from the physical Pioneer AVR and updates the readings accordingly
  • +
  • statusRequest
    gets some information from the Pioneer AV receiver and updates the readings accordingly
  • off
    turn power off
  • on
    turn power on
  • toggle
    toggles power
  • @@ -1554,12 +1465,12 @@ RC_layout_PioneerAVR() {
      get <name> raw <command>

      - Sends the command <command> to the physical Pioneer AVR device + Sends the command <command> to the Pioneer AV receiver <name>. -

    • loadInputNames
      reads the names of the inputs from the physical Pioneer AVR +

    • loadInputNames
      reads the names of the inputs from the Pioneer AV receiver and checks if those inputs are enabled
    • display
      updates the reading 'display' and 'displayPrevious' with what is shown - on the display of the physical Pioneer AVR
    • + on the display of the Pioneer AV receiver


    @@ -1616,9 +1527,11 @@ RC_layout_PioneerAVR() { define <name> PIONEERAVR serial <SerialDevice>[<@BaudRate>]

    - Definiert ein physisches PIONEERAVR device. Die Schlüsselwörter telnet bzw. + Definiert ein Fhem device für einen Pioneer AV Receiver (Kommunikationsschnittstelle und Steuerung der Main - Zone). Die Schlüsselwörter telnet bzw. serial sind fix. Der Standard Port für die Ethernet Verbindung bei Pioneer AV Receiver ist 23 - (laut der oben angeführten Pioneer Dokumetation)

    + (laut der oben angeführten Pioneer Dokumetation)
    + Note: Devices zur Steuerung der Zone2, Zone3 und/oder HD-Zone werden per autocreate beim Eintreffen der ersten Nachricht für eine der Zonen erzeugt. +

    Beispiele:
      @@ -1636,19 +1549,19 @@ RC_layout_PioneerAVR() {

      "was" ist eines von
    • reopen
      Versucht die Datenverbindung wieder herzustellen
    • -
    • statusRequest
      Fragt Information vom physischen Pioneer AV Receiver und aktualisiert die readings entsprechend
    • -
    • off
      Ausschalten
    • -
    • on
      Einschalten
    • -
    • toggle
      Ein/Ausschalten
    • +
    • statusRequest
      Fragt Information vom Pioneer AV Receiver und aktualisiert die readings entsprechend
    • +
    • off
      Ausschalten der Main Zone
    • +
    • on
      Einschalten der Main Zone
    • +
    • toggle
      Ein/Ausschalten der Main Zone
    • volume <0 ... 100>
      Lautstärke der Main-Zone in % der Maximallautstärke
    • -
    • volumeUp
      Lautstärke um 0.5dB erhöhen
    • -
    • volumeDown
      Lautstärke um 0.5dB verringern
    • -
    • volumeStraight<-80.5 ... 12>
      Einstellen der Lautstärke mit einem Wert, wie er am Display des Pioneer AV Receiver angezeigt wird
    • -
    • mute
    • +
    • volumeUp
      Lautstärke der Main Zone um 0.5dB erhöhen
    • +
    • volumeDown
      Lautstärke der Main Zone um 0.5dB verringern
    • +
    • volumeStraight<-80.5 ... 12>
      Einstellen der Lautstärke der Main Zone mit einem Wert, wie er am Display des Pioneer AV Receiver angezeigt wird
    • +
    • mute der Main Zone
    • input
      Die Liste der verfügbaren (also der nicht deaktivierten) Eingangsquellen wird beim Start von Fhem und auch mit get statusRequest eingelesen
    • -
    • inputUp
      nächste Eingangsquelle auswählen
    • -
    • inputDown
      vorherige Eingangsquelle auswählen
    • +
    • inputUp
      nächste Eingangsquelle der Main Zone auswählen
    • +
    • inputDown
      vorherige Eingangsquelle der Main Zone auswählen
    • listeningMode
    • play
      Startet die Wiedergabe für folgende Eingangsquellen: AdapterPort, Ipod, Favorites, InternetRadio, MediaServer, Mhl
    • pause
      Unterbricht die Wiedergabe für die gleichen Eingangsquellen wie "play"
    • diff --git a/fhem/FHEM/71_PIONEERAVRZONE.pm b/fhem/FHEM/71_PIONEERAVRZONE.pm index b3225f670..6854c9937 100644 --- a/fhem/FHEM/71_PIONEERAVRZONE.pm +++ b/fhem/FHEM/71_PIONEERAVRZONE.pm @@ -20,7 +20,6 @@ # ############################################################################## - package main; use strict; @@ -47,7 +46,7 @@ PIONEERAVRZONE_Initialize($) $hash->{ParseFn} = "PIONEERAVRZONE_Parse"; $hash->{AttrFn} = "PIONEERAVRZONE_Attr"; - $hash->{AttrList} = "IODev zone ". + $hash->{AttrList} = "IODev ". $readingFnAttributes; } @@ -271,7 +270,7 @@ return undef; sub PIONEERAVRZONE_Parse($$) { - # we are called from dispatch() from the physical device + # we are called from dispatch() from the PIONEERAVR device # we never come here if $msg does not match $hash->{MATCH} in the first place # NOTE: we will update all matching readings for all (logical) devices, not just the first! @@ -481,9 +480,9 @@ PIONEERAVRZONE_Define($$) my ($hash, $def) = @_; my @a = split("[ \t]+", $def); - return "Usage: define PIONEERAVRZONE [ [...]]" if(int(@a) < 2); + return "Usage: define PIONEERAVRZONE ... wrong paramter count: ".int(@a) if(int(@a) != 3); my $name= $a[0]; - + AssignIoPort($hash); my $IOhash= $hash->{IODev}; @@ -493,18 +492,20 @@ PIONEERAVRZONE_Define($$) return $err; } - #2. Parameter (Zone) + #Parameter (Zone) my $zone=""; - if(defined($a[2])) { - if ($a[2] =~ m/[zone\d]|[hdZone]/) { - $zone= $a[2]; - } + if ($a[2] =~ m/^(zone\d|hdZone)$/) { + $zone= $a[2]; } else { - my $err= "PIONEERAVRZONE define $name error: unknown Zone '$zone' -> must be one of [zone2|zone3hdZone] (I/O device is " - . $IOhash->{NAME} . ")."; + my $err= "PIONEERAVRZONE define $name error: unknown Zone ".dq($a[2])." -> must be one of [zone2|zone3|hdZone] (I/O device is " + . $IOhash->{NAME} . "). Usage: define PIONEERAVRZONE "; Log3 $hash, 1, $err; return $err; } + + # for autocreate: we store here a pointer of defined devices + # so we can check if the device exists + $modules{PIONEERAVRZONE}{defptr}{$zone} = $hash; if(!defined($IOhash->{helper}{SETS}{$zone})) { my $err= "PIONEERAVRZONE define $name error: unknown Zone $zone (I/O device is " @@ -525,7 +526,15 @@ PIONEERAVRZONE_Define($$) } return undef; - +} +##################################### +#Function to show special chars (e.g. \n\r) in logs +sub +dq($) +{ + my ($s)= @_; + $s= "" unless(defined($s)); + return "\"" . escapeLogLine($s) . "\""; } 1; @@ -543,11 +552,12 @@ PIONEERAVRZONE_Define($$) define <name> PIONEERAVRZONE <zone>

      - Defines a Zone (zone2, zone3 or hdZone) of a PioneerAVR device.

      + Defines a Zone (zone2, zone3 or hdZone) of a PioneerAVR device.
      + Note: devices to control zone2, zone3 and/or HD-zone are autocreated on reception of the first message for those zones.

      - Normally, the logical PIONEERAVRZONE is attached to the latest previously defined physical PIONEERAVR device - for I/O. Use the IODev attribute of the logical PIONEERAVRZONE to attach to any - physical PioneerAVR device, e.g. attr myPioneerAvrZone2 IODev myPioneerAvr. + Normally, the PIONEERAVRZONE device is attached to the latest previously defined PIONEERAVR device + for I/O. Use the IODev attribute of the PIONEERAVRZONE device to attach to any + PIONEERAVR device, e.g. attr myPioneerAvrZone2 IODev myPioneerAvr.

      Examples: