How to use ancient Morse code to solve a modern problem

If you own a Raspberry Pi mini computer the following problem may sound familiar to you: You just connected your Rasperry Pi to a network with automatic DHCP. Now you need to find out what IP address has been assigned to it. While this may be quite easy to do when you have a computer screen and a keyboard at hand, it requires some nifty workarounds if don’t.

There are numerous ways to solve this problem, e.g.

  • Set up a network packet sniffer (e.g. Wireshark) on another machine in the same network to examine the DHCP communication between server and client.
  • View the logs or a list of the active clients on the DHCP server.
  • Set up the Raspberry Pi to register with a dynamic DNS provider or some homebrew service on another machine.
  • Write a script and configure the Raspberry Pi to build and send out an email to you each time it is connected to a network.

However, there is a catch to such solutions: They all rely on external devices and configurations. Sometimes you may connect your Raspberry Pi to a network that is configured to block certain ports or traffic. Or maybe there is a a power outage that affects your homemade registration server.

I was therefore looking for an independent alternative solution to find out my Raspberry Pi’s newly assigned IP address. It should not involve sending data across the network, and it was supposed to work without having to connect a computer screen.

The idea I came up with was a program (see below) that displays the device’s IP address on one single LED that is connected to one of its GPIO ports. The only hitch to my nerdy solution is that you need to learn how the digits 0 to 9 are represented in Morse code, which is a piece of cake though.

Feel free to check out my solution by performing the following steps:

  • Compile the C program below in your Raspberry Pi
    gcc ip2morse.c -o ip2morse -lwiringPi
  • Copy the generated executable file to /bin (root permissions / sudo required).
    cp ip2morse /bin
  • Add a new entry to the file /etc/crontab to have the program executed every minute.
    * * * * * root /bin/ip2morse

Note that the author of the C program below cannot be held liable for any damages, loss, claims, or expenses caused by running the program.

/* Program: ip2morse.c
 * Platform/OS: RaspberryPi/Raspbian
 * Description: The purpose of this program is to output the IPv4 
 * address of a network interface on a LED in Morse 
 * code.
 *
 * Copyright (c) 2017 by Andre M. Maier - All Rights Reserved
 * You may use, distribute and modify this code under the
 * terms of the Creative Commons Attribution 4.0 International 
 * (CC BY 4.0) license. For further information, please visit 
 * https://creativecommons.org/licenses/by/4.0
 */
#include <stdio.h>
#include <wiringPi.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define PIN 1 // BCM GPIO 18
#define SHORT_IN_MS 200 // Length of a dot in Morse code
#define LONG_IN_MS 600 // Length of a dash in Morse code
#define PAUSE_IN_MS 200 // Pause within dots and dashes

// Pause between digits; The pause between the octets of the IP
// address will be twice this value.
#define PAUSE_AFTER_DIGIT_IN_MS 1000

// Network interface for which to get the IP address
#define INTERFACE "wlan0"

// Digits in Morse code (from 0 to 9)
const char* const numbers_in_morse[] = { "-----", ".----", "..---",
                                         "...--", "....-", ".....",
                                         "-....", "--...", "---..",
                                         "----." };

/* Outputs a specified decimal digit (0-9)
   on the GPIO pin. */
void digit_to_morse_output( unsigned char digit ) 
{
   const char* num_in_morse = numbers_in_morse[ digit ];
   int i = 0;
   while( num_in_morse[ i ] != '\0' )
   {
      digitalWrite( PIN, 1 );
      if( num_in_morse[ i ] == '.' ) 
      {
         delay( SHORT_IN_MS );
      }
      else
      {
         delay( LONG_IN_MS );
      }
      digitalWrite( PIN, 0 );
      delay( PAUSE_IN_MS );
      i++;
   }
}

/* Determines the IPv4 address from the specified network
   interface and returns it as a string in dotted-decimal
   format. */
char* get_ip_address_string( char* interface )
{
   struct ifreq ifr;
   int fd = socket( AF_INET, SOCK_DGRAM, 0 );
   ifr.ifr_addr.sa_family = AF_INET;
   strncpy( ifr.ifr_name, interface, IFNAMSIZ - 1 );
   ioctl( fd, SIOCGIFADDR, &ifr );
   close( fd );
   return inet_ntoa( ( ( struct sockaddr_in *)&ifr.ifr_addr ) 
                     -> sin_addr );
}
 
/* Main function. This is where the program starts. */
int main( int argc, char** argv )
{
   // Setting up wiringPi and initializing the GPIO port
   if( wiringPiSetup() == -1 )
     return 1;
   pinMode( PIN, OUTPUT );
 
   // Determine ip address of the network interface
   char* ip_address = get_ip_address_string( INTERFACE );

   // Looping through the whole IPv4 string. The dots between
   // the octets will be represented by a long pause (twice
   // as long as the pause between the digits.
   int length = strlen( ip_address );
   int i;
   for( i = 0; i < length; i++ )
   {
      char c = ip_address[ i ];
      if( c == '.' )
      {
         delay( PAUSE_AFTER_DIGIT_IN_MS );
      }
      else
      {
         unsigned char digit = c - '0';
         digit_to_morse_output( digit );
         delay( PAUSE_AFTER_DIGIT_IN_MS );
      }
   }
   return 0;
}

Last but not least, a short note to my teaching colleagues in computer science:
The program can be used as a nice little classroom project for advanced students. It combines topics such as network and hardware-oriented C programming, the history of communications, and scheduled tasks (you can either run the program in a cronjob as described above, or you can make it a SysV or systemd service).

Have fun!
— Andre M. Maier

Advertisements

About bitjunkie

Teacher, Lecturer, and BITJUNKIE ...
This entry was posted in c, Information Theory, Linux, Raspberry Pi, Uncategorized and tagged , , , , , , , . Bookmark the permalink.