Pulling strings on Raspberry Pi

I got my Raspberry PI Starter Kit this week. The Kit is very nice, as it comes packaged with everything you need in order to get your PI up and running ASAP. Just plugin the SD-Card, connect Ethernet cable and USB Power supply and your ready to go!

Booting Up

After the PI has booted from the provided Image on the SD-Card, it is accessible through SSH:

ssh [email protected]

It’s a good idea to copy the SSH public key to the machine, so that you do not have to type in the passphrase everytime:

ssh [email protected] "mkdir -p .ssh"
scp ~/.ssh/id_dsa.pub [email protected]:.ssh/authorized_keys

When the provided Raspberry PI distro is outdated, you can update it with the builtin admin tool:

sudo raspi-config 
=> select update, exit
sudo reboot

Bootstrap for Puppet

As an experiment, I wanted to provision my PI with Puppet. Since the PI comes packaged with Python as a programming language, you need to install Ruby in order to run Puppet.
There are several Ruby Versions available as Debian packages, but I wanted to try out RBenv just for fun. This is only an option if you have plenty of time, cause building a Ruby from source takes round about 2 hours…

# update aptitude
sudo apt-get update -y
# install some basics like git and support for ruby to compile and puppet to work
sudo apt-get install build-essential zlib1g-dev libssl-dev libreadline-dev git-core curl libyaml-dev -y

# clone the rbenv repo and setup the env
git clone git://github.com/sstephenson/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.profile
echo 'eval "$(rbenv init -)"' >> ~/.profile
exec $SHELL -l

# add the ruby-build plugin and install a ruby 1.9.3
git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 1.9.3-p327
# set the ruby as the global ruby version
rbenv global 1.9.3-p327
rbenv rehash
# check if it's working fine
ruby -v

# add the rbenv sudo plugin
git clone git://github.com/dcarley/rbenv-sudo.git ~/.rbenv/plugins/rbenv-sudo

Having a running Ruby, installing Puppet is just a matter of minutes, as it is distributed as a Ruby Gem. It’s a good idea though to disable RDoc and RI documentation generation to speed up the installation:

# puppet needs it's own user and group
sudo useradd --comment "Puppet" --no-create-home --system --shell /bin/false puppet
# disable documentation generation for gems
echo "gem: --no-ri --no-rdoc" > ~/.gemrc
# install the gem
gem install puppet
# make puppet executables available through rbenv
rbenv rehash
# check if facter is installed properly
facter

If facter complains about a problem with the fact fqdn, just add a real hostname to /etc/hosts:

sudo vi /etc/hosts
127.0.1.1       raspberrypi.nofail.de raspberrypi

First Puppet run

After that puppet should run without warnings and you can start writing the first manifest:

mkdir /home/pi/puppet
cd /home/pi/puppet
vi base.pp

Add this to base.pp to install VIM to the Raspberry PI:

package { "vim":
  ensure => installed,
}

This manifest can be applied with rbenv sudo:

rbenv sudo puppet apply base.pp

Et voila, VIM is installed on your PI.

Samba

Working with the tools on my Mac is cool, so sharing a directory on the PI is a nice way of editing locally and running stuff on the server. Deriving from a basic installation of Samba that’s what needs to be done on the PI:

# install samba
sudo apt-get install samba samba-common-bin
# update config
sudo vi /etc/samba/smb.conf

In /etc/samba/smb.conf uncomment line security = user and add the following section:

[Puppet]
  comment = Puppet share 
  path = /home/pi/puppet
  writeable = yes
  guest ok = no

Once you did this, add a Samba user and restart the service:

# make shared dir writable
chmod 777 /home/pi/puppet
# add the user for access over smb
sudo smbpasswd -a pi
# restart smb
sudo /etc/init.d/samba restart

Using ⌘+k on the Mac connects to a remote server. Enter smb://[email protected] and connect to the Puppet share. You can now access your files via open /Volumes/Puppet/.

DynDNS

In order to access the PI over the internet, subscribing to a free Dynamic DNS service like NO-IP is a nice way to get a static hostname for name resolution.
NO-IP has some Tools available for download that help you keeping the switching IP up to date. Since the provided binaries did not work on the PI, the NO-IP client needs to be compiled from source.

On my Airport Extreme I enabled port-forwarding so that i can route services to the PI.

WiFi

If you want the PI to connect to your wireless network, just buy yourself a mini wifi USB adapter. It’s pretty easy to get the PI up and running with this on your local wifi, just enable the network device in /etc/network/interfaces, mine looks like this:

# /etc/network/interfaces
auto wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa.config

auto eth0
iface eth0 inet dhcp

and add the wifi connection settings to /etc/wpa.config:

# /etc/wpa.config
network={
  ssid="YOUR_SSID"
  proto=RSN
  key_mgmt=WPA-PSK
  pairwise=CCMP TKIP
  group=CCMP TKIP
  psk="YOUR_PASSWORD"
}

Raspberry PI with cream and sugar!

Bringing Usergroups on Ruby

I am one of the organizers of the local Ruby Usergroup in Hamburg for over two years now. We meet on a regular basis, every second wednesday each month. Some times we meet in a bar to grab some beers, some times we have full fledged community events with sponsors and high quality talks.

All this is currently managed using the On Ruby plattform that was created to bring the events close to

the Ruby devs. It also eases the process of creating events, submitting talks, finding locations and publishing all that to Twitter, Google+ and Mailinglists.

Some month ago, the project was forked by Cologne.rb and they built their custom version for the Ruby Usergroup in Cologne. After that some more Usergroups wanted to use the tool and that was the reason we merged the Cologne.rb codebase and created a whitelabel version of the application, which is customizable in many regards. It also comes with a Mobile version for iPhone and Android.

If you are interested in joining Hamburg, Cologne, Bremen, Saarland and Karlsruhe just follow the guide for creating your own OnRuby Usergroup!

Karotz + Ruby = Love

I made myself a little present this christmas by putting a Karotz under my christmas tree. This little digital bunny robot is the 3rd generation of a gadget that was once known as Nabaztag.

Karotz can connect to the internet and you can deploy applications on it. It’s a tiny multitalent, speaks, blinks, turns his ears, takes photos and plays musik. The really cool stuff about all this, is that you can also access it via a REST-api.

I was a little disturbed by the bad documentation of the api, but since Karotz has had a pretty shaken history, I was willing to see over it. Nevertheless I had a really hard time figuring out how to use the API, especially the interactiveMode sessions, which are crucial for interacting with Karotz. That’s why I wanted to give you a short HOW-TO wrapup on it.

Basic Setup

First of all you need to have a Karotz up and running, like it’s described in the handbook. Register yourself at karotz.com and click on the lab button at the bottom of the page. Once you registered yourself for all the developer stuff, you need to register a new application for yourself in order to get access to the credentials needed to talk to Karotz.

In order to get your own application, you need to create a descriptor.xml and package it as a zip-file and then load it up to the appstore and then deploy it to your bunny. Here is an example, which exposes the install-id of your application, which you need to accesss your Karotz:

<descriptor>
  <version>0.0.1</version>
  <accesses>
    <access>tts</access>
    <access>ears</access>
    <access>led</access>
    <access>multimedia</access>
  </accesses>
  <deployment>external</deployment>
  <parameters>
    <parameter key="showInstallUuid" value="true"/>
  </parameters>
</descriptor>

Have a look at this Christops Blog if you don’t get it working for yourself.

Using the Gem

There are already some code-examples on the developer-pages on how to get an interactive_id for your Karotz and some code has been released for Ruby as ruby-karotz here and here none of them exposing a nice API or describing the process of how to get all the peaces of the puzzle together. That’s why I am currently writing this…

So here is an example of how to interact with the karotz gem:

Karotz::Configuration.configure do |config|
  config.install_id = ENV['KAROTZ_INSTALL_ID']
  config.api_key    = ENV['KAROTZ_API_KEY']
  config.secret     = ENV['KAROTZ_SECRET']
end

Karotz::Client.session do |karotz|
  karotz.ears
  karotz.led
  karotz.say
  karotz.play
end

This will rotate Karotz ears, blink the LED, say ‘test’ and let it play the A-TEAM theme!

FTW!

Ruby Quirks

Once in a while I come accross some Ruby code where I don’t know why it is doing stuff the way it does…

Ternary Operator

I am using the Ternary Operator quite a lot, because it keeps the code concise and often times more readable then long if-else statements. One thing that I discovered just recently is the following:

val = something ? 'this' : 'that'

If you look closely, you will see that there is not a comparison == but an assignment = operator present. The interesting fact though is where Ruby puts parenthesis in this code:

val = (something ? 'this' : 'that')

Makes a lot of sense, but is not obvious, especially if you are debugging some library code.

Another cool thing that you can do with the operator is nesting:

val == 0 ? 'zero' : val == 1 ? 'one' : 'other'
# is interpreted as
(val == 0 ? 'zero' : (val == 1 ? 'one' : 'other'))

But most of the times you are better of with Switch Cases.

Switch Case

There are some pretty cool features in the Ruby Switch Case. You can switch by class if you like:

case "some string"
when Integer
  puts "i am an int"
when String
  puts "i am a string"
else
  puts "dunno"
end

This works, because Ruby uses the === method to compare in a when block. So the when code above evaluates to:

String === "some string"

The cool thing is that you can implement the === method yourself and add some Ruby magic to the Switch Case.

But be aware of some stuff that might bite you while using Switch Cases! You should know that Ruby allows multiple arguments in a when block:

case val
when 5, 7
  puts "good numbers"
else puts "bad numbers"
end

It’s also important to know that you need to add a newline before writing your block code. It’s also possible to write oneliners by using a semicolon or the then keyword, otherwise the following code will be interpreted as belonging to the when condition:

case val
when 5, 7; puts "good numbers"
when 0 then puts "empty"
when 1, puts "syntax error"
else puts "bad numbers"
end

Older versions of Ruby also supported a syntax with a : at the end instead of a ;, wich looks kind of strange:

case val
when :number: puts "numbers"
else puts "not a numbers"
end

Missing something

Since the Ruby parser allows a lot of flexibility, it’s possible to implement stuff which does not make sense at all. For example this statement which misses the if at the beginning of the condition:

def test_failing
  else puts "invalid"
  end
end

Evaluating this method will fail (or even kill the ruby process):

warning: else without rescue is useless
syntax error, unexpected keyword_end, expecting $end

One thing that happens to me quite often, is that there are implicit things going on if you forget to add commas in your code, while I am not sure how and why they work:

puts "what" "the" "fuck" # => "whatthefuck"
puts String Integer # => Integer

Everything is a Method

Well not everything in Ruby is implemented as a method, but there a lot of things that you can at least use like methods. Did you know for example, that you can call the accessibility modifiers in Ruby like methods? This is pretty handy if you want to mark only some methods:

def my_method; end
private :my_method

It’s also quite important to know that method objects provide a lot of interesting information. Especially if you are doing some serious debugging with a lot of inheritance and Ruby magic involved:

"".method(:class).owner # => Kernel
class A
  def b;end
end
# works only in 1.9
A.new.method(:b).source_location # => ["...test.rb", 3]

When talking about methods, it’s worth knowing the keywords that are used in Ruby and in which context they can be used. A good example for this is the * character, which can be used quite differently:

# as a simple method
1 * 2
# for varargs in method signatures
def method_name(*args)
# for unsplatting arrays
some_method_that_has_three_args(*[1, 2, 3])

You should also be aware that some operators behave different from others:

def some_array
  @some_array ||= []
end

def doit
  some_array << [3,4] # ok
  some_array += [6,7] # raises undefined method `+' for nil:NilClass
end

Predefined Variables

In analogy to Pearl, Ruby provides a bunch of Predefined Variables that are worth knowing. A lot of them contain information about the current environment, code or execution context.

There are f.e. some extra variables for matching groups in Rubys regular expressions:

"hey_you" =~ /(.*)_(.*)/
$1 # => hey
$2 # => you
$0 # => .../test.rb

Unfortunately $0 has nothing to do with match groups, but is the name of the current executed program…

Naming Best Practices

When working with Ruby you get used to some best practices when it comes to names. This is important, because several thing are evaluated differently depending on up- and downcase:

CONSTANTS_ARE_UPPER_SNAKE_CASE
ClassesAreCamelCase
Modules::Should::Map::To::Folder::Structure

So it is quite surprising that Ruby comes with an Array() method which transforms everything it gets into an array unless it’s already an array:

Array("string") # => ["string"]
Array(["string"]) # => ["string"]

It’s also worth having a deep look into the Ruby documentation about Arrays and the Enumerable Module, because they provide a bunch of really cool helpers that can save you an everage developers lifetime if you know them by heart.

For some more cool Ruby tricks have a look at this Rubyinside post.

If you feel like sharing some more Ruby wisdom feel free to post a comment or contribute some sugar!