Monday, November 17, 2014

ER301 NFC/Mifare driver in pure C#

A YouTube viewer found my old demonstration of ER301 anti-collision and asked if I could make the source code available. So I cleaned it up a bit and wrote this small blog entry about it.

When I started tinkering with the unified Danish transit card about a year ago, it was using a cheap Ehuoyan ER301 NFC/Mifare reader which I got from ebay. This was the first time I played with NFC stuff even if I would since move on to other and better devices. The cool thing about the ER301 however, apart from the price, is that it's relatively easy to interface with. This is because it's using a plain virtualized serial port with native (cp2102) driver available in Linux and even Windows.

No software came with the ER301 reader but there was a download link at the ebay site. The software was very basic, and all examples revolved around a driver DLL for which the source code sadly was not provided. With the documentation in hand and tracing the traffic going over the serial interface, I decided to implement it in pure C# so I would not depend on Windows and static architecture libraries.

Although originally developed with Mono/Monodevelop, the current sources revolves around a Visual Studio solution, with the driver as one project and a simple console application as another. Note that the driver is not complete yet and it caters only to the needs I had at the time (complete dump of data), but it should be fairly easy to extend it with the granularity you might need, since most of the core API have already been implemented. It supports Mifare Classic S50 (1K) and S70 (4K). It can easily be made to support other types as well as long as it's supported by the ER301 hardware.

ER301.NET Console app dumping data from a Mifare Classic S70/4K

The source code is available on Github under GPL2 and most of the interesting stuff takes place in ER301.cs. I am looking into releasing a (WinForms) client application as well, but I need to clear it with a customer of some derivative work first.

Sunday, November 9, 2014

Øredev 2014 - The good and the bad

Last year I went to the 2013 GOTO conference in Aarhus, Denmark. This year, I got the opportunity to visit the 2014 Øredev conference in Malmø, Sweden. The following is just a short reflection of my experiences and they may of course be entirely different than those of other attendees.

The whole setup of Øredev is similar to GOTO and with 1300 attendees I believe they are about the same in size. Being in Sweden, albeit right across the water from Copenhagen, the crowd was predominantly Swedish with perhaps 20-30% of Danes. The speakers were slightly less known than those at GOTO, although a few speakers from Thoughtworks, Oracle and Microsoft stood out.

The good
Øredev feels quite a bit more intimate and cozy than GOTO did. It could be due to the constrained space and the lighting, but the pillow sacs, live jazz and plenty of popcorn, chips, candyfloss and beer sure didn't derail that perception.

Wifi coverage was generally good and there were plenty of sessions to attend as a whole. With decent food and no shortage of coffee, cake, snacks and candy, there was no risk of running out of energy anytime soon. At some point they did run out of the local no-name cola brand and finally gave us real coca-cola soft-drinks. If there's ever an event where you should not skimp on brand name cola, it's probably a conference for developers! :)

The venue also had more of a geek festival feel to it than GOTO had, with its 3D printing, classic console platforms, arcade machines, Occulus Rift etc. There were of course still the typical product pitch stands but it didn't feel quite as dominating.

Unlike at GOTO, where lunch takes place in another building at a specified time, lunch took place in the middle of the venue and was spread out over 1½ hour during talks. This meant that people would not all have to stand in line at the same time nor would it feel quite as chaotic. Also, lunch was served from 3 different locations in the halls, contributing further to the feeling of being able to breathe.

It's also very impressive that the Øredev video's are available some 24h after their capture, something other conferences could definitely take a lesson from. This means it's not quite as annoying to have gone into the wrong talk, since you can always catch up on the one you missed. I remember waiting several months for some of the GOTO videos to come out and I have since forgotten about those I missed seeing.

Last but not least, because of Sweden's very restrictive alcohol policies, you can drink a lot more beer before feeling it. A standard Tuborg with 4.6% alcohol is watered down to 3.1%. Not sure whether to characterize this as either good or bad, but it was an interesting observation none the less.

The bad
Interestingly, and unlike at GOTO, the organizers had not chosen to create an app for the event. This was unfortunate, since the supplied programs were not at all detailed enough to make you decide between conflicting talks - 8 simultaneous tracks are hard to choose from, when all you have to go by is a condensed headline.

In stead, you had to rely on the website which didn't work much of the time due to an unresponsive server and also suffered from navigation issues (on Android anyway). It's a good example of how you can scale so much better by taking advantage of a richer client (read: app) with its own state.

Staying with the app theme, it would also have been nice if rating of sessions was possible from your smartphone - sure there were the occasional iPad with a green-yellow-red star on, but it was only for some sessions at some doors. The GOTO app rating was buggy but at least they had put a bit more thought into it.

Finally, before leaving the app aspect, I also missed being able to ask questions during sessions for immediate followup at the end of the talk. This was something I took great advantage of at GOTO, in order to engage the talkers with my own thoughts and issues. At Øredev only a few of the speakers had set aside time for questions and I think that's a real shame. I got to ask 3 questions at Øredev whereas at GOTO I got to ask 11 questions and also opened up an email discussion about micro-services with Sam Newman from Thoughworks in the following weeks.

The seating at Øredev was perhaps a bit worse than at GOTO, with even the one large theater being devoid of armrests. It's a minor detail for sure, but after spending a day sitting down on tight hard chairs in jam-packed rooms, it would be nice with a bit of cushioning.

The worst experience at Øredev was definitely the interview with Nile Rogers. He was scheduled as a special keynote thursday night about "Passion and collaboration". Now granted, I never heard of the man and I have no special relationship with black hipsters from the 70's, but I still dare to say the interview missed its intended purpose. While Nile was certainly an experience and clearly commanded a guitar in the brief moments we were allowed to hear that, at many occasions I was left with "WTF is this?". At no time did the interviewer succeed in bringing either passion or collaboration into the picture, but seemed more interested in celebrating Sweden for its musical roots and making statements confusing poor Niles. Most of my colleagues had left midway in, I left after 1½ hour where the interviewer had apparently only addressed 4 out of a total 10 questions! If you'd like to see for yourself if it was really that bad, the interview is available here but I'd encourage you to spend your spare time on some of the other video's.

In conclusion
It was a very nice conference experience. In particular I'd like to highlight the cozy venue, widespread plentiful content and the fact that the logistics just simply worked. I do think its a pity, that a large amount of the attendee fee went to pay first class airfare, bodyguard, interviewer etc. for Nile Rogers and his wife and entourage. These conferences should not only be available to large corporations with enough money on their hand and I get the impression that the fee would've been lowered by 1000kr if they didn't have to cater to spoiled famous musicians.

I probably got more professionally out of my visit to GOTO simply because of the inherent ability to engage with the speaker through the questions. If Øredev would adjust these things, it would be a slam dunk which conference to go to.

For the mortal developers not engaged by large corporations, don't forget there's a very approachable and affordable conference in Copenhagen nov. 14 called Driving IT. Having attended IDA events before, I'd love to attend this one as well, but I think 2 conferences within one month is probably pushing the limit with my employer.

Saturday, October 18, 2014

TopIt - Window utility for Windows

It's been many years since Linux became my #1 OS of choice, for a variety of reasons. However, I changed job recently and one unfortunate side effect of that, is that I'm now having to spend my work hours on Windows again. Apart from the lackluster command-line, bloated environment, inhospitable development experience etc. etc. one of the annoying aspects, is how desktop and window management basically haven't changed since Windows 95 - for instance, it's still up to the individual application in question, whether it wants to allow the user to pin down a window, promoting its z-order to always be on top. This blog entry is about my attempt at bringing a bit more power to window management as seen from a Linux user.

Gnome Linux desktop
Talking about "the Linux desktop" is a bit of a misnomer. There are of course countless of XOrg window managers. All the recent KDE and Gnome versions I've come across, supports being able to pin a window on top (promote z-order), move a window to a specific workspace/desktop and control a windows transparency/opacity.

In Cinnamon, the Mint fork of Gnome Shell, z-order behavior is build right in!

Crap-ware nightmare 
There have never been a shortage of 3'rd part tools available for Windows to empower users, the problem is... finding them and knowing the flowers from the bad weed. Traditionally there's lots of spy-ware, share-ware, trial-ware in the Windows Eco-system.

I set out with a relatively modest goal, to find a simple application that would allow me to pin a window as the top-level window - something I use all the time for small TODO lists, calculator, chat applications etc.

One application turns up in Google searches as the de-facto solution to the problem, namely Window On Top, which also got a favorable mention on LifeHacker. I downloaded the application, installed it and all seemed fine and dandy... until I was met by a nag screen.

Bait-n-switch in action, Window On Top appears to be trial-ware!

Although neither the authors website, nor LifeHacker, has any mentioning of it being trial-ware, the application costs a whopping $20 - a ridiculous amount for something so simple! A similar utility called MooO which also got a mentioning on LifeHacker, is apparently infested with tool-bars and who knows what other crap.

Realizing full well how I may sound like a grumpy old fart with a long beard and entirely too much time on my hands, these crap-ware experiences made me want to try to solve this problem for myself.

Introducing TopIt
It's been some 10-15 years since I played around with the Windows API's. Back in the Visual Basic and MFC days, if you had to do something just remotely interesting, you had to call C/C++ functions from the core DLL's, so I had a pretty good idea as to how to go about this.

It took a few mornings and evenings of tinkering (when the wife and baby are sleeping), but I now have something entirely functional. In fact, it does more than just toggle a window on/off top - I guess you could argue that it already suffers from feature creep.

TopIt manipulating opacity/transparancy of a third-part window

These features are to be considered stable and tested:
  • <Alt>+<Z> Toggles the "always on top" Z-order lock of a window
  • <Alt>+<X> Completely hides the window temporarily (until combo hit again)
  • <Alt>+<C> Toggles the re-sizable/movable border of a window on/off
  • <Alt>+<Num Plus> Increases opacity (removes transparency) of a window
  • <Alt>+<Num Minus> Decreases opacity (adds transparency) of a window
The following features are tested but somewhat experimental:
  • <Alt>+<Num 5> Tries to expand window to take as much desktop space as available
  • <Alt>+<Num 2> Selects bottom edge of window for manipulation
  • <Alt>+<Num 8> Selects top edge of window for manipulation
  • <Alt>+<Num 4> Selects left edge of window for manipulation
  • <Alt>+<Num 6> Selects right edge of window for manipulation
These features are highly experimental and may or may not work:
  • <Alt>+<Num 7> Selects  top-left edges of window for manipulation
  • <Alt>+<Num 9> Selects  top-right edges of window for manipulation
  • <Alt>+<Num 1> Selects  lower-left edges of window for manipulation
  • <Alt>+<Num 3> Selects  lower-right edges of window for manipulation

You can get TopIt by downloading the raw x86/x64 executable or by cloning my reposatory on GitHub and building it yourself from source. The latter is preferable, as its the bona-fide approach to ensuring what you install on your computer. The memory footprint is absolutely minuscule, requiring just about 800KB of RAM.

Note that if you download the binary executables, you will have to launch it automatically when Windows boots. You can do so by including it in the Windows Start Menu "Startup" folder.

Since starting out on this project, I have since become aware of the utility called PowerMenu which looks very close to what I wanted originally, apparently without being crap-ware. The application is donor-ware, so should be safe to download and you'll likely want to use it rather than TopIt, since it is older and thus better tested. However, my efforts are not entirely wasted, as I plan to expand on TopIt further to get me some more power-features at a minimum overhead. Lot's of ideas come to mind:
  • Application screenshot (invoking "Save as..." dialog)
  • Emulation of multiple workspaces/desktops
  • Dockable and snapping windows
  • Menu item injection
  • Move applications to/from systray
  • Programmable hotkeys
Should you have any cool ideas which would boost your productivity on Windows, you are of course more than welcome to drop me a line about it or fork the code on GitHub and add it yourself. :)

Monday, April 14, 2014

Rejsekort Scanner i samarbejde med Rejsekort A/S

Siden mit forrige blogindlæg, har jeg taget kontakt til Rejsekort A/S og efterfølgende haft flere møder med dem, primært med chefkonsulent Gregers Mogensen. Det har været ganske interesant at få lejlighed til at stille spørgsmål og få indblik i de problemstillinger i systemet som jeg selv har oplevet.

Rejsekort A/S har været overaskende imødekommende og selv om min opfattelse måske er, at der har været lidt vel mange kokke i køkkenet, svarer de rimelig godt for sig og har anlagt en god pragmatisk holdning til tingene, hvilket incl. mig og mit lille indspark.

Der har udspillet sig lidt af en kamp på ord, imellem pressen og Rejsekort A/S, som også jeg blev en mindre del af. Min eneste kommentar til denne del af debatten er nok, at jeg ingenlunde forventer at mobilproducenterne retter ind efter et dansk rejsekort, selv om det da ville være skønt hvis de gjorde.

Udlevering af stationer/stoppesteder

Ved mit andet møde fik jeg uden viddere udleveret et Excel-ark med samtlige stationer/stoppesteder. Skønt det viste sig at Rejsekort Scanner læste stationsdata en smule forkert, gik der ikke lang tid før dette var korrigeret og stationsdata nu lå umiddelbart tilgængelig i selve app'en. Det betød at nu kunne den mest komplicerede del af programmet (geolocation og en masse asynkrone webservice kald) skrottes, ligesom programmet blev hurtigere og nu kunne vise samtlige 20000 placeringer - ikke kun de ca. 200 jeg havde fundet via crowd-sourcing. Excel-arket indeholdt også zone info, så jeg fik ligeledes mulighed for at forbedre aspektet "fortsat rejse" i tilfælde af når folk er under transit i samme zone men imellem forskellige stationer/stoppesteder.

Stod ved en skillevej

Indtil viddere har jeg kunne spille med åbne kort, udtale mig om præcist hvad jeg havde lyst til, beskyttet af det faktum, at man ikke kan tage copyright på, eller patentere, et format, en protokol eller et API. Selv om der er mange der har spurgt ind til de tekniske detaljer, har jeg med vilje undladt at kommentere og publicere dette aspekt indtil jeg havde tænkt tingene grundigt igennem og forhørt mig hos Rejsekort A/S.

Der var to primære veje frem. Enten fortsatte jeg som hidtil med reverse-engineering (puslespil for nørder) og lave en app der virker for de brugs-scenarier jeg lærer at kende igennem fejlrapporter. Alternativet var at indgå i et samarbejde med Rejsekort A/S hvor jeg ad officiel vej får adgang til den fornødne tekniske dokumentation. Der var fordele og ulemper ved begge veje, for selv om det ville være skønt at kunne lave app'en perfekt, strider en NDA imod mit princip omkring åbenhed - jeg har før omgået en NDA i en lignende situation.

Indgået samarbejde

Efter nøje overvejelser, indgik jeg d. 11/4/2014 et samarbejde med Rejsekort A/S. Udslagsgivende for dette var, at jeg blev ved med at modtage suspekte eksempler på rejser som Rejsekort Scanner ikke kunne vise korrekt, primært når en cykel var involveret, opgradering til 1 klasse, samt lignende specielle tilfælde der alligevel er forbavsende mange af. Rejsekortet er af en meget dynamisk natur.

Når jeg lagde alt sammen, var det mest fordelagtige for mig, at indgå i et samarbejde. Nogen vil sige at jeg har solgt ud, andre vil egentlig bare gerne have en Rejsekort Scanner der virker 100% korrekt. Jeg tror og håber på, at de fleste hører til den sidste kategori.

Samarbejdsaftalen giver mig nogle rettigheder samt nogle forpligtelser, og indeholder også et økonomisk incitament. Der er tale om et støtte-tilskud, ikke et køb, dvs. jeg bibeholder samtlige forpligtelser og rettigheder fremover, med undtagelse af at jeg nu ikke kan frigive kommende versioner som open-source jvf. tavshedserklæring. I praksis vil jeg have svært ved at bevise hvad jeg vidste før og efter aftalens indgåelse (selv om jeg har tagget revisionskontrolsystemet), så jeg vælger nok den sikre vej ved at sige så lidt som muligt.

Fortsat udvikling

Rejsekort Scanner vil altså efterfølgende nuværende version 1.1.28, blive viddereudviklet ud fra officiel teknisk dokumentation hvor jeg forventer at tilvejebringe rabat-trin, komfort-trin, person-antal. zone-skift mv. Jeg kunne også godt tænke mig, at forbedre usability lidt, ved f.eks. at vise saldo-bevægelser når man holder telefonen vandret, hvor der jo er lidt mere kolonneplads.

En "Pro" version, uden reklamer og med mere avancerede features, er også en vej jeg påtænker at gå - der er en del brugere der har givet udtryk for at de gerne smed en mønt, mod at komme af med reklamer. En evt. "Pro" version vil iøvrigt brige størrelsen på app'en ned fra 3MB til 1MB, da Google's AdMob ikke ville skulle inkluderes.

Skal jeg tænke endnu længere ud i fremtiden, kunne det være overlegent, at kunne beregne en forventet pris, FØR en rejse er afsluttet. Ligeledes, kunne "spar 12kr ved at tage afsted en afgang senere" eller "Opgradér til 1 klasse for 28kr" tips bidrage til yderligere gennemskuelighed af rejsekortet.

Den fortsatte udvikling er ikke blevet gjort mindre interesant, efter det har vist sig at flagskibene HTC One M8 og Samsung Galaxy S5, der vil stå for en betragtelig andel af smartphone markedet i det kommende år, kan skanne rejsekortet. Jeg har derfor selv købt førstnævnte! :)

One M8 har jeg kunne observere i loggen for Rejsekort Scanner i et par ugers tid.

Det er først fra den officielle launch-dag d. 11/4, at jeg er begyndt at kunne se seriøst aktivt brug af Samsung's Galaxy S5.

Tuesday, March 18, 2014

Opfølgning på launch af Rejsekort Scanner

Læs også nyere indlæg om emnet i form af Rejsekort Scanner i samarbejde med Rejsekort A/S.

Status og statistik

Så er det 2 uger siden at første version af Rejsekort Scanner landede i Google Play butikken, og en uge siden version2, og efterfølgende medier, tog nyheden op og fik udbredt budskabet. At sige at min hverdag tog en drejning, er en underdrivelse. Pludselig vrimlede det med aktivitet i min indbakke, på twitter, på Google Plus, YouTube, Linked In osv. Ja der var også kontakter fra folk der skriver speciale i det ene og det andet, eller som vil hjælpe med markedsføring, viddereudvikling osv. og det var ikke alle jeg nåede at vende tilbage til.

Peak var på førstedagen oppe på små 50 samtidige brugere, der dog sidenhen er faldet en del. Som forventet, benytter folk app'en ret kortvarigt, ca. 10-20 sekunder af gangen.

Der er nu over 5000 aktive brugere af app'en, der er landet på førstepladsen inde på Google Play både i den danske kategori "Transport" samt når man søger specifikt på "Rejsekort". Den ligger også nr. 3 kategorien "Bedste nye gratis apps".

Små 300 brugere har anmeldt app'en hvor den står til flotte 4.7 stjerner ud af 5 mulige. Denne relativ høje rating skyldes at jeg har forsøgt med hård hånd, at udelukke smartphones jeg ved app'en ikke virker med. De fleste kan naturligvis ikke gennemskue at det ikke er app'ens skyld, men mange har dog udvist forståelse.

Crowd-sourcing aspektet mht. indsamling af stationsnavne er gået over al forventning, hvor der på en uge er fundet 142 nye station/stoppe-steder - tak til jer der er med til at indsende disse!

Reaktioner fra brugere

Noget af det sjoveste har helt klart været at se alle de positive reaktioner inde på Google Play. Et par af mine udvalgte favoritter:
Denne app er i den grad noget faste pendlere har manglet! Rejsekort A/S, her kan I godt tage ved lære, super arbejde Casper!
Herligt. Super at der er nu er mulighed for at checke hvad der står på kortet. Tak for det
Nu har jeg tillid til rejsekortet igen.
Super funktionalitet, must have hvis rejsekortet skal bruges til andet end at skrabe ruder fri for is... hvilket det egentlig heller ikke egner sig synderligt til. TAK :-)
Kan se saldo, check inds og aktuel status. Du burde seriøst tilbydes arbejde ved rejsekort a/s så de kan få et seriøst kvalitetsløft :-)
Det tyder jo virkelig på, at der har været et behov, og derfor er jeg i dag glad for jeg lagde lidt ekstra arbejde i tingene og ikke bare nøjedes med at beholde app'en for mig selv. De relativ få negative kommentar jeg får, går primært på telefoner der har problemer med at læse Rejsekortet.

Reaktioner fra medier

Jeg valgte selv at tippe version2, da de traditionelt har fulgt det omtumlede rejsekort tæt, både da Christian Panton fortalte om kortets svagheder men også i mange andre tilfælde. Det var nok det rigtige valg, for dét blev startskuddet til en lidt vild uge i medierne - i alt fald for en introvert system-udvikler som mig der skulle bevæge sig rimelig langt udover sin traditionelle "comfort zone".
Ikke lang tid efter version2 havde skrevet artikel 1 og artikel 2 om app'en, fik nys om sagen og så landede man pludselig på en af danmarks mest besøgte websteder i form af artikel 1 og artikel 2. Så kom MetroExpress, efterfulgt af Politikken*, Living Smart, TV2 Beep og radio24syv. Sidstnævnte var en invitation til at komme i studiet, men valgte telefoninterview fordi der i ugens løb jo også har været et alm. arbejde at passe!

* Politikkens artikel får et par ting galt i halsen. Når jeg har Bluetooth er oppe at vende, skyldes det, at Apple jo ikke er til NFC, men har fokus på den nye lavenergi Bluetooth BLE. Da denne teknologi ligeledes findes til Android og Windows Phone, kunne det derfor være en interesant vej for Rejsekort A/S at gå. Derudover, kan ordlyden "var det ikke umuligt for udvikleren at komme ind" få det til at lyde som om jeg bryder ind i deres online system, hvilket jo ingenlunde er tilfældet, jeg tillader bare folk at aflæse relevante bits på deres eget rejsekort.

Reaktioner fra Rejsekort A/S

Skønt jeg ikke (endnu) har været i direkte kontakt med Rejsekort A/S, indhentede bl.a. Version2 en kommentar fra direktøren Bjørn Wahlsten, der udtalte:
Rejsekort er generelt positiv over for app-udvikling, som jeg har givet udtryk for. Kun cirka 20 procent af de nuværende smartphones på markedet kan bruges til hans app. Men når producenterne kommer med nye smartphones, kan det ændre sig
Der er sågar forlydender om at åbne lidt op for systemerne, så det bliver lidt nemmere at være en 3 parts udvikler som mig. For at det ikke skal være løgn, talte direktøren sågar om en "økonomisk håndsrækning".

Det er selvf. skønt at Rejsekort A/S ser pragmatisk på tingene og modsat Nets, ikke truer indie udviklere med bål og brand. Faktum er jo, at hvorvidt jeg var kommet med denne app eller ej, så hverken forringer eller forbedrer det noget som helst ved selve rejsekortet!

Jeg er måske lidt skeptisk mht. de udmeldinger omkring økonomisk hjælp og åbning af API, for ét er jo hvad man siger i pressen for at virke positiv og imødekommende, noget andet er hvad man mener bag lukkede døre.

Jeg vil kontakte Rejsekort A/S senere på ugen, for at følge op på deres udmeldinger og vise min interesse. Især station/stop-databasen ville være guld værd at få fat på, for det ville kunne forbedre oplevelsen for brugerne væsentligt, udelukke fejl og forsimple koden bag ved.

Udfordringer og lektioner

Det har været en learning experience i mange henseende, både mht. medier/opmærksomhed og mht. dét at launche en app med mange brugere på og det forventningspres der følger med når fejl skal kigges på og rettes - jeg har nået at frigive små 20 forskellige versioner i løbet af en uges tid!

De fleste medier har været søde og venlige, men jeg har dog også kunne mærke at man virkelig er i journalisters vold og magt. Nogle journalister havde meget svært ved at skille skidt fra kanel og forstå hvad min app går ud på. Andre igen, udfordrede mig på sikkerhedsaspektet ved at Rejsekortet nu kan læses af alle og ligeledes manipuleres med.

Jeg har svaret på mange hundrede emails/kommentar, mange af dem omhandlende samme kedelige svar "Beklager, men din mobil understøtter ikke Rejsekort...". Det er ikke altid jeg selv praktiserer RTFM så dét kan jeg nok ikke tillade mig at klage over.

På det mere personlige plan, har jeg helt sikkert ikke fået sover nok i løbet af ugen, ligesom jobbet har været en udfordring at passe til fulde. Det er problematisk når man som jeg, indgår i et større team der sammen arbejde på at få et nyt større projekt søsat. Heldigvis har jeg haft nogle forstående kollegaer.

Google Play er relativ hurtigt til at få opdatering ud, 3-4 timer tager det kun, hvilket er fremragende taget i betragtning af hvad det tager hos Apple. Google's Play opsamler også crash rapporter, som er guld værd. Det viser bl.a. hvor stor en forskel der er på telefonerne (nogle enheder mangler simpelthen ting i Android API'et) ligesom det påviser hvor vigtigt det er at kode defensivt (checke for alle tænkelige og utænkelige fejlscenarier).

Google Analytics er fremragende til at vise hvad der sker, og billederne i denne blog-entry er primært dérfra.

Google's AdMob var en sjov oplevelse, men lad det være sagt med det samme, man bliver ikke rig af at lave en app med 5000 brugere - jeg får måske lige præcist dækket frokosten på jobbet. Men når det drypper på præsten, regner det som bekendt på degnen. Min kollega og ven Jesper Bo Rasmussen og hans udemærkede app "Mit Rejsekort" har faktisk også nydt godt af den seneste uges virak. Desværre har jeg endnu ikke modtaget provision! ;)

Ugens sjoveste oplevelse var helt klart i taxaen på vej ud til TV2, hvor en snaksaglig taxachauffør selv drejede samtalen ind på den kollektive traffik (masser af S-togs problemer denne uge) og da vi nåede Tegnholmen havde han (i kraft af den megen traffik og de mange røde lyskryds) fået installeret Rejsekort Scanner på sin Sony smartphone og scannet sit eget kort!


Der er jo væsentlig forskel på at reverse-engineer et format "good enough" til at lave en app der virker på de 3-4 kort jeg selv har fingrene i, og så til at der er 5000 brugere med alverdens kombinationer af kort og rejser.

Det er gået op for mig at der, udover Rejsekort Personligt, Flex og Anonym, ligeledes findes Handikap, Ung og Pensionist. Så vidt jeg er informeret, skulle Rejsekort Scanner også virke til disse, men det er ikke noget jeg har kunne teste selv - af logiske årsager.

Især ét aspekt af Rejsekortet er lidt en torn i øjet, og kan vise sig særdeles udfordrende, nemlig den såkaldte "fortsat rejse" med transsit-tid. Under normale omstædigheder, kræves det ikke at man checker ud når man laver omstigning fra f.eks. S-tog til regionaltog, og sådan benytter vist også lagt de fleste mennesker systemet. Men reglerne foreskriver også, at man kan checke ud, og hvis man inden for 30min checker ind i samme zone, tæller det for én og samme rejse. Eftersom jeg endnu ikke har afkodet noget omkring zoner (der må være kilden til alt ondt for rejsekortet) har jeg været nødt til kun at kigge på om der er tale om samme stations ID eller ej. Ligeledes, har jeg en stært formodning om, at ting kan gå galt, når folk skifter retning inden for denne transsittid. Med andre ord, jeg ved at Rejsekort Scanner, i specielle tilfælde, ikke viser historikken og omkostningerne korrekt!

Der største begrænsning forbliver naturligvis dét faktum, at det ikke er alle Android smartphones der kan aflæse rejsekortet. Jeg kan ikke lade være med at tænke på hvor fedt det ville være, hvis samtlige ejere af Android telefoner i DK ville kunne benytte app'en - men de må så nøjedes med at lade en rejsepartner med kompatibel enhed, foretage et check. Det forlyder heldigvis, at den kommende Samsung Galaxy S5 vil virke med Rejsekort Scanner - hvis dette er korrekt, er det helt sikkert min næste smartphone. :)


Jeg vil fortsætte med at forbedre app'en, dvs. primært fejl-rette således at dét den gør nu. gør den korrekt. Derfor har jeg også netop tilføjet en "Fejlrapportér via email..." funktion, der vedhæftet relevante og anonymiserede data fra rejsekortet, således at jeg kan debugge problemet.

Alarm funktionalitet for check-ud vil jeg meget gerne snart tilføje, da det virker så åbentlyst og vil kunne laves relativt nemt.

Andre ting jeg gerne vil hive ud af kortet er sådanne ting som zone, rabat-trin, person antal, komfort-trin mv. men det må komme an på en prøve, eftersom jeg ingen ide har omkring hvad jeg vil finde i den kommende tid.

Det optimale scenarie er naturligvis, at Rejsekort A/S giver mig adgang til formatet på rejsekortet samt databasen for stationer. Rejsekort Scanner er jo ude nu aliigevel og bruges af en masse glade personer, så det kan være lidt svært at se hvad Rejsekort A/S får ud af at holde disse ting for sig selv hvis de kunne bidrage til en bedre app.

Thursday, March 6, 2014

Replacing glass on a Samsung Galaxy S3

I went over 5 years owning a state of the art smartphone without ever breaking the glass of one of them. However, those fine statistics came to an end about 10 days ago, when the phone slid out of my hand and went screen first straight into a tiled floor.

Although the Samsung Galaxy SIII is no longer state of the art, it's still plenty fast and one of the latest smartphones which still has NFC Mifare support (to understand why this is important to me, read my previous post). Furthermore, early march is possibly the worst month to go out and invest in a new smartphone, since both HTC and Samsung are launching their next generation model in a month from now. I've seen various videos on YouTube of people fixing the screen so I thought I'd try that, having very little to loose by attempting. I ordered this little kit from Amazon which arrived just a week later. As a guide to the actual process itself, I relied mostly on the one from iFixIt.
The kit came with a screen protector, so rather than using tape, I mounting this onto the broken screen, in an attempt to stabilize the glass panel.

Heating the glass panel with a heat gun was a scary exercise. I used a temperature gun at the screen, to try to monitor the heat-up without really knowning the target temperature. This involved a fair amount of trial and error. I had a lot of trouble getting started without also burning my fingers and melting the plastic tools.

The guides recommends to start at the very top of the phone, however, my phone was cracked much more around the top than the bottom. Furthermore, the cracks around the edge were significant and many. In fact, as small glass splinters were coming off, I got the nasty feeling that this was probably not going to end well.

However, after using a slightly higher temperature approaching 130 celcius, and working from the bottom of the phone and upwards, I regained some hope.

The key seems to be patience and plenty of heat. Eventually I managed to get the glass piece off, with only a minimal of glue gunk left on the actual AMOLED screen.

The easiest way to get the remaining glue off, seems to be to rub with your fingers.

I polished off all remaining traces of residue with standard alcohol wipes used for cleaning glasses.

The kit also came with some thin double-sided tape, which is used to attach the glass to the phone.

After careful cleaning of the AMOLED screen and removal of the back-side plastic protector of the new glass, it was time to let the two meet.

Voila, all done. I was surprised that the end result looked so nice, having read horror stories from other people who went through the process. There are a few lessons from my experiences, which I'd like to recommend to others:
  • Start the removal of the glass where it's the most intact. This will increase the chance of getting it off in one whole piece.
  • Aim for a glass temperature of around 120-130 celcius, any lower will likely cause you to crack the glass and cause more trouble for you.
  • Pry the glass very carefully, when you see the glass lift and melting glue ridges forming as the two parts are coming apart, try to keep it moving as slowly as possible.
  • Be careful not to use too much of the double-adhesive tape, as it will raise the level of the glass a bit too high. This happened with my attempt and I think I will try to remove some of the tape.

All in all, I remain very happy with the end result for £12. Is it perfect? Not yet - there is a slight difference in the feel of the touch screen due to the front glass panel being raised a tad too high. Is it easy? By no means - you should probably only attempt this if you consider yourself a bit of a tinkerer or you have a backup plan ready. :)

Sunday, March 2, 2014

Rejsekort Scanner

Unusual to this blog, the following entry is in danish due to the topic being the national transit ticketing system in Denmark, also known as Rejsekort.

Læs også nyere indlæg om emnet i form af Opfølgning op launch samt Rejsekort Scanner i samarbejde med Rejsekort A/S.

Rejsekort Scanner

Som det eneste program af sin art, lader Rejsekort Scanner dig aflæse dit Rejsekort direkte og øjeblikkeligt blive informeret omkring check-in status, saldo, rejsehistorik mm. Der er altså hverken behov for data-forbindelse eller kompliceret opsætning!

App'en er fungerer med Rejsekort Personligt, Anonymt samt Flex. Man skal bare have en smartphone med NFC der understøtter Mifare Classic smartcards.

Rejsekort Scanner er en uofficiel app uden adgang til Rejskort A/S' officielle systemer, og programmet kender derfor heller ikke alle placeringen for begivenheder udover dem der er fundet manuelt. Hvis du ønsker at opdatere denne liste kan du slå "Download placeringer" til i indstillingerne, som vil konsultere en central database for at hente evt. nye placeringer.

Hvis du ønsker aktivt at hjælpe med at indsamle disse placeringer, kan du yderligere aktivere "Geo-locate placeringer", som vil forsøge at finde stationsnavne tæt på hvor du er såfremt du netop har checket ind eller ud, og bede dig vælge den aktuelle station. Efterfølgende vil app'en indsende den nye stations-information til en central server (Google App Engine), således at placeringen kan deles med andre. Jeg sætter naturligvis pris på hvis folk vil hjælpe med til at høste disse placeringer, da det vil øge brugbarheden af app'en.

Prøv app'en ved at besøge Google Play Store.

Hvorfor blev Rejsekort Scanner til?

Som udgangspunkt savner jeg ikke de gamle klippekort. Men Rejsekort systemet synes desværre at excellere i uigennemskuelighed for den rejsende. Som en af de første pendlere med Rejsekort har jeg siden november 2011 oplevet:
  • Kontrolafgift p.g.a. uobserveret fejl under check-ind. Det kan være svært at høre (selv om de nu har lavet lyden om) og se (du får 2 sekunder) hvorvidt der checkes korrekt ind. Derudover synes Rejsekort standerne ikke at implementere anti-kollision særlig godt, så hvis du har mere end ét NFC kort i din pengepung f.eks. et medarbejdekort, så bliver standeren meget hurtigt forvirret. Prøv til sammenligning at checke denne video, hvor jeg har lagt mit medarbejderkort inde imellem 2 rejsekort, hvor G4S terminalen ingen problemer har med at udvælge dem én efter én. Eller denne video, hvor min billige Kina NFC læser med min egen driver, ej heller har de store problemer med at håndtere flere kort samtidigt.
  • Tvivl om hvorvidt man har husket at checke ind, eller gen-indchecke ved omskiftning. Eftersom man ingen kvittering har, er man ene og alene ladt i stikken til ens kortidshukommelse. S-togs revisorer har iøvrigt svært ved at se check-ind fra regional-tog og omvendt!
  • Manglende check-ud p.g.a. check-in stander fejlagtig brugt istedet. Standerne ligner hinanden på en prik og lyser samme blå farve, så det er ikke usandsynligt at man komme til at bytte rundt på dem (hvorfor i alverden har man ikke lavet én stander både med check-ind og check-ud, når de nu alligevel placeres i par og ligner hinanden?). Hvis man benytter en check-ind stander istedet for check-ud stander, får man ingen fejl-lyd så det gælder om at vælge rigtigt efter en lang arbejdsdag. Ifølge Rejsekort A/S' regler, hvis man glemmer at checke ud 3 gange inden for et år, kan man få sit kort indraget! Lad mig afsløre, at dette kun tog mig 144 dage!
  • Generel uvidenhed omkring saldo, depositum mv. For dém der ikke har automatisk optankning, eller bare gerne vil følge med, skal man konsultere en stander og lave en såkaldt 0-rejse (check-ind efterfuldt af check-ud) og skynde sig at bemærke den saldo der står i displayet. Det er lidt som at gå rundt med en pengepung, uden at du kan se om der er nogen penge i eller ej. Hvis Rejsekort A/S istedet havde forhandlet en aftale med Nets og altid trak pengende med det samme, ville det være 10 gange mere gennemskueligt for kunderne. Der er selvf. et problem med offline standere, men kunne de så ikke i det mindre bruge en unik ID som man kunne bruge til at sammenholde info fra deres hjemmeside med info fra sin bank?
Mange af overstående problemer skyldes simpelthen mangel på en kvittering. Desværre er det ikke nok blot at konsultere Rejsekortets hjemmeside, da systemet er asynkront og først viser begivenheder 20-30 minutter senere.
Rejsekort Scanner var derfor oprindeligt mit eget forsøg på at afkode Rejsekortet, der jo indeholder den øjeblikkelige sandhed - som også togrevisorer kan se når de kontrollerer de rejsende. Eftersom det lykkedes, i alt fald delvist, besluttede jeg mig for at frigive app'en så andre også kan få glæde af den indtil Rejsekort A/S kommer med en officiel version. Da app'en repræsenterer et ikke helt trivielt stykke arbejde i min iøvrigt begrænsede fritid, tillader jeg mig at smide et lille reklame-banner på app'en der skal motivere mig til at holde den ved lige.

Hvorfor virker den ikke på min mobil?

NFC er beklageligvis ikke bare NFC, idét der findes forskellige hardware standarder og software protokoller. NFC er bl.a. defineret via ISO/IEC-14443 og ISO/IEC-18092 der er moduleret på frekvensbåndet 13.56 MHz. Der findes mange konkrete produkter der bygger på denne hardware standard, bl.a. Broadcom Topaz, NXP Mifare/NTAG203/DESFire, Sony FeliCa mf. Udover en forskel på memory størrelse, er der også forskelle i funktionalitet via den overlæggende protokol.

Rejsekortet er baseret på NXP's Mifare (Classic 4K/S70) der indeholder proproitære overbygninger til autorisation og kryptering. Det betyder desværre, at kun NFC chips fra NXP er i stand til at kommunikere med rejsekortet. De første Android telefoner med NFC support, var bestykket med NXP's PN544 og sidenhen PN65N. Desværre er mange nyere Android telefoner istedet bestykket med Broadcoms BCM20793, hvilket betyder at Rejsekort Scanner ikke virker med samtlige Android telefoner der findes derude.

Følgende mobiltelefoner har ikke Mifare support, og virker derfor ikke med Rejsekort Scanner:
  • Google Galaxy Nexus
  • Google Nexus 4
  • Google Nexus 5
  • Google Nexus 7, version 2 (2013)
  • Google Nexus 10
  • Samsung Galaxy SII
  • Samsung Galaxy S4
  • Samsung Galaxy S4 Mini
  • Samsung Galaxy Ace 3
  • Samsung Galaxy Express 2
  • Samsung Galaxy Mega
  • Samsung Galaxy Note 3
  • LG G2
  • LG Optimus L7 II
  • HUAWEI Honor 2 (u9508)

Følgende mobiltelefoner har Mifare support, og virker derfor med Rejsekort Scanner:
  • Google Nexus S
  • Google Nexus 7 (2012)
  • Samsung Galaxy SIII/S3/SG3
  • Samsung Galaxy Note
  • Samsung Galaxy Note 2
  • HTC One
  • HTC One X
  • HTC One X+
  • HTC One XL
  • HTC Evo 4G
  • Motorola Droid Incredible 4G
  • Motorola Droid Razr
  • Motorola Moto X
  • Sony Xperia
  • Sony Z1 compact 
  • Acer Liquid E1/Express/Glow
  • Asus Padfone 2

Hvis app'en ikke virker på din smartphone fordi enheden mangler den fornødne hardware support, undlad venligst at give negativ feedback, da det reelt ikke er programmets skyld! Jeg hører dog gerne fra dig, således at jeg kan opdatere listen. :) Jeg efterstræber at lade Google Play udelukke muligheden for at installere programmet på smartphones der ikke har Mifare support, men dette er desværre noget af en opgave, da der p.t. er 5300 forskellige Android modeller med NFC support hvor jeg kun kender en brøkdel af dem.

Det er p.t. ukendt hvorvidt de kommende flagskibe, henholdsvis HTC's "The All New One" og Samsung's Galaxy S5, får Mifare support enten ved at benytte en nyere Broadcom NFC chip med support for dette (vil kræve licensering fra NXP) eller en NXP NFC chip (den ældre 544 eller nyere 547 chip).


Den obligatoriske disclaimer jeg er nødt til at have med for at beskytte mig selv lidt:
  • Bemærk at der her er tale om en uofficiel app, der ikke er leveret af Rejsekort A/S. Det kan derfor ikke udelukkes at app'en viser noget forkert, ligesom den næppe kan bruges som gyldig kvittering overfor togrevisorer.
  • Jeg er ikke ansvarlig for evt. kontrolafgift eller depositum-tilbageholdelse som følge af manglende check-in/check-ud.
  • På intet tidspunkt bliver der indsendt personlig information der kan identificere dig eller dit rejsekort.
  • App'en hverken forsøger, eller er i stand til (p.g.a manglende nøgler), at skrive data tilbage på rejsekortet og kan derfor ikke gøre nogen skade.


Der er stadig mange data på Rejsekortet som jeg ikke kan tolke. P.t. forstår jeg måske et sted imellem 10-15% af kortets egentlige indhold. Hvis der er nok interesse omkring app'en, vil jeg formeentligt fortsætte arbejdet. Det kunne bl.a. være interesant at lede efter data for rabat-trin, trafikselskab, rejseklasse, antal personer mv.

Det er nærlæggende at tilføje features der aktivt gør brug af disse informationer, f.eks. til at forudsige og alarmere når der skal checkes ud (de eksisterende GPS baserede programmer holder ikke i praksis), vise rest-tid for rejse-gyldighed, registersamkørsel mod Rejsekorts hjemmeside mv.

Det var lidt en streg i regningen, da det gik op for mig, hvor mange af de nyere smartphones der ikke har Mifare Classic support, da det udelukker mange Android brugere fra at bruge app'en. Et gæt er at over 50% af Android brugere på forhånd er udelukket, og det er en procentsats der formeentligt vil stige over tid. Jeg håber naturligvis at nyere smartphones med Mifare Classic support stadig vil melde deres ankomst, for det er næppe sandsynligt at Rejsekort A/S begynder at bruge et format uden kryptering (jeg mener at have set i aktindsigt dokumenterne, at de vil bruge Mifare DESFire i 2015 når Rejsekort version 5 skal rulles ud).

Jeg har ikke haft nogen kontakt med Rejsekort A/S, men hvorfor de ikke selv for længst er kommet med en app kan undre. De har ellers luftet ideen diverse steder, bl.a. her. Jeg kan kun gisne om, at de ikke har synes det var besværet værd. I det mindste kunne de have offentliggjort læse-nøglerne og format-beskrivelse, så andre kunne løse dette problem for dem, uden som jeg, at måtte ty til skrøbelig reverse-engineering.

Skulle man være intereseret i de mere tekniske detaljer bag projektet, kan jeg kun sige... stay tuned. Jeg skal lige overveje fordele/ulemper ved at udlevere for mange detaljer, da jeg ikke som sådan ønsker et udestående med Rejsekort A/S. Men lad mig bare afsløre at det involverede en frygtelig masse kort dumps, nogle special-skrevne analyse værktøj og ikke mindst tekst-markers i så mange forskellige farver som muligt! :)

Thursday, February 20, 2014

VirtualBox: Windows client seeing the Linux host filesystem as a real drive

VirtualBox remains my favorite virtualization solution; it's free, runs everywhere and just does its job real nice - let's hope Oracle doesn't screw this one up as well! Specifically VirtualBox helps me as a developer needing to work in .NET/C#, without having to leave the Linux platform entirely. Let's face it, once you tried the power, freedom and flexibility of a GNU Linux operating system, it is rather hard to go back to the constraints of a Windows box.

VirtualBox shared folder

VirtualBox has a nice feature, where it can expose a folder from the host operating system, as a network share to the client operating system. This has been an approach I have used in the past as well, in order to still have the powerful Linux command-line available along with common utilities like maven, subversion, diff etc. Remember for this to work, you will have to install the Guest Additions in the virtual image.

However, when working on some .NET code using DirectoryCatalog which is part of the Managed Extensibility Framework (now Microsoft Composition), it became apparent that dynamic linking of assemblies poses certain trouble across a network drive on Windows due to security constraints. I find this a little odd, on the Java platform a network drive mount is considered a first class citizen rather than a special network resource (the whole point of mounting would appear to be to forego the network abstraction in the first place no?), so a normal ClassLoader can do the job and there's no need for a URLClassLoader. In any event, after discovering some related issues when loading assemblies dynamically, it became clear that I had to work around the MEF abstractions and that was *not* the point of using it in the first place.

Fooling Windows

So I though that the only way forward was to fool Windows (and the .NET/C# security model) which would allow me to use the MEF as intended. I tried a bunch of tricks incl. the diskpart, mountvol, netdrive and subst command-line tools but nothing worked. However, then I stumbled upon the mlink tool.
First of all, you need to have Windows see and mount your shared folder as a network drive. In my case, I let Windows mount it to the next available drive-letter of E.

Then you use the mklink utility in administrator mode, to mount the E:\ drive into a subdirectory of you NTFS partition. In my case I chose to mount my entire "Development" directory into Windows' generic Document's folder. The only way I figured out how to escalate to administrator mode in Windows, is to right-click on a program, so I used notepad to write the mklink command into a batch-file (mount.bat), saved and then ran it as administrator.

Once the script has run, it will have created a folder (a shortcut actually) for you in "Documents". Once you verified this, you may simple delete the mount.bat file, since you won't have to use it again.

In my case I also created a shortcut to the "Development" folder from the desktop, so now it's easy to navigate the rather complex abstraction-chain shortcut -> soft directory-junction -> network-share -> EXT4 filesystem. Deleting the mount point "Development" only has the effect of deleting the directory-junction, nothing on the actual host EXT4 filesystem is deleted.

I am sure Microsoft thought long and hard over their .NET/C# sandbox and associated security model, but this aspect doesn't strike me as particular bullet-proof. After all, if a hacker is able to mount a network drive, he's probably also able to create a directory-junction!