mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
98_rssFeed: New module for rss news feeds added
git-svn-id: https://svn.fhem.de/fhem/trunk@10115 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
5ab744f5cd
commit
ef64fa1017
@ -1,5 +1,6 @@
|
||||
# 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: 89_rssFeed: New module to get data from rss news feeds
|
||||
- feature: FB_CALLMONITOR: added attribute disabledForIntervals to specify
|
||||
specific time ranges, where FB_CALLMONITOR will be disabled
|
||||
(see commandref for the exact syntax)
|
||||
|
934
fhem/FHEM/98_rssFeed.pm
Normal file
934
fhem/FHEM/98_rssFeed.pm
Normal file
@ -0,0 +1,934 @@
|
||||
##############################################
|
||||
# $Id: 98_rssFeed.pm 4934 2015-11-09 17:10:12Z benni $
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use POSIX;
|
||||
|
||||
use Encode qw(encode);
|
||||
|
||||
use XML::Simple;
|
||||
|
||||
my $modulename='rssFeed'; #Module-Name = TYPE
|
||||
|
||||
my $nb_prefix='n';
|
||||
my $nb_separator="_";
|
||||
|
||||
my $feed_prefix='f'.$nb_separator;
|
||||
my $debug_prefix='d'.$nb_separator;
|
||||
|
||||
my $startup_wait_seconds=10;
|
||||
my $default_interval=3600;
|
||||
my $min_interval=300;
|
||||
|
||||
my $default_max_lines=10;
|
||||
my $maximum_max_lines=99;
|
||||
my $nb_indexlength=length($maximum_max_lines);
|
||||
|
||||
my $rdHeadlines='.headlines';
|
||||
|
||||
my $defaultReadings="title,description,pubDate";
|
||||
my $allReadings=$defaultReadings.",link,buildDate,imageTitle,imageURL";
|
||||
|
||||
my $defaultDisabledText='this rssFeed ist currently disabled';
|
||||
|
||||
|
||||
sub
|
||||
#======================================================================
|
||||
rssFeed_Log3($$$)
|
||||
#======================================================================
|
||||
#Using my own Log3 method, expecting the same
|
||||
#parameters as the official method
|
||||
#rssFeed_Log3 <devicename>,<loglevel>,<logmessage>
|
||||
#making sure, the device-name is always contained in the log message
|
||||
{
|
||||
my ($name,$lvl,$text)=@_;
|
||||
Log3 $name,$lvl,"$name: $text";
|
||||
return undef;
|
||||
}
|
||||
|
||||
#======================================================================
|
||||
sub rssFeed_NotifyFn($$)
|
||||
#======================================================================
|
||||
{
|
||||
#TODO: Catch global INITIALIZED event!!!
|
||||
|
||||
my ($hash,$dev)=@_;
|
||||
|
||||
my $name=$hash->{NAME};
|
||||
my $src=$dev->{NAME};
|
||||
|
||||
if($src eq 'global') {
|
||||
foreach my $event (@{$dev->{CHANGED}})
|
||||
{
|
||||
rssFeed_Log3 $name,5,"global event for $name: $event";
|
||||
if($event =~ /ATTR $name disable/) {
|
||||
rssFeed_Log3 $name,4,"$name disabled changed";
|
||||
if(IsDisabled($name)) {
|
||||
rssFeed_update($hash);
|
||||
rssFeed_Log3 $hash->{NAME},4,'NotifyFn: Removing timer (disabled)';
|
||||
RemoveInternalTimer($hash);
|
||||
readingsSingleUpdate($hash,'state','disabled',1);
|
||||
} else {
|
||||
my $nexttimer=gettimeofday()+$startup_wait_seconds;
|
||||
|
||||
rssFeed_Log3 $name,4,'NotifyFn: starting timer. First event at '.localtime($nexttimer).' (enable)';
|
||||
$hash->{NEXTUPDATE}=localtime($nexttimer);
|
||||
InternalTimer($nexttimer, $modulename."_GetUpdate", $hash, 0);
|
||||
readingsSingleUpdate($hash,'state','defined',1);
|
||||
|
||||
}
|
||||
} elsif($event eq 'INITIALIZED') {
|
||||
if(IsDisabled($name)) {
|
||||
rssFeed_update($hash);
|
||||
rssFeed_Log3 $hash->{NAME},4,'NotifyFn: Removing timer (disabled)';
|
||||
RemoveInternalTimer($hash);
|
||||
readingsSingleUpdate($hash,'state','disabled',1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
rssFeed_Log3 $name,5,"$name hat ein notify von von $src erhalten";
|
||||
|
||||
return undef if(IsDisabled($name));
|
||||
return undef if($dev->{TYPE} eq 'FRITBOX');
|
||||
|
||||
|
||||
foreach my $event (@{$dev->{CHANGED}})
|
||||
{
|
||||
rssFeed_Log3 $name,5,"$src EVENT: $event";
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
#======================================================================
|
||||
rssFeed_GetUpdate($)
|
||||
#======================================================================
|
||||
#This ist the Update-Routine called when internal timer has reached
|
||||
#end. It will call the update routine, updating feed data if device
|
||||
#is not disabled.
|
||||
{
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
rssFeed_Log3 $name,4,$modulename.'_GetUpdate';
|
||||
|
||||
rssFeed_update(@_) if(!AttrVal($name,'disable',undef));
|
||||
|
||||
#Setting Internal with next timer event time
|
||||
my $nexttimer=gettimeofday()+$hash->{INTERVAL};
|
||||
$hash->{NEXTUPDATE}=localtime($nexttimer);
|
||||
|
||||
#Restarting timer
|
||||
rssFeed_Log3 $name,4,"restarting timer: next event ".localtime($nexttimer);
|
||||
InternalTimer($nexttimer, $modulename."_GetUpdate", $hash, 1);
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
#======================================================================
|
||||
rssFeed_Initialize($)
|
||||
#======================================================================
|
||||
#Module instance initialization (constructor)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
#Telling FHEM what routines to use for module handling
|
||||
$hash->{SetFn} = $modulename."_Set"; #setter
|
||||
$hash->{GetFn} = $modulename."_Get"; #getter
|
||||
$hash->{DefFn} = $modulename."_Define"; #define
|
||||
$hash->{UndefFn} = $modulename."_Undef"; #undefine
|
||||
$hash->{NotifyFn} = $modulename."_NotifyFn"; #event handling
|
||||
|
||||
#Telling FHEM what attributes are available
|
||||
$hash->{AttrList} = "disable:1,0 "
|
||||
. "rfDebug:1,0 " #enable (0) or disable (1) the device
|
||||
. "rfMaxLines " #maximum number of title-lines to extract from feed
|
||||
. "rfDisplayTitle " #display a title as first line in headlines (is perl special)
|
||||
. "rfTickerChars " #optional characters to display at the beginning and end of each headline
|
||||
. "rfEncode " #optional encoding to use for setting the readings (e.g. utf8)
|
||||
. "rfReadings:multiple-strict,".$allReadings." " #readings to fill (comma separated list)
|
||||
. "rfDisabledText "
|
||||
#. "rfLatin1ToUtf8:1,0" #optional encoding using latin1ToUtf8 for readings (TEST ONLY)
|
||||
. $readingFnAttributes; #default FHEM FnAttributes -> see commandref.
|
||||
}
|
||||
|
||||
|
||||
sub
|
||||
#======================================================================
|
||||
rssFeedGetTicker($)
|
||||
#======================================================================
|
||||
#getting the Headlines from the given device
|
||||
#rssFeedGetTicker(<devicename>)
|
||||
#This routine will ber calle by 'get ticker'.
|
||||
{
|
||||
my ($name)=@_;
|
||||
#Checking if device exists ...
|
||||
if(!$defs{$name}) {
|
||||
return "$name ist not defined";
|
||||
}
|
||||
#... and has correct TYPE
|
||||
if(!($defs{$name}{'TYPE'} eq $modulename)){
|
||||
return "$name is no $modulename device";
|
||||
}
|
||||
|
||||
#returning the Headlines stored in the corresponding reading
|
||||
return ReadingsVal($name,$rdHeadlines,"No headlines available!\nUse $name set update to refresh data.");
|
||||
|
||||
#--> returning undef here leads to a syntax error.
|
||||
# I just don't know why yet???
|
||||
#return undef;|
|
||||
}
|
||||
|
||||
|
||||
sub
|
||||
#======================================================================
|
||||
rssFeed_Set($@)
|
||||
#======================================================================
|
||||
#Setter - Handling set commands for device
|
||||
{
|
||||
my ($hash, @a) = @_;
|
||||
my $name = shift @a;
|
||||
my $cmd=shift @a;
|
||||
#Currently only the update command is available to refressh
|
||||
#feed date
|
||||
if ($cmd eq 'update') {
|
||||
rssFeed_update(@_);
|
||||
}
|
||||
else {
|
||||
return "Unknown argument $cmd, choose one of update:noArg";
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
#======================================================================
|
||||
rssFeed_Define($$)
|
||||
#======================================================================
|
||||
#defining the device using following syntax
|
||||
#define <name> rssFeed <feedurl> [interval]
|
||||
#Example URLs:
|
||||
# http://www.tagesschau.de/xml/rss2
|
||||
# http://www.spiegel.de/schlagzeilen/tops/index.rss
|
||||
{
|
||||
my ($hash, $def) = @_;
|
||||
my @a = split("[ \t][ \t]*", $def);
|
||||
|
||||
#Check if at least 2 arguments are specified (name and url)
|
||||
return "Wrong syntax: use define <name> $modulename <feedURL> [interval]" if(int(@a) < 3);
|
||||
|
||||
my $name=shift @a;
|
||||
my $type=shift @a;
|
||||
my $url=shift@a;
|
||||
my $interval=shift @a;
|
||||
|
||||
if (defined($interval)) {
|
||||
#if interval defined, make sure its a valid number
|
||||
#and is at least 5 minutes (seconds)
|
||||
$interval=$interval+0;
|
||||
$interval=$min_interval if ($interval<$min_interval);
|
||||
$hash->{INTERVAL}=$interval;
|
||||
} else {
|
||||
#otherwise set default inteval of one hour
|
||||
$hash->{INTERVAL}=$default_interval;
|
||||
}
|
||||
|
||||
#Storing the given feed-URL in the internals
|
||||
$hash->{URL}=$url;
|
||||
|
||||
if(IsDisabled($name)) {
|
||||
readingsSingleUpdate($hash,'state',"disabled",0);
|
||||
return undef;
|
||||
}
|
||||
#return undef if(IsDisabled($name));
|
||||
|
||||
#and setting a state reading for device
|
||||
#-> ToDo: finding a better state value (something meaningful)
|
||||
#-> Done: see in rssFeed_update -> set to last update timestamp
|
||||
readingsSingleUpdate($hash,'state','defined',1);
|
||||
|
||||
rssFeed_Log3 $hash->{NAME},4,'Define: Removing probably existing timer';
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
#Starting first timer loop with waiting for 10 second before first
|
||||
#update of feed data. Followint timers will then be started with the given
|
||||
#interval. This is for waiting a short ammount of time especially when
|
||||
#FHEM is started.
|
||||
my $nexttimer=gettimeofday()+$startup_wait_seconds;
|
||||
|
||||
rssFeed_Log3 $name,4,'Define: starting timer. First event at '.localtime($nexttimer);
|
||||
$hash->{NEXTUPDATE}=localtime($nexttimer);
|
||||
InternalTimer($nexttimer, $modulename."_GetUpdate", $hash, 0);
|
||||
|
||||
my $attReadings=AttrVal($hash->{NAME},"rfReadings",undef);
|
||||
$attr{$hash->{NAME}}{rfReadings}=$defaultReadings if (!$attReadings);
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
#======================================================================
|
||||
rssFeed_Undef($$)
|
||||
#======================================================================
|
||||
#Undefine of device instance (destructor)
|
||||
#Simply remove running timer(s) of device instance to be undefined.
|
||||
{
|
||||
my ( $hash, $arg ) = @_;
|
||||
rssFeed_Log3 $hash->{NAME},4,'Undef: Removing timer';
|
||||
RemoveInternalTimer($hash);
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
#======================================================================
|
||||
rssFeed_Get($@)
|
||||
#======================================================================
|
||||
# getter - Handling get requests
|
||||
{
|
||||
|
||||
my ($hash,@a)=@_;
|
||||
|
||||
my $name=shift @a;
|
||||
my $cmd=shift @a;
|
||||
|
||||
#Getting the ticker data (Healines)
|
||||
if ($cmd eq 'ticker') {
|
||||
return rssFeedGetTicker($name);
|
||||
} else {
|
||||
return "Unknown argument $cmd, choose one of ticker:noArg";
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
sub
|
||||
#======================================================================
|
||||
rssFeed_update(@)
|
||||
#======================================================================
|
||||
#This subroutine is actually doing the update of the feed data for
|
||||
#the device. It's called by 'set update' and rssFeed_GetUpdate when
|
||||
#timer is up.
|
||||
{
|
||||
|
||||
my ($dhash,@a)=@_;
|
||||
|
||||
my $name=$dhash->{NAME};
|
||||
|
||||
#Check if something wrong with the device's hash.
|
||||
if (!$name) {
|
||||
rssFeed_Log3($modulename.'_update',3,'Unable to extract device name');
|
||||
}
|
||||
|
||||
rssFeed_Log3 $name,4,'updating feed data...';
|
||||
|
||||
my $rfDebug=AttrVal($name,"rfDebug",undef);
|
||||
|
||||
#Delete all previously stored data from the readings.
|
||||
#-> ToDo: maybe I'll extract this to a clear readings [what] command
|
||||
fhem("deletereading $name $nb_prefix.*[0-9]{$nb_indexlength}.*",1);
|
||||
fhem("deletereading $name $debug_prefix.*",1);
|
||||
fhem("deletereading $name $feed_prefix.*",1);
|
||||
fhem("deletereading $name preparedLines",1);
|
||||
|
||||
#Checking if ticker characters are defined.
|
||||
#They will surround each headline in the ticker data
|
||||
my ($tt_start,$tt_end);
|
||||
my $ttt=AttrVal($name,'rfTickerChars','');
|
||||
if ($ttt) {
|
||||
$tt_start="$ttt ";
|
||||
$tt_end=" $ttt";
|
||||
} else {
|
||||
$tt_start='';
|
||||
$tt_end='';
|
||||
}
|
||||
|
||||
#get encoding attribute
|
||||
my $enc=AttrVal($name,'rfEncode',undef);
|
||||
|
||||
#TEST ONLY:
|
||||
#my $lutf=AttrVal($name,"latin1ToUtf8",undef);
|
||||
|
||||
my $rfReadings=AttrVal($name,'rfReadings',$defaultReadings);
|
||||
my @setReadings = split /,/, $rfReadings;
|
||||
my %params = map { $_ => 1 } @setReadings;
|
||||
|
||||
#setting state to the same value as it is more meaningful than
|
||||
#just 'defined'
|
||||
readingsSingleUpdate($dhash,'state',localtime(gettimeofday()),1) if(!IsDisabled($name));
|
||||
|
||||
#if the device is disabled then there will be no further update an only the
|
||||
#information, that the ticke is deactivated will be stored to ticker headlines
|
||||
# -> ToDo: This point will currently never be automatically reached, as this update-Routine
|
||||
# is not called by the timer event routine (rssFeed_GetUpdate) when the disable
|
||||
# attribute is set. Shoud be called at least once, when attribute dsable is set.
|
||||
if(AttrVal($name,'disable',undef)) {
|
||||
my $disabledText=AttrVal($name,"rfDisabledText",$defaultDisabledText);
|
||||
readingsSingleUpdate($dhash,$rdHeadlines,$tt_start.$disabledText.$tt_end,0);
|
||||
return ;
|
||||
}
|
||||
|
||||
#Get how many lines should be extracted from feed from attributes.
|
||||
#Set default to 10 if not specified
|
||||
my ($lines) = shift;
|
||||
$lines = AttrVal($name,'rfMaxLines','10')+0;
|
||||
$lines =$default_max_lines if ($lines<=0);
|
||||
$lines =$maximum_max_lines if ($lines>$maximum_max_lines);
|
||||
|
||||
rssFeed_Log3 $name,4,"rfMaxLines: $lines";
|
||||
|
||||
my ($i,$nachrichten,$response,@ticker,$ua,$url,$xml);
|
||||
|
||||
$i = 0;
|
||||
|
||||
#Getting URL from internals
|
||||
$url=InternalVal($name,'URL','');
|
||||
if (!$url) {
|
||||
#If there's no URL in internals, something is very wrong (see define)
|
||||
rssFeed_Log3 $name,3,'url not defined';
|
||||
return;
|
||||
}
|
||||
rssFeed_Log3 $name,4,$url;
|
||||
|
||||
#Getting feed data (hopefully it's xml data) from url
|
||||
my $urlbase=eval('URI->new("'.$url.'")->host');
|
||||
$response = GetFileFromURLQuiet($url,3,undef,1);
|
||||
|
||||
if(!$response) {
|
||||
#Problem: no response was returned!
|
||||
rssFeed_Log3 $name,3,'no response getting rss data from url';
|
||||
return;
|
||||
}
|
||||
|
||||
#If verbose is set to 5 then log complete response
|
||||
rssFeed_Log3 $name,5,$response;
|
||||
|
||||
#If rfDebug attribute is set then store complete response in reading
|
||||
if ($rfDebug) {
|
||||
readingsSingleUpdate($dhash,$debug_prefix."LastResponse",$response,0);
|
||||
#readingsSingleUpdate($dhash,$debug_prefix."LastResponse",$response,0) if (!$enc);
|
||||
#readingsSingleUpdate($dhash,$debug_prefix."LastResponse",encode($enc,$response),0) if ($enc);
|
||||
}
|
||||
|
||||
#Convert xml data from reponse to an array (hash?)
|
||||
$xml = new XML::Simple;
|
||||
$nachrichten = $xml->XMLin($response, ForceArray => ['item']);
|
||||
|
||||
|
||||
# -> ToDo: Add a title line to the ticker data e.g. to describe what's
|
||||
# displayed. This should be a perl-special to evaluate, so
|
||||
# the data could possibly extracted from readings.
|
||||
#my $title=AttrVal($name,'rnDisplayTitle',undef);
|
||||
#$title=$urlbase if($title eq '@');
|
||||
#push (@ticker,$title) if ($title);
|
||||
|
||||
|
||||
#Extracting data from array and converting it to utf8 where necessary.
|
||||
my $feedTitle=$nachrichten->{channel}{title};
|
||||
#$feedTitle=latin1ToUtf8($feedTitle) if($lutf);
|
||||
$feedTitle=encode($enc,$feedTitle) if($enc);
|
||||
|
||||
my $feedDescription=$nachrichten->{channel}{description};
|
||||
#$feedDescription=latin1ToUtf8($feedDescription) if($lutf);
|
||||
$feedDescription=encode($enc,$feedDescription) if ($enc);
|
||||
|
||||
my $feedLink=$nachrichten->{channel}{link};
|
||||
my $feedBuildDate=$nachrichten->{channel}{lastBuildDate};
|
||||
my $feedPubDate=$nachrichten->{channel}{pubDate};
|
||||
|
||||
my $feedImageURL=$nachrichten->{channel}{image}{url};
|
||||
|
||||
my $feedImageTitle=$nachrichten->{channel}{image}{title};
|
||||
#$feedImageTitle=latin1ToUtf8($feedImageTitle) if ($lutf);
|
||||
$feedImageTitle=encode($enc,$feedImageTitle) if ($enc);
|
||||
|
||||
#Now starting update of the readings
|
||||
readingsBeginUpdate($dhash);
|
||||
|
||||
readingsBulkUpdate($dhash,$feed_prefix.'title',$feedTitle) if ($feedTitle && $params{'title'});
|
||||
readingsBulkUpdate($dhash,$feed_prefix.'description',$feedDescription) if ($feedDescription && $params{'description'});
|
||||
readingsBulkUpdate($dhash,$feed_prefix.'link',$feedLink) if ($feedLink && $params{'link'});
|
||||
readingsBulkUpdate($dhash,$feed_prefix.'pubDate',$feedPubDate) if ($feedPubDate && $params{'pubDate'});
|
||||
readingsBulkUpdate($dhash,$feed_prefix.'buildDate',$feedBuildDate) if ($feedBuildDate && $params{'buildDate'});
|
||||
readingsBulkUpdate($dhash,$feed_prefix.'imageTitle',$feedImageTitle) if ($feedImageTitle && $params{'imageTitle'});
|
||||
readingsBulkUpdate($dhash,$feed_prefix.'imageURL',$feedImageURL) if ($feedImageURL && $params{'imageURL'});
|
||||
|
||||
#Loop through the array to extract the data for each single news block in
|
||||
#the feed data array
|
||||
while ($i < $lines) {
|
||||
if($nachrichten->{channel}{item}[$i]{title}) {
|
||||
my $cline=$nachrichten->{channel}{item}[$i]{title};
|
||||
#$cline=latin1ToUtf8($cline) if($lutf);
|
||||
$cline=encode($enc,$cline) if ($enc);
|
||||
|
||||
my $cdesc=$nachrichten->{channel}{item}[$i]{description};
|
||||
#$cdesc=latin1ToUtf8($cdesc) if($lutf);
|
||||
$cdesc=encode($enc,$cdesc) if ($enc);
|
||||
|
||||
my $clink=$nachrichten->{channel}{item}[$i]{link};
|
||||
#$clink=latin1ToUtf8($clink) if ($lutf);
|
||||
$clink=encode($enc,$clink) if ($enc);
|
||||
|
||||
my $cdate=$nachrichten->{channel}{item}[$i]{pubDate};
|
||||
#$cdate=latin1ToUtf8($cdate) if ($lutf);
|
||||
$cdate=encode($enc,$cdate) if ($enc);
|
||||
|
||||
#my $cenc=$nachrichten->{channel}{item}[$i]{enclosure}{url};
|
||||
|
||||
last unless $cline;
|
||||
|
||||
#store headlines tor ticker-array for later joining to healines string
|
||||
my $h = $tt_start.$cline.$tt_end;
|
||||
last unless $h;
|
||||
push (@ticker,$h);
|
||||
|
||||
#Index for numbering each news-block
|
||||
my $ndx=sprintf('%0'.$nb_indexlength.'s',$i);
|
||||
|
||||
readingsBulkUpdate($dhash,$nb_prefix.$ndx.$nb_separator."title",$cline) if ($params{'title'});
|
||||
readingsBulkUpdate($dhash,$nb_prefix.$ndx.$nb_separator."description", $cdesc) if ($cdesc && $params{'description'});
|
||||
readingsBulkUpdate($dhash,$nb_prefix.$ndx.$nb_separator."link", $clink) if ($params{'link'});
|
||||
readingsBulkUpdate($dhash,$nb_prefix.$ndx.$nb_separator."pubDate", $cdate) if ($params{'pubDate'});
|
||||
#readingsBulkUpdate($dhash,$nb_prefix.$ndx.$nb_separator."image",$cenc) if ($cenc);
|
||||
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
my $tickerLines=@ticker;
|
||||
readingsBulkUpdate($dhash,"preparedLines", $tickerLines);
|
||||
|
||||
#mass updating/generation of readings is complete so
|
||||
#tell FHEM to update them now!
|
||||
readingsEndUpdate($dhash,0);
|
||||
|
||||
#joining all headlines separated by newlin in a single string and
|
||||
#store it in the readings
|
||||
my $tickerHeadlines=join("\n", @ticker);
|
||||
readingsSingleUpdate($dhash,$rdHeadlines, $tickerHeadlines,0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
#======================================================================
|
||||
#======================================================================
|
||||
#
|
||||
# HTML Documentation for help and commandref
|
||||
#
|
||||
#======================================================================
|
||||
#======================================================================
|
||||
=pod
|
||||
=begin html
|
||||
|
||||
<a name="rssFeed"></a>
|
||||
<h3>rssFeed</h3>
|
||||
<ul>
|
||||
This device helps to extract data from an rss feed specified by the
|
||||
url given in the DEF section. Trhe results will be extracted to
|
||||
several corresponding readings. Also the headlines of the news
|
||||
elements will be extracted to a special "ticker"-string that could
|
||||
be retrieved via GET or a special function.
|
||||
The data will be updated automatically after the given interval.
|
||||
<br/><br/>
|
||||
|
||||
<a name="rssFeeddefine"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> rssFeed <url> [interval]</code>
|
||||
<br/><br/>
|
||||
<ul>
|
||||
url = url of the rss feed
|
||||
</ul>
|
||||
<ul>
|
||||
interval = actualization interval in seconds
|
||||
<br/>
|
||||
Minimum for this value is 600 and maximum is 86400
|
||||
</ul>
|
||||
<br/>
|
||||
Example:
|
||||
<ul>
|
||||
<code>http://www.gea.de/rss?cat=Region%20Reutlingen&main=true 3600</code>
|
||||
<br/><br/>
|
||||
The example will retrieve the data from the rss feed every hour
|
||||
</ul>
|
||||
</ul>
|
||||
<br/>
|
||||
|
||||
<a name="rssFeedset"></a>
|
||||
<b>Set</b>
|
||||
<ul>
|
||||
<code>set <name> update</code><br/>
|
||||
retrieving the data from feed and updateing readings data
|
||||
</ul>
|
||||
<br/>
|
||||
|
||||
<a name="rssFeedget"></a>
|
||||
<b>Get</b><br/>
|
||||
<ul>
|
||||
<code>get <name> ticker</code><br/>
|
||||
getting the headlines from the feed with specified formatting
|
||||
(also see attributes)
|
||||
</ul>
|
||||
<br/>
|
||||
<a name="rssFeedattr"></a>
|
||||
<b>Attributes</b>
|
||||
<ul>
|
||||
<li><a name="disabled">disable</a><br/>
|
||||
This attribute can be used to disable the entier feed device (1)
|
||||
or to activate it again (0 or attribute missing).
|
||||
If the device is disabled all readings will be removed, except
|
||||
the state reading which will then be set to "disabled".
|
||||
Data will no longer be automatically retrieved from the url.
|
||||
The ticker data contains only one line indicating the disabled
|
||||
ticker device. (s.a. attribute rfDisabledText).
|
||||
<br/>
|
||||
</li>
|
||||
<li><a name="rfDisabledText">rfDisabledText</a><br/>
|
||||
The text in this attribute will be returnde by GET ticker when the
|
||||
device is disabled (s.a. attribute disable).
|
||||
If this attribute is not specified a default text is returned.<br/>
|
||||
Example: <code>attr <name> rfDisabledText This feed is disabled</code>
|
||||
</li>
|
||||
<li><a name="rfTickerChars">rfTickerChars</a><br/>
|
||||
Specifies a string which will surround each headline in the ticker data.<br/>
|
||||
Example: <code>attr <name> rfTickerChars +++</code>
|
||||
<br/>
|
||||
Result: <code>+++ This is a sample headline +++</code>
|
||||
<br/>
|
||||
</li>
|
||||
<li><a name="rfMaxLines">rfMaxLines</a><br/>
|
||||
Defines the maximum number of news items that will be extracted from the
|
||||
feed. If there are less items in the feed then specified by this attribute
|
||||
then only that few items are extracted.
|
||||
If this attribute is missing a default of 10 will be assumed.<br/>
|
||||
Example: <code>attr <name> rfMaxLines 15</code>
|
||||
<br/>
|
||||
</li>
|
||||
<li><a name="rfEncode">rfEncode</a><br/>
|
||||
Defines an encoding which will be used for any text extracted from the
|
||||
feed that will be applied before setting the readings. Therefore the
|
||||
encode method of the Perl-core module Encode is used.
|
||||
If the attribute is missng then no encoding will be performed.
|
||||
Sometimes this is necessary when feeds contain wide characters that
|
||||
could sometimes lead to malfunction in FHEMWEB.
|
||||
Also the headlines data returned by rssFeedFunctions and get ticker
|
||||
are encoded using this method.
|
||||
<br/>
|
||||
</li>
|
||||
<li><a name="rfReadings">rfReadings</a><br/>
|
||||
This attribute defines the readings that will be created from the extracted
|
||||
data. It is a comma separated list of the following values:
|
||||
<ul>
|
||||
<li>title = title section<br/>
|
||||
extract the title section of the feed and each news item to a
|
||||
corresponding reading<br/>
|
||||
</li>
|
||||
<li>description = description section<br/>
|
||||
extract the description section of the feed and each news item
|
||||
to a corresponding reading
|
||||
<br/>
|
||||
</li>
|
||||
<li>pubDate = Publication time of feed and of each news item will
|
||||
be extracted to a corresponding reading.
|
||||
<br/>
|
||||
</li>
|
||||
<li>link = link url to the feed or to the full article of a
|
||||
single news items in the feed.
|
||||
<br/>
|
||||
</li>
|
||||
<li>buildDate = time of the last feed actulization by the feed
|
||||
vendor.
|
||||
<br/>
|
||||
</li>
|
||||
<li>imageURl = url of a probably available image of a news item
|
||||
<br/>
|
||||
</li>
|
||||
<li>imageTitle = image title of a probably available news item
|
||||
image.
|
||||
<br/>
|
||||
</li>
|
||||
</ul>
|
||||
If this attribute is missing "title,description,pubDate" will be assumed
|
||||
as default value. When the device is defined for the first time the
|
||||
attribute will be automatically created with the default value.
|
||||
<br/>
|
||||
</li>
|
||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||||
</ul>
|
||||
<br/>
|
||||
<a name="rssFeedfunctions"></a>
|
||||
<b>Functions</b>
|
||||
<ul>
|
||||
<li>rssFeedGetTicker<br/>
|
||||
This function will returned the foratted headlines as a single string.
|
||||
Each headline will be separated by a new line character.
|
||||
The result of this function can for example be used in InfoPanel as
|
||||
ticker data.
|
||||
The function takes the name of a rssFeed device as single parameter.
|
||||
The result is the same as from <code>get ticker</code> as it uses this function too.
|
||||
Syntax: <code> rssFeedGetTicker(<rssFeedDevice>)</code><br/>
|
||||
</li>
|
||||
</ul><br/>
|
||||
<a name="rssFeedreadings"></a>
|
||||
<b>Readings</b>
|
||||
<ul>
|
||||
Depending on the attribute rfReadings a bunch of readings is created
|
||||
from the extracted news feed data.
|
||||
Some of the readings ar prefixed to tell to which part of the feed the
|
||||
data belongs to.
|
||||
</ul>
|
||||
<ul>
|
||||
<br/>
|
||||
<li><code>Nxx_</code><br/>
|
||||
readings with that prefix correspond to the news items in the feed.
|
||||
<code>xx</code> index of the news item
|
||||
<br/>
|
||||
Example showing the readings of a single news item<br/>
|
||||
<ul>
|
||||
<code> N00_title </code><br/>
|
||||
<code> N00_descripton </code><br/>
|
||||
<code> N00_pubDate </code><br/>
|
||||
</ul>
|
||||
</li>
|
||||
<li><code>f_</code><br/>
|
||||
redings with that prefix correspond to the feed itself.
|
||||
<br/>
|
||||
Example of feed-readings:
|
||||
<ul>
|
||||
<code> f_title </code><br/>
|
||||
<code> f_descripton </code><br/>
|
||||
<code> f_buildDate </code><br/>
|
||||
</ul>
|
||||
</li>
|
||||
<li><code>preparedLines</code><br/>
|
||||
This readings contains the number of new items that were extracted
|
||||
in the last update of the feed data.
|
||||
</li>
|
||||
<li><code>state</code><br/>
|
||||
The state reading contains the timestamp of the last automatic or manual
|
||||
update of the device data from the feed, as long as the device is not
|
||||
disabled.
|
||||
If the device is disabled state contains "disabled".
|
||||
When the device is defined then the start of cyclic updates is retarded
|
||||
for about 10 seconds. During that time state is set to "defined"
|
||||
</li>
|
||||
</ul><br/>
|
||||
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
|
||||
=begin html_DE
|
||||
|
||||
<a name="rssFeed"></a>
|
||||
<h3>rssFeed</h3>
|
||||
<ul>
|
||||
|
||||
Mit diesem Hilfs-Device kann ein RSS-Feed per URL abgerufen werden.
|
||||
Das Ergebnis wird zum einen in entsprechende Readings (s.u.) eingetragen,
|
||||
zum Anderen können die Schlagzeilen (Headlines) noch per GET oder per
|
||||
bereitgestellter Funktion als Ticker-Daten abgerufen werden.
|
||||
Die Daten des RSS-Feeds werden dabei jeweils im angegebenen Interval
|
||||
aktualisiert.
|
||||
<br><br>
|
||||
|
||||
<a name="rssFeeddefine"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> rssFeed <url> [interval]</code>
|
||||
<br><br>
|
||||
<ul>
|
||||
url = URL zum RSS-Feed
|
||||
</ul>
|
||||
<ul>
|
||||
interval = Aktualisierungsinterval in Sekunden<br>
|
||||
minimum Wert sind 600 Sekunden (10 Minuten)<br>
|
||||
maximum Wert sind 86400 Sekunden (24 Stunden)
|
||||
</ul>
|
||||
<br>
|
||||
Beispiel:
|
||||
<ul>
|
||||
<code>http://www.gea.de/rss?cat=Region%20Reutlingen&main=true 3600</code>
|
||||
<br><br>
|
||||
Damit wird stündlich der RSS-Feed des Reutlinger Generalanzeigers
|
||||
abgerufen.
|
||||
</ul>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<a name="rssFeedset"></a>
|
||||
<b>Set</b>
|
||||
<ul>
|
||||
<code>set <name> update</code><br>
|
||||
Abrufen der Daten vom rssFeed und aktualisieren der Readings
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<a name="rssFeedget"></a>
|
||||
<b>Get</b><br>
|
||||
<ul>
|
||||
<code>get <name> ticker</code><br>
|
||||
Abrufen der zuletzt gelesenen Schlagzeilen im gewünschten
|
||||
Format (s. Attribute)
|
||||
</ul>
|
||||
<br>
|
||||
<a name="rssFeedattr"></a>
|
||||
<b>Attribute</b>
|
||||
<ul>
|
||||
<li><a name="disabled">disabled</a><br>
|
||||
Mit diesem Attribut kann das Device deaktiviert (1) werden
|
||||
bzw. auch wieder aktiviert (0 oder Attribut nicht vorhandn).
|
||||
Wenn das device deaktiviert ist, sind keine Readings mehr
|
||||
vorhanden, außer state. Außerdem werden die Daten nicht mehr
|
||||
zyklisch aktualisiert und get ticker liefert nur noch die
|
||||
Information zurück, dass der Ticker nicht mehr aktiv ist
|
||||
(s. dazu auch Attribut rfDisabledText).
|
||||
<br>
|
||||
</li>
|
||||
<li><a name="rfDisabledText">rfDisabledText</a><br>
|
||||
Der hier eingetragenee Text wird beim Abruf der Schlagzeilen als einzige
|
||||
Zeile angezeigt, wenn der rssFeed disabled ist (s. Attribut disabled).
|
||||
Ist dieses Attribut nicht angegeben, so wird ein Standardtext angezeigt.<br>
|
||||
Beispiel: <code>attr <name> rfDisabledText Dieser Feed wurde deaktiviert</code>
|
||||
</li>
|
||||
<li><a name="rfTickerChars">rfTickerChars</a><br>
|
||||
Hiermit kann eine Zeichenfolge festgelegt werden, die bei den Schlagzeilen
|
||||
für den get-Abruf vor und nach jeder Schlagzeile, wie bei einem Nachrichten-Ticker
|
||||
angefügt wird.
|
||||
Beispiel: <code>attr <name> rfTickerChars +++</code>
|
||||
<br>
|
||||
Ergebnis: <code>+++ Dies ist eine Beispiel-Schlagzeile +++</code>
|
||||
<br>
|
||||
</li>
|
||||
<li><a name="rfMaxLines">rfMaxLines</a><br>
|
||||
Bestimmt, wieviele Schlagzeilen maximal aus dem Feed extrahiert werden sollen.<br>
|
||||
Sind weniger Nachrichten-Elemente im Feed enthalten, als über rfMaxLines angegeben,
|
||||
so werden eben nur so viele Schlagzeilen extrahiert, wie vorhanden sind.<br>
|
||||
Ist dieses Attribut nich angegeben, so wird dafür der Standard-Wert 10 angenommen.<br>
|
||||
Beispiel: <code>attr <name> rfMaxLines 15</code>
|
||||
<br>
|
||||
</li>
|
||||
<li><a name="rfEncode">rfEncode</a><br>
|
||||
Hier kann eine Encoding-Methode (Bspw. utf8) angegeben werden.
|
||||
Die Texte die aus dem Feed extrahiert werden (title, descripton, ...)
|
||||
werden dann vor der Zuwesung an die Readings mittels encode (Perl core-Module Encode)
|
||||
enkodiert. Fehlt dieses Attribut, so findet keine umkodierung statt.
|
||||
Das kann u.U. notwendig sein, wenn in den zurückgelieferten Feed-Daten s.g. wide Characters
|
||||
enthalten sind. Dies kann evtl. dazu führen, das u.a. die Darstellung in FHEMWEB nicht mehr
|
||||
korrekt erfolgt.
|
||||
Dies betrifft auch das Ergebnis von rssFeedFunctions, bzw. get ticker.
|
||||
<br>
|
||||
</li>
|
||||
<li><a name="rfReadings">rfReadings</a><br>
|
||||
Über dieses Attribut kann angegeben werden, welche Daten aus dem RSS-Feed in
|
||||
Readings extrahiert werden sollen. Das Attribut ist als Komma getrennte Liste
|
||||
anzugeben.<br>
|
||||
Zur Auswahl stehen dabei folgende möglichen Werte:
|
||||
<ul>
|
||||
<li>title = Titelzeile<br>
|
||||
Dies erzeugt ein Reading für den Feed-Titel und für jedes
|
||||
Nachrichten-Element aus dem Feed.<br>
|
||||
</li>
|
||||
<li>description = Beschreibungstext
|
||||
Dies erzeugt ein Reading für die Feed-Beschreibung, bzw.
|
||||
für den Beschreibungstext jeden Nachrichten-Eelements.<br>
|
||||
</li>
|
||||
<li>pubDate = Zeitpunkt der Veröffentlichung des Feeds, bzw. der einzelnen
|
||||
Nachrichten-Elemente
|
||||
<br>
|
||||
</li>
|
||||
<li>link = Link zum Feed, bzw. zum einzelnen Nachrichten-Element auf
|
||||
der Homepage des Feeds.
|
||||
<br>
|
||||
</li>
|
||||
<li>buildDate = Zeitpunkt der letzten aktualisierung der Feed-Daten
|
||||
vom Feed-Betreiber.
|
||||
<br>
|
||||
</li>
|
||||
<li>imageURl = URL zum ggf. vorhandenen Bild eines Nachrichten-Elements,
|
||||
bzw. zum Nachrichten-Feed.
|
||||
<br>
|
||||
</li>
|
||||
<li>imageTitle = Titel eines ggf. zum Feed oder Nachrichten-Element
|
||||
vorhandenen Bildes.
|
||||
<br>
|
||||
</li>
|
||||
</ul>
|
||||
Ist Dieses Attribut nicht vorhanden, so werden die Werte "title,description,pubDate" als
|
||||
Voreinstellung angenommen. Beim ersten Anlegen des Device wird das Attribut automatisch
|
||||
erste einmal mit genau dieser Voreinstellung belegt.
|
||||
|
||||
<br>
|
||||
</li>
|
||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||||
</ul>
|
||||
<br>
|
||||
<a name="rssFeedfunctions"></a>
|
||||
<b>Funktionen</b>
|
||||
<ul>
|
||||
<li>rssFeedGetTicker<br>
|
||||
Diese Funktion gibt die ermittelten und formatierten Schlagzeilen als Zeichenkette
|
||||
zurück. Die einzelnen Schlagzeilen sind dabei durch Zeilenvorschub getrenn.
|
||||
Dieses Ergebnis kann bspw. in einem InfoPanel für einen Ticker verwendet werden.
|
||||
Der Funktion muss dazu der Name eines rssFeed-Devices übergeben werden.
|
||||
Die Ausgabe ist praktisch die selbe wie das Ergebnis, das bei <code>get ticker</code>
|
||||
geliefert wird.<br>
|
||||
Syntax: <code> rssFeedGetTicker(<rssFeedDevice>)</code><br>
|
||||
</li>
|
||||
</ul><br>
|
||||
<a name="rssFeedreadings"></a>
|
||||
<b>Readings</b>
|
||||
<ul>
|
||||
Je nach Auswahl der Attribute werden verschiedene Readings bereitgestellt.
|
||||
Diese Readings sind teilweise mit einem Präfix versehen um sie bspw. dem Feed
|
||||
selbst oder einem Nachrichten-Element zuozuordnen.
|
||||
</ul>
|
||||
<ul>
|
||||
<br>
|
||||
<li><code>Nxx_</code><br>
|
||||
Diese Readings beziehen sich alle auf die einzelnen Nachrichten-Elemente, wobei
|
||||
<code>xx</code> den Index des jeweiligen Nachrichten-Elements angibt.
|
||||
<br>
|
||||
Beispiel für die Readings eines Nachrichten-Elements:<br>
|
||||
<ul>
|
||||
<code> N00_title </code><br/>
|
||||
<code> N00_descripton </code><br/>
|
||||
<code> N00_pubDate </code><br/>
|
||||
</ul>
|
||||
</li>
|
||||
<li><code>f_</code><br>
|
||||
Diese Readings beziehen sich alle auf den Nachrichten-Feed selbst.
|
||||
<br>
|
||||
Beispiel für die Readings des Nachrichten-Feeds<br>
|
||||
<ul>
|
||||
<code> f_title </code><br/>
|
||||
<code> f_descripton </code><br/>
|
||||
<code> f_buildDate </code><br/>
|
||||
</ul>
|
||||
</li>
|
||||
<li><code>preparedLines</code><br>
|
||||
Dieses Reading gibt an, wie viele Schlagzeilen tatsächlich beim letzten
|
||||
update aus dem Nachrichten-Feed extrahiert wurden.
|
||||
</li>
|
||||
<li><code>state</code><br>
|
||||
Dieses Reading gibt, wenn das Device nicht disabled ist, den Zeitpunkt
|
||||
der letzten aktualisierung mittels update an, egal ob automatisch oder
|
||||
manuell ausgelöst. Ist das device disabled, steht genau das im Reading.
|
||||
Beim Anlegegen des Device mittels define findet das erste Aktualisieren
|
||||
der Daten verzögert statt. Während dieser Verzögerung steht der state
|
||||
auf "defined".
|
||||
</li>
|
||||
</ul><br>
|
||||
|
||||
</ul>
|
||||
|
||||
=end html_DE
|
||||
=cut
|
@ -655,4 +655,8 @@
|
||||
- added new module 30_DUOFERN
|
||||
|
||||
- Sun Nov 29 2015 (DS_Starter)
|
||||
- added new module 49_SSCam to trigger records of cameras within Synology Surveillance Station
|
||||
- added new module 49_SSCam to trigger records of cameras within Synology Surveillance Station
|
||||
|
||||
- Sun Dec 06 2015 (Benni)
|
||||
- added new module 98_rssFeed to get data from rss news feeds
|
||||
|
||||
|
@ -323,6 +323,7 @@ FHEM/98_pilight.pm andreas-fey http://forum.fhem.de Unterstue
|
||||
FHEM/98_ping mattwire http://forum.fhem.de Sonstiges
|
||||
FHEM/98_rain.pm baumrasen http://forum.fhem.de Sonstiges
|
||||
FHEM/98_restore.pm rudolfkoenig http://forum.fhem.de Sonstiges
|
||||
FHEM/98_rssFeed.pm Benni http://forum.fhem.de Unterstuetzende Dienste
|
||||
FHEM/98_statistics.pm tupol http://forum.fhem.de Unterstuetzende Dienste (Link als PM an tupol)
|
||||
FHEM/98_structure.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
||||
FHEM/98_telnet.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
||||
|
@ -133,6 +133,7 @@
|
||||
<a href="#readingsHistory">readingsHistory</a>
|
||||
<a href="#readingsProxy">readingsProxy</a>
|
||||
<a href="#remotecontrol">remotecontrol</a>
|
||||
<a href="#rssFeed">rssFeed</a>
|
||||
<a href="#RESIDENTS">RESIDENTS</a>
|
||||
<a href="#ROOMMATE">ROOMMATE</a>
|
||||
<a href="#SUNRISE_EL">SUNRISE_EL</a>
|
||||
|
@ -133,6 +133,7 @@
|
||||
<a href="#readingsHistory">readingsHistory</a>
|
||||
<a href="#readingsProxy">readingsProxy</a>
|
||||
<a href="#remotecontrol">remotecontrol</a>
|
||||
<a href="#rssFeed">rssFeed</a>
|
||||
<a href="#RESIDENTS">RESIDENTS</a>
|
||||
<a href="#ROOMMATE">ROOMMATE</a>
|
||||
<a href="#SUNRISE_EL">SUNRISE_EL</a>
|
||||
|
Loading…
Reference in New Issue
Block a user