diff --git a/fhem/FHEM/30_HUEBridge.pm b/fhem/FHEM/30_HUEBridge.pm index 8d366fc7d..c27fee3a6 100644 --- a/fhem/FHEM/30_HUEBridge.pm +++ b/fhem/FHEM/30_HUEBridge.pm @@ -21,6 +21,8 @@ use HttpUtils; use IO::Socket::INET; +use vars qw(%defs); + sub HUEBridge_loadHUEDevice() { @@ -30,7 +32,8 @@ HUEBridge_loadHUEDevice() } } -sub HUEBridge_Initialize($) +sub +HUEBridge_Initialize($) { my ($hash) = @_; @@ -47,12 +50,24 @@ sub HUEBridge_Initialize($) $hash->{GetFn} = "HUEBridge_Get"; $hash->{AttrFn} = "HUEBridge_Attr"; $hash->{UndefFn} = "HUEBridge_Undefine"; - $hash->{AttrList} = "key disable:1 disabledForIntervals createEventTimestampReading:1,0 eventstreamTimeout createGroupReadings:1,0 httpUtils:1,0 noshutdown:1,0 pollDevices:1,2,0 queryAfterSet:1,0 $readingFnAttributes"; + $hash->{AttrList} = "key disable:1 disabledForIntervals createEventTimestampReading:1,0 eventstreamTimeout createGroupReadings:1,0 httpUtils:1,0 ignoreUnknown:1,0 noshutdown:1,0 pollDevices:1,2,0 queryAfterSet:1,0 $readingFnAttributes"; #$hash->{isDiscoverable} = { ssdp => {'hue-bridgeid' => '/.*/'}, upnp => {} }; HUEBridge_loadHUEDevice(); + if( $init_done ) { + foreach my $chash ( values %defs ) { + next if( !$chash ); + next if( $chash->{TYPE} ne 'HUEBridge' ); + my $name = $chash->{NAME}; + if( $chash->{has_v2_api} ) { + + CommandSet( undef, "$name reconnect" ); + } + } + } + return FHEM::Meta::InitMod( __FILE__, $hash ); } @@ -141,7 +156,7 @@ HUEBridge_Read($) delete $hash->{helper}{ignored}{$code}; } - } elsif( !$hash->{helper}{ignored}{$code} ) { + } elsif( !$hash->{helper}{ignored}{$code} && !AttrVal($name, "ignoreUnknown", undef) ) { Log3 $name, 2, "$name: websocket: event for unknown device received: $code"; } @@ -334,7 +349,8 @@ HUEBridge_Notify($$) return undef; } -sub HUEBridge_Undefine($$) +sub +HUEBridge_Undefine($$) { my ($hash,$arg) = @_; @@ -721,7 +737,8 @@ HUEbridge_groupOfLights($$) return $group; } -sub HUEBridge_Set($@); +sub +HUEBridge_Set($@); sub HUEBridge_Set($@) { @@ -735,6 +752,7 @@ HUEBridge_Set($@) # usage check if($cmd eq 'reconnect') { + Log3 $name, 2, "$name: reconnecting"; HUEBridge_closeWebsocket($hash); HUEBridge_closeEventStream($hash); @@ -1503,12 +1521,24 @@ HUEBridge_Get($@) } elsif($cmd eq 'ignored' ) { return join( "\n", sort keys %{$hash->{helper}{ignored}} ); - } elsif($cmd eq 'getv2resources' ) { - HUEBridge_getv2resources($hash, 1); + } elsif($cmd eq 'refreshv2resources' ) { + return "$name: v2 api not supported" if( !$hash->{has_v2_api} ); + HUEBridge_refreshv2resources($hash, 1); return "done"; + } elsif($cmd eq 'v2resourcetypes' ) { + return "$name: v2 api not supported" if( !$hash->{has_v2_api} ); + my %result; + foreach my $entry ( values %{$hash->{helper}{resource}{by_id}} ) { + next if( $arg && $arg ne $entry->{type} ); + $result{$entry->{id}} = 1 if( $arg ); + $result{$entry->{type}} = 1 if( !$arg ); + } + return join( "\n", keys %result ); + } elsif($cmd eq 'v2resource' ) { + return "$name: v2 api not supported" if( !$hash->{has_v2_api} ); if( $arg ) { my $ret; foreach my $entry ( values %{$hash->{helper}{resource}{by_id}} ) { @@ -1523,16 +1553,33 @@ HUEBridge_Get($@) } return Dumper $hash->{helper}{resource}; - } elsif($cmd eq 'v2resourcetypes' ) { - my %result; + } elsif($cmd eq 'v2devices' ) { + return "$name: v2 api not supported" if( !$hash->{has_v2_api} ); + return "usage: $cmd [lights|sensors]" if( $arg && $arg eq '?' ); + + my $ret; foreach my $entry ( values %{$hash->{helper}{resource}{by_id}} ) { - next if( $arg && $arg ne $entry->{type} ); - $result{$entry->{id}} = 1 if( $arg ); - $result{$entry->{type}} = 1 if( !$arg ); + next if( $entry->{type} ne 'device' ); + my(undef, $t, $id) = split( '/', $entry->{id_v1} ); + next if( $arg && $arg ne $t ); + my $code = $name ."-". $id; + my $fhem_name = ''; + $fhem_name = $modules{HUEDevice}{defptr}{$code}->{NAME} if( defined($modules{HUEDevice}{defptr}{$code}) ); + $ret .= sprintf( "%-36s %-2s %-15s %s", $entry->{id}, $id, $fhem_name, $entry->{metadata}{name} ); + $ret .= "\n"; + + foreach my $service ( sort {$a->{rtype} cmp $b->{rtype}} @{$entry->{services}} ) { + $ret .= sprintf( " %-36s %s", $service->{rid}, $service->{rtype} ); + $ret .= "\n"; + } + $ret .= "\n"; } - return join( "\n", keys %result ); + $ret = sprintf( "%-36s %-2s %-15s %s\n", "ID", "V1", "FEHM", "NAME", ). + sprintf( " %-36s %s\n","ID", "TYPE" ).$ret if( $ret ); + return $ret; } elsif($cmd eq 'v2scenes' ) { + return "$name: v2 api not supported" if( !$hash->{has_v2_api} ); my $ret; foreach my $entry ( values %{$hash->{helper}{resource}{by_id}} ) { next if( $entry->{type} ne 'scene' ); @@ -1549,7 +1596,7 @@ HUEBridge_Get($@) } if( $hash->{has_v2_api} ) { - $list .= " v2resource v2resourcetypes v2scenes"; + $list .= " v2devices v2resource v2resourcetypes v2scenes"; } return "Unknown argument $cmd, choose one of $list"; @@ -2271,7 +2318,7 @@ HUEBridge_schedule($$;$) InternalTimer(gettimeofday()+$delay, $fn, $hash, 0); } sub -HUEBridge_getv2resources($;$) +HUEBridge_refreshv2resources($;$) { my ($hash,$blocking) = @_; my $name = $hash->{NAME}; @@ -2382,7 +2429,7 @@ HUEBridge_dispatch($$$;$) if( !$key ) { Log3 $name, 5, "$name: ignoring: $value"; - HUEBridge_getv2resources($hash); + HUEBridge_refreshv2resources($hash); next; } @@ -2444,13 +2491,13 @@ HUEBridge_dispatch($$$;$) my $device = $hash->{helper}{resource}{by_id}{$obj->{v2_id}}; if( !$device ) { Log3 $name, 2, "$name: EventStream: event for unknown device received, trying to refresh resouces"; - HUEBridge_getv2resources($hash, 1); + HUEBridge_refreshv2resources($hash, 1); $device = $hash->{helper}{resource}{by_id}{$obj->{v2_id}}; } my $service = $hash->{helper}{resource}{by_id}{$obj->{v2_service}}; if( !$service ) { Log3 $name, 2, "$name: EventStream: event for unknown service received, trying to refresh resouces"; - HUEBridge_getv2resources($hash, 1); + HUEBridge_refreshv2resources($hash, 1); $service = $hash->{helper}{resource}{by_id}{$obj->{v2_service}}; } #Log 1, Dumper $device; @@ -2575,7 +2622,7 @@ HUEBridge_dispatch($$$;$) delete $hash->{helper}{ignored}{$code}; } - } elsif( !$hash->{helper}{ignored}{$code} ) { + } elsif( !$hash->{helper}{ignored}{$code} && !AttrVal($name, "ignoreUnknown", undef) ) { Log3 $name, 3, "$name: EventStream: update for unknown device received: $code"; } @@ -2584,7 +2631,7 @@ HUEBridge_dispatch($$$;$) } elsif( $event->{type} eq 'add' ) { Log3 $name, 4, "$name: EventStream: got $event->{type} event"; - HUEBridge_schedule($hash,'HUEBridge_getv2resources'); + HUEBridge_schedule($hash,'HUEBridge_refreshv2resources'); } elsif( $event->{type} eq 'delete' ) { Log3 $name, 4, "$name: EventStream: got $event->{type} event"; @@ -2667,7 +2714,7 @@ HUEBridge_dispatch($$$;$) delete $hash->{helper}{ignored}{$code}; - } elsif( !$hash->{helper}{ignored}{$code} ) { + } elsif( $hash->{has_v2_api} && !$hash->{helper}{ignored}{$code} && !AttrVal($name, "ignoreUnknown", undef) ) { Log3 $name, 3, "$name: data for unknown sensor received: $code"; HUEBridge_schedule($hash,'HUEBridge_Autocreate'); @@ -2685,7 +2732,7 @@ HUEBridge_dispatch($$$;$) delete $hash->{helper}{ignored}{$code}; - } elsif( !$hash->{helper}{ignored}{$code} ) { + } elsif( !$hash->{helper}{ignored}{$code} && !AttrVal($name, "ignoreUnknown", undef) ) { Log3 $name, 2, "$name: data for unknown group received: $code"; HUEBridge_schedule($hash,'HUEBridge_Autocreate'); @@ -2718,7 +2765,7 @@ HUEBridge_dispatch($$$;$) delete $hash->{helper}{ignored}{$code}; } - } elsif( !$hash->{helper}{ignored}{$code} ) { + } elsif( !$hash->{helper}{ignored}{$code} && !AttrVal($name, "ignoreUnknown", undef) ) { Log3 $name, 3, "$name: data for unknown device received: $code"; } @@ -3073,15 +3120,17 @@ __END__ 2 -> the bridge will poll all devices in one go instead of each device polling itself independently
default is 2. will be deleted if v2 api is detected and eventstream connects.
  • createEventTimestampReading
    - timestamp reading for every event received
  • - 0 -> update reading without fhem event + timestamp reading for every event received
    + 0 -> update reading without fhem event
    1 -> update reading with fhem event - undef -> don't create reading + undef -> don't create reading
  • createGroupReadings
    - create 'artificial' readings for group devices.
  • - 0 -> create readings only for group devices where createGroupReadings ist set to 1 - 1 -> create readings for all group devices where createGroupReadings ist not set or set to 1 - undef -> do nothing + create 'artificial' readings for group devices.
    + 0 -> create readings only for group devices where createGroupReadings ist set to 1
    + 1 -> create readings for all group devices where createGroupReadings ist not set or set to 1
    + undef -> do nothing +
  • ignoreUnknown
    + don't try to autocreate devices after data or events with unknown references are received.
  • queryAfterSet
    the bridge will request the real device state after a set command. default is 1.
  • noshutdown