OS Tricks

This page details some tricks we find very useful.

Python

 Open a serial port in Python, without knowing its number.

When you plug a mote in your Linux-based OpenLBR, it will appear as /dev/ttyUSBx, where x is a number. Similarly, when plugged into Windows, it appears as COMx in your device manager. It is frustrating, each time you plug in a mote, to look for that number and change a global variable in your Python script.

Instead, the following script scans for the connected motes and returns a list containing the list of the serial ports a mote is connected to.

#!python
import os

serialport_names = []

def findSerialPortsNames():
   global serialport_names
   if os.name=='nt':
      path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
      key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
      for i in range(winreg.QueryInfoKey(key)[1]):
         try:
            val = winreg.EnumValue(key,i)
         except:
            pass
         else:
            if val[0].find('VCP') > -1:
               serialport_names.append(str(val[1]))
      serialport_names.sort()
   elif os.name=='posix':
      serialport_names = glob.glob('/dev/ttyUSB*')
      serialport_names.sort()

After running the findSerialPortsNames() function, you script can open the first serial port using:

serialHandler = serial.Serial(serialport_names[0],baudrate=115200)
 Plugging/unplugging a mote without crashing your Python script.

When you start a script which attaches to the serial port your mote is attached to, chances are it will crash if you unplug your mote while the script is running. Similarly, if you start your script while the mote is not connected, chances are your script will crash and exit.

The following script is a way around. The function scan() looks for connected motes. If no mote is connected, the script will run scan() every second, until a mote is connected. When a mote connects, it constantly reads characters the mote sends and prints those. If the mote gets disconnected, it goes back to running scan() every second.

#!python
#!/usr/bin/python
import serial, signal, sys, time, glob

serialHandler = ''

def scan():
   return glob.glob('/dev/ttyUSB*')

def serialRx():
   while True:
      availableports = scan()
      if (len(availableports)>0):
         try:
            serialHandler = serial.Serial(availableports[0],baudrate=115200,timeout=5)
         except:
            err = sys.exc_info()
            sys.stderr.write( "Error serialRx 1: %s (%s) \n" % (str(err[0]), str(err[1])))
         else:
            print "connected to "+serialHandler.portstr
            while True:
               try:
                  char = serialHandler.read(1)
               except SystemExit:
                  return
               except:
                  err = sys.exc_info()
                  sys.stderr.write( "Error serialRx 2: %s (%s) \n" % (str(err[0]), str(err[1])))
                  break
               else:
                  print char
      else :
         print "no mote connected"
         time.sleep(1)

def signal_handler(signal, frame):
   sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)
serialRx()

This means that you can start running your script regardless of whether the mote is connected to the OpenLBR or not. Similarly, you can unplug your mote and replug it later on without having to deal with restarting the script.

LBR

 Retrieve your OpenLBR's dynamic IP address.

You may have configured your OpenLBR to acquire it's IPv4 address through DHCP. If that is the case, chances are that the DHCP server gives it a different IPv4 address everytime the OpenLBR reboots. Since the OpenLBR does not have a screen, you don't know what IPv4 address to point your PuTTY to configure it.

One solution is to have the OpenLBR load a PHP script on a remote server. That server can store the IPv4 address of the OpenLBR which contacted it, and display it on some webpage for your to see.

On the remote server (in our case http://wsn.eecs.berkeley.edu/), create a folder openserver/ under your server's DocumentRoot and create the file record_openlbr_address.php:

#!php
<?php
$file_name = "ipv4_".$_GET["hostname"].".txt";
$file_handler = fopen($file_name, "w");
$logdetails = $_SERVER['REMOTE_ADDR'];
fwrite($file_handler, $logdetails);
fclose($file_handler);
?>

<html><body>This should be accessed only by an LBR.</body></html>

Make sure you can see that page, in our case http://wsn.eecs.berkeley.edu/openserver/record_openlbr_ipv4.php. Once you have visited that page once, a file ipv4_<hostname>.txt should have been created, with hostname the value of the GET parameters passed when opening that page.

On the OpenLBR, create the file /etc/network/if-up.d/openlbr/reportaddress.sh with the following content:

#!/bin/bash
wget -O - http://wsn.eecs.berkeley.edu/openserver/record_openlbr_ipv4.php?hostname=`cat /etc/hostname`
exit 0

We use the -O flag of wget so that it does not store any file when loading the PHP script. Don't forget to give the script execution privileges used chmod.

Now, add the following line at the end of /etc/network/interfaces on your OpenLBR:

post-up /etc/network/if-up.d/openlbr/reportaddress.sh

This instructs Debian to execute that script right after the OpenLBR's Ethernet interface is up. So now, each time your OpenLBR boots, read it's current IPv4 address at http://wsn.eecs.berkeley.edu/openserver/.

 Have your OpenLBR reprogram itself at boot-time, using the OpenLBR bootstrap loader.
The OpenLBR is meant to be "forgotten" once installed. Yet, the firmware which needs to run on it may need to be updated. One elegant solution is to enable a minimal script which runs as soon as the Ethernet interface of the OpenLBR comes up, and which downloads a script from a remote server. This technique can function in a cascading effect, i.e. the downloaded script can download another script, and so on. This is the technique we choose to use in the OpenWSN project. It is described in detail in OpenLbrRunIt.

Misc

 Ping an IPv6 address from outside of the IPv6 cloud.

If you happen to be outside of the IPv6 cloud, and you still want to check whether a node is alive, you can ask http://lg.he.net/, which sits on the IPv6 cloud, to ping it for you.

 Use the auto-indent feature in vi.

We recommend vi as a code editor. You can install it:

  • in Linux by typing apt-get install vim;
  • in Windows by install gVim.

It comes with an auto-indent feature. To configure that, edit the configuration file:

  • C:\Program Files\Vim_vimrc in Windows;
  • ~/.vimrc in Linux

Add the following lines at the beginning to instruct the auto-indent engine to use soft tabulations of 3 spaces

set sw=3

When you edit some code, hit Esc and type gg=G to edit the whole file. Other vi tips at http://www.vim.org/tips/.

Windows

 In Vista, increase the MTU of an interface.

In an Administrator command window:

C:\Windows\system32>netsh interface ipv4 show interface

Idx  Met   MTU   State        Name
---  ---  -----  -----------  -------------------
  1   50 4294967295  connected    Loopback Pseudo-Interface 1
 11    5   1300  disconnected  Wireless Network Connection
 10   20   1300  connected    Local Area Connection


C:\Windows\system32>netsh interface ipv4 set interface "10" MTU=1375
Ok.


C:\Windows\system32>netsh interface ipv4 show interface

Idx  Met   MTU   State        Name
---  ---  -----  -----------  -------------------
  1   50 4294967295  connected    Loopback Pseudo-Interface 1
 11    5   1300  disconnected  Wireless Network Connection
 10   20   1375  connected    Local Area Connection
 Public-key authentication in OpenSSH.

You can connect remotely to an OpenLBR or your OpenServer using PuTTY in Windows. Normally, you would specify a username in Connection > Data > Auto-login username and enter the password when prompted. The problems are:

  • you don't want to enter the password every time;
  • a brute force attack will break you password and you'll end up reinstalling the server.

Instead, you should use public key authentication:

  • download puttygen.exe
  • double-click on it and choose Generate. Follow the instructions so you end up with two files public_key.pub and private_key.ppk on your hard drive.
  • on your Linux server:
    • create a file called /.ssh/authorized_keys2 (Ubuntu) or /.ssh/authorized_keys (all other Linux flavors) which contains your publickey.

      If your public_key.pub contains:

      ---- BEGIN SSH2 PUBLIC KEY ----
      Comment: "rsa-key-thomas"
      AAAAB3NzaC1yc2EAAAABJQAAAIBx8jcskAQwgmw2ZR18K1cyW4NyQDFhLYiva4WL
      DHyVgxBuo95ndyeYHoc1lk6FpRpV9jdvTCD4rGx8OT28dFyVFvDSiNxbwm/qMHhv
      Y9Vtu7842h0Hkelb5w2DU8Qvp33OQ67frQNKcvnYOP2MQxkfKVRInP/pfzuux0Ni
      ErcFxQ==
      ---- END SSH2 PUBLIC KEY ----
      

      Your ~/.ssh/authorized_keys should contain:

      ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIBx8jcskAQwgmw2ZR18K1cyW4NyQDFhLYiva4WLDHyVgxBuo95ndyeYHoc1lk6FpRpV9jdvTCD4rGx8OT28dFyVFvDSiNxbwm/qMHhvY9Vtu7842h0Hkelb5w2DU8Qvp33OQ67frQNKcvnYOP2MQxkfKVRInP/pfzuux0NiErcFxQ==
      
  • If you want only public authentication, and never a password (recommended), add the following line to /etc/ssh/sshd_config:

    PasswordAuthentication no
    
  • restart your OpenSSH server:

    sudo /etc/init.d/ssh restart

     

     

  • on your Windows computer
    • Load the session to your server
    • In Connection > SSH > Auth, put the path to your private key in tehe Private key file for authentication field.

Linux

 Startup a script at boot time, using screen.

screen is a Linux command which allows you to leave a script running even though you log out of the computer, and to go back interacting with it when you log back in, as if you had never logged of. On the OpenLBR, we use the script [openlbr.py openlbr.py] to interact with the attached mote. We start that script as soon as the Ethernet connection is up, by adding the following line to /etc/network/interfaces:

post-up screen -d -m /etc/network/if-up.d/openlbr/openlbr.py

The double flag -d -m of screen start in "detached" mode. This creates a new session but doesn't attach to it.

Whenever the interface is up, the script is running. When logging on to the OpenLBR, use the flag -list to see the identifier of the screen session running:

openlbr:~# screen -list
There is a screen on:
        1290..openlbr         (06/03/10 19:40:56)     (Detached)
1 Socket in /var/run/screen/S-root.

Then, reconnect to that session using the -r flag:

openlbr:~# screen -r 1290

To "detach" from a screen session (i.e. leave without terminating it), type Ctrl-A d. If you type exit, you will terminate it.

 Reconnect to a lost screen session.

For some reason, it happens sometimes that the screen -list command tells you there is no session running, although a ps -aux tells you there is. You can force a screen session to recreate the sessions number (in fact a file in /var/run/screen/S-root/) by sending it a CHLD signal. The following shows you a typical sequence of commands:

openlbr:~# screen -list
No Sockets found in /var/run/screen/S-root.

openlbr:~# ps -aux
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
[...]
root      1290  0.0  3.2   3000   948 ?        S<s  19:40   0:00 SCREEN -d -m /etc/network/if-up.d/wsnlbr/wsnlbr_reportdata.py
[...]
openlbr:~# kill -CHLD 1290
openlbr:~# screen -list
There is a screen on:
        1290..openlbr         (06/03/10 19:40:56)     (Detached)
1 Socket in /var/run/screen/S-root.

openlbr:~# screen -r 1290
 Kill a process without knowing its PID.
kill -9 `ps -aef | grep 'python' | grep -v grep | awk '{print $2}'`
 Replace all occurrences of a string in multiple files by another string.

 From a terminal cd to the desired directory then do the following:

 mkdir ../theNewDirectory
for i in `find . -type d`; do mkdir -p ../theNewDirectory/"$i"; done
for i in `find . -type d`; do sed 's/oldString/newString/ig' "$i"; done 

Use only /g for the command not to ignore case.

 Retrieve the IP address of an interface.
ifconfig eth0 | sed -n '/inet addr:/s/.*addr:\([^ ]*\) .*/\1/p'
 Change the name of your machine.
 echo 'openlbr5' > /etc/hostname

You need to reboot for this to take effect.

 Have your machine set its time from the Internet.
# apt-get install ntp

MAC OSX

 Connect a TelosB to a MAC OSX computer.

Install Xcode from Mac OS X install DVD. This adds developer support applications. You must check Unix development tools or something like that during the install to get unix support for the typical gcc, perl, etc. Python 2.5.4 is run by typing python2.5 at the terminal. NOTE: this may change with future releases of Apple xcode.

Install pyserial from http://pyserial.sourceforge.net/

Install virtual com port driver from http://www.ftdichip.com/Drivers/VCP.htm for MAC OSX.

A Crossbow TelosB mote shows up as something like /dev/tty.usbserial-XBRAHH4P.

Git and GitHub

 Delete a branch using TortoiseGit.

You will be removing the branch directly on GitHub. If you have not merged it back into another branch, the changes in the branch you delete will be lost.

  1. Hold Shift and right-click on your source code directory. Choose TortoiseGit, Browse Reference.
  2. On the left, expand remotes and select origin.
  3. Right-click on the branch you want to delete and select Delete remote branch.
  4. Accept the warnings if you know what you're doing.