Publié le

Gâteau Basque à la cerise / Faisan au pommes- Test1

J’ai un oncle qui habite au Pays Basque et quand on y allait gamin, ma tante faisait toujours un gâteau basque à la cerise.

Du coup ce matin je me suis lancé pour en faire un.

1. Ingrédients :

  • 300g de farine,
  • 3 pincées de sel,
  • 120g de beurre,
  • 200g de sucre en poudre,
  • 2 œufs + 1 jaune,
  • 1 sachet de levure chimique,
  • 1 gousse de vanille / vanille en poudre,
  • 1 faisan
  • 1 1/2 pommes,
  • sel, poivre huile.

2. La préparation :

Allez je commence à attraper mes ingrédients !

Et là premier drame : je n’ai pas d’œufs ! Bon pas de soucis, je vais en chercher chez la voisine, il lui en reste que deux, donc exit le jaune d’œuf pour dorer le gâteau ! On papotte on papotte, et je reviens chez moi.

Second drame : je n’ai plus de farine et je n’ai pas de levure ! Allez hop direction l’épicerie du village, 2€50 pour les deux (en prenant de la farine premier prix hein).

Allez go ! On sort le robot, la feuille (l’accessoire feuille hein) :

  • On mélange dans un premier temps le beurre un peu ramolli avec le sucre,
  • On y ajoute la farine, la levure, les œufs, le sel, la vanille et on mélange pour avoir une pâte bien lisse.
  • On fait une boule, dans du film plastique et au frigo pour la faire reposer environ 1h.

IMG_0118

  • Pendant ce temps, éplucher les pommes, les couper en morceau et farcir le faisan,
  • Ficeler le faisan pour ne pas que les pommes sortent pendant la cuisson. Assaisonner.
  • Mettre au four le faisan à 200°C pendant 1 heure (en le retournant à mi-cuisson).

IMG_0119IMG_0120

  • Une heure après, on sépare la boule en deux en en faisant une plus petite que l’autre.
  • On étale la grosse boule, on dispose la confiture de cerises,
  • On étale la seconde, on recouvre la confiture avec pour obtenir :

IMG_0123

  • On fait cuire 40 minutes à 160°C
  • Et on obtient ce truc tout moche (mais très bon) car il s’est dilaté à la cuisson (avec un cerclage ça doit être mieux, je testerai) :

IMG_0124IMG_0126

 

Oubli : le faisan en sortie de cuisson

Publié le

Station météo maison couplée à une station Netatmo Part.1

Les modules additionnels Netatmo étant un peu cher, j’ai décidé de me faire des petits modules maison avec un ESP8266 et des ds18b20/DHT11-22.

Bien sur, je n’ai pas envie de faire un truc tout moche, donc pour les graphiques je me suis penché sur Highstocks.

Alors d’entrée j’ai bloqué : on doit utiliser du Javascript et moi je sais pas en faire… Ça commence bien…

Alors j’ai essayé de comprendre quand même, mais l’import des données avec json.encode() dans le php m’a un peu saoulé car sur les démos de Highstocks, c’était pas encodé pareil… Du coup sauce maison !

Pour la partie base de donnée, il suffit de regarder mes tutos précédents pour alimenter la BDD avec les relevés Netamo.

1. Encodage des données pour Highstock :

En regardant les démos, j’ai vu que le format des données étaient du style :

[
[data1,data2],
[data1,data2],
[data1,data2],
[data1,data2],
[data1,data2],
[data1,data2],
[data1,data2]
]

Du coup, je me suis fait un fichier temperaturenetatmo.php qui quand je l’exécute m’affiche les données sous cette forme :

<?php
include('connexionDB.php');

$date = 1445538928*1000;
echo "[";
$i=0;
$sth = mysql_query("SELECT datemesure, temp_int, temp_ext, pres, hum_int, hum_ext FROM netatmo");
$rows = array();

while($r = mysql_fetch_array($sth)) {
    if (date("I",time())==0){
    	if (($r["datemesure"]+3600)*1000-$date > 30*60*1000)
    	{
    		$date2 = $date + 1000;
    		$rows[] = "[".$date2.",null,null,null,null,null]";
    		$i = $i +1;
    	}
    	$date = ($r['datemesure']+3600)*1000 ;
    	$rows[] = "[".$date.",".$r["temp_int"].",".$r["temp_ext"].",".$r["pres"].",".$r["hum_int"].",".$r["hum_ext"]."]";
    	$i = $i +1;
	}
	else {
		if (($r["datemesure"]+3600)*1000-$date > 10*360*1000)
    	{
    		$date2 = $date + 1000;
    		$rows[] = "[".$date2.",null]";
    		$i = $i +1;
    	}
		$date = ($r['datemesure']+3600)*1000 ;
		$rows[] = "[".$date.",".$r["temp_int"].",".$r["temp_ext"].",".$r["pres"].",".$r["hum_int"].",".$r["hum_ext"]."]";
        $i = $i+1;
	}
}
for ($j = 0 ; $j<$i-1; $j ++){
	echo $rows[$j];
	echo ",";
}
echo $rows[$i-1];
echo "]";

mysql_close($con);
?>

Quelques précisions :

$date = 1445538928*1000;

Est la PREMIERE date de ma table (elle me permet de définir mes « null » quand il n’y a pas de données dans un intervalle de 30 minutes.

On remarque aussi que je multiplie toutes mes dates par 1000 : le temps en javascript prend en compte les milisecondes, on multiplie donc le timestamp php qui lui ne les prend pas.

Voici un extrait de la sortie :

[
[1428155100000,20.4,14.4,1015.1,67,61],
[1428156900000,20.5,14.3,1014.9,67,63],
[1428158700000,20.2,14.4,1014.6,68,63],
[1428158701000,null,null,null,null,null],
[1428176700000,20.4,12.1,1014.1,67,74]
]

La première partie est finie (j’y ai passé 3 jours quand même (en comptant le temps passé avec json.encode() ).

2. La partie Highstock :

Avant de vous dire le pourquoi du comment, voilà ce que je voulais obtenir :

chart

C’est là que la déprime a commencé… Heureusement que les démos sur Highstocks sont pas mal, je me suis inspiré de :

Et voilà mon code :

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Surveillance maison</title>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>



<script type="text/javascript">



$(function () {
    var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
Highcharts.setOptions({
lang: {

months: ["Janvier "," Février ","Mars "," Avril "," Mai "," Juin "," Juillet "," Août "," Septembre ",
" Octobre "," Novembre "," Décembre"],
weekdays: ["Dim "," Lun "," Mar "," Mer "," Jeu "," Ven "," Sam"],
shortMonths: ['Jan', 'Fev', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil','Août', 'Sept', 'Oct', 'Nov', 'Déc'],
decimalPoint: ',',
resetZoom: 'Reset zoom',
resetZoomTitle: 'Reset zoom à 1:1',
downloadPNG: "Télécharger au format PNG image",
downloadJPEG: "Télécharger au format JPEG image",
downloadPDF: "Télécharger au format PDF document",
downloadSVG: "Télécharger au format SVG vector image",
exportButtonTitle: "Exporter image ou document",
printChart: "Imprimer le graphique",
loading: "Chargement...",
rangeSelectorFrom: "Du",
rangeSelectorTo: "au"
 }

});
    $.getJSON('temperaturenetatmo.php', function (data) {

        // split the data set into temp_int and temp_ext
        var temp_int = [],
            temp_ext = [],
            rose = [],
            pression = [],
            hum_int = [],
            hum_ext = [],
            dataLength = data.length,
            // set the allowed units for data grouping


            i = 0;

        for (i; i < dataLength; i += 1) {
            temp_int.push([
                data[i][0], // the date
                data[i][1], // température intérieure

            ]);

            temp_ext.push([
                data[i][0], // the date
                data[i][2] // température extérieure
            ]);

            rose.push([
                data[i][0], // the date
                (Math.pow(data[i][5] /100,0.125)  )*(112+0.9*data[i][2])+0.1*data[i][2]-112 // point de rosée
            ]);

             pression.push([
                data[i][0], // the date
                data[i][3] // pression
            ]);
            hum_int.push([
                data[i][0], // the date
                data[i][4] // hum int
            ]);
            hum_ext.push([
                data[i][0], // the date
                data[i][5] // hum ext
            ]);
            }


        // create the chart
        $('#container2').highcharts('StockChart', {

             rangeSelector : {
                buttons : [ {
                    type : 'hour',
                    count : 12,
                    text : '12h'
                },{
                    type : 'day',
                    count : 1,
                    text : '1j'
                },{
                    type : 'day',
                    count : 7,
                    text : '1s'
                },{
                    type : 'month',
                    count : 1,
                    text : '1m'
                }, {
                    type : 'all',
                    count : 1,
                    text : 'Tout'
                }],
                selected : 1
            },

            title: {
                text: 'Données Netatmo'
            },

            yAxis: [{

                labels: {
                    align: 'right',
                    x: -3
                },
                title: {
                    text: 'Température'
                },
                height: '30%',
                lineWidth: 2
            }, {
                labels: {
                    align: 'right',
                    x: -3
                },
                height: '30%',
                offset: 0,
                lineWidth: 2
            },{
                labels: {
                    align: 'right',
                    x: -3
                },
                title: {
                    text: 'Pression'
                },
                top: '35%',
                height: '30%',
                offset: 0,
                lineWidth: 2,
                plotLines: [{
                value: 1015,
                width: 1,
                color: 'red',
                zIndex : 2,
            }],
            },{
                labels: {
                    align: 'right',
                    x: -3
                },
                title: {
                    text: 'Humidité'
                },
                top: '70%',
                height: '25%',
                offset: 0,
                lineWidth: 2
            },{
                labels: {
                    align: 'right',
                    x: -3
                },
                top: '70%',
                height: '25%',
                offset: 0,
                lineWidth: 2
            }],
            xAxis: {
                ordinal: false,
                alternateGridColor: '#F0FFFF'
            },
            tooltip: {
                    xDateFormat: '%a %d %b %H:%M'

                },
            plotOptions: {
                line: {
                    connectNulls: false
                        }
            },
            series: [{
                name: 'T° Intérieure',
                data: temp_int,
                tooltip: {
                    valueDecimals: 2,
                    valueSuffix:' °C'
                }
            }, {
                name: 'T° Extérieure',
                data: temp_ext,
                yAxis:0,
                tooltip: {
                    valueDecimals: 2,
                    valueSuffix:' °C'
                }
            },{
                name: 'Point de Rosée',
                data: rose,
                yAxis:0,
                tooltip: {
                    valueDecimals: 2,
                    valueSuffix:' °C'
                }
            },{
                name: 'Pression',
                data: pression,
                yAxis: 2,
                tooltip: {
                    valueDecimals: 0,
                    valueSuffix:' hPa'
                }
            },
            {
                name: 'Humidité intérieur',
                data: hum_int,
                yAxis: 3,
                tooltip: {
                    valueDecimals: 0,
                    valueSuffix:' %'
                }
            },{
                name: 'Humidité extérieur',
                data: hum_ext,
                yAxis: 3,
                tooltip: {
                    valueDecimals: 0,
                    valueSuffix:' %'
                }
            }]
        });
    });
});


</script>

<script src="http://code.highcharts.com/stock/highstock.js"></script>
<script src="http://code.highcharts.com/stock/modules/exporting.js"></script>
    </head>
    <body>

       <div id="container2" style="width: 50%; height: 95%; float: left; "></div>


    </body>
</html>

 

Publié le

Afficher les données de Netatmo avec… Un ESP8266 ESP1

Et pourquoi ne pas réduire un peu ce que j’ai fait sur l’autre tuto ?

Alors oui on pourrait remplacer l’Arduino Méga par un nano, mais pour le Wifi on fait comment ?

Dans mon précédant tuto, je parle de l’ESP8266, mais comment ça fonctionne ?

1. L’ESP8266

Voici l’ESP8266 ESP01.

WiFi Serial Transceiver Module

On pourrait reprendre la formule « Petit mais costaud », c’est petit, assez sympa, mais aussi très galère au début quand on y connait rien !

1.1 Les pins :

images

8 pins seulement, on a pas besoin de plus (on pourrait même faire avec 6…).

1.2 On le programme avec Arduino IDE !

Et oui, on ne s’embête pas pour le programmer on peut le faire à l’aide de l’IDE Arduino, mais avant il faut la préparer un peu :

1.2.1 Configuration de l’interface Arduino :

Alors dans un premier temps on installe Arduino 1.6.5.

On ouvre les préférences et dans « Additional Bords Manager URLs » on ajoute l’URL

http://arduino.esp8266.com/stable/package_esp8266com_index.json

prefs

Et on clique sur Ok.

Ensuite on va dans Outils > type de carte > Boards Manager , dans le champ de recherche on tape esp8266 et On voit apparaitre un cadre avec esp8266… On clique dessus puis sur install.

Une fois installé dans Outils > type de carte en bas on va retrouver l’esp8266 :

Esp

 

On utilisera le type de carte « Generic ESP8266 module ». L’interface est donc prête, on ferme l’interface Arduino pour installer les librairies.

1.2.2 Installation des librairies :

Première étape, on va sur le Github de Sandeepmistery et on télécharge la dernière release.

Ensuite on va dans le dossier Arduino, le dossier dans mes documents qui contient les sketches Arduino et on crée un dossier hardware.

Une fois le fichier télécharger (archive Zip) on copie-colle le dossier esp8266 dans le dossier hardware que nous venons de créer.

Attention : mon nom de compte sur mon pc est JiPé et Arduino n’aime pas ça, j’ai donc un second compte utilisateur nomé JiP, (oui oui avec une virgule à la place du é) et c’est dans ce compte utilisateur que j’ai du faire ces manipulations.

 

2. Premiers pas : récupération du fichier out.txt.

On revient en fait à l’étape 3.1 du tuto  Afficher les données Netatmo avec un Arduino.

Voici le code utilisé (d’après un exemple contenu dans la libairie esp8266wifi) :

#include <ESP8266WiFi.h>

const char* ssid     = "SSID Wifi";
const char* password = "MDP Wifi";

const char* host = "192.168.1.50";

void setup() {
  Serial.begin(115200);
  delay(10);

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

int value = 0;

void loop() {
  ++value;

  Serial.print("connecting to ");
  Serial.println(host);

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  // We now create a URI for the request
  String url = "/Netatmo/out.txt";


  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
 "Host: " + host + "\r\n" + 
 "Connection: close\r\n\r\n");
  delay(10);

  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('r');
    Serial.print(line);
  }

  Serial.println();
  Serial.println("closing connection");
  delay(60000);
}

Et en sortie j’obtient :

Capture

 

3. Affichage LCD des données reçues :

Alors la partie qui m’a pris le plus de temps (en oubliant une ligne dans le code c’est sur que ça ne peut pas fonctionner).

L’ESP8266 ESP1 a deux GPIO qui peuvent servir pour l’I2C :

  • GPIO0 => SDA
  • GPIO2 => SCL

Du coup il est facile d’afficher sur un écran LCD avec une interface I2C.

Voici le code utilisé :

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <ESP8266WiFi.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const char* ssid     = "SSID Wifi";
const char* password = "MDP Wifi";

const char* host = "192.168.1.50";

void setup() {
  Serial.begin(115200);
  delay(10);
  Wire.begin(0,2);                                  //LIGNE LA PLUS IMPORTANTE POUR DEMARRER L'I2C SUR L'ESP8266
  lcd.begin();
  lcd.backlight();

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

int value = 0;

void loop() {

  ++value;

  Serial.print("connecting to ");
  Serial.println(host);

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  // We now create a URI for the request
  String url = "/Netatmo/out.txt";


  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
 "Host: " + host + "\r\n" + 
 "Connection: close\r\n\r\n");
  delay(10);
  String line = "";
  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    line = client.readStringUntil('r');
   // Serial.print(line);
  }

//Serial.println(line);



char messageChar[500];
  line.toCharArray(messageChar,500);

  char dlm[] = "[";
            int cnt = 0;
            char* tab[255] = { 0 };
            char *pch = strtok(messageChar, dlm);
            while ( pch != NULL ) {
              if (cnt < 60) {
              tab[cnt++] = pch;
              } else {
              break;
              }
            pch = strtok (NULL, dlm);
            }


  char *chaine = tab[1];
  //Serial.println(chaine);
  char dlm2[] = "n";
            int cnt2 = 0;
            char* tab2[255] = { 0 };
            char *pch2 = strtok(chaine, dlm2);
            while ( pch2 != NULL ) {
              if (cnt2 < 60) {
              tab2[cnt2++] = pch2;
              } else {
              break;
              }
            pch2 = strtok (NULL, dlm2);
            }

lcd.clear();
lcd.print("T:");
lcd.print(tab2[0]);
lcd.print(" CO2:");
lcd.print(tab2[1]);
lcd.setCursor(0,1);
lcd.print("H:");
lcd.print(tab2[2]);
lcd.print(" P:");
lcd.print(tab2[3]);

  Serial.println();
  Serial.println("closing connection");
  delay(60000);
}

Et du coup :

 

IMG_0012

Publié le

Afficher les données Netatmo avec un Arduino

L’inconvénient des stations météo Netatmo c’est qu’il faut avoir un smartphone/pc/tablette à disposition pour pouvoir consulter les données de la station (ou avoir un Karotz comme Mathieu).

Du coup je me suis mis à la recherche de pistes pour faire un afficheur LCD avec un Arduino pour avoir les données en temps réel !

Du coup il faut pas mal de choses :

  • Un NAS Synology (ou un pc sous Unix ou un Raspberry Pi),
  • un Arduino avec un lcd,
  • de la patience quand on est pas doué comme moi.

Et il faut aussi quelques connaissances :

  • Savoir programmer sur Arduino,
  • maitriser le PHP,
  • savoir bidouiller dans son NAS (merci encore une fois à Mathieu).

 

1. Créer une application Netatmo :

La première étape est d’aller créer un application sur dev.netatmo.com.

On clique en haut sur « CREATE AN APP » et on se connecte avec nos identifiants Netatmo.

On remplit les champs avec astérisque, dans mon cas :

 

Netatmo1

On descend en bas de la page, on pose la case et on valide.

On arrive ensuite sur la page OAUTH SETTINGS d’ou nous allons récupérer les identifiants de l’application :

Sans titre

On récupère le « Client id » et le « Client secret » qui vont nous servir dans la partie PHP.

2. Partie PHP / Synology

2.1 Partie PHP :

On a donc les « Client id » et « Client secret » de notre application Netatmo, on va maintenant mettre tout ça dans un fichier PHP pour récupérer les informations de la station météo Netatmo.

Voici le code de mon fichier netatmo.php (qui à l’origine vient de Domotique Info mais que j’ai modifié).

<?php
$password="Mot de passe du compte Netatmo";
$username="Identifiant du compte Netatmo";
$app_id = "Client id de l'app";
$app_secret ="client secret de l'app";

$token_url = "https://api.netatmo.net/oauth2/token";
$postdata = http_build_query(
        array(
            'grant_type' => "password",
            'client_id' => $app_id,
            'client_secret' => $app_secret,
            'username' => $username,
            'password' => $password
    )
);

$opts = array('http' =>
    array(
        'method'  => 'POST',
        'header'  => 'Content-type: application/x-www-form-urlencoded',
        'content' => $postdata
    )
);

$context  = stream_context_create($opts);
$response = file_get_contents($token_url, false, $context);

$params = null;
$params = json_decode($response, true);
$api_url = "https://api.netatmo.net/api/getuser?access_token=" . $params['access_token'];
$requete = file_get_contents($api_url);

$url_devices = "https://api.netatmo.net/api/devicelist?access_token=" .  $params['access_token'];
$resulat_device = file_get_contents($url_devices);
$json_devices = json_decode($resulat_device,true);
$module_interne = $json_devices["body"]["devices"][0]["_id"];
$module_externe = $json_devices["body"]["modules"][0]["_id"];

$url_mesures_internes = "https://api.netatmo.net/api/getmeasure?access_token=" .  $params['access_token'] . "&device_id=" . $module_interne . "&scale=max&type=Temperature,CO2,Humidity,Pressure,Noise&date_end=last";
$mesures_internes = file_get_contents($url_mesures_internes);

$url_mesures_externes = "https://api.netatmo.net/api/getmeasure?access_token=" .  $params['access_token'] . "&device_id=" . $module_interne . "&module_id=" . $module_externe . "&scale=max&type=Temperature,Humidity&date_end=last";
$mesures_externes = file_get_contents($url_mesures_externes);

$int = substr($mesures_internes,42,25);
$ext = substr($mesures_externes,42,25);

$interieur=explode(",", $int);
$exterieur=explode(",",$ext);
$h_ext=explode("]",$exterieur["1"]);
$decibel=explode("]", $interieur["4"]);
$message = "[".$interieur["0"]."n".$interieur["1"]."n".$interieur["2"]."n".$interieur["3"]."n".$decibel["0"]."n".$exterieur["0"]."n".$h_ext["0"]."[";
echo $message;


?>

Petites précision sur la fin du script php :

Quand le script exécute

$url_mesures_internes = "https://api.netatmo.net/api/getmeasure?access_token=" .  $params['access_token'] . "&device_id=" . $module_interne . "&scale=max&type=Temperature,CO2,Humidity,Pressure,Noise&date_end=last";
$mesures_internes = file_get_contents($url_mesures_internes);

il nous renvoie un résultat du type :

{"body":[{"beg_time":1444133653,"value":[[24.1,433,60,1007.7,50]]}],"status":"ok","time_exec":0.020297050476074,"time_server":1444134057}

sachant que les valeurs dont nous avons besoin sont : 24.1,433,60,1007.7,50 (Température, CO2, Humidité, Pression, Décibels).

Du coup pour ne récupérer que ça (et pas toute la chaine $mesures_internes) je vais me placer sur le premier chiffre pour la température, j’extrait 25 caractères et ensuite je découpe entre avec mon séparateur « , » puis pour la dernière mesure je découpe avec le séparateur « ] ». (Je ne suis pas en pro, on doit bien pouvoir faire plus propre, mais je fais avec mes connaissances !).

Une fois fait, je compose un message à afficher après avoir exécuté le script PHP sous forme d’un écho qu’on récupèrera avec l’arduino (message avec les séparateurs « [ » et « n » on verra ça dans la partie Arduino).

2.2 Mise en place sur le Synology :

J’ai déjà un serveur Web installé sur mon NAS, donc je suis allé dans le dossier « www », j’ai créé un dossier « Netatmo » et j’ai copié mon fichier « netatmo.php » dedans. Pour automatiser l’exécution de mon script, direction le panneau de configuration et « planificateur de tâche ».

On clique sur créer et on rentre le code suivant :

/usr/bin/php -f /volume1/web/Netatmo/netatmo.php > /volume1/web/Netatmo/out.txt

Voilà ce qu’on obtient :

syno1

 

On va dans l’onglet Programmer :

syno2

On valide et on exécute le script (pour voir si tout se passe bien, le fichier out.txt devrait apparaitre dans le dossier Netatmo.

Le contenu du fichier doit ressembler à ça :

[24.3n450n60n1007.8n51n26.9n45[

Génial c’est la chaine qu’on va récupérer sur l’Arduino !

Note : ne pas faire de bêtises et ne pas effacer le fichier /usr/bin/php (ne me demandez pas comment je l’ai fait, merci à Mathieu de m’avoir envoyé le sien).

 

3. Récupération et affichage sur un LCD : Partie ARDUINO.

3.1 Tests préliminaires (Et il y en a eu…) :

Habituellement, je travaille avec des ESP8266, mais il y a un mois, je me suis commandé un shield CC3000 sur ebay qui ressemble à ça :

$_57

Avantage : il fonctionne avec les librairies ADAFRUIT que l’on trouve ici.

Pour le codage, j’ai fait le flemmard. J’avais déjà testé le code exemple WebClient.ino fournit avec la librairie ADAFRUIT, donc je l’ai bêtement repris.

Il faut juste modifier un peu les premières ligne (je ne montre que les premières lignes) :

#define WLAN_SSID       "LE SSID DE LA BOX"           // cannot be longer than 32 characters!
#define WLAN_PASS       "MOT DE PASSE WIFI"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY   WLAN_SEC_WPA2

#define IDLE_TIMEOUT_MS  3000      // Amount of time to wait (in milliseconds) with no data
                                   // received before closing the connection.  If you know the server
                                   // you're accessing is quick to respond, you can reduce this value.

// What page to grab!
#define WEBSITE      "IP DU NAS"
#define WEBPAGE      "/Netatmo/out.php"  // lien vers out.txt

Sur la voie série quand j’exécute mon programme, j’ai la visualisation suivante :

Hello, CC3000!

Free RAM: 5687

Initializing...

Attempting to connect to Livebox-4246
Connected!
Request DHCP

IP Addr: 192.168.1.65
Netmask: 255.255.255.0
Gateway: 192.168.1.1
DHCPsrv: 192.168.1.1
DNSserv: 192.168.1.1
192.168.1.50 -> 192.168.1.50-------------------------------------
HTTP/1.1 200 OK
Date: Tue, 06 Oct 2015 13:02:00 GMT
Server: Apache
Last-Modified: Tue, 06 Oct 2015 13:01:11 GMT
ETag: "1d-5216f395e9d25"
Accept-Ranges: bytes
Content-Length: 29
Vary: Accept-Encoding
Content-Type: text/plain

[24.5n455n60n1007.9n51n27n44[-------------------------------------


Disconnecting

En fait le programme WebClient.ino me renvoie la réponse donnée par le site web, mais la réponse COMPLETE, c’est à dire :

HTTP/1.1 200 OK
Date: Tue, 06 Oct 2015 13:02:00 GMT
Server: Apache
Last-Modified: Tue, 06 Oct 2015 13:01:11 GMT
ETag: "1d-5216f395e9d25"
Accept-Ranges: bytes
Content-Length: 29
Vary: Accept-Encoding
Content-Type: text/plain

[24.5n455n60n1007.9n51n27n44[

Et devinez ce dont on a besoin ? Et oui juste la fin de la réponse…

3.2 Après les tests, le programme fonctionnel :

Donc j’ai passé un peu de temps à voir comment récupérer juste le contenu de mon fichier « out.txt », j’ai retravaillé le fichier « WebClient.ino » car d’une part, tout était dans le void setup, et d’autre part, il me fallait récupérer l’essentiel (c’est lors de cette étape que j’ai rajouté les délimiter « [ » dans le fichier netatmo.php).

Voici mon code :

#include <Adafruit_CC3000.h>
#include <LiquidCrystal.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"


#define ADAFRUIT_CC3000_IRQ   3  // MUST be an interrupt pin!
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIVIDER); // you can change this clock speed

#define WLAN_SSID       "SSID Wifi"           // cannot be longer than 32 characters!
#define WLAN_PASS       "Mot de passe Wifi"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY   WLAN_SEC_WPA2

#define IDLE_TIMEOUT_MS  3000      // Amount of time to wait (in milliseconds) with no data
                                   // received before closing the connection.  If you know the server
                                   // you're accessing is quick to respond, you can reduce this value.

// What page to grab!
#define WEBSITE      "192.168.1.50"             //ip NAS
#define WEBPAGE      "/Netatmo/out.txt"         //Chemin du fichier Out


LiquidCrystal lcd(42,41,37,38,39,40);

/**************************************************************************/
/*!
    @brief  Sets up the HW and the CC3000 module (called automatically
            on startup)
*/
/**************************************************************************/

uint32_t ip;

void setup(void)
{
  Serial.begin(115200);
  lcd.begin(16,2);
  lcd.clear();
  lcd.write("test");
}

void loop(void)
{
    Serial.println(F("Hello, CC3000!n"));

  Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);

  /* Initialise the module */
  Serial.println(F("nInitializing..."));
  if (!cc3000.begin())
  {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    while(1);
  }

  // Optional SSID scan
  // listSSIDResults();

  Serial.print(F("nAttempting to connect to ")); Serial.println(WLAN_SSID);
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    while(1);
  }

  Serial.println(F("Connected!"));

  /* Wait for DHCP to complete */
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())
  {
    delay(100); // ToDo: Insert a DHCP timeout!
  }

  /* Display the IP address DNS, Gateway, etc. */
  while (! displayConnectionDetails()) {
    delay(1000);
  }

  ip = 0;
  // Try looking up the website's IP address
  Serial.print(WEBSITE); Serial.print(F(" -> "));
  while (ip == 0) {
    if (! cc3000.getHostByName(WEBSITE, &ip)) {
      Serial.println(F("Couldn't resolve!"));
    }
    delay(500);
  }

  cc3000.printIPdotsRev(ip);

  // Optional: Do a ping test on the website
  /*
  Serial.print(F("nrPinging ")); cc3000.printIPdotsRev(ip); Serial.print("...");
  replies = cc3000.ping(ip, 5);
  Serial.print(replies); Serial.println(F(" replies"));
  */

  /* Try connecting to the website.
     Note: HTTP/1.1 protocol is used to keep the server from closing the connection before all data is read.
  */
  Adafruit_CC3000_Client www = cc3000.connectTCP(ip, 80);
  if (www.connected()) {
    www.fastrprint(F("GET "));
    www.fastrprint(WEBPAGE);
    www.fastrprint(F(" HTTP/1.1rn"));
    www.fastrprint(F("Host: ")); www.fastrprint(WEBSITE); www.fastrprint(F("rn"));
    www.fastrprint(F("rn"));
    www.println();
  } else {
    Serial.println(F("Connection failed"));
    return;
  }

  Serial.println(F("-------------------------------------"));
  int i=0;
  String message ="";
  /* Read data until either the connection is closed, or the idle timeout is reached. */
  unsigned long lastRead = millis();
  while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
    while (www.available()) {
      char c = www.read();
      message += c;
      Serial.print(c);
      lastRead = millis();
    }
  }

 //Serial.println(message);
  www.close();
  Serial.println(F("-------------------------------------"));

  /* You need to make sure to clean up after yourself or the CC3000 can freak out */
  /* the next time your try to connect ... */
  Serial.println(F("nnDisconnecting"));
  cc3000.disconnect();

  char messageChar[500];
  message.toCharArray(messageChar,500);

  char dlm[] = "[";
            int cnt = 0;
            char* tab[255] = { 0 };
            char *pch = strtok(messageChar, dlm);
            while ( pch != NULL ) {
              if (cnt < 60) {
              tab[cnt++] = pch;
              } else {
              break;
              }
            pch = strtok (NULL, dlm);
            }


  char *chaine = tab[1];
  //Serial.println(chaine);
  char dlm2[] = "n";
            int cnt2 = 0;
            char* tab2[255] = { 0 };
            char *pch2 = strtok(chaine, dlm2);
            while ( pch2 != NULL ) {
              if (cnt2 < 60) {
              tab2[cnt2++] = pch2;
              } else {
              break;
              }
            pch2 = strtok (NULL, dlm2);
            }
 char *temp = tab2[0];
 Serial.print(temp);
 lcd.clear();
 lcd.setCursor(0,0);
 lcd.write("t:");
 lcd.write(temp);
 lcd.write("C CO2:");
 lcd.write(tab2[1]);
 lcd.setCursor(0,1);
 lcd.write("h:");
 lcd.write(tab2[2]);
 lcd.write("% p:");
 lcd.write(tab2[3]);

 delay(120000);
}

/**************************************************************************/
/*!
    @brief  Begins an SSID scan and prints out all the visible networks
*/
/**************************************************************************/

void listSSIDResults(void)
{
  uint32_t index;
  uint8_t valid, rssi, sec;
  char ssidname[33];

  if (!cc3000.startSSIDscan(&index)) {
    Serial.println(F("SSID scan failed!"));
    return;
  }

  Serial.print(F("Networks found: ")); Serial.println(index);
  Serial.println(F("================================================"));

  while (index) {
    index--;

    valid = cc3000.getNextSSID(&rssi, &sec, ssidname);

    Serial.print(F("SSID Name    : ")); Serial.print(ssidname);
    Serial.println();
    Serial.print(F("RSSI         : "));
    Serial.println(rssi);
    Serial.print(F("Security Mode: "));
    Serial.println(sec);
    Serial.println();
  }
  Serial.println(F("================================================"));

  cc3000.stopSSIDscan();
}

/**************************************************************************/
/*!
    @brief  Tries to read the IP address and other connection details
*/
/**************************************************************************/
bool displayConnectionDetails(void)
{
  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;

  if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
  {
    Serial.println(F("Unable to retrieve the IP Address!rn"));
    return false;
  }
  else
  {
    Serial.print(F("nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
    Serial.print(F("nNetmask: ")); cc3000.printIPdotsRev(netmask);
    Serial.print(F("nGateway: ")); cc3000.printIPdotsRev(gateway);
    Serial.print(F("nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
    Serial.print(F("nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
    Serial.println();
    return true;
  }
}

Et voici le résultat :

IMG_2739

3.3 Ce qu’il reste à faire :

  • J’ai commandé un écran LCD 20×4 I2C car sur le 16×2 (qui n’est pas en I2C) je ne peux pas tout afficher.
  • Voir pour récupérer les infos du pluviomètre.
Publié le

Mes premiers pas avec mon Raspberry pi 2

Depuis la sortie du Raspberry Pi, je voulais m’en offrir un, mais je n’ai jamais sauté le pas.

Cette semaine je me suis enfin décidé et j’ai reçu hier mon Raspberry Pi 2 !

Bien entendu j’avais déjà un projet en tête quand je l’ai commandé : faire un serveur IOT avec EasyIOT.

 

Installation du Raspberry Pi :

Première étape, créer une carte micro SD avec le système Raspbian.

Je ne vais pas détailler ici comment j’ai créé la carte micro SD car la documentation est très bien faite.

Une fois la carte prête, direction le Raspberry Pi.

J’ai configuré mon Raspberry Pi sans écran (pratique de le configurer en se connectant par ssh depuis mon iMac).

 

Réglages initiaux :

Par défaut le nom d’utilisateur du Rasperry Pi est « pi » et le mot de passe « raspberry ».

Pour la connection ssh, il suffit de taper dans le terminal

ssh pi@192.168.1.66

(En remplaçant 192.168.1.66 par l’adresse ip du Raspberry Pi).

La première étape est de changer le mot de passe de l’utilisateur « pi » :

pi@raspberrypi ~ $ sudo raspi-config

La fenêtre de configuration s’affiche :

config

On se place sur le choix 2, on valide et :

Capture2

On valide et on se retrouve dans le shell. On tape le mot de passe on valide avec entrée, on le confirme avec entrée.

La première étape est finie !

On va voir maintenant comment installer EasyIOT !

 

Installation de EasyIOT :

Première chose à faire, aller faire un tout sur iot-playground.

Je pourrais vous dire de suivre le tuto, mais j’ai eu quelques galères donc autant les partager ici.

 

Téléchargement d’EasyIOT :

J’ai eu quelques soucis avec la version v0.9, donc j’ai décidé d’installer la version v0.8, il se télécharge ici.

Je l’ai extrait sur le bureau et direction le terminal :

imac-de-jean-pierre:~ jp$ cd Desktop/
imac-de-jean-pierre:Desktop jp$ tar cf easy.tar easyiot
imac-de-jean-pierre:Desktop jp$ sftp pi@192.168.1.66
pi@192.168.1.66's password:
Connected to 192.168.1.66.
sftp> put easy.tar
Uploading easy.tar to /home/pi/easy.tar
easy.tar                                      100% 4559KB   4.5MB/s   00:01
sftp> exit

Direction le terminal avec la connexion ssh ouverte (oui ce terminal on ne le ferme pas) :

pi@raspberrypi ~ $ tar xf easy.tar
pi@raspberrypi ~ $ rm easy.tar

On a ainsi extrait notre dossier et effacé notre archive.

 

Préparation avant la configuration d’EasyIOT :

Petit tour de nouveau dans la configuration du Raspberry Pi :

sudo raspi-config

Choix 8 « Advanced Options », choix A6 « SPI »

« Would you like the SPI interface to be enabled » => Yes.

On valide.

« Would you like the SPi kernel module to be loaded by default ? » => Yes

Si le système ne le demande pas, on fait un petit reboot :

sudo reboot

On va connecter un module NRF24L01+ au Raspberry Pi (je ne l’utilise pas encore, mais on va quand même le connecter).

Attention là aussi avec le tuto, le modèle du Raspberry pi présenté n’est pas un Pi 2.

Untitled Sketch_bb

Installation de MONO :

Allez on attaque l’installation de Mono :

sudo apt-get update
sudo apt-gat upgrade
sudo apt-get install mono-complete

Ca prend en gros 5 minutes, des fois moins.

Configuration de EasyIOT :

Première étape, on se place dans le dossier d’EasyIOT pour changer les permission de fichiers  :

cd /home/easyiot
sudo chown -R root log
sudo chmod -R 644 log
sudo chown -R root config
sudo chmod -R 644 config

Je rajoute une étape par rapport au tuto sur IOT Playground car sinon les mesures n’étaient pas sauvegardées dans la base de données :

sudo chown -R EasyIoTDatabase.sqlite

Pour nous simplifier la vie, on va lancer EasyIOT comme un service (il sera donc lancé au démarrage du Raspberry PI) :

On commence par télécharger l’archive easyiot

Un petit coup de sftp comme tout à l’heure pour l’envoyer sur le Raspberry Pi, on repasse sur la console ssh (note on est toujours dans le dossier easyiot) et :

sudo mv ../easyiot.tar /etc/init.d/
sudo tar xf /etc/init.d/easyiot
sudo rm easyiot.tar

Il ne nous reste plus qu’à terminer la configuration pour le lancement automatique :

sudo chmod +x /etc/init.d/easyiot
sudo chmod +x startup.sh
sudo update-rc.d easyiot defaults

On peut stopper et mettre en en route le service avec les commandes :

sudo /etc/init.d/easyiot stop

sudo /etc/init.d/easyiot start

A présent EasyIOT est installé sur le Raspberry Pi et fonctionnel.

Prochaine étape ajouter un capteur température !

Publié le

Capteur RFID

Semaine très chargée et week-end à venir encore plus… Je vais quand même prendre un peu de temps pour vous présenter le capteur RFID RC522 que j’ai reçu aujourd’hui.

Déballage :

Voici le petit bijou que j’ai reçu :

 

IMG_2665

Il se compose donc :

  • Un module  RV522
  • Une carte RFID
  • Un porte clef RFID

Le montage :

  • Un arduino MEGA
  • Deux LEDS
  • Deux résistances de 330Ω
  • Des fils…

Pour la connection du capteur RFID sur une arduino MEGA :

MOSI: Pin 51 / ICSP-4
MISO: Pin 50 / ICSP-1
SCK : Pin 52 / ISCP-3
SDA : Pin 53 (Configurable)
RST : Pin 5 (Configurable)

Si ce n’est pas un MEGA :

MOSI: Pin 11 / ICSP-4
MISO: Pin 12 / ICSP-1
SCK : Pin 13 / ISCP-3
SDA : Pin 10 (Configurable)
RST : Pin 9 (Configurable)

Je vous propose le montage COMPLET (c’est à dire avec les LEDS mais qui ne vont pas servir dans la première partie de l’article :

ATTENTION LE MODULE RFID FONCTIONNE EN 3,3V 

RFID-mega_bb1 RFID-Nano_bb

Lecture de l’identifiant de la carte et du porte clef :

Les cartes RFID possèdent un identifiant qu’il va falloir retrouver pour pouvoir ensuite savoir si notre carte est autorisée ou refusée.

#include <SPI.h>                            // Librairies nécessaires
#include <RFID.h>

RFID monModuleRFID(53,5);                  // On déclare les PINS SDA et RST Pour le NANO : monModuleRFID(10,9)

int UID[5];                                // On crée notre variable qui vit stocker l'UID de notre carte

void setup()
{
  Serial.begin(9600);
  SPI.begin();
  monModuleRFID.init();                    // On initialise le module RFID

}

void loop()
{
    if (monModuleRFID.isCard()) {
          if (monModuleRFID.readCardSerial()) {
            Serial.print("L'UID est: ");
            for(int i=0;i<=4;i++)
            {
              UID[i]=monModuleRFID.serNum[i];
              Serial.print(UID[i],DEC);
              Serial.print(".");
            }
            Serial.println("");
          }
          monModuleRFID.halt();
    }
    delay(5000);
}

En sortie j’obtient ceci (J’ai passé le porte clef et premier puis la carte) :

Sans-titre2

  • Porte clef : 105.115.122.158.254
  • Carte : 138.55.50.59.180

Commande d’une LED :

Mettons en pratique l’authentification. Je vais programmer pour que le porte clef soit reconnu comme valide (LED verte) et que la carte soit invalide (LED ROUGE) :

#include <SPI.h>
#include <RFID.h>

const char DOUT_LED_ROUGE = 2;
const char DOUT_LED_VERTE = 3;

RFID monModuleRFID(53,5);

int UID[5]={};
int MASTERKEY[5]={105,115,122,158,254};

void setup()
{
  Serial.begin(9600);
  SPI.begin();
  monModuleRFID.init();
  pinMode(DOUT_LED_ROUGE, OUTPUT);
  pinMode(DOUT_LED_VERTE, OUTPUT);
  digitalWrite(DOUT_LED_ROUGE, LOW);
  digitalWrite(DOUT_LED_VERTE, LOW);

}

void loop()
{
    if (monModuleRFID.isCard()) {
          if (monModuleRFID.readCardSerial()) {
            Serial.print("L'UID est: ");
            for(int i=0;i<=4;i++)
            {
              UID[i]=monModuleRFID.serNum[i];
              Serial.print(UID[i],DEC);
              Serial.print(".");
            }
            Serial.println("");
          }

          if (UID[0] == MASTERKEY[0]
           && UID[1] == MASTERKEY[1]
           && UID[2] == MASTERKEY[2]
           && UID[3] == MASTERKEY[3]
           && UID[4] == MASTERKEY[4])
          {
              digitalWrite(DOUT_LED_VERTE, HIGH);
              delay(500);
              digitalWrite(DOUT_LED_VERTE, LOW);
          }
          else
          {
              digitalWrite(DOUT_LED_ROUGE, HIGH);
              delay(500);
              digitalWrite(DOUT_LED_ROUGE, LOW);
          }
          monModuleRFID.halt();
    }
    delay(1);
}

Le résultat en vidéo :

Téléchargement des librairies ICI