Archive for the ‘Scripts’ Category

Compiling a kernel module on and for the raspberry pi

Wednesday, May 18th, 2016

So in order to compile a module for a precompiled version of the raspberry pi linux kernel, some quirks were necessary. The goal was to not build the kernel fully (which is also possible after these steps) but to rebuild a module for the currently running kernel after modifying its source.

If you have seen

Error: could not insert module drivers/w1/slaves/w1_therm.ko: Invalid module format

while trying to insmod and

[ 5697.914596] w1_therm: no symbol version for module_layout

in dmesg or

ERROR: could not insert 'w1_therm': Exec format error

after modprobe, then stick around.

My script with explanations is available over at

https://github.com/x29a/kernel/blob/master/rpi/prepare.sh

so hopefully all that needs to be done on the rpi is (as root, sudo -i)

# mkdir -p /root/kernel
# cd /root/kernel
# wget https://raw.githubusercontent.com/x29a/kernel/master/rpi/prepare.sh

then check if the defaults in the script are fine for you, like location for source and kernel branch, then execute

# bash prepare.sh

and follow the instructions. Each new message expects a keypress to continue.

Following is some additional info i found handy on my journey to a loadable module.

If you have used rpi-update by accident and got on an experimental kernel (remember, new kernels are now installed via apt-get!) you can revert to a stock kernel by forcing a reinstall via

apt-get install --reinstall raspberry-bootloader

When is Module.symvers generated.

How to get the right kernel version for a running setup without recompiling kernel.

Crosscompile a kernel module.

General information on building the rpi kernel and general kernel module building and contribution infos.

Hacking the Withings WiFi Body Scale

Sunday, April 14th, 2013

Keeping track of weight development just got a lot easier, now that scales like the “Wifi Body Scale” by Withings (available at e.g. Amazon) can post their measurements via Wifi.

Unfortunately, the scales post their results to the webpage of the manufacturer, which some people are not comfortable with. Fortunately, the communication is unencrypted and easy understandable (JSON based).

Other folks have paved the way by analyzing the protocol. The general approach stays the same

  1. Pair the scales via the instructions (need an account at my.withings.com) with the wifi network
  2. Redirect the DNS requests from the scales to your own server
  3. Setup some script which simulates a Withings server
  4. Communicate!
  5. Do something with the data

1. Pairing
There are different models that have different pairing approaches, consult the FAQ for additional information. The document also provides information on error codes and how to reset the device (or perform firmware updates).

UPDATE: Withings now uses Zendesk for support information.

2. DNS Spoofing
In order to redirect the requests from the device, many ways lead to Rome. Depending on your network configuration, you could use dnsmasq on your router and configure it to respond with a modified ip via:

address=/withings.net/10.0.0.5
address=/withings.com/10.0.0.5

where 10.0.0.5 is the ip of your own server. While the WebGUI is hosted at withings.com, the scales try to communicate with scalews.withings.net. Both resolve to ‘89.30.121.150’. If you have your own bind service running, configure a zone for the withings domains.

3. Server
Now that the scales talk to your webserver at 10.0.0.5, the conversation has to be performed. “Prox” wrote a python script, while “sd” (german) used PHP.

The configuration of the webserver might have to be changed in order to redirect the requests from

  • /cgi-bin/once
  • /cgi-bin/session
  • /cgi-bin/maint
  • /cgi-bin/measure

to your own script. Running nginx, add the following to your server configuration

# allow POST requests to static content
error_page 405 = $uri;

# redirect withings scale requests
location /cgi-bin {
rewrite ^/cgi-bin/(.*)$ /withings/index.php?s=$1;
}

and the requests will be forwared to the PHP script “index.php” at /withings on your webserver.

4. The communication
The communication consists of 5 Steps and is handled via POST requests containing JSON data

  1. Request to /cgi-bin/once:

    POST: Array
    (
    [action] => get
    )

    Response:
    {
    "status": 0,
    "body": {
    "once": "87a6549c-93f7bce8"
    }
    }

    Remarks:
    – status 0 means no error (query the withings service to get some error codes like 2554)
    – the once UID can be random 8 chars, dash, 8 chars

  2. Request to /cgi-bin/session:

    POST: Array
    (
    [action] => new
    [auth] => 00:00:be:ef:00:07
    [hash] => e26b6c7dcb05ac46bde912d2bc951d83
    [mfgid] => 114700
    [currentfw] => 79
    [batterylvl] => 100
    [duration] => 30
    [zreboot] => 0
    )

    Response:
    {
    "status": 0,
    "body": {
    "sessionid": "7bf5-382a9b74-183dcfe5",
    "sp": {
    "users": [
    {
    "id": 5555,
    "sn": "BEN",
    "wt": 80,
    "ht": 1.75,
    "agt": 23.4,
    "sx": 0,
    "fm": 131,
    "cr": 1365963066,
    "att": 0
    },
    {
    "id": 6666,
    "sn": "SEN",
    "wt": 80,
    "ht": 1.75,
    "agt": 42,
    "sx": 1,
    "fm": 131,
    "cr": 1365963066,
    "att": 0
    }
    ]
    },
    "ind": {
    "lg": "en_US",
    "imt": 1,
    "stp": 1,
    "f": 2,
    "g": 98124
    },
    "syp": {
    "utc": 1365974415
    },
    "ctp": {
    "goff": 7200,
    "dst": 0,
    "ngoff": 0
    }
    }
    }

    Remarks:
    – auth in request: MAC address of scales (can be found in the battery compartment)
    – response: list of user profiles, scale settings and time information

    “id”: numeric id for user
    “sn”:” three chars displayed in the scales (usernick)
    “wt”: weight in kilograms, used for identification
    “ht”: height of user in meters
    “agt”: age in years
    “sx”: sex of user (0: male, 1: female)
    “fm”: unknown
    “cr”: timestamp of last measurement or account creation
    “att”: unkown
    lg”: language, like “en_US” or “en_GB”
    “imt”: perform induction measurement (0: off, 1: on)
    “stp”: 1 (unknown)
    “f”: autocalibrate mode (0: measure directly, 2: calibrate via tap before measuring)
    “g”: value for gravity (98124). This highly influences the weight result!
    “utc”: current UNIX timestamp}
    goff”: unkown
    “dst”:0 (DST switch?)
    “ngoff”: unkown

  3. Request to /cgi-bin/maint:

    POST: Array
    (
    [action] => store
    [sessionid] => 7bf5-382a9b74-183dcfe5
    [source] => 1
    [type] => 2
    [data] => [WDEBUG] dac: 1419 1508 1638 1791
    [WDEBUG] adc: 21800 21500 21900 21800
    )

    Response:
    {
    "status": 0
    }

    Remarks:
    – Maintenance values (seem like raw values from ADC and DAC)
    – Response from real server is much longer, but since its not needed for now, status: 0 should be enough

  4. Request to /cgi-bin/measure:

    POST: Array
    (
    [action] => store
    [sessionid] => 7bf5-382a9b74-183dcfe5
    [macaddress] => 00:00:be:ef:00:07
    [userid] => 5555
    [meastime] => 1365974385
    [devtype] => 1
    [attribstatus] => 0
    [measures] => {“measures”:[{“value”:80050,”type”:1,”unit”:-3},{“value”:239,”type”:16,”unit”:0}]}
    )

    Response:
    {
    "status": 0
    }

    Remarks:
    – Measurement from scales, type: 1 seems like weight
    – Response from server is just the usual “ACK”

  5. Another request to /cgi-bin/maint, ignored for now.
  6. Request to /cgi-bin/session:

    POST: Array
    (
    [action] => delete
    [sessionid] => 7bf5-382a9b74-183dcfe5
    )

    Response:
    {
    "status": 0
    }

    Remarks:
    – Logoff from service
    – Response from server is just the usual “ACK”

5. The data
Since the device can buffer some measurements, it can happen that multiple results are transfered at once.

Once the data is saved, its up to you how to analyze it. More to come (like my index.php).

Simple script for changing wallpaper using RSS feed

Monday, July 16th, 2012

Just had the idea to change the wallpaper of my desk according to an RSS feed.

Here’s the shellscript:

#!/bin/sh
 
IMGPATH="/home/chris/Pictures/Wallpapers/factsandchicks"
IMGURL=$(wget -q -O- "http://www.factsandchicks.com/rss" | grep -o 'src="[^"]*' | grep -m 1 -o '[^"]*$')
LOCALFILENAME=$(echo $IMGPATH/$(date +"%Y%m%d").jpg)
 
wget -q -O$LOCALFILENAME $IMGURL
 
gsettings set org.gnome.desktop.background picture-uri file:///$LOCALFILENAME

For this example, I used the RSS feed from factsandchicks.com (o.O)
The command in the last line depends on your distribution, this one works for newer Ubuntus. You probably want to run this script via cron or rc.local to get the new wallpapers regularly.

Have fun!

UCF Filetype for Geany

Saturday, June 30th, 2012

Geany is currently my favorite graphical editor. Soon, I was missing a syntax highlighting for UCF (user constraints file) files and recently I was motivated to create an UCF Filetype.

I built it according to the information in the Geany Manual, and here it is (sorry for the horrible formatting, but some stuff has to be in one single line):

# For complete documentation of this file, please see Geany's main documentation [styling] 
# foreground;background;bold;italic 
default=default 
comment=comment 
number=number 
word=keyword 
word2=keyword2 
string=string 
preprocessor=preprocessor
 
[keywords] # all items must be in one line 
primary=AREA_GROUP ASYNC_REG BEL BLKNM BUFG COLLAPSE COMPGRP CONFIG CONFIG_MODE COOL_CLK DATA_GATE DCI_VALUE DISABLE DROP_SPEC ENABLE FEEDBACK FILE FLOAT FROM HBLKNM HU_SET IN INREG IOB IOBDELAY IOSTANDARD KEEP KEEP_HIERARCHY KEEPER LOC LOCATE LOCK_PIN MAP MAXDELAY MAXPT MAXSKEW NET NODELAY NOREDUCE OFFSET OPEN_DREIN OPT_EFFORT OPTIMIZE OUT PERIOD PIN PRIORITY PROHIBIT PWR_MODE REG RLOC RLOC_ORIGIN RLOC_RANGE SCHMITT_TRIGGER SLEW SYSTEM_JITTER TEMPERATURE THRU TIG TIMEGRP TIMESPEC TNM TO TPSYNC TPTHRU U_SET USE_RLOC USELOWSKEWLINES VFEF VOLTAGE WIREAND XBLKNM 
secondary=COMPRESSION DATAPATHONLY GROUP IMPLEMENT INST MODE PLACE RANGE ROUTE TNM_NET AFTER BEFORE DRIVE FALLING FAST HIGH NOT PULLDOWN PULLUP RISING SLOW 
#docComment=
 
[settings] 
# Vala uses the C lexer
lexer_filetype=C
tag_parser=Python
 
# default extension used when saving files
extension=ucf
 
# the following characters are these which a "word" can contains, see documentation 
#wordchars=_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
 
# if only single comment char is supported like 
# in this file, leave comment_close blank 
comment_single=#

Create the file ~/.config/geany/filedefs/filetypes.ucf.conf and insert the text above.

Then open Geany and insert the following line to filetypes_extensions.conf (Tools -> Configuration Files)

ucf=*.ucf;

Now, Geany should do some basic but useful syntax highlighting for ucf files!