First steps into the world of Nim

by david 2. May 2016 13:16

I was recently doing a bit of reading up on the Rust programming language, but a stray comment somewhere about the Nim programming language sent me off on a bit of a tangent. The thing that really got me interested in Nim was that it compiles to C, and I noticed that this brings quite some options for portability. One of the reasons why I like programming in C is that you can run the code on all kinds of machines, from tiny embedded devices to supercomputers. But that does come at a cost, because it takes longer and you often have lots more typing to do because of all that boilerpate stuff.

But it looks like Nim would allow you to be quite productive, whilst the resulting executables should still be efficient and fast. To get some ideas, I went off to Rosetta Code and found the Nim code for a simple webserver which looks like this:

import asynchttpserver, asyncdispatch
proc cb(req: Request) {.async.} =
  await req.respond(Http200, "Hello, World!")
asyncCheck newAsyncHttpServer().serve(Port(8080), cb)

Being able to create a webserver with just a few lines of code, and with the potential for the code to be portable and run on all kinds of devices seemed very tempting! By this point, I'd forgotten about Rust and wanted to explore Nim a bit further.

So whilst Nim has not reached v1.0 yet, it certainly looked very compelling. The compiler documentation made it look like cross-compilation was not that difficult, so I decided to try and cross-compile some code for a router running OpenWrt. Before going off and spendng a lot of time learning a new language, I wanted to see that I *really* can write portable code. I was very happy to see that in just a few minutes I had the example webserver code running on my TP-Link WR740N, as shown here:

To my amazement and joy, this really wasn't that hard. After installing Nim, I had to edit Nim/config/nim.cfg to point to my cross-compile toolchain, so I ended up with these lines:

mips.linux.gcc.exe = "/home/openwrt/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-"
mips.linux.gcc.linkerexe = "/home/openwrt/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-"

Then, after doing that I simply needed to pass the correct parameters to the Nim compiler, like this:

nim c --cpu:mips --os:linux webserver.nim

Which cross-compiled the example webserver ready for it to run on my TP-Link WR740N. That actually seems pretty awesome. I think that I need to learn more, perhaps I'll even go and buy the Nim in Action book. All this stuff worked perfectly without any trouble, which is pretty rare, so I am left feeling very impressed so far.

Another lightweight webserver for the Vocore

by david 15. December 2014 23:32

Qin Wei, the inventor of the Vocore has written his own lightweight web server. But I haven’t tried it out personally, because I have been messing about with my own minimal webserver as well.

Actually, one of the reasons why I have been working on my own web server is so that I could run it on minimal hardware - the Vocore being a good candidate. So it goes without saying that I have been itching to try that out.

I already did a trial run some months ago, where I got it running on OpenWrt for some different hardware. So the procedure for the Vocore is pretty much the same. I’ve made it slightly easier, because the makefile now has a target called ‘openwrt’ which will do the cross-compilation. I guess it should work for whatever device your OpenWrt build environment has been configured for, but I’ve only tried it for the Vocore.

Anyway, I’ve just got to the point where I have had time to try it out. I still needed to install the POSIX thread library, by using these commands on the Vocore:

opkg update
opkg install libpthread

And after that I was able to run dweb without any problems, like this:

Even the ajax calls back to the Vocore were working, which means that I could build something to control the GPIOs through javascript in the browser, if I wanted. But in the meantime, I decided trying to serve up some of the system statistics, so I did this:

cd /dweb
ln -s /proc/stat stat.txt

Which makes the contents of /proc/stat available to the webserver, and meant that I could browse to /stat.txt and view the contents of /proc/stat in my browser. I thought that was an interesting little experiment.

I love it when a plan comes together

by david 3. September 2014 20:17

So recently, several of the different things I have been messing about with have come together. This was always in the back of my mind, but I didn't really know how long it was going to take. Recently, I have been working on:

  • building my own webserver (dweb)
  • cross-compiling for Linux on a TP-Link router (with OpenWrt)
  • ...and my own experimental programming language (H2D2)

Now I have bean able to bring all that together, what it means is that I can run H2D2 programs on my little TP-Link router. At the moment, I'm doing it through jQuery Ajax calls. So the programs are sent to the router with an HTTP POST from an ajax request, the router runs the program remotely and then returns the output back to the browser. Nice.

Here is a screenshot showing it all in action:

Woo-hoo... it works! Oh, and apologies for the partial ASCII Mandelbrot, I really can’t help it. The next experiment will probably be to do what H2D2 was actually designed for, namely to run a program partially on the router and then finish off the same program instance on some other platform. Then, I should be able to bounce a single program between the router, a Raspberry Pi and a desktop, which will be a neat trick.

Music by numbers - more notes

by david 31. August 2014 12:16

I blogged before about building a Raspberry Pi music player by numbers thingy and I said that I’d mention some more details about the software used. I did write up the notes, but then forgot to post it on the blog, so here goes, better late than never…

I had already mentioned the USB Message Board linux driver and the MP3 player that I used. The USB Message Board also requires the libusb-1.0-dev package to be installed, like this:

sudo apt-get install libusb-1.0-0-dev

But before I got that far, I needed an OS … and I wanted a version that wouldn’t corrupt the filesystem on the SD card if I just switched the power off at the mains. I have ended up running something called IPE - Industrial Perennial Environment of which I’m using the R1 edition, which is based on Raspbian. It seems to work a treat: I don’t need to worry about clean shutdowns, the filesystem runs in read-only mode. The R2 version of IPE looks even better, but for the time being I’ve stuck with the Raspbian derived version which is more familiar to me.

It goes without saying, that the webserver I used to provide the web-based API was my own dweb lightweight webserver which seems to have done the job very well.

I also wanted the Raspberry Pi to offer its own WiFi hotspot, for which I followed these instructions. After that I also followed this advice and disabled ifplugd for the wireless lan.

So … putting those things together and with a simple C program, I have:

  • a version of Raspbian which can be powered off without a safe shutdown
  • a Raspberry Pi which operates a WiFi hotspot with a DHCP server
  • an MP3 player which shows the track number on an LED display
  • a web based user interface and API

Normally, I just use Safari on my iPhone to call up a song over WiFi, but I added a numeric keypad as a backup, in case of WiFi interference or other problems. I’m sure that I could really go to town and make a much more complicated wireless MP3 player out of this … but what I have just seems to work perfectly, so at the moment I’m leaving it well alone.

Remoting into a Raspberry Pi

by david 9. June 2012 23:40

The little LCD TV I tested the Raspberry Pi with wasn't very good, so I wondered if it was possible to remote into the Raspberry Pi from another machine. I found that this is no problem when I looked here. So I tried the following commands:

sudo apt-get install tightvncserver

...on the Raspberry Pi and it worked perfectly. Then with a copy of the TightVNC client running on my windows machine, I can access the Raspberry Pi remotely. This is awesome.

I used that approach to do more testing of my simple C# webserver, so here I am testing the webserver in TightVNC ... and also checking that the page is being served over my network to the PC in internet explorer:

...and finally, here is the Raspberry Pi serving the same test page to my iPhone:

OK, that all seems to work. I've just got to figure out what to do next now.

Unexpected Pi

by david 8. June 2012 22:13

A very kind colleague of mine has lent me his Raspberry Pi, so that I can have a little play with it. Here it is being hooked up on my workbench:

I used the standard Debian 'squeeze' image, since that's what I've been messing about with recently. After checking that I had internet access, I went off and installed the mono runtime, like this:

sudo apt-get update
sudo apt-get install mono-runtime

...after doing that I ran the C# webserver example that I had already written - and it works a treat! I didn't compile the code on the Raspberry Pi, I simply copied the exe file over and ran it with the mono command. The code was compiled in monodevelop running on Debian in VirtualBox.

Anyway, here is another photo, taken when I was first cheking that I could get online. Umm, I need to tidy up in here again.

More reports will follow I'm sure...

Raspberry Pi Preparations

by david 29. May 2012 22:46

I am currently in the queue to receive a Raspberry Pi. Apparently my machine is about 5 weeks away. So I have decided that I should begin making some preparations. I have downloaded an ISO image of Debian "squeeze" (the version with the LXDE desktop). So at least I should know my way round the OS in advance.

After installing the Debian ISO on a virtual machine, the first thing that I did was install the monodevelop IDE which I don't think will actually work on the Raspberry Pi ... but should enable me to try some things out and then just compile them from the command line on the Pi (hopefully).

Monodevelop seemed to work like a charm on Debian, so I grabbed my C# webserver example to try out some code.

Amazingly, the only real thing that I had to change was add the following delegate declaration:

public delegate TResult Func<in T1, out TResult>(T1 arg1);

...apart from that the code worked without any changes. Here is a screenshot of it all working:

So I am hopeful that I will be able to run my little slimline webserver on my Raspberry Pi when it arrives.

Simple C# Web Server

by david 1. April 2012 17:28

During my lunchbreak the other day I wondered how hard it would be to write a simple webserver in C#. Surely with all the toys in the .net framework these days it should be pretty easy? So I decided to give it a go and see what happens. The aim was to write a simple class that recieves a delegate to a method which is responsible for the page content, everything else could be taken care of by the class I'm writing. That way the server can serve whatever page(s) you like, but you just need to write a simple method that returns a string with some html in it. Of course, with this approach the HttpListener is our friend and does much of the hard stuff. Here it is in action running on my Iconia tablet:

The webserver running

It took me about 30 minutes to get it working. After taking the code home and tidying it up a bit, this is what now I have:

using System;
using System.Net;
using System.Threading;
using System.Linq;
using System.Text;
namespace SimpleWebServer
    public class WebServer
        private readonly HttpListener _listener = new HttpListener();
        private readonly Func<HttpListenerRequeststring> _responderMethod;
        public WebServer(string[] prefixes, Func<HttpListenerRequeststring> method)
            if (!HttpListener.IsSupported)
                throw new NotSupportedException(
                    "Needs Windows XP SP2, Server 2003 or later.");
            // URI prefixes are required, for example 
            // "http://localhost:8080/index/".
            if (prefixes == null || prefixes.Length == 0)
                throw new ArgumentException("prefixes");
            // A responder method is required
            if (method == null)
                throw new ArgumentException("method");
            foreach (string s in prefixes)
            _responderMethod = method;
        public WebServer(Func<HttpListenerRequeststring> method, params string[] prefixes)
            : this(prefixes, method) { }
        public void Run()
            ThreadPool.QueueUserWorkItem((o) =>
                Console.WriteLine("Webserver running...");
                    while (_listener.IsListening)
                        ThreadPool.QueueUserWorkItem((c) =>
                            var ctx = c as HttpListenerContext;
                                string rstr = _responderMethod(ctx.Request);
                                byte[] buf = Encoding.UTF8.GetBytes(rstr);
                                ctx.Response.ContentLength64 = buf.Length;
                                ctx.Response.OutputStream.Write(buf, 0, buf.Length);
                            catch { } // suppress any exceptions
                                // always close the stream
                        }, _listener.GetContext());
                catch { } // suppress any exceptions
        public void Stop()

All the work is done on background threads, which will be automatically cleaned up when the program quits.  Example use of this code is pretty simple, like this:

class Program
    static void Main(string[] args)
        WebServer ws = new WebServer(SendResponse, "http://localhost:8080/test/");
        Console.WriteLine("A simple webserver. Press a key to quit.");
    public static string SendResponse(HttpListenerRequest request)
        return string.Format("<HTML><BODY>My web page.<br>{0}</BODY></HTML>"DateTime.Now);    

I'm even considering using this code to build a little DALIS aware test server, so that I can run DALIS programs without hosting anything in IIS... even better I could run a couple of them and bounce DALIS programs between them.

EDIT:This little bit of code has proved quite popular, and recently I have been asked if it has been released under any particular license. Since it was such a small bit of code and just an evolution of the MSDN documentation found here, I didn't really think about a license for it. But I am happy to share this code, so to make the situation clear I'm releasing it under the MIT License.

PDP-11 webserver

by david 1. April 2011 22:39

I thought that the simplest application for my PDP-11 / WiFly combo would be to serve up some basic web pages.  So I've been tinkering around with some C code to make that work.  The HTTP protocol is not too hard once you get those CRLFs in the right places...  So here is a screenshot of my PDP-11 serving it's first webpage to my iPhone:

PDP serving webpage to iPhone

I'm pretty happy with that.  For the moment I'll ignore the fact that when you exit the webserver program it crashes RT-11.  I've probably made some stupid typo.  But whilst the program is running, it seems to work OK.  SMTP is next on my list, I want to send mail from my PDP.

About the author


I'm a C# developer having worked with .Net since it was in beta.  Before that I mainly worked in C and C++.  I have been developing commercial software for more than 20 years.  I also mess around with microprocesors, but that's just for fun.  I live near Cambridge, England and work from home in my 'silicon shed'.

Tag cloud