WittyPi power management board with a RPi3 docker container

We’re trying to use the WittyPi with Resio.io, however we’re having some problems getting it running with a container. The WittyPi is a power management and RTC board for RPi. When we insert the USB power into the witty pi and press the button the RPi’s red light turns on for one second and then powers off. The WittyPi uses I2C to communicate with the RPi. We run the witty pi installation script (see below) from the Dockerfile, however I suspect the scripts needs to be installed in the base image.

Any suggestions?

Witty Pi installation script:

#!/usr/bin/env bash
[ -z $BASH ] && { exec bash "$0" "$@" || exit; }
#!/bin/bash
# file: installWittyPi.sh
#
# This script will install required software for Witty Pi.
# It is recommended to run it in your home directory.
#

# check if sudo is used
if [ "$(id -u)" != 0 ]; then
  echo 'Sorry, you need to run this script with sudo'
exit 1
fi

# target directory
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/wittyPi"

# error counter
ERR=0

echo '================================================================================'
echo '|                                                                              |'
echo '|                   Witty Pi Software Installing Script                        |'
echo '|                                                                              |'
echo '================================================================================'

     # enable I2C on Raspberry Pi
     echo '>>> Enable I2C'
     if grep -q 'i2c-bcm2708' /etc/modules; then
      echo 'Seems i2c-bcm2708 module already exists, skip this step.'
     else
       echo 'i2c-bcm2708' >> /etc/modules
    fi
    if grep -q 'i2c-dev' /etc/modules; then
      echo 'Seems i2c-dev module already exists, skip this step.'
    else
      echo 'i2c-dev' >> /etc/modules
    fi
if grep -q 'dtparam=i2c1=on' /boot/config.txt; then
  echo 'Seems i2c1 parameter already set, skip this step.'
else
  echo 'dtparam=i2c1=on' >> /boot/config.txt
fi
if grep -q 'dtparam=i2c_arm=on' /boot/config.txt; then
  echo 'Seems i2c_arm parameter already set, skip this step.'
else
  echo 'dtparam=i2c_arm=on' >> /boot/config.txt
fi
if grep -q 'dtoverlay=pi3-miniuart-bt' /boot/config.txt; then
  echo 'Seems setting Pi3 Bluetooth to use mini-UART is done already, skip this step.'
else
  echo 'dtoverlay=pi3-miniuart-bt' >> /boot/config.txt
fi
if grep -q 'core_freq=250' /boot/config.txt; then
  echo 'Seems the frequency of GPU processor core is set to 250MHz already, skip this step.'
else
  echo 'core_freq=250' >> /boot/config.txt
fi
if [ -f /etc/modprobe.d/raspi-blacklist.conf ]; then
  sed -i 's/^blacklist spi-bcm2708/#blacklist spi-bcm2708/' /etc/modprobe.d/raspi-blacklist.conf
  sed -i 's/^blacklist i2c-bcm2708/#blacklist i2c-bcm2708/' /etc/modprobe.d/raspi-blacklist.conf
else
  echo 'File raspi-blacklist.conf does not exist, skip this step.'
fi

     # install i2c-tools
    echo '>>> Install i2c-tools'
    if hash i2cget 2>/dev/null; then
      echo 'Seems i2c-tools is installed already, skip this step.'
    else
      apt-get install -y i2c-tools || ((ERR++))
    fi

 # install wiringPi
if [ $ERR -eq 0 ]; then
  echo '>>> Install wiringPi'
  if hash gpio 2>/dev/null; then
    echo 'Seems wiringPi is installed already, skip this step.'
  else
    if hash git 2>/dev/null; then
      echo "Git is ready to go..."
    else
      echo "Git is missing, install it now..."
      apt-get install -y git || ((ERR++))
    fi
    if [ $ERR -eq 0 ]; then
      git clone git://git.drogon.net/wiringPi || ((ERR++))
      cd wiringPi
      ./build
      cd ..
    fi
  fi
fi

# install wittyPi
if [ $ERR -eq 0 ]; then
  echo '>>> Install wittyPi'
  if [ -f wittyPi ]; then
    echo 'Seems wittyPi is installed already, skip this step.'
  else
    wget http://www.uugear.com/repo/WittyPi/LATEST -O wittyPi.zip || ((ERR++))
    unzip wittyPi.zip -d wittyPi || ((ERR++))
    cd wittyPi
    chmod +x wittyPi.sh
    chmod +x daemon.sh
    chmod +x syncTime.sh
    chmod +x runScript.sh
    sed -e "s#/home/pi/wittyPi#$DIR#g" init.sh >/etc/init.d/wittypi
    chmod +x /etc/init.d/wittypi
    update-rc.d wittypi defaults
    cd ..
    sleep 2
    rm wittyPi.zip
  fi
fi

echo
if [ $ERR -eq 0 ]; then
  echo '>>> All done. Please reboot your Pi :-)'
else
  echo '>>> Something went wrong. Please check the messages above :-('
fi

Hi there,

Having a brief look through the script, there may be a few different issues as to why bits of it aren’t working.

Could you possibly paste your entire Dockerfile here for us, please? It will help us determine what’s going on, including the base image you’re using.

Thanks and best regards,

Heds

Hey @hedley ,
Here is the docker file we’re using

# base-image for python on any machine using a template variable,
# see more about dockerfile templates here:http://docs.resin.io/pages/deployment/docker-templates
FROM resin/%%RESIN_MACHINE_NAME%%-python

# use apt-get if you need to install dependencies,
# for instance if you need ALSA sound utils, just uncomment the lines below.
RUN apt-get update && apt-get --assume-yes install python3-gpiozero python-gpiozero sshfs python-dev libzmq3-dev rsync sshpass unzip

# Install bridging depeendencies
RUN apt-get install -yq --no-install-recommends \
      parprouted dhcp-helper avahi-daemon avahi-daemon avahi-utils libnss-mdns

# For Avahi, DNS and DBUS
RUN apt-get --assume-yes install avahi-daemon avahi-utils libnss-mdns dbus

# For Paramiko
RUN apt-get --assume-yes install libssl-dev libffi6 libffi-dev

# OpenSSH
RUN apt-get update && apt-get install -yq --no-install-recommends \
    openssh-server && \
    apt-get clean && rm -rf /var/lib/apt/lists/*


# here we set up the config for openSSH.
RUN mkdir /var/run/sshd \
    && echo 'root:resin' | chpasswd \
    && sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config \
    && sed -i 's/UsePAM yes/UsePAM no/' /etc/ssh/sshd_config

# Set our working directory
WORKDIR /usr/src/app

# Install bridging depeendencies
COPY ./resources/dhcp-helper /etc/default/dhcp-helper
COPY ./resources/avahi-daemon.conf /etc/avahi/avahi-daemon.conf

# Copy requirements.txt first for better cache on later pushes
COPY ./requirements.txt /requirements.txt

# pip install python deps from requirements.txt on the resin.io build server
RUN pip install -r /requirements.txt


# Install Witty Pi
COPY ./resources/install_witty.sh /install_witty.sh
RUN chmod +x /install_witty.sh
RUN  (cd / && ./install_witty.sh)

# This will copy all files in our root to the working  directory in the container
COPY . ./

# Set our working directory
WORKDIR /usr/src/app/src

# switch on systemd init system in container
ENV INITSYSTEM on

# Start the main app
CMD ["./start.sh"]

Witty Pi Install Script:

#!/usr/bin/env bash
[ -z $BASH ] && { exec bash "$0" "$@" || exit; }
#!/bin/bash
# file: installWittyPi.sh
#
# This script will install required software for Witty Pi.
# It is recommended to run it in your home directory.
#

# check if sudo is used
if [ "$(id -u)" != 0 ]; then
  echo 'Sorry, you need to run this script with sudo'
  exit 1
fi

# target directory
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/wittyPi"

# error counter
ERR=0

echo '================================================================================'
echo '|                                                                              |'
echo '|                   Witty Pi Software Installing Script                        |'
echo '|                                                                              |'
echo '================================================================================'

# enable I2C on Raspberry Pi
echo '>>> Enable I2C'
if grep -q 'i2c-bcm2708' /etc/modules; then
  echo 'Seems i2c-bcm2708 module already exists, skip this step.'
else
  echo 'i2c-bcm2708' >> /etc/modules
fi
if grep -q 'i2c-dev' /etc/modules; then
  echo 'Seems i2c-dev module already exists, skip this step.'
else
  echo 'i2c-dev' >> /etc/modules
fi
if grep -q 'dtparam=i2c1=on' /boot/config.txt; then
  echo 'Seems i2c1 parameter already set, skip this step.'
else
  echo 'dtparam=i2c1=on' >> /boot/config.txt
fi
if grep -q 'dtparam=i2c_arm=on' /boot/config.txt; then
  echo 'Seems i2c_arm parameter already set, skip this step.'
else
  echo 'dtparam=i2c_arm=on' >> /boot/config.txt
fi
if grep -q 'dtoverlay=pi3-miniuart-bt' /boot/config.txt; then
  echo 'Seems setting Pi3 Bluetooth to use mini-UART is done already, skip this step.'
else
  echo 'dtoverlay=pi3-miniuart-bt' >> /boot/config.txt
fi
if grep -q 'core_freq=250' /boot/config.txt; then
  echo 'Seems the frequency of GPU processor core is set to 250MHz already, skip this step.'
else
  echo 'core_freq=250' >> /boot/config.txt
fi
if [ -f /etc/modprobe.d/raspi-blacklist.conf ]; then
  sed -i 's/^blacklist spi-bcm2708/#blacklist spi-bcm2708/' /etc/modprobe.d/raspi-blacklist.conf
  sed -i 's/^blacklist i2c-bcm2708/#blacklist i2c-bcm2708/' /etc/modprobe.d/raspi-blacklist.conf
else
  echo 'File raspi-blacklist.conf does not exist, skip this step.'
fi

# install i2c-tools
echo '>>> Install i2c-tools'
if hash i2cget 2>/dev/null; then
  echo 'Seems i2c-tools is installed already, skip this step.'
else
  apt-get install -y i2c-tools || ((ERR++))
fi

# install wiringPi
if [ $ERR -eq 0 ]; then
  echo '>>> Install wiringPi'
  if hash gpio 2>/dev/null; then
    echo 'Seems wiringPi is installed already, skip this step.'
  else
    if hash git 2>/dev/null; then
      echo "Git is ready to go..."
    else
      echo "Git is missing, install it now..."
      apt-get install -y git || ((ERR++))
    fi
    if [ $ERR -eq 0 ]; then
      git clone git://git.drogon.net/wiringPi || ((ERR++))
      cd wiringPi
      ./build
      cd ..
    fi
  fi
fi

# install wittyPi
if [ $ERR -eq 0 ]; then
  echo '>>> Install wittyPi'
  if [ -f wittyPi ]; then
    echo 'Seems wittyPi is installed already, skip this step.'
  else
    wget http://www.uugear.com/repo/WittyPi/LATEST -O wittyPi.zip || ((ERR++))
    unzip wittyPi.zip -d wittyPi || ((ERR++))
    cd wittyPi
    chmod +x wittyPi.sh
    chmod +x daemon.sh
    chmod +x syncTime.sh
    chmod +x runScript.sh
    sed -e "s#/home/pi/wittyPi#$DIR#g" init.sh >/etc/init.d/wittypi
    chmod +x /etc/init.d/wittypi
    update-rc.d wittypi defaults
    cd ..
    sleep 2
    rm wittyPi.zip
  fi
fi

echo
if [ $ERR -eq 0 ]; then
  echo '>>> All done. Please reboot your Pi :-)'
else
  echo '>>> Something went wrong. Please check the messages above :-('
fi

Thanks!

Hi again.

We’ve had a look at the Dockerfile now, and notice that you’re actually running the script from within it. Because we build containers on separate build machines and not the device they’ll eventually run on, this will not work as none of the devices or boot data is available.

To successfully get this running, you’ll need to take the Witty Pi Install script and break it up into several parts:

  1. For all of the sections which use the /boot/config.txt file, you’ll either need to set config environment variables or manually alter the config.txt file on the SD card you’re using on the Pi, to set the relevant variables. Examples of how to do this can be found on this page.

  2. For sections that operate on Linux specific parts, such as the enabling of subsystem, you’ll need to run this as part of your startup script (start.sh looking at your Dockerfile). Something to be aware of is that the I2C system needs to be specifically initialised at startup, see the I2C section of the link above to see how to do this.

Best regards,

Heds

Another thing that came to mind, that module blacklists do not work within containers, as the hostOS mounts the modules, instead the start script have to rmmod the unwanted modules, if I recall correctly?

Thanks for your help, it’s working now.

GPIO 4 needs to be pulled high on boot for the Witty Pi to keep powering the Rpi. I added the following lines to the config.txt file

dtparam=i2c1=on
dtparam=i2c_arm=on
dtoverlay=pi3-miniuart-bt
core_freq=250

How do I set these up as environment variables? I’m not sure which part of the string is the key and value. Also, does the ‘=’ sign get automatically added?

For example:
[Key] RESIN_HOST_CONFIG_dtparam=i2c1=
[Value] on
or
[Key] RESIN_HOST_CONFIG_dtparam=i2c1
[Value] on
or
[Key] RESIN_HOST_CONFIG_dtparam=
[Value] i2c1=on

Awesome, glad to hear it works! :crown:

You can set those values in the Fleet Configuration or Device Configuration section, as detailed here in the docs: https://docs.resin.io/configuration/advanced/#raspberry-pi

Basically RESIN_HOST_CONFIG_variable set to value: RESIN_HOST_CONFIG_dtoverlay set to pi3-miniuart-bt.

I think you only need to set the dtoverlay and core_freq values, as the other two about i2c should be already enabled by default (will double-check it in a bit, though).

(If needed, it would be set as RESIN_HOST_CONFIG_dtparam to i2c1=on, because dtparam is the variable name. See for example the Raspberry Pi documentation on config.txt :bookmark: )

Finally the WittyPi board we ordered here arrived today too, so will check it out, and add some tutorials or example projects for it later.

How is it working out for you so far, how’s your experience?

Hello,

Sorry to revive a really old thread. I have just installed wittypi dependencies into a balena debian+python image. I think I have got all of the required programmes working. However I have hit a stumbling block, when the wittyPi issues a shutdown command (which usually turns of a pi) the container restarts but as it is run as part of a multi-container setup the board does not turn off. Is there a way I can give the container privileges or send information to the supervisor to issue a safe shutdown?

Many thanks,
Sam

I have found a solution by using the advice on here - interacting with supervisor. This allows my ‘wittypi container’ to send a command to the supervisor to shutdown the containers and board.

The wittypi shuts power completely to the pi after 5-8 seconds of issuing the command. Is there a way I can check that all of the containers have fully shut down within 8 seconds? I’m a bit concerned that the wittypi might be cutting off the power before a full safe shutdown has been acheived.

Hi

Have you checked the supervisor API for getting the state?

This should get you a list of the running services, and that should help you determine if it’s safe to shutdown.