I was asked to give a presentation at work about Akka.Net. Even though my audience is 100% C# loving, I will give a demonstration with F# code. I was already working on a project to rewrite “Three is a Crowd” to the Actor model in F#, and this presentation was a driver to finish this project. Let’s share my experiences with Akka.Net here.

Choices and Motivation
There were two goals of rewriting the game to Akka.Net. First of all, I wanted to try out a few design patterns. Secondly, if you run a multi-player game and your server needs to bring different players into the same context, you will run into big technical challenges if you store state in a file or database.

The previous version of the game stores state in a file, and uses file-locking to synchronize/sequence the threads for multi-player access. This choice was made due to past bad experiences with a cheap hosting-party in India, whose load-balancers took away any form of pan-threaded resource sharing, except the filesystem. Even if I chose a DB to store state, then the technical solution would still be quite hard, because then you end up migrainial row-locking feasts, with the risk of time-wasting deadlocks.

Akka.Net seemed to be the ultimate solution to the problem of different players working together in the same state-full context. That could of course not run on the cheap Indian hosting provider with their faulty Plesk interface. But it could certainly run as a service under different operating systems.

Because from work-side, we were investigating Akka.Net as a solution to some project, I was extra interested in Akka.Remote. So this project was separated in a Game Engine part and a Presentation part, instead of having the GameEngine embedded in the Web-Server.

The Presentation part was written with Websharper, because I wanted to (easily) use the HTML5 Websocket as a bidirectional communication channel between client and Game Engine. The previous version of the game had a polling mechanism to determine for each client whether it was his turn, or whether one of the other players had made a move and changed the board.

The Presentation part communicates with the Game Engine via Akka.Remote. One issue popped up quite quickly, Akka.Remote did not like my Discriminated Unions. Well, the issue was not really in Akka.Remote, but in the underlying serialization library from Newtonsoft. There have been numerous fixes over the years but none satisfactory, so I was adviced to use “Wire” for serialization. Instead of configuring this myself, I chose to use an experimental side-project, Akkling, which uses “Wire” by default and provides extra F# features such as static typing. With Akkling, you need to know what you’re doing. But when you get the hang of it, it works nicely. Wire processes Discriminated Unions flawlessly, so it certainly solves the issue.

If you compare working in C# or F# in respect to creating actors with Akka.Net, then the difference is that F# code is about 70% smaller than the C# version. In C#-land people are already making ML’s and/or DSL’s to speed up the work. Akkling reduced the work even more than Akka.Net’s standard F# support, with more features and extra static typing, which greatly reduced the error-risk. I really hope that this library will see a serious future.

Application Architecture
The basic application architecture is as follows:

To start at the left, the client has a bit of logic how to build the screen from data. At initialization it tries to register with the Game Server. Akka.Remote only allows actor systems to communicate with other actor systems. So the “Player Client” is an actor (in a local actor-system) through which this communication takes place. The Websocket-server bridges messages between the Websocket-client (in the browser) and the Player-Client actor system, in both directions. Finally, the “Player Client” connects with the “Player Server” in the Game Engine, through which the whole game is played.

Design Patterns
At the Game Engine side, I wanted to create a system with a waiting room. The first thing a new Player-Server actor does, is connect with a Waiting-Room actor. The Waiting-Room waits until enough players have entered, 3 players in this game. When enough players have entered, the Waiting-Room actor starts a Game-Room actor, and tells the players in the waiting room that they can connect to the Game-Room. The Game-Room determines who starts the game, who has which color, what the game-board looks like, and after this the game begins. During the game, the Game-Room informs all players about whether it is their turn, what choice other players made, what the game-board looks like after a player made a move. To support NPC AI’s, whenever a human-player enters the Waiting room, two AI’s are started, who wait 20 seconds before entering the Waiting-Room themselves. If their seat is taken (by another human player), then their attendance is ignored. Otherwise the AI is treated as a regular player.

The specific design pattern I wanted to try out in this game, was to find a way to move a player from the Waiting-Room to the Game-Room. The problem is though that there are limitations in how far an actor may be a container of other actors.

I thought of the “supervision” capability, where both Waiting-Room and Game-Room have Supervision on player-actors hang under them. The player actors could then communicate with their context (one of the rooms) via the “Parent” property. But I found two problems in this approach, -1- I did not find clear documentation how to create hierarchy in actors with F#, and I did not have much confidence in my own experiment-results. -2- I did not find any documentation on how to rehang an actor from one supervisor, to the other supervisor. I also did not want to re-create the player-actors under their new supervisor (the Game-Room), because this would at some point interrupt the communication, somewhere in the pipe between Browser and GameEngine.

One could also think of a construction in which both Waiting-Room and Game-Room have an array/list with player-actors. But then you still need to tell the player-actors about their context, ie. tell them in which room they are in. This implies that you manually program something into the player actor, that looks like the “Parent” property I mentioned above. Telling the player-actors about their context would make the whole array-structure obsolete anyway.

Instead of one actor being container of other actors, I decided for a different pattern. The Player Actor would have a flexible communication-line to his current Room. So a Player-Server actor should first talk to the Waiting-Room actor, and then change its connection to the Game-Room actor.

The player actor has max only one connection to a room, and this is the room he is in. This finally became the pattern. Thanks to Akkling I was able to use static typing and many Discriminated Unions to enable this quite complex mechanism.
Also the AI’s got a slightly different design pattern. In the previous TIC version, the AI’s had access to the centralized game-board state. That was possible because everything was happening in the same thread. In this version, everything is split it into different actors, and sharing game-board became less obvious. Now the AI-player actor keeps track of the game-board state locally. This also caused many more message to be send through the system, to keep the data consistent.

How to Run
The complete code can be downloaded from Github. The two most important projects are “GameEngine.Service” and “GameUI.Owin”, which should both be started when running this code in Visual Studio 2015.
​
The “GameEngine.Service” project can also be run stand-alone, and with this Fsharp script you can run it step-by-step.

As the previous article was "current-status". Progress brought new insights, and so the following corrections apply:

I develop in VS2015 under Windows, so I didn’t need to install Akka.Net on the RPi; installing fsharp for Debian/Ubuntu Linux is enough;

The Self-Hosted Websharper template does not work -fully- as was described, see below;

﻿Control Panel﻿

The goal is to write a webapplication, which provides a Control Panel for the Robot Arm. I want to run the Control Panel via my home-network on my iPad.

The webapplication should show all four Servo-motors, and two buttons per motor, with which I can turn the motor clockwise or anticlockwise. Ifthe buttons are untouched, the motors don't move. If a button is pressed, the motor should rotate at a constant speed, and not too fast.

The robot arm, together with the control panel. It works on my home-network, via Wifi! It almost crashed when my 2-year-old showed his interest..

Application Architecture

The visual part of the Control Panel is written using FSharp and Websharper. Websharper enables the visual interface and to send events (button pressed) to the Webserver on the Raspberry Pi.

At the server side a user event is sent to a "Directional Controller" (later more about this) which is created using Akka.Net. The directional controller receives the events and converts this into motion of the Servo-motors. There is one "Directional Controller" per motor.

We are going to use the ServoBlaster installed in part 1. According to this article, the following Linux shell command will rotate one of the Servo motors:

echo0=50%>/dev/servoblaster

We want to be able to write move commands to this device, for all motors concurrently. But to avoid a sharing violation, these commands need to be throttled: one per time.

Akka.Net provides a good way to throttle. We just create a "device-actor" which writes to the device. If the directional controller wants to invoke motion, it send a move command to the device-actor. The device-actor handles all messages in order, and one per time, so we'll have no Sharing Violation issues.

Another reason to use Akka.Net is to gain a bit experience; we are considering using Akka.Net at work, in C# though, but still.

Directional ControllerFor the directional controller, I modelled a strange kind of pressure based structure. For the metaphor, I assume that water delivers the pressure. I couldn't find a real-world product, so I made up a name. The schematics are below:

From the left, pressure (ie water) flows into the structure and this pressure spreads evenly over the upper and lower part. If you pull the upper valve, water will flow through the upper part, pushing the centre gear rotating clockwise, which then rotates the attached robot-arm limb. If you pull the lower valve, the centre gear will rotate anticlockwise, pushing the limb in the other direction. If you pull neither, or both, the centre gear does not move. Of course, these "valves" represent the two buttons for a Servo motor in the Control Panel.

I used this metaphor of the "directional controller" in my source code, which you can find here on GitHub.

Running the Control Panel

Get the code from GitHub, and compile it in Visual Studio 2015. In part 1 you made a shared drive on your Raspberry Pi, and you should copy the relevant files to this share, from your Windows machine. Copy everything except .fs source code files, "packages" file, "Visual Studio Project" file.

Lessons LearnedThislittle summer project had lessons to learn. Some in the code (I've added comments), and some in the bigger picture.

Screw aroundWhile screwing the parts into a Robot-Arm, I was just following orders, with no experience whatsoever. And some joints are just rough, which is why they resist rotating well. I was just screwing around, and felt sorry later. However, if I paid a bit more attention in the beginning, I would probably have made similar mistakes. Currently I am re-screwing (around) to ease up the joints. Not satisfied yet, so I carry-on screwing.

SolderingIt has been quite a while the last time I soldered something. A few pins needed to be soldered onto the card, which interfaces on the RPi, and to which you can connect the Servo's. I didn't do a good job the first time, and when I plugged in my RPi, something got smelly. Later on, I found my Micro SD card was melted and broken in two. Lessons learned? Don't under-estimate this, things can really break.

WebserverInitially, my plan was to run Websharper as WebApp framework, under a webserver from the F# community. Unfortunately my plan failed. I tried Suave.io with Websharper, but I could not find any way to connect these two. From Freya I understood that it still requires some work 5) for Freya to run Websharper. As time was running out, I decided to use Websharper's Warp. First I tried the self-hosted template, mentioned in part-1, but at closer look, only the server-side HTML worked, while the dynamic HTML created with Javascript did not work. Another possibility is that I did something wrong, but like I said - time was running out, I did not follow-up.I used the self-hosted client-server template from Websharper to create the project, but deleted the code in the Main.fs and replaced it with Warp code (example).

It worked fine, but sometimes I copied all the stuff from my Windows machine to the Raspberry Pi, ran it, and it showed no changes, even when I erased the whole WebApp. Caching anyone? No there wasn't.

As I moved stuff around to make my deploy procedure much easier, I found out that the folder "Scripts" was created in unexpected locations. Then it came to me. I used the relative folder".." as WebApp-root. In some cases Websharperuses this relative to the binary's location and in other cases relative to the execution folder (which caused "Scripts" in unexpected locations). When I cd'd to the bin folder and executed the binary from there, the issue was gone.

Mono CrashesSo I created everything. First proof of concept of all parts, ran it on my PC, then ran it on the Raspberry Pi 2B. And when I felt confident, I put it all together, in one FSharpArm solution, with Websharper, Akka and Websharper.UI.Next v3.4 (which is awesome). It worked on my Windows PC, but when I copied everything to the Raspberry Pi, I got this screen:

After a long investigation, I discovered that all my working Proof-of-Concepts were using F# v4.0, while my final project, FsharpArm, was using F# 3.1. When I changed this to F# 4.0, everything worked like a charm. Ehm, feature-request, how about showing an error-message for this?

Akka.Net

The first thing I received from Akka.Net was a "DeadLetterNotification", when the first message was send. It appeared that I used keyword "use" instead of "let" to create the actor system in a function. When the function exited, the actor-system was disposed. With "let" you don't have this problem. That "use" came from example code.

Did Akka.Net add any value? I think it did. It worked perfectly for throttling the writes to the device. You can press two buttons in the Control Panel at the same time, and I did almost nothing to solve this concurrency problem. The "pressure" in the controller is done by (see source code) a "pulsar", which sends a message to the controller at a fixed time-interval. Thanks to the scheduler (and a co-worker who tipped me this feature) I didn't need "Quartz for .Net" or write something myself. Using a structure which open/closes valves to block or let messages through, I have a system with which I can give the Servo-motors a constant slow speed. I experimented with higher speeds and found that the Robot-arm may lose its balance.

To Conclude

This was it for the FSharpArm summer-project. Summer is finished here in Northern Europe and I will fly for holidays to the City of the Sun in Brazil, in September. It was nice to see, how little is needed to have an interesting learning experience.

I know what's like in the summertime, a bit quiet, so I thought it would be fun to build a Robot Arm, and to control it from a Raspberry Pi using self written F# software. Project goals are: have fun, learn some, and if possible, do a "Sean's dad" trick: inspire a kid.

I would not start with inspiring the kid, especially if they're very young. In my case, my two-year old just lied down on the Robot arm parts, which is his way of saying, can I play Dance Central on the XBox please.

﻿Constructing the Robot Arm﻿

The MeArm robot arm is an "open source" Robot Arm. If you were able to buy it, it should come with a construction manual. If it did not, then try to find it on the internet. In my case, I received a printed copy of the PDF found here. Take your time to construct it, be thorough, patient and careful not to break the materials. And don't forget to have some fun.

This is a typical example of a staged photograph. That's not curiosity, he is thinking of a cunning plan how to get away ASAP. He won btw, those little people are a clever lot.

You can control it from the command line, using servoblaster (see below).

Preparing the Raspberry Pi 2B

I came quite novice to this ground, the following is to give a Raspberry Pi quickstart.

At Raspberry's website, you can download the image of Raspbian, then you should use your Windows PC to install the image on the micro SD card. Even though my first encounter with Linux was somewhere in 1998, I've never worked with Debian. But it works the same as my usual choice - Ubuntu, I like it.

After installation, put the micro SD card in the appropriate slot of your RPi, hook it op to your TV-set with an HDMI cable, and connect it to you home-network with a network cable and plugin the USB keyboard. You need internet access. The first steps will be via the TV-set, but we change ASAP to accessing our RPi via our Windows PC. So there can't be any Dance Central on Xbox yet.

Finally enter "ifconfig", and you should see the RPI's ip-address, in the "eth0" section, write it down.

Now you can disconnect your RPi from the TV-set, take it to another place in your home and connect it to the network. If you haven't downloaded Putty yet, do it now. Start it up and enter the hostname in the "hostname" field, port stays 22 and click "Open". The first time you do this, you need to accept the encryption key. If it does not work with the hostname, perhaps you can try again with the IP-address you wrote down before.

Login to your Rapsberry Pi, go to root mode with "sudo su".

What is nice to have, is that your RPi has an easy access shared drive using Samba. I've searched the internet over and over, but I can never ever find a quick way to configure Samba, to share me a folder to my Windows desktop, without entering credentials, fiddling with file-permissions or assigning incorrect file-owners. No need for a rigorous security policy when doing simple in-home stuff.

The solution is simple, follow these EasySamba instructions from my Github account.

Now, on your Windows PC, you can right-click on your Desktop and add a short-cut. Where it asks for the path, enter "\\<hostname>" or "\\<ip-address>", give the shortcut a name and it should work.

Finally, we need a device driver, enabling us to write to the pins of the Raspberry Pi, to signal the Servo Motors. For older models of Raspberry Pi you can use this software. However this does not work for the Raspberry Pi 2B. For the Raspberry Pi 2B, you need to download and install the driver's upgrade, which you'll find here. I understand they both have the same interface, so I assume this project should also work on older RPi's.

Some optional cool stuff. I installed "vssh" on my iPad, which is like Putty, and a great way to login into your RPi. You can use your iPad as a second screen to run "top". Or you can demonstrate the Fsharp Interactive to your little bright nephew and show what's programming about (Enter "fsharpi" in your Linux shell after the setup above).

Another cool thing is that the setup above is enough to run Websharper. In Visual Studio 2015 with Websharper 3.4 installed, I created a new project using the "Self-hosted Client-Server Application" template. This runs a console application.

Build it. Copy everything from the project except *.fs to the shared folder on your RPi. With Putty go to the root-folder and enter "bin/yourapplicationname.exe . http://`hostname`:8080 ", note the ticks around "hostname".

(part of the menu is missing due to the small browser window)

End of part 1. Not very much FSharp at this point. We'll get to that later.

Download the command-line utility. Make sure that nuget.exe goes to your Ubuntu installation. In my case, I downloaded it to a Windows host and copied it to my Ubuntu Virtual Machine via a Samba shared drive.

Copy nuget.exe to /usr/bin/nuget (or if you like it, you can keep the .exe extension)

Now create and go to a folder where you want to start your Akka.NET project. Run the following command to download the correct certificates:

mozroots --import--sync

And now you can install Akka.NET via nuget. Make sure that nuget has execution rights on you Ubuntu system. From your Akka project folder: