From 33fe5028eb1f57ea09da10a9c4cf6c65e69e09d3 Mon Sep 17 00:00:00 2001 From: eki <> Date: Mon, 21 Dec 2020 08:11:45 +0000 Subject: [PATCH] 89_ESPEInk: Several small modifications to avoid freezes (Forum https://forum.fhem.de/index.php/topic,104171.msg1050446.html#msg1050446) git-svn-id: https://svn.fhem.de/fhem/trunk@23397 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/89_ESPEInk.pm | 529 ++++++++++++++++++++++++++++++++-------- 1 file changed, 426 insertions(+), 103 deletions(-) diff --git a/fhem/FHEM/89_ESPEInk.pm b/fhem/FHEM/89_ESPEInk.pm index e15c9984c..faf11e88d 100644 --- a/fhem/FHEM/89_ESPEInk.pm +++ b/fhem/FHEM/89_ESPEInk.pm @@ -1,5 +1,10 @@ # $Id$ +# Änderungen Viegener - 2020-05-04 +# Umstellung verzögerte berechnung der Pixel erst beim upload +# blocktext (ESPEInk_FormatBlockText) korrigiert für Behandlung von \\n +# text height ($th) is potentially wrong if text is wrapped to multiple lines so text height shoul dbe calced from one char only (addobjects) + package main; use strict; use warnings; @@ -45,7 +50,8 @@ my %ESPEInk_devices = ( # "7.8inch_e-Paper_HAT" => {width => 200, height => 200, pindex => 10, id => 23}, # "6inch_e-Paper_HAT" => {width => 200, height => 200, pindex => 10, id => 22}, # "2.9inch_e-Paper_HAT_(D)" => {width => 200, height => 200, pindex => 10, id => 21}, - "7.5inch_e-Paper_HAT_V2_(B)" => {width => 800, height => 480, pindex => 5, id => 23}, + "7.5inch_e-Paper_HAT_(B)_HD" => {width => 880, height => 528, pindex => 1, id => 24}, + "7.5inch_e-Paper_HAT_V2_(B)" => {width => 800, height => 480, pindex => 1, id => 23}, "7.5inch_e-Paper_HAT_V2" => {width => 800, height => 480, pindex => 0, id => 22}, "7.5inch_e-Paper_HAT_(C)" => {width => 640, height => 384, pindex => 5, id => 21}, "7.5inch_e-Paper_HAT_(B)" => {width => 640, height => 384, pindex => 1, id => 20}, @@ -86,6 +92,7 @@ my %ESPEInk_sets = ( "upload" => "noArg", # perform upload of converted picture to EInk Display via WLAN "addtext" => "textFieldNL", # add text to picture at given position (see set for details) "addicon" => "textFieldNL", # add icon to picture at given position (see set for details) + "addsymbol" => "textFieldNL", # add symbol (line, rectangle, ellipse) to picture at given position (see set for details) "iconreading" => "textFieldNL", # add text to picture at given position (see set for details) "textreading" => "textFieldNL" # add text to picture at given position (see set for details) ); @@ -260,12 +267,13 @@ sub ESPEInk_Set($@) { return "Unknown argument $opt, choose one of " . join(" ", map{ "$_:".$ESPEInk_sets{$_}} keys %ESPEInk_sets); } - if ($opt eq 'addtext' || $opt eq 'textreading' || $opt eq 'addicon' || $opt eq 'iconreading') { + if ($opt eq 'addtext' || $opt eq 'textreading' || $opt eq 'addicon' || $opt eq 'iconreading' || $opt eq 'addsymbol') { my ($text, $x, $y, $size, $angle, $color, $font, $linegap, $blockwidth) = split("#",$value); return "No text defined, use format: 'addtext text#x#y#size#angle#color#font'" if (!$text && ($opt eq 'addtext')); return "No reading defined, use format: 'textreading device:reading#x#y#size#angle#color#font'" if (!$text && ($opt eq 'textreading')); return "No icon defined, use format: 'addicon icon#x#y#size#angle#color'" if (!$text && ($opt eq 'addicon')); return "No reading defined, use format: 'iconreading device:reading#x#y#size#angle#color'" if (!$text && ($opt eq 'iconreading')); + return "No symbol defined, use format: 'addsymbol symbol#x#y#size#angle#color#width#height#arc'" if (!$text && ($opt eq 'addsymbol')); my($texts,$eval) = split("{",$text); my ($device,$reading) = split(':',$texts); $reading = "state" if (!$reading); @@ -288,8 +296,14 @@ sub ESPEInk_Set($@) { if ($opt eq 'iconreading' || $opt eq 'addicon') { readingsBulkUpdate($hash,$itext."-icon",$text) if ($opt eq 'iconreading'); readingsBulkUpdate($hash,$itext."-isIcon",1); - } elsif ($opt eq 'textreading' || $opt eq 'addtext') { - readingsBulkUpdate($hash,$itext."-isIcon",0) + readingsBulkUpdate($hash,$itext."-isSymbol",0); + } elsif ($opt eq 'textreading' || $opt eq 'addtext' || $opt eq 'addsymbol') { + readingsBulkUpdate($hash,$itext."-isIcon",0); + if ($opt eq 'addsymbol') { + readingsBulkUpdate($hash,$itext."-isSymbol",1); + } else { + readingsBulkUpdate($hash,$itext."-isSymbol",0); + } } $x = 0 if (!$x || (($x !~ '-?\d+')&&($x !~ '(left|mid|right)'))); @@ -299,21 +313,25 @@ sub ESPEInk_Set($@) { $color = "000000" if (!$color || !ESPEInk_CheckColorString($color)); - $font = "medium" if (!ESPEInk_CheckFontString($font)); + $font = "medium" if (!ESPEInk_CheckFontString($font) and ($opt ne 'addsymbol')); $linegap = 0 if (!$linegap || ($linegap !~ '\d+')); $blockwidth = 0 if (!$blockwidth || ($blockwidth !~ '\d+')); readingsBulkUpdate($hash,$itext."-def",$opt."#".$value); readingsBulkUpdate($hash,$itext."-text",$text) if ($opt eq 'addtext'); + readingsBulkUpdate($hash,$itext."-symbol",$text) if ($opt eq 'addsymbol'); readingsBulkUpdate($hash,$itext."-icon",$text) if ($opt eq 'addicon'); readingsBulkUpdate($hash,$itext."-x",$x); readingsBulkUpdate($hash,$itext."-y",$y); readingsBulkUpdate($hash,$itext."-size",$size); readingsBulkUpdate($hash,$itext."-angle",$angle); readingsBulkUpdate($hash,$itext."-color",$color); - readingsBulkUpdate($hash,$itext."-font",$font) if ($opt eq 'addtext' || $opt eq 'textreading'); - readingsBulkUpdate($hash,$itext."-linegap",$linegap); - readingsBulkUpdate($hash,$itext."-blockwidth",$blockwidth); + readingsBulkUpdate($hash,$itext."-font",$font) if (($opt eq 'addtext' || $opt eq 'textreading') and $opt ne 'addsymbol'); + readingsBulkUpdate($hash,$itext."-linegap",$linegap) if ($opt ne 'addsymbol');; + readingsBulkUpdate($hash,$itext."-blockwidth",$blockwidth) if ($opt ne 'addsymbol');; + readingsBulkUpdate($hash,$itext."-width",$font) if ($opt eq 'addsymbol'); # parameter number 7 is width instead of font for symbols + readingsBulkUpdate($hash,$itext."-height",$linegap) if ($opt eq 'addsymbol'); # parameter number 8 is height instead of linegap for symbols + readingsBulkUpdate($hash,$itext."-arc",$blockwidth) if ($opt eq 'addsymbol'); # parameter number 9 is height instead of linegap for symbols ESPEInk_AddTextAttributes($name,$itext); @@ -455,9 +473,10 @@ sub ESPEInk_Attr(@) { } elsif($attr_name =~ '.*-trigger') { my ($ind,$cmd) = split("-",$attr_name); my ($type,$trigger) = split("#",ReadingsVal($name,$ind."-def","")); - readingsDelete($hash,"$ind-trigger") if ($type eq 'addtext' || $type eq 'addicon'); + readingsDelete($hash,"$ind-trigger") if ($type eq 'addtext' || $type eq 'addicon' || $type eq 'addsymbol'); readingsSingleUpdate( $hash, "$ind-icon", $trigger, 1 ) if ($trigger && ReadingsVal($name,"$ind-isIcon",0)); - readingsSingleUpdate( $hash, "$ind-text", $trigger, 1 ) if ($trigger && !ReadingsVal($name,"$ind-isIcon",0)); + readingsSingleUpdate( $hash, "$ind-text", $trigger, 1 ) if ($trigger && !ReadingsVal($name,"$ind-isIcon",0) && $type eq 'addtext'); + readingsSingleUpdate( $hash, "$ind-sybmol", $trigger, 1 ) if ($trigger && !ReadingsVal($name,"$ind-isIcon",0) && $type eq 'addsymbol'); Log3 $hash, 5, "$name: deleted attribute $attr_name for triggering reset to initial definition"; } elsif($attr_name =~ '^\d+-.*') { my ($ind,$cmd) = split("-",$attr_name); @@ -467,6 +486,8 @@ sub ESPEInk_Attr(@) { if ($cmd =~ "text") { readingsSingleUpdate( $hash, "$ind-text", $text, 1 ) if ($text); + } elsif ($cmd =~ "sybmol") { + readingsSingleUpdate( $hash, "$ind-symbol", $text, 1 ) if ($text); } elsif ($cmd =~ "icon") { readingsSingleUpdate( $hash, "$ind-icon", $text, 1 ) if ($text); } elsif ($cmd =~ "x") { @@ -493,6 +514,15 @@ sub ESPEInk_Attr(@) { } elsif ($cmd =~ "blockwidth" && !ReadingsVal($name,"$ind-isIcon",0)) { readingsSingleUpdate( $hash, "$ind-blockwidth", $blockwidth, 1 ) if ($blockwidth); readingsSingleUpdate( $hash, "$ind-blockwidth", 0, 1 ) if (!$blockwidth); + } elsif ($cmd =~ "width" && !ReadingsVal($name,"$ind-isIcon",0)) { + readingsSingleUpdate( $hash, "$ind-width", $font, 1 ) if ($font); + readingsSingleUpdate( $hash, "$ind-width", 0, 1 ) if (!$font); + } elsif ($cmd =~ "height" && !ReadingsVal($name,"$ind-isIcon",0)) { + readingsSingleUpdate( $hash, "$ind-height", $linegap, 1 ) if ($linegap); + readingsSingleUpdate( $hash, "$ind-height", 0, 1 ) if (!$linegap); + } elsif ($cmd =~ "arc" && !ReadingsVal($name,"$ind-isIcon",0)) { + readingsSingleUpdate( $hash, "$ind-arc", $blockwidth, 1 ) if ($blockwidth); + readingsSingleUpdate( $hash, "$ind-arc", 0, 1 ) if (!$blockwidth); } Log3 $hash, 5, "$name: deleted attribute $attr_name reset to default if in initial definition (set ".$name." ".$type.")"; @@ -807,7 +837,8 @@ sub ESPEInk_CheckIconString($) { # Add all new attributes (text, position, size, angle, color, font) for a text object sub ESPEInk_AddTextAttributes($$) { my ($name,$itext) = @_; - addToDevAttrList($name, "$itext-text") if (!ReadingsVal($name,"$itext-isIcon",0)); + addToDevAttrList($name, "$itext-text") if (!ReadingsVal($name,"$itext-isIcon",0) and !ReadingsVal($name,"$itext-isSymbol",0)); + addToDevAttrList($name, "$itext-symbol") if (!ReadingsVal($name,"$itext-isIcon",0) and ReadingsVal($name,"$itext-isSymbol",0)); addToDevAttrList($name, "$itext-icon") if (ReadingsVal($name,"$itext-isIcon",0)); addToDevAttrList($name, "$itext-trigger"); addToDevAttrList($name, "$itext-x"); @@ -815,9 +846,12 @@ sub ESPEInk_AddTextAttributes($$) { addToDevAttrList($name, "$itext-size"); addToDevAttrList($name, "$itext-angle"); addToDevAttrList($name, "$itext-color:colorpicker,RGB"); - addToDevAttrList($name, "$itext-font") if (!ReadingsVal($name,"$itext-isIcon",0)); - addToDevAttrList($name, "$itext-linegap") if (!ReadingsVal($name,"$itext-isIcon",0)); - addToDevAttrList($name, "$itext-blockwidth") if (!ReadingsVal($name,"$itext-isIcon",0)); + addToDevAttrList($name, "$itext-font") if (!ReadingsVal($name,"$itext-isIcon",0) && !ReadingsVal($name,"$itext-isSymbol",0)); + addToDevAttrList($name, "$itext-linegap") if (!ReadingsVal($name,"$itext-isIcon",0) && !ReadingsVal($name,"$itext-isSymbol",0)); + addToDevAttrList($name, "$itext-blockwidth") if (!ReadingsVal($name,"$itext-isIcon",0) && !ReadingsVal($name,"$itext-isSymbol",0)); + addToDevAttrList($name, "$itext-width") if (!ReadingsVal($name,"$itext-isIcon",0) && ReadingsVal($name,"$itext-isSymbol",0)); + addToDevAttrList($name, "$itext-height") if (!ReadingsVal($name,"$itext-isIcon",0) && ReadingsVal($name,"$itext-isSymbol",0)); + addToDevAttrList($name, "$itext-arc") if (!ReadingsVal($name,"$itext-isIcon",0) && ReadingsVal($name,"$itext-isSymbol",0)); } #--------------------------------------------------------------------------------------------------- @@ -883,9 +917,11 @@ sub ESPEInk_RemoveTextReadings($$){ if ($itext <= $deftexts) { my $isicon = ReadingsVal($name,"$itext-isIcon",0); + my $issymbol = ReadingsVal($name,"$itext-isSymbol",0); readingsDelete($hash,$itext."-def"); readingsDelete($hash,$itext."-text"); + readingsDelete($hash,$itext."-symbol"); readingsDelete($hash,$itext."-icon"); readingsDelete($hash,$itext."-trigger"); readingsDelete($hash,$itext."-x"); @@ -897,13 +933,19 @@ sub ESPEInk_RemoveTextReadings($$){ readingsDelete($hash,$itext."-linegap"); readingsDelete($hash,$itext."-blockwidth"); readingsDelete($hash,$itext."-isIcon"); + readingsDelete($hash,$itext."-isSymbol"); + readingsDelete($hash,$itext."-width"); + readingsDelete($hash,$itext."-height"); + readingsDelete($hash,$itext."-arc"); readingsBeginUpdate($hash); for (my $i=$itext; $i<$deftexts; $i++) { $isicon = ReadingsVal($name,"$i-isIcon",0) if ($i > $itext); + $issymbol = ReadingsVal($name,"$i-isSymbol",0) if ($i > $itext); readingsBulkUpdate($hash,$i."-def",ReadingsVal($name,($i+1)."-def","")); - readingsBulkUpdate($hash,$i."-text",ReadingsVal($name,($i+1)."-text","")) if (!ReadingsVal($name,($i+1)."-isIcon",0)); + readingsBulkUpdate($hash,$i."-text",ReadingsVal($name,($i+1)."-text","")) if (!ReadingsVal($name,($i+1)."-isIcon",0) and !ReadingsVal($name,($i+1)."-isSymbol",0)); + readingsBulkUpdate($hash,$i."-sybmol",ReadingsVal($name,($i+1)."-symbol","")) if (!ReadingsVal($name,($i+1)."-isIcon",0) and ReadingsVal($name,($i+1)."-isSymbol",0)); readingsBulkUpdate($hash,$i."-icon",ReadingsVal($name,($i+1)."-icon","")) if (ReadingsVal($name,($i+1)."-isIcon",0)); readingsBulkUpdate($hash,$i."-trigger",ReadingsVal($name,($i+1)."-trigger","")) if (ReadingsVal($name,($i+1)."-trigger",undef)); readingsBulkUpdate($hash,$i."-x",ReadingsVal($name,($i+1)."-x","")); @@ -914,13 +956,25 @@ sub ESPEInk_RemoveTextReadings($$){ readingsBulkUpdate($hash,$i."-font",ReadingsVal($name,($i+1)."-font","")) if (ReadingsVal($name,($i+1)."-font",undef)); readingsBulkUpdate($hash,$i."-linegap",ReadingsVal($name,($i+1)."-linegap","")) if (ReadingsVal($name,($i+1)."-linegap",undef)); readingsBulkUpdate($hash,$i."-blockwidth",ReadingsVal($name,($i+1)."-blockwidth","")) if (ReadingsVal($name,($i+1)."-blockwidth",undef)); + readingsBulkUpdate($hash,$i."-width",ReadingsVal($name,($i+1)."-width","")) if (ReadingsVal($name,($i+1)."-width",undef)); + readingsBulkUpdate($hash,$i."-height",ReadingsVal($name,($i+1)."-height","")) if (ReadingsVal($name,($i+1)."-height",undef)); + readingsBulkUpdate($hash,$i."-arc",ReadingsVal($name,($i+1)."-arc","")) if (ReadingsVal($name,($i+1)."-arc",undef)); - addToDevAttrList($name, "$i-font") if ($isicon && !ReadingsVal($name,($i+1)."-isIcon",0)); - delFromDevAttrList($name, "$i-font") if (ReadingsVal($name,($i+1)."-isIcon",0)); + addToDevAttrList($name, "$i-font") if ($isicon && !ReadingsVal($name,($i+1)."-isIcon",0) && !ReadingsVal($name,($i+1)."-isSymbol",0)); + delFromDevAttrList($name, "$i-font") if (ReadingsVal($name,($i+1)."-isIcon",0) && !ReadingsVal($name,($i+1)."-isSymbol",0)); + + addToDevAttrList($name, "$i-width") if ($isicon && !ReadingsVal($name,($i+1)."-isIcon",0) && ReadingsVal($name,($i+1)."-isSymbol",0)); + delFromDevAttrList($name, "$i-width") if (ReadingsVal($name,($i+1)."-isIcon",0) && ReadingsVal($name,($i+1)."-isSymbol",0)); + addToDevAttrList($name, "$i-height") if ($isicon && !ReadingsVal($name,($i+1)."-isIcon",0) && ReadingsVal($name,($i+1)."-isSymbol",0)); + delFromDevAttrList($name, "$i-height") if (ReadingsVal($name,($i+1)."-isIcon",0) && ReadingsVal($name,($i+1)."-isSymbol",0)); + addToDevAttrList($name, "$i-arc") if ($isicon && !ReadingsVal($name,($i+1)."-isIcon",0) && ReadingsVal($name,($i+1)."-isSymbol",0)); + delFromDevAttrList($name, "$i-arc") if (ReadingsVal($name,($i+1)."-isIcon",0) && ReadingsVal($name,($i+1)."-isSymbol",0)); readingsBulkUpdate($hash,$i."-isIcon",ReadingsVal($name,($i+1)."-isIcon","")); + readingsBulkUpdate($hash,$i."-isSymbol",ReadingsVal($name,($i+1)."-isSymbol","")); if (defined(AttrVal($name,($i+1).'-text',undef))) {fhem("attr $name $i-text ".AttrVal($name,($i+1)."-text",""))} else {delFromDevAttrList($name, "$i-text")}; + if (defined(AttrVal($name,($i+1).'-sybmol',undef))) {fhem("attr $name $i-sybmol ".AttrVal($name,($i+1)."-sybmol",""))} else {delFromDevAttrList($name, "$i-sybmol")}; if (defined(AttrVal($name,($i+1).'-icon',undef))) {fhem("attr $name $i-icon ".AttrVal($name,($i+1)."-icon",""))} else {delFromDevAttrList($name, "$i-icon")}; if (defined(AttrVal($name,($i+1).'-trigger',undef))) {fhem("attr $name $i-trigger ".AttrVal($name,($i+1)."-trigger",""))} else {delFromDevAttrList($name, "$i-trigger")}; if (defined(AttrVal($name,($i+1).'-x',undef))) {fhem("attr $name $i-x ".AttrVal($name,($i+1)."-x",0))} else {delFromDevAttrList($name, "$i-x")}; @@ -931,6 +985,9 @@ sub ESPEInk_RemoveTextReadings($$){ if (defined(AttrVal($name,($i+1).'-font',undef))) {fhem("attr $name $i-font ".AttrVal($name,($i+1)."-font","medium"))} else {delFromDevAttrList($name, "$i-font")}; if (defined(AttrVal($name,($i+1).'-linegap',undef))) {fhem("attr $name $i-linegap ".AttrVal($name,($i+1)."-linegap",0))} else {delFromDevAttrList($name, "$i-linegap")}; if (defined(AttrVal($name,($i+1).'-blockwidth',undef))) {fhem("attr $name $i-blockwidth ".AttrVal($name,($i+1)."-blockwidth",0))} else {delFromDevAttrList($name, "$i-blockwidth")}; + if (defined(AttrVal($name,($i+1).'-width',undef))) {fhem("attr $name $i-width ".AttrVal($name,($i+1)."-width",0))} else {delFromDevAttrList($name, "$i-width")}; + if (defined(AttrVal($name,($i+1).'-height',undef))) {fhem("attr $name $i-height ".AttrVal($name,($i+1)."-height",0))} else {delFromDevAttrList($name, "$i-height")}; + if (defined(AttrVal($name,($i+1).'-arc',undef))) {fhem("attr $name $i-arc ".AttrVal($name,($i+1)."-arc",0))} else {delFromDevAttrList($name, "$i-arc")}; } readingsBulkUpdate($hash,"deftexts",($deftexts-1)); @@ -938,6 +995,7 @@ sub ESPEInk_RemoveTextReadings($$){ readingsDelete($hash,"$deftexts-def"); readingsDelete($hash,"$deftexts-text"); + readingsDelete($hash,"$deftexts-symbol"); readingsDelete($hash,"$deftexts-icon"); readingsDelete($hash,"$deftexts-trigger"); readingsDelete($hash,"$deftexts-x"); @@ -949,8 +1007,13 @@ sub ESPEInk_RemoveTextReadings($$){ readingsDelete($hash,"$deftexts-linegap"); readingsDelete($hash,"$deftexts-blockwidth"); readingsDelete($hash,"$deftexts-isIcon"); + readingsDelete($hash,"$deftexts-isSymbol"); + readingsDelete($hash,"$deftexts-width"); + readingsDelete($hash,"$deftexts-height"); + readingsDelete($hash,"$deftexts-arc"); delFromDevAttrList($name, "$deftexts-text"); + delFromDevAttrList($name, "$deftexts-symbol"); delFromDevAttrList($name, "$deftexts-icon"); delFromDevAttrList($name, "$deftexts-trigger"); delFromDevAttrList($name, "$deftexts-x"); @@ -961,8 +1024,11 @@ sub ESPEInk_RemoveTextReadings($$){ delFromDevAttrList($name, "$deftexts-font"); delFromDevAttrList($name, "$deftexts-linegap"); delFromDevAttrList($name, "$deftexts-blockwidth"); + delFromDevAttrList($name, "$deftexts-width"); + delFromDevAttrList($name, "$deftexts-height"); + delFromDevAttrList($name, "$deftexts-arc"); - Log3 $hash, 5, "$name: Removed readings for ".(ReadingsVal($name,"$deftexts-isIcon",0)?"icon":"text"); + Log3 $hash, 5, "$name: Removed readings for ".(ReadingsVal($name,"$deftexts-isIcon",0)?"icon":(ReadingsVal($name,"$deftexts-isSymbol",0)?"symbol":"text")); } @@ -1084,50 +1150,51 @@ sub ESPEInk_FormatBlockText($$$$$$$) { my $text = $txt; if ($blockwidth) { # insert additional \n if width of text reaches maximum width + my @words; my $xoffset = 0; my ($wspc, $ww, $wh); my $newline = 1; ($wspc, $wh) = ESPEInk_GetStringPixelWidth($name," ",$fnt,$angle,$size); + + $text =~ s/\n/\\n/gm; +# Debug "text :$text:"; + + @words = split(/[ ]/,$text); $text = ""; foreach my $word (@words) { + my $ww2; + my $wd; + while ( $word =~ /(.*)\\n(.*)/ ) { + $wd = $1; + $word = $2; + my ($ww2, $wh) = ESPEInk_GetStringPixelWidth($name,$wd,$fnt,$angle,$size); +# Debug " offset :$xoffset: width :$ww2: spacew :$wspc: text :$wd: "; + if (($xoffset+$ww2) <= $blockwidth) { + $wd = (($newline)?"":" ") . $wd; + } else { + $wd = "\\n" . $wd; + } + $xoffset = 0; + $newline = 1; + $text = $text . $wd . "\\n"; + } + ($ww, $wh) = ESPEInk_GetStringPixelWidth($name,$word,$fnt,$angle,$size); +# Debug " offset :$xoffset: width :$ww: spacew :$wspc: text :$word: "; Log3 $defs{$name}, 5, "--->> Width (outer) of $word (lengt ".length($word).") is: $ww, Width of Space is: $wspc, Text offset is: $xoffset"; - if ($word =~ /.*\\n.*/) { - my $ww2; - foreach my $wd (split(/[\\n]/,$word)) { - ($ww2, $wh) = ESPEInk_GetStringPixelWidth($name,$wd,$fnt,$angle,$size); - Log3 $defs{$name}, 5, "--->> Width (inner) of $wd (lengt ".length($wd).") is: $ww2, Width of Space is: $wspc, Text offset is: $xoffset"; - if (length($wd) > 0) { - if (($xoffset+$ww2) <= $blockwidth) { - $wd = (($xoffset==0)?"":" ") . $wd; - $xoffset = $xoffset + $ww2 + $wspc; - $newline = 0; - } else { - $wd = "\\n" . $wd . " " if (!$newline); - $wd = $wd . "\\n" if ($newline); - $xoffset = $ww2 + $wspc; - $newline = 1; - } - } - $xoffset = 0 if (length($wd) == 0); - $wd = $wd . "\\n" if (length($wd) == 0); - $text = $text . $wd; - } - } else { - if (($xoffset+$ww) <= $blockwidth) { - $word = (($newline)?"":" ") . $word; - $xoffset = $xoffset + $ww + $wspc; - $newline = 0; - } else { - $word = "\\n" . $word . " "; - # $word = $word . "\\n" if ($newline); - $xoffset = $ww + $wspc; - $newline = 1; - } - $text = $text . $word; - } + if (($xoffset+$ww) <= $blockwidth) { + $word = (($newline)?"":" ") . $word; + $xoffset = $xoffset + $ww + $wspc; + $newline = 0; + } else { + $word = "\\n" . $word . " "; + # $word = $word . "\\n" if ($newline); + $xoffset = $ww + $wspc; + $newline = 1; + } + $text = $text . $word; } Log3 $defs{$name}, 5, "--->> Text is: $text"; } @@ -1173,19 +1240,19 @@ sub ESPEInk_AddObjects($$) { $linegap = int($linegap) if ($linegap); $blockwidth = int($blockwidth) if ($blockwidth); + next if (!defined $type); + next if (!defined $text); + $x = 0 if (!$x || (($x !~ '-?\d+')&&($x !~ '(left|mid|right)'))); $y = 0 if (!$y || (($y !~ '-?\d+')&&($y !~ '(top|mid|bottom)'))); $size = 10 if (!$size || ($size !~ '-?\d+')); $ang = 0 if (!$ang || ($ang !~ '-?\d+')); $docolor = $col?1:0; $col = "000000" if (!$col || !ESPEInk_CheckColorString($col)); - $fnt = "medium" if (!ESPEInk_CheckFontString($fnt)); + $fnt = "medium" if (!ESPEInk_CheckFontString($fnt) && $type ne "addsymbol"); $angle = $ang/180*(4*atan2(1,1)); $color = $col; - next if (!defined $type); - next if (!defined $text); - if ($type eq "iconreading" || $type eq "textreading") { my $eval=0; ($text,$eval) = split("{",$text); @@ -1284,15 +1351,20 @@ sub ESPEInk_AddObjects($$) { ($x,$y) = ESPEInk_CorrectXY($name,$type,"$dw#$dh",$fnt,$ang,$size,$iw,$ih,$x,$y); $image->copyResized($icon_img_rot,$x,$y,0,0,$dw,$dh,$srw,$srh); } - } else { + } elsif ($type ne "addsymbol") { $font = gdGiantFont if ($fnt eq "giant"); $font = gdLargeFont if ($fnt eq "large"); $font = gdMediumBoldFont if ($fnt eq "medium"); $font = gdSmallFont if ($fnt eq "small"); my ($dw,$dh) = $image->getBounds; my $ly = $y; - my ($tw, $th) = ESPEInk_GetStringPixelWidth($name,$text,$fnt,$ang,$size); + + # Do not use full text here, since only height is relevant here and this can be calced from one char + # + my ($tw, $th) = ESPEInk_GetStringPixelWidth($name,"A",$fnt,$ang,$size); +# Debug "line height : $th :"; $th += $linegap if ($linegap); +# Debug "line height after : $th :"; $text = ESPEInk_FormatBlockText($name,$text,$fnt,$ang,$size,$blockwidth,$th); @@ -1310,6 +1382,49 @@ sub ESPEInk_AddObjects($$) { } $ly += $th; } + } else { + my ($sym,$s1,$s2) = ("","",""); + ($sym,$s1,$s2) = split("-",$text); + my $width = $fnt; + my $height = $linegap; + $image->setStyle($color); + if ($sym eq "line") { + my $angle = atan2($height,$width); + for (my $i=0;$i<$size;$i++) { + $image->setStyle($color,$color,$color,$color,gdTransparent,gdTransparent,gdTransparent,gdTransparent) if ($s1 eq "dashed" or $s2 eq "dashed"); + $image->setStyle($color,$color,gdTransparent,gdTransparent) if ($s1 eq "dotted" or $s2 eq "dotted"); + $image->line($x,$y,$x+$width,$y+$height,gdStyled); + $x+=sin($angle); + $y-=cos($angle); + } + } elsif ($sym eq "rectangle") { + $image->setThickness($size); + $image->setStyle($color,$color,$color,$color,gdTransparent,gdTransparent,gdTransparent,gdTransparent) if ($s1 eq "dashed" or $s2 eq "dashed"); + $image->setStyle($color,$color,gdTransparent,gdTransparent) if ($s1 eq "dotted" or $s2 eq "dotted"); + if ($s1 eq "filled" or $s2 eq "filled") { + $image->filledRectangle($x,$y,$x+$width,$y+$height,gdStyled); + } else { + $image->rectangle($x,$y,$x+$width,$y+$height,gdStyled); + } + } elsif ($sym eq "ellipse") { + $image->setThickness($size); + $image->setStyle($color,$color,$color,$color,gdTransparent,gdTransparent,gdTransparent,gdTransparent) if ($s1 eq "dashed" or $s2 eq "dashed"); + $image->setStyle($color,$color,gdTransparent,gdTransparent) if ($s1 eq "dotted" or $s2 eq "dotted"); + if ($s1 eq "filled" or $s2 eq "filled") { + $image->filledEllipse($x+$width/2,$y+$height/2,$width,$height,gdStyled); + } else { + $image->ellipse($x+$width/2,$y+$height/2,$width,$height,gdStyled); + } + } elsif ($sym eq "arc") { + $image->setThickness($size); + $image->setStyle($color,$color,$color,$color,gdTransparent,gdTransparent,gdTransparent,gdTransparent) if ($s1 eq "dashed" or $s2 eq "dashed"); + $image->setStyle($color,$color,gdTransparent,gdTransparent) if ($s1 eq "dotted" or $s2 eq "dotted"); + if ($s1 eq "filled" or $s2 eq "filled") { + $image->filledArc($x+$width/2,$y+$height/2,$width,$height,$ang,$ang+$blockwidth,gdStyled,gdEdged); + } else { + $image->arc($x+$width/2,$y+$height/2,$width,$height,$ang,$ang+$blockwidth,gdStyled); + } + } } } } @@ -1397,7 +1512,7 @@ sub ESPEInk_AddObjects($$) { my ($x,$y) = ESPEInk_CorrectXY($name,"icon","$dw#$dh",ReadingsVal($name,"$itext-font",""),ReadingsVal($name,"$itext-angle",""),ReadingsVal($name,"$itext-size",""),$iw,$ih,ReadingsVal($name,"$itext-x",0),ReadingsVal($name,"$itext-y",0)); $image->copyResized($icon_img_rot,$x,$y,0,0,$dw,$dh,$srw,$srh); } - } else { + } elsif (!ReadingsVal($name,"$itext-isSymbol",0)) { $font = undef; $font = gdGiantFont if (ReadingsVal($name,"$itext-font","") eq "giant"); $font = gdLargeFont if (ReadingsVal($name,"$itext-font","") eq "large"); @@ -1405,7 +1520,9 @@ sub ESPEInk_AddObjects($$) { $font = gdSmallFont if (ReadingsVal($name,"$itext-font","") eq "small"); my ($dw,$dh) = $image->getBounds; my $ly = ReadingsVal($name,"$itext-y",0); - my ($tw, $th) = ESPEInk_GetStringPixelWidth($name,ReadingsVal($name,"$itext-text",""),ReadingsVal($name,"$itext-font","small"),ReadingsVal($name,"$itext-angle",0),ReadingsVal($name,"$itext-size",10)); + # Do not use full text here, since only height is relevant here and this can be calced from one char + # + my ($tw, $th) = ESPEInk_GetStringPixelWidth($name,"A",ReadingsVal($name,"$itext-font","small"),ReadingsVal($name,"$itext-angle",0),ReadingsVal($name,"$itext-size",10)); $th += int(ReadingsVal($name,"$itext-linegap",0)); my $text = ESPEInk_FormatBlockText($name,ReadingsVal($name,"$itext-text",""),ReadingsVal($name,"$itext-font","small"),ReadingsVal($name,"$itext-angle",0),ReadingsVal($name,"$itext-size",10),int(ReadingsVal($name,"$itext-blockwidth",0)),$th); @@ -1424,6 +1541,54 @@ sub ESPEInk_AddObjects($$) { } $ly += $th; } + } else { + my ($sym,$s1,$s2) = ("","",""); + ($sym,$s1,$s2) = split("-",ReadingsVal($name,"$itext-symbol","")); + my $size = ReadingsVal($name,"$itext-size",""); + my $width = ReadingsVal($name,"$itext-width",0); + my $height = ReadingsVal($name,"$itext-height",0); + my $ang = ReadingsVal($name,"$itext-angle",0); + my $arc = ReadingsVal($name,"$itext-arc",0); + my $x = ReadingsVal($name,"$itext-x",0); + my $y = ReadingsVal($name,"$itext-y",0); + $image->setStyle($color); + if ($sym eq "line") { + my $angle = atan2($height,$width); + for (my $i=0;$i<$size;$i++) { + $image->setStyle($color,$color,$color,$color,gdTransparent,gdTransparent,gdTransparent,gdTransparent) if ($s1 eq "dashed" or $s2 eq "dashed"); + $image->setStyle($color,$color,gdTransparent,gdTransparent) if ($s1 eq "dotted" or $s2 eq "dotted"); + $image->line($x,$y,$x+$width,$y+$height,gdStyled); + $x+=sin($angle); + $y-=cos($angle); + } + } elsif ($sym eq "rectangle") { + $image->setThickness($size); + $image->setStyle($color,$color,$color,$color,gdTransparent,gdTransparent,gdTransparent,gdTransparent) if ($s1 eq "dashed" or $s2 eq "dashed"); + $image->setStyle($color,$color,gdTransparent,gdTransparent) if ($s1 eq "dotted" or $s2 eq "dotted"); + if ($s1 eq "filled" or $s2 eq "filled") { + $image->filledRectangle($x,$y,$x+$width,$y+$height,gdStyled); + } else { + $image->rectangle($x,$y,$x+$width,$y+$height,gdStyled); + } + } elsif ($sym eq "ellipse") { + $image->setThickness($size); + $image->setStyle($color,$color,$color,$color,gdTransparent,gdTransparent,gdTransparent,gdTransparent) if ($s1 eq "dashed" or $s2 eq "dashed"); + $image->setStyle($color,$color,gdTransparent,gdTransparent) if ($s1 eq "dotted" or $s2 eq "dotted"); + if ($s1 eq "filled" or $s2 eq "filled") { + $image->filledEllipse($x+$width/2,$y+$height/2,$width,$height,gdStyled); + } else { + $image->ellipse($x+$width/2,$y+$height/2,$width,$height,gdStyled); + } + } elsif ($sym eq "arc") { + $image->setThickness($size); + $image->setStyle($color,$color,$color,$color,gdTransparent,gdTransparent,gdTransparent,gdTransparent) if ($s1 eq "dashed" or $s2 eq "dashed"); + $image->setStyle($color,$color,gdTransparent,gdTransparent) if ($s1 eq "dotted" or $s2 eq "dotted"); + if ($s1 eq "filled" or $s2 eq "filled") { + $image->filledArc($x+$width/2,$y+$height/2,$width,$height,$ang,$ang+$arc,gdStyled,gdEdged); + } else { + $image->arc($x+$width/2,$y+$height/2,$width,$height,$ang,$ang+$arc,gdStyled); + } + } } } } @@ -1634,10 +1799,22 @@ sub ESPEInk_DoConvert(@) { return "$name|$upload"; } +#--------------------------------------------------------------------------------------------------- +# get pixel from image +sub ESPEInk_getPixel($$$$) { + my ($image, $w, $h, $indx ) = @_; + + my $iy = int( $indx / $w ); + my $ix = $indx % $w; + my ($r,$g,$b) = $image->rgb($image->getPixel($ix,$iy)); + + return ($r==0&&$g==0)?0:(($r==255&&$g==255)?1:(($r==127&&$g==127)?2:3)); #convert color values to values between 0 and 3 +} + #--------------------------------------------------------------------------------------------------- # helper function for coding picture pixels to EInk bit settings -sub ESPEInk_CodePixel2Bits($$$$$) { - my ($indx,$bits,$comp,$imax,$array) = @_; +sub ESPEInk_CodePixel2BitsImage($$$$$$$$) { + my ($indx,$bits,$comp,$imax,$image,$w,$h,$isize) = @_; my $v; my $x; my $str; @@ -1650,7 +1827,7 @@ sub ESPEInk_CodePixel2Bits($$$$$) { while ($x < 122) { $v = 0; for (my $i=0; $i<$bits&&$x<122; $i++,$x++) { - if ((${$array}[$indx]!=0)) { + if ((ESPEInk_getPixel($image,$w,$h,$indx)!=0)) { $v|=(128>>$i); } $indx++; @@ -1662,7 +1839,7 @@ sub ESPEInk_CodePixel2Bits($$$$$) { } else { $v = 0; for (my $i=0; $i<$bits; $i++) { - if (($indx<@{$array})&&(${$array}[$indx]!=$comp)) { + if (($indx<$isize)&&(ESPEInk_getPixel($image,$w,$h,$indx)!=$comp)) { $v|=(128>>$i); } $indx++; @@ -1672,8 +1849,8 @@ sub ESPEInk_CodePixel2Bits($$$$$) { } elsif ($bits == 16) { $v = 0; for (my $i=0; $i<$bits; $i+=2) { - if ($indx<@{$array}) { - $v|=(${$array}[$indx]<<$i); + if ($indx<$isize) { + $v|=(ESPEInk_getPixel($image,$w,$h,$indx)<<$i); } $indx++; } @@ -1681,6 +1858,53 @@ sub ESPEInk_CodePixel2Bits($$$$$) { } } +# #--------------------------------------------------------------------------------------------------- +# # helper function for coding picture pixels to EInk bit settings +# sub ESPEInk_CodePixel2Bits($$$$$) { + # my ($indx,$bits,$comp,$imax,$array) = @_; + # my $v; + # my $x; + # my $str; + + # if ($bits == 8) { + # if ($comp == -1) { + # $str = ""; + # while (($indx < $imax)) { + # $x = 0; + # while ($x < 122) { + # $v = 0; + # for (my $i=0; $i<$bits&&$x<122; $i++,$x++) { + # if ((${$array}[$indx]!=0)) { + # $v|=(128>>$i); + # } + # $indx++; + # } + # $str .= ESPEInk_Byte2String($v); + # } + # } + # return ($indx, $str); + # } else { + # $v = 0; + # for (my $i=0; $i<$bits; $i++) { + # if (($indx<@{$array})&&(${$array}[$indx]!=$comp)) { + # $v|=(128>>$i); + # } + # $indx++; + # } + # return ($indx, ESPEInk_Byte2String($v)); + # } + # } elsif ($bits == 16) { + # $v = 0; + # for (my $i=0; $i<$bits; $i+=2) { + # if ($indx<@{$array}) { + # $v|=(${$array}[$indx]<<$i); + # } + # $indx++; + # } + # return ($indx, ESPEInk_Word2String($v)); + # } +# } + #--------------------------------------------------------------------------------------------------- # helper function for converting a byte value to a string readable by EInk display sub ESPEInk_Byte2String($) { @@ -1697,14 +1921,19 @@ sub ESPEInk_Word2String($) { #--------------------------------------------------------------------------------------------------- # helper function to encode the picture pixels to the right values for the EIknk display -sub ESPEInk_Encode4Upload($$$$) { - my($param,$bits,$comp,$data) = @_; +sub ESPEInk_Encode4UploadImage($$$) { + my($param,$bits,$comp) = @_; my $i = int($param->{control}{srcindex}); my $ret = ""; my $imax; + + my $image = $param->{image}; + my $w = $param->{imagew}; + my $h = $param->{imageh}; + my $isize = $param->{imagesize}; - if (($i+int($param->{maxulsize})*($bits==8?4:2)) > (@{$data}-1)) { - $imax = @{$data}-1; + if (($i+int($param->{maxulsize})*($bits==8?4:2)) > ($isize-1)) { + $imax = $isize-1; } else { $imax = $i+int($param->{maxulsize})*($bits==8?4:2); } @@ -1715,12 +1944,38 @@ sub ESPEInk_Encode4Upload($$$$) { my $postdata = ""; while ($i < $imax) { - ($i, $ret) = ESPEInk_CodePixel2Bits($i,$bits,$comp,$imax,\@{$data}); + ($i, $ret) = ESPEInk_CodePixel2BitsImage($i,$bits,$comp,$imax,$image, $w, $h, $isize); $postdata .= $ret; } return ($i,$postdata.ESPEInk_Word2String(length($postdata))."LOAD"); } +# #--------------------------------------------------------------------------------------------------- +# # helper function to encode the picture pixels to the right values for the EIknk display +# sub ESPEInk_Encode4Upload($$$$) { + # my($param,$bits,$comp,$data) = @_; + # my $i = int($param->{control}{srcindex}); + # my $ret = ""; + # my $imax; + + # if (($i+int($param->{maxulsize})*($bits==8?4:2)) > (@{$data}-1)) { + # $imax = @{$data}-1; + # } else { + # $imax = $i+int($param->{maxulsize})*($bits==8?4:2); + # } + + # if ($param->{device} == 3) { + # $imax = $i+int($param->{maxulsize})*($bits==8?4:2)-(($param->{board} eq "ESP8266")?366:122); + # } + + # my $postdata = ""; + # while ($i < $imax) { + # ($i, $ret) = ESPEInk_CodePixel2Bits($i,$bits,$comp,$imax,\@{$data}); + # $postdata .= $ret; + # } + # return ($i,$postdata.ESPEInk_Word2String(length($postdata))."LOAD"); +# } + #--------------------------------------------------------------------------------------------------- # callback function for the http calls. Here all upload logic is happening sub ESPEInk_HTTPCallbackA(@) { @@ -1763,10 +2018,10 @@ sub ESPEInk_HTTPCallbackA(@) { $bits = 8; $param->{command} = "LOAD"; # start uploading black channel $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{command}; - ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4Upload($param,$bits,$comp,\@{$param->{outarray}}); + ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4UploadImage($param,$bits,$comp); $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{data}.'_' if ($param->{board} eq "ESP32"); $param->{data} = '' if ($param->{board} eq "ESP32"); - $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= @{$param->{outarray}}); # complete array has been coded and sent, go to next step + $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= $param->{imagesize}); # complete array has been coded and sent, go to next step $cparams->{$name} = $param; $cparams->{data} = $param->{data}; HttpUtils_NonblockingGet($cparams); @@ -1797,10 +2052,10 @@ sub ESPEInk_HTTPCallbackA(@) { $bits = 8; $param->{command} = "LOAD"; # start uploading black channel $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{command}; - ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4Upload($param,$bits,$comp,\@{$param->{outarray}}); + ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4UploadImage($param,$bits,$comp); $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{data}.'_' if ($param->{board} eq "ESP32"); $param->{data} = '' if ($param->{board} eq "ESP32"); - $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= @{$param->{outarray}}); # complete array has been coded and sent, go to next step + $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= $param->{imagesize}); # complete array has been coded and sent, go to next step $cparams->{$name} = $param; $cparams->{data} = $param->{data}; HttpUtils_NonblockingGet($cparams); @@ -1823,10 +2078,10 @@ sub ESPEInk_HTTPCallbackA(@) { $bits = 16; $param->{command} = "LOAD"; # start uploading black channel $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{command}; - ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4Upload($param,$bits,$comp,\@{$param->{outarray}}); + ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4UploadImage($param,$bits,$comp); $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{data}.'_' if ($param->{board} eq "ESP32"); $param->{data} = '' if ($param->{board} eq "ESP32"); - $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= @{$param->{outarray}}); # complete array has been coded and sent, go to next step + $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= $param->{imagesize}); # complete array has been coded and sent, go to next step $cparams->{$name} = $param; $cparams->{data} = $param->{data}; HttpUtils_NonblockingGet($cparams); @@ -1857,10 +2112,10 @@ sub ESPEInk_HTTPCallbackA(@) { } $param->{command} = "LOAD"; # start uploading black channel $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{command}; - ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4Upload($param,$bits,$comp,\@{$param->{outarray}}); + ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4UploadImage($param,$bits,$comp); $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{data}.'_' if ($param->{board} eq "ESP32"); $param->{data} = '' if ($param->{board} eq "ESP32"); - $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= @{$param->{outarray}}); # complete array has been coded and sent, go to next step + $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= $param->{imagesize}); # complete array has been coded and sent, go to next step $cparams->{$name} = $param; $cparams->{data} = $param->{data}; HttpUtils_NonblockingGet($cparams); @@ -1881,10 +2136,10 @@ sub ESPEInk_HTTPCallbackA(@) { $bits = 8; $param->{command} = "LOAD"; # start uploading black channel $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{command}; - ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4Upload($param,$bits,$comp,\@{$param->{outarray}}); + ($param->{control}{srcindex},$param->{data}) = ESPEInk_Encode4UploadImage($param,$bits,$comp); $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$param->{data}.'_' if ($param->{board} eq "ESP32"); $param->{data} = '' if ($param->{board} eq "ESP32"); - $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= @{$param->{outarray}}); # complete array has been coded and sent, go to next step + $param->{control}{stepindex}++ if ($param->{control}{srcindex} >= $param->{imagesize}); # complete array has been coded and sent, go to next step $cparams->{$name} = $param; $cparams->{data} = $param->{data}; HttpUtils_NonblockingGet($cparams); @@ -1907,14 +2162,22 @@ sub ESPEInk_HTTPCallbackA(@) { #--------------------------------------------------------------------------------------------------- # initialization of upload and first http call (rest is cared for in the callback function) -sub ESPEInk_PostToDevice($$$$$) { - my ($hash,$command,$devind,$control,@outarray) = @_; +sub ESPEInk_PostToDeviceImage($$$$$) { + my ($hash,$command,$devind,$control,$image) = @_; my $name = $hash->{NAME}; + + my ($w,$h) = $image->getBounds if ( defined( $image ) ); # JV + + my $params = { command => $command, device => $devind, - outarray => @outarray, +# outarray => @outarray, + image => $image, # JV + imagew => $w, # JV + imageh => $h, # JV + imagesize => $w*$h, # JV board => ($command eq "EPDx_")?"ESP32":"ESP8266", hash => $hash, control => $control, @@ -1945,6 +2208,46 @@ sub ESPEInk_PostToDevice($$$$$) { HttpUtils_NonblockingGet($cparams); } +# #--------------------------------------------------------------------------------------------------- +# # initialization of upload and first http call (rest is cared for in the callback function) +# sub ESPEInk_PostToDevice($$$$$) { + # my ($hash,$command,$devind,$control,@outarray) = @_; + # my $name = $hash->{NAME}; + + # my $params = { + # command => $command, + # device => $devind, + # outarray => @outarray, + # board => ($command eq "EPDx_")?"ESP32":"ESP8266", + # hash => $hash, + # control => $control, + # maxulsize => ($command eq "EPDx_")?1000:1500 + # }; + + # my $cparams = { + # method => "POST", + # header => "Content-Type: text/plain\r\nUser-Agent: fhem\r\nAccept: */*", + # data => ESPEInk_Byte2String($devind), + # callback => \&ESPEInk_HTTPCallbackA, + # devname => $name + # }; + + # if ($params->{board} eq "ESP32") { + # if ($params->{device} == 3) { # special treatment for this device + # $params->{command} =~ s/x_/d_/g; + # } else { # treatment for all smaller color capable displays + # my $subst = chr($params->{device}+97)."_"; + # $params->{command} =~ s/x_/$subst/g; + # } + # } + + # $cparams->{url} = 'http://'.ESPEInk_GetSetting($name,"url").'/'.$params->{command}; + # $cparams->{data} = '' if ($params->{board} eq "ESP32"); + # $cparams->{$name} = $params; + # Log3 ($hash, 3, "$name: sending HTTP request to $cparams->{url} with data: $cparams->{data}"); + # HttpUtils_NonblockingGet($cparams); +# } + #--------------------------------------------------------------------------------------------------- # code converted picture and send it to eInk driver board (and thus to the connected eInk display) sub ESPEInk_Upload(@) { @@ -1971,31 +2274,33 @@ sub ESPEInk_Upload(@) { my $rootname = $FW_dir; #File::Spec->rel2abs($FW_dir); # get Filename of FHEMWEB root my $filename = catfile($rootname,$hash->{SUBFOLDER},$name,"result.png"); + my $image; # JV if (!open(RESULT,$filename)) { Log3 $hash, 1, "File $filename cannot be opened"; return "Error opening image file $filename for upload"; - } else { - close RESULT; - my $image = GD::Image->newFromPng($filename); - my ($w,$h) = $image->getBounds; - my ($r,$g,$b); - my $i = 0; + } # else { + close RESULT; + # my $image = GD::Image->newFromPng($filename); # JV + $image = GD::Image->newFromPng($filename); # JV + # my ($w,$h) = $image->getBounds; + # my ($r,$g,$b); + # my $i = 0; - for (my $iy=0; $iy<$h; $iy++) { - for (my $ix=0; $ix<$w; $ix++) { - ($r,$g,$b) = $image->rgb($image->getPixel($ix,$iy)); - $outarray[$i] = ($r==0&&$g==0)?0:(($r==255&&$g==255)?1:(($r==127&&$g==127)?2:3)); #convert color values to values between 0 and 3 - $i++; - } - } - } + # for (my $iy=0; $iy<$h; $iy++) { + # for (my $ix=0; $ix<$w; $ix++) { + # ($r,$g,$b) = $image->rgb($image->getPixel($ix,$iy)); + # $outarray[$i] = ($r==0&&$g==0)?0:(($r==255&&$g==255)?1:(($r==127&&$g==127)?2:3)); #convert color values to values between 0 and 3 + # $i++; + # } + # } +# } $ESPEInk_uploadcontrol{"retries"} = 0; # actual number of retries $ESPEInk_uploadcontrol{"maxretries"} = AttrVal($name,"maxretries",3); # maximum number of retries $ESPEInk_uploadcontrol{"timeout"} = AttrVal($name,"timeout",10); # timout for HTTP calls $ESPEInk_uploadcontrol{"stepindex"} = 0; # step currently performed (for multi color displays each color is transferred separately) $ESPEInk_uploadcontrol{"srcindex"} = 0; # index of source array currently transferred (we might need to split due to the limit on arduino code in data transfer length via HTTP) - ESPEInk_PostToDevice($hash,($boardtype eq "ESP32")?'EPDx_':'EPD',$devind,\%ESPEInk_uploadcontrol,\@outarray); # convert data from conversion result in appropriate format and send it to the device via HTTP + ESPEInk_PostToDeviceImage($hash,($boardtype eq "ESP32")?'EPDx_':'EPD',$devind,\%ESPEInk_uploadcontrol,$image); # convert data from conversion result in appropriate format and send it to the device via HTTP return $hash->{STATE}; } @@ -2087,6 +2392,24 @@ sub ESPEInk_Upload(@) { The attributes allow an easy change of the readings (see details in the description below). Once at least one icon is specified, the set option removeobject is added.
+
  • addsymbol
    + This option allows to specify an symbols (lines, ellipses, rectangles, arcs) that should be added to the template picture at any position. +
    The value must be given in the form: symbol#x#y#thickness#angle#color#width#height#segment +
    where: +
    symbol is specifying which symbol should be drawn. Possible values are line or rectangle or ellipse or arc. If -filled is added, the symbol is filled, if -dotted or -dashed is added, the line is drawn dotted or dashed. + For example a symbol value given as 'line-dotted' will draw a dotted line, 'rectangle-filled' will draw a filled rectangle. +
    x is the x-position of the lower left corner of the symbol relative to the lower left corner of the display area +
    y is the y-position of the lower left corner of the symbol relative to the lower left corner of the display area +
    thickness is the thickness of lines or outlines of the symbols drawn. +
    angle is the rotation angle (counterclockwise) that should be used when drawing the symbol. +
    color is an RGB hex string that specifies the RGB values of the color respectively (e.g. 00FF00 for green) +
    width is the width of the symbol (in case of lines, the line is drawn width pixels in x direction and height pixels in y direction). +
    height is the width of the symbol (in case of lines, the line is drawn width pixels in x direction and height pixels in y direction). +
    segment is only used for arc type symbols. In this case angle (see above) specifies the start of the arc and segment specifices the width of the arc. +
    For each of the specified symbols a list of readings and attributes is added to the device. The readings are holding the parameters finally taken for the generation of the output picture. + The attributes allow an easy change of the readings (see details in the description below). Once at least one symbol is specified, the set option removeobject is added. +
    +
  • textreading
    This option allows to specify a device:reading as trigger for adding texts to the template picture at any position.
    The value must be given in the form: device:reading#x#y#size#angle#color#font#linegap#blockwidth @@ -2219,13 +2542,13 @@ sub ESPEInk_Upload(@) { The url of the WLAN driver board the eInk display is connected to (typically an IP address but could also be a Web-URL)
  • definition
    - This is an alternative to using the set addtext/addicon/textreadin/iconreading command. The attribute contains a list of defintions separated by newline. - The syntax of the defintion is the same as in the reading [0-n]-def. It contains the command (addtext or addicon or textreading or iconreading) followed by '#' and then the same defintion values as statet in set (addtext ...) above. + This is an alternative to using the set addtext/addicon/addsymbol/textreadin/iconreading command. The attribute contains a list of defintions separated by newline. + The syntax of the defintion is the same as in the reading [0-n]-def. It contains the command (addtext or addicon or addsymbol or textreading or iconreading) followed by '#' and then the same defintion values as statet in set (addtext ...) above. Lines starting with a # are ignored and treated as comment lines. Example: addtext#Hello#10#10#12#0#000000#giant
  • definitionFile
    - This is another alternative to using the set addtext/addicon/textreadin/iconreading command. The attribute holdes the name of a text file containing a list of defintions separated by newline. - The syntax of the defintion is the same as in the reading [0-n]-def. It contains the command (addtext or addicon or textreading or iconreading) followed by '#' and then the same defintion values as statet in set (addtext ...) above. + This is another alternative to using the set addtext/addicon/addsymbol/textreadin/iconreading command. The attribute holdes the name of a text file containing a list of defintions separated by newline. + The syntax of the defintion is the same as in the reading [0-n]-def. It contains the command (addtext or addicon or addsymbol or textreading or iconreading) followed by '#' and then the same defintion values as statet in set (addtext ...) above. Lines starting with a # are ignored and treated as comment lines. Example: addtext#Hello#10#10#12#0#000000#giant
  • interval