Domoticz age checker

A script to check the age of sensors.
Sometimes you don’t have a good 433Mhz connection.
Or the battery has died of your sensor.

This script will warn you.

sensoragescript.sh (for cron)

#!/bin/bash
#Call as follows
#sensoragescript.sh <ipdomoticz> <idx-of-sensor> <age-to-test-in-seconds>

now=$(date +%s)
lastupdate=$(curl -s -i -H "Accept: application/json" "http://$1:8080/json.htm?type=devices&rid=$2" |  grep LastUpdate | cut -f4 -d\" )
#echo $lastupdate
seen=$(date -d "$lastupdate" +%s)
#echo $seen
#echo "$(( $now - $seen))"
difftime="$(( $now - $seen))"
if [ $difftime -gt $3 ] ; then
  echo "WARN : too old - $difftime seconds"
  exit 1
else
  echo "OK : $difftime seconds"
  exit 0
fi

Outputs:

./new.sh 192.168.1.1 123 60
OK : 22 seconds

./new.sh 192.168.1.1 123 60
WARN : too old - 69 seconds

check_mk / icinga check

#!/bin/bash
IPDOMO=192.168.1.1
IDX=123
agewarn=300
now=$(date +%s)
lastupdate=$(curl -s -i -H "Accept: application/json" "http://$IPDOMO:8080/json.htm?type=devices&rid=$IDX" |  grep LastUpdate | cut -f4 -d\" )
seen=$(date -d "$lastupdate" +%s)
difftime="$(( $now - $seen))"
if [ $difftime -gt $agewarn ] ; then
  echo "1 \"WARN - Age check Fridge\" realage=$difftime|age=$agewarn Age of fridge"
  exit 1
else
  echo "0 \"OK - Age check Fridge\" realage=$difftime|age=$agewarn Age of fridge"
  exit 0
fi

Domotemp – domoticz temperature floorplan

For my home automation i’m using Home Assistant and Domoticz.
All 433Mhz Temperature/Humidity are connected to a RFXcom device on two domoticx instances. (Master slave construction)

I’ve made a php script and a bash script to draw all sensors on a floorplan in realtime.

There is also a cron running which takes a snapshot of the generated image every 5 minutes.
These images are being converted to MP4 and animated GIF to have a timelapse with all temperatures displayed on a floorplan.

An obfuscated view of the floorplan

The circles are where sensors are placed.
Colors are from blue till red, representing the heat.
In the center is the measured temperature value.

The (shortened) PHP script: (index.php)

<?php
header('Content-type: image/png');
// This is the floorplan empty ..
$png_image = imagecreatefrompng('plattegrondenmerge.png');
$white = ImageColorAllocate($png_image, 0, 0, 0);

$max = 40;
$min = -10;

// living
// getstate is a bash script (see below which gets the values from domoticz using curl) 
// 840 is the domoticz idx
$temp840 = shell_exec('./getstate 840');
// A gray circle will be drawn if the temperature age is > 500 seconds
$age = shell_exec('./new.sh 18 840 500 >/dev/null || echo gray');
// location of circle
$start_x = 950;
$start_y = 760;
$line = $temp840 + 10;
// get x-th line from colors
$colorfromlist = shell_exec("tail --lines=$line ./colors2 | head -1");
if(strpos($age, "gray") !== false){
 $colorfromlist = "128,128,128";
};
$colors = explode(",", $colorfromlist);
$color = imagecolorallocatealpha($png_image, $colors[0], $colors[1], $colors[2], 50);
// draw circle
imagefilledellipse ($png_image, $start_x, $start_y, 175, 175, $color);
$start_x = $start_x - 70;
$start_y = $start_y + 15;
// add text
imagettftext($png_image, 24, 0, $start_x, $start_y, $white, './verdana.ttf', $temp840);

// winecellar
$temp840 = shell_exec('./getstate 839');
$age = shell_exec('./new.sh 18 839 700 >/dev/null || echo gray');
$start_x = 560;
$start_y = 840;
$line = $temp840 + 10;
$colorfromlist = shell_exec("tail --lines=$line ./colors2 | head -1");
if(strpos($age, "gray") !== false){
 $colorfromlist = "128,128,128";
};
$colors = explode(",", $colorfromlist);
$color = imagecolorallocatealpha($png_image, $colors[0], $colors[1], $colors[2], 50);
imagefilledellipse ($png_image, $start_x, $start_y, 175, 175, $color);
$start_x = $start_x - 70;
$start_y = $start_y + 15;
imagettftext($png_image, 24, 0, $start_x, $start_y, $white, './verdana.ttf', $temp840);

// ETC ETC

imagesavealpha($png_image, TRUE); 

  imagepng($png_image);
  imagedestroy($png_image);
?>


getstate bash script
(gets the temperature from domoticz instance1 given an idx)

#!/bin/bash
curl -s --connect-timeout 2 --max-time 5 "http://ip-domoticz1:8080/json.htm?type=devices&rid=$1" | egrep "Temp|Humid" | awk '{print $3 }' | cut -f1 -d\. | grep -v \" | tr -d "\n\r" | sed s/,/%\ /g | awk '{ print $2"° "$1 }'

new.sh script gets the age of the reading from
domoticz1 or domoticz1
Usage: ./new.sh <domoticz-last-numer-ip> <idx> <maxageinseconds>

#!/bin/bash
## server idx time
now=$(date +%s)
lastupdate=$(curl -s -i -H "Accept: application/json" "http://192.168.1.$1:8080/json.htm?type=devices&rid=$2" |  grep LastUpdate | cut -f4 -d\" )
#echo $lastupdate
seen=$(date -d "$lastupdate" +%s)
#echo $seen
#echo "$(( $now - $seen))"
difftime="$(( $now - $seen))"
if [ $difftime -gt $3 ] ; then
  echo "WARN : too old - $difftime seconds"
  exit 1
else
  echo "OK : $difftime seconds"
  exit 0
fi

colors2 – a list of colors representing the temperature
red -> green -> blue

255,0,0
255,10,0
255,20,0
255,30,0
255,40,0
255,60,0
255,70,0
255,80,0
255,90,0
255,100,0
255,120,0
255,130,0
255,140,0
255,150,0
255,160,0
255,180,0
255,190,0
255,200,0
255,210,0
255,220,0
255,240,0
255,250,0
253,255,0
215,255,0
176,255,0
101,255,0
62,255,0
23,255,0
0,255,16
0,255,54
0,255,131
0,255,168
0,255,208
0,255,244
0,228,255
0,196,255
0,180,255
0,164,255
0,148,255
0,132,255
0,100,255
0,84,255
0,68,255
0,50,255
0,34,255
0,2,255
0,0,255
1,0,255
2,0,255
3,0,255
5,0,255

Crontab and gif/mp4 generators

# crontab
5 * * * * root /scripts/domotemp/crontemp.sh

# crontemp.sh
# stores an image with a date.
cd /www/webdir/domotemp
wget https://mydomoticzweb/domotemp/ -O $(date +%Y%m%d%H).png >/dev/null 2>/dev/null 1>/dev/null


# rest scripts
mkdir -p embed
# below adds the time to the image
ls 2020*png | sort -n -k1 | while read ; do hour=$(echo $REPLY | cut -c9,10) ; convert -pointsize 80 -fill black -draw 'text 1650 100 '\"$hour:00\"'' -resize 960x540 $REPLY  embed/$REPLY ;done
# convert to gif
convert $(ls embed/2020*png | sort -n -k1) animation.gif
# convert to mp4
ffmpeg -f image2 -r 24 -pattern_type glob -i '*.png'   -vcodec libx264 -profile:v high444 -refs 16 -crf 0 -preset ultrafast -vf scale=1920:1080 domotemp.mp4

Making Art using 220V

I have a rol of printer paper that was used by an old 8bit computer. I forgot which one, one out of my collection.

Fractal-like ‘art’

I dont think it is thermal paper, maybe the printer uses electricity just like the movie clip you see below. (Well .. not using 220V directly on the paper maybe) 🙂

Having fun at our old place during moving to Hilversum.

3D Printing

In 2012 I started with 3D printing, I didn’t have my own yet. So it was done using shapeways.
April 2019 I ordered my own, a Creality CR-10S.

Specs

  • Build Volume: 300 x 300 x 400mm
  • Layer Thickness: 0.1-0.4mm
  • Positioning Precision: Z-axis – 0.0025mm, X & Y-axis – 0.015mm
  • Nozzle Temperature: 250°C
  • Printing Speed: 200mm/s
  • Filament Diameter: 1.75mm
  • Printer Weight: 9kg
  • Printing Filament: PLA, ABS, TPU, Wood, Carbon fiber, etc.
  • Input Support: SD card/USB
  • File Types: STL/OBJ/G-Code/JPG
  • Supports(OS): Windows/Linux/Mac/XP
  • Printing Software: Cura/Repetier-Host
  • Frame & Body: Imported V-Slot Aluminum Bearings
  • Power Requirement Input: AC110V~220V, Output: 12V, Power 270W
  • Output: DC12V, 10A 100~120W (Support storage battery)
  • Working Condition Temp:10-30°C, Humidity: 20-50%

Problem with this 3D Printer is the lack of a thermal runaway detection. My solution is a MQTT/Nodered warning system which plays an alarm and uses a shelly to disconnect the power.
https://www.henriaanstoot.nl/2022/05/11/mqtt-bash-nodered-notify/

Software I Use – see other posts

  • Openscad
  • Cura
  • Meshroom
  • Blender
  • Sketchup

Hardware

  • Octoprint on a raspberry pi – (with Octoscreen)
Octoscreen (image from internet) I’m using a faytec touchscreen monitor
  • Octoprint monitor
Little display on my desk which monitors the progress

I’m using a filament sensor like the one in below picture

It used to be a DIY thingy using an arduino. (below)

Filament under my table ( in the “dark” )

Software on my mobile

  • Octoremote
    https://play.google.com/store/apps/details?id=com.kabacon.octoremote

Hints and tips

  • Use painters tape against bending of the glass, it will warp because of the heat.
  • Use 3D spray to fix model to base-plate.
    (I used a gluestick before)
  • Always think of model placement, less support the better.
  • Try to remember which fill-in is the best for your purpose.
  • Calibrate distance print tool and glass using printing paper.
  • Know your printer, make a lot of test prints when starting.
  • Learn / read about 3D printing finishing. Sanding/smoothing/melting.
    I’ve got some smoothing liquid (print coating) , a dremel and below tool
  • Use a print model to test your leveling
    ( https://www.printables.com/model/69956-bed-level-calibration-square-grid )
  • Learn how gcode’s work!

Laser engraving using my 3D printer (pre lasercutter)

Websites

  • Yeggi
  • Thingiverse
  • printables – not that much

UPDATE 20230803

Best gap filler i found which is easily sanded down with a dremel.
Alabastine Polyester Plamuur

DDC i2c monitor control

I wanted to control the input of my monitors, these are my findings.

DDC – Display Data Channel
I2C – (Inter-Integrated Circuit, eye-squared-C), alternatively known as IIC, is a synchronous, multi-master/multi-slave (controller/target) bus

Getting monitor information with the ddccontrol -p command

##### PART OF THE OUTPUT #####
Detected monitors :
 - Device: dev:/dev/i2c-9
   DDC/CI supported: Yes
   Monitor Name: VESA standard monitor
   Input type: Digital
  (Automatically selected)
 - Device: dev:/dev/i2c-7
   DDC/CI supported: Yes
   Monitor Name: VESA standard monitor
   Input type: Digital
 - Device: dev:/dev/i2c-6
   DDC/CI supported: Yes
   Monitor Name: VESA standard monitor
   Input type: Digital
Reading EDID and initializing DDC/CI at bus dev:/dev/i2c-9...
I/O warning : failed to load external entity "/usr/share/ddccontrol-db/monitor/AOC2490.xml"

Switching inputs

ddcutil -b 7 setvcp 0x60 0x11 # 7 is Second monitor (starts with 6), 0x60 is the input register (see below) and 0x11 is HDMI
ddcutil -b 6 setvcp 0x60 0x0f # First monitor DP (Displaylink)

alternative command

ddccontrol -r 0x60 -w 15 dev:/dev/i2c-7

List the control registers

ddccontrol -d dev:/dev/i2c-6
ddccontrol version 0.6.0
Copyright 2004-2005 Oleg I. Vdovikin (oleg@cs.msu.su)
Copyright 2004-2006 Nicolas Boichat (nicolas@boichat.ch)
This program comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of this program under the terms of the GNU General Public License.

Reading EDID and initializing DDC/CI at bus dev:/dev/i2c-6...
I/O warning : failed to load external entity "/usr/share/ddccontrol-db/monitor/AOC2490.xml"
Document not parsed successfully.

EDID readings:
	Plug and Play ID: AOC2490 [VESA standard monitor]
	Input type: Analog
=============================== WARNING ===============================
There is no support for your monitor in the database, but ddccontrol is
using a basic generic profile. Many controls will not be supported, and
some controls may not work as expected.
Please update ddccontrol-db, or, if you are already using the latest
version, please send the output of the following command to
ddccontrol-users@lists.sourceforge.net:

LANG= LC_ALL= ddccontrol -p -c -d

Thank you.
=============================== WARNING ===============================

Controls (valid/current/max) [Description - Value name]:
Control 0x02: +/1/2 C [New Control Value - No changes]
Control 0x04: +/0/1 C [Restore Factory Defaults]
Control 0x05: +/0/1 C [Restore Brightness and Contrast]
Control 0x08: +/0/1 C [Restore Factory Default Color]
Control 0x10: +/90/100 C [Brightness]
Control 0x12: +/50/100 C [Contrast]
Control 0x14: +/5/13 C [???]
Control 0x16: +/50/100 C [Red maximum level]
Control 0x18: +/50/100 C [Green maximum level]
Control 0x1a: +/50/100 C [Blue maximum level]
Control 0x60: +/772/4 C [Input Source Select (Main)]
Control 0x62: +/17/100 C [Audio Speaker Volume Adjust]
Control 0x6c: +/50/100 C [Red minimum level]
Control 0x6e: +/50/100 C [Green minimum level]
Control 0x70: +/50/100 C [Blue minimum level]
Control 0xac: +/6750/65535   [???]
Control 0xae: +/6000/65535   [???]
Control 0xb2: +/1/8   [???]
Control 0xb6: +/3/8 C [???]
Control 0xc8: +/5/65302 C [???]
Control 0xc9: +/8/65535 C [???]
Control 0xcc: +/4/255   [???]
Control 0xd6: +/1/4 C [DPMS Control - On]
Control 0xdf: +/513/65535 C [???]
Control 0xfe: +/4/255   [???]

Setting volume (reg 0x62) of monitor 2

ddcutil -b 7 setvcp 0x62 0x01

AOC monitor PROBLEM

You can’t switch from an input which is not active!
So my workstation is connected via DP, and i can switch to HDMI.
Now i HAVE TO use the hdmi to switch back to DP.
A solution could be to ssh into the machine connected with HDMI (passwordless login) and switch back to DP.
I made a mqtt button sending a topic that was read by the two machines using the mqtt python program elsewhere on this site.
(Rotary Mqtt Volume control)

gddccontrol

Colleage at work brings a Freecom Internet Radio

Big mistake 😉 It a Linux ARM system with Busybox

Less do some searching on the web.
Ah .. enable telnet

Open in a browser:

http://192.168.1.x/admin/cgi-bin/debug.cgi

I was controlling my colleage’s music from the next room

Enable telnet:

Connect and install Pong:

telnet 192.168.1.x (username root)
# wget http://agilo.acjs.net/files/mppong/setup.sh
# chmod 755 setup.sh
# ./setup.sh
# ./start.sh
# ./start.sh musicpal # For the normal player

Links i have to look into:
https://www.qemu.org/docs/master/system/arm/musicpal.html

Garbage display

I wanted to know when trash is being collected. So i made a dual led thingy.

Version without lid .. just to test

When we lived in Utrecht, the website which mentions when, what is collected was easy .. like a API

We live in Hilversum now, so i had to write a scraper.

UPDATE : Script not working anymore. Site has been changed, and I’m not willing to run a headless browser (phantomjs) to scrape the info

See below my new solution

Script to set leds

#!/bin/bash
set -x

if [[ $# -eq 0 ]] ; then
curl  http://10.1.0.46/control?cmd=NeoPixel,1,0,0,0
curl  http://10.1.0.46/control?cmd=NeoPixel,2,0,0,0
exit 0
fi


set -x
if [ $1 = "GFT" ] ;then led1="150,0,0" ;fi
if [ $1 = "Rest" ] ;then led1="150,150,150" ;fi
if [ $1 = "Paper" ] ;then led1="0,0,150" ;fi
if [ $1 = "Plastic" ] ;then led1="75,191,0" ;fi
if [ $1 = "Textiel" ] ;then led1="191,191,191" ;fi
if [ $1 = "Kerstbomen" ] ;then led1="191,0,0" ;fi

if [ "w$2" = "wgft" ] ;then led2="255,0,0" ;fi
if [ "w$2" = "wRest" ] ;then led2="150,150,150" ;fi
if [ "w$2" = "wpapier" ] ;then led2="0,0,255" ;fi
if [ "w$2" = "wplastic" ] ;then led2="100,255,0" ;fi
if [ "w$2" = "wTextiel" ] ;then led2="191,191,191" ;fi
if [ "w$2" = "wKerstbomen" ] ;then led2="191,0,0" ;fi

if [[ $# -eq 1 ]] ; then
led2=$led1
fi
curl  http://10.1.0.46/control?cmd=NeoPixel,1,$led1
curl  http://10.1.0.46/control?cmd=NeoPixel,2,$led2

Scraper ( calls setleds and mqtt )

#!/bin/bash
cd /home/pi/
./afvalleds
curl -s https://inzamelkalender.gad.nl/adres/1222HP:39 > /tmp/afvalcurl
today=$(date +%F)
tomorrow=$(date --date="next day" +%F)
for f in petfles-blik-drankpak-pmd.svg appel-gft.svg kliko-grijs-rest.svg doos-karton-papier.svg shirt-textiel.svg kerstboom.svg ; do
p1=$(cat /tmp/afvalcurl | grep -i  -A2 "$f" | grep class | cut -f2 -d\> | cut -f1 -d\< | cut -f2- -d" ")
p2=$(echo $p1 | sed s/mei/may/g | sed s/okt/oct/g )
p3=$(date --date="$p2" +%F)
dater=$p3
now=$(date -d $(date --date="1 days ago" +%F) +%s)
p3epoch=$(date --date="$p3" +%s)
diff=$(expr $p3epoch - $now)
if [ $diff -lt 0 ] ; then
                dater=$(date -d "$p3 1 year" +%F)
fi
whatdate=$(echo $f | sed s/petfles-blik-drankpak-pmd.svg/Plastic/g |sed s/appel-gft.svg/GFT/g | sed s/kliko-grijs-rest.svg/Rest/g | sed s/doos-karton-papier.svg/Paper/g | sed s/shirt-textiel.svg/Textiel/g | sed s/kerstboom.svg/Kerstbomen/g)
mosquitto_pub -h 127.0.0.1 -p 1883 -t "afvalwijzer/$whatdate" -m "$dater"
if [ "w$today" == "w$dater" ]; then
alltoday="$alltoday $whatdate"
fi
if [ "w$tomorrow" == "w$dater" ]; then
alltomorrow="$alltomorrow $whatdate"
fi
done
mosquitto_pub -h 127.0.0.1 -p 1883 -t "afvalwijzer/Today" -m "$alltoday"
mosquitto_pub -h 127.0.0.1 -p 1883 -t "afvalwijzer/Tomorrow" -m "$alltomorrow"
./afvalleds $alltomorrow

Utrecht scraper

#!/bin/bash
set -x
curl -s "http://json.mijnafvalwijzer.nl/?method=postcodecheck&postcode=3543eh&huisnummer=72&" > /tmp/afv
cat /tmp/afv | python -mjson.tool > /tmp/afv.json
today=$(cat /tmp/afv.json | grep -A1 $(date +%Y-%m-%d) | grep nameType | cut -f4 -d\" | paste -sd "/" -)
today=$(echo $today | sed s/\ /,/g)

tomorrow=$(cat /tmp/afv.json | grep -A1 $(date -d "+1 days" +%Y-%m-%d) | grep nameType | cut -f4 -d\" | paste -sd "/" -)
tomorrow=$(echo  $tomorrow" | sed s/\ /,/g)

cat /tmp/afv.json | grep -B1 nameType | grep -B1 gft | cut -f4 -d\" | grep 202 > /tmp/gft.afv
cat /tmp/afv.json | grep -B1 nameType | grep -B1 papier | cut -f4 -d\" | grep 202 > /tmp/papier.afv
cat /tmp/afv.json | grep -B1 nameType | grep -B1 plastic | cut -f4 -d\" | grep 202 > /tmp/plastic.afv
cat /tmp/afv.json | grep -B1 nameType | grep -B1 kerst | cut -f4 -d\" | grep 202 > /tmp/kerst.afv
(
(
for f in $(seq 1 31) ; do
 dater=$(date -d "+$f days" +%Y-%m-%d)
 grep $dater /tmp/gft.afv > /dev/null &&  echo "$dater GFT" | head -1
done ) | head -1

(
for f in $(seq 1 31) ; do
 dater=$(date -d "+$f days" +%Y-%m-%d)
 grep $dater /tmp/papier.afv > /dev/null && echo "$dater Papier"  | head -1
done ) | head -1

(
for f in $(seq 1 31) ; do
 dater=$(date -d "+$f days" +%Y-%m-%d)
 grep $dater /tmp/plastic.afv > /dev/null && echo "$dater Plastic"  | head -1
done ) | head -1

(
for f in $(seq 1 31) ; do
 dater=$(date -d "+$f days" +%Y-%m-%d)
 grep $dater /tmp/kerst.afv > /dev/null && echo "$dater Kerstboom"  | head -1
done ) | head -1

) | sort -n -k1 | sed s/\ /,/g > /tmp/afv.sorted
gft=$(cat /tmp/afv.sorted | grep GFT | cut -f1 -d,)
papier=$(cat /tmp/afv.sorted | grep Papier | cut -f1 -d,)
plastic=$(cat /tmp/afv.sorted | grep Plastic | cut -f1 -d,)

mosquitto_pub -h 127.0.0.1 -p 1883 -t "afvalwijzer/Today" -m "$today " 
mosquitto_pub -h 127.0.0.1 -p 1883 -t "afvalwijzer/Tomorrow" -m "$tomorrow " 
mosquitto_pub -h 127.0.0.1 -p 1883 -t "afvalwijzer/Papier" -m "$papier" 
mosquitto_pub -h 127.0.0.1 -p 1883 -t "afvalwijzer/GFT" -m "$gft" 
mosquitto_pub -h 127.0.0.1 -p 1883 -t "afvalwijzer/Plastic" -m "$plastic" 

Update new solution

My home assistant has a hacs addon installed which does the heavy lifting for me.
Why not use this info?

I wrote about NR and HA here

So getting the info for NR to parse:

I only need to use the lightblue node bottom right!

It is the current state node, inject a timestamp every day to get new values.
Parse this and send using Mqtt to my Led display thingy

Old phones, organisers and gadgets

Old ones

  • Ericsson PF768?
  • One in between ?? with fancy wood cover
  • Nokia 7110 (Symbian)
  • Nokia 7650 (Symbian 6)
  • Nokia 6630 (Symbian  8)
This is not the one .. but simular .. still looking if i can find this one

Playing around with these i made a :

  • MMS server
  • Wap server
  • SMS gateway
  • Netsaint ( pre check_mk/icinga/nagios ) web thingy

Androids

  • G1 – First android phone (2009)
  • HTC Desire Z (2011)
  • Nexus (2013)
  • OnePlusOne (2015)
  • Realme (2019)
G1, HTC, Nexus and OnePlusOne
Current phone

Work phones

  • ??
  • Iphone for work ( stopped using this crap )
    • (funny story, got more for cheap to embed in my flightsim dash)
  • Sony Xperia XZ for work

Organizers

  • Multiple sharps
  • Xircom Rex
  • Sharp Zaurus SL-5500 (Linux)
  • Nokia 770

Organizing programs

  • Hyper (dos) – hyplus.exe (1989)
  • Twiki/Foswiki
  • Google docs
  • Joplin (Current)

"If something is worth doing, it's worth overdoing."