Badgy - IoT Badge - E-Ink / E-Paper Display 2.9'' - Einbindung in IPS

Hier eine kurze Anleitung zum einbinden des Badgy E-Ink-Display in IP-Symcon.
Die Anleitung soll es möglichst jedem ermöglichen das Display einzubinden und mit eigenem Inhalt zu füllen.

Als Firmware auf dem Badgy dient die websocketDraw.ino von GitHub ohne Modifikationen.
Diese wird laut Anleitung auf GitHub aufgespielt.

Als nächstes benötigt man das Modul IPSNetwork von Nall-Chan.
-> Einen Websocket-Client anlegen mit der einzigen Einstellung: ws://BADGY_IP_ADRESSE:81

Jetzt ein Skript mit folgendem Inhalt anlegen:

<?php
$websocket_id = 49865;
$width = 296; //Displaysize x
$height = 128; // Displaysize y
$dest_image = imagecreatetruecolor($width, $height);  // Create image
$white = imagecolorallocate($dest_image, 255, 255, 255); // Color white
$black = imagecolorallocate($dest_image, 0, 0, 0);	// Color black
imagefill($dest_image,0,0,$white); // Fill image

$load = getvaluefloat(14333); // Variable load 0 to 100
$soc = getvalueinteger(58053); // State of charge 0 to 100
$current = getvaluefloat(48387); // Current -50 to 50

// -------------------- Edit image to create -----------------------------

// -------------------- Text ---------------------------------------------
$text = number_format ($current,1)."A"; // generate text for current
imagestring($dest_image, 5, 162, 48, $text, $black); // copy text to image

// --------------- Draw Lines --------------------------------------------
if ($load < 25){imageline ( $dest_image , 49 , 14 , 49 , 18 , $black );} // 25%
if ($load < 50){imageline ( $dest_image , 98 , 14 , 98 , 18 , $black );} // 50%
if ($load < 75){imageline ( $dest_image , 147 , 14 , 147 , 18 , $black );} // 75%

// ---------------- Draw rectangles --------------------------------------
$soc_y = 113 - round(($soc/100)*90,0); // Calculate rectangle for soc
imagefilledrectangle ( $dest_image , 224 , 113 , 279 , $soc_y , $black ) ; // Draw rectangle

if ($soc < 100){imagefilledrectangle ( $dest_image , 234 , 55 , 269 , 80 , $white ) ;} // White rectangle for text

imagerectangle($dest_image,2,2,194,20, $black); // frame 1 for load
imagerectangle($dest_image,3,3,193,19, $black); // frame 2 for load

$load_x = 4 + round(($load/100)*190,0); // Calculate rectangle for load
if ($load_x > 190){$load_x = 191;} // if calculated value is to big
imagefilledrectangle ( $dest_image , 5 , 5 , $load_x , 17 , $black ) ; // Draw load bar

imagefilledrectangle ( $dest_image , 90 , 7 , 112 , 15 , $white ); // white rectangle for text

$x_pos = 95; // Position for one digit
if ($load == 100){$x_pos = 91;} // Position for three digits
if ($load >= 10 and $load < 100){$x_pos = 93;} // Position for two digits
imagestring($dest_image, 1, $x_pos, 7, $load."%", $black); // copy text to image
// --------------- Place Images ------------------------------------------
// ImageCopy ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h ) : int
// imagecopyresized ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h ) : bool
$image = imagecreatefrompng("/var/lib/symcon/media/battery.png"); // load image
imagecopy($dest_image, $image, 198, 0, 10, 0, 108, 128); // copy image to destination
imagedestroy($image);    //destroy image

if ($current > 0 ){ // images for battery is loading

    $image = imagecreatefrompng("/var/lib/symcon/media/arrow-right.png"); // load image
    imagecopyresized($dest_image, $image, 160, 65, 0, 0, 50, 30, 64, 64); // copy resized image to destination
    imagedestroy($image); //destroy image
    
    $image = imagecreatefrompng("/var/lib/symcon/media/arrow-left.png"); // load image
    imagecopyresized($dest_image, $image, 40, 65, 0, 0, 50, 30, 64, 64); // copy resized image to destination
    imagedestroy($image); //destroy image

    $image = imagecreatefrompng("/var/lib/symcon/media/solar-panel.png"); // load image
    imagecopyresized($dest_image, $image, 90, 45, 0, 0, 70, 70, 128, 128); // copy resized image to destination
    imagedestroy($image); //destroy image

     $image = imagecreatefrompng("/var/lib/symcon/media/plug.png"); // load image
    imagecopyresized($dest_image, $image,2, 65, 0, 0, 50, 50, 128, 128); // copy resized image to destination
    imagedestroy($image); //destroy image 

    
}
if ($current <= 0 and $current >= -1.4){ // images for battery is not loading - supply from grid
     $image = imagecreatefrompng("/var/lib/symcon/media/power.png"); // load image
    imagecopyresized($dest_image, $image, 0, 55, 0, 0, 45, 60, 128, 128); // copy resized image to destination
    imagedestroy($image); //destroy image

     $image = imagecreatefrompng("/var/lib/symcon/media/plug.png"); // load image
    imagecopyresized($dest_image, $image, 105, 60, 0, 0, 50, 50, 128, 128); // copy resized image to destination
    imagedestroy($image); //destroy image  

    $image = imagecreatefrompng("/var/lib/symcon/media/arrow-right.png"); // load image
    imagecopyresized($dest_image, $image, 48, 65, 0, 0, 50, 30, 64, 64); // copy resized image to destination
    imagedestroy($image); //destroy image

    $image = imagecreatefrompng("/var/lib/symcon/media/arrow-left.png"); // load image
    imagecopyresized($dest_image, $image, 160, 65, 0, 0, 50, 30, 64, 64); // copy resized image to destination
    imagedestroy($image); //destroy image     
}
if ($current < -1.4){ // images for load is on battery
     $image = imagecreatefrompng("/var/lib/symcon/media/plug.png"); // load image
    imagecopyresized($dest_image, $image, 105, 60, 0, 0, 50, 50, 128, 128); // copy resized image to destination
    imagedestroy($image); //destroy image

    $image = imagecreatefrompng("/var/lib/symcon/media/arrow-left.png"); // load image
    imagecopyresized($dest_image, $image, 160, 65, 0, 0, 50, 30, 64, 64); // copy resized image to destination
    imagedestroy($image); //destroy image  
}
// --------------------- Text "True Type Font" --------------------------
// imagettftext ( resource $image , float $size , float $angle , int $x , int $y , int $color , string $fontfile , string $text ) : array
$font = '/var/lib/symcon/webfront/user/eInk/Arial.ttf'; // location of True Type Font

$text = getvaluestring(27105); // get string which contains remaining time

if ($text !== "INF:NAN"){ // if time is available copy it to image
        imagettftext($dest_image, 14, 0, 14, 38, $black, $font, "Verbleibend: ".$text); // copy text to image
}

$pos_txt = 239; // position for two digits
if ($soc < 10){$pos_txt = 245;} // position for one digit
if ($soc < 100){imagettftext($dest_image, 18, 0, $pos_txt, 75, $black, $font, $soc);} // copy text to image if soc < 100

// ------------------- End create Image ------------------------


$sendstr = ""; // empty string for data to send
for ($ypos = 0; $ypos <= ($height -1); $ypos++){  // lines of display
	for ($a = 0; $a <= ($width/8)-1; $a++) {     // bytes per line (width divided by 8)
		$outbyte = 0;							 // empty byte for pixels
		for ($onebyte = 0; $onebyte <=7; $onebyte++) {  // bits per byte
			$xpos = ($a * 8)+$onebyte;					// x-position to read
			$rgb = imagecolorat($dest_image, $xpos, $ypos);  // get the pixel color
			if ($rgb > 0 ){									// if pixel is not white set bit
				$outbyte = $outbyte + pow(2,7-$onebyte);    // calculation of bit to set
			}
		}
	$sendstr = $sendstr.chr($outbyte^0xFF);    // append byte to string to send
	}
}

// Generate jpeg image for prewiew
if ($_IPS['SENDER'] == "Execute"){ // only on script execute 
ob_start(); // Turn on output buffering
header( "Content-type: image/jpeg" ); // set header
imagerectangle ( $dest_image , 0 , 0 , $width-1 , $height-1 , $black ) ; // image size
imagejpeg( $dest_image, NULL, 100 ); // generate jpeg from image data
$i = ob_get_clean(); // Get current buffer contents and delete current output buffer
echo "<img src='data:image/jpeg;base64," . base64_encode( $i )."'>"; // echo jpeg data 
}
imagedestroy($dest_image);    //destroy image



WSC_SendPacket($websocket_id, true, 2, $sendstr );  // send data with websocket

Dieses Skript dient als Beispiel und ist ohne Bearbeitung nicht lauffähig, da die Schriftart, die Grafiken und die Variablen bei euch fehlen.

Ist das Skript angepasst und wird ausgeführt, sieht man im Ausgabefenster (HTML) die Grafik für das Display als Vorschau.

Demnächst will ich das Skript auch noch mit anderen Displays testen.

Bis dahin.
Grüße
Stefan

Was ich noch vergessen habe zu erwähnen…

Das ganze ist überhaupt nicht auf geringen Energieverbrauch ausgelegt. Der Badgy läuft immer voll. Mit dem kleinen Akku auf der Platine würde das natürlich keinen Spaß machen.
Vorteil ist, man kann Aktualisierungen am Display mit ausgelösten Ereignissen der sich ändernden Variablen sofort senden.

Ich will aber noch eine geänderte Firmware für den Badgy machen, die dann auf geringen Energieverbrauch ausgelegt ist und dann mit dem OnBoard-Akku längere zeit läuft. Wann ich dazu komme? Keine Ahnung…

Vielen Dank für Deinen Bericht, ist ein deutscher Zeichensatz möglich?
Gruß Helmut

Hallo Helmut,
da die Daten als Grafik generiert werden, ist alles möglich. Es werden hier unter anderem True Type Fonts verwendet. Du könntest auch Windings als Schriftart verwenden.

Grüße