############################################## # $Id$ ############################################## package main; use strict; use warnings; use POSIX; #use Encode qw(encode); my $version='0.95'; my $apiurl='http://qrcode.tec-it.com/API/QRCode'; my $service='TEC-IT'; my $modulename='QRCode'; #Module-Name = TYPE my $defsyntax="define $modulename"; my $defImgPath='/tmp'; my $defWidth=200; my $defHeight=200; sub #====================================================================== QRCode_Log3($$$) #====================================================================== #Using my own Log3 method, expecting the same #parameters as the official method #QRCode_Log3 ,, #making sure, the device-name is always contained in the log message { my ($name,$lvl,$text)=@_; Log3 $name,$lvl,"$name: $text"; return undef; } sub #====================================================================== QRCode_Initialize($) #====================================================================== #Module instance initialization (constructor) { my ($hash) = @_; #Telling FHEM what routines to use for module handling $hash->{SetFn} = $modulename."_Set"; #setter $hash->{DefFn} = $modulename."_Define"; #define $hash->{FW_detailFn} = $modulename."_FWDetail"; $hash->{AttrFn} = $modulename."_Attr"; $hash->{NotifyFn} = $modulename."_Notify"; #Telling FHEM what attributes are available $hash->{AttrList} = "qrData:textField " #Text für den QRCode im generic Modus . "qrSize:small,medium,large " . "qrColor " . "qrBackColor " . "qrTransparent:True,False " . "qrQuietZone " . "qrQuietUnit:mm,in,mil,mod,px " . "qrCodepage:UTF8,Cyrillic,Ansi " . "qrResolutionDPI " . "qrErrorCorrection:L,M,Q,H " . "qrDisplayWidth " . "qrDisplayHeight " . "qrDisplayData:0,1 " . "qrNoAutoUpdate:1 " . "qrDisplayNoImage:1 " . "qrDisplayNoText:1 " . "qrDisplayText:textField-long " #. "qrDeliveryMethod:Base64,Image,Download " # We only use 'Image' . $readingFnAttributes; #default FHEM FnAttributes -> see commandref. } sub #====================================================================== QRCode_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') { QRCode_update(@_); } else { return "Unknown argument $cmd, choose one of update:noArg"; } return undef; } sub #====================================================================== QRCode_Define($$) #====================================================================== #defining the device using following syntax #define QRCode { my ($hash, $def) = @_; my @a = split("[ \t][ \t]*", $def); #Check if at least 2 arguments are specified (name and url) return "Wrong syntax: use $defsyntax" if(int(@a) != 2); my $name = shift @a; my $type = shift @a; $hash->{SERVICE}=$service; $hash->{APIURL}=$apiurl; $hash->{NOTIFYDEV}='global'; $hash->{VERSION}=$version; #setting initial state reading for device readingsSingleUpdate($hash,'state','defined',1); return undef; } #====================================================================== sub QRCode_Attr ($$$$) #====================================================================== #Checking Attributes for validity { my ( $cmd, $name, $attrName, $attrValue ) = @_; my $error=undef; if($cmd eq 'set') { QRCode_Log3 $name,4,"checking new attribute value $attrName=$attrValue"; if($attrName eq 'qrResolutionDPI') { $error='dpi value is out of range (96...600)' if($attrValue < 96 || $attrValue > 600); } elsif ($attrName eq 'qrTransparent') { $error='transparent flag must be set to True or False' if($attrValue !~ /(True|False)/); } elsif ($attrName eq 'qrSize') { $error='size must be one of small, medium or large' if ($attrValue !~ /(small|medium|large)/); } elsif ($attrName =~ /(qrBackColor|qrColor)/) { $error='color must be a hex color RGB value (e.g. FF0000 for red)' if ($attrValue !~ /^(?:[0-9a-fA-F]{3}){1,2}$/); } elsif ($attrName eq 'qrQuietUnit') { $error='unit must be one of mm,in,mil,mod,px' if ($attrValue !~/(mm|in|mil|mod|px)/); } elsif ($attrName eq 'qrErrorCorrection') { $error='error correction must be one of L,M,Q,H' if ($attrValue !~ /^[LMQH]$/); } elsif ($attrName eq 'qrCodepage') { $error='codepage must be one of UTF8,Cyrillic,Ansi' if ($attrValue !~ /(UTF8|Cyrillic|Ansi)/); } elsif ($attrName =~/(qrQuietZone|qrDisplayHeight|qrDisplayWidth)/) { $error='value must be a positive number' if ($attrValue <= 0); } elsif ($attrName =~ /(qrNoAutoUpdate|qrDisplayNoImage|qrDisplayNoText)/) { $error='value can be only set to 1 (otherwise delete the attribute)' if ($attrValue != 1); } } return $error; } #====================================================================== sub QRCode_Notify($$) #====================================================================== #Getting notifications to enable auto update feature when attributes #are changed that are relevant for url and QRCode generation { return undef unless ($init_done); my ($hash,$dev)=@_; my $name=$hash->{NAME}; my $src=$dev->{NAME}; my $needsUpdate=undef; if($src eq 'global') { foreach my $event (@{$dev->{CHANGED}}) { QRCode_Log3 $name,4,"global event for $name: $event"; my @evtArray = split /\s+/, $event; my $cmd=$evtArray[0]; QRCode_Log3 $name,4,"event is $cmd"; if($cmd =~ /.*ATTR/) { my $devName=$evtArray[1]; my $attrName=$evtArray[2]; QRCode_Log3 $name,4,"attribute $attrName of $devName"; if($devName eq $name) { if($attrName =~ /^(qrData|qrSize|qrColor|qrBackColor|qrTransparent|qrQuietZone|qrQuietUnit|qrCodepage|qrResolutionDPI|qrErrorCorrection)$/) { QRCode_Log3 $name,4,"$name auto update relevant attribute changed"; $needsUpdate=1; } } else { QRCode_Log3 $name,4,"only checking own attributes this one was for $devName -> ignoring!"; } } } } QRCode_Log3 $name,5,"$name was notified by $src erhalten"; foreach my $event (@{$dev->{CHANGED}}) { QRCode_Log3 $name,5,"$src EVENT: $event"; } if($needsUpdate && !AttrVal($name,'qrNoAutoUpdate',undef)) { QRCode_Log3 $name,4,"auto updating ..."; QRCode_update($hash); } return undef; } sub #====================================================================== QRCode_update(@) #====================================================================== #This subroutine is actually doing the update of QRCode-url { my ($dhash,@a)=@_; my $name=$dhash->{NAME}; my $errText=''; QRCode_Log3 $name,4,'updating url ...'; #Check if something wrong with the device's hash. if (!$name) { $errText='Unable to extract device name'; QRCode_Log3($modulename.'_update',3,$errText); readingsSingleUpdate($dhash,'data',$errText,1); #readingsSingleUpdate($dhash,'error',1,1); $defs{$name}{ERROR}=1; return; } #Getting Api-URL from internals my $url=InternalVal($name,'APIURL',''); if (!$url) { #If there's no URL in internals, something is very wrong (see define) $errText='APIURL is not defined'; QRCode_Log3($modulename.'_update',3,$errText); readingsSingleUpdate($dhash,'data',$errText,1); #readingsSingleUpdate($dhash,'error',1,1); $defs{$name}{ERROR}=1; return; } delete($defs{$name}{ERROR}) if defined ReadingsVal($name,'error',undef); my $data=AttrVal($name,'qrData',undef); if(!$data) { $errText='No data to encode! Attribute qrData not defined!'; QRCode_Log3($modulename.'_update',3,$errText); readingsSingleUpdate($dhash,'data',$errText,1); #readingsSingleUpdate($dhash,'error',1,1); $defs{$name}{ERROR}=1; return; } delete($defs{$name}{ERROR}) if defined InternalVal($name,'ERROR',undef); my $encdata=urlEncode($data); $url.="?data=$encdata"; my $fcolor=AttrVal($name,'qrColor',undef); $url.="&color=$fcolor" if($fcolor && $fcolor ne '000000'); my $transp=AttrVal($name,'qrTransparent',undef); $url.="&istransparent=$transp" if($transp && $transp ne 'False'); my $bcolor=AttrVal($name,'qrBackColor',undef); $url.="&backcolor=$bcolor" if($bcolor && $bcolor !~ /^(?:[fF]{3}){1,2}$/ && !$transp); my $qzone=AttrVal($name,'qrQuietZone',undef); $url.="&quietzone=$qzone" if($qzone && $qzone > 0); my $qunit=AttrVal($name,'qrQuietUnit',undef); $url.="&quietunit=$qunit" if($qunit && $qunit ne 'mm' ); my $cerr=AttrVal($name,'qrErrorCorrection',undef); $url.="&errorcorrection=$cerr" if($cerr && $cerr ne 'L'); my $cpage=AttrVal($name,'qrCodepage',undef); $url.="&codepage=$cpage" if($cpage && $cpage ne 'UTF8'); my $dpi=AttrVal($name,'qrResolutionDPI',undef); $url.="&dpi=$dpi" if($dpi && $dpi != 300); my $size=AttrVal($name,'qrSize',undef); $url.="&size=$size" if($size && $ size ne 'medium'); my $response = GetFileFromURLQuiet($url,5,undef,1); QRCode_Log3 $name,5,"--- BOF ---"; QRCode_Log3 $name,5,$response; QRCode_Log3 $name,5,"--- EOF ---"; # Maybe I'll do a caching of the created QRCode later # my $fpath=AttrVal($name,'qrFilePath',$defImgPath); # my $fname="$fpath/$name.png"; # my @fcontent=($response); # my $err=FileWrite({ FileName=>$fname,ForceType=>"file",NoNL=>1 },@fcontent); #Now starting update of the readings readingsBeginUpdate($dhash); # readingsBulkUpdateIfChanged($dhash,'file_name',$fname); readingsBulkUpdateIfChanged($dhash,'data',$data); readingsBulkUpdateIfChanged($dhash,'qrcode_url',$url); readingsBulkUpdate($dhash,'state',TimeNow()); #mass updating/generation of readings is complete so #tell FHEM to update them now! readingsEndUpdate($dhash,1); return; } #====================================================================== sub QRCode_getHtml($;$$) #====================================================================== #Generate the details HTML code for display in device details #or use with an weblink or something else. { my ($name,$noImage,$noText)=@_; #Checking if device exists ... return "
$name is not defined
" if(!$defs{$name}); #...and is of correct TYPE return "
$name is not of TYPE $modulename
" if(!($defs{$name}{'TYPE'} eq $modulename)); #Check for errors set by QRCode_update return '
'.ReadingsVal($name,'data','unknown error!').'
' if(InternalVal($name,'ERROR',undef)); my $imageurl=ReadingsVal($name,'qrcode_url',undef); return '
No image url available! Use set update to create it.
' if(!$imageurl); my $width='width="'.AttrVal($name,'qrDisplayWidth',$defWidth).'"'; my $height='height="'.AttrVal($name,'qrDisplayHeight',$defHeight).'"'; my $ret = ""; $ret .= ""; $ret .= ""; $ret .= ""; my $dtext=AttrVal($name,'qrDisplayText',undef); if ($dtext && !$noText && AttrVal($name,'qrData',undef)) { $dtext =~ s/\n/\/g; $ret .= ""; } $ret .= "
"; $ret .= ""; $ret .= "" if($imageurl && !$noImage); $ret .= "No image url available!
Use set update to create it" if(!$imageurl); $ret .= "
"; my $stylecolor=''; $stylecolor=' style="color:red"' if !AttrVal($name,'qrData',undef); $ret .= ''.AttrVal($name,'qrData',ReadingsVal($name,'data','attr qrData n/a')).'' if($imageurl && AttrVal($name,'qrDisplayData',undef) || !AttrVal($name,'qrData',undef)); $ret .= "
"; $ret .= $dtext; $ret .= "
"; return $ret; } #====================================================================== sub QRCode_FWDetail($@) { #====================================================================== #Display the QRCode in device details in FHEMWEB my ($FW_wname, $name, $room, $pageHash) = @_; QRCode_Log3 $name,4,"FWDetail.name=$name"; return QRCode_getHtml($name,AttrVal($name,'qrDisplayNoImage',undef),AttrVal($name,'qrDisplayNoText',undef)); } 1; #====================================================================== #====================================================================== # # HTML Documentation for help and commandref # #====================================================================== #====================================================================== =pod =item device =item summary create and display QRCode in FHEMWEB =item summary_DE QRCode erzeugen und in FHEMWEB darstellen =begin html

QRCode

    Devices of this module are used to generate an URL that will be used to generate and receive a QRCode from the service of TEC-IT
    The device will also display the generated QRCode in the device details. It can also provide the HTML-code used for display for other purposes (e.g. weblink devices)

    ATTENTION:The sevice provider does not allow more than 30 QRCode generations / minute without special permission

    See terms of sevice on TEC-IT homepage: http://qrcode.tec-it.com/de#TOS

    Define
      define <name> QRCode


    Set
      set <name> update
      Refreshes the QRCode-URL for Image generation.

    Attributes

      QRCode-URL relevant attributes

      The following attributes take influence on the QRCode generation.

      If one of those attributes is changed, per default an auto update of the QRCode-URL is performed.

    • qrData
      This attribute is used to set the data that will be encoded in the QRCode.
      If this attribute is not set an error message is generatet.

    • qrSize
      Defines the size of the generated QRCode image
      Possible values are small, medium (default), large.

    • qrResolutionDPI
      Defines the resolution for QRCode generaation
      Valid values are between 96 and 600 (Default is 300dpi)

    • qrColor
      Defines the foreground color of the genereted QRCode image
      This is a RGB color value in hex format (eg. FF0000 = red) Default is 000000 (black)

    • qrBackColor
      Defines the background color of the genereted QRCode image
      This is a RGB color value in hex format (eg. 0000FF = blue) Default is FFFFFF (white).

    • qrTransparent
      Defines that the background of the generated QRCode will be transparent
      Possible values are False (non-tranparent background) or True (transparent background)
      default is non-transparent.

    • qrQuietZone
      defines the size of a quiet zone around the QRCode in the image.
      This is a blank zone making it easier to scan the QRCode for some scanners.
      Default ist 0, if attribute is not set.

    • qrQuietUnit
      specifies the unit for qrQuietZone attribute
      Possible values are mm (default), in (=inch), mil (=mils), mod (=Module) or px (=Pixel).

    • qrCodepage
      Used Codepage for QRCode generation.
      Possible values are UTF8 (default), Cyrillic or Ansi

    • qrErrorCorrection
      Error correction used in generated QRCode image.
      Possible values are L (default), M,Q or H

    • Display relevant attributes

      The followin Attribute change the behaviour and display parameters for the detail view
      of QRCode devices in FHEMWEB. Therfore it changes the result of QRCode_getHtml function
      (see below.)

      In cas of an error, neither QRCode, nor qrDisplayText will be displayed. Instead
      an error message is displayed.

    • qrDisplayWidth
      display width of the QRCode image
      Default is 200

    • qrDisplayHeight
      Display height of the QRCode image
      Default is 200

    • qrDisplayData
      If set the contents or the reading data is displayed below the QRCode image
      Usually this is the contents of attribute qrData.

    • qrDisplaNoImage
      If set, the QRCode image will not be displayed

    • qrDisplaText
      user defined text to be displayed below QRCode image

    • qrDisplaNoText
      If this attribute is set, the text specified in qrDisplayText will not be displayed
      below QRCode image. So qrDisplayText doesn't have to be deleted.

    • qrNoAutoUpdate
      If set not auto update will be processed for QRCode relevant attributes.

    • readingFnAttributes


    Generated Readings


    • data
      This reading contains the data to be encoded by the QRCode
      Usually this is the contents of attribute qrData.
      In case of an error it contains the error message.

    • qrcode_url
      By set update generated URL, used to get the QRCode image


    • state
      The state of the device
      Initially this is defined or the timestamp of last set update, or auto-update



    Usefull Funktionen

    The module comes with a useful function to provide the HTML code used for display in detail view of the
    QRCode device in FHEMWEB for other purposes, e.g. weblink.


    • QRCode_getHtml($;$$)

      Returns the HTML code for the specified QRCode device

      Arguments:

      • QRCodeDevice
        Name of the QRCode device as a string.
      • noImage (Optional)
        The same as attribute qrDisplayNoImage
      • noText (Optional)
        The same as attribute qrDisplayNoText


      Example:

      QRCode_getHtml('MyQRCode',1,0)

      Generate HTML code of (QRCode-) device named MyQRCode with QRCode image but not with the
      user defined Text (qrDisplayText).
=end html =begin html_DE

QRCode

    Mit hilfe dieses Moduls, kann auf einfache Weise eine URL generiert werden, mit der vom Dienstleister TEC-IT ein QRCode abgerufen werden kann.
    Ein Device dieses Moduls kann außerdem den QRCode auch selbst direkt in FHEMWEB darstellen und auch anderen Devices (bspw. weblink) als HTML zur Verfügung stellen.

    HINWEIS: Es ist ohne schriftliche Genehmigung des Dienstaanbieters nur erlaubt, maximal 30 QRCode-Abrufe / Minute durchzuführen.

    Siehe dazu auch die Nutzungsbedingungen von TEC-IT: http://qrcode.tec-it.com/de#TOS

    Define
      define <name> QRCode


    Set
      set <name> update
      Führt eine aktualisierung der QRCode-Url durch.

    Attributes

      QRCode-URL-relevante Attribute

      Die folgenden Attribute sind für die Erzeugung der Abruf-URL relevant und haben somit
      direkten Einfluß auf die Erzeugung des QRCode-Images.

      Für diese Attribute wird bei Änderung, standardmäßig ein automatisches Udate der QRCode-URL
      durchgeführt. Dies kann durch setzen des Attirbutes qrNoAutoUpdate (s.w.u.) deaktiviert werden.

    • qrData
      Dieses Attribut legt die Daten fest, die im QRCode kodiert werden sollen.
      Ist dieses Attribut nicht gesetzt, wird beim update eine entsprechende Fehlermeldung erzeugt.

    • qrSize
      Dieses Attribut legt die Größe fest, in der das QRCode-Image erstellt werden soll.
      Mögliche Ausprägungen sind small, medium (default), large.

    • qrResolutionDPI
      Dieses Attribut legt die Auflösung fest, in der das QRCode-Image erstellt werden soll.
      Mögliche Werte liegen zwischen 96 und 600 (Default ist 300dpi)

    • qrColor
      Dieses Attribut legt die Vordergrundfarbe fest, in der das QRCode-Image erstellt werden soll.
      Der Wert ist ein RGB-Farbwert in Hexadezimaler schreibweise (Bspw. FF0000 für rot) Default ist 000000 (schwarz)

    • qrBackColor
      Dieses Attribut legt die Hintergrundfarbe fest, in der das QRCode-Image erstellt werden soll.
      Der Wert ist ein RGB-Farbwert in Hexadezimaler schreibweise (Bspw. 0000FF für blau) Default ist FFFFFF (weiß).

    • qrTransparent
      Dieses Attribut legt fest, ob der Hintergrund transparent sein soll.
      Mögliche Werte sind True für transparenten Hintergrund und False für nicht-transparenten Hintergrund (default)

    • qrQuietZone
      Über diesen Wert kann eine Ruhe-Zone, also ein Rand um den eigentlichen QRCode festgelegt werden.
      Dies ermöglicht ggf. ein erleichtertes Erfassen des QRCodes beim Scannen.
      Mögliche Werte sind positive numerische Werte. Default ist 0, wenn das Attribut nicht gesetzt ist.

    • qrQuietUnit
      Über diesen Wert kann die Maßeinheit für das Festlegen einer Ruhe-Zone eingestellt werden.
      Mögliche Ausptägungen sind mm (default), in (=inch), mil (=mils), mod (=Module) oder px (=Pixel).

    • qrCodepage
      Über diesen Wert kann die Zeichentabelle für die QRCode-Erzeugung festgelegt werden.
      Mögliche Werte sind UTF8 (default), Cyrillic oder Ansi

    • qrErrorCorrection
      Über diesen Wert kann Fehlerkorrektur für die QRCode-Erzeugung festgelegt werden.
      Mögliche Werte sind L (default), M,Q oder H

    • darstellungsrelevante Attribute

      Die folgenden Attribute haben nur Einfluß auf das Verhalten und die Darstellung in FHEMWEB
      in der Deatailansicht des QRCode-Devices, bzw. beim Abruf der HTML-Daten mittels QRCode_getHtml (s.u.)

      Im Fehlerfall wird weder der QRCode, noch qrDisplayText dargestellt, sondern eine entsprechend
      Fehlermeldung stattdessen eingeblendet.

    • qrDisplayWidth
      Breite des Images bei der Darstellung in FHEMWEB in der Detailübersicht
      Default ist 200

    • qrDisplayHeight
      Höhe des Images bei der Darstellung in FHEMWEB in der Detailübersicht
      Default ist 200

    • qrDisplayData
      Wenn dieses Attribut gesetzt ist, wird unterhalb des QRCodes der Datenteil als einfacher
      Text dargestellt.

    • qrDisplaNoImage
      Wenn dieses Attribut gesetzt ist, der QRCode nicht in der Detailansicht dargestellt.

    • qrDisplaText
      Hier kann ein beliebiger Text eingetragen werden, der unterhalb des QRCodes eingeblendet werden soll.

    • qrDisplaNoText
      Ist dieses Attribut gesetzt, so wird der, im Attribut qrDisplayText eingetragene Text nicht eingeblendet, auch ohne das Attribut qrDisplayText zu löschen.

    • qrNoAutoUpdate
      Ist dieses Attribut gesetzt, so wird bei Änderung eines für die QRCode-Erzeugung relevanten
      Attributs kein automatisches Update der QRCode-URL durchgeführt.

    • readingFnAttributes


    Erzeugte Readings


    • data
      Dieses Reading enthält die vom QRCode zu kodierenden Daten.
      Das ist im Normalfall der Inhalt aus dem Attribut qrData.
      Im Fehlerfall steht hier stattdessen der entsprechende Fehlertext.

    • qrcode_url
      Dies ist die durch set update erzeugte URL, die für den Abruf des QRCode-Image
      verwendet wird.

    • state
      Status des QRCode-Device.
      Das ist entweder defined, oder der Zeitpunkt des letzten set update, bzw. auto-update



    Enthaltene Funktionen

    Es gibt im Modul eine Funktion, die auch für andere Anwendungsfälle einsetzbar ist, wie bspw. in einem weblink


    • QRCode_getHtml($;$$)

      Die Funktion gibt den HTML-Code zurück, wie er auch für die Darstellung im QRCode-Device in der
      Detail-Ansicht verwendet wird.

      Parameter:

      • QRCodeDevice
        Hier ist der Name des QRCode-Devices anzugeben, dessen HTML-Code abgerufen werden soll.
      • noImage (Optional)
        Entspricht dem Attribut qrDisplayNoImage
        Wenn dieser Parameter angezeigt wird, wird also keine Referenz auf QRCode-Image im HTML-Code
        erzeugt.
      • noText (Optional)
        Entspricht dem Attribut qrDisplayNoText
        Wenn dieser Parameter angezeigt wird, wird also Benutzerdefinierter Text unterhalb des QRCode
        im HTML-Code erzeugt.


      Beispiel:

      QRCode_getHtml('MyQRCode',1,0)

      Damit wird der HTML-Code für das (QRCode-)Device MyQRCode abgerufen, das nur das Image enthält,
      aber nicht den Benutzerdefinierten text.
=end html_DE =cut