Tuesday, August 31, 2021

Re-publish RF433 data from a weather station to MQTT with an SDR USB dongle

Thanks to a 433MHz USB dongle and some folks on the web who wrote nice tools, it is pretty easy to collect and interpret the radio data send from my 60€ Aliexpress weather station to its base station, and re-publish them on a MQTT broker.

Oh, and it runs on a sngle-board computer like a Raspberry, a Beagle Bone or an Orange PI.

We need rtl-sdr to talk to the SDR USB radio, and rtl_433 to interpret and publish it as MQTT (it even knows already about the data format for this weather station).

Friday, August 27, 2021

NGINX configuration block to run any fastcgi bash, perl, python scripts


NGINX configuration block to run fastcgi scripts by their shebangs

This configuration will use the shebang at the start of the script to select the proper interpreter.

''
LOCKFILE=/var/lock/$(basename $0).lock
[ -f $LOCKFILE ] && exit 0
trap "{ rc=$?; rm -f $LOCKFILE ; exit $rc; }" EXIT
touch $LOCKFILE
''

''I had to be able to run bash, perl and other kinds of CGI programs but found it difficult to gather all the bits on nginx + fastcgi.

Do not forget to install ''apt install fcgiwrap'' for the generic tool, not the one for PHP.

''
# Bash, perl ... CGI scripts
# Make sure to allow them in this setting of /etc/php/*/fpm/pool.d/www.conf:
#    security.limit_extensions = .sh .py .pl .cgi .exe .php
location ~ ^/cgi.*(\.cgi|\.py|\.sh|\.pl)$ {
root /home/www/cgi-bin;
# Check if CGI script exists
fastcgi_split_path_info ^(.+?\.sh)(/.*)$;
try_files $fastcgi_script_name =404;
# Remove /cgi-bin/ or /cgi/ prefix in path
rewrite ^/cgi(-bin)?/(.*) /$2 break;
# Set parameters
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME /home/www/cgi-bin$fastcgi_script_name;
# apt install fcgiwrap
fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
''

Here is a minimalist example of a CGI script made with bash. Just do not forget to return proper HTTP data else you will end up with an error that tells ''upstream prematurely closed FastCGI stdout while reading response header from upstream''):

''
#!/bin/bash
printf "HTTP/1.0 200 OK\r\n"
printf "Content-type: text/plain\r\n\r\n"

printenv | grep ^HTTP_ 

echo "Query string is $QUERY_STRING"
''

Monday, August 9, 2021

Open Web Analytics for Dokuwiki

Customized PHP header for Open Web Analytics best suited to dokuwiki :



''<?php
$actionkind=@$_GET['do'];
if($actionkind=='') $actionkind='page';
if($actionkind=='page' || $actionkind=='search') {
        require_once('/var/www/stats.mysite.com/owa_php.php');
        $owa = new owa_php();
        $owa->setSiteId('4bda91f72a70c48a2ad1d6cdc11523af');
        $owa->setPageTitle(tpl_pagetitle(null,true));
        $owa->setPageType($actionkind);
//      if(@$_GET['q']!="") $owa->setSearchTerms(@$_GET['q']);
        // Set other page properties
        //$owa->setProperty('foo', 'bar');
        $owa->trackPageView();
}
?>''

It helps sorts the collected data and avoids logging administrative accesses. Note that I did not investigate further to make the "search terms" work Dokuwiki ''q'' argument.

Wednesday, August 4, 2021

Profile gcc code and produce a graphical tree

Obviously compile with profile, then use ''gprof'' and ''dot'':

''

gprof myprog.bin | gprof2dot.py -s | dot -Tpng -o profiler.png && gwenview profiler.png

''

Saturday, April 24, 2021

Simple MQTT handler in bash

How to subscribe to an MQTT topic efficiently in bash.

This is hosted on a Raspberry Pi which controls a pool pump via a solid state relay on GPIO 4, and these topics :

  • /pool/pump/action 0  # Command, set externally (subscribed)
  • /pool/pump/state  1  # Feedback state (published)


''

#!/bin/bash -feu
set -o pipefail

mqtt()
{
action="$1"
shift
"mosquitto_${action}" -h 192.168.1.1 -p 8833 -t "$@"
}

handler()
{
new_state=$(echo "$1" | sed 's/[^01]//g')
[[ -z "$new_state" ]] && new_state="0"

if /usr/local/bin/gpio_out.sh 4 "$new_state"; then
echo "pump state change OK, now $new_state"
else
echo "ERROR: pump state change fail towards $new_state"
fi

# Ping back
real_state=$(cat /sys/class/gpio/gpio4/value)
mqtt pub '/pool/pump/state' -m "$real_state" -r
}

export -f mqtt
export -f handler


action={1-}
cfg=$(basename $0 .sh).service
if [[ $action = 'stop' ]]; then
systemctl stop $cfg

elif [[ $action = 'start' ]]; then
systemctl restart $cfg

elif [[ $action = 'install' ]]; then

cat > /etc/systemd/system/$cfg << EOF
[Install]
WantedBy=multi-user.target
[Service]
Restart=always
RestartSec=3
ExecStart=$(realpath $0)
#Type=simple
#Restart=on-failure
EOF

systemctl daemon-reload &&
systemctl restart $cfg &&
systemctl enable $cfg

else # here is the deal

# Run only once
LOCK_FILE="/var/lock/$(basename $0 .sh).lock"
exec 9> "$LOCK_FILE" && flock -n 9 || exit 5
trap "rm -f '$LOCK_FILE'; logger 'Stopped $0 watcher on $(date)'" EXIT
logger "Started $0 watcher on $(date)"

# Wait for orders
mqtt sub '/pool/pump/action' |\
xargs -n 1 -I {} /bin/bash -c 'handler "$@"' _ {}

fi

''

This small script embeds its own ''systemd'' config, just run it with ''install' as the sole parameter.

Wednesday, March 3, 2021

Install CH552 support for platformio (and CH5xx variants) with ch5xduino support

https://community.platformio.org/t/platformio-8051-model-medium-linker-err/18099

''
mkdir ~/.platformio/boards
cd ~/.platformio/boards
cat > ch55xduino.json << 'EOF'
{
  "build": {    
    "f_cpu": "24000000",
    "size_iram": 256,
    "size_xram": 1024,
    "size_code": 14336,
    "size_heap": 128,
    "mcu": "ch552t",
    "cpu": "mcs51"
  },
  "frameworks": [],
  "upload": {
    "maximum_ram_size": 1280,
    "maximum_size": 14336,
    "protocol": "stcgal",
    "stcgal_protocol": "stc15",
    "protocols": [
      "stcgal"
    ]
  },
  "name": "Generic CH552",
  "url": "http://www.wch.cn/product/CH552.html",
  "vendor": "WCH"
}
EOF

platformio boards|grep ch5xduino
cd
mkdir myproj552
cd myproj552
platformio init --board ch55xduino

cat > platformio.ini <<'EOF'
[env:ch552]
platform = intel_mcs51
board = ch552
build_flags =
  --model-medium
  --LC:/Users/caoyf/.platformio/packages/toolchain-sdcc/lib/medium
  -IC:
  -IC:/Users/caoyf/Documents/PlatformIO/Projects/ch552_gpio/src/Driver/inc
  -Isrc/PLAT/inc

extra_scripts = link_medium.py
'EOF'

cat > link_medium.py
Import("env")
env.Append(LINKFLAGS=["--model-medium"])

''