Le Post de MCNEXT

Les articles des consultants de MCNEXT

Bienvenue sur le Post de MCNEXT !

MCNEXT

  • Retrouvez ici les posts des consultants du groupe MCNEXT ( déjà plus de 500 !)
  • Vous voulez en savoir plus sur MCNEXT ou vous souhaitez nous rejoindre ?
  • Consultez notre site corporate ici
    Suivez nous sur twitter: @LE_FIL_MCNEXT 
    Regardez nos videos sur notre chaîne YouTube McnextTV

 

How to use WinJS resources with a Cordova App

If you need to use WinJS resources in a cordova app, you have to load them manually and that is very simple !

You only have to read the ‘good’ resjson (the file that matches your language) before you call WinJS.UI.processAll  and set the global « strings » variable.

In our apps we use this method to load resources:

var loadLocalRessources = function (language) {
   language = language || 'en';
    return new WinJS.Promise(function (complete, error) {
        var url = './strings/' + language + '/resources.resjson';
        console.log('trying to load resources from ' + url);

        WinJS.xhr({ url: url }).then(function (res) {
            console.log('resource ok for ' + language);
            try {
                window.strings = JSON.parse(res.responseText);
            } catch (exception) {
                console.error('resource parse error ' + exception.message);
            }
            complete(window.strings);
        }, function (err) {
            console.error('resource load error for ' + language + ' ' + err.statusText);
            if (language != 'en') {
                data.loadLocalRessources('en').then(complete, error);
            }
            else {
                error(err);
            }
        });
    });

}

La serre Connectée d-meter


Logo du projet d-meter

D’abord je voudrais clarifier le nom : Demeter est la déesse grecque de la moisson et de la fertilité des graines.

D-Meter est un projet qui a démarré autour d’une table, pendant un après-midi classique de Janvier à Paris, sous la pluie. On cherchait un sujet pour travailler sur le thème des objets connectés, quelque chose à la fois utile, facile et simple. Le résultat : une serre d’intérieur connectée !

 

Right place, right time

L’idée tombait bien, puisqu’au même moment le Hackathon “Zone 61” était lancé pour mi-janvier 2015. Il fallait donc se dépêcher et affiner le concept.

 

Pourquoi une serre ?

Pour plein de raisons :

  • Pour avoir un petit coin bio dans un appartement sombre, typiquement parisien, et participer au mouvement de l’agriculture dans la ville
  • Pour s’étonner à chaque fois de la croissance des plantes. Et faire découvrir la nature aux enfants, chez vous directement. Regardez les photos, avec 3 jours d’écart, sans engrais, sans miracles :

d-meter, ça pousse !

  • Pour avoir une base de recherche sur l’IoT et le Cloud
  • Pour ne pas avoir à s’occuper des plantes, et chercher à automatiser la problématique avec l’aide du Cloud
  • Etc.

 

Pourquoi le Cloud (Azure) ?

L’utilisation du Cloud peut sembler au départ comme inutile. Mais rappelons-nous d’un schéma assez plébiscité par Microsoft par rapport à l’IoT :

IOT selon Microsoft

(Source : « Embarquez pour l’Internet des objets avec Microsoft », Microsoft, 16 déc. 2014)

On voit bien deux sens :

  • l’information qui remonte dans le Cloud pour mieux la comprendre
  • l’information qui redescend vers le device pour le piloter

Dans le cas de notre serre, l’intérêt du Cloud est de stocker et analyser les données, puis piloter la serre, avec un algorithme qui va s’améliorer au fil du temps. Le gain pour l’utilisateur de la serre est que, sans avoir la moindre connaissance en agronomie, il pourra avoir un paramétrage éprouvé pour la croissance de ses plantes :

  • par les autres utilisateurs de la plateforme (le coté social)
  • par des algorithmes prédictifs (avec du Machine Learning)

La serre doit donc être capable de :

  • relever les informations (température, humidité, éclairage…)
  • automatiser les réglages (arrosage, éclairage…)

 

Le hardware

La construction de la serre était le premier point. On a pris du bois (prix, facilité de découpe, coté naturel) et du plexi (sécurité des enfants, facilité de découpe). La taille choisie (environ 60x60x40cm) doit permettre son utilisation dans des endroits étroits, sans pour autant empêcher la croissance des plantes moyennes.

Initialement avec la V1, pour le début du hackathon, on est parti sur une carte Micro Framework GHI Panda 2, avec un écran tactile (FEZ Touch), une carte réseau (FEZ Connect) et deux capteurs (température et éclairage). Pour prouver le concept, la carte a rempli parfaitement son devoir :

  • super vitesse de développement, c’est l’avantage du Micro Framework par rapport à d’autres plateformes, debugage dans Visual Studio, fiabilité, etc. Pour ceux qui ont des doutes entre les différentes plateformes, on a gagné énormément du temps avec cette infrastructure. Et on n’est pas les seuls à avoir cet avis: http://blog.ianlee.info/2015/01/gadgeteer-vs-arduino-vs-phidgets.html
  • le prix était raisonnable. Plus cher que l’Arduino, mais pas tant que ça.

 

Une fois la phase initiale du hackathon finalisée, les limitations nous ont fait migrer vers une solution plus scalable, tout en restant sur du Micro Framework :

  • une carte GHI Gadgeteer Hydra
  • une carte réseau ENC28
  • un écran tactile TE35
  • un capteur numérique (précis !) pour la température et l’humidité de l’air SI70
  • un capteur pour l’humidité du sol
  • une camera L2
  • des « break-out » boards (on verra plus tard pourquoi)
  • et bien sûr un module d’alimentation Gadgeteer

Le tout se base sur le système Gadgeteer. C’est un système facile à connecter, avec une intégration assez élevée dans Visual Studio. On peut connecter les modules visuellement directement dans l’IDE :

d-meter, schéma gadgeteer

Maintenant pour le petit bémol :

  • Depuis la version 4.3 le Micro Framework et le Gadgeteer GHI, on rencontre quelques petits soucis… Espérons qu’ils vont corriger les choses au plus vite. C’était la mauvaise surprise par rapport à la carte V1 que je connais depuis un bon moment, et qui a toujours été un exemple de simplicité lors de son utilisation.
  • Trouver l’ensemble des composants Gadgeteer dans le même magasin n’était pas possible. La plateforme Gadgeteer existe depuis 2012, mais comme le prix est assez élevé, les ventes ne justifient pas des stocks importants. Du coup il faut faire le tour des classiques : Farnell, Mouser, Lextronic, CoolComponents, etc.
  • Le prix. Ouch…

Pour la partie « commande », il nous a fallu :

  • Une petite pompe d’aquarium. Elle fonctionne en 220V, donc la carte Micro Framework doit couper/brancher un relais, et on a pris un relais en 5V pour simplifier le circuit.
  • Des spots, ou plutôt des leds, un sur lumière chaude et un sur lumière froide. Un socle G10 / 5.5W. L’arrêt/allumage se fait également via un relais.

Rajoutez en plus :

  • Un câble d’alimentation avec un interrupteur
  • Un chargeur de Nokia 5V / 1,3A (ils sont minuscules et fiables)
  • Un petit boîtier pour isoler la partie 220V

Et voilà nous avons la partie matérielle de la serre.

 

La partie software

Pour la partie software, le projet se décline en plusieurs parties :

  • Du Micro Framework sur la carte Gadgeteer
  • Un Azure Website. Le choix mérite une petite justification.
    • Il faut d’abord savoir que la serre remonte à un intervalle plutôt espacé les informations. On n’est donc pas dans l’urgence, et implicitement, mettre un Event Hub capable d’encaisser plusieurs millions d’appels par seconde n’est pas utile. Pourquoi pas plus tard, quand la serre sera un hit ou juste pour essayer !
    • On compte aussi sur la partie WebJobs pour faire du « stop motion » de la croissance des plantes avec la caméra. Voici un petit aperçu
    • On a voulu avoir un site web depuis le départ. Tout le monde ne veut pas installer une application pour piloter la serre.
    • Rapidité de mise en œuvre. C’est suffisamment scalable et performant pour ne pas avoir besoin d’une usine à gaz.
    • Nous avons besoin d’un scheduler (style Quartz.NET) pour automatiser la serre. Mieux vaut avoir la main là-dessus.
  • Stockage sur SQL Azure. Le volume de lignes de données monte petit à petit, pour analyser les infos c’est mieux d’avoir du potentiel disponible.
  • Stockage Azure. Pour la partie images.
  • Une appli cross-plateform. C’est une appli qui tourne sous Windows, Windows Phone, Android et iOS, grâce à WinJS et Cordova.
  • Une appli native Windows Phone. Pour le fun et parce qu’on sait le faire J !

Le Machine Learning est la prochaine étape, il faut d’abord.qu’on étudie plus en détail les besoins d’analyse.

 

La communication

Premier choix : utiliser les WebSockets entre la serre et Azure (http://jdiwebsocketclient.codeplex.com/). Mais reality check :

  • Pas le temps lors du hackathon
  • Pas la mémoire suffisante sur la V1 de la carte
  • Pas besoin du temps réel
  • Trop risqué (voir les risques avec le NETMF 4.3)

Du coup, pragmatisme à fond, le choix a été de faire du polling Azure. La carte publie les valeurs des capteurs, et récupère en retour les consignes (pompage et éclairage).

Entre le serveur et les apps (et le site), c’est du JSON. Inutile d’expliquer comment utiliser ce genre de flux.

 

Le schéma global est donc :

d-meter, schéma global

L’IHM

Pour l’écran tactile de la serre, le composant qui permet de gagner énormément de temps est GLIDE. Grosso modo, il permet d’avoir des composants graphiques réutilisables, avec un éditeur WYSIWYG :

d-meter-ecran-tactile

L’éditeur a le format suivant :

d-meter, éditeur glide

Clairement rustique, mais pour ceux qui ont l’habitude de faire du micro framework et de galérer sur le positionnement des UI, c’est vraiment une bonne aide. Il suffit de copier le code dans les ressources de l’appli NETMF, et c’est parti.

 

Pour la partie site web, de l’ASP.NET MVC, des WebAPI, un Azure WebSite, des graphiques avec la librairie NV3… Voici un screenshot de l’accueil d’une serre  :

d-meter, le dashboard sur le site web

 

Pour l’application universelle, c’est donc du Cordova avec du WinJS. N’hésitez pas à regarder nos autres articles sur le blog concernant le sujet.

d-meter, sur windows phone

 

Le fonctionnement

A priori, le fonctionnement de la serre est assez facile :

  • On l’allume
  • On la branche au réseau Ethernet de la maison. Elle récupère son IP en dynamique avec du DHCP. En théorie, car avec la ENC28 et la Micro Framework 4.3, le DHCP ne marche pas… Mais les choses vont se corriger petit à petit, Microsoft vient de mettre des ressources sur le NETMF.
  • Et on plante nos graines (disons des « Radis »).

La serre est prévue pour fonctionner d’une manière autonome, à partir d’un profil. C’est-à-dire on choisit le profil « Radis » qui lui-même prévoit des programmes journaliers :

  • Lundi arrosage 500ml, éclairage 8h-22h
  • Mardi éclairage 10-19h
  • Etc.

Le logiciel permet lui bien sûr aussi de générer son propre profil, avec ses propres critères. Mais c’est dommage de ne pas profiter de l’expérience de la communauté !

Il faut juste penser à remplir le réservoir de la pompe pour l’arrosage !

 

L’état d’avancement actuel

Actuellement la serre dans sa V2, a permis de valider le concept de la caméra pour prendre des photos. Le stop motion est un bonus évident.

Malheureusement, le prix énorme du Gadgeteer et le prix dérisoire du Raspberry Pi2 vont nous faire changer de solution pour le Raspberry. La seule chose qui nous manque : le Windows 10 for IoT. Mais il ne devrait pas trop tarder, la carte est déjà achetée.

L’autre chantier est le Machine Learning, pour détecter la croissance de la plante à partir de l’image et ajuster les paramètres de croissance. Nous sommes en pleine récolte (!) d’information, avec une librairie d’images qui s’agrandit constamment et des valeurs qui remontent 24/24.

 

Conclusion

En tant qu’équipe, c’était et c’est toujours un bon projet. On a appris, on s’est éclatés et surtout on s’est confrontés à d’autres problématiques qu’on ne voit pas traditionnellement sur un projet classique.

Il y a eu des déceptions (la partie NETMF 4.3, avec des problèmes, le Gadgeteer…), il y a eu de belles surprises (le Stop Motion, la croissance ultrarapide des plantes), il y a eu du désespoir (faire marcher la caméra et le réseau en même temps sur la carte micro framework), de l’émotion (quand on nous a annoncé qu’on était le “Coup de cœur” Microsoft pour le Hackathon), et surtout de beaux souvenirs.

 

Je souhaite remercier :

  • Cyril pour la partie Azure
  • Mehdi et Guillaume pour la partie Universal Apps
  • David et Edwige pour Windows Phone
  • Julien, Marine et Pauline pour les inputs au niveau du design
  • Hubert, Pierre-Yves (l’idée de la serre) et toute la boite MCNEXT pour le support logistique, moral et financier
  • Ceux qui nous ont encouragé pendant les jours et nuits du hackathon, sur les Techdays ou tout simplement par mail

Croisons les doigts, l’annonce du résultat du hackathon Zone61 est prévue pour le 24 mars. En attendant les radis poussent, la serre fonctionne et il reste de belles choses à découvrir !

Si le sujet vous intéresse, n’hésitez pas à nous faire un signe.

 

Alex.

Café MCNEXT Paris du 19 mars 2015

Café MCNEXT Paris: Le Big Data associé à la BI grâce au Cloud de Microsoft – Jeudi 19 mars 2015 – http://bit.ly/1BGkKT1

EDF, Azure, Windows Phone et du Micro Framework

DISCLAIMER : avant toute chose, l’auteur n’est pas responsable pour toute action, accident, etc. survenue lors du montage, l’installation, l’utilisation, etc. des procédés décrits dans cet article !

L’objet de ce post est de présenter la solution que j’ai pu mettre en place pour récupérer la consommation électrique de la maison en temps réel, et la consulter sur mon Windows Phone.

 

Liste des courses

Pour ceci nous avons besoin :

  • D’un compteur ERDF numérique. Si vous disposez d’un ancien modèle (la version à disque rotatif), vous pouvez demander le changement avec des frais pas trop importants.
  • D’activer l’option « teleinfo » sur votre compteur. Par défaut il est installé.
  • D’un compte Azure pour stocker les informations.
  • D’une carte Micro Framework. Le code en exemple s’applique sur du Micro Framework 4.2.Ma recommandation actuelle est un bon compromis : la FEZ Cerbuino, disponible sur le site du producteur (https://www.ghielectronics.com/catalog/product/473 ).
  • A l’époque où j’ai fait tourner le code, j’ai utilisé un FEZ Domino mais qui n’est plus en vente.
  • D’un petit montage électronique, avec des composants disponibles sur ebay ou chez Farnell/Mouser/etc. Le prix des composants est ridicule :
    • Un optocoupleur SFH620 (j’ai utilisé une Vishay SFH6206-2)
    • 1 résistance 4.7KOhm
    • 1 résistance 1.2KOhm

 

Schéma physique

D’abord pour le montage, nous avons besoin de réaliser le schéma suivant :

schéma électronique

Dans la partie droite du schéma, le montage se branchera sur la carte Micro Framework. A gauche du schéma arrivent les fils reliés à la sortie Teleinfo du compteur électrique (I1 et I2) :

schéma montage

On note :

  • Le branchement en 5V de la carte et du petit montage électronique. Un chargeur USB peut faire l’affaire.
  • La liaison masse sur la carte Micro Framework et du petit montage (GND)
  • La double liaison avec le compteur (I1 et I2)
  • La liaison avec la COM1 IN sur la carte Micro Framework.

 

Le protocole Teleinfo

Peu connu, cette fonctionnalité permet de récupérer en mode port série le flux réel des informations EDF. Les caractéristiques du port exposé par le compteur : 1 200 bps, 7 bit, Parity Even, Stop Bit One.

Pour les trames envoyées, le protocole est plutôt bien documenté :

http://www.planete-domotique.com/notices/ERDF-NOI-CPT_O2E.pdf (documentation « officielle »)

http://bernard.lefrancois.free.fr/teleinfo.htm (exemples de trames)

Personnellement j’ai de l’heure creuse/heure pleine (HC/HP) à la maison, monophasé. Passer dans du triphasé ou autre revient à interpréter les bonnes trames.

 

Le code

Pour la partie code Micro Framework, rien de plus facile :

On commence déjà par se faire une classe qui encapsule les parties qui nous intéressent :

public class EdfReading
{
  public string NoCompteur { get; set; }
  public string PeriodeTarifaireEnCours { get; set; }
  public string PuissanceApparente { get; set; }
  public string IndexHeuresCreuses { get; set; }
  public string IndexHeuresPleines { get; set; }
}

Ensuite on démarre la lecture :

  • déclaration des variables importantes :
const byte startByte = 0x002;
const byte endByte = 0x003;
static Encoding enc = Encoding.UTF8;
static EdfReading currentReading;
  • déclaration du port sériel :
static SerialPort serialPortEdf = new SerialPort("COM1", 1200, Parity.Even, 7);

En plus il faut rajouter dans le Main :

serialPortEdf.StopBits = StopBits.One; // pas accessible dans le constructeur le stopbit… 
InitiateEdfPort();

Cet appel de fonction pointe vers :

private static void InitiateEdfPort()
{
  // ouverture du port
  if (serialPortEdf.IsOpen)
    serialPortEdf.Close();
 
  serialPortEdf.DataReceived += new SerialDataReceivedEventHandler(EdfPacketReceived);
  serialPortEdf.Open();
}

L’interprétation des packets se fait dans EdfPacketReceived, avec un petit bémol :

    static void EdfPacketReceived(object sender, SerialDataReceivedEventArgs e)
    {
        var incoming = new byte[serialPortEdf.BytesToRead];
        serialPortEdf.Read(incoming, 0, incoming.Length);

        if (incoming == null || incoming.Length < 5)
            return; // du bruit sur le reseau….

        if (currentPosition + incoming.Length > cursorByteArray.Length)
        {
            // ah, il y a un probleme... on est au bout du buffer sans pourtant avoir la trame de fin
            currentPosition = 0;
            cursorByteArray = new byte[buffersize]; // repartir de zero
        }

        // concatener un peu..
        System.Array.Copy(incoming, 0, cursorByteArray, currentPosition, incoming.Length)

        currentPosition += incoming.Length;
        // find startindex
        int startIndex = System.Array.IndexOf(cursorByteArray, startByte, 0);
        int endIndex = System.Array.IndexOf(cursorByteArray, startByte, startIndex + 1);

        // decommentez cette partie si vous voulez avoir la trame en DEBUG
        //string s = new String(Encoding.UTF8.GetChars(cursorByteArray));
        //Debug.Print(s);
        if (endIndex < 1 || startIndex < 0 || startIndex > endIndex)
        {
            return;// pas de trame valide encore
        }

        // si on est la ca veut dire
        // - trame edf valide (start, endbyte)
        // - on peut la lire</pre>
        // lire uniquement la partie qui nous interesse
        byte[] validPacket = new byte[endIndex - startIndex + 1];
        System.Array.Copy(cursorByteArray, startIndex, validPacket, 0, validPacket.Length);
        TranslateEdfProtocolIntoCurrentReading(validPacket);

        currentPosition = 0;
        cursorByteArray = null;
        cursorByteArray = new byte[buffersize];
    }

    static void TranslateEdfProtocolIntoCurrentReading(byte[] packets)
    {
        if (packets == null || packets.Length < 1)
            return;
        string adco = FindPacketValue(packets, "ADCO");
        string hchc = FindPacketValue(packets, "HCHC");
        string hphp = FindPacketValue(packets, "HCHP");
        string ptec = FindPacketValue(packets, "PTEC");
        string papp = FindPacketValue(packets, "PAPP

        if (hchc != null && hchc.Length > 1)
        {
            // la lecture est ici
            currentReading = new EdfReading()
            {
                IndexHeuresCreuses = hchc,
                IndexHeuresPleines = hphp,
                NoCompteur = adco,
                PeriodeTarifaireEnCours = ptec,
                PuissanceApparente = papp
            };
        }

      if (currentReading != null)
            Debug.Print("*** HP:" + currentReading.IndexHeuresPleines + " & HC:" + currentReading.IndexHeuresCreuses);
    }

    private static string FindPacketValue(byte[] packets, string packetName)
    {
        int position = FindIndexOf(packets, enc.GetBytes(packetName));
        if (position == -1) // not found...
            return string.Empty;

        int startByte = 0;
        int endByte = 0;
        for (int i = position; i < packets.Length; i++)
        {
            var b = packets[i];
            if (b == 0x20)
            {
                if (startByte == 0)
                    startByte = i;
                else if (endByte == 0)
                {
                    endByte = i; // end of packet reached..
                    break;
                }
            }
        }

       // find the value...
        byte[] valByte = new byte[endByte - startByte + 1];
        System.Array.Copy(packets, startByte, valByte, 0, endByte - startByte);
        return new String(System.Text.Encoding.UTF8.GetChars(valByte));
    }

    private static int FindIndexOf(byte[] arrayToSearchThrough, byte[] patternToFind)
    {
        if (patternToFind.Length > arrayToSearchThrough.Length)
            return -1;
        for (int i = 0; i < arrayToSearchThrough.Length - patternToFind.Length; i++)
        {
            bool found = true;
            for (int j = 0; j < patternToFind.Length; j++)
            {
                if (arrayToSearchThrough[i + j] != patternToFind[j])
                {
                    found = false;
                    break;
                }
            }
            if (found)
            {
                return i;
            }
        }
        return -1;
    }

On voit bien que j’ai dû créer une méthode pour trouver des arrays de bytes dans des arrays de bytes. Il ne faut pas oublier qu’on est sur un Micro Framework et qu’on n’a pas le Rolls habituel !

Du coup, si tout est bon, vous avez les valeurs dans currentReading, et vous pouvez ensuite envoyer les infos vers Azure, les afficher, etc.

Chez moi la carte Micro Framework qui fait la lecture du compteur n’est pas le même que cela qui communique avec Azure. Les deux sont reliées par un réseau RS485.

 

Partie Azure

Dans Azure j’ai créé un simple site MVC qui m’expose, en GET tout simple, une manière des stocker les infos dans une base SQL Azure.

La sécurité se fait par l’envoi d’une clé non-répétitive (Hint: prenez l’heure, prenez une key et composez votre token non-répétitif).

La partie qui va envoyer l’info dans Azure tourne sur un FEZ Panda 2 + un FEZ Connect. Mais si vous avez le Cerbuino Net, vous pouvez récupérer et envoyer les informations directement depuis la même carte. L’URL contiendra les valeurs (ex : http://monsiteweb/Sauvegarde?valeurHC=123&valeurHP=321&tokenSecret=ABCD )

    private static void CallWSWithUrl(string url)
    {
        for (int i = 0; i < 30; i++)
        {
            if (requestInProgress)
                Thread.Sleep(100);
            else
                break;
        }
        requestInProgress = true;

        using (HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url))
        {
            request.ContentType = "application/text";
            request.Method = "GET";
            request.Timeout = 4000;
            request.KeepAlive = false;

            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    response.GetResponseStream().ReadByte();
                    Thread.Sleep(300);
                    response.Close();
                }
            }
            catch (Exception ex)
            {
                Debug.Print("WS ERROR: " + ex.Message);
            }
        }

        requestInProgress = false;
    }

Le résultat ?

tableau de valeurs dans Azure

On voit bien la sauvegarde des valeurs toutes les minutes, et la précision qui va nous permettre de calculer la consommation en Watt.

Un point d’attention : vu la volumétrie qui s’accumule, il faudra bien penser à indexer et optimiser la lecture de la table. Un exemple pour récupérer la consommation par heure, en HC/HP, d’une manière optimale, pour une période donné :

SELECT
  MAX(ReadingValueHP) as hp,
  MAX(ReadingValueHC) as hc,
  CONVERT(DateTime, Convert(NVARCHAR, CONVERT(Date, ReadingDate))+' '+CONVERT(NVARCHAR, DATEPART(hour, ReadingDate)) + ':00') as Readingdate
FROM EdfReading
WHERE ReadingDate >= @start
AND ReadingDate <= @end
GROUP BY CONVERT(DateTime, CONVERT(NVARCHAR, CONVERT(Date, ReadingDate))+' '+CONVERT(NVARCHAR, DATEPART(hour, ReadingDate)) + ':00')

Et la même chose pour avoir la valeur par jour (on fera la différence par la suite, sur le phone) :

SELECT MAX(ReadingValueHP), MAX(ReadingValueHC), CONVERT(Date, Readingdate) as ReadingDate
FROM EdfReading
WHERE ReadingDate >= @start
AND ReadingDate <= @end
GROUP BY CONVERT(Date, Readingdate)

 

Partie Windows Phone

screenshot windows phone 2 screenshot windows phone 1

Pour la partie Phone, l’application récupère simplement les valeurs du site, et on fait la différence entre les valeurs pour avoir la consommation réelle.

Des totaux sont proposés pour la période affichée.

Les deux parties à retenir :

  • le calcul des Watts :
private static void CalculateConsumption(EdfReading[] results, out double totalKWHP, out double totalKWHC, out double indexHP, out double indexHC, out List<EdfReadingExtended> items)
{
var minValHP = results.Min(x => x.ReadingValueHP);
var minValHC = results.Min(x => x.ReadingValueHC);

indexHP = results.Max(x => x.ReadingValueHP);
indexHC = results.Max(x => x.ReadingValueHC);

totalKWHP = indexHP - minValHP;
totalKWHC = indexHC - minValHC;

items = new List<EdfReadingExtended>();
var orderedRdgs = results.OrderBy(x => x.ReadingDate).ToArray();

var cursorHP = minValHP;
var cursorHC = minValHC;
var cursorDate = results.Min(x => x.ReadingDate);

foreach (EdfReading rdg in orderedRdgs)
{
// start digging...
// find out the consumption in watts
double hours = (rdg.ReadingDate - cursorDate).TotalHours;

// now, we should get the wattage for the given interval
var hcConsumption = (rdg.ReadingValueHC - cursorHC);
var hpConsumption = (rdg.ReadingValueHP - cursorHP);

items.Add(new EdfReadingExtended()
{
ReadingDate = rdg.ReadingDate,
ReadingValueHC = hcConsumption / (double)1000,
ReadingValueHP = hpConsumption / (double)1000,
KW = (int)(hcConsumption / hours + hpConsumption / hours)
});

cursorHC = rdg.ReadingValueHC;
cursorHP = rdg.ReadingValueHP;
cursorDate = rdg.ReadingDate;
}
}
  • et l’utilisation des graphs DataVisualisation Toolkit. J’ai modifié légèrement les sources pour que je puisse :
    • slider gauche/droite pour décaler l’axe de temps
    • pinch pour changer l’échelle de temps (minute/heure/semaine/mois/période)

Depuis ma galère initiale pour le porter sur WP 8.0, il existe en package NuGet désormais, mais sans les deux features.

 

Conclusion et lecture supplémentaire

J’espère avoir suscité votre curiosité sur le sujet.

L’application tourne chez moi depuis plus d’un an, sans soucis majeur. La carte Micro Framework est dehors dans un boitier étanche, et elle résiste sans soucis à des températures extérieures entre -15 degrés l’hiver et +35 l’été. Donc une belle surprise pour une carte qui n’est pas prévu pour le milieu industriel.

Le code est parfois rudimentaire, et je m’excuse par avance si vous trouvez des raccourcis de geek.

La semaine prochaine, je vais essayer de vous expliquer le même processus, mais avec mon compteur d’eau (qui n’est pas avec des impulsions !).

En attendant, si vous avez des commentaires, n’hésitez pas à m’en faire part. Le code source ne sera ni publié, ni diffusé intégralement. Je pense avoir donné toutes les informations pour vous faire bien démarrer en revanche.

Mes points de départ :

http://blog.cquad.eu/2012/02/02/recuperer-la-teleinformation-avec-un-arduino/

http://www.planete-domotique.com/blog/2010/03/30/la-teleinformation-edf/

 

Alex.

Event Javascript Open Day 1 – Jeudi 19 m

Event Javascript Open Day 1 – Jeudi 19 mars 2015 – Campus Microsoft France
Microsoft vous propose un événement gratuit sur une journée complète dans laquelle on parle de Javascript, de performance et d’ouverture.
De 17h à 17h30, Guillaume, expert MCNEXT, intervient sur la «Conception d’apps cross-plateformes WinJS / Cordova»
http://www.meetup.com/Javascript-Open-Day/events/220087351/

Débuguer une Universal Windows app et d’une application Cordova dans Visual Studio

Petit rappel : Vu l’architecture du projet (Applications natives en Universal App + application cordova) il faut bien penser à ajouter les fichiers copiés depuis le shared project en as link dans l’application cordova. C’est le seule moyen de débuguer/modifier le bon fichier.

 

Dans les applications universelles aucune configuration spéciale n’est nécessaire, Visual Studio gère parfaitement le debug. Il suffit de lancer l’application en mode debug et avoir accès dès le lancement au dom ainsi qu’aux points d’arrêts. Les choses se compliquent légèrement avec les applications cordova. En effet Visual studio met plusieurs secondes (voir minutes) avant d’attacher correctement et d’une façon stable le debugger. Et si on souhaite débuguer les premières lignes qui s’exécutent lors du lancement de l’application, cela devient rapidement compliqué, voir impossible.

Deux solutions existent :

  • La première (mais qui ne marche que si l’application s’initialise correctement = pas de crash au démarrage) c’est simplement via la console JavaScript de Visual Studio d’appeler la méthode window.location.reload() la page index.html est rechargée = les scripts se ré exécutent et on a donc accès aux debug des premières lignes de code.
  • La deuxième c’est de créer un mode debug avec une étape intermédiaire qui consistera à avoir un fichier index.html qui charge le stricte minimum de fichiers qui contient un lien (button) qui va nous permettre de naviguer vers une deuxième page qui va charger le reste des fichiers. Avec cette formule on s’assure du démarrage de l’application, on peut attendre que le debugger Visual Studio soit correctement attaché pour pourvoir charger les autres fichiers.

 

Le débogage/déploiement sous iOS requière un mac et l’installation des outils de build:

  • (Mac) Depuis le terminal lancer la commande désinstallation: sudo npm install -g vs-mda-remote –user=$USER ($user = l’utilisateur courant)
  • (Mac) Après l’installation lancer la commande: vs-mda-remote –secure false
  • Configurer Visual Sutdio: Tools => Options => Tools for Apache Cordova => remote Agent configuration:
    • Enable remote iOS processing = True
    • Host : adresse ip du mac de build.

Le déploiement peut se faire avec le simulateur ou un device.

Avec ces quelques notes vous avez maintenant les outils pour pourvoir débugger facilement votre nouvelle application.

Écriture/lecture/modification de fichiers dans un projet Universel app et cordova

Dans nos applications, nous avons pris le parti d’écrire nos fichiers en JSON. Nous avons donc conçu une abstraction (en WinJS, avec des promises par exemple) pour avoir la possibilité de le faire avec des méthodes claires et simples sur toutes les plateformes (WinRT ou Cordova)

Ce module « DataContainer » est disponible dans notre libraire WinJSContrib (nuget ou dans github).

Dans WinJSContrib.DataContainer, nous avons 4 fichiers qui exposent les mêmes méthodes avec des implémentations différentes :

  • read : lecture d’un élément (renvoi une promise)
  • save : enregistrement d’un élément
  • remove : suppression d’un élément
  • list : liste des fichiers d’un container
  • child : création/accès container enfant

Dans une application Windows 8 ou Windows Phone nous allons naturellement utiliser la couche WinRT pour écrire/lire les fichiers. Pour cela il suffit d’inclure le fichier « winjscontrib.datacontainer.winrt.file.js »

Dans une application cordova, nous avons plusieurs choix :

  • utiliser une base de données : winjscontrib.datacontainer.cordova.database.js
  • utiliser le système de fichiers avec le plugin file : « winjscontrib.datacontainer.cordova.file.js »
  • utiliser le local Storage : « winjscontrib.datacontainer.localstorage.js » (utilisable en WinRT aussi)

 

Il faut simplement instancier un container parent et l’utiliser partout dans l’application.

Dans le JS des applications Windows 8/Phone il suffit d’instancier le container (dossier) parent :

  • MyApp.Data.container = new WinJSContrib.DataContainer.WinRTFilesContainer(undefined, { logger: WinJSContrib.Logger });

Et changer WinRTFilesContainer par notre choix (CordovaDatabaseContainer par exemple) pour l’application cordova en faisant attention de ne l’appeler qu’après l’enclenchement de l’évènement deviceready.

Et c’est tout, la magie s’opère à l’intérieur de notre librairie :)

Quelques exemples d’utilisation :

  • Pour lire un fichier :
    • Data.container.read(« objKey »).then(function (data) { }, function (error) { });
  • Supprimer un fichier :
    • Data.container.remove(« objKey »).then(function () { }, function (error) { });
  • Enregistrer un fichier :
    • Data.container.save(« objKey »,obj).then(function () { }, function (error) { });
  • Accès à un container enfant (sous dossier) avec la lecture d’un fichier fichier :
    • Data.container.child(folderid).read(« subObjKey »).then( function (subObjInFolderID) {

}, function (error) { }));

  • Liste des fichiers dans un container :
    • Data.container.list().then(function (res) {}, function (error) { });

Universal Windows app et Cordova avec WinJS

L’architecture que je conseil pour cibler les trois (quatres) plateformes, c’est de partir principalement d’un projet natif Universal app (Windows 8.1/ Windows Phone) en HTML5 et de créer un projet Cordova à l’aide du plugin Visual studio.

Ensuite pour brancher l’application Cordova avec le projet shared, il faut écrire un script (robocopy) à exécuter avant le build pour copier les fichiers du projet shared vers le projet cordova:

(robocopy ..\UniversalApp.Shared\ . /E /XF UniversalApp.Shared.*)^& IF %ERRORLEVEL% LEQ 1 exit 0

Et modifier le fichier de projet (jsproj) pour lancer cette exécution:

<Target Name= »BeforeBuild »>
<Message Text= »### BeforeBuild ### » Importance= »high » />
<Exec Command= »prebuild.bat » />
</Target>

Mais pour pouvoir débugguer les fichiers copiers, il faut aussi créer la structure des dossiers et ajouter les fichiers en as link.

Pour ajouter WinJS à vos projets vous pouvez passer par nuget (qui ne marche pas avec les projets shared pour le moment) ou récupérer directement la dernière version stable disponible depuis le repo github. Vous pourrez ensuite ajouter les fichiers WinJS.js, css ui-light.css ou ui-dark .css ainsi que la typo Symbols.ttf dans le dossier scripts du projet shared (cette version de WinJS sera aussi utilisée avec les Universel Apps)

Enfin il reste à inclure les références dans les fichiers default.html et index.html. Votre projet est ainsi prêt et on peut lancer le développement de notre application cross-plateforme.

Note importante: l’initialisation de l’application est différente en WinRT et en Cordova. Sous Windows on va conserver le fichier default.js, et pour le projet Cordova, on va modifier le fichier équivalent, index.js, pour initialiser correctement notre application.

Un exemple de solution est disponible ici

WinJS dans une application cross plateforme Cordova

Depuis avril 2014, WinJS le Framework SPA de Microsoft est devenu libre (disponible sur github) et  surtout cross-platform.
C’est avec ces nouvelles possibilités qu’on peut maintenant l’utiliser sur d’autres plateformes que Windows 8/Phone 8.1.

Dans cette série de posts, je vais donc aborder le développement multiplateforme d’application avec WinJS.

Techdays 2015 : Review de la session « Docker, une alternative aux machines virtuelles pour déployer ses services .Net »

Docker : Késako ?

Docker permet d’embarquer une application dans un container virtuel qui pourra s’exécuter sur n’importe quel serveur (Linux et bientôt Windows). C’est une technologie qui a pour but de faciliter les déploiements d’une application, et la gestion du dimensionnement de l’infrastructure sous-jacente. Cette solution est proposée en open source (sous licence Apache 2.0) par une société américaine, également appelée Docker, qui a été lancée par le Français Solomon Hykes.

Voici un slide comparant la même infrastructure utilisant Docker et des VM.

dockerVSVm

Comme vous pouvez le constater cela permet d’éviter de dupliquer les couches (notamment celle de l’OS Hôte !) par rapport à une architecture à VM. Les blocs sont versionnés et ne sont pas dupliqués sur l’hôte :

  • Sur l’architecture à VM on a 3 VM avec 3 blocs (9 blocs)
  • Sur l’archi Docker on a que 5 conteneurs car Lib 1 a été mutualisé entre les « App 1″ et « App 2″. L’OS Hôte est un OS minimaliste comme CoreOs qui n’embarque que les fonctionnalités essentielles pour accueillir un conteneur, si l’application nécessite un composant (comme un hôte de site web)cela sera compris dans ses conteneurs en dessous de lui.

D’un point de vue d’un développeur C# cela s’apparente un peu à un package Nuget mais au lieu d’être au niveau de la solution c’est au niveau du serveur.

Docker crée le conteneur à partir d’un Dockerfile contenant les instructions pour cette image, en voici un exemple :

dockerfile

  • FROM : Image de départ (un conteneur est créé à partir du conteneur en dessous de lui)
  • ADD : Ajoute ce qu’il y a dans le dossier src vers le dossier /app/
  • WORKDIR : Déplace l’environnement de travail (où sont traités les commades) vers le dossier app
  • RUN : lance la commande kpm restore qui télécharge tous les paquets nécessaires
  • EXPOSE : Indique à Docker que le conteneur va écouter sur ce port
  • ENTRYPOINT : Permet d’indiquer qu’un conteneur est un exécutable. Dans ce cas-ci on va utiliser kestrel (web server linux) pour faire tourner l’app.

Plus d’infos à ce sujet ici : https://docs.docker.com/reference/builder/

 

.Net avec Docker

Pour .Net ce n’est pas actuellement Production Ready, en effet .Net Core est encore en bêta sur Linux et Docker n’est pas dispo sur Windows Server 2012 (mais le sera sur la prochaine version de Windows Server). Une config standard pour tester Docker est d’avoir une machine virtuelle Linux tournant sur un poste Windows (qui fait tourner Visual Studio) :

dockerDevOps

Une configuration plus précise pour la partie Dev :

devWithDocker

Le développeur utilise un share entre sa VM Linux et son Windows. La VM tourne grâce à Hyper-V. On voit ici qu’actuellement faire du .Net avec Docker est un peu compliqué et que de manière général ça manque de tooling (beaucoup de lignes de commandes).

 

Bonne nouvelle : Demain ce sera plus simple on pourra le faire tourner sur un Windows Server, plus d’infos ici.

dockerDevFutur

 

A savoir

  • L’ops peut reconfigurer certains paramètres (ports si la même appli existe sur le même hôte).
  • Docker possède un cache pour ne pas re-télécharger l’image.
  • Pour le moment Docker ne gère rien côté sécurité, il ne fait aucun check pour savoir si l’image obtenue est bien celle demandée mais c’est prévu.
  • Une best practice est de créer un conteneur coquille utilisée par toutes les applications de l’entreprise.
Suivre

Recevez les nouvelles publications par mail.

Rejoignez 31 autres abonnés