Categories
Uncategorized

Project digital drink vouchers – part 3

After a bit of a break, I turned back to the digital drink voucher project. Most of the functionality described in the earlier blogs have been implemented, and I have decided to release the whole thing under the GPLv3 license. I have also setup a rudimentary website at drinks.catlab.eu. Feel free to use our hosted instance, just don’t rely on it too much ūüôā

I’ve also removed the vendor specific authentication mechanics from the open source project, so you can now just set it up with the traditional laravel authentication forms.

I’ve also started writing some documentation, but for now it’s limited to describing how I’ve designed the NFC topup cards. Please give it a read and let me know if there is any scenario that might still be causing problems (other than the ones I’ve already described in the file).

Next week we’re using the NFC cards ‘in the wild’ for the first time. An earlier test with 3 teams at the first quiz resulted in a few bugfixes, but now I’m confident that the system should work as expected.

Hopefully…

Categories
Uncategorized

Project digital drink vouchers – part 2

Raspberry pi

After driving for 20 minutes to buy a microsd card, I opened the raspberry pi box to discover that a microsd card was included in the box. Yay me.

I started out by installing Ubuntu Core on the Pi, since I thought it would be easy to create a snap from the nodejs application that would talk to the pcscd service. This proved a little more difficult, so after about half a day trying I ended up installing Ubuntu Server on the Pi. Installation of the required services and nodejs environment went without issue.

Talking to the NFC tags in nodejs was pretty easy; I used a nodejs package that already handles most of the conversation between pcscd daemon and the nodejs environment, and the repository included examples on how to passport protect NTAG213s, so that jumpstarted development.

The NTAG2x password protection only allows you to set a 4-byte password, so you can’t really call it a security measure. I decided I would use the 4-byte password to discourage users overwriting the tag, but the true authentication would lay in using an SHA-256 HMAC on the content I would write. The 32 byte signature already takes quite a big bite on the 144 byte total available memory, but given the offline requirements this seems like a fair tradeoff. The password also only enforces write protection, I decided to keep all data on the card readable; since I’m planning to open-source the whole project it doesn’t seem logical to disallow users to read their won tag.

In our current ‘CatLab Drinks’ application, an organisation can organise multiple events. Our own organisation is active in multiple locations, so it makes sense to have a separate pricelist for each location. Early on we have decided that credit bought at one event would be transferable to other events, so each nfc card is linked to the organisation, not the event. So I gave each organisation their own ‘nfc secret’ which is used to calculate both the NTAG213 password and the HMAC.

Since we’re planning to allow users to topup their credit with their cellphone, I decided to encode all data in the NDEF format. This way I was able to write one NDEF record with the user specific URL for topup, while the signed wallet data would be stored in a second NDEF record. There is a very, very small overhead, but giving users with an NFC-ready phone the ability to scan their card and topup straight from their phone, seems worth it.

Signed data

It took me some sleepless nights to figure out what to actually store on the NFC tags. ‘Current balance’ is an obvious one, but the requirement that not all POSs need to be online at all times makes the whole thing a little more difficult. In the end I decided to take a practical approach that – according to our sale statistics – would work out fine:

  • balance
  • transaction count
  • timestamp last transaction
  • 5x last transaction amount

All data is stored in 32bit signed integer. I briefly thought about storing the timestamp in 64bit, but it would be silly to think this format would survive another 19 years (and also I couldn’t figure out how to write 64 bit signed integer).

There are only 2 vital elements of this content: ‘balance’ and ‘transaction count’. Balance is obviously required, since otherwise it would be impossible to check if a user has enough credits to buy a drink. Transaction count, however, is also of vital importance. For starters it avoids people rewriting old data to the card. If they would do so, the POS would notice that the last seen transaction count is lower than the new transaction count, and can then dismiss the card.

(There is still a situation where an offline bar could not be in the possibility to transmit the new ‘transaction count’ to the other bars, and a user who decides to go to an online bar would be able to double-spend, but honestly this situation seems too uncommon to take into account. Also, when the offline bar would finally come online, it would upload all its transactions and the card would be charged into negative values.)

The 5 last transactions are not really required, they are just used for online POSs that don’t know about offline transactions. An online POS will always upload the card state to the server, and the last 5 transactions could then be used to fill in the gaps between the last known transaction and the current transactions. If the amount of transactions would exceed 5, a 6th ‘unreliable’ transaction would be constructed that holds the difference between the Nth and the 5th transaction.

Finally, the timestamp is not used at all. I’m not sure if it is usefull for salting purposes, but even if it’s not it might be a nice-to-have for the future.

Mirroring

I took some time checking the security requirements and I talking to some people about the format; it seems a reasonably secure system. So I got started and tried to write the data to the NFC cards.

One of my main concerns was writing to the tags. Writes can be interrupted at any time, and since the data I’m writing is rather long there isn’t any tear-protection available. I briefly thought about writing the balance data twice, so that there is always one record to recover from, but the space limitations of NTAG213 finally forced me to abandon the idea.

In the end I just went for storing the latest known (valid) data in the browser localstorage of the POS terminal, and throwing a big warning message whenever a write fails. This way, a user that presents their card and interrupts the write, will be asked to scan its card again. If a user would at this point walk away, he would end up with an invalid card. It will be up to my UX design to make sure that the bartenders handle this situation correctly and ask the user to scan their card again.

I also improved the NFC nodejs service to only write data that has changed since the last write, lowering the risk of tearing. Since the first NDEF message (with the topup url) will always stay the same, there is no reason to write that on every transaction.

Topup & spending

With the write-procedure implemented in a reasonably reliable way, it was now time to implement the POS side of things: allowing our own staff to topup cards and allow bartenders to sell beers… More about that in a next blog.

Categories
Uncategorized

Project digital drink vouchers

Since I am a huge fan of starting projects and never finishing/polishing them, I decided to give ‘nfc based digital drank vouchers’ a try. I am part of an organisation that regularly organises quizzes using our own QuizWitz software, and I am constantly trying to improve and optimize the way we organise our events.

At these events we sell drinks and snacks, and since I recently got interested in NFC I decided to see if I could introduce some cashless system that would replace our current foolproof ‘paper vouchers’ system. There are ofcourse loads of existing solutions on the market, but since we have absolutely no budget for that I decided to see if I could do something DIYish.

Last year I already implemented a simple webbased cashier system that allowed us to track what drinks were sold and also allowed players to order drinks straight from there table. We would then bring the drinks to their table and demand the required amount of ‘paper vouchers’. Some people would come straight to the bar and order drinks there, but both situations were handled by a very simple web based cashier system. And now I want to play with NFC cards, so … let’s get going.

The Goals

Our players have to register before they can join the quiz, so we already have the players grouped in teams of 4 (or less). My goal is to give each team a single NFC card that they can topup and use to buy drinks. At the same time, the ‘remote orders’ also still have to be possible, and I don’t want bartenders to walk around with NFC readers (since I only have 1 and it is not exactly portable). Additionally, since there is no budget, I try to keep hardware costs as low as possible and try to reuse parts I still have laying around.

  • Each competing team should receive 1 NFC card that can be used to topup and buy drinks.
  • Teams should be able to order drink through the existing app, so the team should be linked to the NFC card. Payment for a remote order is done at the time of the order, not at the time of drink delivery (so bartenders don’t have to walk around with nfc readers)
  • Players should be able to topup their credit online (through an online payment gateway). Players should also be able to topup in cash at the entrance.
  • The topup station must be connected to the internet.
  • It should be possible to have multiple POS (point of sales = bars) and, while the bars should try to maintain a connection to the internet, such connection should not be required.
  • The topup station at the entrance must always be connected to the internet.
  • We have an android tablet that we use at the bar, and we intend to keep using that.
  • I have a raspberry pi and 2 NFC card readers (ACR122U) that I intend to use. I also have 80-ish NTAG213 stickers that I want to use for this.
  • The user interface must run in the browser.

Having the requirements set, it is clear that the available credit must be stored on the NFC cards, which poses.

Babysteps

Since I have no experience with NFC I decided to start with trying to get that working. Since I don’t want to bother with trying to get android to play nice with the external NFC readers, I decided to connect the NFC reader to a raspberry pi 3 and install a socket.io server on the pi. All NFC communication will thus go over the network trough the rasperry pi. So I bought a microsd card and connected everything up… Wish me luck.

Categories
Uncategorized

Missie Noorderlicht, Act 2, Scene 4

Doek blijft dicht.
Jongeman speelt voor doek.
Dramatisch voorgedragen.

Voormiddag.
Een haiku door een jonge man.

Jongeman kucht / maakt keel vrij.

Regen verdringt sneeuw.
Racen over gladde weg.
Hotdog in buskot.

Licht dooft, applaus.
Even later, licht gaat terug aan.
Applaus ebt weg.

Namiddag.
Een haiku door een jonge man.

Jongeman maakt keel weer vrij.

Bus komt van Sortland,
Rijdt de boot op in Melbu,
Verder naar Solvaer.

Licht dooft. Gigantisch applaus.
Staande ovatie.
Even later, licht gaat terug aan.
Publiek gaat weer zitten.

Dank u.

Jongeman maakt keel nogmaals vrij.

Avond.
Een haiku door een jonge man.

Solvaer, koud en nat.
Pizza in warme oven.
Pintjes in pub.

Licht dooft. Applaus is oorverdovend.
Licht gaat terug aan, jongeman buigt diep.
Licht dooft terug. Applaus blijft. Publiek scandeert “bis”!
Licht gaat terug aan. Jongeman staat te grijnzen.

Dank u, dank u.
U bent te goed.
Ik kan u nog ééntje brengen.

Oorverdovend gegil vanuit het publiek.
Mensen beginnen te “shhhushen”.
Publiek bedaart.

Nacht.
Een haiku door een jonge man.

Publiek shhhhuust verder.
Publiek wordt helemaal stil.

Iemand in het publiek fluistert: “dit is mijn favoriete stuk!”

Sport op ‘t grote scherm.
Chelsea wint van Manchester (city)
Bier vloeit; buiten koud.

Jongeman buigt nogmaals diep.
Licht uit. Zaallicht aan.
Pauze.

Categories
Uncategorized

Missie Noorderlicht, Act 2, Scene 3

Cafetaria van een hotel in Noorwegen. Jongeman zit aan een tafeltje met een flesje bier voor z’n neus. Jongeman nipt af en toe eens aan het pintje, maar staart verder voor zich uit. Het meisje van het hotel komt het podium op.

“Hushta mal ikke yum yum kapouw?”
Jongen kijkt op van pintje.
– “Oh, I’m sorry. I don’t speak Norwegian”
“Oh, that’s alright. I van speak English. I was asking if everything is alright, sir?”
– “Oh. Yes. Well, it’s going alright. But do you mind if we talk in Dutch?”
“Why? My Dutch isn’t very good.”
– “Well, some of my readers are a bit slow…”
“Oh. Of course, I see. OK, ik zal probeer.”
– “Dank je.”
Jongen glimlacht en nipt van zijn pint.

“Wat doe je helemaal alleen hier?”
Het meisje staat met een dieblad tegen haar borst gedrukt.
– “Ik drink nog een pintje.”
“Maar je familie… Zij zijn al weg?”
– “Ja, die zijn al om tien uur gaan slapen.”
Het meisje glimlacht.
“Dat meisje dat bij je was, is toch nog jong?”
– “Ja. Maar ja, ze begint ook al saai te worden he.”
Het meisje knikt.
“Nood aan wat gezelschap?”
De jongen glimlacht.

Het meisje zet zich op de stoel recht tegenover de jongen. De jongen schuifelt wat nerveus. Het meisje grijnsd.
“Moet je me dan niets te drinken aanbieden?”
Jongen tast in zijn zak en haalt zijn portefeuille boven. Hij draait ze om boven de tafel en er valt enkel een houten knoop uit.
– “Ik vrees dat ik geen kronen meer heb.”
Het meisje neemt de knoop en doet alsof ze hem grondig inspecteert.
“Maar jullie hebben hier een kamer, toch?”
De jongen knikt.
“Dan zetten we het nu toch gewoon op de rekening van de kamer?” De ogen van het meisje fonkelen.
De jongen lacht terug. – “Doe mij dan maar nog een lontje van ‚ā¨7,00. En neem voor jezelf ook maar wat.”

Meisje gaat af.
Jongen kijkt wat onwennig om zich heen.
Jongen bestudeerd knoop, likt er aan, trekt vies gezicht en steekt knoop terug weg.
Meisje komt terug met twee pintjes.

“Vertel eens, jongen. Wat vind je ‘t schoonste van Noorwegen tot nu toe?”
De jongen strijkt door zijn baard en doet alsof hij diep aan het nadenken is.
– “De meisjes.”
Het meisje lacht luidop.
“Bevalt het je dan?”
– “Ja, er lopen hier echt schone meisjes rond.”
“En dat vind je ‘t schoonst hier? Niet de bergen, of de fjorden, of het Noorderlicht… maar”
– “… de meisjes. Yep.”
Jongen grijnst.

“Dus vandaag heb je de hele dag naar meisjes gekeken?”
– “Nee hoor, ook wel wat rond gereisd.”
“Wat gezien?”
– “Ja, mijn zus had eigenlijk de reis al wat gepland?”
“Is dat je zus?”
– “Ja.”
“AH, leuk!”
– “Wie dacht je wel dat het was?”
“Euh, neeja, niemand.”
Meisje kucht nerveus.
“Euh, en waar ben je naar toe geweest?”

– “Wel, even denken. Deze ochtend hebben we die kabelbaan naar de top van die berg daar genomen.”
“Stor¬≠stei¬≠nen?”
– “Sorry?”
“Dat is de naam van die berg.”
– “Aha, OK. Ik zal het proberen onthouden.”
“Het betekent “grote steen” in het Noors.”
– “Wie vindt dat uit…”
“Mijn voorvaderen.”
– “Euh. Ja. Misschien.”
Beide nippen van hun pint.

– “Goed, de kabelbaan naar de top van de Stor¬≠stei¬≠nen genomen dus…”
“Welja… Top…”
– “… De kabelbaan naar het midden van de Stor¬≠stei¬≠nen genomen?”
“Nou, het is best wel wat hoger dan het midden…”
– “Wat is het dan wel?”
Jongen begint een beetje ge√Įrriteerd te worden.
“Goh, bet kabelbaan station?”
– “… dan hebben we de kabelbaan genomen naar het kabelbaanstation op de Stor¬≠stei¬≠nen dat hoger ligt dan het midden van de berg maar niet zo hoog als de top?”
Het meisje grijnst.
“Correct.”
– “Takk.”
Kuch. “Euh, Nederlands…”
– “OK, ok. ¬ęBedankt.¬Ľ”

“En daarna?” vraagt het meisje.
– Daarna zouden we naar een Samisch kamp trekken, maar na wat extra lezen leek het ons een erg commerci√ęle bedoening te zijn?”
“Oh, en je was al onderweg?”
– “Ja, we zaten al 25km van Trons√ł.”
“Wat heb je dan gedaan?”
– “Terug gekeerd.”
Meisje trekt een wenkbrouw op.
“Heb je de benzineprijzen hier al gezien?”
De jonge’ negeert de vraag.

– “We zijn dan meteen doorgereden naar Sommar√ły.”
“Dat is nog eens 40km verder!”
– “Ja, maar ik vind het fijn om te rijden hier.”

“Maar Sommar√ły, daar is toch ook niet veel te doen?”
– “We hebben er gegeten.”
“En daarna?”
– “Eventjes buiten gestaan en gekeken naar de oceaan.”
“Dat rijmt.”
– “Sorry.”

“En daarna terug naar Troms√ł?”
– “Yep. Naar het museum van poolvaarders.”
“Leuk?”
– “Best wel, maar we moesten ons haasten want het sloot al om vijf uur.”
“Ja, ik weet het. Ik heb er nog gewerkt.”
– “Werd je dan niet ziek van al die toeristen?”
“Soms. Maar hier is het niet veel beter.”
Hij knikte. – “Sorry.”
“Jij valt best nog mee.”
– “Takk.”

Meisje: “En daarna naar hier gekomen?”
– “Yep.”
“Met pizza?”
– “Met pizza.”
“Kwam hij hier uit de straat?”
– “Ja.”
“Lekker je?”
– “Ja.”

De jongeman geeuwt. De pintjes zijn op.
– “Ik ga maar eens slapen…”
“Nu al?”
– Ja, ik moet morgenvroeg rijden.”
“Blijf je niet nog even?”
De jongen stelt zich recht en neemt zijn jas.
– “Slaap zacht, Noors meisje.”
Het meisje glimlacht.
“Slaap zacht.”

Jongen gaat af. Meisje zet lege flesjes weg, haalt schotelvod uit schort, kuist de tafel, neemt een nieuw flesje bier, kijkt naar de klok, neemt een slokje van het bier en zucht. Doek.

Categories
Uncategorized

Missie Noorderlicht, Act 2, Scene 2

Jongeman zit door raam te staren. Op een bureau: pen en papier. Jongeman schrijft luidop.

Jongeman:
Het is gebeurd, liefste. Het is vandaag gebeurd. Ik vind het jammer dat je er niet bij was, maar ik beloof dat ik je nog wel eens mee zal brengen.

Ook vandaag begon het allemaal ‘s ochtends. De zon kwam op en Vader werd wakker. Of nee, vader werd wakker lang voor de zon op kwam. Omdat we nog moesten ontbijten. Omdat dat ‘s ochtends hoort.

Ik bleef echter te lang liggen en dronk dus enkel een tas koffie; of eerder, een halve tas, want het busje dat ons ‘aar de luchthaven zou brengen zat alreeds vol met bejaarden van ietwat hogere ouderdom, die ongeduldig op ons zaten te wachten.

Busje op, rijden maar. Aan een duizelingwekkende vaart, op spekgladde wegen. Ik kon mijn ogen niet geloven! De oudjes moesten zich vastklampen aan elkaar om niet uit de bus geslingerd te worden.

Luchthaven, liefste. Busje af (“takk”), vliegtuig op. Vliegtuig af in Narvik. Naar Hertz: rental car please. Sleutel gekregen (“takk”) en ondergetekende aan het stuur.

Ik heb het snel geleerd, liefste, waarom we die ochtend niet gestorven waren in een gekanteld busje. Spijkers in de banden. Van metaal. Voor meer grip. En werken dat dat doet!

Ik ben niet langer bang van ijs op de weg.
Ik ben nu enkel nog bang van spinnen.

Van Narvik zijn we dan naar Troms√ł gereden. Dat is de grootste stad van Noord Noorwegen, maar ook in Noorwegen is ze nog vrij groot. Het is er koud en er ligt daar ijs op de wegen. Verder lijkt het leven er wel fijn.

In het hotel gestopt. Bagage achter gelaten. Naar de kerk, maar de mis was al bezig en God wou ons daar niet. Dat voelde ik, want hij strafte Silke met een splinter.

(Ikzelf bleef voorlopig ongeschonden, maar Hij heeft ongetwijfeld nog een plan voor mij.)

Naar een andere kerk dan maar. Een houten kerk. Volgens het boekje de enige houten kathedraal ter wereld. Had echter veel weg van een kerk.

Daarna hebben we gegeten, liefste. Ik at een pepersteak. En een grote cola. Liefste, zo’n grote cola, dat kan je je niet voorstellen! En duur. Duur!

En terug naar het hotel. En door het raam gekeken. En iets gezien dat me blij maakte…

Er hing een vreemde wolk in de lucht, liefste! Een wolk die leek licht te geven. We zijn dan met z’n allen naar buiten gerend om dit vreemde fenomeen verder te onderzoeken…

Het Noorderlicht! Na jarenlang wachten, eindelijk gezien. Het licht speelde van links naar rechts; van horizon tot zenit. En al die kleuren! Ofja, welja… groen. Maar wat een schoon groen dat het was…

Ik moest aan je denken, liefste. Over hoe fijn het niet zou zijn als jij er was… Maar toen vroren mijn vingers er af en ging ik binnen naar Jim Carrey kijken.

Jonge man frommelt papier tot propje en eet het op.

Categories
Uncategorized

Missie Noorderlicht, Act 2, Scene 1

Jongeman ligt in bed, televisie speelt op achtergrond. Zacht geluid van snurkende mensen. Af en toe geluid van overvliegend vliegtuig.

Na een eerder gefaalde poging: terug naar het noorden. Lapland. Of toch het stuk dat overlapt met Noorwegen. Lapland: geen eigen taal, geen eigen natie; wat is het punt?

Deze ochtend dus vroeg opgestaan om naar Charleroi te treinen. Vlucht naar Oslo… Of eerder, wat Ryanair als “Oslo” ziet: Oslo Rygge, een mooie 50km van de hoofdstad zelf. Busrit naar het station, trein naar Oslo, een dik uur later: opgelost. SMS van Ma: “Alles in orde daar?” – “Yep”.

Birger King. Yum. Hebben we nog nodig in Gent. En dan terug de trein terug op, naar de andere luchthaven van in de buurt van Oslo: Gardermoen. Serieuze luchthaven. Alles tip top in orde. Elke serieuze luchthaven hoort een station te hebben.

Goed. Station uit, luchthaven in. Luchthaven terug uit, taxi in. Naar het hotel alsjeblieft. Een bed en breakfast volgens de folder, meer een motel volgens eigen beleving. Maar ‘t is warm en Trainspotting speelt er op de televisie.

Iedereen moe en ik slapeloos.
Morgen naar Narvik.
Nog geen noorderlicht te melden.

Licht verduistert, doek.

Categories
Uncategorized

Ludum dare – 100 – The end

I’m throwing the towel in the ring. Still ten hours to go and I probably could finish at least one room by the end of the challenge, but I have to prepare some stuff for next week, so I can’t go much futher.

So how far did I get? You can check it out here. I’ve spent most of the time yesterday working on a working rigging system to animate the characters. Today I finally could get started at simple interaction. I’ve implemented some kind of simple walking algorithm, but it looks aweful. However, with a little more work it could become something very acceptable.

I know all I did was make a very simple canvas implementation of features Flash simply has build in. And I also know there probably are frameworks out there that do whatever I made a lot better. But I wanted to start from scratch, so that’s what I did.

And well, maybe one day I’ll continue working on this tiny adventure game.

Categories
Uncategorized

Ludum dare – 011 – One day later

So we’re almost a full day into Ludum dare. I’m not sure how I feel about the project. On one side, you could consider I have made a few huge steps towards a working engine, but it’s far from being finished. The rigging system I wrote works … kindof. There still are some mistakes in transfering the desired angles to the “child bones”.¬†The event manager kindof works, but due to the trouble with distributing the angles I sometimes get rather weird effects.

As far as level design, I have nothing yet. I don’t even have a system to create the rooms yet. I have the two first rooms ready in my mind, but without the proper system to implement them, I’m still nowhere. I hope I can develop such a system in the next few hours, so I can concentrate on content tomorrow. After all, this is a content driven game and without content it will only last for a few minutes.

Anyway, this is that status of the “game” as of 00:27 (Belgian time, of course).

Categories
Uncategorized

Ludum dare – 010 – Rigging

To have complete control over my character, I have decided to go for a 2d rigging system. My main character will be composed of a number of sprites, each with their own position and rotation. Changing the position of one sprite should influence the position of all attached sprites, that way providing an easier way to program the animations.

I have no experience at all working like this and I haven’t found (and didn’t properly look for) existing libraries, so I’m doing all the math myself.

I still have until this evening to finish the engine and the whole rigging system. If I don’t make it, there is no point in continueing, so let’s hope I have something nice by then.

(Thanks to instragram the above picture is now worth 1 billion dollars.)