Testing, testing, 1 … 2 … 3 …

To assure that every order is working, I test every module I make for sale. Early days connected them to my own smart meter and see if I get the well known telegrams on the network. While wifi modules are tested while they’re flashed, my ethernet modules had to be tested 1 by 1, and the most time was waiting to see which IP address they’d get and than connecting to that address… Well that should be optimized …

As I have my own meter on my workplace, I want to make an easy testing method, and the idea is quite simpel:

  • make sure the module gets the same ip-address every time
  • make a testing script that automatically connects when available

As dhcp-server must be configured on an active port, configuring on eth0 was not a good option. When the Raspberry Pi is booting up with no ethernet connected, DHCP won’t start. So a bridge is required and the eth0 is member of the bridge.

Installing the required packages

For this to work we need tools to make a bridge and a DHCP-server. After assuming the package manager is up2date (sudo apt update), we install:

$ sudo apt install bridge-utils isc-dhcp-server

After installing these packages, it is possible that the dhcp-server gives error messages and won’t start up. Probably that is because there is no interface to use. In my case, I’m connected via WiFi and ethernet is not connected (that’s why we’re going to use a bridge).

Configuring a bridge

I’d like to use names that can be identified (like eth0/1/2/3 and wlan0/1/2/3 etc). So obviously the bridge is going to be called br0. Therefor I make a configuration file for the br0.

$ sudo vi /etc/network/interfaces.d/br0

static ip config file for br0
auto br0
iface br0 inet static
    address 192.168.0.1
    broadcast 192.168.0.255
    netmask 255.255.255.0
    bridge_ports eth0
    bridge_stp off       # disable Spanning Tree Protocol
    bridge_waitport 0    # no delay before a port becomes available
    bridge_fd 0          # no forwarding delay

In my case I’ve chosen for the network range of 192.168.0.0/24. This can be any range you like, as long as it is not the same range of the WiFi network.

Reboot or restart the network and the bridge br0 should be visible ($ ip add).

Configuring DHCP server

First we have to create a scope, and that scope has got only one address. The ip-address can be any ip within the range, as long as it is not the network address (192.168.0.0), not the bridge address (I’ve chosen 192.168.0.1) and not the broadcast address (192.168.0.255). I choose 192.168.0.10.

subnet 192.168.0.0 netmask 255.255.255.0 {
  range 192.168.0.10 192.168.0.10;
  option routers 192.168.0.1;
  default-lease-time 1;
  max-lease-time 1;
}

Note the lease time of 1 second. If this is default 600, then it will take 600 seconds before the address will be available again. Connecting another device won’t get an ip-address as the pool as only got one and that one is claimed for the configured lease time.

Somewhere in the beginning of this config file there should be two lines

default-lease-time 600;
max-lease-time 7200;

change that also to 1 second:

default-lease-time 1;
max-lease-time 1;

Now change the interface for the dhcp-server to the bridge br0. Change INTERFACESv4=”” to INTERFACESv4=”br0″ and put a ‘#’ before INTERFACESv6=”” (we’re not using ipv6):

$ vi /etc/default/isc-dhcp-server 

#Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server)

#Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
#DHCPDv4_CONF=/etc/dhcp/dhcpd.conf
#DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf

#Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
#DHCPDv4_PID=/var/run/dhcpd.pid
#DHCPDv6_PID=/var/run/dhcpd6.pid

#Additional options to start dhcpd with.
#  Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
#OPTIONS=""

#On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#  Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4="br0"
#INTERFACESv6=""

Enable the DHCP server

Now everything is configured, it time to restart the dhcp-server make sure it starts at boot:

$ sudo systemctl enable isc-dhcp-server
$ sudo systemctl start isc-dhcp-server

Now start a ping and connect an ethernet module:

$ ping 192.168.0.10
 PING 192.168.0.10 (192.168.0.10) 56(84) bytes of data.
 From 192.168.0.1 icmp_seq=1 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=2 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=3 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=4 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=5 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=6 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=7 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=8 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=9 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=10 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=11 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=12 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=13 Destination Host Unreachable
 From 192.168.0.1 icmp_seq=14 Destination Host Unreachable
 64 bytes from 192.168.0.1: icmp_seq=15 ttl=64 time=220.10 ms
 64 bytes from 192.168.0.1: icmp_seq=16 ttl=64 time=5.77 ms
 64 bytes from 192.168.0.1: icmp_seq=17 ttl=64 time=0.092 ms
 64 bytes from 192.168.0.1: icmp_seq=18 ttl=64 time=0.102 ms
 64 bytes from 192.168.0.1: icmp_seq=19 ttl=64 time=0.088 ms
 64 bytes from 192.168.0.1: icmp_seq=20 ttl=64 time=0.095 ms
 64 bytes from 192.168.0.1: icmp_seq=21 ttl=64 time=0.104 ms
 64 bytes from 192.168.0.1: icmp_seq=22 ttl=64 time=0.102 ms
 64 bytes from 192.168.0.1: icmp_seq=23 ttl=64 time=0.095 ms

The test script

Now we need a script that verifies the connection and connect once there is a connection. I’ve chosen for a double while loop. The first is simply true, to keep running until you quit it (ctrl + c). The second while loop checks if there it is pingable. If true it starts a netcat to the device its telnet service (nc 192.168.0.10 23) and a timeout flag of 2 seconds (-w2). If it doesn’t receive any data within those 2 seconds, nc quits. If the device isn’t pingable, it shows a fancy message “Whoopsie,… device offline!”.

$ Vi E20.sh
 !/bin/bash
 clear
 while true; do
     while [ ping 192.168.0.10 -c 1 | grep "1 packets transmitted, 1 received" | wc -l -eq 1 ]; do
         nc -w2 192.168.0.10 23
     done
     echo "Whooopsie,... device offline!"
 done

Ok, all set and done. Now make sure the Raspberry Pi does autologin and starts the script on login. To autologin on boot, use raspi-config:

  • $ sudo raspi-config
  • go to “System Options”
  • go to “Boot / Autologin”
  • Choose “Console Autologin”
  • Quit and reboot

Edit the .profile file (/home/pi/.profile on a RPi, or ~/.profile) and add at the end “/bin/bash /home/pi/E20.sh”:

# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
 exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
     # include .bashrc if it exists
     if [ -f "$HOME/.bashrc" ]; then
     . "$HOME/.bashrc"
     fi
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
     PATH="$HOME/bin:$PATH"
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
     PATH="$HOME/.local/bin:$PATH"
fi

/bin/bash /home/pi/E20.sh

And it works

The modules boots within 1~2 seconds, gets an ip-address within 1~2 seconds, and when module works, than it shows telegrams after about 5 seconds. Now that’s a huge time win.

Leave a Reply

Your email address will not be published.