Skip to main content leehalls.net

Raspberry Pi Snippets & Code Info

Various code examples & notes for the raspberry pi


UPDATE: [2024-11-18 Mon] These all were relevant when the RPi first arrived, given all the changes, updates etc some may no longer work but I leave them here as a reference


Various things i’ve found useful for my projects using raspberry pi’s, covers things from turning the red light off on the camera to kiosk mode for Chrome. Most of these were initially done under Raspbian - Jessie and may not work uner the latest Buster.

Everything here can be downloaded in the original org-mode format: Snippets of code because of the way hugo interprets org files i’ve had to save it with a txt extension for the link to work. If you want to view the file in emacs/org then simply change the extension to org instead of txt or copy and paste.

Working with files

  • read csv and create an array variable

    So the following tries to open a csv file and store in the array SensorValues the contents of each row, if it fails to open the file it simply stores an arbitrary value

    python code snippet start

    # read in stored values & initialise preset values
    import csv
    try:
        with open('/tmp/tmpvalues.csv', 'r') as csvfile:
            fileRead = csv.reader(csvfile, delimiter=',')
            for row in fileRead:
                SensorValues = [float(x) for x in row if x != '']
    except:
        SensorValues = (
            66.00,
            66.00,
            66.00,
            66.00,
            66.00,
            66.00,
            66.00,
            66.00,
            66.00,
            66.00)

    python code snippet end

  • credential file

    If you dont want to store your login details in a python script, for example if you want to share that script you dont want to give people you password do you? So you can create a file credentials file eg

    emacs -nw credentials.py

    Then type in the following;

    python code snippet start

    # email login details
    em_login = {
        'smtpdata': 'smtp.server.address',
        'login': 'login.address',
        'password': 'login.password',
        'toemail': 'send.to.email.address'
    }
    # initial state details
    in_login = {
        'login': 'login.address',
        'password': 'login.password',
        'accesskey': 'access.key',
        'bucketname': 'monitorhome',
        'bucketkey': 'bucket.key'
    }

    python code snippet end

    now call this file as a module in the main code and assign to your chosen variable

    python code snippet start

    import credentials
    
    empassword = credentials.em_login['password']
    inpassword = credentials.in_login['password']
    
    print("email password:", empassword)
    print("initial password:", inpassword)

    python code snippet end

  • convert windows CR (carriage returns) to linux

    sed -i 's/\r//' filename

    Use with care it could destroy your file, it might be better to the dos2unix utility

PiDisplay

Notes on using the offical pi touch screen

  • rotate official display

    Useful if the display case you’ve bought has a fixed orientation;

    edit your /boot/config.txt file, and add the following line:

    lcd_rotate=2

  • onscreen keyboard

    You can install an onscreen keyboard by;

    sudo apt-get install florence

    or

    sudo apt-get install matchbox-keyboard

    then reboot, to access the keyboard click on menu/accessories/keyboard

  • get backlight status

    Weirdly (at least i think so) it’s 0 for on and 1 for off and script must be run as root

    python code snippet start

    #!/usr/bin/env python3
    # gets current backlight state
    file=open('/sys/devices/platform/rpi_backlight/backlight/rpi_backlight/bl_power','r+')
    current_status=int(file.read(1))
    
    print(current_status)

    python code snippet end

  • kiosk mode

    Kiosk mode runs your internet browser full screen useful for setting up a display system. Modify the /etc/xdg/lxsession/LXDE/autostart file or if using the NOOBS installation /etc/xdg/lxsession/LXDE-pi/autostart

    bash code snippet start

    @lxpanel --profile LXDE-pi
    @pcmanfm --desktop --profile LXDE-pi
    @xscreensaver -no-splash
    @point-rpi
    
    @xset s noblank
    @xset s off
    @xset -dpms
    
    @chromium-browser --noerrdialogs --kiosk http://127.0.0.1:5000 --incognito --disable-translate

    bash code snippet end

    BE AWARE if the following file exists then it overrides any other files so the @chromium command must go in here.

    nano .config/lxsession/LXDE-pi/autostart

    so edit it to show the line;

    @chromium-browser --noerrdialogs --kiosk http://127.0.0.1:5000 --incognito --disable-translate

    so my file reads;

    bash code snippet start

    @lxpanel --profile LXDE-pi
    @pcmanfm --desktop --profile LXDE-pi
    @xscreensaver -no-splash
    @point-rpi
    @chromium-browser --noerrdialogs --kiosk http://127.0.0.1:5000 --incognito --disable-translate

    bash code snippet end

Audio

  • Enabling Audio Output

    By default, the RPi audio output is set to automatically select the digital HDMI interface if its being used, otherwise the analog audio output. You can force it to use a specific interface via the sound mixer controls. amixer allows command-line control of the mixer for the ALSA driver.

    You can force the RPi to use a specific interface using the command amixer cset numid=3 N where the N parameter means the following:

    • 0=auto
    • 1=analog
    • 2=hdmi

    Therefore, to force the Raspberry Pi to use the analog output:

    amixer cset numid=3 1

  • How to play Internet radio on your Raspberry PI (mpd/mpc)

    first make sure your audio is working, using the ALSA package

    install the mpd and mpc packages:

    sudo apt-get install mpd mpc

    change the permissions of mpd (just to make sure):

    sudo service mpd stop sudo chmod -R g+w /var/lib/mpd sudo chmod -R g+w /var/run/mpd

    make a change to the mpd config file /etc/mpd.conf

    sudo nano /etc/mpd.conf

    Note all the sites i visited suggested that it was simply commenting OUT the line:

    bind_to_address "localhost"

    however i had many issues and nothing seemed to work until i had the conf file set as follows;

    shell code snippet start

    # bind_to_address "localhost"
    bind_to_address "127.0.0.1"
    port "6600"

    shell code snippet end

    shutdown/reboot your Raspberry PI after it’s up and running again add an Internet radio URL, for instance:

    • mpc add http://icecast.omroep.nl/3fm-bb-mp3

    to start playing the stream type:

    • mpc play

    The other thing to be aware of is you may need to download the radio stations m3u playlist file and open it to extract the direct URL of the stream (i had to) so the stream i needed was;

    http://stream4.nadaje.com:11986/prs

    then save that into MY OWN m3u playlist for for the MPD daemon to work.

  • python check if mpc is playing

    python code snippet start

    from mpd import MPDClient
    
    client=MPDClient()
    client.idletimeout = None          # timeout for fetching the result of the idle command is handled seperately, default: None
    client.connect("localhost", 6600)  # connect to localhost:6600
    print(client.mpd_version)
    
    if client.status()['state'] in ('play', 'pause'):
        print('Playing')
    else:
        print('stopped')

    python code snippet end

bash

  • alias

    for example if you get tired of typing emacs -nw to start emacs without a gui window then add

    alias enw='emacs -nw'

    to the end of your .profile or .bashrc file located at /home or /home/usr

misc

  • Display system’s serial support

    dmesg | grep tty

    resulting output resembles;

    bash code snippet start

    pi@raspberrypi:~/xbee $ dmesg | grep tty
    [    0.000000] Kernel command line: dma.dmachans=0x7f35 bcm2708_fb.fbwidth=656 bcm2708_fb.fbheight=416 bcm2708.boardrev=0x3 bcm2708.serial=0xf83a1e37 smsc95xx.macaddr=B8:27:EB:3A:1E:37 bcm2708_fb.fbswap=1 bcm2708.uart_clock=48000000 vc_mem.mem_base=0xec00000 vc_mem.mem_size=0x10000000  dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
    [    0.000718] console [tty1] enabled
    [    0.201139] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, base_baud = 0) is a PL011 rev2
    [    0.201529] console [ttyAMA0] enabled
    [    2.333606] systemd[1]: Expecting device dev-ttyAMA0.device...
    [    2.353451] systemd[1]: Starting system-serial\x2dgetty.slice.
    [    2.354181] systemd[1]: Created slice system-serial\x2dgetty.slice.
    [    9.556243] usb 1-1.2: FTDI USB Serial Device converter now attached to ttyUSB0
    pi@raspberrypi:~/xbee $

    bash code snippet end

  • nginx gpg key

    The distributed version of nginx is old, if you want to install the newer versions you have to self compile but first you need to take a couple of steps;

    create a file;

    • sudo nano /etc/apt/sources.list.d/nginx.list

    and add the line;

    deb-src http://nginx.org/packages/mainline/debian/ wheezy nginx

    then run apt-get update and you will receive an error stating the signatures cannot be verified, to overcome this you need the nginx keys which you can get via;

    curl -O https://nginx.org/keys/nginx_signing.key && apt-key add ./nginx_signing.key

    now run sudo apt-key update sudo apt-get update

    and you should get no error messages meaning you can now run;

    apt-get source nginx

    to finally get the latest nginx source for building on your pi (set aside quite some time for it to build) and to install use

    sudo dpkg -i nginx_1.9.4-1~squeeze_armhf.deb

  • MOTD

    Below MOTD was found somewhere on the net, when i find from where i’ll add a link (its only here in this file so i remember)

    To get something like this every time you log in;

    You need a custom message of the day script, copy the code and place it in /home/pi/.bash_profile

    bash code snippet start

    let upSeconds="$(/usr/bin/cut -d. -f1 /proc/uptime)"
    let secs=$((${upSeconds}%60))
    let mins=$((${upSeconds}/60%60))
    let hours=$((${upSeconds}/3600%24))
    let days=$((${upSeconds}/86400))
    UPTIME=`printf "%d days, %02dh%02dm%02ds" "$days" "$hours" "$mins" "$secs"`
    
    # get the load averages
    read one five fifteen rest < /proc/loadavg
    
    echo "$(tput setaf 2)
       .~~.   .~~.    `date +"%A, %e %B %Y, %r"`
      '. \ ' ' / .'   `uname -srmo`$(tput setaf 1)
       .~ .~~~..~.
      : .~.'~'.~. :   Uptime.............: ${UPTIME}
     ~ (   ) (   ) ~  Memory.............: `cat /proc/meminfo | grep MemFree | awk {'print $2'}`kB (Free) / `cat /proc/meminfo | grep MemTotal | awk {'print $2'}`kB (Total)
    ( : '~'.~.'~' : ) Load Averages......: ${one}, ${five}, ${fifteen} (1, 5, 15 min)
     ~ .~ (   ) ~. ~  Running Processes..: `ps ax | wc -l | tr -d " "`
      (  : '~' :  )   IP Addresses.......: `/sbin/ifconfig eth0 | /bin/grep "inet addr" | /usr/bin/cut -d ":" -f 2 | /usr/bin/cut -d " " -f 1` and `wget -q -O - http://icanhazip.com/ | tail`
       '~ .~~~. ~'
           '~'
    $(tput sgr0)"

    bash code snippet end

    $(tput sgr0)"

  • identify usb devices

    create a script with the following and make it executable

    bash code snippet start

    #!/bin/bash
    for sysdevpath in $(find /sys/bus/usb/devices/usb*/ -name dev); do
        (
            syspath="${sysdevpath%/dev}"
            devname="$(udevadm info -q name -p $syspath)"
            [[ "$devname" == "bus/"* ]] && continue
            eval "$(udevadm info -q property --export -p $syspath)"
            [[ -z "$ID_SERIAL" ]] && continue
            echo "/dev/$devname - $ID_SERIAL"
        )
    done

    bash code snippet end

    taken from: https://unix.stackexchange.com/questions/144029/command-to-determine-ports-of-a-device-like-dev-ttyusb0

  • mysql

    using mariadb as the main sql server

    logon to sql server: mysql -u root -p

    create database: CREATE DATABASE home;

    now we need at least one table.

    CREATE TABLE temps (recnum int NOT NULL AUTO_INCREMENT, recdate DATE DEFAULT NULL, rectime time DEFAULT NULL, external float DEFAULT NULL, frontroom float DEFAULT NULL, bedroom float DEFAULT NULL, kitchen float DEFAULT NULL,PRIMARY KEY( recnum ));

    now we can see what we’ve created with;

    show columns in temps

    verse code snippet start

    +-----------+---------+------+-----+---------+----------------+
    | Field     | Type    | Null | Key | Default | Extra          |
    +-----------+---------+------+-----+---------+----------------+
    | recnum    | int(11) | NO   | PRI | NULL    | auto_increment |
    | recdate   | date    | YES  |     | NULL    |                |
    | rectime   | time    | YES  |     | NULL    |                |
    | external  | float   | YES  |     | NULL    |                |
    | frontroom | float   | YES  |     | NULL    |                |
    | bedroom   | float   | YES  |     | NULL    |                |
    | kitchen   | float   | YES  |     | NULL    |                |
    +-----------+---------+------+-----+---------+----------------+
    7 rows in set (0.04 sec)

    verse code snippet end

    now to leave the sql server simply type exit;

  • access serial port

    when you want python to access the serial port it will if not run as root error out with permission denied. To get round this add your user to the dialout group eg

    sudo adduser <username> dialout

    then logout and log back in, you should now be able to run your python script with using root. To check what groups your user is a member of simply type groups

crontab

  • run in background during boot

    The & at the end of the line makes the script run in the background whilst the pi carries on booting @reboot sudo python /home/pi/homeApp/ourhome.py &

  • enable cron logging

    By default, the logging for the cron daemon is not enabled in Debian To enable it, open the file /etc/rsyslog.conf via

    sudo nano /etc/rsyslog.conf

    and uncomment the line

    cron.* /var/log/cron.log

  • run on reboot

    to run a command on boot i use the following in the crontab file

    @reboot run_command

  • cron sleep

    Starting a command on reboot after x seconds

    For some reason my pi would not wait for the wifi network to come online (wait for network on boot is enabled) so my NAS wont connect, to be honest i had other things to do than fault find so as i added an @reboot mount command with a sleep period to ensure the drive was accessible;

    @reboot sleep 10;sudo mount -a

  • specifying the crontab editor

    if like me you’ve accidentally set the wrong editor when first using crontab you can specify the editor everytime using the following;

    bash code snippet start

    export VISUAL=nano; crontab -e

    bash code snippet end

    alternatively you can edit the ~/.selected.editor file and change to your chosen editor;

    bash code snippet start

    # Generated by /usr/bin/select-editor
    SELECTED_EDITOR="/usr/bin/nano"

    bash code snippet end

network

  • setup new blank image

    before removing the flashed sd card

    create a blank file called ssh

    then create a file called wpa_supplicant.conf with the following;

    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=gb

    network={ ssid=“your_SSID” psk=“your_password” key_mgmt=WPA-PSK }

  • setup wifi via command line

    sudo iwlist wlan0 scan

    Open the wpa-supplicant configuration file in nano: sudo nano /etc/wpa_supplicant/wpa_supplicant.conf Go to the bottom of the file and add the following:

    bash code snippet start

    country=gb
    update_config=1
    ctrl_interface=/var/run/wpa_supplicant
    
    network={
        scan_ssid=1
        ssid="testing"
        psk="testingPassword"
    }

    bash code snippet end

    Then re-configure the interface by wpa_cli -i wlan0 reconfigure

  • Static or fixed IP address

    add to /etc/dhcpcd.conf

    bash code snippet start

    #Custom static IP address
    interface eth0
    static ip_address=192.168.1.04/24
    static routers=192.168.1.1
    static domain_name_servers=192.168.1.1

    bash code snippet end

    changing eth0 to wlan0 depending on connection type and also remember to use your own choice of IP address/subnet etc

  • mail

    Had problems with a cron job and no idea why & at the time had not setup logging and without an MTA [Mail Transport Assistant] i could not see what errors were being given, after reading up i installed postfix

    sudo apt install postfix

    Choosing “LOCAL” during setup, then after a reboot i could use the following to find out what went wrong:

    shell code snippet start

    sudo tail -f /var/mail/<user>

    shell code snippet end

    alternatively you can set up a more capable system and allow your Pi to send mail using your google account

    shell code snippet start

    sudo apt-get install ssmtp mailutils mpack
    sudo nano /etc/ssmtp/ssmtp.conf

    shell code snippet end

    shell code snippet start

    # Config file for sSMTP sendmail
    
    # The person who gets all mail for userids < 1000
    # Make this empty to disable rewriting.
    # root=localhost
    root=your_chosen_address
    
    # The place where the mail goes. The actual machine name is required no
    # MX records are consulted. Commonly mailhosts are named mail.domain.com
    mailhub=smtp.gmail.com:587
    
    # Where will the mail seem to come from?
    # rewriteDomain=gmail.com
    
    # The full hostname
    hostname=yourHOSTNAME
    
    # Are users allowed to set their own From: address?
    # YES - Allow the user to specify their own From: address
    # NO - Use the system generated From: address
    FromLineOverride=YES
    
    UseSTARTTLS=YES
    
    AuthUser=yourEMAIL
    AuthPass=either password or two-factor key

    shell code snippet end

    • TODO - update rqd Example python script for using sSMTP

      sudo apt-get install ssmtp sudo apt-get install mailutils

      root=postmaster mailhub=smtp.gmail.com:587 hostname=raspberrypi AuthUser=AGmailUserName@gmail.com AuthPass=TheGmailPassword FromLineOverride=YES UseSTARTTLS=YES

    • old

      python code snippet start

      #!/usr/bin/python
      # Taken and modified from an example here:
      # http://tombuntu.com/index.php/2008/10/24/server-monitoring-with-python-and-ssmtp/
      
      import subprocess, re, time
      import urllib, urllib2
      
      # email address to use in the to field
      recipient = 'towhomit@mayconcern'
      # email address to use in the from field
      sender = 'fromwhom@sentit'
      # template for the email message
      # first '%s' is recipient, second is sender, third is content
      message = '''To: %s
      From: %s
      Subject: rpiELEC IP: %s
      
      '''
      
      def send_mail(content):
          try:
              ssmtp=subprocess.Popen(('/usr/sbin/ssmtp', recipient), stdin=subprocess.PIPE)
          except OSError:
              print('Error sending mail')
      
          # pass mail to sSMTP client
          ssmtp.communicate(message % (recipient, sender,content))
          ssmtp.wait()
      
      
      data = re.search('"([0-9.]*)"', urllib.urlopen("http://ip.jsontest.com/").read()).group(1)
      send_mail(data)

      python code snippet end

access a network drive

Edit your /etc/fstab file and add the following line (changing the ip address and location of the credentials file to suit your setup);

bash code snippet start

//192.168.1.1/Drive /media/nas_documents cifs credentials=/home/drakx/.nas_credentials,sec=ntlmv2,uid=1000,gid=1000,iocharset=utf8 0 0

bash code snippet end

Now create a file called .nas_credentials in your home directory

bash code snippet start

username=YOUR_ROUTER_LOGIN
password=YOUR_ROUTER_LOGIN_PASSWORD

bash code snippet end

ssh file system

One trick i didnt learn until far too late was sshfs essentially it mounts your remote system as a folder on your desktop/laptop so instead of saving files then transfering etc you can open and load the remote files and work on them as if local. Excellent for tweaking your python website.

The line of code you need is really simple;

sshfs pi@192.168.1.69:/home/pi home/user/folder/

python ping

need to sudo pip install ping first

python code snippet start

import ping, socket
try:
    ping.verbose_ping('www.google.com', count=3)
except socket.error, e:
    print "Ping Error:", e

python code snippet end

emacs

  • emacs commands/tips
    key command
    M-; when a region is highlighted pressing M-; will comment out the section
    C-c C-x - starts a list in emacs with timer, now pressing M-RET will allow notes
    eg
    - 0:00:00 :: Now I can start taking some notes.
    - 0:00:02 :: If I hit M-RET, a new list item is created.
    - 0:00:06 :: And so on
    org-toggle-link-display OK not a shortcut but really useful for me once toggled it displays
    links in their unshortened form which means if a link has a %20
    in it then the emacs search & replace ~M-shift-% will work
    (for some reason files i’ve transferred all had link spaces replaced
    with %20 bloody annoying
    M-x occur searches your file with regexp & opens a second buffer with all matches
  • emacs org-publish

    took me a long time to get this working and i dont use the ctrl c-e P to get it going you have to use alt-x org-publish ret org ret

    elisp code snippet start

    (setq org-publish-project-alist
          '(
            ("org-notes"
             :base-directory "C:/Users/drakx/Documents/org_files"
             :base-extension "org"
             :publishing-directory "C:/Users/drakx/Documents/org_publish"
             :recursive -t
             :publishing-function org-html-publish-to-html
             :headline-levels 4
             :auto-preamble t
             :auto-sitemap t                ; Generate sitemap.org automagically...
             :sitemap-filename "sitemap.org"  ; ... call it sitemap.org (it's the default)...
             :sitemap-title "Sitemap"         ; ... with title 'Sitemap'.
             :language "en"
             :section-numbers nil
             :with-toc t
             :html-preamble t
             )
    
            ("org-static"
             :base-directory "C:/Users/drakx/Documents/org_files/files/"
             :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
             :publishing-directory "C:/Users/drakx/Documents/org_publish/files/"
             :recursive t
             :publishing-function org-publish-attachment
             )
    
          ("org" :components ("org-notes" "org-static"))
          )
    )

    elisp code snippet end

    now all i need to do is test in my work files and on interlinked org files, as of today [2018-08-05 Sun 09:01] i have only tested it on a simple project

camera camera

  • Disable red LED

    Edit /boot/config and add the line

    disable_camera_led=1