• Non ci sono risultati.

3.5 Il codice - Lato device

3.5.2 device.js

Si procede ora ad illustrare l’applicativo del device:

1 c o n s t fs = r e q u i r e (’ fs ’) ;

2 c o n s t r e q u e s t = r e q u i r e (’ r e q u e s t ’) ; 3 c o n s t i o t h u b = r e q u i r e (’ azure - i o t h u b ’) ;

4 c o n s t C l i e n t = r e q u i r e (’ azure - iot - d e v i c e ’) . C l i e n t ;

5 c o n s t P r o t o c o l = r e q u i r e (’ azure - iot - device - m q t t ’) . M q t t ; 6 c o n s t c r y p t o = r e q u i r e (’ c r y p t o ’) ;

7 c o n s t c o n f i g = r e q u i r e (’ ./ c o n f i g . js ’) ;

8 c o n s t j s o n M a n a g e r = r e q u i r e (’ ./ j s o n M a n a g e r . js ’) ; 9 c o n s t { C o n s o l e } = r e q u i r e (’ c o n s o l e ’) ;

10

11 // S e t u p the c o n n e c t i o n s t r i n g 12 // For the IoT hub

13 c o n s t I O T _ H U B _ C O N N E C T I O N _ S T R I N G = c o n f i g . I O T _ H U B _ C O N N E C T I O N _ S T R I N G ;

14 c o n s t r e g i s t r y = i o t h u b . R e g i s t r y . f r o m C o n n e c t i o n S t r i n g ( I O T _ H U B _ C O N N E C T I O N _ S T R I N G ) ;

15

16 // Ask for a new r e g i s t r a t i o n to iot hub

17 r e q u e s t ( c o n f i g . O P T I O N S _ D E V I C E , a s y n c f u n c t i o n( error , r e s p o n s e , b o d y ) {

18 try {

19 c o n s o l e . log ( r e s p o n s e . s t a t u s C o d e ) ; 20 s w i t c h ( r e s p o n s e . s t a t u s C o d e ) {

21 // If the r e s p o n s e is a 201 , the d e v i c e is not r e g i s t e r e d yet

22 c a s e 2 0 1 :

23 r e g i s t r y N e w D e v i c e ( error , r e s p o n s e , J S O N . p a r s e ( b o d y ) )

24 . t h e n (f u n c t i o n( c l i e n t ) {

25 c o n s o l e . log (’ D e v i c e r e g i s t e r e d ’ , J S O N . p a r s e ( b o d y ) ) ;

26 c r e a t e T w i n ( c l i e n t ) ;

27 })

28 .c a t c h(f u n c t i o n( e r r o r ) {

29 c o n s o l e . log (’ E r r o r in the r e q u e s t ’ + e r r o r ) ;

3.5 – Il codice - Lato device

30 r e t u r n new E r r o r ( e r r o r ) ;

31 })

32 b r e a k;

33

34 // If the r e s p o n s e is a 202 , the d e v i c e is a l r e a d y r e g i s t e r e d

35 c a s e 2 0 2 :

36 c o n s o l e . log (’ D e v i c e a l r e a d y r e g i s t e r e d ’ , b o d y . m e s s a g e ) ;

37

38 // R e a d the l o c a l f i l e w h e r e sas t o k e n is s t o r e d 39 j s o n M a n a g e r . r e a d J s o n ()

40 . t h e n (f u n c t i o n( k e y s ) {

41 var c l i e n t = C l i e n t . f r o m S h a r e d A c c e s s S i g n a t u r e ( k e y s . s a s T o k e n , P r o t o c o l ) ;

42 c o n s o l e . log (’ o g g e t t o : ’ , c l i e n t . _ t r a n s p o r t . _ f s m . s t a t e ) ;

43 if( c l i e n t . _ t r a n s p o r t . _ f s m . s t a t e . t r i m () == d i s c o n n e c t e d ’) {

44 c o n s o l e . log ( k e y s ) ;

45 c o n s o l e . log (’ Sas t o k e n has expired , g e n e r a t i n g a new one ’) ;

46 let s a s T o k e n = g e n e r a t e S a s T o k e n ( S t r i n g ( k e y s . e n d p o i n t ) , S t r i n g ( k e y s . S y m m e t r i c K e y ) , ’ ’, 1 2 0 ) ;

47 var c l i e n t = C l i e n t . f r o m S h a r e d A c c e s s S i g n a t u r e ( s a s T o k e n , P r o t o c o l ) ;

48 k e y s . s a s T o k e n = s a s T o k e n ;

49 c o n s o l e . log (’ U p d a t i n g the new t o k e n ’) ;

50 j s o n M a n a g e r . w r i t e J s o n ( J S O N . s t r i n g i f y ( k e y s ) ) ;

51 c h e c k T w i n ( c l i e n t ) ;

52 }e l s e{

53 c o n s o l e . log (’ A c q u i r i n g the t w i n ’) ;

54 c h e c k T w i n ( c l i e n t ) ;

55 }

56 })

57 .c a t c h(f u n c t i o n( err ) {

58 c o n s o l e . log (’ E r r o r d u r i n g the r e c o n n e c t i o n w i t h the iot hub ’ , err ) ;

59 })

60 b r e a k;

61

62 // S o m e p r o b l e m s o c c u r r e d d u r i n g the r e q u e s t

63 d e f a u l t :

64 c o n s o l e . log (’ S t a t u s c o d e not r e c o g n i z e d for the r e g i s t r a t i o n r e q u e s t ’ , b o d y ) ;

65 b r e a k;

66 }

67 }c a t c h( e r r o r ) {

68 c o n s o l e . log (’ An e r r o r o c c u r r e d d u r i n g the r e q u e s t for r e g i s t r a t i o n ’ + e r r o r ) ;

69 }

70 })

71

72 // W r i t e the d e v i c e I D i n t o the r e g i s t e r of the iot hub 73 f u n c t i o n r e g i s t r y N e w D e v i c e ( error , r e s p o n s e , b o d y ) { 74 r e t u r n new P r o m i s e (f u n c t i o n( resolve , r e j e c t ) { 75 if( b o d y . e n d p o i n t ) {

76 r e g i s t r y . c r e a t e ( c o n f i g . DEVICE , f u n c t i o n( err , d e v i c e I n f o , res ) {

77 if ( e r r o r ) {

78 c o n s o l e . log (’ E r r o r d u r i n g the c o n n e c t i o n w i t h the iot hub : ’ + err ) ;

79 r e t u r n new E r r o r ( err ) ;

80 }

81 e l s e if ( res && d e v i c e I n f o ) {

82 c o n s o l e . log (’ S t a t u s of the r e q u e s t : ’ + res . s t a t u s C o d e + ’ ’ + res . s t a t u s M e s s a g e ) ; 83 c o n s o l e . log (’ D e v i c e i n f o : ’ + J S O N . s t r i n g i f y (

d e v i c e I n f o ) ) ; 84

85 // Get the s y m m e t r i c key g e n e r a t e d d u r i n g the r e g i s t r a t i o n

86 // In o r d e r to g e n e r a t e a sas t o k e n w i t h a l i m i t e d t i m e v a l i d i t y

87 c o n s t s a s T o k e n = g e n e r a t e S a s T o k e n ( b o d y . e n d p o i n t , d e v i c e I n f o . a u t h e n t i c a t i o n . S y m m e t r i c K e y .

p r i m a r y K e y , ’ ’, 1 2 0 ) ;

88 // W r i t e the t o k e n i n t o a l o c a l f i l e

89 var k e y s = {

90 e n d p o i n t : b o d y . e n d p o i n t ,

91 p r i m a r y K e y : d e v i c e I n f o . a u t h e n t i c a t i o n . S y m m e t r i c K e y . p r i m a r y K e y ,

92 s a s T o k e n : s a s T o k e n

93 }

94 j s o n M a n a g e r . w r i t e J s o n ( J S O N . s t r i n g i f y ( k e y s ) ) ; 95

96 c o n s t c l i e n t = C l i e n t . f r o m S h a r e d A c c e s s S i g n a t u r e ( s a s T o k e n , P r o t o c o l ) ;

97

98 // C h e c k if an e r r o r o c c u r e d d u r i n g 99 // The a u t h e n t i c a t i o n w i t h SAS t o k e n

3.5 – Il codice - Lato device

100 if ( err ) {

101 c o n s o l e . log (’ C o u l d not o p e n I o t H u b c l i e n t ’) ;

102 r e j e c t ( err ) ;

103 } e l s e if( c l i e n t ) {

104 c o n s o l e . log (’ C l i e n t c o n n e c t e d ’) ;

105 r e s o l v e ( c l i e n t ) ;

106 }

107 }

108 })

109 }e l s e{

110 c o n s o l e . log (’ An e r r o r o c c u r e d w h i l e t r y i n g to r e g i s t r a t e a new d e v i c e ’ , e r r o r ) ;

111 r e j e c t ( e r r o r ) ;

112 }

113 })

114 }

115

116 // O p e n the t w i n of the d e v i c e in the iot hub 117 f u n c t i o n c r e a t e T w i n ( c l i e n t ) {

118 c l i e n t . o p e n (f u n c t i o n( err ) { 119

120 // C r e a t e the i o t h u b c l i e n t

121 if(! err ) {

122 c o n s o l e . log (’ C l i e n t o p e n e d ’) ; 123

124 // A c q u i r e d e v i c e T w i n

125 c l i e n t . g e t T w i n (f u n c t i o n( err , t w i n ) {

126 if ( err ) {

127 c o n s o l e . e r r o r (’ C o u l d not get t w i n ’ + err ) ;

128 r e t u r n new E r r o r ( err ) ;

129 } e l s e {

130 // I n i t i a l i z e the t w i n of the d e v i c e in the iot hub

131 i n i t i a l i z e S t a t u s ( t w i n ) ;

132 c o n s o l e . log (’ T w i n a c q u i r e d ’) ;

133 t w i n . on (’ p r o p e r t i e s . d e s i r e d . f i r m w a r e ’, f u n c t i o n( f i r m w a r e U p d a t e ) {

134 if ( f i r m w a r e U p d a t e . s t a t u s == ’ a v a i l a b l e ’) {

135 c o n s o l e . log (’ U p d a t i n g f i r m w a r e v e r s i o n :

) ; 136

137 // C a l l the g e t A v a i l a b l e F i r m w a r e API 138 r e q u e s t ( c o n f i g . O P T I O N S _ F I R M W A R E ,

f u n c t i o n ( error , r e s p o n s e , b o d y ) {

139 if( r e s p o n s e . s t a t u s C o d e == 2 0 0 ) {

140

141 // If a s u c c e s s f u l l r e q u e s t has

o c c u r r e d

142 // D o w n l o a d the u p d a t e f i l e

143 c o n s o l e . log ( b o d y )

144 var n e w F i r m w a r e S t r e a m = fs .

c r e a t e W r i t e S t r e a m (’ ./ l a s t U p d a t e . zip ’)

145 r e q u e s t ( b o d y . s a s T o k e n ) . p i p e (

n e w F i r m w a r e S t r e a m ) ;

146 n e w F i r m w a r e S t r e a m . on (’ c l o s e ’,

f u n c t i o n() {

147 if( e r r o r ) {

148 r e t u r n new E r r o r ( e r r o r ) ;

149 }e l s e{

150 c o n s o l e . log (’ New v e r s i o n ’ +

b o d y . f w V e r s i o n ) ;

151 t w i n . p r o p e r t i e s . r e p o r t e d . u p d a t e

({ f i r m w a r e : { f w V e r s i o n : b o d y . f w V e r s i o n }} , f u n c t i o n( err ) {

152 if( err ) {

153 c o n s o l e . log (’ E r r o r d u r i n g

the r e p o r t i n g of the p r o p e r t i e s ’ + err ) ;

154 r e t u r n new E r r o r ( err ) ;

155 }

156 }) ;

157 }

158 }) ;

159 } e l s e {

160 c o n s o l e . log (’ E r r o r d u r i n g the

a c q u i s i t i o n of the new f i r m w a r e on d e v i c e s i d e : ’+ e r r o r )

161 r e t u r n new E r r o r ( e r r o r ) ;

162 }

163 })

164 }e l s e{

165 c o n s o l e . log (’ E r r o r d u r i n g the c h e c k of

the d e s i r e d p r o p e r t i e s ’ + e r r o r ) ;

166 r e t u r n new E r r o r ( e r r o r ) ;

167 }

168 }) ;

169 }

170 })

171 }

3.5 – Il codice - Lato device

172 })

173 } 174

175 // C h e c k the d e s i r e d p r o p e r t i e s of the t w i n 176 f u n c t i o n c h e c k T w i n ( c l i e n t ) {

177 c l i e n t . g e t T w i n (f u n c t i o n( err , t w i n ) {

178 if ( err ) {

179 c o n s o l e . e r r o r (’ c o u l d not get t w i n ’ + err ) ; 180 r e t u r n new E r r o r ( err ) ;

181 } e l s e {

182 t w i n . on (’ p r o p e r t i e s . d e s i r e d . f i r m w a r e ’, f u n c t i o n( f i r m w a r e U p d a t e ) {

183 if ( f i r m w a r e U p d a t e . s t a t u s == ’ a v a i l a b l e ’) { 184 c o n s o l e . log (’ U p d a t i n g f i r m w a r e v e r s i o n : ’) ; 185

186 // C a l l the g e t A v a i l a b l e F i r m w a r e API

187 r e q u e s t ( c o n f i g . O P T I O N S _ F I R M W A R E , f u n c t i o n ( error , r e s p o n s e , b o d y ) {

188 if( r e s p o n s e . s t a t u s C o d e == 2 0 0 ) {

189 // If a s u c c e s s f u l l r e q u e s t has o c c u r r e d 190 // D o w n l o a d the u p d a t e f i l e

191 var n e w F i r m w a r e S t r e a m = fs . c r e a t e W r i t e S t r e a m (

’ ./ l a s t U p d a t e . zip ’)

192 r e q u e s t ( b o d y . s a s T o k e n ) . p i p e ( n e w F i r m w a r e S t r e a m ) ;

193 n e w F i r m w a r e S t r e a m . on (’ c l o s e ’, f u n c t i o n() {

194 if( e r r o r ) {

195 r e t u r n new E r r o r ( e r r o r ) ;

196 }e l s e{

197 c o n s o l e . log (’ New v e r s i o n ’ + b o d y .

f w V e r s i o n ) ;

198 t w i n . p r o p e r t i e s . r e p o r t e d . u p d a t e ({ f i r m w a r e : { f w V e r s i o n : b o d y . f w V e r s i o n }} ,

f u n c t i o n( err ) {

199 if( err ) {

200 c o n s o l e . log (’ E r r o r d u r i n g the

r e p o r t i n g of the p r o p e r t i e s ’ + err ) ;

201 r e t u r n new E r r o r ( err ) ;

202 }

203 }) ;

204 }

205 }) ;

206 } e l s e {

207 c o n s o l e . log (’ E r r o r d u r i n g the a c q u i s i t i o n of the new f i r m w a r e on d e v i c e s i d e : ’+ e r r o r )

208 c o n s o l e . log ( b o d y ) ;

209 r e t u r n new E r r o r ( e r r o r ) ;

210 }

211 })

212 }e l s e{

213 c o n s o l e . log (’ E r r o r d u r i n g the c h e c k of the d e s i r e d p r o p e r t i e s ’ + e r r o r ) ;

214 r e t u r n new E r r o r ( e r r o r ) ;

215 }

216 }) ;

217 }

218 }) 219 } 220

221 var g e n e r a t e S a s T o k e n = f u n c t i o n( r e s o u r c e U r i , s i g n i n g K e y , p o l i c y N a m e , e x p i r e s I n M i n s ) {

222 r e s o u r c e U r i = e n c o d e U R I C o m p o n e n t ( r e s o u r c e U r i ) ; 223

224 // Set e x p i r a t i o n in s e c o n d s

225 var e x p i r e s = ( D a t e . now () / 1 0 0 0 ) + e x p i r e s I n M i n s * 60;

226 e x p i r e s = M a t h . c e i l ( e x p i r e s ) ;

227 var t o S i g n = r e s o u r c e U r i + ’ \ n ’ + e x p i r e s ; 228

229 // Use c r y p t o

230 var h m a c = c r y p t o . c r e a t e H m a c (’ s h a 2 5 6 ’, B u f f e r . f r o m ( s i g n i n g K e y , ’ b a s e 6 4 ’) ) ;

231 h m a c . u p d a t e ( t o S i g n ) ;

232 var b a s e 6 4 U r i E n c o d e d = e n c o d e U R I C o m p o n e n t ( h m a c . d i g e s t (’

b a s e 6 4 ’) ) ; 233

234 // C o n s t r u c t a u t h o r i z a t i o n s t r i n g

235 var t o k e n = " S h a r e d A c c e s s S i g n a t u r e sr = " + r e s o u r c e U r i + " &

sig = "

236 + b a s e 6 4 U r i E n c o d e d + " & se = " + e x p i r e s ;

237 if ( p o l i c y N a m e ) t o k e n += " & skn = "+ p o l i c y N a m e ; 238 r e t u r n t o k e n ;

239 };

240

241 // S e n d f i r m w a r e u p d a t e s t a t u s to the hub 242 f u n c t i o n i n i t i a l i z e S t a t u s ( t w i n ) {

243 var p a t c h = {

244 c l a s s D e v i c e : c o n f i g . D E V I C E . c l a s s D e v i c e , 245 f i r m w a r e : {

246 f w V e r s i o n : c o n f i g . D E V I C E . f i r m w a r e V e r s i o n ,

247 }

248 };

3.5 – Il codice - Lato device

249 t w i n . p r o p e r t i e s . r e p o r t e d . u p d a t e ( patch , f u n c t i o n( err ) {

250 if( err ) {

251 c o n s o l e . log (’ E r r o r d u r i n g the r e p o r t i n g of the p r o p e r t i e s ’ + err ) ;

252 r e t u r n new E r r o r ( err ) ;

253 }

254 }) ;

255 }

Listing 3.15. Codice Javascript per il file device.js

Le righe 1-9 rappresentano gli import del progetto del device: fs è la libre-ria nativa di Javascript che permette l’interfaccia di lettura/scrittura con i file ed è utilizzata per creare uno streaming di chunks4 durante la scrittura del file d’aggiornamento. La libreria azure-iothub è la stessa utilizzata nel blocco hub.js ma qui verrà utilizzata lato front-end. azure-iot-device è la SDK che permette di implementare la messaggistica e la comunicazione tra il device e l’hub: in particolare la classe Client specifica che si vuole met-tere in comunicazione un dispositivo che avrà bisogno di un’autenticazione.

[29] Come specificato nella sezione relativa ai protocolli per l’IoT hub, la scelta è ricaduta sul protocollo MQTT; si utilizzerà quindi la libreria azure-iot-device-mqtt con il suo modulo Mqtt che fornirà l’implemetazione del protocollo MQTT per il device. Si è utilizzata una libreria crypto per gene-rare un SAS token in grado di fornire un accesso sicuro e veloce al dispositivo ogni volta che deve effettuare una connessione. [30] Oltre alle librerie, si im-porta anche il file di configurazione mostrato in precedenza e jsonManager.js che è stato scritto per facilitare il salvataggio e la lettura del file in cui viene archiviato il token necessario per la connessione.

Osservazione 3 Si è scelto di archiviare il SAS token dei dispositivi in un file locale differente da quello di configurazione per fare in modo che, in applicazioni reali, sia il dispositivo a scegliere una locazione della memoria sicura in cui salvare il token.

La prima azione che il device deve effettuare quando allaccia una comunica-zione con l’IoT hub è quella di iscriversi al registro delle identità dell’hub:

per realizzare questa operazione è necessario utilizzare il metodo Registry e passare la stringa di connessione dell’IoT hub. Se la connessione esiste e la stringa di connessione è valida, diventa possibile richiamare il back-end

4Blocchi di memoria ad allocazione dinamica.

attraverso le opzioni del file di configurazione dell’API registryDevice. All’in-terno della richiesta, viene analizzato lo status code della risposta (rigo 18) e tramite un costrutto switch si analizzano le possibili opzioni:

• 201: il dispositivo non esisteva nel registro delle identità e l’IoT hub può iscriverlo per la prima volta. Si lancia una funzione registryNewDevice, descritta al rigo 73, la quale processa la risposta dell’API registryDe-vice; se la risposta del server contiene al suo interno un endpoint di connessione, allora il device può registrarsi all’iot hub. La registrazione avviene tramite il metodo create che indica all’hub di iscrivere il nuovo dispositivo nel registro delle identità. Una volta che la registrazione sa-rà completata, se l’hub invia una risposta ed è presente un parametro chiamato deviceInfo, allora la funzione va avanti. deviceInfo è un pa-rametro generato dalla libreria iot-hub per il device al momento della registrazione e comunica il tag con cui è stato registrato il device, lo stato attuale della connessione tra dispositivo e cloud, il numero dei messaggi scambiati e, in particolare, due chiavi simmetriche generate al momento della registrazione. Firmando un endpoint di connessione attraverso una di queste chiavi, il device potrà autenticarsi all’hub e comunicare. Per questo motivo al rigo 87 si genera un SAS token basandosi su questi due parametri, fornendo una policy di default per la lettura e scrittura dei messaggi e un tempo di validità pari a 120 minuti; quest’ultimo fatto implica la necessità di salvare il token in un file locale e leggerlo se è ancora valido. Al rigo 89 si procede alla creazione di un file JSON locale impostando l’endpoint, la chiave primaria simmetrica ed il sas token ap-pena generato: il tutto viene scritto attraverso il metodo writeJson del file jsonManager (il metodo stringify permette di trasformare il JSON in una stringa salvarlo come tale). A questo punto la funzione aprirà la connessione attraverso il metodo fromSharedAccessSignature fornen-do come parametri il token appena generato ed il protocollo MQTT. Se la connessione è stata autenticata, la promise diventerà fullfilled e ritor-nerà un oggetto client da utilizzare per le operazioni di aggiornamento, altrimenti ritornerà gli errori.

Tornando al rigo 23, se la promise è stata risolta positivamente, si lancia una nuova funzione createTwin a cui viene passato il parametro client.

La funzione createTwin viene definita al rigo 117 e apre la connessione client tramite il comando open e, se non c’è stato errore, acquisisce il mo-dello del dispositivo gemello del device tramite il comando getTwin: se il

3.5 – Il codice - Lato device

dispositivo gemello non è stato acquisito, si ritorna un errore, altrimen-ti si procede ad inizializzare il twin. La funzione inialtrimen-tializeStatus viene definita al rigo 242: essa riceve in ingresso l’oggetto twin e costruisce una patch d’inizializzazione partendo dalla classe del dispositivo e dal-la versione del firmware instaldal-lata dal costruttore. La funzione richiama il percorso delle reported properties dall’oggetto twin ed utilizza il metodo update per caricare la patch. Nel caso in cui il caricamento sia fallito, viene riportato un errore.

Dopo aver inizializzato le proprietà segnalate, al rigo 133 il device rileva se avvengono delle modifiche da parte del back-end sulle proprietà desi-derate: se ciò avviene nel campo firmware, viene eseguito un controllo sullo status. Il controllo sullo status rileva se il messaggio corrisponde alla stringa available: se esiste corrispondenza, al rigo 138, il device fa una richiesta all’API getAvailableFirmware attraverso i parametri speci-ficati precedentemente nel file di configurazione. Se il codice di risposta dell’API è un 200, il device potrà avere accesso alla risorsa necessaria per l’aggiornamento; viene quindi aperto uno stream per la scrittura del nuovo file attraverso il metodo createWriteStream della libreria fs e vie-ne effettuata una richiesta al blob storage attraverso l’URI firmato col SAS token e attraverso un metodo pipe viene inserita all’interno dello stream di scrittura. Al rigo 146 si attende il salvataggio del file, quindi si controlla se è occorso un errore durante la fase di scrittura e, in caso di successo, viene stampato a schermo un messaggio con l’indicazione sulla nuova versione. Il device riporta a questo punto la notifica del ricevuto aggiornamento all’hub andando a modificare le reported properties tramite il metodo update indicando la versione appena scaricata. La fun-zione si chiude con la gestione degli errori dovuta al download del nuovo file e alla modifica delle proprietà del dispositivo gemello.

• 202: il dispositivo era già presente nel registro delle identità e può quindi procedere direttamente con la comunicazione; tramite il metodo readJ-son al rigo 39, si legge il file di testo in cui era stato archiviato il SAS token e, in caso di stato fullfilled della promise, si ricostruisce l’oggetto client tramite il metodo fromSharedAccessSignature passando nuovamen-te il token ed il protocollo come parametri. Nel caso in cui il token sia scaduto, bisogna generarne uno nuovo; si procede leggendo la chiave pri-maria dal file di testo e la si passa al metodo generateSasToken assieme all’endpoint, alle policy di default e al tempo di vita del token. Una vol-ta rigenerato, si procederà a controllare il parametro svol-tate dell’oggetto

client per verificare se la connessione ha avuto successo: se il parametro riporta lo stato disconnected, il token è scaduto e bisogna generarne uno nuovo col metodo generateSasToken ed i parametri specificati in precedenza. Sia nel caso in cui il token sia scaduto, sia nel caso in cui sia ancora valido, si richiamerà una funzione checkTwin definita al rigo 176.

La funzione prende l’oggetto client da cui chiama il metodo getTwin per individuare, anche in questo caso, la presenza di modifiche al cam-po firmware delle desired properties: nel caso in cui sia rilevata una modifica, si controlla lo status del campo firmwareUpdate e, se risulta come available, e si effettua una richiesta GET alla getAvailableFirm-ware. Se la risposta dell’API è un 200, si procede anche in questo caso al download della risorsa dallo storage con la stessa metodologia illustrata nell’altro ramo. Quando il download è stato completato, il device scrive nelle reported properties la nuova versione. In coda alla funzione av-viene, come nel resto del progetto, la gestione degli errori con i relativi messaggi.

• Default: il codice inviato dal server è sconosciuto e non interpretabile dal device e viene stampato un messaggio con il body della risposta.

La funzione definita al rigo 221 permette la realizzazione di una firma di accesso condiviso: l’URI passato come stringa di testo viene trasformato con codifica URI e il tempo in minuti, passato come parametro, viene convertito in secondi prendendo in considerazione come base dei tempi la data attuale ottenuta tramite Date.now. La data di validità viene quindi approssimata tramite il metodo ceil della libreria nativa Math di Javascript; si costruisce quindi la stringa da firmare con il token, unendo l’URI e il tempo di validità. A questo punto si richiama la libreria crypto ed il suo metodo createHmac che consente la creazione di un oggetto hmac 5, criptato da un algoritmo di hash che crea un’impronta non invertibile, a 256 bit, utilizzando la chiave primaria fornita come parametro d’ingresso. Al rigo 230, tramite il metodo update dell’oggetto hmac, si unisce all’impronta già creata le stringhe dell’URI e del tempo di validità. A questo punto si può generare l’URI firmato tramite la struttura illustrata alle righe 235-236 e ritornare dalla funzione il valore ottenuto.

5eyed-Hash Message Authentication Code

3.5 – Il codice - Lato device

Documenti correlati