Month: August 2013

M2Mqtt library finalmente anche su Nuget !

m2mqtt_nuget

Oggi ho pubblicato la mia libreria M2Mqtt su Nuget, oltre ad essere già disponibile da tempo su CodePlex.

Ho incluso gli assembly compilati per il .Net Framework 4.0 e 4.5 e per il .Net Micro Framework 4.2 e 4.3.

Spero di aver fatto cosa gradita per coloro che sino ad oggi l’hanno utilizzata scaricando i sorgenti direttamente da CodePlex.

Advertisements

Il client M2Mqtt su Ubuntu ? Con Mono si può !

Nonostante la mia libreria M2Mqtt sia scritta in C#, per cui ne è garantito il funzionamento su tutte le versioni del .Net Framework in ambiente Microsoft Windows, è assolutamente possibile utilizzarla anche su Linux attraverso il runtime del Mono Project.

In primo luogo, ho preparato l’ambiente utilizzando come distribuzione Linux quella più famosa e maggiormente usata nell’ambito desktop : Ubuntu (in particolare la 12.04 LTS). Il sistema operativo non fornisce nativamente il supporto per Mono, che è necessario scaricare ed installare attraverso il gestore di pacchetti Synaptic oppure attraverso il terminale mediante il seguente comando :

sudo apt-get install mono-complete

mono-complete

Il pacchetto mono-complete installa praticamente tutto, sia il runtime che le librerie per lo sviluppo delle applicazioni basate su tale framework.

Successivamente, ho scelto l’IDE MonoDevelop per poter compilare la libreria M2Mqtt con il compilatore di Mono e per poter realizzare una semplice applicazione console di test. Anche in questo caso, possiamo fare uso di Synaptic oppure del comando :

sudo apt-get install monodevelop

Sfruttando questo IDE ho creato una nuova solution ed un nuovo file di progetto che ho prontamente caricato su CodePlex, in modo che attualmente la libreria sia perfettamente compilabile sia con le versioni del .Net Framework (Desktop, Compact e Micro) che con Mono in ambiente Linux.

Per eseguire i test, ho deciso di non utilizzare il solito RSMB della IBM (sotto Windows) ma il broker Mosquitto, anch’esso a disposizione nei repository di Ubuntu e quindi facilmente installabile da Synaptic oppure attraverso :

sudo apt-get install mosquitto

sudo apt-get install mosquitto-clients

mosquitto

Il pacchetto mosquitto installa il broker mentre mosquitto-clients installa due client di esempio (mosquitto_pub e mosquitto_sub) per la pubblicazione e sottoscrizione di messaggio al broker stesso. Dopo averlo installato, non è necessaria alcuna configurazione, in quanto il broker viene automaticamente avviato ed è subito in ascolto sulla porta MQTT di default, ossia la 1883.

using System;
using uPLibrary.Networking.M2Mqtt;
using System.Net;
using System.Text;

namespace M2MqttTest
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			MqttClient client = new MqttClient(IPAddress.Parse("192.168.1.4"));
			client.Connect("testmono");

			client.MqttMsgPublishReceived += HandleClientMqttMsgPublishReceived;
			client.Subscribe(new string[] { "sensors/temp" }, new byte[] { 1 });

			//client.Publish("sensors/temp", Encoding.UTF8.GetBytes("35"), 1);

			Console.ReadLine();

		}

		static void HandleClientMqttMsgPublishReceived (object sender, uPLibrary.Networking.M2Mqtt.Messages.MqttMsgPublishEventArgs e)
		{
			Console.WriteLine(Encoding.UTF8.GetString(e.Message));
		}
	}
}

L’applicativo console, realizzato con MonoDevelop, è alquanto banale, in quanto si connette al broker (mosquitto in questo caso) e si sottoscrive al topic “sensors/temp”, volendo simulare che si sia in “ascolto” di un sensore che pubblichi dei valori di temperatura. Il publisher è simulato mediante l’utilizzo del client mosquitto_pub con la semplice riga di comando :

mosquitto_pub –t sensors/temp –q 1 –m 32

Dove il parametro “t” identifica il topic, “q” indica il QoS secondo il protocollo MQTT ed “m” il messaggio da trasmettere (in questo caso un valore di temperature, es. 32 °C).

Dall’immagine che segue, si osserva come il risultato sia correttamente acquisito e visualizzato sulla console dall’applicativo di test che fa uso della mia libreria.

example_sub

Allo stesso modo, è possibile utilizzare l’applicativo di test come publisher ed il client mosquitto_sub per ricevere i messaggi, attraverso il comando seguente :

mosquitto_sub –t sensors/temp –q 1

example_pub

In conclusione, nonostante si trovino in rete degli ottimi client MQTT che possono essere usati senza problemi su Linux (la stessa libreria di Mosquitto oppure tanti altri scritti in in C++ o Python), per chi lo volesse può continuare ad usare la mia libreria grazie al supporto di Mono. Il prossimo passo può essere quello di utilizzare questa libreria su un sistema embedded basato su Raspberry Pi !

M2Mqtt client : un “piccolo” ma utile aggiornamento

Ho effettuato un “piccolo” aggiornamento alla mia libreria relativa al client MQTT (adesso alla versione 1.1.0.0), aggiungendo un ulteriore costruttore della classe MqttClient che prevede in ingresso il nome host del broker (aggiungendosi quindi al costruttore che prevede solo l’indirizzo IP). Tale costruttore può essere utile in tutti quei casi in cui si usa un broker MQTT pubblico, come ad esempio il server di test Mosquitto che è all’indirizzo test.mosquitto.org.

public static void Main()
{
    MqttClient client = new MqttClient("test.mosquitto.org");
    ...
    ...
}

uCloudy : l’accesso al cloud dal .Net Micro Framework è servito!

2728.ucloudy_thumb_55C1D3A0

Questa è la volta di un progetto completamente dedicato al Cloud ma sempre con l’obiettivo di fornire ulteriori funzionalità e potenzialità ad un sistema embedded.

uCloudy è infatti una libreria che ha come obiettivo quello di mettere a disposizione una serie di client per il .Net Micro Framework per la connessione ai principali servizi Cloud. Il primo e per adesso unico servizio supportato in questa prima release è Windows Azure Mobile Services.

Come ben sappiamo, la Microsoft fornisce una serie di SDK per poter usufruire di questo servizio all’interno delle applicazioni Windows Store, Windows Phone, iOS, Android e Web. Io ho cercato di portare questa funzionalità anche nei sistemi embedded dotati di .Net Micro Framework. Tutto ciò è stato reso possibile grazie all’interfaccia RESTful che i mobile services forniscono per potersi interfacciare ad essi. Grazie al client HTTP che ho ultimamente integrato nella uPLibrary, ho realizzato una serie di classi attraverso le quali poter eseguire le quattro operazioni principali sulle tabelle dei mobile services : insert, update, delete e query.

Il client in questione è implementato attraverso la classe MobileServiceClient alla quale, attraverso il costruttore, è necessario fornire l’URI dell’applicazione (es. <miapplicazione>.azure-mobile.net) ed una delle chievi (master key o application key) oppure un authentication token, per poter stabilire i permessi con cui il client stesso può effettuare le operazioni.

L’unico metodo fornito dal client è GetTable() al quale è necessario passare il nome della tabella sulla quale voler effettuare un’operazione, per vedersi ritornare un oggetto che implementa l’interfaccia IMobileServiceTable e sul quale è possibile invocare i seguenti metodi :

  • Insert : per inserire una riga nella tabella attraverso un oggetto IMobileServiceEntity;
  • Update : per aggiornare una riga nella tabella attraverso un oggettoIMobileServiceEntity;
  • Delete : per cancellare una riga nella tabella fornendone l’ID;
  • Query : per eseguire una query nella tabella;

Ogni oggetto che viene mappato su una riga di una tabella deve implementare l’interfacciaIMobileServiceEntity, il cui metodo principale è ToJson() che deve restituire la rappresentazione JSON dell’oggetto comprensiva del relativo ID. Non ho volutamente realizzato una classe base (astratta) con un’implementazione di questo metodo che si basasse sulla Reflection, per evitare inutili rallentamenti a runtime. In questi casi, è più performante implementare il metodo nella propria classe conoscendone direttamente i campi.

Immaginiamo che il nostro oggetto da mappare sia il seguente :

public class MockEntity : IMobileServiceEntity
{
    public int Id { get; set; }

    public string FieldA { get; set; }
    public int FieldB { get; set; }

    public string ToJson()
    {
        return "{ \"FieldA\" : \"" + FieldA + "\", \"FieldB\" : " + FieldB + "}";
    }

    public void Parse(string json)
    {
        throw new NotImplementedException();
    }
}

Come si può osservare, il metodo ToJson() è semplice ed immediato da eseguire, in quanto non fa uso della reflection, in quanto i campi sono assolutamente noti al momento dell’implemetazione.

public static void Main()
{
    Uri appUri = new Uri("http://myapp.azure-mobile.net");

    MobileServiceClient client = new MobileServiceClient(appUri, "applicationkey");

    // insert records
    client.GetTable("mock").Insert(new MockEntity() { FieldA = "Temp1", FieldB = 100 });
    client.GetTable("mock").Insert(new MockEntity() { FieldA = "Temp2", FieldB = 200 });
    client.GetTable("mock").Insert(new MockEntity() { FieldA = "Temp3", FieldB = 300 });
    client.GetTable("mock").Insert(new MockEntity() { FieldA = "Temp4", FieldB = 400 });

    // delete id = 1
    client.GetTable("mock").Delete(1);

    // update record id = 2
    MockEntity mock = new MockEntity() { Id = 2, FieldA = "Temp2_update", FieldB = 201 };
    client.GetTable("mock").Update(mock);

    // query
    client.GetTable("mock").Query("$orderby=FieldB");
}

Dall’esempio di utilizzo, si evince che il client rispecchia in parte la corrispondente versione presente negli SDK forniti dalla Microsoft.

Ovviamente, la storia di questa libreria è appena iniziata e l’obiettivo è di integrarla nel tempo con ulteriori client per l’accesso ad altri servizi Cloud !

Un micro client HTTP nella uPLibrary !

Non mi fermo mai ed anche ora che sono in ferie continuo a …. programmare !

Questa volta tocca alla mia uPLibrary che ho aggiornato alla versione 2.0 (ovviamente anche su Nuget con il supporto a ben tre versioni del .Net Micro Framework, dalla 4.1 all’attuale 4.3) con un nuovo componente : un client HTTP.

Tutti vi starete facendo delle domande sul perché della necessità di riscrivere un client HTTP considerando che esistono le già ampiamente collaudate classi HttpWebRequest edHttpWebResponse direttamente incluse nel .Net Micro Framework. Ebbene, in alcune board con poca memoria (vedi Netduino), gli assembly relativi a queste due classi occupano troppo spazio e lavorando con degli stream sono poco performanti. Per questo motivo, ho deciso di realizzare un semplice client (ogni consiglio per il suo miglioramento è ben accetto) che sfrutta direttamente le socket senza alcuno strato intermedio di astrazione (concetto che molte volte nei sistemi embedded bisogna limitare per migliorare le performance).

Il modello di programmazione è abbastanza semplice, in quanto prevede l’uso della classeHttpClient che mette a disposizione i tre seguenti metodi principali :

  • Send() : per eseguire una generica richiesta HTTP (GET, POST, PUT, …);
  • Get() : metodo ad hoc per eseguire richieste di tipo GET;
  • Post() : metodo ad hoc per eseguire richieste di tipo POST;

Il metodo Send() riceve in ingresso un oggetto di tipo HttpRequest nel quale vanno specificati tutti i dati che compongono la richiesta (metodo HTTP, URI di destinazione ed eventuali headers). Esso ritorna un oggetto di tipo HttpResponse con tutte le informazioni sulla risposta ricevuta dal server. Per poter gestire la ricezione di un body (nel caso di GET) o l’invio (nel caso di POST o PUT), è possibile utilizzare i seguenti due eventi che la classe espone :

  • RecvBody : sollevato nel momento in cui ci sono dati nel body in ricezione e possono essere acquisiti;
  • SendBody : sollevato dal client solo nel caso in cui c’è un event handler registrato, che sancisce la volontà di voler trasferire dei dati al client attraverso il body;

In caso di ricezione, l’event handler riceve in ingresso l’oggetto HttpResponse attraverso il quale poter accedere alla proprietà Body su cui invocare il metodo Read(), che legge i dati direttamente dalla socket restituendoli in un buffer da noi specificato. L’evento viene sollevato più volte fino al completamento del body.

In caso di invio, l’event handler riceve in ingresso l’oggetto HttpRequest attraverso il quale poter accedere sempre alla proprietà Body su cui invoare il metodo Write() al quale poter passare un buffer con i dati da scrivere sulla socket sottostante. Questo evento viene sollevato una sola volta dal client, per cui è necessario effettuare al suo interno eventualmente più chiamate su Body.Write() fino alla completa trasmissione del body desiderato.

Di seguito è riportato un banalissimo esempio per ricevere la pagina del sito Microsoft.

public static void Main()
{
    HttpRequest req = new HttpRequest();
    req.Method = HttpMethod.Get;
    req.Uri = new Uri("http://www.microsoft.com");
    req.Headers.Add("Accept", "text/html");

    HttpClient client = new HttpClient();
    client.RecvBody += client_RecvBody;
    client.Send(req);
}

static void client_RecvBody(HttpResponse httpResp)
{
    byte[] buffer = new byte[1024];
    int read = httpResp.Body.Read(buffer, 0, 1024);
    Debug.Print(new String(Encoding.UTF8.GetChars(buffer)));
}
I metodi Get() e Post() sono banalmente due wrapper del metodo Send() che servono solo a semplificare le operazioni più comunemente eseguite, appunto GET e POST. Entrambe ricevono l’URI verso il quale effettuare la richiesta (senza la necessità di “riempire e passare” un oggetto HttpRequest , lo faranno loro per noi) e l’event handler per eseguire la ricezione del body (in caso di GET) o l’invio (in caso di POST).

Riprendendo l’esempio precedente, attraverso il metodo Get() avremmo il seguente codice.

public static void Main()
{
    HttpClient client = new HttpClient();
    client.Get("http://www.microsoft.com", client_RecvBody);
}

Nel caso di collegamento ad un servizio REST al quale dover trasmettere dei dati, possiamo pensare ad un utilizzo di questo tipo.

public static void Main()
{
    HttpClient client = new HttpClient();
    client.Post("http://myserver/api/", client_SendBody);
}

static void client_SendBody(HttpRequest httpReq)
{
    byte[] buffer = Encoding.UTF8.GetBytes("");
    httpReq.ContentLength = buffer.Length;
    httpReq.Body.Write(buffer, 0, httpReq.ContentLength);
}