+ All Categories
Home > Engineering > Progettazione e sviluppo di un software applicativo su un single board computer

Progettazione e sviluppo di un software applicativo su un single board computer

Date post: 14-Apr-2017
Category:
Upload: alessandro-mascherin
View: 64 times
Download: 0 times
Share this document with a friend
44
UNIVERSITÀ DEGLI STUDI DI TRIESTE Dipartimento di Ingegneria e Architettura Laurea Triennale in Ingegneria dell’Informazione Progettazione e sviluppo di un software applicativo su single-board computer 2 dicembre 2016 Laureando Relatore Alessandro Mascherin Chiar.mo Prof. Sergio Carrato Correlatore Ing. Piergiorgio Menia Anno Accademico 2016/2017
Transcript
Page 1: Progettazione e sviluppo di un software applicativo su un single board computer

UNIVERSITÀ DEGLI STUDI DITRIESTE

Dipartimento di Ingegneria e Architettura

Laurea Triennale in Ingegneria dell’Informazione

Progettazione e sviluppo di un softwareapplicativo su single-board computer

2 dicembre 2016

Laureando RelatoreAlessandro Mascherin Chiar.mo Prof. Sergio Carrato

CorrelatoreIng. Piergiorgio Menia

Anno Accademico 2016/2017

Page 2: Progettazione e sviluppo di un software applicativo su un single board computer

Indice

Introduzione iiObiettivi della tesi . . . . . . . . . . . . . . . . . . . . . . . . . . . iiiOrganizzazione della tesi . . . . . . . . . . . . . . . . . . . . . . . . iiiStrumenti utilizzati . . . . . . . . . . . . . . . . . . . . . . . . . . . iii

1 Analisi Introduttiva 11.1 Descrizione problema . . . . . . . . . . . . . . . . . . . . . . . 11.2 Scelta dell’ambiente di lavoro . . . . . . . . . . . . . . . . . . 31.3 Descrizione dell’hardware . . . . . . . . . . . . . . . . . . . . 3

1.3.1 Interfaccia e protocollo Wiegand . . . . . . . . . . . . 51.4 Scelta del sistema operativo . . . . . . . . . . . . . . . . . . . 6

2 Impostazione iniziale dispositivo 72.1 Installazione librerie . . . . . . . . . . . . . . . . . . . . . . . 72.2 Configurazioni di rete . . . . . . . . . . . . . . . . . . . . . . 92.3 Partizioni del sistema operativo . . . . . . . . . . . . . . . . . 10

3 Sviluppo Software applicativo 133.1 Descrizione generale . . . . . . . . . . . . . . . . . . . . . . . 133.2 Modulo di stampa . . . . . . . . . . . . . . . . . . . . . . . . 143.3 Modulo di analisi e gestione dell’input . . . . . . . . . . . . . 173.4 Modulo di configurazione . . . . . . . . . . . . . . . . . . . . 18

4 Automatizzazione del dispositivo 214.1 Script per la gestione del software applicativo . . . . . . . . . 214.2 Accesso via FTP e SSH e permessi utente . . . . . . . . . . . 22

Conclusioni 24

A Codice Sorgente 26A.1 PrinterModule.cpp . . . . . . . . . . . . . . . . . . . . . . . . 26A.2 InputParser.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . 30A.3 Configuration.cpp . . . . . . . . . . . . . . . . . . . . . . . . . 33A.4 Utilizzo Tiny Xml . . . . . . . . . . . . . . . . . . . . . . . . 38

i

Page 3: Progettazione e sviluppo di un software applicativo su un single board computer

Introduzione

La seguente tesi descriverà il lavoro svolto presso la Elimos S.r.l per il pro-getto e lo sviluppo di un software applicativo implementato su single-boardcomputer. Il progetto prevede l’installazione di numerose unità distribuitein rete in grado di leggere un Tag RFID, richiedere ad un server centraleconnesso in rete TCP/IP un set di informazioni legate al Tag in oggetto, estampare su stampante termica i dati ricevuti dal centro di controllo. Que-sto sistema deve essere piccolo, inscatolato per ambiente industriale, ed ingrado di essere acceso/spento senza controllo di un operatore. A fronte del-l’analisi dei requisiti e dei target di costo richiesti da un’azienda committenteesterna, si è deciso di utilizzare come unità centrale di elaborazione per ognimodulo un single-board computer (SBC) embedded Raspberry Pi 2 modelB. Il lavoro si è sviluppato in più fasi. Nella prima, ci si è dedicati allascelta dell’ambiente di lavoro, andando a definire la totalità dell’hardwaresu cui si sarebbe andati a lavorare e gli strumenti software a disposizione.Nella seconda fase si è andati a sviluppare un software applicativo in gra-do di soddisfare le richieste del committente. Si è cercato di sviluppare unprogramma il più modulare possibile, per far fronte a diversi casistiche eper garantire longevità al progetto. In fase di sviluppo si è lavorato paral-lelamente sul codice applicativo e sulla parte piu’ sistemistica propria delRaspberry, installando driver e pacchetti, e creando le librerie software ne-cessarie al funzionamento del programma, il tutto per ottenere un sistemaoperativo configurato in maniera opportuna. Nella fase finale del lavoro si èandati a integrare l’applicativo sull’hardware testando completamente tuttala connettività e ricercando delle soluzioni per rendere il dispositivo in gradodi operare in maniera autonoma senza operatore. In questa fase sono anchestati sviluppati dei tool per permettere un accesso remoto alla SBC e special-mente le procedure di aggiornamento e configurazione remota direttamentesul campo.

Nei capitoli seguenti andremo ad esporre le soluzioni sviluppate, descri-vendo le problematiche riscontrate in fase di sviluppo e le scelte effettuateper soddisfare i requisiti di progetto.

ii

Page 4: Progettazione e sviluppo di un software applicativo su un single board computer

INTRODUZIONE

Obiettivi della tesi

L’obiettivo della tesi è quello di descrivere le operazioni da svolgere perutilizzare un single-board computer ARM-based in ambiente non presidiato,a partire dall’impostazione iniziale dell’ambiente di sviluppo per giungereall’implementazione di un programma di una certa complessità sul sistemaoggetto di analisi. Uno dei requisiti cardine sui cui si è sviluppato il progettoè stato quello di ottenere un sistema di semplice utilizzo per l’utente finale,privo di interfacce per l’operatore. Il sistema deve essere interfacciato adun lettore di tessere RFID, ad una stampante termica e deve comunicareattraverso la rete TCP/IP. Si è quindi lavorato per rendere il dispositivo ingrado di lavorare in maniera autonoma, gestendo eventuali configurazioni eaggiornamenti in maniera remota.

Organizzazione della tesi

Nel capitolo 1 verrà effettuata un’analisi dei requisiti richiesti dal committen-te e dei motivi che hanno portato alla scelta del Raspberry Pi come ambientedi lavoro per la realizzazione del progetto. Verranno inoltre discusse alcunepossibili scelte relative ai sistemi operativi utilizzabili. Le varie configurazio-ni del sistema operativo scelte e le principali librerie software installate sonodescritte nel capitolo 2. Nel capitolo 3 viene esposto il software applicativosviluppato, sia nel suo funzionamento generale che negli specifici moduli svi-luppati dal laureando. Il capitolo 4 è dedicato alla descrizione degli strumentiutilizzati per garantire un funzionamento autonomo del Raspberry, fornendonel contempo degli strumenti per l’aggiornamento e la configurazione remotaall’utente. Infine il capitolo 5 è dedicato alle conclusioni sul lavoro svolto,mentre in appendice sono inseriti la bibliografia e parte del codice sorgenteopportunamente commentato.

Strumenti utilizzati

L’hardware su cui si è andati a sviluppare il progetto è stato il RaspberryPi 2 model B, un computer single-board rilasciato sul mercato nel febbraio2015 dalla RaspberryPi Foundation™. Il Raspberry Pi è un computer co-siddetto single-board, in quanto costruito su un’unica scheda circuitale, conprocessore ARM in grado di supportare una vasta gamma di sistemi operativiGNU/Linux. Il software sviluppato è stato scritto in C/C++ 11 sfruttandol’ambiente di sviluppo integrato NetBeans. Sono stati inoltre scritti diversiscript bash e per alcune opzioni di configurazione vengono utilizzati degliscript AWK open-source.

iii

Page 5: Progettazione e sviluppo di un software applicativo su un single board computer

Capitolo 1

Analisi Introduttiva

In questa sezione verranno descritte le specifiche richieste al progetto e lescelte iniziali fatte per l’implementazione del dispositivo.

1.1 Descrizione problema

Le specifiche di progetto prevedevano la realizzazione di un sistema senza in-terfaccia utente in grado di implementare diverse funzionalità che verrannodi seguito esposte. A livello globale il sistema finale si presenta essenzial-mente come un timbratore che deve fornire a ogni operatore un ruolino diservizio con le attività prevista per la giornata lavorativa. Il dispositivo fina-le necessita di una connessione con un server centrale, installato in sede delcommittente, che contiene i dati relativi agli operatori e alle attività previste.Per quanto riguarda la connettività, il dispositivo finale deve quindi potersicollegare alla rete Internet tramite protocollo TCP/IP, attraverso la tecno-logia Ehternet. La comunicazione con il server centrale avviene attraversoun web-service. Altro aspetto fondamentale dei requisiti è la gestione delsistema di input/output. Per poter stampare il ruolino di servizio, il dispo-sitivo deve poter comunicare con una stampante termica collegabile tramitel’interfaccia USB, il cui modello è stato stabilito dal committente. Il sistemadeve gestire un processo di analisi dei pin in input ricevendo dei dati da unlettore di tessere magnetiche, collegato ai GPIO del Raspberry. Questo letto-re utilizza l’interfaccia Wiegand per la trasmissione dei dati e deve pertantoessere opportunamente collegato al dispositivo su cui si andrà a sviluppare ilprogetto. Tramite lo stesso lettore è necessario fornire all’utente un feedbacksonoro e visivo delle operazioni che vengono svolte; il feedback viene invia-to grazie al led e al buzzer presenti sul lettore di tessere. Questo sistemadeve analizzare la sequenza di bit che riceve dal lettore di tessere e, in se-guito ad un’opportuna elaborazione, inviare una richiesta al server centralecon i dati elaborati. Per comunicare con il server è stato necessario quindiimplementare un client web-service sul dispositivo, per poter effettuare una

1

Page 6: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 1. ANALISI INTRODUTTIVA

convalida dei dati elaborati dal badge e ricevere delle opportune risposte dalserver. L’utilizzo dei web service è lo standard de facto per la comunica-zione attraverso il Web di diversi dispositivi e diverse applicazioni software.Secondo la definizione fornita dal W3C, il World Wide Web Consortium, leweb service sono la tecnologia standard per poter mettere in comunicazionediversi applicazioni software installate su una grande varietà di piattaformee framework. Nel caso in analisi lo sviluppo di una web service permette dipoter ottenere una facile comunicazione con il server centrale, senza doversipreoccupare della compatibilità fra diverse piattaforme e sistemi operativi.

Sono previste diverse tipologie di risposta da parte del web server, eil sistema deve adottare un opportuno comportamento per ogni possibilerisposta:

• Codice di errore in caso di tessera sconosciuta

• Codice di errore differente nel caso di tessera conosciuta, ma rispo-sta di errore da parte del web server (data/ora non valida, mancatatimbratura, o altro)

• In caso di risposta positiva da parte del web server è necessaria un’e-laborazione dei dati ricevuti e la preparazione di un modulo di stampada inviare alla stampante termica collegata al sistema.

Durante l’elaborazione dei dati per la stampa o in presenza di un codicedi errore, deve essere previsto uno specifico feedback per l’utente tramite illed e il sistema sonoro implementato nel lettore di tessere. In assenza di erro-ri, i dati ricevuti devono venire stampati in dei ruolini di servizio con diversiformati; è necessario quindi sviluppare un programma in grado di distinguerele varie casistiche e di creare dei layout di stampa adeguati, in modo tale dafornire ad ogni diverso operatore il suo specifico ruolino di servizio. Il tutto,dovendo operare senza interfaccia utente, deve inoltre disporre di un sistemaper l’aggiornamento e la configurazione in modo remoto, senza la necessitàdi accedere fisicamente ai dispositivi finali. Per queste procedure è statodeciso di utilizzare i protocolli FTP e SSH per accedere al sistema. L’ag-giornamento e la configurazione devono avvenire stabilendo una connessionead un indirizzo IP specifico, che deve essere attivo per un certo intervallotemporale dopo il quale il sistema si deve connettere a un indirizzo IP diservizio. Un ulteriore requisito è la robustezza sia del software applicativo,sia del dispositivo in caso di malfunzionamenti. In particolare, non essen-doci interfaccia utente, bisogna prevenire errori di memoria in seguito allospegnimento della scheda o in caso di problemi legati all’alimentazione.

2

Page 7: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 1. ANALISI INTRODUTTIVA

1.2 Scelta dell’ambiente di lavoro

La prima decisione è stata quella di non utilizzare dei semplici microcontrol-lori, in quanto non in grado di rispettare le specifiche fornite in modo sem-plice ed economico. Per poter soddisfare in modo efficace i requisiti impostidal committente è necessario avere a disposizione un dispositivo che deveoffrire le funzionalità di un personal computer, mantenendo nel contempodelle dimensioni contenute. Si è scelto quindi di sfruttare una single-boardcomputer embedded, dispositivi molto compatti e dal costo contenuto, ingrado di fornire prestazioni comunque elevate. Sono dei computer completiche vengono installati su una singola scheda elettronica. Questi single-boardcomputer hanno avuto un’ampia diffusione negli ultimi anni per utilizzi edu-cazionali o come controllori embedded. Pur non potendo competere con lapotenza di calcolo di un personal computer di fascia alta, hanno come van-taggio le dimensioni estremamente contenute, un basso consumo e un costonotevolmente inferiore. L’hardware preso in considerazione consisteva nelRaspberry Pi 2 model B e nell’Odroid-C1plus. Sono schede molto simili incaratteristiche e prestazioni, e sono quasi equivalenti quando utilizzati per larealizzazione di questo tipo di progetti. Entrambi i prodotti sono basati suprocessori ARM, hanno dimensioni comparabili e sono dotati delle interfacceI/O richieste. L’Odroid è superiore al Raspberry in termini di caratteristi-che hardware, mentre è leggermente inferiore in termini di supporto tecnicoe di reperibilità dei dispositivi. Essendo il costo dei due prodotti essenzial-mente identico e non essendo necessarie particolari prestazioni hardware perl’implementazione delle richieste del committente, si è deciso di iniziare losviluppo sul Raspberry Pi, data la facile reperibilità del prodotto e il maggiorsupporto tecnico presente in rete.

1.3 Descrizione dell’hardware

Figura 1.1: Foto del chip BCM2836

3

Page 8: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 1. ANALISI INTRODUTTIVA

Il Raspberry Pi 2 model B è basato su un processore quad-core ARMCortex-A7 da 900MHz costruito dalla Broadcom™. In particolare il chip uti-lizzato è il BCM2836, che va a sostituire il precedente BCM2835, installatosulle versioni precedenti del RaspberryPi.

Questo modello di Raspberry dispone inoltre di 1 GB di memoria RAM, edi una GPU, prodotta anch’essa dalla Broadcom™, da 250 MHz con OpenGLES 2.0 OpenVG 1080p30 H.264. Per quanto riguarda la connettività lascheda dispone di 4 porte USB 2.0, utilizzando il Microchip™ LAN9514, unaporta Ethernet, una porta HDMI e un jack audio da 3,5 mm che comprendeanche il video composito utilizzabile con un adattatore a 4 poli. Per lamemorizzazione dei dati è necessario l’utilizzo di una scheda SD, collegabile alRaspberry tramite un apposito slot. Le periferiche di basso livello installatesulla scheda consistono in un modulo GPIO da 40 pin, di un Serial PeripheralInterface Bus (SPI), di pins per le comunicazioni I2C e I2S, e un Universalasynchronous receiver/transmitter (UART). La scheda per il funzionamentorichiede 5V in DC, che possono essere forniti tramite una porta Micro USBdi tipo B.

La suddivisione dei pin dell’interfaccia GPIO è illustrata nell’immagine1.2:

Figura 1.2: Schema GPIO

I pins 2 e 4 sono pin utilizzati per alimentare dispositivi collegati all’in-terfaccia a una tensione di 5V e con una corrente che può arrivare a 1,5A. Ipin da 5V possono essere anche utilizzati per alimentare il Raspberry stesso,prestando attenzioni ad eventuali picchi di tensione che potrebbero danneg-giare i pins del bus GPIO. In modo analogo i pin 1 e 17 forniscono unatensione di 3.3V ma con una limitazione alla corrente fornita. Esistono poidei pin deputati a specifici metodi di input/output. Ad esempio i pins 3, 5,27 e 28 vengono utilizzati per il sistema di comunicazione I2C mentre i pin 8e 10 vengono utilizzati per le comunicazioni UART (Universal AsynchronousReceiver/Transmitter).

4

Page 9: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 1. ANALISI INTRODUTTIVA

L’immagine 1.3 raffigura il mechanical drawing del modello di Raspberryutilizzato. Il drawing che viene presentato è quello del Raspberry Pi ModelB+, ma risulta valido anche per il Raspberry Pi 2 Model B. Le misure sonoespresse in mm.

Figura 1.3: Mechanical Drawing

1.3.1 Interfaccia e protocollo Wiegand

Un’altra componente hardware fondamentale del sistema oggetto di analisiè costituita dal lettore di tessere magnetiche. Questo lettore utilizza un in-terfaccia Wiegand per la trasmissione dei dati al Raspberry. L’interfacciaWiegand è costituita da 3 linee che devono essere collegate al bus GPIOdel Raspberry. Una linea costituisce la massa e le altre due linee vengonoutilizzate per la trasmissione dei dati e di solito vengono chiamate DATA0 eDATA1. In assenza di dati da trasmettere le due linee vengono mantenutead un livello di tensione “alto” che generalmente consiste in 5 V in DC. Nelcaso in cui viene trasmesso un bit di valore 0, la tensione della linea DATA0viene abbassata per una specifica durata temporale. Viceversa, nel caso incui viene trasmesso un bit con valore 1 è la tensione della linea DATA1 adessere abbassata, mentre DATA0 rimarrà su un valore di tensione alto. Letempistiche di questi segnali sono tipicamente 50-100 µs per gli impulsi in-tervallati da 2ms, ma non sono assolutamente stringenti e possono variareanche in percentuali significative. Questi bit vengono inviati secondo il for-

5

Page 10: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 1. ANALISI INTRODUTTIVA

mato stabilito dal protocollo Wiegand standard da 26 bit. Questo formatoconsiste in uno stream di 26 bit che sono così suddivisi:

Figura 1.4: Protocollo Wiegand

Il bit di testa e di coda dello stream vengono utilizzati come controlloridi parità. In particolare il primo bit è settato in modo tale che il numero di“1” nei primi 13 bit dello stream sia pari, mentre l’ultimo viene impostatoper far sì che il numero di “1” negli ultimi 13 bit dello stream sia dispari.Il facility code contiene le informazioni relative al modello e al produttoredella scheda. L’user code, chiamato anche ID code, come viene suggerito dalnome, codifica un valore identificativo della singola tessera. Per l’analisi diquesti bit è stato sviluppato un modulo software che si occupa di eseguireil controllo di parità della sequenza trasmessa e di separare il facility code el’ID code.

1.4 Scelta del sistema operativo

Sui single-board computer ARM-based è possibile installare una gran varie-tà di sistemi operativi, generalmente linux-based. Nel caso del Raspberry isistemi operativi supportati ufficialmente sono Rasbian e Noobs, maggior-mente adatti per un utilizzo di tipo didattico o dimostrativo della scheda.Esistono tuttavia alcuni sistemi operativi che non sono sviluppati dalla Ra-spberryPi Foundation™ ma che sono comunque ottimizzati per il Raspberry,quali Ubuntu Mate, Windows 10 IOT, Snappy Ubuntu e altri. Si è decisodi installare una versione di Ubuntu Mate, in quanto più adatta alle speci-fiche di progetto rispetto ai sistemi sopra menzionati. Un’altra alternativapresa inizialmente in considerazione è stata quella di installare un sistemaAndroid; l’ipotesi è stata scartata durante la prima fase di analisi in quantoil sistema non è ufficialmente supportato e risulta spesso instabile sul mo-dello di hardware scelto. L’implementazione di Android sarebbe stata unavalida scelta utilizzando l’Odroid, che supporta nativamente questo sistemaoperativo.

6

Page 11: Progettazione e sviluppo di un software applicativo su un single board computer

Capitolo 2

Impostazione inizialedispositivo

In questa sezione verrà descritto il lavoro svolto per l’impostazione generaledella scheda a livello software e le soluzioni adottate per rendere il sistemarobusto in seguito a eventi non previsti dalle specifiche, quali l’interruzioneimprovvisa dell’alimentazione o la rimozione della scheda di memoria. Ver-ranno introdotte e analizzate le librerie software installate, le configurazionidi rete adottate e un’importante modifica al sistema operativo, ovvero lacreazione di differenti partizioni di sistema configurate in modo differenteper risolvere diverse situazioni impreviste che potrebbero insorgere durantel’utilizzo del dispositivo.

2.1 Installazione librerie

Nel corso del processo di sviluppo del software applicativo è stato necessarioinstallare diverse librerie software disponibili in Internet. In ambiente linuxsono disponibili un ampio numero di librerie, la maggior parte delle qualigratis e open-source. L’installazione, l’aggiornamento e la rimozione di li-brerie e pacchetti software è gestita di default da APT (Advanced PackagingTool), software che mette a disposizione vari comandi che facilitano questeoperazioni, come apt-get. Tutte le librerie analizzate in seguito sono stateinstallate utilizzando il comando apt-get. Le principali librerie che sono sta-te installate e configurate per lo sviluppo del software applicativo sono leseguenti:

• le librerie grafiche Pango e Cairographics utilizzate per la creazione delmodulo di stampa

• la libreria CUPS per la gestione della stampante termica

• la libreria libconfig++, utilizzata per il modulo di configurazione

7

Page 12: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 2. IMPOSTAZIONE INIZIALE DISPOSITIVO

• ntpdate per l’aggiornamento di data e ora

• TinyXML

Cairographics è una libreria grafica 2D che viene utilizzata per la rea-lizzazione di grafica vettoriale in modo consistente su diversi dispositivi esistemi operativi. E’ una libreria open-source sviluppata in linguaggio C,che offre numerosi bindings per altri linguaggi di programmazione. Pango èuna libreria che viene utilizzata per la gestione del layout e del rendering dicontenuto di tipo testuale. E’ integrata nativamente con Cairo ed è infattiraccomandata dalla documentazione di Cairographics per la gestione di testi.

CUPS è un sistema di stampa open source sviluppato da Apple per siste-mi UNIX-like e macOS. Generalmente CUPS è installato di default in tuttii sistemi Ubuntu, ma per operazioni di controllo più avanzate è necessarioinstallare la versione per sviluppatori della libreria. L’utilizzo di CUPS ci hapermesso di controllare la stampante termica con il programma sviluppatoin C++ e di poter avere un maggior controllo delle opzioni di stampa, qualile dimensioni della superficie di stampa o la gestione del taglio dei fogli.

Libconfig è una libreria per la gestione di file di configurazione strutturati.La libreria è scritta in C++, e prevede l’uso di file di configurazione scritti inun formato più semplice e leggibile dell’XML. E’ stata scelta questa libreria,tra le molte disponibili, per la semplicità nell’utilizzo e per la consolidatacompatibilità con i sistemi Unix.

Ntp è un protocollo basato su TCP/IP per l’aggiornamento dell’ora di uncomputer, il cui funzionamento è basato sulla comunicazione fra un client,in esecuzione sulla macchina di cui si vuole aggiornare l’ora, e dei serverche forniscono l’ora corrente. Ubuntu dispone di due diversi strumenti perutilizzare ntp, chiamati ntpdate e ntpd. Nel sistema oggetto di analisi si èdeciso di installare ntpdate, strumento che contatta i server ntp ad ogni avviodel sistema operativo per aggiornare l’ora del sistema. Questo strumentoinoltre richiede meno utilizzo di risorse rispetto a ntpd.

Tinyxml è un analizzatore di testo XML sviluppato in C++. Questalibreria fa dei suoi punti di forza la semplicità di utilizzo e un basso utilizzodi risorse di sistema per il suo funzionamento. E’ inoltre disponibile gra-tuitamente ed è open-source, caratteristiche che hanno quindi portato allascelta di questa libreria rispetto ad altre disponibili sul mercato.

8

Page 13: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 2. IMPOSTAZIONE INIZIALE DISPOSITIVO

2.2 Configurazioni di rete

Di default il Raspberry adotta il protocollo DHCP per ottenere accesso allarete IP al quale è stato connesso. Nel caso in esame è sorta la necessitàdi installare diversi dispositivi sulla stessa network, rimanendo in grado diindividuare in modo univoco tramite l’indirizzo IP ogni scheda in quelladata network. Questa identificazione univoca è necessaria solo per potereffettuare aggiornamenti e controlli mirati al singolo computer. E’ statoquindi deciso di impostare due diversi tipi di configurazione, i cui parametriverranno gestiti dal programma in esecuzione sulla macchina. Si è andati acreare due distinte interfacce di rete, una configurata in maniera statica e unaseconda configurata in maniera dinamica tramite DHCP. Per implementarequeste interfacce è stato necessario modificare il file /etc/network/interfacescontenente i parametri di accesso e configurazione ethernet. In questo file,di default è presente l’interfaccia di loopback, ovverosia il localhost. Inoltre,in presenza di un accesso ethernet il sistema operativo aggiunge in manieraautonoma un’interfaccia ethernet configurata tramite DHCP. Nel caso inanalisi il file si presentava inizialmente così:

auto loauto MAC-Addressiface lo inet loopbackiface MAC-Address inet dhcp

Nei dispositivi in uso il sistema operativo denomina di default l’interfacciaethernet con l’indirizzo MAC della stessa (denominato MAC-Address nel fileprecedente). E’ stato necessario utilizzare il seguente script, scritto in bash,per modificare in modo permanente questa impostazione:

#!/bin/bashmymac="$(ifconfig | grep ’HWaddr’ | cut -d\ -f11)"file="/etc/udev/rules.d/70-persistent-net.rules"echo $mymacif [ -f $file ]thenecho "$file Found"elseecho "$file Not Found"echo ’SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*",

ATTR{address}=="’$mymac’", ATTR{dev_id}=="0x0",ATTR{type}=="1", KERNEL=="eth*", NAME="eth0" ’>> $file

fi

Lo script va ad inserire una nuova regola di sistema nella quale si impostail nome dell’interfaccia ethernet con eth0. Questa operazione è stata resanecessaria per avere un software uniforme e semplice su tutti i dispositiviche si andranno a configurare.

9

Page 14: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 2. IMPOSTAZIONE INIZIALE DISPOSITIVO

Effettuata questa modifica, si è proceduto a modificare il file /etc/networ-k/interfaces. L’interfaccia di loopback non è stata modificata, mentre sonostate distinte due diverse interfacce ethernet, chiamate eth0-conf e eth0-work,la prima destinata a essere configurata tramite indirizzo statico, la secondatramite DHCP. L’interfaccia eth0-conf è stata configurata con un indirizzoIP statico, appartenente alla network privata nella quale è installato il Rasp-berry. L’interfaccia eth0-work è stata impostata in modalità DHCP. Questedue interfacce sono modificabili dal software applicativo secondo necessità,basandosi su un opportuno file di configurazione. E’ stato inoltre imposta-to che all’avvio la scheda non deve connettersi con nessuna interfaccia, inquanto sarà uno specifico script bash che si occuperà di attivare la connes-sione di configurazione (eth0-conf), mentre il software applicativo effettueràil cambio di interfaccia portandosi sull’interfaccia eth0-work.

Il file /etc/network/interfaces modificato si presenta quindi così:

auto loiface lo inet loopbackiface eth0-work inet dhcpiface eth0-conf inet static

address some-IPnetwork some-networknumbergateway some-gatewayIP

I parametri di rete quali l’indirizzo IP, il network number e l’indirizzo digateway vengono specificati nel file di configurazione.

2.3 Partizioni del sistema operativo

Uno dei principali requisiti di lavoro consiste nell’ottenere un sistema in gra-do di operare senza interfaccia utente. Nel caso del sistema operativo presoin considerazione è stato riscontrato un bug che al momento della realizza-zione del progetto non era ancora diventato oggetto di analisi per il team disviluppo di Ubuntu Mate. In seguito il problema non è stato riconosciutocome valido in quanto le build del sistema operativo in cui si verifica questoproblema non sono state considerate come ufficiali. Il problema consiste nelfatto che, in caso di spegnimento del dispositivo in seguito all’interruzionedell’alimentazione, al reboot il sistema operativo entrerà sempre in una mo-dalità di emergenza, richiedendo un controllo ai file di sistema. Per uscire daquesta modalità di emergenza è necessario inserire manualmente le creden-ziali di amministratore e riavviare nuovamente il sistema operativo. Tuttaviaquesta modalità blocca il boot del sistema operativo e impedisce l’esecuzionedi qualsiasi altro processo che si vuole eseguire, andando pertanto a creareun incongruenza con le specifiche di progetto. Questo sistema di emergenzaè stato implementato per verificare l’integrità del sistema in caso di spegni-

10

Page 15: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 2. IMPOSTAZIONE INIZIALE DISPOSITIVO

menti considerati anomali dal sistema operativo, andando però a inficiare ilfunzionamento automatizzato del Raspberry.

Per risolvere questo problema si è deciso quindi di configurare il sistemain modo tale da prevenire errori in caso di spegnimento anomalo, evitandol’insorgere del problema descritto.

La soluzione adottata è stata quella di impostare una parte del sistemaoperativo in modalità read-only, per prevenire errori in fase di scrittura nelfile-system. Non è stato possibile impostare l’intero sistema operativo inmodalità di sola lettura in quanto il software necessario per il funzionamentodella stampante ha necessità di creare dei file temporanei in diverse sezionidel sistema operativo. Si è optato quindi per una configurazione in cui solola directory contenente i file necessari all’avvio del sistema operativo è im-postata in modalità di sola lettura, in modo tale da prevenire il problemadella modalità di emergenza descritto in precedenza.

La tabella di configurazione dei file system è un file che contiene i datirelativi alle partizioni di sistema e alle sue proprietà, ed è nota come fstab esi trova all’interno della directory etc. La tabella è stata così impostata:

file system mount-point type options dump pass

proc /proc proc defaults 0 0tmpfs /tmp tmpfs nodev, nosuid, 0 0

size=100 M, mode=1777/dev/mmcblk0p2 / ext4 defaults,noatime 0 2/dev/mmcblk0p1 /boot vfat defaults,ro 0 2

E’ stata allocata una partizione sulla RAM del dispositivo, in cui vengonodestinati i processi di creazione di file temporanei generati dal software appli-cativo. In questa partizione verranno creati tutti i file temporanei necessariper il funzionamento del software applicativo che si è andati a sviluppare.Grazie a questa partizione, nel caso in cui avvenga una rimozione imprevistadella scheda di memoria si previene la possibilità di andare a corrompere deifile essenziali per il funzionamento del software applicativo. L’unico impre-visto che può arrecare danni al sistema è l’interruzione dell’alimentazione ola rimozione della memoria durante le operazioni di aggiornamento software,eventualità che non può essere risolta sfruttando particolari partizioni dellamemoria. Questa problematica può essere però risolta utilizzando altri ac-corgimenti software, come ad esempio l’utilizzo di backup esterni e copie delprogramma principale in altre sezioni della scheda di memoria. La scheda SDè stata quindi divisa in due partizioni, la prima in formato ext4 che contienela maggior parte del sistema operativo e una partizione in formato vfat incui è stata allocata la sezione /boot. Per la partizione /dev/mmcblk0p2 èstata impostata l’opzione noatime per limitare le operazioni di scrittura sulla

11

Page 16: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 2. IMPOSTAZIONE INIZIALE DISPOSITIVO

scheda di memoria. Linux generalmente associa ad ogni file degli attributiin cui vengono memorizzati le date di creazione del file, di ultimo accessoal file e di ultima modifica. Senza l’opzione noatime questi attributi ven-gono aggiornati per ogni accesso ad uno specifico file. Impostando noatimein una partizione quando il sistema operativo legge un determinato file disistema non aggiorna più gli attributi dello stesso, limitando notevolmentele operazioni di scrittura, migliorando le performance del sistema operati-vo e riducendo la possibilità di incorrere in errori in fase di scrittura. Lapartizione /dev/mmcblk0p1 è stata impostata in modalità di sola letturaper ovviare al bug descritto all’inizio di questa sezione e per evitare erroriin scrittura nella partizione. In questo modo tutto ciò che è necessario perl’avvio del sistema operativo viene protetto dalla corruzione dei dati in casodi interruzione dell’alimentazione.

12

Page 17: Progettazione e sviluppo di un software applicativo su un single board computer

Capitolo 3

Sviluppo Software applicativo

Tutti i moduli software descritti in questa sezione sono stati sviluppati dallaureando. Il programma è stato scritto in C++.

3.1 Descrizione generale

Lo schema generale del sistema sviluppato è così composto:

Il Raspberry è collegato ad un lettore di schede magnetiche, a un led e aun piezo monotonale tramite l’interfaccia GPIO. E’ inoltre collegato ad unastampante termica tramite USB e a internet tramite ethernet. Il softwaresi occupa di gestire tutte le periferiche collegate al Raspberry, eseguendo leopportune elaborazioni richieste dal committente. Il software è stato svilup-pato in maniera modulare e i vari moduli software vengono attivati in caso dinecessità. Il sistema si avvia quando si rileva un input dal lettore di tesseremagnetiche. E’ presente quindi un modulo che esegue un loop in lettura dei

13

Page 18: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 3. SVILUPPO SOFTWARE APPLICATIVO

dati provenienti dal lettore di schede connesso all’interfaccia GPIO. Quandoavviene la ricezione dei dati verrà attivato un modulo per fornire un feedbackaudiovisivo all’utente che ha utilizzato il badge magnetico, e un secondo mo-dulo che si occupa di codificare i dati ricevuti per renderli compatibili conquelli attesi dal WebServer. Dal WebServer il sistema si attende tre possibilirisposte: scheda valida e dei dati, scheda non valida e scheda non riconosciu-ta. Per ogni risposta è previsto un differente feedback audiovisivo. L’analisidei dati ricevuti viene svolta dai moduli descritti nella sezione 3.3, modulidedicati alla codifica e all’interpretazione dei dati. In caso di scheda valida, idati ricevuti e codificati vengono ulteriormente elaborati per essere inviati instampa alla stampante termica. Il modulo software che si occupa di questaoperazione è descritto nella sezione 3.2. Il modulo di stampa fornisce deifeedback sullo stato della stampa e sulla presenza di eventuali errori nei datial modulo che lo ha attivato; quest’ultimo modulo segnalerà all’utente inmodo opportuno tramite l’interfaccia GPIO i feedback ricevuti.

All’avvio inoltre il software attiva un modulo dedicato alla configurazionedel sistema e all’aggiornamento dello stesso nel caso in cui siano presentinuove opzioni di configurazione.

3.2 Modulo di stampa

La stampa viene gestita da un modulo sviluppato in C++ chiamato Prin-terModule.cpp. Questo modulo fa uso delle librerie Cairographics, Pangoe Cups descritte nella sezione 2.1. Pango e Cairo vengono utilizzate pergenerare un file in formato PostScript che viene poi inviato alla stampantetermica tramite la libreria Cups. Le stampe generate hanno un layout similea quello presentato nella seguente immagine:

Figura 3.1: Esempio di layout di stampa desiderato

Lo scopo di questo modulo software è quelli di posizionare le varie strin-ghe desiderate sul foglio, secondo uno specifico layout. Sono state previste le

14

Page 19: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 3. SVILUPPO SOFTWARE APPLICATIVO

seguenti tipologie di stampa per soddisfare i requisiti forniti dal committente:

• Una stampa effettuata all’avvio del sistema, per segnalare all’operatoreche il programma è pronto per l’utilizzo; in questo messaggio si è decisodi inserire dati relativi alla versione del software e all’indirizzo di retedi lavoro al quale è stato configurato il sistema

• A seconda dei dati ricevuti dal webserver è prevista una stampa deno-minata “responsabile” e una seconda stampa chiamata “operatore”

Le stampe operatore e responsabile hanno layout e dati differenti, pertantosono gestiti da due metodi differenti.

Per generare un file PostScript con Cairo è necessario creare un oggettodenominato surface che funge da struttura di base del file finale. Questasurface è inizializzata specificando la tipologia di file che si vuole andare acreare, in questo caso PostScript. Le dimensioni del file PostScript sonoespresse in punti tipografici. Questa unità di misura può essere convertitautilizzando la seguente relazione: 1 punto tipografico = 1/72 inch = 0,35278mm = 0,75 pixel. Questa equivalenza è importante in quanto Cairo for-nisce le dimensioni del file generato in pixel o in punti tipografici, mentreCUPS ha bisogno di un valore espresso in millimetri per un corretto tagliodella stampa. Ottenuta la superficie di lavoro il programma genera un og-getto chiamato context su cui vengono effettuate le operazioni di disegno escrittura. Cairo fornisce un API per la gestione testuale che però presentadiverse limitazioni e di cui è sconsigliato l’uso se non per prove o demo. Peril progetto in analisi, se si fosse deciso di utilizzare Cairo anche per l’inse-rimento del testo il codice sarebbe risultato molto più complesso in quantola gestione di diverse tipologie di font e il posizionamento del testo in mododinamico non sono ben gestiti dalle funzioni fornite dall’API. L’inserimentodel testo viene eseguito utilizzando la libreria Pango. Con questa libreriaè possibile definire agevolmente diversi font di scrittura, che possono venireutilizzati per una preparazione più personalizzata della stampa. Per ognifont desiderato si inizializza una struttura chiamata PangoFontDescriptionin cui vengono specificati tramite diverse funzioni il colore, la dimensione, lafamiglia del font e altre opzioni. Il testo viene posizionato sulla superficie dilavoro tramite coordinate cartesiane, la cui unità di misura è il punto tipo-grafico e la cui origine è nell’angolo superiore sinistro della pagina. Pangopermette inoltre di definire vari parametri per il layout, quali le coordinatedi inserimento del testo, fornite da Cairo, l’interlinea tra le righe, la larghez-za massima del testo e il “text wrapping”, ovvero le opzioni di gestione deltesto se questo supera una cella di dimensioni prefissate. Quando si procedeall’inserimento del testo si specifica il layout scelto e il descrittore del fontche si vuole utilizzare.

Uno dei problemi sorti durante lo sviluppo di questo modulo è stato ilcalcolo delle dimensioni della stampa finale, in particolare della lunghezza

15

Page 20: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 3. SVILUPPO SOFTWARE APPLICATIVO

del file PostScript, parametro essenziale per il funzionamento corretto dellastampante. Il problema sorge in quanto in alcune tipologie di stampa previsteè variabile sia il numero di parametri che la lunghezza delle stringhe fornite.Non è quindi possibile calcolare a priori la lunghezza finale del foglio ed èstato necessario ricorrere a due cicli di impaginazione, il primo per il calcolodella dimensione finale, e il secondo per la creazione del file PostScript finale.

Un’altra funziona importante implementata in questo modulo è quelladedicata alla gestione della stampante termica tramite il sistema di stampaCUPS. Questa funzione non si occupa solamente di inviare alla stampanteil file PostScript creato, ma deve anche rilevare eventuali malfunzionamentinella stampante per poterli segnalare all’utente tramite una specifica codificaaudio-visiva. Il programma per prima cosa crea una opzione di stampa per-sonalizzata inizializzando l’oggetto cups_option_t. In questo oggetto vieneinserita la lunghezza del foglio che verrà stampato, determinata dalla funzio-ne che crea il file PostScript, e la larghezza, che ha un valore predefinito. Inseguito la funzione invia un comando per svuotare la coda di stampa, questoper evitare che in caso di errori e mancata stampa di una qualche chiamataprecedente della funzione non si accumulino troppe stampe in coda. Questopotrebbe risultare problematico ad esempio nel momento in cui la carta oil toner risultassero esauriti, poiché al ripristino della stampante potrebberoesserci troppe stampe in attesa ed eventualmente multiple se l’utente ha pas-sato il badge più volte sul lettore. Gli errori di stampa vengono rilevati daun loop che verifica che, per ogni stampa che è stata inserita nella coda, lostato inviato come feedback dalla stampante sia “printing”. Nel caso in cui lestampe in coda rimangono in uno stato di “pending” o di altro errore è neces-sario segnalare all’utente il malfunzionamento della stampante. La funzioneterminerà quindi inviando un valore false (EXIT_FAILURE) al metodoche l’ha invocata, che si occuperà quindi di segnalare il malfunzionamentotramite il led e un segnale sonoro.

16

Page 21: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 3. SVILUPPO SOFTWARE APPLICATIVO

3.3 Modulo di analisi e gestione dell’input

In questa sezione verranno descritti i procedimenti eseguiti per l’analisi e lagestione dei dati ricevuti dal WebServer in seguito alla lettura di un badgetramite il lettore di tessere magnetiche. Il software applicativo contatta ilWebServer ad un URL specificato nei parametri di configurazione, che ver-ranno descritti in seguito, inviando il codice della tessera magnetica e ladata. Il WebServer invia una risposta in un formato testuale, la cui sintassiè molto simile a quella del linguaggio marcatore XML. Infatti, a causa diun’errata configurazione del WebServer, alcuni caratteri vengono codificaticon una sintassi non corretta; ad esempio i tag ’<’ e ’>’ vengono letti dalweb-service client come ’&lt’ e ’&gt’. La prima operazione che viene esegui-ta dal client è pertanto quella di convertire questa risposta in XML “puro”,in modo tale da poter esplorare agevolmente i dati ricevuti. Effettuata laconversione viene chiamata una funzione che ha il compito di eseguire unparsing del testo XML per salvarlo in un vettore di stringhe. Il parsingviene effettuando utilizzando la libreria TinyXML introdotta in preceden-za (sezione 2.1). TinyXML a partire dal documento XML costruisce unDocument Object Model (o DOM), ovverosia struttura il documento comeoggetti C++ che possono essere esplorati e manipolati. Le varie sezioni deldocumento XML vengono quindi modificate a seconda del loro significato; adesempio un commento, espresso in XML nella forma <!–Comment–>, diven-ta un oggetto denominato TiXmlComment. Nell’analisi che si vuole andaread effettuare gli elementi rilevanti sono i tag, elaborati come TiXmlElement,e il testo contenuto nelle varie sezioni, che diventa un oggetto TiXmlText.L’algoritmo utilizza questi oggetti per analizzare il documento, inserendo inun vettore di stringhe i vari elementi testuali che vengono incontrati duran-te l’esplorazione dell’albero del DOM. L’algoritmo termina quando tutti gliTiXmlElement sono stati analizzati e restituisce il vettore di stringhe al me-todo invocante. Ogni stringa che viene inserita nel vettore contiene i datirelativi per una singola stampa che si vuole andare a ottenere. I singoli va-lori testuali che devono essere inseriti nel foglio che si vuole ottenere sonoinseriti con un ordine prestabilito e separati da un carattere con la funzionedi delimitatore. Queste stringhe devono essere quindi ulteriormente analiz-zate per venire scomposte in vari “tokens” che potranno essere utilizzati dalmodulo di stampa. Questa operazione viene gestita da un modulo softwaredenominato InputParser. Il modulo inizialmente esplora la stringa fornitagliin input andando a cercare al suo interno il carattere fornito come delimita-tore, separando la stringa principale in sottostringhe in corrispondenza deidelimitatori. La seconda operazione consiste nel riconoscimento della tipo-logia di stampa, indicata dalla prima sottostringa. Sono previsti due casidi stampa e per ogni tipologia viene effettuata un’ulteriore elaborazione deitokens. In un caso, denominato “operatore”, è previsto un numero di para-metri stabilito a priori, pertanto l’algoritmo verifica se il numero di stringhe

17

Page 22: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 3. SVILUPPO SOFTWARE APPLICATIVO

è corretto, producendo una segnalazione di errore per il metodo invocantenel caso in cui il controllo non venga superato. Fra le stringhe oggetto dianalisi è presente una stringa che ha il valore di una data che, da specifi-che, deve essere convertita dal formato “dd/mm/yyyy” (giorni, mesi e annoespressi in formato numerico) nel formato “dayname dd/monthname/yyyy”dove dayname è il nome esteso in italiano del giorno, e monthname il no-me esteso del mese considerato. La conversione viene effettuata sfruttandole funzioni strptime e strftime di linux. Strptime converte una stringa cherappresenta un’indicazione temporale in una struttura di tipo tm. Questastruttura è definita nell’header time.h presente nella libreria standard di C.Al suo interno vengono inseriti tutti i dati relativi alle informazioni temporalicontenute nella stringa che viene fornita a strptime. La struttura tm vienepoi riconvertita in stringa sfruttando la funzione strftime secondo i parametridi formattazione desiderati.

Nel secondo caso, denominato “responsabile” i dati contenuti nei tokensdevono essere ulteriormente suddivisi in quanto prevedono a loro volta deidelimitatori. Per ogni token viene quindi applicato l’algoritmo utilizzatoinizialmente per suddividere la stringa di input nei vari tokens.

3.4 Modulo di configurazione

La libreria libconfig++ permette di creare file di configurazione molto ver-satili e in grado di fornire diversi dati al sistema. Il formato del file di confi-gurazione è di tipo testuale ed è costruito per essere più leggibile e compattodell’XML. E’ inoltre un sistema di gestione della configurazione che richiedepoche risorse e, visto il numero non elevato di parametri da configurare nelprogetto in analisi, si è rivelato la scelta più opportuna.

Una configurazione, utilizzando la sintassi di questa libreria, è costituitada un insieme settings associate ad un nome e a uno o più valori. I valoripossono essere valori scalari, array di valori, gruppi di settings, o liste. Lasintassi per definire una setting è la seguente: name:value; o name=value; igruppi vengono identificati dalle parentesi grafe. Ogni settings viene iden-tificata in maniera univoca da un percorso (path), che è costituito da unasequenza di nomi, separati da punti, che partono dal nome del gruppo dilivello più alto fino a giungere al nome della setting stessa. Un altro vantag-gio nell’utilizzare questa libreria consiste nel fatto che il tipo dei valori vienedeterminato in automatico dal valore stesso del dato. Ad esempio un valoreracchiuso fra apici viene considerato di tipo stringa; una stringa ’true’ (o ’fal-se’), senza tenere in considerazione maiuscole o minuscole, viene consideratacome un parametro di tipo booleano.

18

Page 23: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 3. SVILUPPO SOFTWARE APPLICATIVO

Il file di configurazione per il progetto è stato così strutturato:

# --------------------------# Example Configuration File# --------------------------

version = "1.0.0.0";authWebServiceURL = "http://192.168.50.50:8725/ws.asmx";NetworkParam = {

conf = {dhcp = FALSE;address = "192.168.50.150";gateway = "192.168.50.254";netmask = "255.255.255.0";network = "192.168.20.0";dnsVal = "8.8.8.8\ 8.8.8.4";

}work = {

dhcp = FALSE;address = "192.168.50.151";gateway = "192.168.50.254";netmask = "255.255.255.0";network = "192.168.20.0";dnsVal = "8.8.8.8\ 8.8.8.4";

}}

I parametri principali contenuti nel file di configurazione sono quindi laversione del software, l’indirizzo URL del WebService con il quale il program-ma dovrà comunicare e i parametri per la configurazione di rete. Il moduloC++ di configurazione del software applicativo si occupa di effettuare un’a-nalisi del documento e di estrarre i dati contenuti nel file, sfruttando lefunzionalità della libreria. L’indirizzo del WebService viene salvato e utiliz-zato quando si verifica la necessità di contattare il WebService per otteneredei dati relativi a una tessere magnetica. I parametri di rete vengono utiliz-zati come input per uno script AWK che si occupa della configurazione direte. Questo script è stato sviluppato da terze parti e consente la lettura e lamodifica del file /etc/network/interfaces, descritto nel paragrafo 2.2, senzanecessità di modificare direttamente il file dei parametri di rete. L’utilizzodi questo script semplifica quindi il programma C++, in quanto è sufficienteeseguire lo script senza la necessità di accedere ai file di sistema.

19

Page 24: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 3. SVILUPPO SOFTWARE APPLICATIVO

Lo script, chiamato changeInterfaces.awk viene eseguito nel seguentemodo:

awk -f /path/to/changeInterfaces.awk <interfaces file>dev=<eth device>

[address=<ip addr>] [gateway=<ip addr>] [netmask=<ip addr>][network=<ip addr>] [mode=dhcp|static] [dns=<ip addr>]

Tutti i parametri indicati con le parentesi quadre sono opzionali, se noninseriti non vengono modificati dallo script. Il modulo prepara quindi unastringa corrispondente al comando awk che si vuole eseguire e la manda inesecuzione sfruttando i privilegi di amministratore di cui è dotato il software.

Un’altra importante funzionalità gestita da questo modulo software è ilcontrollo dell’autenticità del programma. Per evitare che il software instal-lato sulla scheda SD, che funge da memoria per il Raspberry, possa venirclonato in modo incontrollato, è stato deciso di inserire una licenza univocaper ogni dispositivo. La licenza sviluppata è legata ai parametri hardwaredel Raspberry che, essendo univoci, permettono di legare in maniera indisso-lubile licenza e hardware. I parametri hardware non sono inseriti “in chiaro”all’interno della licenza, ma vengono elaborati e crittografati utilizzando unsistema a codifica XOR. Per evitare manomissioni del file contenente la li-cenza, essa è stata inserita nella partizione /boot impostata in modalitàread-only (descritta nella sezione 3.3), che risulta accessibile in lettura a tut-ti gli utenti, ma modificabile solo da un utente amministratore che decida direimpostare la partizione in modalità di scrittura. La licenza viene infatti ge-nerata dall’amministratore di sistema al momento della prima installazionedel software applicativo o in caso di sostituzione della scheda SD. Il modulosoftware qui trattato esegue un algoritmo che gli permette di calcolare a suavolta il codice di licenza che verrà poi confrontato con quello contenuto nellapartizione protetta. Il risultato e il timestamp di questo controllo viene sal-vato su un file di log accessibile via FTP. Il risultato sarà rispettivamente unvalore EXIT_SUCCESS nel caso in cui il controllo risulti superato, per-mettendo la prosecuzione del programma, o un valore EXIT_FAILUREnel caso in cui il controllo fallisca, caso che verrà trattato opportunamentedalla classe che ha invocato questa funzione.

20

Page 25: Progettazione e sviluppo di un software applicativo su un single board computer

Capitolo 4

Automatizzazione deldispositivo

In questa sezione verranno descritti gli interventi fatti per rendere auto-matizzato il funzionamento del dispositivo. In particolare verrà descritto eanalizzato lo script bash utilizzato per eseguire il software applicativo, i toole le configurazioni adottate per l’utilizzo di FTP e SSH.

4.1 Script per la gestione del software applicativo

Per poter eseguire all’avvio il software applicativo, è stato sviluppato unoscript bash che viene eseguito all’avvio del sistema. Questo script svolgediverse funzioni: si occupa di monitorare la cartella dove vengono caricatitramite il protocollo FTP i nuovi file di configurazione e di spostare questifile nella sezione apposita del dispositivo, crea un log delle accensioni e man-da in esecuzione il software applicativo. La prima operazione svolta dalloscript è quella di attivare l’interfaccia di rete di default, ovvero l’interfacciadi configurazione che, come visto nel paragrafo 2.2 è stata configurata tra-mite indirizzo IP statico. Il log delle accensioni della scheda viene generatosalvando gli ultimi 50 accessi, con data di accesso, data dell’ultimo login edata dell’ultima configurazione. Questi dati vengono inseriti in un file che èvisualizzabile tramite FTP o SSH. Quando viene eseguito, lo script controllase sono stati inseriti nuovi aggiornamenti in una cartella definita in fase diconfigurazione. Se il controllo non viene superato, lo script continua a mo-nitorare la cartella in questione per 30 secondi tramite il tool “inotifywait”.Inotifywait è un tool utilizzato per monitorare dei cambiamenti su specificifiles, utilizzando l’API inotify di linux. Questa API mette a disposizionediverse system call per il monitoraggio di files e cartelle. Nel progetto inanalisi è stata scelta inotifywait in quanto più adatta per essere usata inshell script. Se nel controllo iniziale, o nei 30 secondi successivi vengonotrovati aggiornamenti, lo script crea un backup del programma precedente

21

Page 26: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 4. AUTOMATIZZAZIONE DEL DISPOSITIVO

e posiziona i nuovi file nel percorso voluto. Per l’esecuzione del programmaviene eseguita una fork dello script in esecuzione che viene messa in statodi “sleep” per 50 secondi. Al termine di questo periodo il processo generatotramite la chiamata di sistema fork() manda in esecuzione il programma einvia un comando kill() tramite il segnale SIGUSR1 a se stesso e al processoche l’ha generato. Tramite questa procedura il processo figlio dello script,ovvero il software applicativo, viene “adottato” da root, garantendogli quindii permessi di amministratore per tutta la durata del programma. L’utiliz-zo della system call kill() viene adottato anche per terminare eventuali casinon previsti o errori durante l’esecuzione dello script, come ad esempio er-rori duranti il loop di monitoraggio della cartella FTP o nella creazione delbackup.

In ambiente linux esistono diverse vie valide per eseguire un programmao uno script all’avvio del sistema operativo. Una di queste prevede la crea-zione di uno script, basato su un preciso standard, nella directory /etc/init.dper eseguire un dato programma. Lavorando con il Raspberry esiste un’al-ternativa più semplice per eseguire un comando o un programma al bootdel sistema operativo, senza la necessità di ulteriori script o configurazioni.Questa alternativa consiste nell’inserire i comandi desiderati all’interno delfile rc.local, il cui percorso è /etc/rc.local. Nel caso in analisi la modifica delfile è stata l’inserimento della seguente stringa all’interno di rc.local:

sudo /path/to/ConfigMonitorRoutine.sh &

Il comando esegue con i permessi di superuser lo script analizzato in prece-denza, chiamato appunto ConfigMonitorRoutine.sh. Il carattere ‘&’ è statoinserito per eseguire una chiamata di sistema fork() del processo, consenten-do allo stesso tempo il proseguimento dell’esecuzione dello script rc.local ela conclusione del boot del Raspberry.

4.2 Accesso via FTP e SSH e permessi utente

Per consentire l’aggiornamento e un monitoraggio in remoto del sistema si èdeciso di abilitare un server FTP e di configurare opportunamente un SSHserver su ogni sistema operativo installato.

La prima operazione è stata quella di creare due tipologie di utente, laprima con i permessi di superuser, mentre la seconda come utente standard,senza privilegi di root. Questo per consentire solo agli amministratori disistema di effettuare modifiche significative al progetto. L’idea è quella digarantire l’accesso completo da remoto al sistema solo agli utenti in possessodei privilegi di amministratore, mentre gli utenti standard devono poter avereaccesso solo a un particolare server FTP usato per gli aggiornamenti e perla lettura di alcuni log di sistema.

22

Page 27: Progettazione e sviluppo di un software applicativo su un single board computer

CAPITOLO 4. AUTOMATIZZAZIONE DEL DISPOSITIVO

E’ stato quindi attivato un server FTP su ogni scheda, garantendo l’ac-cesso a tutti gli utenti autorizzati solo a una specifica cartella. Questa car-tella verrà utilizzata per l’inserimento di nuovi aggiornamenti del softwareapplicativo e del file di configurazione. In questa cartella vengono inoltregenerati alcuni file di log, in modo tale da garantire un primo metodo perdiagnosticare eventuali problemi avvenuti durante l’avvio del programma.La configurazione del server FTP è stata fatta utilizzando vsftpd uno deiprogrammi più usati disponibili in ambiente linux per l’installazione di unserver FTP. L’installazione di vsftpd viene fatta sfruttando il comando apt-get, mentre per la configurazione dello stesso si procede alla modifica del filevsftpd.conf, che viene collocato al momento dell’installazione nella directory/etc. Il file di configurazione è stato quindi modificato negando l’accesso tra-mite FTP ad utenti anonimi e limitando l’accesso alle due tipologie di utentiprima descritte solo a una particolare cartella che si è deciso di collocarenella directory /var.

Per consentire agli amministratori un accesso completo in remoto al si-stema operativo è stato inoltre abilitato un server SSH. Anche in questo casoper l’installazione si è utilizzato il tool apt-get, e per la configurazione è sta-to necessario modificare il file di configurazione relativo, collocato anch’essonella directory /etc.

23

Page 28: Progettazione e sviluppo di un software applicativo su un single board computer

Conclusioni

Il dispositivo che si è andati a sviluppare si è dimostrato in grado di soddisfa-re le specifiche emerse in fase di analisi introduttiva. Sono state utilizzate inmodo efficace tutte le periferiche imposte dal committente ed è stato svilup-pato un opportuno sistema di feedback per l’utente. Il funzionamento dellaweb service e la comunicazione con il web server sono stata testati in modoestensivo, così come i moduli software per l’elaborazione dei dati. Il sistemasi è inoltre dimostrato molto robusto, garantendo così stabilità al progetto.Il software sviluppato è stato installato su diversi Raspberry Pi 2, che dopoesser stati opportunamente configurati, sono adesso operativi nelle sedi sta-bilite dal committente. Grazie alle soluzioni adottate per l’aggiornamento ela configurazione remota del sistema, c’è la possibilità di migliorare ulterior-mente il sistema in futuro e eventualmente di sviluppare nuove funzionalità.Alcune delle soluzioni che sono state sviluppate sono inoltre utilizzabili anchesu differenti progetti basati sulla stessa tipologia di hardware. In particolarel’impostazione di parte del file-system in modalità di sola lettura, lo scriptper l’esecuzione all’avvio di un software applicativo e l’abilitazione degli ac-cessi FTP e SSH sono strumenti che possono essere agevolmente utilizzati inaltri progetti basati sul Raspberry Pi o schede simili.

24

Page 29: Progettazione e sviluppo di un software applicativo su un single board computer

CONCLUSIONI

Figura 4.1: Foto del progetto ultimato e preparato per l’utilizzo industriale

Figura 4.2: Foto del progetto installato in ambito industriale

25

Page 30: Progettazione e sviluppo di un software applicativo su un single board computer

Appendice A

Codice Sorgente

In questa sezione verranno presentate le parti più significative del codicesviluppato. Alcune sezioni sono state omesse per motivi di riservatezza.

A.1 PrinterModule.cpp

Classe contenente le varie funzioni dedite alla creazione di file PostScript perla stampa e la gestione della stampante termica. Verrà presentata solo unadelle funzioni di stampa, quella per la creazione della stampa all’avvio. Lacreazione delle stampe in seguito all’analisi dei dati ricevuti dal WebServerè analoga, ma con un layout molto più complesso. I dati per questo tipo distampa vengono ottenuti dalla classe InputParser.c .

#include "PrinterModule.h"#include "Periph/InputParser.h"

using std::string;using std::vector;

/*Definizione delle dimensioni del foglio e di alcuni parametricome il bordo laterale e l’interlineaQuesti valori sono espressi in punti tipografici*/#define WIDTH 520#define HEIGHT 2080#define INTERLINE 20#define BORD 0#define FONT "Calibri"

26

Page 31: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

int settext (cairo_t *context, PangoFontDescription *desc,int x, int y, char string[]){

/* Questo metodo posiziona una stringa su un cairo context allecoordinate desiderate. */

PangoLayout *layout;//Utilizzo dei metodi della librerie pango e cairo per la

gestione del testocairo_translate(context, x, y);layout = pango_cairo_create_layout(context);pango_layout_set_width(layout, WIDTH*PANGO_SCALE);pango_layout_set_wrap (layout, PANGO_WRAP_WORD);pango_layout_set_spacing

(layout,(int)INTERLINE*PANGO_SCALE*0.5);pango_layout_set_text(layout, string, -1);pango_layout_set_font_description(layout, desc);

pango_cairo_update_layout(context, layout);pango_cairo_show_layout(context, layout);

int width;int height;pango_layout_get_size (layout, &width, &height);height =(int)(height/PANGO_SCALE);cairo_translate(context, -x, -y);g_object_unref(layout);return height;

}

int setcenteredtext (cairo_t *context, PangoFontDescription *desc,int x, int y, char string[]){

/*Posiziona il testo al centro della riga utilizzando il metodoprecedente*/

int x_len;int y_len;

//funzione che fornisce lunghezza del testo in pxpango_layout_get_pixel_size (layout, &x_len, &y_len);

//calcola la lunghezza del testo in punti tipograficix_len=0.75*x_len;

//calcola la posizione del testo centratoint x_coord=0.5*(WIDTH-x_len+x);

return settext (context, desc, x_coord, y, string);}

27

Page 32: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

int PrinterModule::PrintRoutine(char tmpfilename[], int len){/*Questa sezione del programma dedicata all’invio alla stampante

termica dei file PostScript creati*/

int num_jobs;cups_job_t *joblist; //Oggetto contenente la coda di stampa

//Determinazione della stampante di defaultcups_dest_t *dests;int num_dests = cupsGetDests(&dests);

//Creazione delle opzioni di stampaint num_options;cups_option_t *options;num_options = 0;options = (cups_option_t *)0;int mylen=(int)((len+10)/10)*10;string optiontext = "job-sheets=none,none

media=Custom.72x"+std::to_string(mylen)+"mm sides=one-sided";

//Impostazione delle opzioni di stampanum_options = cupsParseOptions(optiontext.c_str(), num_options,

&options);

//Svuotamento della coda di stampacupsFreeDests(num_dests, dests);cupsCancelJob(cupsGetDefault(), CUPS_JOBID_ALL);

//Inizio della stampaint job = cupsPrintFile(cupsGetDefault(), tmpfilename, "cairo

PS", num_options, options);

num_jobs = cupsGetJobs(&joblist, NULL, 0, -1);

/*Controllo di eventuale stampe bloccate ed eventualesegnalazione dell’errore.

Il controllo viene fatto verificando che le stampe inserite incoda di stampa siano in uno stato di "printed"*/

for (int i = 0; i < num_jobs; i ++){printf("%-16.16s %-6d %-12.12s %s (%s)\n", joblist[i].dest,

joblist[i].id,joblist[i].user, joblist[i].title,joblist[i].state != IPP_JOB_PENDING ? "printed" : "pending");

if(joblist[i].id == job) {if(joblist[i].state == IPP_JOB_PENDING ){

28

Page 33: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

std::cout << "Errore nella stampa"<<’\n’;cupsFreeOptions (num_options, options);cupsFreeJobs(num_jobs, joblist);return EXIT_FAILURE;

}}

}cupsFreeJobs(num_jobs, joblist);cupsFreeOptions (num_options, options);return EXIT_SUCCESS;

}

int PrinterModule::StartingPrint (string Version, stringMACAddress, string IPAddress){char filename[]="/tmp/StartingPrint.ps";cairo_surface_t* surface;cairo_t *context;PangoFontDescription *font;

//Creazione di una surface con una specifica dimensione (inpunti tipografici)

int len = 500;double mmlen=len*(0.35)/(2.5);surface=cairo_ps_surface_create (filename, WIDTH, len);//Creazione del contextcontext=cairo_create (surface);

//Creazione di un descrittore di fontfont=pango_font_description_new ();pango_font_description_set_size (font,17*PANGO_SCALE);pango_font_description_set_family (font, FONT);pango_font_description_set_weight(font, PANGO_WEIGHT_BOLD);

settext(context, font, BORD, 0, (char*)"QAS SERVICE REPORTERSTARTED");

settext(context, font, BORD, 50,(char*)"------------------------------------------------------");

std::string Versiontext="Version: "+Version;settext(context, font, BORD, 100, (char*)Versiontext.c_str());std::string LicenseText="License OK";settext(context, font, BORD, 150, (char*)LicenseText.c_str());std::string MACtext="MACAddress: "+MACAddress;settext(context, font, BORD, 200, (char*)MACtext.c_str());std::string IPtext="Work IP Address: "+IPAddress;settext(context, font, BORD, 250, (char*)IPtext.c_str());settext(context, font, BORD, 300,

(char*)"------------------------------------------------------");

29

Page 34: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

//Salvataggio del file e distruzione degli oggetti creaticairo_surface_flush(surface);cairo_surface_destroy(surface);cairo_destroy(context);pango_font_description_free(font);

//Inizio stampaPrintRoutine(filename, (int)mmlen);return EXIT_SUCCESS;

}

A.2 InputParser.cpp

Classe contente le funzioni che vengono utilizzate da PrinterModule.cpp perottenere le stringhe da inserire nel modulo di stampa.

#include "InputParser.h"

using std::string;using std::vector;

vector<string> InputParser::str_decode (string Input, string delim){//Questa funzione scompone la stringa in input in vari token

separati dalla sottostringa delimvector<string> res;int start = 0;int end = Input.find(delim);

while (end != std::string::npos){

res.push_back (Input.substr(start, end - start));

start = end + delim.length();end = Input.find(delim, start);

}

return res;}

int InputParser::ConvertDate (char *input){/*Converte la data dal formato "dd/mm/yyyy" nel formato

"local_dayname dd/mmmm/yyyy" */setlocale (LC_ALL, "" );struct tm tm;char buf[255];

30

Page 35: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

memset(&tm, 0, sizeof(struct tm));

//Utilizzo di strptimeif(strptime(input,"%d/%m/%Y",&tm)==NULL){

printf ("Formato data errato\n"); //input non validoreturn(EXIT_FAILURE);

};//Utilizzo di strftimeif(strftime(buf, sizeof(buf), "%^A %d %^B %Y", &tm)==0) {

printf ("Errore conversione data\n"); //contents of buf areundeterminate

return(EXIT_FAILURE);};std::string Date ((const char*) buf);this->Date=Date;

return(EXIT_SUCCESS);}

int InputParser::CheckTokens (vector<string> tokens){//Controlla il numero di tokens per l’input di tipo "operatore"if (tokens.size()<6) {printf("Numero Parametri Insufficiente\n");return EXIT_FAILURE;

}return EXIT_SUCCESS;

}

int InputParser::GetOperator (){this->Operator = this->tokens[0];tokens.erase(tokens.begin());return EXIT_SUCCESS;

}

int InputParser::DecodeInput (string input, string delim){//Scompone l’input e prepara i parametri necessari alla classe

PrinterModule.cppthis->tokens = str_decode (input, delim);

this->GetOperator();

if (Operator == "O") {if (this->CheckTokens(tokens) == EXIT_FAILURE) {

return EXIT_FAILURE;}

this->Name = str_decode (tokens[0],";");if (Name.size()==0){

31

Page 36: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

this->Name.push_back(tokens[0]);}

if(this->ConvertDate((char*)tokens[1].c_str()) ==EXIT_FAILURE){return EXIT_FAILURE;

}this->Partofday = tokens[2];this->Activity = tokens[3];this->Location = tokens[4];this->Vehicle = str_decode (tokens[5], ";");if(Vehicle.size()==0){

this->Vehicle.push_back(tokens[5]);}this->Nota = tokens[6];return EXIT_SUCCESS;

}else if (Operator == "R") {

for(int i=0;i<tokens.size();i++){vector<string> decode = str_decode(tokens[i], ";");this->UncoveredActivities.insert(std::end(UncoveredActivities),

std::begin(decode),std::end(decode));

}return EXIT_SUCCESS;

}return EXIT_FAILURE;

}

32

Page 37: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

A.3 Configuration.cpp

#include "Configuration.h"#include "Periph/PrinterModule.h"

using namespace std;using namespace libconfig;

void Configuration::SettingNetwork(string networktype) {//Funzione che si occupa di impostare le modifiche ai parametri di

rete basandosi sul file di configurazione//Il programma genera una stringa costituente un apposito comando

AWK//Il comando viene poi eseguito sfruttando i privilegi di

amministratore di questo programmabool dhcp;std::string Address;std::string Gateway;std::string Netmask;std::string Network;std::string dnsVal;

try {

/*Funzionamento script awkawk -f /path/to/changeInterfaces.awk <interfaces file>

dev=<eth device> \n* [address=<ip addr>] [gateway=<ip addr>] [netmask=<ip

addr>] \n* [network=<ip addr>] [mode=dhcp|static] [dns=<ip addr>]*/std::string cmd = "awk -f /path/to/changeInterface.awk";

//posizione dello script sul dispositivocmd = cmd + " /etc/network/interfaces ";cmd = cmd + "dev=eth0-" + networktype;

const Setting& root = cfg.getRoot();const Setting& param =

root["NetworkParam"][networktype.c_str()];

//Connessione tramite DHCPtry {

dhcp = param.lookup("dhcp");if (dhcp == true) {

cmd = cmd + " " + "mode=dhcp";cmd = cmd + " >> /etc/network/interfaces.tmp && mv

/etc/network/interfaces.tmp/etc/network/interfaces";

33

Page 38: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

system(cmd.c_str());return;

}} catch (const SettingNotFoundException &nfex) {}

//Connessione staticatry {

param.lookupValue("address", Address);cmd = cmd + " address=" + Address;if (networktype == "work") {

this->WorkIPAddress = Address;}

} catch (const SettingNotFoundException &nfex) {}

try {param.lookupValue("gateway", Gateway);cmd = cmd + " gateway=" + Gateway;

} catch (const SettingNotFoundException &nfex) {}

try {param.lookupValue("netmask", Netmask);cmd = cmd + " netmask=" + Netmask;

} catch (const SettingNotFoundException &nfex) {}

try {param.lookupValue("network", Network);cmd = cmd + " network=" + Network;

} catch (const SettingNotFoundException &nfex) {}

cmd = cmd + " " + "mode=static";

try {param.lookupValue("dnsVal", dnsVal);cmd = cmd + " dns=" + dnsVal;

} catch (const SettingNotFoundException &nfex) {}

cmd = cmd + " >> /etc/network/interfaces.tmp && mv/etc/network/interfaces.tmp /etc/network/interfaces";

system(cmd.c_str());

} catch (SettingNotFoundException &nfex) {}

34

Page 39: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

}

string EncryptDecrypt(string source) {//Cifratura XOR. La chiave contenuta nell’array key[], qui omesso

string output = source;for (int i = 0; i < source.size(); i++) {

output[i] = source[i] ^ key[i % (sizeof (key) / sizeof(char))];

}return output;

}

string GetLocalSerial() {char line[256];FILE *mac;mac = fopen("/sys/class/net/eth0/address", "r");if (mac == NULL) {

throw "Rete non configurata correttamente";}fgets(line, 256, mac);fclose(mac);string result = line;return EncryptDecrypt(result);

}

string GetLicenceSerial() {//Verifica la presenza di una licenza e ne ottiene il codice.

FILE *licenceFile;char line[256];char code[256];licenceFile = fopen("/boot/EliLicence.txt", "r");if (licenceFile == NULL) {

throw "File di Licenza mancante";}else {

while (fgets(line, 256, licenceFile)) {if (strncmp(line, "License Code", 12) == 0) {

strcpy(code, strchr(line, ’:’) + 2);}

}}fclose(licenceFile);string LicenseID = code;return LicenseID;

}

int Configuration::CheckLicence() {//Controllo della licenza

time_t rawtime;

35

Page 40: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

struct tm * timeinfo;time(&rawtime);timeinfo = localtime(&rawtime);

ofstream resfile;//Crea un log nella partizione FTP contenente lo stato della

licenzaresfile.open("/var/ftp/configuser/LicenceResult.txt",

std::ofstream::app);try {

this->LicenseID = GetLicenceSerial();} catch (const char* msg) {

//File di licenza mancanteresfile << asctime(timeinfo) << ": " << msg << std::endl;resfile.close();throw msg;return EXIT_FAILURE;

}(...) //Calcolo della licenza RpiID tramite i parametri di

sistemaif (RpiID.compare(this->LicenseID) != 0) {

resfile << asctime(timeinfo) << ": Codice di licenza noncorrispondente\n";

resfile.close();std::cerr << "Codice di licenza non corrispondente" <<

std::endl;throw "Codice di licenza non corrispondente";return EXIT_FAILURE;

}

resfile << asctime(timeinfo) << ": Controllo licenza superatocorrettamente\n";

resfile.close();ofstream licfile;licfile.open("/var/ftp/configuser/EliLicence.txt");licfile << this->LicenseID;licfile.close();

return EXIT_SUCCESS;}

int Configuration::LoadConfiguration() {

//Tentativo di lettura del file di configurazione.try {

cfg.readFile("/path/to/configuration.cfg"); //posizioneprevista del file

} catch (const FileIOException &fioex) {std::cerr << "MISSING CONFIGURATION FILE" << std::endl;

36

Page 41: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

return (EXIT_FAILURE);} catch (const ParseException &pex) {

std::cerr << "Parse error at " << pex.getFile() << ":" <<pex.getLine()

<< " - " << pex.getError() << std::endl;return (EXIT_FAILURE);

}

//accesso ai parametriconst Setting& root = cfg.getRoot();const Setting& param = root["NetworkParam"];

this->version = VERSION;

try {cfg.lookupValue("authWebServiceURL",

this->authWebServiceURL);} catch (const SettingNotFoundException &nfex) {

cerr << "No authWebServiceURL setting in configurationfile." << endl;

}//impostazione configurazioni di retetry {

SettingNetwork("conf");SettingNetwork("work");

} catch (SettingNotFoundException &nfex) {}return 0;

}

void Configuration::SwitchConnection() {//Passa dalla connessione di Configurazione a quella Operativa//In caso di fallimento del controllo di licenza, questo cambio

non avviene e//il dispositivo rimane connesso alla connessione di

configurazionestd::cout << "Turning OFF Configuration Connection" <<

std::endl;system("ifdown eth0=eth0-conf");std::cout << "Turning ON Service Connection" << std::endl;system("ifup eth0=eth0-work");

}

void Configuration::Dump() {//Stampa che viene effettuata all’avvio del programma, per

segnalare all’utente che il sistema operativostd::string localIPAddress = GetLocalIPAddress();PrinterModule module;

37

Page 42: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

module.StartingPrint(this->version, this->MACAddress,localIPAddress);

}

A.4 Utilizzo Tiny Xml

Il parsing del testo XML ricevuto in input è gestito da un modulo inserito nelWebClient sviluppato per il dispositivo. Esistono due possibili stringhe cherisultano di interesse. La prima è delimitata dai tag <string>< /string>,mentre la seconda è una stringa inserita fra i tag <lavoro>< /lavoro>, cheviene inserita come figlio dell’elemento <string>.

(...)

vector<string> eliWebClient::ParseResultXML(std::string resultxml){

vector<string> result;

TiXmlDocument doc;doc.Parse(resultxml.c_str(), 0, TIXML_ENCODING_UTF8);

//Determinazione dell’elemento "padre"//father -> <string>..</string>

TiXmlElement* father = doc.FirstChildElement("string");

//Determinazioni dei "figli"//element -> <string><lavoro>...</lavoro></string>

TiXmlNode* firstChildString = doc.FirstChild("string");TiXmlElement* element;

if (firstChildString) {element = firstChildString->FirstChildElement();

//<string><lavoro>...</lavoro></string>if (element)

{for(element; element;

element=element->NextSiblingElement()){result.push_back(element->GetText());

}return result;

}}

if (father){result.push_back(father->GetText());

38

Page 43: Progettazione e sviluppo di un software applicativo su un single board computer

APPENDICE A. CODICE SORGENTE

return result;}

return result;}

39

Page 44: Progettazione e sviluppo di un software applicativo su un single board computer

Bibliografia

[1] J. Kuan. (2015) Script awk per modificare il file /etc/net-work/interfaces. [Online]. Available: https://github.com/JoeKuan/Network-Interfaces-Script

[2] (2016) Dati tecnici raspberry pi 2 model b. [Online]. Available:http://elinux.org/RPi_Hardware

[3] RaspberryPiFoundation. (2016) Documentazione ufficiale raspberry pi.[Online]. Available: https://www.raspberrypi.org/documentation/

[4] W3C. (2016) Web server architecture. [Online]. Available: https://www.w3.org/TR/ws-arch/

[5] Cairographics. [Online]. Available: https://www.cairographics.org/

[6] Pango. [Online]. Available: https://developer.gnome.org/pango/stable/

[7] Libconfig++. [Online]. Available: http://www.hyperrealm.com/libconfig/

40


Recommended