Category Archives: Raspberry Pi

Home Automation with Raspberry Pi – Garage Door

I hate keys. And even though I hate not having keys when I need them even more I still think keys are annoying. I keep forgetting or losing them. In some cases, they make life harder than it needs to be. For example, I bike to work almost every day from early spring to late fall and I should not even have to think about keys and door since I just need to open the garage door, take/park my bike and close the garage door. Currently what I need to do is to make a couple trips around the house to open/unlock doors and then close/lock everything I opened/unlocked. I tried using my kids to do all of this for me but they simply started to avoid seeing me in the morning and even if I caught them they kept forgetting to do what I asked. Yes, I could carry a remote with me. I actually did for a while but it was even worse than carrying the key – it’s bigger, it’s another thing to remember about and the last one got some rust within a year or so and stopped working completely. There is, however, one thing I carry with me almost always – my cell phone. If I could open my garage from my cell phone (almost) all my problems would be solved. As a bonus my kids wouldn’t be afraid of leaving their rooms before I leave for work. Yes, I know there are already some garage openers on the market that can be controlled with cell phones so one way to go would be just to replace my garage opener with one like that. I don’t like, however, throwing away things that work. Replacing the garage opener would also cost at least a few hundred bucks even if I did all the work myself. Another thing is that I am currently using a Windows Phone (hey, an unlocked Nokia Lumia 640 was like $30 + tax – this deal was hard to beat for a cheapo like me) and given Windows Phone’s market share I don’t expect any garage opener to have an app for that. Finally, hacking something myself is much more fun then using a ready made solution.

Enough talking, let’s get started. What you need for this project is a Raspberry Pi running Raspbian and a remote that matches your garage opener. If you don’t have a spare remote you can buy a generic one on eBay or Amazon. (I had a remote with a broken button so it was useless in general but perfect for this project since we need to short-circuit the button anyways). The idea is to connect the remote to the Raspberry Pi via GPIO (General Purpose Input/Output) and then write a web application that could be used to control the remote. Whenever you are on your home network you will be able to access this web application (e.g. from your phone) and open or close the garage door. Heck, if you have friends who you trust and allow on your network they will be able to open your garage door to (this obviously has pros and cons). This might sound complicated but it is really not that hard.

GPIO (General Purpose Input/Output)

The first thing you need to be familiar with is GPIO (General Purpose Input/Output). If you have never heard about GPIO these are the 26 pins on your Raspberry Pi. You can find out more on GPIO from this tutorial.

Hardware

Preparing the hardware requires a bit of soldering. Don’t be afraid – it is so basic that even I could do that! The first thing to take care of is the button you press to open or close the garage door. Because we are going to control the remote from Raspberry Pi we need to short-circuit the button otherwise it will prevent the current from flowing and nothing will work. We also need to solder jumper wires which we will connect to GPIO. Note – GPIO pins are 3.3V and my garage opener used a 3.3V battery so I soldered the wires directly to the battery socket. This is what I ended up with :

Connecting remote to Raspberry PI

The important thing before connecting anything is to know what version of Raspberry PI you have because the layout of GPIO pins vary between models and revisions. In this project I used pin 7 (GPIO4) because it seems to be the same in most/all of the models and revisions. I would recommend however double checking your Raspberry Pi before wiring things up (if you decide to use a different pin you will have to update the script that controls GPIO).  Now, you just need to connect the ‘hot’ wire to pin 7 (GPIO 4) and the other wire to GND (e.g. pin 6). This is how things look like after I put them together:

Connected

Hint – for testing instead of connecting the remote you can connect just a LED. This way you can quickly test if things work without leaving your neighbors wondering why the hell your garage door opens 10 times in a minute. The GPIO tutorial shows how to do this and here is what I used for testing:

LED

Software

With hardware ready we can now take care of software. We want to be able to control GPIO from a web server. The problem is that you need root permissions to access GPIO and granting root permissions to a webserver is generally a bad idea. Fortunately, there is the pigpio library which allows to control GPIO. pigpio contains a utility – pigpiod – that launches pigpio as a daemon and enables talking to pigpio using sockets or the pipe. You talk to the pigpio library by sending pigpio messages. The list of available messages with descriptions can be found here. One very useful thing is that when pipgpiod is running you can send messages directly from command line by writing to /dev/pigpio – e.g. echo "w 4 1" > /dev/pigpio sets GPIO4 to high (w – write, 4 – GPIO4, 1 – high) – we will use this command in out script.

Thanks to pigpiod the webserver no longer needs to have root permissions to control GPIO.

I chose lighttp as my webserver. Installing and configuring it is not hard and there are quite a few tutorials on the internet showing how to set it up. Once you have a webserver up and running you only need a script that will handle user requests and send messages to pigpiod. I wrote the script in Python so you will need to install Python on your Raspberry Pi if you have not done it yet.

If you have never configured a daemon (like me – I just used the init script template I found here and adapted it) or written anything in Python (like me – but it’s like 7 lines of code) fear not. All the code is ready. Just clone my repo (or even copy files) from https://github.com/moozzyk/GarageDoor and follow steps below:

  1. Install pigpio
  2. Configure pigpiod (pigpio daemon)
    • copy the pigpiod script from the GarageDoor/scripts/init.d folder to /etc/init.d/. You must be root to do this. If you are in the GarageDoor repo root run:
      sudo cp scripts/init.d/pigpiod /etc/init.d/
    • Make sure the pigpiodscript you copied has execute permissions. If it does not you need to chmod +x it. Again, you have to have root permissions to do that:
      sudo chmod +x /etc/init.d/pigpiod
    • Start pigpiod daemon with:
      service pigpiod start
      (You can stop the service with service pigpiod stop or check the status with service pigpiod status)
    • If you have a test setup with LED you can now easily check if things work – set GPIO4 to high by running
      echo "w 4 1" > /dev/pigpio
      The LED should light up. To turn off the LED execute
      echo "w 4 0" > /dev/pigpio
    • Configure the daemon to start on boot:
      sudo update-rc.d pigpiod defaults
  3. Configure lighttp to execute python scripts (if you are not running lighttp configure your webserver accordingly). In /etc/lighttpd.config:
    • In the server.modules section uncomment or add "mod_cgi" e.g.:
      server.modules = (
              "mod_simple_vhost",
              "mod_evhost",
              "mod_userdir",
              "mod_cgi",
              "mod_compress"
      )
    • In the cgi.assignsection add a mapping for .pyfiles:
      cgi.assign = (
              ".py" => "/usr/bin/python"
      )
  4. Prepare and run the application
    • copy the garage.py file from GarageDoor/Script/web to /var/www (or wherever your application root is)
    • Navigate to the application using a browser – you should see something like this:
      wp_ss_20160522_0002
    • Now if everything is set up correctly your garage door should open/close if you click the open/close button

Points of interests

Currently the application lets everyone who is on the home network play with your garage door. This may not be desirable. One improvement to make would be to authorize people before they can open or close the door. Another useful thing would be to log when the garage door is opened and closed. Finally, configuring the webserver to use https would be useful as well.

Advertisements

Raspmodore 360

My brother is visiting us from overseas and I thought it would be cool to set up some kind of a retro gaming environment we could use to refresh our memories from childhood when we spent hours playing M.U.L.E., Kikstart 2 or HatTrick on our Commodore 64. Raspberry Pi seemed a perfect choice – it’s close to the TV (or already connected if you are using Raspbmc) and it has access to the network which makes it easy to acquire software. To play games however you need some kind of a controller. So, what else is close to the TV? An XBox! And it actually has some controllers (let’s forget about Kinect for now). And this is how I came up with the idea of something I called:

Raspmodore 360

Raspmodore 360

– a Commodore 64 emulator running on Raspberry Pi and using XBox 360 controllers. Setting things up turned out to be relatively easy. First you need to install Vice emulator. You can find some steps here but they don’t actually work. Firstly they refer to the “squeeze” distro and you most likely have the “wheezy” distro (the “regular” Raspbian image recommended on the Raspberry Pi download page). Secondly the Raspbian “wheezy” image is a hard float image and when running Vice installed from ftp.uk.debian.org it just dies with the Segmentation Fault error. After my last battle with Raspberry Pi, Mono and EF6 I think it might be possible to install the package from ftp.uk.debian.org on the Soft-float Debian “wheezy” distro but this distro is a bit slower so I kept looking for a version I could run directly on Raspbian. Soon I found this thread which points to something that seems like a private version of Vice built for armhf architecture. If you just follow the steps (btw. notice the _armhf suffix in the Vice package – the package from ftp.uk.debian.org does not have this suffix and I believe this is the reason it doesn’t work on Raspbian):

wget http://www.frank-buss.de/raspberrypi/vice_2.3.dfsg-4_armhf.deb
dpkg -i vice_2.3.dfsg-4_armhf.deb
wget http://www.zimmers.net/anonftp/pub/cbm/crossplatform/emulators/VICE/old/vice-1.5-roms.tar.gz
tar -xvzf vice-1.5-roms.tar.gz
cp -a vice-1.5-roms/data/* /usr/lib/vice/

you will end up with a working C64 emulator on your Raspberry Pi (don’t forget to copy ROMs or you will have an opportunity to see yet another Segmentation Fault error – verified empirically). Just run a console window in the X Window environment and start Vice emulator with the x64 command.
[Spoiler Warning] Had I run any game at this point I would probably have given up setting up the controllers but I did not and instead[/Spoiler Warning] I moved on to setting up the controllers. It seemed to be very easy. There is this xboxdrv thingy you install and stuff should just work (note: you will need the XBox 360 controller “for Windows” – it contains a standalone USB receiver which you will need to plug into your Raspberry Pi (your “Windows” today)). To install xboxdrv you just need to run the following commands:

sudo apt-get update
sudo apt-get install xboxdrv

Just to see if/that the controller works I started the xboxdrv and turned on verbose output

sudo xboxdrv --v

synced the controller and started pressing buttons and pushing sticks. Unfortunately I did not see any activity on the screen. I “reset” the controller (i.e. removed and replaced batteries) pressed the button on the receiver to initiate syncing and turned on the controller. Again it synced fine but I could not see any activity in the xboxdrv window regardless of what I did to the controller. I even restarted my Raspberry Pi and repeated the process but it still did not help. I found a small app called jstest-gtk that allows testing joysticks but it could not find any controllers attached. I learnt about a few interesting debugging options built in xboxdrv (like debugging at the USB protocol level) but this did not help much. With that I started thinking that it must have been a problem with the controller so I grabbed a different one turned it on and… it synced immediately. That was unexpected since I did not press the sync button on the receiver. This is when I realized that the Problem Existed Between Chair And Keyboard (PEBCAK). I had been trying to sync the controller by pressing the button on the receiver but had not pressed the sync button on the controller itself. Therefore the controller started the Xbox located in a different room and then was syncing with it rather than with the receiver connected to the Raspberry Pi. A complete fail on my side. It took me a while to get over my lameness but when I did the things went smoothly. I disconnected my Xbox and really synced my controller with the receiver connected to my Raspberry Pi. xboxdrv woke up and jstest-gtk finally showed that there is a controller present. I configured Vice to use arrow keys as joystick and space as the fire button. The only remaining thing was to map the controller joystick and button(s). This is not difficult and can be done just by providing parameters when starting xboxdrv – just like this:

sudo xboxdrv –ui-axismap x1=KEY_LEFT:KEY_RIGHT,y1=KEY_UP,KEY_DOWN –ui-buttonmap a=XK_space

I started the emulator and ran a game. The controller worked fine – I was able to use it but I was not really able to play any game. Vice was way too slow – games ran just at 5-7 frames per second and the terminal window I used to start Vice from constantly showed the message:

Warning – Your machine is to slow for current settings

I played for 10 more minutes and gave up. That’s too bad. I still don’t quite understand why Raspberry Pi is not able to handle this. I ended up digging up the original Xbox from my garage. It has an ancient version of XBMC but with a working Commodore 64 emulator. We used it instead of Raspberry Pi. Unfortunately when playing M.U.L.E. pirates helped my brother by stealing all my smithore twice (the second time in the 11th round) and I lost the game. It probably would not have felt that bitter had it happened on Raspberry Pi.

Raspberry Pi + Mono + EF6 – defeat!

After (or maybe even before) I successfully made EF6 work on Mono I thought it would be cool to try it on Raspberry Pi. Since my project already worked on Mono I thought it should be relatively easy to do. The first thing I had to do was to install Mono on my Raspberry Pi. It is easy and requires running just two commands:

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

Since my project uses MySQL I also had to install MySQL database. Again it was as easy as executing:

sudo apt-get install mysql-server

After that I used mysql and mysqladmin tools to create a user and a database that would be used by my app. With my Raspberry Pi ready I copied my little app to the Raspberry Pi and ran it using the mono command:

mono EF6MySqlTest.exe

only to see it failing with the following exception:

Missing method .ctor in assembly /home/pi/monotest/MONOTest/EntityFramework.dll, type
System.Runtime.CompilerServices.ExtensionAttribute
Can't find custom attr constructor image: 
 /home/pi/monotest/MONOTest/EntityFramework.dll mtoken: 0x0a00006a

Unhandled Exception: System.TypeLoadException: Could not load
type 'System.Runtime.CompilerServices.ExtensionAttribute' from assembly 'EntityFramework'.
  at EF6MySqlTest.SimpleContext..ctor () [0x00000] in :0
  at EF6MySqlTest.Program.Main (System.String[] args) [0x00000] in :0
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeLoadException: Could not load
type 'System.Runtime.CompilerServices.ExtensionAttribute' from assembly 'EntityFramework'.
  at EF6MySqlTest.SimpleContext..ctor () [0x00000] in :0
  at EF6MySqlTest.Program.Main (System.String[] args) [0x00000] in :0

The exception startled me a little bit. The very first thing I noticed was that the app failed even before it started executing. I looked at the documentation for the ExtensionAttribute type on the MSDN but I did not find anything extraordinary. Only comparing the documentation for .NET Framework 4.5 with the documentation for .NET Framework 4 gave me the clue. In the .NET Framework 4.5 the ExtensionAttribute type lives in the mscorlib.dll while in the .NET Framework 4 it lived in the System.Core.dll assembly. In general it is OK. CLR has this feature where a type can be moved from one assembly to another as long as its full name does not change and the original assembly contains the TypeForwardedToAttribute assembly level attribute pointing to the assembly the type lives in the new version (this is called type forwarding and you can find more details here). The exception I got just said that the EntityFramework assembly depends on the ExtensionAttribute which could not be found. Putting the information together I inferred what the exception did not say – namely that the ExtensionAttribute type could not be found in the mscorlib.dll assembly. This was just one step away from solving my problem. If the mscorlib.dll did not contain the ExtensionAttribute type then the type had to be in the System.Core.dll assembly which in turn meant that the version of the .NET Framework supported by Mono packages I installed was 4 and my application was compiled targeting version 4.5. This was not a big deal. Entity Framework 6 supports both .NET Framework 4.5 and .NET Framework 4 so I went back and recompiled my app so that it targets .NET Framework 4, copied it to my Raspberry Pi started again and… failed again. This time the exception looked like this:

Unhandled Exception: 
System.TypeInitializationException: An exception was thrown by the type initializer for System.Data.Entity.Config.DbConfigurationManager 
---> System.TypeInitializationException: An exception was thrown by the type initializer for System.Data.SqlTypes.SqlDecimal 
---> System.OverflowException: Can't convert to SqlDecimal, Out of range
  at System.Data.SqlTypes.SqlDecimal..ctor (Byte bPrecision, Byte bScale, Boolean fPositive, Int32 data1, Int32 data2, Int32 data3, Int32 data4) [0x00000] in :0
  at System.Data.SqlTypes.SqlDecimal..cctor () [0x00000] in :0
  --- End of inner exception stack trace ---
  at System.Data.DataColumn..ctor (System.String columnName, System.Type dataType, System.String expr, MappingType type) [0x00000] in :0
  at System.Data.DataColumn..ctor (System.String columnName, System.Type dataType) [0x00000] in :0
  at System.Data.Common.DbProviderFactoriesConfigurationHandler.CreateDataSet () [0x00000] in :0

  [... omitted for brevity ...]

  --- End of inner exception stack trace ---
  at System.Data.Entity.DbContext.InitializeLazyInternalContext (IInternalConnection internalConnection, System.Data.Entity.Infrastructure.DbCompiledModel model) [0x00000] in :0
  at System.Data.Entity.DbContext..ctor (System.String nameOrConnectionString) [0x00000] in :0
  at EF6MySqlTest.SimpleContext..ctor () [0x00000] in :0
  at EF6MySqlTest.Program.Main (System.String[] args) [0x00000] in :0

The good thing was that the previous exception was gone and that I could see some familiar Entity Framework methods in the stack trace. This means that this time the application at least tried running. But then I got to the System.OverflowException: Can't convert to SqlDecimal, Out of range exception thrown from System.Data.SqlTypes.SqlDecimal..ctor and started feeling a bit uneasy. This did not look like a bug in my code. On the contrary, it looked like some problem in Mono which I most likely would not be able to fix or work around. To confirm that it was unrelated to my app or EF6 I played a bit and came up with the following program that duplicated the issue (yes, it is just one line of code and it probably could be simplified even more):

public static void Main()
{
  Console.WriteLine(DbProviderFactories.GetFactoryClasses().Rows.Count);
}

Running the above code resulted in the same exception I saw when running my app:

Unhandled Exception: System.TypeInitializationException: 
An exception was thrown by the type initializer for System.Data.SqlTypes.SqlDecimal —>
System.OverflowException: Can’t convert to SqlDecimal, Out of range
 at System.Data.SqlTypes.SqlDecimal..ctor (Byte bPrecision, Byte bScale, Boolean fPositive, Int32 data1, Int32 data2, Int32 data3, Int32 data4) [0x00000] in :0
 at System.Data.SqlTypes.SqlDecimal..cctor () [0x00000] in :0

I looked around a little bit and found two bugs (bug report 1 and bug report 2) that looked similar to what I was seeing. One of them even contained a link to a patch with the fix which made me think that this might be fixed in a newer version of Mono. Soon I found this page which mentions a Debian Experimental version which is 3.0.6 as opposed to 2.10.8 installed on the Raspberry Pi. I tried to follow the steps listed on the page but unfortunately I could not install the experimental version due to missing package dependencies:

Reading package lists... Done
Building dependency tree
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
mono-complete : Depends: mono-devel (= 2.10.8.1-5) but it is not going to be installed
Depends: mono-mcs (= 2.10.8.1-5) but it is not going to be installed
Depends: mono-gmcs (= 2.10.8.1-5) but it is not going to be installed
Depends: mono-dmcs (= 2.10.8.1-5) but it is not going to be installed
Depends: mono-csharp-shell (= 2.10.8.1-5) but it is not going to be installed
Depends: mono-2.0-gac (= 2.10.8.1-5) but it is not going to be installed
Depends: mono-2.0-service (= 2.10.8.1-5) but it is not going to be installed
Depends: mono-4.0-service (= 2.10.8.1-5) but it is not going to be installed
Depends: monodoc-base (= 2.10.8.1-5) but it is not going to be installed
Depends: monodoc-manual (= 2.10.8.1-5) but it is not going to be installed
Depends: libmono-cil-dev (= 2.10.8.1-5) but it is not going to be installed
E: Unable to correct problems, you have held broken packages.

I am not a Linux guru but really wanted to make it work (or at least understand why it did not want to work) so I asked a question on stackoverflow and wrote an email to Mirco Bauer who seems to overlook Mono 3.0 on Debian. Unfortunately I have not received any answers which would help me resolve the problem so I gave up and forgot about this when suddenly after a couple weeks I got a response from Mirco. He wrote:

Mono has no working armhf port, but there is now work done to create an official armhf port. The only option for Mono is armel right now.

I have to admit that when I read the message I did not really understand it. So I did some research and found this post. It enlightened me and made me realize that the bug report I looked at before and the Raspberry Pi downloads page already had the answer I needed. I should have just tried understanding some details included there instead of ignoring them :). To put it simply
– the Raspbian “wheezy” is an armhf distro (and – as per email from Mirco – “Mono has no working armhf port”) while the Soft-float Debian “wheezy” is an armel image. The difference between the images is how they handle floating point operations. This gave me some hope. I downloaded the Soft-float Debian “wheezy” image and quickly prep my Raspberry Pi by installing mono and MySQL. One of the very first thing I did was to run the repro app to verify if the OverflowException is gone. Indeed this time instead of the exception the app wrote 7 (I wish it had been 42 but 7 is still better than OverflowException). This started looking promising so I tried to run the “proper” app. I got a few uninteresting exceptions (like no permissions to access registry etc.) but then I got this:

Unhandled Exception: System.TypeInitializationException: An exception was thrown by the type initializer for System.Data.Entity.ModelConfiguration.Conventions.Sets.V2ConventionSet ---> System.TypeInitializationException: An exception was thrown by the type initializer for System.Data.Entity.ModelConfiguration.Conventions.Sets.V1ConventionSet ---> System.TypeLoadException: Could not load type 'System.Data.Entity.ModelConfiguration.Conventions.KeyAttributeConvention' from assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
  --- End of inner exception stack trace ---
  at System.Data.Entity.ModelConfiguration.Conventions.Sets.V2ConventionSet..cctor () [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Data.Entity.DbModelBuilder.SelectConventionSet (DbModelBuilderVersion modelBuilderVersion) [0x00000] in <filename unknown>:0
  at System.Data.Entity.DbModelBuilder..ctor (System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration modelConfiguration, DbModelBuilderVersion modelBuilderVersion) [0x00000] in <filename unknown>:0
  at System.Data.Entity.DbModelBuilder..ctor (DbModelBuilderVersion modelBuilderVersion) [0x00000] in <filename unknown>:0
  at System.Data.Entity.Internal.LazyInternalContext.CreateModelBuilder () [0x00000] in <filename unknown>:0
  at System.Data.Entity.Internal.LazyInternalContext.CreateModel (System.Data.Entity.Internal.LazyInternalContext internalContext) [0x00000] in <filename unknown>:0
  at System.Data.Entity.Internal.RetryLazy`2[System.Data.Entity.Internal.LazyInternalContext,System.Data.Entity.Infrastructure.DbCompiledModel].GetValue (System.Data.Entity.Internal.LazyInternalContext input) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: An exception was thrown by the type initializer for System.Data.Entity.ModelConfiguration.Conventions.Sets.V2ConventionSet ---> System.TypeInitializationException: An exception was thrown by the type initializer for System.Data.Entity.ModelConfiguration.Conventions.Sets.V1ConventionSet ---> System.TypeLoadException: Could not load type 'System.Data.Entity.ModelConfiguration.Conventions.KeyAttributeConvention' from assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
  --- End of inner exception stack trace ---
  at System.Data.Entity.ModelConfiguration.Conventions.Sets.V2ConventionSet..cctor () [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Data.Entity.DbModelBuilder.SelectConventionSet (DbModelBuilderVersion modelBuilderVersion) [0x00000] in <filename unknown>:0
  at System.Data.Entity.DbModelBuilder..ctor (System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration modelConfiguration, DbModelBuilderVersion modelBuilderVersion) [0x00000] in <filename unknown>:0
  at System.Data.Entity.DbModelBuilder..ctor (DbModelBuilderVersion modelBuilderVersion) [0x00000] in <filename unknown>:0
  at System.Data.Entity.Internal.LazyInternalContext.CreateModelBuilder () [0x00000] in <filename unknown>:0
  at System.Data.Entity.Internal.LazyInternalContext.CreateModel (System.Data.Entity.Internal.LazyInternalContext internalContext) [0x00000] in <filename unknown>:0
  at System.Data.Entity.Internal.RetryLazy`2[System.Data.Entity.Internal.LazyInternalContext,System.Data.Entity.Infrastructure.DbCompiledModel].GetValue (System.Data.Entity.Internal.LazyInternalContext input) [0x00000] in <filename unknown>:0

The most important thing here is Could not load type 'System.Data.Entity.ModelConfiguration.Conventions.KeyAttributeConvention' from assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.. I looked at the KeyAttributeConvention and the class is very simple. There is actually hardly anything that could break here. Since the only dependency this class has is the KeyAttribute type it had to be the thing that caused problems. Again, I tried to isolate the issue so I added the following line to my test app:

Console.WriteLine(typeof(System.ComponentModel.DataAnnotations.KeyAttribute).Name);

After I did this the test app failed to compile complaining that it cannot resolve the KeyAttribute type and recommended adding references to an assembly containing a definition of this type even though I did provide a reference to System.ComponentModel.DataAnnotations.dll. This was weird. I decided to list all the types from the System.ComponentModel.DataAnnotations.dll assembly to make sure that the KeyAttribute is there so I replaced the line referring to the KeyAttribute with:

foreach(var t in typeof(ScaffoldColumnAttribute).Assembly.GetTypes())
{
    Console.WriteLine(t.FullName);
}

After running the app I looked at the type names and could not find the KeyAttribute type. This is unfortunate since it means that it’s impossible to run EF6 on the stable version (2.10.8) of Mono I installed. I thought the attribute might have been added in a newer version so I tried installing the experimental version. Unfortunately this did not really work. This time I did not get any errors but I got the message mono-complete is already the newest version and nothing was installed.
This was an interesting journey and I am a bit disappointed I was not able to achieve what I wanted especially because the goal seemed so close. The bright side is that I learnt quite a lot of interesting things and I believe it will be possible to run EF6 on the Raspberry Pi when either Mono works on armhf or there is a newer version of Mono for armel available. I will give it a try for sure in the future!