Handleliste? Sånt har vi systemer for

Med en strekkodeleser, en raspberry pi, noen linjer kode og Microsoft Azure, oppdateres nå husholdningens handleliste på kolonial.no i takt med at vi går tomme for varer.

For noen måneder siden gikk jeg til innkjøp av en raspberry pi, siden jeg noe naivt trodde jeg ville ha tid og lyst til å bygge et Magic Mirror. Den illusjonen brast umiddelbart da jeg innså at det ville innebære én del koding/programvare og 99 deler finsnekring, så rpien ble liggende i en skuff.

Det endret seg dog veldig raskt da jeg kom over en bloggpost fra 2013 om Oscar, et system som automatisk oppdaterer en handleliste på trello ved hjelp av en strekkodescanner og litt koding.

Vår husholdning ble tidlig kunder av de nettbaserte dagligvarebutikkene, så ideen min var å kombinere prinsippet bak Oscar med en eksisterende netthandel. Som tenkt så utført: En strekkodescanner montert på kjøkkenet og noen linjer kode senere, og vi har et system som automatisk oppdaterer vår handlekurv på kolonial.no når vi scanner varer, enten når vi ser vi trenger mer eller når den tomm eemballasjen går i søpla.

Dette ble samtidig en gylden mulighet til å utforske Azure Functions før jeg tar de i bruk i faktiske kundeprosjekter – håpet er å publisere en liten føljetong med bloggposter som belyser de forskjellige kode- og arkitektur-valgene løsningen består av.

Strekkodeleseren

barcode-scanner

Selve strekkodeleseren kjøpte fra en mer eller mindre tilfeldig valgt forhandler på ebay. Det er en USB-variant som kobles til rpien på helt vanlig måte og registreres som en input-enhet:

python-list-devices

Som man ser av skjermbildet over, valgte jeg python som utviklingsspråk på raspberrien. Jeg befinner meg som oftest på microsoft-stacken i mitt daglige virke, så valget var mest for variasjonens skyld og for å bruke python til noe annet enn å si hallo til verden.

Litt rask googling avslørte at evdev var et naturlig valg når det kommer til å lese input fra en enhet, og det tok ikke mange minutter å snekre sammen en liten snutt som leste alle tegn frem til linjeskift og samlet disse til en barcode.

Den første versjonen (altså nåværende, og eneste, versjon), dytter strekkodene til en Azure Storage Queue, også tar en azure function over derifra. Kodenunder faller forøvrig inn i kategorien “kode som virker”, men neppe “dogmatisk og strukturelt korrekt python” – ta det for det det er

Som man ser, gjør kodesnutten ikke mye: Den leser tall frem til “enter”, og sender disse (altså strekkoden) til Azure via azure.storage-pakken. I denne første, rudimentære versjonen brukes en kø som retry-mekanisme.

Scriptet starter ved maskinstart som en cronjobb:

# m h dom mon dow command
@reboot sh /home/pi/launch_barcode_reader.sh > /home/pi/logs/cronlog 2>&1

launch_barcode_reader.sh setter opp pythonmiljøet og starter scriptet.

#!/usr/bin/env bash
cd /home/pi/Devel/barcode_reader/
/home/pi/.virtualenvs/barcode_reader/bin/python reader.py

Neste gang viser jeg hvordan dette håndteres på mottakssiden, men en azure function storage queue trigger (altså en funksjon som eksekveres hver gang noe legges til en spesifikk kø).

Experiences with Paypal Adaptive Payments API

I just finished a small project involving PayPal’s Adaptive Payments API (and the nuget package they supply for it). The points below is stuff I spent too much time on, hopefully this can save someone the trouble.

First of all, I got the error “Your payment can’t be completed. Please return to the participating website and try again.” after completing the payment as a test user in the sandbox. This was solved by creating an application id for the application and including it in the signature credentials I pass to PayPal. I think this happened after I switched to the SignatureCredential implementation. Its constructor does not accept  the Application ID, but the property can be set afterwards.

The second stumbling block was a generic exception (“Input string was not in a correct format.”) when passing the payment info to PayPal. It turns out that the Adaptive Payments package assumes that point is the universal decimal mark – “100.00” is OK, while “100,00”, which is my locale’s preferred way of expressing a hundred, does not compute.