Skip to main content

Ralsina.Me — Roberto Alsina's website

Posts about linux

The perfect Raspberry Pi setup

I am do­ing some semi-se­ri­ous Rasp­ber­ry Pi de­vel­op­men­t, so it was time I fig­ured out how to do it com­fort­ably.

My desk­top set­up is a two-­mon­i­tor con­fig­u­ra­tion, with my note­book on the ta­ble and a larg­er mon­i­tor above it. I like it, it's nice. The point­er nat­u­ral­ly goes from one screen to the oth­er in the ob­vi­ous way.

Desktop setup

Spe­cial­ly nice is that the lap­top's screen is touch and has an ac­tive pen, so I can use it nat­u­ral­ly.

But now, with the Rasp­ber­ry, I want to oc­ca­sion­al­ly show its dis­play. And that means switch­ing the mon­i­tor to it. Since I hate plug­ging and un­plug­ging things, I use one of the­se:

HDMI switch

It's a cheap tiny black plas­tic box that takes up to 5 HD­MI in­puts and switch­es be­tween them to its one out­put by click­ing a but­ton. It on­ly goes through the in­puts that have sig­nal, so since I on­ly have the lap­top's and the Pi's the but­ton tog­gles be­tween them.

If your mon­i­tor has more than one HD­MI in­put you can prob­a­bly just use that, but mine has just one.

But... what about key­board and mouse?

I could get a mul­ti­de­vice key­board and mouse, but I like the ones I have.

I could use a USB switch and tog­gle be­tween the two de­vices, but ... I don't have one.

So, I use bar­ri­er and con­fig­ure it in both the rasp­ber­ry pi and in the lap­top so that when my point­er goes "up" in­put goes to the Pi, and when it goes "down" in­put goes to the lap­top. That's ex­act­ly the same as with the du­al-dis­play se­tup, but with two com­put­er­s. Neat!

So, go ahead and con­fig­ure bar­ri­er. It's easy and there are tons of tu­to­ri­al­s.

Nex­t, make sure bar­ri­er starts when I lo­gin in­to both com­put­er­s. They way I pre­fer to do these things is us­ing sys­temd.

Put this in ~/.local/share/systemd/user/barrier.service in both machines:

[Unit]
Description=Barrier server
[Service]
Environment=DISPLAY=:0
Type=simple
TimeoutStartSec=0
ExecStart=/usr/bin/barrier
[Install]
WantedBy=default.target

Now you can make it start with systemctl --user start barrier or stop with systemctl --user stop barrier and make it start on every login with systemctl --user enable barrier

But while this is nice, it presents a prob­lem. When I am us­ing both dis­plays for the lap­top, I don't want bar­ri­er run­ning! Since I can't see the Pi's dis­play, it makes no sense.

So, I want to start bar­ri­er when the lap­top is us­ing one mon­i­tor, and stop it when it's us­ing two.

To do that, the trick is udev in the laptop. Put this (replacing my username with yours) in /etc/udev/rules.d/90-barrier.rules:

ACTION=="change", \
    KERNEL=="card0", \
    SUBSYSTEM=="drm", \
    ENV{DISPLAY}=":0", \
    ENV{XAUTHORITY}="/home/ralsina/.Xauthority", \
    ENV{XDG_RUNTIME_DIR}="/run/user/1000", \
    RUN+="/home/ralsina/bin/monitors-changed"

Basically that means "when there is a change in the configuration of the video card, run monitors-changed. Change the 1000 by your user ID, too.

The last piece of the puzzle is the monitors-changed script:

if `xrandr --listmonitors | grep -q HDMI`
then
    # The HDMI output is connected, stop barrier
    su ralsina -c '/usr/bin/systemctl stop --user barrier'
else
    # The Pi is using the monitor, start barrier
    su ralsina -c '/usr/bin/systemctl start --user barrier'
fi

And that's it!

This is the be­hav­iour now:

  • When the lap­­top is us­ing both dis­­­plays, they work nor­­mal­­ly in a "ex­­tend­ed dis­­­play" con­­fig­u­ra­­tion. They be­have like a sin­­gle large screen.

  • When I click on the HD­­MI switch and change the top dis­­­play to show the Pi's desk­­top, au­­to­­mat­i­­cal­­ly bar­ri­er starts in the lap­­top, and now the point­er and key­board change from one com­put­er to the oth­­er when the point­er moves from one mon­i­­tor to the nex­t.

  • If I click on the HD­­MI switch again, bar­ri­er stops on the lap­­top and I have a sin­­gle two-screen desk­­top again.

Ev­ery­thing be­haves per­fect­ly and I can switch be­tween com­put­ers by click­ing a but­ton.

Al­ter­na­tive­ly, we could start the bar­ri­er client when the rasp­ber­ry pi "get­s" the dis­play, and stops it when it goes away. The re­sult should be the same ex­cept for some cor­ner cas­es, but it has the added ben­e­fit of al­low­ing for a set­up with up to 5 de­vices :-)

A week using tiling windows.

It has been a lit­tle over a week since I com­mit­ted to us­ing a tiling win­dow man­ag­er.

Sure, I am cheat­ing be­cause I am ac­tu­al­ly still us­ing KDE plus Kröhnkite but my win­dows are tiled and I am lik­ing it a lot.

Why this and not i3 or what­ev­er? Be­cause I don't want to change my lifestyle, I just want my win­dows to not over­lap gen­er­al­ly.

Kröhnkite pro­vides enough tiling func­tion­al­i­ty that I get (I think) the ben­e­fits with­out the mas­sive up­heaval of giv­ing up ev­ery­thing I am used to in my desk­top. I still use the Win­dows Key (ok, ok, the "Meta" key) to launch app­s. I still have a plas­ma pan­el with plas­moids at the bot­tom of my mon­i­tor, I can still float the win­dows if I want to! I can still use most of the short­cuts from my past 24 years us­ing KDE (yes, re­al­ly) and so on.

What are some things I had to change to adap­t?

  • I had to change to fo­­cus-­­fol­lows-­­mouse. BUT for the first time since I start­ed us­ing FVWM in 1993 I am lik­ing fo­­cus-­­fol­lows-­­mouse bet­ter than click­­-­­to-­­fo­­cus. It turns out KDE's im­­ple­­men­­ta­­tion of it is quite nice and al­­most "does what I mean". As it says in the doc­s, "like click to fo­­cus, but just don't click­­".

  • I re­­moved win­­dow dec­o­ra­­tion­s. Yes, you can keep them, but they feel out of place.

  • I set thick­­er win­­dow bor­der­s. Re­­siz­ing win­­dows via short­­­cuts is just not nice in gen­er­al, so thick­­er bor­ders help.

What are some things I have liked?

  • Fixed tiling lay­out in one mon­i­­tor and float­ing in the oth­­er is awe­­some when need­ed. And I can get it in place with one key­­press! So, in gen­er­al, dy­­nam­ic, sep­a­rate lay­outs for each screen is very, very use­­ful.

  • Hav­ing a "til­ing" wm that still re­spects most WM con­ven­­tions is good. So, pop­ups float. Yay.

  • The Al­t+En­ter short­cut to make a win­dow the "im­por­tan­t" one is neat.

  • Love how max­i­miza­­­tion/min­i­miza­­­tion work­s.

What are some things I have not liked?

  • The "tiled" lay­out has mul­ti­­ple ver­­sions you can switch be­tween with Ctr­l+I/D ... and well, some­­times none of them is ex­ac­t­­ly what I wan­t? Al­­so, the high­­er num­bered ones on­­ly are use­­ful when you have many win­­dows tiling, and if you don't they don't do any­thing.

  • Since I have no win­dow dec­o­ra­tions, the bru­tal in­con­sis­ten­cy on ap­p-quit­ting short­cuts is an­noy­ing. It can be ctr­l+q or ctr­l+x or esc or what­ev­er. I end up do­ing al­t+f4 which feels like win­dows 3.11.

  • The UX of KWin scripts is a bit lack­­ing. I in­­stalled an­oth­er one a while ago, called Quar­ter-Til­ing, and I have re­­moved ev­ery trace of it from my sys­tem... ex­­cept for its short­­­cut­s, which will ap­­par­en­t­­ly pol­­lute my con­­fig di­alogs for­ev­er.

So, ex­per­i­ment will con­tin­ue!

(Sor­ry, the video is in span­ish)

The Minimal Server

I was a sysad­min for a long time. I did that for mon­ey, so I nev­er re­al­ly want­ed to spend time do­ing the same thing in my own time, which lead to a se­vere case of cob­bler's chil­dren walk­ing bare­foot in my pri­vate serv­er.

So, to­day at lunch, I de­cid­ed to clean up my garbage. So this is what I end­ed up with, which is the min­i­mal serv­er that is good enough to be gen­er­al­ly use­ful for me.

Hosting

This is a cheap VPS pro­vid­ed by the nice folks at burst.net who are not giv­ing me any­thing to speak nice things about their ser­vice. How­ev­er, I will do it any­way:

  • Crazy cheap ($5.50 but I have a 20% dis­­­count for life)

  • Good amount of mon­th­­ly band­width

  • Lots of disk space

  • Good up­­­time

  • Fast net­­work

  • Very cheap

  • De­­cent per­­for­­mance

Distribution

I had Cen­tOS 5 in­stalled, and it stays. If burst ev­er starts of­fer­ing Ubun­tu Pre­cise, I may switch. Or, since this work­s, I may not.

What's good about Cen­tOS? It's sta­ble and bor­ing.

What's bad about Cen­tOS? It's too bor­ing. Lots of cool stuff just is­n't pack­aged.

Web Server

I need to serve a bunch of do­main­s, but I have a pe­cu­liar­i­ty: they are all stat­ic sites. I wan­t:

  • Low re­­source us­age

  • De­­cent per­­for­­mance (that most­­ly in­­­volves sup­­port­ing ranges and con­­tent ne­­go­ti­a­­tion)

  • Sta­ble

  • Sup­­port di­rec­­to­ry in­­dex­es

  • Easy con­­fig­u­ra­­tion

  • Vir­­tu­al do­­mains by name

Al­most any serv­er works well for this. Even Apache, ex­cept for the easy con­fig­u­ra­tion bit. I end­ed up with gatling be­cause it fits those cri­te­ria fair­ly well.

  • It us­es about 1.4MB of RAM , which is al­ways nice in a VPS

  • It's pret­­ty fast

  • Has not crashed in 2 hours?

  • Sup­­ports in­­dex­es

  • Here's the con­­fig­u­ra­­tion: "-c /s­rv/www -P 2M -d -v -p 80 -F -S" (yes, there is no con­­fig file at al­l)

  • Vir­­tu­al do­­mains are just fold­ers and sym­links in­­­side /s­rv/www which is the eas­i­est pos­sil­ble way to do it.

  • It sup­­ports re­­verse prox­­y­ing for when I want to try a python web app I am work­ing on.

Mail Server

No, I don't want a mail serv­er. I have gmail and/or a re­al mail serv­er for that. I want to get the mails from cron. For this, I used ssmtp and an ex­tra gmail ac­coun­t. It work­s, and here's the whole con­fig:

root=roberto.alsina@gmail.com
mailhub=smtp.gmail.com:587
UseTLS=YES
UseSTARTTLS=YES
AuthMethod=LOGIN
AuthUser=roberto.alsina.3@gmail.com
AuthPass=notputtingthetrueoneheredude

The best I can say about this con­fig­u­ra­tion is that it work­s, and does­n't in­volve run­ning a dae­mon.

Misc

For when I need to be in two places at the same time: Open­VPN rules, and there is no ar­gu­men­t. I have a squid run­ning oc­ca­sion­al­ly, and there is a Quas­sel core for IRC stuff. I in­stalled mosh to make ssh less painful, rsync han­dles file de­ploy­ment and back­up stor­age, cron sched­ules stuff, and that's it.

Status

Plen­ty of free RAM and CPU (yes, that's the full process list):

[root@burst1 ~]# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1   2156   664 ?        Ss   22:01   0:00 init [3]
root      1135  0.0  0.1   2260   576 ?        S<s  22:01   0:00 /sbin/udevd -d
root      1518  0.0  0.1   1812   572 ?        Ss   22:01   0:00 syslogd -m 0
root      1594  0.0  0.1   7240  1032 ?        Ss   22:01   0:00 /usr/sbin/sshd
root      1602  0.0  0.2   4492  1112 ?        Ss   22:01   0:00 crond
root      1630  0.0  0.1   5684   716 ?        Ss   22:01   0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a pam -n 2
root      1631  0.0  0.0   5684   444 ?        S    22:01   0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a pam -n 2
root      1636  0.0  0.2   3852  1372 ?        S    22:01   0:01 /opt/diet/bin/gatling -c /srv/www -P 2M -d -v -p 80 -F -S
root      1677  0.0  0.2   4284  1232 ?        Ss   22:02   0:00 SCREEN /root/quasselcore-static-0.7.1
root      1678  0.0  2.1  36688 11148 pts/0    Ssl+ 22:02   0:03 /root/quasselcore-static-0.7.1
root      3228  1.0  0.7  12916  4196 ?        Ss   23:28   0:13 mosh-server new -s -c 8
root      3229  0.0  0.3   3848  1588 pts/2    Ss   23:28   0:00 -bash
root      3275  0.0  0.1   2532   908 pts/2    R+   23:48   0:00 ps aux
[root@burst1 ~]# w
 23:49:03 up  1:47,  1 user,  load average: 0.00, 0.01, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/2    186.153.52.253   23:28    0.00s  0.01s  0.00s w
[root@burst1 ~]# free
             total       used       free     shared    buffers     cached
Mem:        524800      49100     475700          0          0          0
-/+ buffers/cache:      49100     475700
Swap:            0          0          0

All things con­sid­ered, fair­ly hap­py with the re­sult.

Ubuntu One APIs by Example (part 1)

One of the nice things about work­ing at Canon­i­cal is that we pro­duce open source soft­ware. I, specif­i­cal­ly, work in the team that does the desk­top clients for Ubun­tu One which is a re­al­ly cool job, and a re­al­ly cool piece of soft­ware. How­ev­er, one thing not enough peo­ple know, is that we of­fer damn nice APIs for de­vel­op­er­s. We have to, since all our client code is open source, so we need those APIs for our­selves.

So, here is a small tu­to­ri­al about us­ing some of those APIs. I did it us­ing Python and PyQt for sev­er­al rea­son­s:

  • Both are great tools for pro­­to­­typ­ing

  • Both have good sup­­port for the re­quired stuff (D­Bus, HTTP, OAu­th)

  • It's what I know and en­joy. Since I did this code on a sun­­day, I am not go­ing to use oth­­er things.

Hav­ing said that, there is noth­ing python-spe­cif­ic or Qt-spe­cif­ic in the code. Where I do a HTTP re­quest us­ing Qt­Net­work, you are free to use lib­soup, or what­ev­er.

So, on to the nuts and bolt­s. The main pieces of Ubun­tu One, from a in­fra­struc­ture per­spec­tive, are Ubun­tu SSO Clien­t, that han­dles us­er reg­is­tra­tion and login, and Sync­Dae­mon, which han­dles file syn­chro­niza­tion.

To in­ter­act with them, on Lin­ux, they of­fer DBus in­ter­faces. So, for ex­am­ple, this is a frag­ment of code show­ing a way to get the Ubun­tu One cre­den­tials (this would nor­mal­ly be part of an ob­jec­t's __init__):

# Get the session bus
bus = dbus.SessionBus()

:
:
:

# Get the credentials proxy and interface
self.creds_proxy = bus.get_object("com.ubuntuone.Credentials",
                        "/credentials",
                        follow_name_owner_changes=True)

# Connect to signals so you get a call when something
# credential-related happens
self.creds_iface = dbus.Interface(self.creds_proxy,
    "com.ubuntuone.CredentialsManagement")
self.creds_proxy.connect_to_signal('CredentialsFound',
    self.creds_found)
self.creds_proxy.connect_to_signal('CredentialsNotFound',
    self.creds_not_found)
self.creds_proxy.connect_to_signal('CredentialsError',
    self.creds_error)

# Call for credentials
self._credentials = None
self.get_credentials()

You may have no­ticed that get_­cre­den­tials does­n't ac­tu­al­ly re­turn the cre­den­tial­s. What it does is, it tells Sync­Dae­mon to fetch the cre­den­tial­s, and then, when/if they are there, one of the sig­nals will be emit­ted, and one of the con­nect­ed meth­ods will be called. This is nice, be­cause it means you don't have to wor­ry about your app block­ing while Sync­Dae­mon is do­ing all this.

But what's in those meth­ods we used? Not much, re­al­ly!

def get_credentials(self):
    # Do we have them already? If not, get'em
    if not self._credentials:
        self.creds_proxy.find_credentials()
    # Return what we've got, could be None
    return self._credentials

def creds_found(self, data):
    # Received credentials, save them.
    print "creds_found", data
    self._credentials = data
    # Don't worry about get_quota yet ;-)
    if not self._quota_info:
        self.get_quota()

def creds_not_found(self, data):
    # No credentials, remove old ones.
    print "creds_not_found", data
    self._credentials = None

def creds_error(self, data):
    # No credentials, remove old ones.
    print "creds_error", data
    self._credentials = None

So, ba­si­cal­ly, self­._­cre­den­tials will hold a set of cre­den­tial­s, or None. Con­grat­u­la­tion­s, we are now logged in­to Ubun­tu One, so to speak.

So, let's do some­thing use­ful! How about ask­ing for how much free space there is in the ac­coun­t? For that, we can't use the lo­cal APIs, we have to con­nect to the server­s, who are, af­ter al­l, the ones who de­cide if you are over quo­ta or not.

Ac­cess is con­trolled via OAuth. So, to ac­cess the API, we need to sign our re­quest­s. Here is how it's done. It's not par­tic­u­lar­ly en­light­en­ing, and I did not write it, I just use it:

def sign_uri(self, uri, parameters=None):
    # Without credentials, return unsigned URL
    if not self._credentials:
        return uri
    if isinstance(uri, unicode):
        uri = bytes(iri2uri(uri))
    print "uri:", uri
    method = "GET"
    credentials = self._credentials
    consumer = oauth.OAuthConsumer(credentials["consumer_key"],
                                   credentials["consumer_secret"])
    token = oauth.OAuthToken(credentials["token"],
                             credentials["token_secret"])
    if not parameters:
        _, _, _, _, query, _ = urlparse(uri)
        parameters = dict(cgi.parse_qsl(query))
    request = oauth.OAuthRequest.from_consumer_and_token(
                                        http_url=uri,
                                        http_method=method,
                                        parameters=parameters,
                                        oauth_consumer=consumer,
                                        token=token)
    sig_method = oauth.OAuthSignatureMethod_HMAC_SHA1()
    request.sign_request(sig_method, consumer, token)
    print "SIGNED:", repr(request.to_url())
    return request.to_url()

And how do we ask for the quo­ta us­age? By ac­cess­ing the http­s://one.ubun­tu.­com/api/quo­ta/ en­try point with the prop­er au­tho­riza­tion, we would get a JSON dic­tio­nary with to­tal and used space. So, here's a sim­ple way to do it:

    # This is on __init__
    self.nam = QtNetwork.QNetworkAccessManager(self,
        finished=self.reply_finished)

:
:
:

def get_quota(self):
    """Launch quota info request."""
    uri = self.sign_uri(QUOTA_API)
    url = QtCore.QUrl()
    url.setEncodedUrl(uri)
    self.nam.get(QtNetwork.QNetworkRequest(url))

Again, see how get_quo­ta does­n't re­turn the quo­ta? What hap­pens is that get_quo­ta will launch a HTTP re­quest to the Ubun­tu One server­s, which will, even­tu­al­ly, re­ply with the da­ta. You don't want your app to block while you do that. So, QNet­workAc­cess­Man­ag­er will call self­.re­ply_fin­ished when it gets the re­spon­se:

def reply_finished(self, reply):
    if unicode(reply.url().path()) == u'/api/quota/':
        # Handle quota responses
        self._quota_info = json.loads(unicode(reply.readAll()))
        print "Got quota: ", self._quota_info
        # Again, don't worry about update_menu yet ;-)
        self.update_menu()

What else would be nice to have? How about get­ting a call when­ev­er the sta­tus of sync­dae­mon changes? For ex­am­ple, when sync is up to date, or when you get dis­con­nect­ed? Again, those are DBus sig­nals we are con­nect­ing in our __init__:

self.status_proxy = bus.get_object(
    'com.ubuntuone.SyncDaemon', '/status')
self.status_iface = dbus.Interface(self.status_proxy,
    dbus_interface='com.ubuntuone.SyncDaemon.Status')
self.status_iface.connect_to_signal(
    'StatusChanged', self.status_changed)

# Get the status as of right now
self._last_status = self.process_status(
    self.status_proxy.current_status())

And what's sta­tus_changed?

def status_changed(self, status):
    print "New status:", status
    self._last_status = self.process_status(status)
    self.update_menu()

The pro­cess_s­ta­tus func­tion is bor­ing code to con­vert the in­fo from sync­dae­mon's sta­tus in­to a hu­man-read­able thing like "Sync is up­-­to-­date". So we store that in self­._last_s­ta­tus and up­date the menu.

What menu? Well, a QSys­tem­Tray­I­con's con­text menu! What you have read are the main pieces you need to cre­ate some­thing use­ful: a Ubun­tu One tray app you can use in KDE, XFCE or open­box. Or, if you are on uni­ty and in­stall sni-qt, a Ubun­tu One app in­di­ca­tor!

http://ubuntuone.com/7iXTbysoMM9PIUS9Ai4TNn

My Ubun­tu One in­di­ca­tor in ac­tion.

You can find the source code for the whole ex­am­ple app at my u1-­toys project in launch­pad and here is the full source code (miss­ing some icon re­sources, just get the re­po)

Com­ing soon(ish), more ex­am­ple app­s, and cool things to do with our APIs!


Contents © 2000-2021 Roberto Alsina