La scorsa settimana ho partecipato in qualità di speaker a WPReborn, un evento organizzato dalla Community DotNetLombardia presso la sede Microsoft di Milano.

Come indica il nome l’evento poneva l’accento su Windows Phone ed in particolare tutte le novità che WP8 ha portato ma anche parecchi aspetti che di solito vengono meno trattati.

Il mio speech riguardava le applicazioni Enterprise su WP8.

In particolare ho sviluppato la demo applicativa di una app per la gestione dei parcheggi a pagamento cittadini, con relativa stampa del ticket relativo alla sanzione di parcheggio.

Questo tipo di applicazioni sono ovviamente sotto I nostri occhi tutti I giorni, ma ovviamente (per ora) non ce ne sono per Windows Phone.

Vorrei condividere la mia esperienza relativa alla connessione della stampante e alla stampa vera e propria dello scontrino.

Partiamo parlando della stampante: ho utilizzato una Custom MY Printer Bluetooth.

La azienda ha recentemente annunciato il supporto per Windows Phone 8 e dovrebbe rendere disponibile un piccolo SDK per interfacciarsi alla stampante.

Visto che io non avevo ancora a disposizione l’SDK del costruttore, ho seguito un approccio “a mano”.

Connessione e comunicazione

La connessione con la stampante avviane tramite Bluetooth che deve (ovviamente) essere attivato sul telefono e stabilita una relazione con la stampante.

imageA questo punto nella applicazione possiamo ricercare i device Bluetooth disponibili (e connessi) tramite il seguente:

 1:  PeerFinder.AlternateIdentities["Bluetooth:PAIRED"] = "";
 2:             try
 3:             {
 4:                 IReadOnlyList<PeerInformation> devices =
 5:          await PeerFinder.FindAllPeersAsync();

 

La lista che otteniamo potrà essere scandita per cercare il device per nome (nel mio caso cercavo nel nome del device la stringa “MY”Printer”.

A questo punto siamo in grado di aprire effettivamente il canale di comunicazione con il dispositivo:

 1:    this.btsocket = new StreamSocket();
 2:    try
 3:    {
 4:        await this.btsocket.ConnectAsync
 5: (hname, "{00001101-0000-1000-8000-00805F9B34FB}");
 6:    }
 7: ...
 8:    if (this.btsocket != null)
 9:    {
 10:        this.txData = new DataWriter
 11:           (this.btsocket.OutputStream);
 12:        this.rxData = new DataReader
 13:           (this.btsocket.InputStream)
 14:    }

 

E successivamente creare un DataWriter ed un DataReader che utilizzeremo per scrivere e leggere sulla stampante.

Stampiamo

A questo punto inizia la parte “divertente”, ovvero inizieremo a mandare stringhe alla stampante che verranno impresse sulla sottile striscia di carta termica.

C’è da tenere conto che la stampante funziona in emulazione ESC/POS e pertanto è possibile cambiare la tipologia del carattere, allargarlo, allungarlo o stampare in negativo semplicemente inviando gli opportuni caratteri di controllo prima della stringa da stampare.

Ad esempio per stampare in modalità negativa è sufficiente inviare la sequenza esadecimale “1D” “42” “01” seguito dalla stringa da stampare, successivamente invieremo la sequenza “1D” “42” “00” che disabiliterà questa modalità, ovvero:

 1: txData.WriteBytes(Cmd_ALTCMD);
 2: txData.WriteBytes(Cmd_Inverse);
 3: txData.WriteBytes(Cmd_ON);
 4: txData.WriteString("| Enterprise APP on WP8 |");
 5: txData.WriteBytes(Cmd_CommandLF);
 6: txData.WriteBytes(Cmd_ALTCMD);
 7: txData.WriteBytes(Cmd_Inverse);
 8: txData.WriteBytes(Cmd_OFF);
 9:  
 10: await (IAsyncOperation<uint>)
 11:    txData.StoreAsync();

 

dove I vari “Cmd…” sono definiti nel seguente modo:

 1: byte[] Cmd_CommandLF = new byte[] { 10 };
 2: byte[] Cmd_ESC = new byte[] { 27 };
 3: byte[] Cmd_ALTCMD = new byte[] { 29 };
 4: byte[] Cmd_Enlarged = new byte[] { 69 };
 5: byte[] Cmd_ON = new byte[] { 1 };
 6: byte[] Cmd_OFF = new byte[] { 0 };
 7: byte[] Cmd_Inverse = new byte[] { 66 };
 8: byte[] Cmd_ModoStampa = new byte[] { 33 };
 9: byte[] Cmd_D_LargALT = new byte[] { 48 };
 10: byte[] Cmd_D_LargALT_font2 = new byte[] { 49 };
 11: byte[] Cmd_D_Larg = new byte[] { 32 };
 12: byte[] Cmd_D_Alte = new byte[] { 16 };

 

La chiamata a “StoreAsync()” prende lo stream di dati precedentemente predisposto e lo invia (in maniera asincrona) alla stampante.

Questo approccio ovviamente ci riporta indietro di parecchi anni quando per programmare un report bisognava impazzire fra codici di controllo e salti riga in una impari lotta giornaliera.

Discorso analogo, ma molto più complicato per quanto riguarda la stampa di immagini o grafiche personalizzate, in questo caso infatti l’immagine da stampare (ovvero la sua rappresentazione a mappa di bit) deve essere scomposta in “strisce” di bit rappresentanti l’immagine ed inviati a pacchetti secondo una specifica sintassi.

In questi giorni ho ricevuto dal produttore la conferma della disponibilità a breve dell’SDK completo per la stampante in cui sarà possibile stampare una bitmap partendo direttamente da dal file e senza necessità di fare conversioni di nessun tipo.

 

UPDATE: La Custom ha pubblicato una applicazione di prova sullo store per WP8 che permette di testare le funzionalità di stampa testuale e grafica della stampante in maniera molto intuitiva, la potete trovare a questo link.

Tagged with: