Farbverläufe zum Einfärben von Werten bzw. Icons

Begonnen von christiang, 25 November 2016, 18:15:15

Vorheriges Thema - Nächstes Thema

christiang

Hallo zusammen,

ich habe ein kleines Script gebastelt, das konfigurierbare Farbübergänge zur Darstellung von Werten liefert.

Ich verwende das Skript derzeit, um Icons für eine Readingsgroup einzufärben. Deshalb werden vom Skript Farben in HTML Kodierung generiert und mit einem übergebenen Icon-String passend für die ReadingsGroup formatiert. Falls jemand ein anderes Format benötigt, ist das allerdings sehr leicht abzuändern.

Zur Konfiguration müssen lediglich die Stützpunkte des Farbverlaufs mit den entsprechenden Farben angegeben werden.
Zusätzlich wird die Genauigkeit angegeben, für die Farben erzeugt werden sollen.

Die Farbwerte werden einmalig beim ersten Aufruf der Funktion berechnet und in einem Array abgelegt.
Die Größe des erzeugten Arrays ergibt sich durch den Abstand der max/min Stützpunkte mal 10^Genauigkeit.

Das Skript besteht aus zwei Funktionen:

Die erste Funktion (hier "tempToColor($@)") enthält die Konfiguration des Farbübergangs (%points und $decimals) und wird entsprechend öfters benötigt, falls mehrere Übergänge verwendet werden sollen.

Die zweite Funktion "generateColorArray($$)" berechnet das Array und wird nur ein einzelnes Mal benötigt, auch wenn mehrere Farbübergänge verwendet werden. Sie muss nur geändert werden, falls eine andere Kodierung benötigt wird.

Zur Verwendung muss dann lediglich die erste Funktion mit dem aktuellen Messwert aufgerufen werden. z.B:

attr rgroup valueIcon {'humidity'=>'{humToColor($VALUE,qq(humidity))}',\
'temperature'=>'{tempToColor($VALUE,qq(temp_temperature))}'}


Grüße,
Christian


use feature qw(state);

sub tempToColor($@)
{
my $val = shift;
my $icon = shift;

state $colors;
state $min;
state $max;
state $mult;
state $init = 0;

unless ($init) {

# Configuration
my %points = (
-10  => [0,0,128],
10  => [0,255,255],
22  => [0,128,0],
26  => [255,255,0],
30  => [255,0,0]
);
my $decimals = 1;

($colors, $min, $max, $mult) = generateColorArray(\%points, $decimals);
$init = 1;
}

my $color;
if ($val <= $min) {
$color = @$colors[0];
} elsif ($val >= $max) {
$color = @$colors[$#{ $colors }];
} else {
$color = @$colors[int(($val-$min)*$mult)];
}

return $icon ? "$icon\@$color" : $color;
}

sub generateColorArray($$)
{
my $points = shift;
my $decimals = shift;

my @keys = sort keys %$points;
my $mult = (10 ** $decimals);
my $size = ($keys[$#keys] - $keys[0] ) * $mult + 1;

# Initialize empty array
my @colors;
@colors[$size-1] = undef;

# Previous/next point and color
my $prevpts = $keys[0];
my $nextpts = $keys[1];
my $prevcol = $points->{$keys[0]};
my $nextcol = $points->{$keys[1]};

# Index after current position
my $currspts = 1;

# Range between previous and next point
my $range = $nextpts - $prevpts;

my $index = 0;
for (my $i = $keys[0]*$mult ; $i <= $keys[$#keys]*$mult ; $i++) {

# Select next range when i has reached next point
if ($i/$mult > $nextpts) {
$prevpts = $keys[$currspts];
$nextpts = $keys[$currspts+1];
$prevcol = $points->{$prevpts};
$nextcol = $points->{$nextpts};
$range = $nextpts - $prevpts;
$currspts++;
}

# High and low percentage
my $hp = ($i/$mult - $prevpts)/$range;
                my $lp = 1-$hp;
       
                # Get rgb
                my $r = $lp * ${$prevcol}[0] + $hp * ${$nextcol}[0];
                my $g = $lp * ${$prevcol}[1] + $hp * ${$nextcol}[1];
                my $b = $lp * ${$prevcol}[2] + $hp * ${$nextcol}[2];

$colors[$index] = sprintf ("%2.2X%2.2X%2.2X",$r,$g,$b,);
$index++;
}

return(\@colors, $keys[0], $keys[$#keys], $mult);
}


justme1968

hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

christiang

#2
Na offentlichlich bisher nicht :/