2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00
Support for custom and special characters

- remove fixed replacements like ä => ae
- add attr replaceRegex for replacements needed by the used display
- add attr customChar0-7 for custom chars
- replace \x{XY} with char XY to access non ASCII and custom chars

git-svn-id: https://svn.fhem.de/fhem/trunk@6721 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
ntruchsess 2014-10-09 11:20:46 +00:00
parent 440bac9efa
commit e83daeb088

View File

@ -57,7 +57,8 @@ I2C_LCD_Initialize($)
$hash->{StateFn} = "I2C_LCD_State"; $hash->{StateFn} = "I2C_LCD_State";
$hash->{AttrList} = "restoreOnReconnect:on,off restoreOnStartup:on,off IODev model pinMapping" $hash->{AttrList} = "restoreOnReconnect:on,off restoreOnStartup:on,off IODev model pinMapping"
." backLight:on,off blink:on,off autoClear:on,off autoBreak:on,off $main::readingFnAttributes"; ." customChar0 customChar1 customChar2 customChar3 customChar4 customChar5 customChar6 customChar7"
." backLight:on,off blink:on,off autoClear:on,off autoBreak:on,off replaceRegex $main::readingFnAttributes";
# autoScroll:on,off direction:leftToRight,rightToLeft do not work reliably # autoScroll:on,off direction:leftToRight,rightToLeft do not work reliably
} }
@ -114,6 +115,9 @@ I2C_LCD_Init($$)
# I2C_LCD_Apply_Attribute($name,"autoscroll"); # I2C_LCD_Apply_Attribute($name,"autoscroll");
# I2C_LCD_Apply_Attribute($name,"direction"); # I2C_LCD_Apply_Attribute($name,"direction");
I2C_LCD_Apply_Attribute($name,"blink"); I2C_LCD_Apply_Attribute($name,"blink");
foreach (0..7) {
I2C_LCD_Apply_Attribute($name,"customChar".$_);
}
}; };
return I2C_LCD_Catch($@) if $@; return I2C_LCD_Catch($@) if $@;
} }
@ -159,6 +163,13 @@ I2C_LCD_Attr($$$$) {
I2C_LCD_Init($hash,\@def) if ($main::init_done); I2C_LCD_Init($hash,\@def) if ($main::init_done);
last; last;
}; };
$attribute =~ /customChar[0-7]/ and do {
my @vals = split(/, */, $value);
die "wrong number of elements (must be 8) in '$value'" if ( @vals != 8 );
foreach (@vals) {
die "$_ is out of range 0-31" if ($_ < 0 || $_ > 31 );
}
};
$main::attr{$name}{$attribute}=$value; $main::attr{$name}{$attribute}=$value;
I2C_LCD_Apply_Attribute($name,$attribute); I2C_LCD_Apply_Attribute($name,$attribute);
} }
@ -208,6 +219,12 @@ sub I2C_LCD_Apply_Attribute {
} }
last; last;
}; };
$attribute =~ /customChar([0-7])/ and do {
my $nr = $1;
my $p = AttrVal($name,$attribute,"0,0,0,0,0,0,0,0");
my @vals = split(/, */, $p);
$lcd->createChar($nr,\@vals);
}
} }
} }
} }
@ -235,6 +252,9 @@ sub I2C_LCD_Set(@) {
if (AttrVal($hash->{NAME},"autoClear","on") eq "on") { if (AttrVal($hash->{NAME},"autoClear","on") eq "on") {
$lcd->clear(); $lcd->clear();
} }
# set reading prior to regexp, could contain unprintable chars!
main::readingsSingleUpdate($hash,"text",$value,1);
$value = _i2c_lcd_replace($hash,$value);
if (AttrVal($hash->{NAME},"autoBreak","on") eq "on") { if (AttrVal($hash->{NAME},"autoBreak","on") eq "on") {
my $sizex = $hash->{sizex}; my $sizex = $hash->{sizex};
my $sizey = $hash->{sizey}; my $sizey = $hash->{sizey};
@ -252,7 +272,6 @@ sub I2C_LCD_Set(@) {
} else { } else {
$lcd->print($value); $lcd->print($value);
} }
main::readingsSingleUpdate($hash,"text",$value,1);
last; last;
}; };
$command eq "home" and do { $command eq "home" and do {
@ -306,9 +325,10 @@ sub I2C_LCD_Set(@) {
$lcd->setCursor($x,$y); $lcd->setCursor($x,$y);
shift @a; shift @a; shift @a; shift @a; shift @a; shift @a;
my $t = join(" ", @a); my $t = join(" ", @a);
my %umlaute = ("ä" => "ae", "Ä" => "Ae", "ü" => "ue", "Ü" => "Ue", "ö" => "oe", "Ö" => "Oe", "ß" => "ss" ," - " => " " ,"©"=>"@"); # set reading prior to regexp, could contain unprintable chars!
my $umlautkeys = join ("|", keys(%umlaute)); main::readingsSingleUpdate($hash,"writeXY",$value." ".$t,1);
$t =~ s/($umlautkeys)/$umlaute{$1}/g; readingsSingleUpdate($hash,"state",$t,1);
$t = _i2c_lcd_replace($hash,$t);
my $sl = length $t; my $sl = length $t;
if ($sl > $l) { if ($sl > $l) {
$t = substr($t,0,$l); $t = substr($t,0,$l);
@ -321,8 +341,6 @@ sub I2C_LCD_Set(@) {
$t = ($al eq "l") ? $t.$dif : $dif.$t; $t = ($al eq "l") ? $t.$dif : $dif.$t;
} }
$lcd->print($t); $lcd->print($t);
main::readingsSingleUpdate($hash,"writeXY",$value." ".$t,1);
readingsSingleUpdate($hash,"state",$t,1);
last; #"X=$x|Y=$y|L=$l|Text=$t"; last; #"X=$x|Y=$y|L=$l|Text=$t";
}; };
} }
@ -354,6 +372,23 @@ STATEHANDLER: {
} }
} }
sub _i2c_lcd_replace($$){
my ($hash, $txt) = @_;
my($lcdReplaceRegex)=AttrVal($hash->{NAME},"replaceRegex","none");
if($lcdReplaceRegex ne "none"){
my(@rex)=split(/,/,$lcdReplaceRegex);
foreach(@rex){
my($search,$replace)=split(/=/,$_);
$txt=~s/$search/$replace/g;
}
}
$txt =~ s/\\(
(?:x\{[0-9a-fA-F]+\}) | # more than 2 digit hex
(?:N\{U\+[0-9a-fA-F]{2,4}\}) # unicode by hex
)/"qq|\\$1|"/geex;
return $txt;
}
package I2C_LCD_IO; package I2C_LCD_IO;
sub new { sub new {
@ -433,6 +468,11 @@ sub write {
<li>autoBreak &lt;on|off&gt;</li> <li>autoBreak &lt;on|off&gt;</li>
<li>restoreOnStartup &lt;on|off&gt;</li> <li>restoreOnStartup &lt;on|off&gt;</li>
<li>restoreOnReconnect &lt;on|off&gt;</li> <li>restoreOnReconnect &lt;on|off&gt;</li>
<li>replaceRegex ä=ae,cd+=ef,g=\x{DF}<br/>
specify find=replace regex pattern eg for non-printable characters. \x{DF} will become char 223, which is ° on my lcd.
</li>
<li>customChar&lt;0-7&gt;<br/>
up to 8 5x8px custom chars, see http://www.quinapalus.com/hd44780udg.html for a generator, use \x{00} to \x{07} to display</li>
<li><a href="#IODev">IODev</a><br> <li><a href="#IODev">IODev</a><br>
Specify which <a href="#I2C">I2C</a> to use. (Optional, only required if there is more Specify which <a href="#I2C">I2C</a> to use. (Optional, only required if there is more
than one I2C-device defined.) than one I2C-device defined.)