Simple xmpp standup meeting notification for the team

I guess you all know it – when it is standup time some notice it immediately while others are still on the phone or some still digging in the code. It does help to have a calendar notification but everyone has to enable it etc.

At my work we are all using the company wide jabber service and it’s a great tool I think. With these few steps you can build a simple notifier for your team.

First you’ll have to install sendxmpp. For debian:
% apt-get install sendxmpp

The usage is easy and you can write a simple script file and place it in your PATH.
% cat bin/standupnote
#!/bin/sh

MEMBERS="
fred@jabber.example.com
barney@jabber.example.com
pebbles@jabber.example.com
"

echo "Reminder: Standup Meeting! :-)" | sendxmpp $MEMBERS

Your credentials have to be added to added to the ~/.sendxmpprc file. Don’t forget to chmod 600 it!
echo "user@jabber.example.com password componentname" > ~/.sendxmpprc && chmod 600 ~/.sendxmpprc

And finally you should install a cronjob to run the script at standup time. Simply run as user and edit the config file:
% crontab -e
# m h dom mon dow command
45 10 * * 1,2,3,4,5 /home/fred/bin/standupnote

Yes, our meeting is not until 10:45 … :-\

Clojure store persistent data structures gotcha – load-file size limit

In clojure – the data structure and their default representation are suited as readable and portable format to persist data. But there is a small pitfall in using it.

Data Structure example:

{
  :request-time 2636,
  :status 200,
  :headers
  {
    "server" "Server",
    "content-encoding" "gzip",
  }
}

Be aware that this function is intended to load code only. If your data structures or a string in them grow bigger than around 65,535 it crashes.

Exception similar to:

java.lang.ClassFormatError: Unknown constant tag 49 in class file parse$eval13

Please use read-string instead.

Example: (read-string (slurp "data.clj"))

Source: Rich Hickey on google groups Google Groups

XBMC windowed mode calibration (overscan) settings not remembered

I love XBMC, it is a great free media center, controllable via android phone with lot’s of cool plugins and even blue ray support.

But there was this bug annoying me. I am using two monitors and want to keep the mouse non captured, therefore using xbmc in maximized windowed mode instead of fullscreen. This works great but the overscan settings get lost on every restart, hiding great parts of the GUI.

The settings are written correctly to the „resolution“ node in guisettings.xml with the description „Windowed“ but are not loaded. After the next start the default settings are used and the config overwritten.

These forum posts or some posts of them might be related:
http://forum.xbmc.org/showthread.php?tid=104735
http://forum.xbmc.org/showthread.php?tid=132776

I tried to fix the problem myself and got up with a patch. There were a couple of problems preventing the settings from being loaded and applied – see pull request for details. It also seems like it makes sense to reset the overscan settings when the window is resized but upon initial start they should be loaded from the config.

See Ticket http://trac.xbmc.org/ticket/11861
Pull Request https://github.com/xbmc/xbmc/pull/1246

Edit:

Well, the xbmc folks answered quite fast, see below. Too bad but until then I got my patch.

FernetMenta commented
check out #1231
There are (and should) no calibration settings for windowed mode. Your original problem mentioned in the ticket 11861 will be fixed by not grabbing the mouse.

Clojure Game Of Life App on Heroku

A while ago I created a heroku account to try it out. They allow you to host clojure web apps in the cloud. One worker is for free and there are also quite more languages supported.

In order to practice some clojure I implemented game of life and packaged it into a lib. Here does leiningen help you a lot, it is the maven of the clojure world and also creates maven compatible jar files.

My app was originally printing out the game of life world to the CLI but now outputs it as text/plain.

I won’t repeat the steps to setup heroku since they are explained very well on heroku: http://devcenter.heroku.com/articles/clojure

The result can be accessed here: http://gentle-journey-9851.herokuapp.com/

The state is globally shared through all requests. So don’t be surprised if there are some generations missing.

The code and library is available on github. The game of life source code is included in the jar, in case some is interested. I might have a different post about this later.

https://github.com/dedeibel/herokus_game_of_clojure_life

To start the app:

Prerequisites: leiningen

To run locally, simple run

$ lein run -m herokutest.web 5000

or

$ foreman start

And visit http://localhost:5000

(ns herokutest.web
  (:use [game_of_life.cell :only (new_cell)])
  (:use [game_of_life.world_printer :only (to_string)])
  (:use [game_of_life.world_builder :only (from_string)])
  (:use [game_of_life.game :only (next_generation)])
  (:use ring.adapter.jetty)
)

(def twentyfour_and_more
"xx
,xx
,
,
,
,                                   x x  xxx
,                                   x x    x
,                                   xxx  xxx
,                                     x  x
,                                     x  xxx
,                                                                                                   xx  
,                                                                                                  x  x
,                                                                                                 x    x
,                                                                                                x      x
,                                                                                                x      x
,                                                                                                 x    x
,                                                                                                  x  x
,                                                                                                   xx"
)

(def counter (atom 0))
(def world (atom (from_string twentyfour_and_more new_cell)))

(defn app [req]
  (let [current @world]
    (swap! counter inc)
    (swap! world next_generation)
    {:status 200
     :headers {"Content-Type" "text/plain"}
     :body 
       (str "Game Of Life (Step " @counter "):\n" (to_string current))
    }
  )
)

(defn -main [port]
  (run-jetty app {:port (Integer. port)}))

Short review: Zoe’s Tale from John Scalzi (Old Man’s War)

This a short review I wrote about Zoe’s Tale, the fourth book in the Old Man’s War universe. A great, easy to read and modern series for sci-fi fans.

When I started reading I was just happy there was something more about the Old Man’s War universe and it would be interesting to hear the same story from a different perspective.

But it was more than just another perspective it extends it by tells a new story at the same time – not boring you with a lot of things you already heard. But you kind of see where the Scalzi tries to catch up with history.

At the beginning, the book does not read so fluently I must admit. Seeing the world from the eyes of a sixteen year old girl can be annoying – even if authentic. I kind of got the feeling even Scalzi had to get into writing from this point of view, assuming he even started with the beginning of the book. ;-)

After a while all of this vanishes and you build up a lot of sympathy with Zoe and resolving in a pleasing ending. I am usually disappointed by book’s endings – being unspectacular – in this book there are no world ending battles to expect and the end is known anyway but there was kind of a showdown for me.

This book is a valuable part of Old Man’s War with place for topics that might have come a bit short in the other books. Thank you John Scalzi.

Android phone as webcam to capture binary clock patterns

A while ago I got a binary clock for my birthday by some college friends (thank you again at this point). When you watch it from the sofa, you can sometimes see it creating some interesting or funny shapes and I wondered how many of them are there.

Sure, you could write a program to generate all combinations but I wanted to make a photo for each of the clock’s states. Since I don’t have a webcam or something more advanced – the idea was to use my android phone.

Searching for an app, I found this really great and easy one IP Webcam which allows you to take shots via HTTP or and directly grab an image from the video buffer. Luckily this was fast enough to make a picture every second. This was not the case when I tried using the auto focus and normal photo mode.

I wrote a little C program to print out seconds and microseconds to analyze the camera’s delay by taking a shot of the screen. The result surprised me a little since the picture was actually from before it was triggered and not after.
The explanation is at hand, the picture from the camera is buffered on the phone or the app and you simple get a snapshot of what is ready at that time.

I’ll just dump the source code of the program to take a shot every second here and with some interesting pictures I found after recording about ten hours. one to ten o’clock.

/* makeshots.c */

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

#define MSSLEEP "./mssleep"
#define CAMERA_LATENCY "350000"
#define CAMERA_URL "\"http://192.168.1.112:8080/shot.jpg\""
// printf
#define TIMEFORMAT "%010ld,%06ld"
// strftime
#define OUTTIMEFORMAT "%H_%M_%S"

#define MINUTE 60l
#define HOUR (60l * MINUTE)
// 86_400 pictures per 24 hours
#define RUNTIME (10l * HOUR + MINUTE)
#define LOOPWAIT_MS 2000

void shoot() {
  char shoot_cmd[256];
  char timestamp[128];
  struct tm tmine;
  time_t rawtime;

  time (&rawtime);
  localtime_r(&rawtime, &tmine);

  strftime(timestamp, 128, OUTTIMEFORMAT, &tmine);
  snprintf(
    shoot_cmd,
    256,
    "("MSSLEEP" "CAMERA_LATENCY"; curl -s -S "CAMERA_URL" -o out/%s.jpg 2>> curl.log) &",
    timestamp
  );
  system(shoot_cmd); // returns immediately
}

int main(int argc, char **argv) {
  struct timeval t;
  struct timezone tz;

  // init
  if (gettimeofday(&t, &tz)) {
    perror("gettimeofday in init failed");
  }
  time_t start_sec = t.tv_sec;
  time_t lastsec   = t.tv_sec;

  while (t.tv_sec - start_sec < RUNTIME) {
    if (gettimeofday(&t, &tz)) {
      perror("gettimeofday in loop failed");
    }
    printf(TIMEFORMAT, (long) t.tv_sec, (long) t.tv_usec);

    // Shoot every second
    if (t.tv_sec - lastsec > 0) {
      lastsec = t.tv_sec;
      shoot();
    }

    usleep(LOOPWAIT_MS);
    // Must be as long as TIMEFORMAT
    printf("\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r");
  }
  printf("\n");
  return EXIT_SUCCESS;
}
/* mssleep.c */

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "%s: <milliseconds>\n", argv[0]);
    return EXIT_FAILURE;
  }

  long ms = atol(argv[1]);
  usleep((useconds_t) ms);
  return EXIT_SUCCESS;
}

I was using C to get a good performance but mostly since it has been a while and I wanted to get my hands on it again. The code runs on mac osx leopard using gcc. curl must be installed.

clojure lein gives error „Exception in thread „main“ java.lang.RuntimeException: java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite …“

For all of you searching for this problem when running lein (1.6) and clojure (1.3). You have to add the clojure directory to your classpath. Simple as that. :-\

$ lein help
Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite.(ILclojure/lang/Keyword;)V
at clojure.lang.Util.runtimeException(Util.java:165)
at clojure.lang.Compiler.eval(Compiler.java:6476)
at clojure.lang.Compiler.eval(Compiler.java:6431)
at clojure.core$eval.invoke(core.clj:2795)
at clojure.main$eval_opt.invoke(main.clj:296)
at clojure.main$initialize.invoke(main.clj:315)
at clojure.main$script_opt.invoke(main.clj:339)
at clojure.main$main.doInvoke(main.clj:426)
at clojure.lang.RestFn.invoke(RestFn.java:457)
at clojure.lang.Var.invoke(Var.java:413)
at clojure.lang.AFn.applyToHelper(AFn.java:172)
at clojure.lang.Var.applyTo(Var.java:518)
at clojure.main.main(main.java:37)
Caused by: java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite.(ILclojure/lang/Keyword;)V
at leiningen.util.paths$native_arch_path.(paths.clj:32)
at leiningen.util.paths__init.load(Unknown Source)
at leiningen.util.paths__init.(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.RT.loadClassForName(RT.java:2030)
at clojure.lang.RT.load(RT.java:417)
at clojure.lang.RT.load(RT.java:398)
at clojure.core$load$fn__4610.invoke(core.clj:5386)
at clojure.core$load.doInvoke(core.clj:5385)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5200)
at clojure.core$load_lib.doInvoke(core.clj:5237)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$load_libs.doInvoke(core.clj:5271)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$require.doInvoke(core.clj:5352)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at leiningen.core$loading__4414__auto__.invoke(core.clj:1)
at leiningen.core__init.load(Unknown Source)
at leiningen.core__init.(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.RT.loadClassForName(RT.java:2030)
at clojure.lang.RT.load(RT.java:417)
at clojure.lang.RT.load(RT.java:398)
at clojure.core$load$fn__4610.invoke(core.clj:5386)
at clojure.core$load.doInvoke(core.clj:5385)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5200)
at clojure.core$load_lib.doInvoke(core.clj:5237)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$load_libs.doInvoke(core.clj:5271)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:604)
at clojure.core$use.doInvoke(core.clj:5363)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at user$eval1.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:6465)
... 11 more

Setting the paths:


echo "export CLOJURE_HOME=$HOME/Opt/clojure
export CLASSPATH=$CLASSPATH:$CLOJURE_HOME" >> $HOME/.profile

lein works, tadaaa:

$ lein help
Leiningen is a tool for working with Clojure projects.

Several tasks are available:
classpath Print the classpath of the current project.