Commenting and Uncommenting in vi

Sometimes I have to edit large config files in vi. Typically I have to comment out a block or even the whole file. Here’s the command to insert a # before every line in the file:

:%s/^/# /

To comment the next 4 lines (. is current line , . + 3 lines more)

:.,.+3s/^/# /

And to uncomment the first character from every line:

:%s/^#  

Or uncomment a section:

:.,.+3s/^#

Updating my Raspberry Pi’s IP address on a distant server via SFTP

Now I have my external IP address, I want to collect it on a regular basis and push it to a server that accepts SFTP. Now sadly, that server doesn’t allow me to use passkey files, so I have to workaround using sshpass (a great little module allowing to pass passwords to the SSH commands – install as usual with apt-get install sshpass ).

The EOF at the end of the sftp command is to ensure that I am passing the rest of the commands to the sftp command. I could also use a -b flag and a file, but it would mean one more file to deal with.

#!/bin/bash
wget -q -O- http://ip4.me |
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' > ip.txt
sshpass -p XXXXX sftp -oPort=22 username@xxx.cloudplush.com <<-EOF
cd /location
put ip.txt
bye

Then it was a simple matter of putting that in a crontab job, running it every five minutes is enough. Calling crontab crons.txt launched the job. crontab -l lists the jobs.

*/5 * * * * ~/go.sh >/dev/null

Raspberry pi

Since I’ve finally had time to do something with my Raspberry Pi, I’ve set it up as a file server for macs and iTunes server for the house. I’m using a 7 port USB hub, powered, that uses 2 4-port hubs inside. As a drive, I used a Toshiba 500 gig USB powered HDD that supports USB3. The Raspberry is powered directly from the USB hub, so there is only one power supply for the setup with 3 USB cables (1 hub to pi for power supply, 1 pi to hub data, 1 hub to hdd data cable) and 1 ethernet cat5 cable.

The distribution is a standard Raspbian that I keep up to date using sudo apt-get update and sudo apt-get upgrade. (Linux raspberrypi 3.2.27+ #250 PREEMPT Thu Oct 18 19:03:02 BST 2012 armv6l)

To mount the Toshiba HDD, I first used dmesg to watch for where the USB drive appeared when connected to the USB hub. For me it was sda : sda1. So I mounted it using mount and after verifying it worked, edited the /etc/fstab to make the drive auto mount on boot. I added the line: /dev/sda1 /srv/toshiba auto defaults 0 0

To act as a file server for mac, I used the software netatalk. It’s quick to install and requires practically no configuration and it worked out of the box. My raspberry appeared on the mac within seconds with the home drive shared, then it was a simple share of the extra folders.

To Install: apt-get install netatalk
To configure which folders are shared: vi /etc/netatalk/AppleVolumes.default
(remember to check the rights on these folders if you have a problem)
To start/stop/restart the service: sudo /etc/init.d/netatalk start (or stop or restart)

To act as an iTunes server, I used forked-daapd. Again, worked out of the box with just a touch of configuration. The config file is very easy. I didn’t used the remote function of daapd yet, using the box only as a server, not as a playback device.

To install: apt-get install forked-daapd
To configure where the music is at: sudo vi /etc/forked-daapd.conf
To start/stop the service: sudo /etc/init.d/forked-daapd start (or stop)

With that installed, I had “Music on Raspberry pi” showing up in my iTunes side panel. It just worked.

The only problem I was getting was that the playback of certain songs was getting interrupted in midstream and when I changed songs in iTunes, there was a very long “Opening URL” message box coming up. The Toshiba hard drive where the music is located was running really slow and any access loaded the CPU to 100% for far too long. Similar problems had been reported on the raspberry pi forum. To diagnose what was the issue, I used hdparm to check the performance of the HDD and lsusb to find out the tree structure of the USB hub.

Run a performance test of drive sda: hdparm -tT /dev/sda

My first test gave me a speed of ~280 KB/s. Abysmal performance. After checking the logs with dmesg, I saw many USB reset messages with respect to the USB drive. With lsusb, I confirmed the HDD was connected to the second internal usb hub of my powered hub, so I changed port until I found one that is connected to the first hub. The performance difference was instantaneous: 26 MB/s. Connecting it directly to the raspberry pi proved to be too much of a power drain for the pi’s usb port.

List the tree of USB hubs and devices connected: sudo lsusb -t

A couple more things remained before I could leave my pi headless in the closet next to the router: I changed the default password (raspberry) to another one using the command passwd.

Then I installed tightvncserver on the pi to serve the desktop over the network to a mac or a windows computer. I don’t launch it automatically on logging in, I only launch a graphical environment occasionally, so it can live on the command line for the time being.

To install: sudo apt-get install tightvncserver
To launch: tightvncserver
To create a display on port 0 with a 1024×768 resolution and 24 bit colour depth: vncserver :0 -geometry 1024×768 -depth 24

Over the network I could now SSH into the pi (On windows I use Putty, on mac I just use SSH from the command shell) and launch the GUI on another computer.

Finally, I connected to my home network and forwarded the SSH (port 22) service to my raspberry pi.

Next time, I want to set-up a dynamic dns for the Pi, so that I can always gain access to it, even if my home router reboots and changes ip. I would like it to use a subdomain of my cloudplush address, but I don’t know if my hosting provider iPower supports that. Another option would be to email or tweet the ip address of my home router every time it changes.

I also saw an interesting AirPi project online, where the pi works as an airplay receiver, this would be an interesting addition to my pi. For this, I need to get a wireless adapter.

I want to investigate using the pi with a LAMP stack on it and OwnCloud to serve as a private owned dropbox.

Finally, I really should stop relying on passwords with my SSH connection and start using an SSH keyfile, Especially if it will be more and more internet facing.

The command history to helped me remember all the things I did.

Making Fortran DLLs to interface with VBA in Excel

Note to self, Remember:
  • When working with Intel visual fortran, always perform a static link (/MT) in the command line options so that you don’t dependent on a DLL being present on the target machine.
  • DLLs need Kernel32.lib to be added to the dependencies
  • ByVal in VBA doesn’t always mean ByVal, when calling a DLL it means “Copy then give a Ref”, so on the Fortran side, get the address by reference.

Styling a Checkbox as an Ellipse

I wanted to restyle a WPF Checkbox so that is used an Ellipse as a image. It also had to support the IsThreeState property and show a clear sign that the value is null.

The image above shows the different styles available (Grey: False, Green: True, White and Barred: Null).

<Style x:Key="EllipseCheckBoxStyle" TargetType="CheckBox">
 <Setter Property="SnapsToDevicePixels" Value="true"/>
 <Setter Property="OverridesDefaultStyle" Value="true"/>
 <Setter Property="Template">
   <Setter.Value>
     <ControlTemplate TargetType="CheckBox">
       <Border x:Name="Border" Width="32" Height="32" Background="Transparent" CornerRadius="1" BorderThickness="1" BorderBrush="DarkGray">
         <Grid>
           <Ellipse x:Name="MyEllipse" MinHeight="5" MinWidth="5" Stretch="Fill" Fill="{Binding Path=FilterValue, Converter={StaticResource BoolToRG}}"></Ellipse>
           <Line x:Name="Diag" Stroke="Transparent" X1="0" Y1="0" X2="1" Y2="1" Stretch="Fill"/>
         </Grid>
       </Border>
 
     <ControlTemplate.Triggers>
       <Trigger Property="IsChecked" Value="{x:Null}">
         <Setter TargetName="Diag" Property="Stroke" Value="Black" />
       </Trigger>
       <Trigger Property="IsMouseOver" Value="true">
         <Setter TargetName="Border" Property="Background" Value="Orange" />
       </Trigger>
     </ControlTemplate.Triggers>
   </ControlTemplate>
 </Setter.Value>
 </Setter>
</Style>

The converter itself is simply a Bool? to colour converter that I use. You could also set the colour as a Trigger on the control template itself on the IsChecked property like I did for the Null value.