diff --git a/fhem/CHANGED b/fhem/CHANGED index bf6b6223b..90bf1a489 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: 72_FB_CALLLIST: support for contact images (new attributes + contactImageDirectory and contactImageDirectory) - change: 70_ONKYO_AVR: clearing screenItemCxxx readings on page update - bugfix: 93_DbRep: sort problem in diffValue Forum:#msg882082 - bugfix: 98_weekprofile: fix f18 style diff --git a/fhem/FHEM/72_FB_CALLLIST.pm b/fhem/FHEM/72_FB_CALLLIST.pm index 8f6599404..db2857f3e 100755 --- a/fhem/FHEM/72_FB_CALLLIST.pm +++ b/fhem/FHEM/72_FB_CALLLIST.pm @@ -52,7 +52,7 @@ FB_CALLLIST_Initialize($) "connection-mapping:textField-long ". "external-mapping:textField-long ". "create-readings:0,1 ". - "visible-columns:sortable-strict,row,state,timestamp,name,number,internal,external,connection,duration ". + "visible-columns:sortable-strict,row,state,timestamp,image,name,number,internal,external,connection,duration ". "show-icons:1,0 ". "list-type:all,incoming,outgoing,missed-calls,completed,active " . "time-format-string ". @@ -67,6 +67,8 @@ FB_CALLLIST_Initialize($) "expire-calls-after ". "no-heading:0,1 ". "no-table-header:0,1 ". + "contactImageDirectory ". + "contactDefaultImage ". $readingFnAttributes; $hash->{FW_detailFn} = "FB_CALLLIST_makeTable"; @@ -814,11 +816,12 @@ sub FB_CALLLIST_index2line($$) state => FB_CALLLIST_returnCallState($hash, $index), timestamp => FB_CALLLIST_strftime(AttrVal($name, "time-format-string", "%a, %d %b %Y %H:%M:%S"), localtime($index)), name => ($data->{external_name} eq "unknown" ? "-" : $data->{external_name}), - number => $data->{external_number}, + number => ($data->{external_number} eq "unknown" ? "-" : $data->{external_number}), external => ($data->{external_connection} ? ((exists($hash->{helper}{EXTERNAL_MAP}) and exists($hash->{helper}{EXTERNAL_MAP}{$data->{external_connection}})) ? $hash->{helper}{EXTERNAL_MAP}{$data->{external_connection}} : $data->{external_connection} ) : "-"), internal => ((exists($hash->{helper}{INTERNAL_FILTER}) and exists($hash->{helper}{INTERNAL_FILTER}{$data->{internal_number}})) ? $hash->{helper}{INTERNAL_FILTER}{$data->{internal_number}} : $data->{internal_number} ), connection => ($data->{internal_connection} ? ((exists($hash->{helper}{CONNECTION_MAP}) and exists($hash->{helper}{CONNECTION_MAP}{$data->{internal_connection}})) ? $hash->{helper}{CONNECTION_MAP}{$data->{internal_connection}} : $data->{internal_connection} ) : "-"), - duration => FB_CALLLIST_formatDuration($hash, $index) + duration => FB_CALLLIST_formatDuration($hash, $index), + image => (FB_CALLLIST_getImagePathForNumber($hash, $data->{external_number}) or "-") }; setlocale(LC_ALL, $old_locale); @@ -909,7 +912,7 @@ sub FB_CALLLIST_list2html($) $ret .= '
'; # div tag to support inform updates $ret .= ''; - $ret .= FB_CALLLIST_returnOrderedHTMLOutput($hash, FB_CALLLIST_returnTableHeader($hash), 'class="fbcalllist header"'.((AttrVal($name, "no-table-header", "0") eq "1") ? ' style="display:none;"' : ''),''); + $ret .= FB_CALLLIST_returnOrderedHTMLOutput($hash, FB_CALLLIST_returnTableHeader($hash), 'class="fbcalllist header"'.((AttrVal($name, "no-table-header", "0") eq "1") ? ' style="display:none;"' : ''),'', 1); if(AttrVal($name,'disable',"0") eq "2") { @@ -1144,10 +1147,10 @@ sub FB_CALLLIST_loadList($) ##################################### # produce a HTML -Output for a specific data set depending on visible-columns setting -sub FB_CALLLIST_returnOrderedHTMLOutput($$$$) +sub FB_CALLLIST_returnOrderedHTMLOutput($$$$;$) { - my ($hash, $line, $tr_additions, $td_additions) = @_; + my ($hash, $line, $tr_additions, $td_additions,$is_header) = @_; my $name = $hash->{NAME}; @@ -1161,11 +1164,30 @@ sub FB_CALLLIST_returnOrderedHTMLOutput($$$$) $line->{number} = ''.$line->{number}.""; } + push @ret, ''; foreach my $col (@order) { + if($col eq "image") + { + my $content; + + if($is_header) + { + $content = $line->{$col}; + } + else + { + my $url = FB_CALLLIST_generateImageUrl($hash, $line->{$col}); + $content = (defined($url) ? '' : "-" ); + } + + push @ret, ''; + next; + } + push @ret, '' if(defined($line->{$col})); } @@ -1190,6 +1212,8 @@ sub FB_CALLLIST_returnOrderedJSONOutput($$) $line->{number} = ''.$line->{number}.""; } + + $line->{image} = FB_CALLLIST_generateImageUrl($hash, $line->{image}); push @ret, '"line":"'.$line->{line}.'"'; @@ -1350,6 +1374,68 @@ sub FB_CALLLIST_updateOneItemInFHEMWEB($$) return undef; } +##################################### +# returns the filename of a corresponding contact image if exist. +sub FB_CALLLIST_getImagePathForNumber($$) +{ + my ($hash, $number) = @_; + my $name = $hash->{NAME}; + + my $local_path = AttrVal($name,"contactImageDirectory", undef); + + return undef unless(defined($local_path)); + return undef if($number eq "-"); + + $local_path =~ s,/+$,,; + + opendir(DIR, $local_path) or return undef; + + while (my $file = readdir(DIR)) + { + next if($file =~ /^\./); + next unless(-f "$local_path/$file"); + next unless($file =~ /\.(?:gif|jpg|jpe|jpeg|png|bmp)$/i); + next unless($file =~ /^$number\./); + + return $file; + } + + return AttrVal($name, "contactDefaultImage", undef); +} + +##################################### +# generates a data URL for a specific image file +sub FB_CALLLIST_generateImageUrl($$) +{ + my ($hash, $file) = @_; + my $name = $hash->{NAME}; + + return undef unless(defined($file)); + + my $local_path = AttrVal($name,"contactImageDirectory", undef); + + return undef unless(defined($local_path)); + return undef if ($file eq "-"); + + my $suffix = lc((split(/\./, $file))[-1]); + + $suffix = "jpeg" if($suffix =~ /^(?:jpg|jpe)$/); + + $local_path =~ s,/+$,,; + + my ($err, @content) = FileRead({FileName => $local_path."/".$file, ForceType=> "file"}); + + if($err) + { + Log3 $name, 3 , "FB_CALLIST ($name) - unable to load contact image: $err"; + return undef; + } + + my $base64 = encode_base64(join("\n", @content), ""); + + return "data:image/$suffix;base64,$base64"; +} + ##################################### # returns the table header in the configured language @@ -1366,6 +1452,7 @@ sub FB_CALLLIST_returnTableHeader($) state => "Status", timestamp => "Zeitpunkt", name => "Name", + image => "Bild", number => "Rufnummer", internal => "Intern", external => "Extern", @@ -1380,6 +1467,7 @@ sub FB_CALLLIST_returnTableHeader($) state => "State", timestamp => "Timestamp", name => "Name", + image => "Image", number => "Number", internal => "Internal", external => "External", @@ -1507,8 +1595,27 @@ sub FB_CALLLIST_strftime(@)
  • create-readings 0,1
  • If enabled, for all visible calls in the list, readings and events will be created. It is recommended to set the attribute event-on-change-reading to .* (all readings), to reduce the amount of generated readings for certain call events.

    Possible values: 0 => no readings will be created, 1 => readings and events will be created.
    - Default Value is 0 (no readings will be created)

    + Default Value is 0 (no readings will be created) +

    +
  • contactImageDirectory <directory>
  • + If set, FB_CALLLIST will use this directory to display a contact image for each call. + This image will be shown in the column "image", which needs to be explicit configured via attribute visible-columns. + If this directory contains a file with the external number as filename (e.g. "0123456789.jpg" or "0345678901.gif"), it will be displayed in the call list. +

    + Supported formats are: JPEG, GIF, PNG, BMP +

    + By default, no directory is set and therefore no images will be displayed +

    + +
  • contactDefaultImage <filename>
  • + If contact images are configured (via attribute contactImageDirectory) and there is no image file available or the external number is unknown, + FB_CALLLIST will use this file (e.g. unkown.jpg) as contact image in case there is no image for the external number available or the external number is unknown. + The file must be located in the directory configured via attribute contactImageDirectory. +

    + If not configured, no images will be shown for such calls. +

    +
  • disable 0,1,2,3
  • Optional attribute to disable the call list. When disabled, call events will not be processed and the list wouldn't be updated accordingly. Depending on the value, the call list can

    @@ -1534,9 +1641,9 @@ sub FB_CALLLIST_strftime(@) Possible values: 0 => no event processing when FB_CALLIST is disabled, 1 => events are still processed, even FB_CALLLIST is disabled
    Default Value is 0 (no event processing when disabled)

    -
  • expire-calls-after <time frame>
  • - Optional attribute to automatically delete finished calls which are older than a given time frame. If a finished call is older than this time frame, it will be deleted from the list. -

    A time frame can be specified as follows: +
  • expire-calls-after <timeframe>
  • + Optional attribute to automatically delete finished calls which are older than a given timeframe. If a finished call is older than this timeframe, it will be deleted from the list. +

    A timeframe can be specified as follows:
    @@ -1785,6 +1892,24 @@ sub FB_CALLLIST_strftime(@) Standardwert ist nicht gesetzt (Keine Zuordnung, es werden die Originalwerte verwendet)

    +
  • contactImageDirectory <Verzeichnis>
  • + Sofern gesetzt, nutzt FB_CALLLIST dieses Verzeichnis um Kontaktbilder für jeden Anruf anzuzeigen. + Diese Bilder werden in der Spalte "image" dargestellt, welche dazu explizit in dem Attribut visible-columns konfiguriert sein muss. + Wenn in diesem Verzeichnis eine Bilddatei mit der externen Nummer als Dateiname (z.B. 0123456789.jpg oder 0345678901.gif) enthalten ist, wird diese als Kontaktbild in der Anrufliste verwendet. +

    + Unterstützte Dateiformate: JPEG, GIF, PNG, BMP +

    + Standardmäßig ist kein Verzeichnis vorkonfiguriert. Daher werden standardmäßig keine Kontaktbilder angezeigt. +

    + +
  • contactDefaultImage <Dateiname>
  • + Sofern Kontaktbilder verwendet werden (via Attribut contactImageDirectory) und kein zugehöriges Kontaktbild existiert oder die externe Rufnummer unbekannt ist, + wird die konfigurierte Datei (z.B. unknown.jpg) als Kontaktbild verwendet. + Die Datei muss sich dabei in dem Verzeichnis befinden, welches via Attribut contactImageDirectory konfiguriert ist. +

    + Wenn nicht konfiguriert, werden keine Kontaktbilder in solchen Fällen angezeigt. +

    +
  • disable 0,1,2,3
  • Optionales Attribut zur Deaktivierung der Anrufliste. Sofern aktiviert, werden keine Anruf-Events mehr verarbeitet und die Liste nicht weiter aktualisiert. Je nach gesetztem Wert verhält sich FB_CALLLIST unterschiedlich.

    @@ -1830,7 +1955,7 @@ sub FB_CALLLIST_strftime(@) Der Wert 0 bedeutet, das keine Gespräche nach einem gewissen Zeitfenster gelöscht werden.

    Standardwert ist 0 (keine Gespräche werden nach einem Zeitfenster gelöscht)

    -
  • external-mapping <hash>
  • +
  • external-mapping <Hash>
  • Definiert eine eigene Zuordnung der externen Anschlussbezeichnung (Reading: external_connection) zu eigenen Bezeichnungen. Die Zuordnung erfolgt über eine Hash-Struktur.

    z.B.
    '; + else if(key == "image") + { + new_tr += ''; + } + else + { + new_tr += ''; + } }); new_tr += ""; @@ -114,9 +121,16 @@ function FW_FbCalllistUpdateRowNumbers(table) function FW_setCallListValue(table,index,key,val) { - table.find("tr[index='"+index+"'] td[name="+key+"]").each(function(index, obj) { - $(obj).html(val); - }); + var el = table.find("tr[index='"+index+"'] td[name="+key+"]"); + + if(key == "image") + { + el.children("img").attr("src", val); + } + else + { + el.html(val); + } } function FW_FbCalllistCreate(elName, devName, vArr, currVal, set, params, cmd)