WS2812B LED-Stripes and Matrix

Monday, June 24. 2019

I'm rather fond of WS2812B 'Neopixel' led strips and the elgant, minimalistic construction it allows in combination with Nodemcu as the controller. It takes a fat power source (like Meanwell ) connected to the red and white power cables of the strip, on the 3 connections at the data cable of the strip the nodemcu is hooked in with Vin to red, GND to black and the yellow cable to one of  the Nodemcu's data pins. Add a program on the Nodemcu that supports mosquitto, OTA updates and makes use of the FastLED library to control the leds and you are ready to go.

Create your own effects or adapt something open sourced by others - a search on 'ws2812b fastled effect' is a nice start. The prices are moderate, not far from what a Phillips Hue Ledstrip (2m, 36 LED elements) will cost you for 5m of LED strip with 300 Led elements.

Those LED strips come in a number of variants, 30 or 60 (or even 144) leds per meter, IP65 water resistant ones that come with an adhesive back side (an anti-feature for me) and IP67 ones in a silicone tube. The matrix is special, it is a 16cmx16cm plate with 16x16 LEDs mounted on it, connected into a single line that sort of zig-zags over the plate, the first row in a left to right orientation, the second row right to left and then left to right again... You can search and select from the rich supply of 16x16 pixel art left over from console game programming, format the image files to fit with the zig-zag orientation of the matrix and you have a flexible display for retro style icons.

There are some videos on youtube how to create that which I found really helpful even when I ended doing things in a slightly different way. Once everything has been installed and set up the question comes up how to get new icons to display (web search and considerable afterwork) and how to obtain the rgb information for the pic in the correct order. There is another tutorial for that recommending a program lcd-image converter and manually merging rows of pixel data. That program is even available for Arch Linus but unfortunately it crahes a lot. And the manual merging of image data isn't really a viable option.

After some fruitless trials along those lines I came up with my own solution in the form a tiny bash script using image magick's convert which creates an array of rgb values in the right order from a supplied 16x16 .bmp file.


#!/bin/bash

# convert banane.bmp rgb:- | xxd -g3 -c48

#echo $0 $1

`convert $1 rgb:- | xxd -g3 -c48 > ccxx.tmp`

t=0

input="./ccxx.tmp"
while IFS= read -r line
do
  a=( $line )
  var=$((var+1))
  #echo "$line"
  if (( $var % 2 )); then
     echo 0x${a[16]}, 0x${a[15]}, 0x${a[14]}, 0x${a[13]}, 0x${a[12]}, 0x${a[11]}, 0x${a[10]}, 0x${a[9]}, 0x${a[8]}, 0x${a[7]}, 0x${a[6]}, 0x${a[5]}, 0x${a[4]}, 0x${a[3]}, 0x${a[2]}, 0x${a[1]},
  else
     echo 0x${a[1]}, 0x${a[2]}, 0x${a[3]}, 0x${a[4]}, 0x${a[5]}, 0x${a[6]}, 0x${a[7]}, 0x${a[8]}, 0x${a[9]}, 0x${a[10]}, 0x${a[11]}, 0x${a[12]}, 0x${a[13]}, 0x${a[14]}, 0x${a[15]}, 0x${a[16]},
  fi
done < "$input"
 

The process is not perfect though, for some reason the colors often turn out quite different on the lcd display than what they looked on the monitor and I ended with several loops of edit and copy again. I'll end this with 3 pixel arrays as a bonus:

const long herz[]  =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x330000, 0xcc0000, 0xcc0000, 0x330000, 0x000000, 0x000000, 0x000000, 0x000000, 0x330000, 0xcc0000, 0xcc0000, 0x330000, 0x000000, 0x000000,
0x000000, 0x660000, 0xcc3333, 0xcc3333, 0xcc0000, 0xcc0000, 0x660000, 0x000000, 0x000000, 0x660000, 0xcc0000, 0xcc0000, 0xcc0000, 0xcc0000, 0x330000, 0x000000,
0xcc0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xcc0000, 0x990000, 0x660000, 0xcc0000, 0xff0000, 0xff3333, 0xffcccc, 0xffffff, 0xcc3333, 0x330000,
0xcc0000, 0xcc3333, 0xffcccc, 0xff3333, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000,
0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xcc0000, 0xcc0000,
0x330000, 0xcc0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xcc0000, 0x000000,
0x000000, 0x000000, 0xcc0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xcc0000, 0x330000, 0x000000,
0x000000, 0x000000, 0x330000, 0xcc0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xcc0000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0xcc0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xcc0000, 0x330000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x330000, 0xcc0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xcc0000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcc0000, 0xff0000, 0xff0000, 0xcc0000, 0x330000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x330000, 0xcc0000, 0xcc0000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
};

const long cool_smiley[]  =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x332001, 0x835601, 0xa87204, 0xa57005, 0x7f5601, 0x271700, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x472e00, 0xc28814, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xc28916, 0x4d3201, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x694602, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0x634102, 0x000000, 0x000000,
0x000000, 0x402800, 0xb77a08, 0xb77a08, 0xb77b08, 0xb57804, 0xb57804, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0x4d3201, 0x000000,
0x000000, 0xb8841a, 0xa29878, 0x807342, 0x9e843a, 0x9f863e, 0xa38c45, 0xb67a07, 0xb67a07, 0xa18b47, 0x9e853d, 0x9e853d, 0x8b815d, 0xa49b7f, 0xb88114, 0x000000,
0x543906, 0x685932, 0x6b6553, 0x31280f, 0x31280f, 0x31280f, 0x31280f, 0x31280f, 0x342b13, 0x31280f, 0x31280f, 0x31280f, 0x31280f, 0x000000, 0x4f4220, 0x503907,
0x5a3d02, 0xbdad7f, 0x000000, 0x000000, 0x31280f, 0x31280f, 0x31280f, 0xb77a08, 0xb77a08, 0x000000, 0x000000, 0x31280f, 0x31280f, 0x31280f, 0xb77a08, 0x986702,
0xb97b04, 0xb77a08, 0x716330, 0x000000, 0x000000, 0x000000, 0x473f28, 0xb77a08, 0xb77a08, 0x473f28, 0x000000, 0x000000, 0x000000, 0x473f28, 0xc28814, 0xc28814,
0xc28814, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb47804,
0x986702, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0x5c3e02,
0x452e01, 0xb77a08, 0xb77a08, 0xb77a08, 0x473f28, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0x473f28, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0x402800,
0x000000, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0x473f28, 0x473f28, 0xb77a08, 0xb77a08, 0xb77a08, 0x473f28, 0x473f28, 0xb77a08, 0xb77a08, 0xc38b18, 0x000000,
0x000000, 0x5c3d02, 0xb77a08, 0xb77a08, 0xb77a08, 0x473f28, 0x473f28, 0x473f28, 0x473f28, 0x473f28, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0x4d3201, 0x000000,
0x000000, 0x000000, 0x694602, 0xc28814, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0x694602, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x533802, 0xc48c18, 0xb77a08, 0xb77a08, 0xc28814, 0xb77a08, 0xb77a08, 0xb77a08, 0xb77a08, 0x4d3201, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x472e00, 0xa16d03, 0xbd7f04, 0xbd7f04, 0xa56f03, 0x533802, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
  };


const long om[]  =
{

0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x8a0001, 0x900001, 0x050000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x3b0000, 0x5f0000, 0x000000, 0xef0002, 0xee0002, 0x000000, 0x1f0000, 0x290000, 0x000000, 0x000000,
0x000000, 0x2c0000, 0xbe0001, 0xc20001, 0x000000, 0x000000, 0x000000, 0x950001, 0xc40001, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x320000, 0x860001, 0xb70001, 0xc80001, 0x990001, 0x000000, 0xeb0002, 0xd70001, 0xd40001, 0xea0002, 0xfa0002, 0xed0002, 0x770000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0xea0002, 0xf00002, 0xe50002, 0x000000, 0x4e0000, 0xfa0002, 0xfa0002, 0xfa0002, 0xf60002, 0xcf0001, 0x460000, 0x000000,
0x000000, 0x340000, 0xd30001, 0xf70002, 0xdf0002, 0x770000, 0xd90001, 0xf30002, 0x750000, 0x000000, 0x000000, 0x000000, 0xd60001, 0xb80001, 0x4e0000, 0x000000,
0x340000, 0xc70001, 0xda0001, 0xe90002, 0xfa0002, 0xe50002, 0x000000, 0x4e0000, 0xe60002, 0x6c0000, 0x000000, 0x000000, 0x8b0001, 0x6b0000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x770000, 0xa10001, 0xd40001, 0xc80001, 0x2b0000, 0xc20001, 0xfa0002, 0xe50002, 0x6c0000, 0x260000, 0xbf0001, 0x770000,
0xbf0001, 0x9d0001, 0x000000, 0x000000, 0x940001, 0xf40002, 0xf30002, 0x9a0001, 0x7f0000, 0xe90002, 0xfa0002, 0xe80002, 0x520000, 0x000000, 0x000000, 0x370000,
0x970001, 0x000000, 0x000000, 0x030000, 0xab0001, 0xe80002, 0xf00002, 0xf00002, 0xe80002, 0xe00002, 0xab0001, 0x1e0000, 0x000000, 0x000000, 0xa20001, 0xcf0001,
0xcb0001, 0xd30001, 0x380000, 0x000000, 0x000000, 0x000000, 0x000000, 0xc70001, 0xe60002, 0x740000, 0x000000, 0x1f0000, 0x000000, 0x000000, 0x6f0000, 0xb30001,
0x9f0001, 0xbb0001, 0x0f0000, 0x000000, 0x000000, 0x000000, 0x000000, 0xca0001, 0xe10002, 0x000000, 0xc30001, 0x6a0000, 0x000000, 0xc80001, 0xf80002, 0x770000,
0x000000, 0xf10002, 0xfa0002, 0xf40002, 0xf20002, 0xf10002, 0x000000, 0xe20002, 0xe50002, 0x6a0000, 0x060000, 0x010000, 0x3b0000, 0x9e0001, 0xe20002, 0x600000,
0x050000, 0xae0001, 0xf40002, 0xe10002, 0xcd0001, 0xd00001, 0xea0002, 0xfa0002, 0xc60001, 0x310000, 0xbe0001, 0xf70002, 0xfa0002, 0xf20002, 0x4e0000, 0x130000,
0x000000, 0x190000, 0x000000, 0x9d0001, 0x870001, 0x310000, 0x000000, 0x000000, 0xe10002, 0xfa0002, 0xfa0002, 0xfa0002, 0xf40002, 0xba0001, 0x330000, 0x000000,
0x000000, 0x000000, 0x1e0000, 0x4e0000, 0xba0001, 0xc70001, 0xb10001, 0x4e0000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000

};

 

 

 

openHab2 startup chaos

Thursday, October 25. 2018

starting and stopping openhab2 is a messy affair, filling the logs with loads of Java's verbose exception messages and since the order of loaded models is basically random things may or may not work as intended when items have not been loaded or rules not executed that are assumed to be there.

As it was, manual corrections and reloads were needed after each restart.

There is an elegant workaround discussed at community.openhab.org/t/cleaning-up-the-startup-process-renaming-rules-windows-possible/38438/9 which uses systemd's ExecStartPre and ExecStartPost commands to deactivate all rules before starting openhab, and then reactivate them one by one when the system is up and has it's feet on the ground.

It did not work exactly like described there for me, but I still found a solution that has cleaned up the messy startup here.

A small bash script does the renaming. I put it in /etc/openhab2 next to openhab's configuration into a new folder /exec-scripts:

#!/bin/bash
#######################
#
# clean up the start process 
#  starting rules in a sorted manner after openhab2 got it's feet on the ground
#  called from systemd pre start 
#  to rename *.rules away initially 
#
#  synopsis: move_rules_at_start.sh org-extension new-extension (POST)
#  
#  first call is from
#  /etc/systemd/system/openhab2.service.d/override.conf
#
#  called from the running openhab again to rename them back one by one
#
# $3 allows to distinguish between pre and post action 
#
# REF: https://community.openhab.org/t/cleaning-up-the-startup-process-renaming-rules-windows-possible/38438/9


ORG=$1
NEW=$2
THX=$3
DUR=1
IGNORE=005_start.rules

for f in /etc/openhab2/rules/*.${ORG};
do
    CURRENT=$(basename $f)
    if [ "$CURRENT" == "$IGNORE" ]    
    then
        echo "ignoring $IGNORE"
    else
        OLDFILE=$f
        NEWFILE=${f%$ORG}$NEW
        mv "$OLDFILE" "$NEWFILE"
    fi
    # let some time between each load
    if [ "$THX" == "POST" ]
    then
        /bin/sleep $DUR
    fi
done

# some things left on startup
if [ "$THX" == "POST" ]
then
    /usr/bin/touch /etc/openhab2/things/tradfri.things
fi


Since the openhab2.service file is part of the package and thus is replaced with each update modifying the .service file would need to be repeated whenever a new version gets installed, but, systemd provides a way to override a service definition. systemctl edit openhab2.service creates an override dir and opens the editor to allow creating a service file that is not replaced by the next update.

Now don't try to copy the entire .service file, systemd will complain duplicated statements. My override.conf looks like this:

[Service]
ExecStartPre=/etc/openhab2/exec-scripts/move_rules_at_start.sh rules rules_

The third element is a .rules file in openhab2 that triggers the renaming of all the other .rules once the system is running. It is excepted from the renaming and I named it 005_start.rules. This works for me:


var rulesDelayed
var nada

rule "triggered by system start"
when 
    System started
then
    var duration = 1
    rulesDelayed = createTimer(now.plusMinutes(duration), [|
					logInfo("rulesDelayed", "Timer expired and start")
					nada=executeCommandLine("/bin/bash /etc/openhab2/exec-scripts/move_rules_at_start.sh rules_ rules POST ",90000)
                    logInfo("rulesDelayed", "result: "+nada)
					rulesDelayed = null

				])
    logInfo("rulesDelayed", "Timer set on "+duration+" min")
end


The bash script works the list of rules -files in an alphanumerical order so a naming scheme like praefixing all .rules with a three digit number finally allows to control the order of rules loading.

Startup is much faster now, less or no exceptions and a much cleaner log :-) Openhab is a Java application and those exceptions are super-ugly and come with a performance penalty.

You'll notice that the bash script supports an optional 3. parmeter to distinguish between pre- and post-action and that a certain config file is touched after the renaming. touch-ing triggers a reload of that config file and this was a workaround for a bug in the tradfri-addon, the bug may have been addressed by now.

Bash: *.wav in *.mp3 konvertieren

Monday, August 13. 2012

Ganz simpel:

 

# leerzeichen in Dateinamen neutralisieren
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

for i in *.wav ; do
  echo $i
  b=`basename $i | cut -d'.' -f1`.mp3
  lame -V 1 -h $i $b 
done

IFS=$SAVEIFS
 
Das ist eher auf Qualität denn auf Geschwindigkeit / kleine Dateien getrimmt, bei Bedarf den Parameter V höher setzen. 

 

Thunderbird logging

Tuesday, May 22. 2012

 Thunderbird erlaubt ein wohl konfigurierbares Logging seiner Aktionen, hier die Doku dazu. Unter Linux /bash ist .profile ein guter Ort für die nötigen Settings, zB:

 

# das kann recht gross werden
export NSPR_LOG_FILE=/tmp/tbtrace.log
export NSPR_LOG_MODULES=SMTP:5,POP3:5,IMAP:5,nsHostResolver:4
 
 
 
 

 

command line - Schnipsel

Sunday, April 15. 2012

Kleinigkeiten, die ich immer wieder nachsuchen muss: 

Recursively rename all files containing "dings" into "bums"
for i in `find .` ; do mv $i `echo $i | sed 's/dings/bums/'` ; done 

Recursively list all files '.forward' containing string 'bin'
find -type f -name '.forward' -exec grep -H -n 'bin' {} \;

in eine Logdatei protokollieren, was ein Programm so treibt:
strace -e trace=open -o logfile.log ./xyz

umount /dev/sdc1 scheitert, weil irgendeine Datei offen ist, wer hat sie?  
fuser -m /dev/sdc1

Recursively chmod only directories
find . -type d -exec chmod 755 {} \;

Recursively chmod only files
find . -type f -exec chmod 644 {} \;

Recursively chmod only files with extension .php
find . -type f -name '*.php' -exec chmod 644 {} \;

Recursively find all files > some size
find . -type f -size +10000000k -exec ls -lh {} \;

Recursively find all files > some size named like something and delete
find . -type f -size +100000k -name access.log -exec rm -i {} \;

Password generator
openssl rand -base64 32|head -c 12;echo 

View the contents of a certificate signing request (csr)
openssl req -text -noout -in host.csr
 
View x509 certificate details
openssl x509 -in filename.crt -noout -text 
 
View the fingerprint to verify ssh goes to the right machine directly
ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key

alle an einem best Datum geaenderten Dateien auflisten:
ls -AlturR --time-style=long-iso  | grep ^.*2004\-03\-19.2.* >/home/dp/katalog_040319_2x:xx:xx.txt 

Haeufigkeit bestimmter Eintraege in messages nach Tagen sortiert ausgeben
grep DPT=1434 /var/log/messages >/var/log/SQL.slammer.txt
for i in 24 25 26 27 28; do j=`grep Jan\ $i SQL.slammer.txt -c`;echo $i, $j;done

user passwd fuer geschuetztes web-verzeichnis mit .htaccess anlegen
htpasswd -b /usr/local/httpd/.htpasswd user pass 

haessliches XML lesbar formatieren
xmllint –format ugly.xml –output pretty.xml

 

KDE clipboard history aus cli löschen
qdbus org.kde.klipper /klipper clearClipboardHistory

 

 

 

 

 

(Page 1 of 2, totaling 8 entries) » next page