mercredi 12 mars 2014

Intégartion des modules Fibaro sur rail DIN

En vue d'intégrer mes modules Fibaro d'ouverture/fermeture de volets roulants dans le tableau électrique, je me suis mis à les intégrer dans des boitiers sur rail DIN.
Boitiers disponibles à cette adresse : http://www.altinkaya.eu/66-din-rail-enclosure-components
- Modèle RT-204 : 3 modules par boitiers.
- Les boitiers sont ajourés pour la ventilation
- c'est propre et facile à câbler.

Boitier ouvert :

Le bornier à 2 pôles en haut à gauche recevra la phase et le neutre. Le bornier à côté les fils de montée/descente allant vers le moteur du volet roulant. Le bornier du bas, les fils venant d'un interrupteur mural (optionnel)
Boitier fermé :  
Boitier fermé avec verre fumé:
Coffret fermé.

 Maintenant que le proto est validé, me reste plus qu'à faire un joli typon et fabriquer le circuit imprimé propre en 4 exemplaires  pour mes besoins



mardi 11 septembre 2012

Téléinformation 5/5 (Affichage des valeurs)

Pour l'affichage, j'ai décider d'utiliser le framework http://www.highcharts.com/ qui est très flexible en terme d'affichage et plutôt facile à paramétrer.



J'ai un premier fichier index.html contenant le code suivant :
<FRAMESET ROWS="500,500">
<FRAME SRC="index.php">
<FRAME SRC="index2.php">
</FRAMESET>


Le fichier index.php m'affichera les courbes de consommation instantannées mesurées
Le fichier index2.php m'affichera les graphes de consommation sur une journée, mois et le tarif associé

Pour ce qui est de index.php, voici le code :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<title>Using Highcharts with PHP and MySQL</title>

<script type="text/javascript" src="js/jquery-1.7.2.min.js" ></script>
<script type="text/javascript" src="js/highcharts.js" ></script>
<script type="text/javascript" src="js/themes/gray.js"></script>

<script type="text/javascript">
    var chart;
   
function GetUrlParameter( name )
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}

    $(document).ready(function() {
                var options = {
                    chart: {
                        renderTo: 'container',
                        defaultSeriesType: 'spline',
                        zoomType: 'x'
                    },
                    title: {
                        text: 'Consommation électrique',
                        x: -20 //center
                    },
                    rangeSelector : {
                        buttons : [{
                          type : 'hour',
                          count : 1,
                          text : '1h'
                        },{
                          type : 'hour',
                          count : 3,
                          text : '3h'
                        },{
                          type : 'hour',
                          count : 6,
                          text : '6h'
                        },{
                          type : 'hour',
                          count : 9,
                          text : '9h'
                        },{
                          type : 'hour',
                          count : 12,
                          text : '12h'
                        },{
                          type : 'all',
                          count : 1,
                          text : 'All'
                        }],
                        selected : 5,
                        inputEnabled : false
                    },
                    xAxis: {
                        type: 'datetime',
                        //tickInterval: 3600 * 1000, // one hour
                        //tickWidth: 0,
                        //gridLineWidth: 1,
                        maxZoom: 12 * 3600000, // 12 hours
                        //labels: {
                        //    align: 'center',
                        //    x: -3,
                        //    y: 20,
                        //    formatter: function() {
                        //        return Highcharts.dateFormat('%d.%m.%y', this.value) + '<br/>' + Highcharts.dateFormat('%H:%M',this.value) ;
                        //    }
                        //}
                       
                    },
                    yAxis: { // Primary yAxis,
                        title: {
                            text: 'Consommation',
                        },
                        min: 0,
                        labels: {
                            formatter: function() {
                                return this.value +' Watts';
                            },
                            style: {
                                color: '#808080'
                            }
                        }
                    },           
                    legend: {
                        backgroundColor: '0',
                        reversed: false
                    },
                    plotOptions: {
                        spline: {
                            lineWidth: 4,
                            states: {
                                hover: {
                                    lineWidth: 5
                                }
                            },
                            marker: {
                                enabled: false,
                                states: {
                                    hover: {
                                        enabled: true,
                                        symbol: 'circle',
                                        radius: 5,
                                        lineWidth: 1
                                    }
                                }
                            }
                        }
                    },
                    series: [{
                        type: 'spline',
                        name: 'Heures Pleines',
                        color: 'red',
                        yAxis: 0
                    }, {
                        type: 'spline',
                        color: 'blue',
                        name: 'Heures Creuses',
                        yAxis: 0
                    }],
                    //exporting: {
                    //    url: 'http://export.highcharts.com/index-utf8-encode.php'
                    //}
                }
                // Load data asynchronously using jQuery. On success, add the data
                // to the options and initiate the chart.
                // This data is obtained by exporting a GA custom report to TSV.
                // http://api.jquery.com/jQuery.get/
               
                jQuery.get('data.php?periode='+GetUrlParameter('periode'), null, function(tsv) {
                    var lines = [];
                    HCHP = [];
                    HCHC = [];
                    try {
                        // split the data return into lines and parse them
                        tsv = tsv.split(/\n/g);
                        jQuery.each(tsv, function(i, line) {
                            line = line.split(/\t/);
                            date = Date.parse(line[0].replace(/-/g,'/').replace(/\.\d*$/,'') +' UTC');
                            //date = Date.parse(line[0] +' UTC');
                            if (line[1] == "HP" && line[2] != '') {
                       
                                HCHP.push([    date, parseInt(line[2].replace(',', '')) ]);
                                HCHC.push([    date, 0 ]);
                            } else if (line[1] == "HC" && line[2] != '') {
                           
                                HCHP.push([    date, 0    ]);
                                HCHC.push([    date, parseInt(line[2].replace(',', '')) ]);
                            }
                        });
                    } catch (e) {  }
                    options.series[0].data = HCHP;
                    options.series[1].data = HCHC;
                   
                    chart = new Highcharts.Chart(options);
                });
            });
</script>
</head>
<body>
<style>
input[type="submit"]{
width:100px;
height:30px;
margin-left:20px;
font-size:1em;
font-weight:bold;
border:none;
color:#cecece;
text-shadow:0px -1px 0px #000;
background:#1f2026;
background:-moz-linear-gradient(top,#1f2026,#15161a);
background:-webkit-gradient(linear,left top,left bottom,from(#1f2026),to(#15161a));
-webkit-border-radius:5px;
   -moz-border-radius:5px;
        border-radius:5px;
-webkit-box-shadow:0px 0px 1px #000;
   -moz-box-shadow:0px 0px 1px #000;
        box-shadow:0px 0px 1px #000;
}
input[type="submit"]:hover{
background:#343640;
background:-moz-linear-gradient(top,#343640,#15161a);
background:-webkit-gradient(linear,left top,left bottom,from(#343640),to(#15161a));
}
</style>
<div id="container" style="width: 100%; height: 400px; margin: 0 auto"></div>
                    <br /><br />
    <form method="GET" action="<?php echo $_SERVER['PHP_SELF'];?>" style="text-align: center;" >
        <input type="submit" value="1jour" name="periode">
        <input type="submit" value="8jours" name="periode">
        <input type="submit" value="1mois" name="periode">
        <input type="submit" value="6mois" name="periode">
        <input type="submit" value="1an" name="periode">
    </form>
</body>
</html>


Pour index2.php, voici le code :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<title>Using Highcharts with PHP and MySQL</title>

<script type="text/javascript" src="js/jquery-1.7.2.min.js" ></script>
<script type="text/javascript" src="js/highcharts.js" ></script>
<script type="text/javascript" src="js/themes/gray.js"></script>

<script type="text/javascript">
    var chart;
   
function GetUrlParameter( name )
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}
  // prix tarif HP/HC EDF
var prixHP = 0.1312;
var prixHC = 0.0895;
  // Abpnnement pour disjoncteur 45 A
var abonnement = 112.87;

    $(document).ready(function() {
                var options = {
                    chart: {
                        renderTo: 'container',
                        defaultSeriesType: 'column'
                    },
                    title: {
                        text: 'Consommation électrique',
                        x: -20 //center
                    },
                    xAxis: [{
                        //categories: ['Apples', 'Oranges', 'Pears']
                        //type: 'datetime'
                        //tickInterval: 3600 * 1000, // one hour
                        //tickWidth: 0,
                        //gridLineWidth: 1,
                        //maxZoom: 12 * 3600000, // 12 hours
                        //labels: {
                        //    align: 'center',
                        //    x: -3,
                        //    y: 20,
                        //    formatter: function() {
                        //        return Highcharts.dateFormat('%d.%m.%y', this.value) + '<br/>' + Highcharts.dateFormat('%H:%M',this.value) ;
                        //    }
                        //}
                       
                    }],
                    yAxis: [{
                        title: {
                            text: 'Heures Creuses  -  Heures Pleines',
                        },
                        min: 0,
                        labels: {
                            formatter: function() {
                                return this.value +' kWh';
                            },
                            style: {
                                color: '#808080'
                            }
                        },
                        stackLabels: {
                            formatter: function() {
                                return Highcharts.numberFormat(this.total, 1) + ' kWh';
                            },
                            enabled: true
                        }
                    }],
                    tooltip: {
                        formatter: function() {
                            totalHP=prixHP*((this.series.name == 'Heures Pleines')? this.y :this.point.stackTotal-this.y);
                            totalHC=prixHC*((this.series.name == 'Heures Creuses')? this.y :this.point.stackTotal-this.y);
                            totalprix=Highcharts.numberFormat(( totalHP + totalHC),2);
                            tooltip = '<b> '+ this.x +' <b><br /><b>Consommation : '+ Highcharts.numberFormat(this.total, 1) +' kWh<b><br />';
                            tooltip += 'HP : '+ Highcharts.numberFormat(totalHP,2) + ' Euro / HC : ' + Highcharts.numberFormat(totalHC,2) + ' Euro<br />';
                            tooltip += '<b> Total: '+ totalprix +' Euro<b>';
                            return tooltip;
                        }
                    },
                   
                    legend: {
                        backgroundColor: '0',
                        reversed: false
                    },
                    plotOptions: {
                        column: {
                            stacking: 'normal',
                        }
                    },
                    series: [{
                        name : 'Heures Pleines',
                        color: 'red',
                        dataLabels: {
                            enabled: true,
                            color: '#FFFFFF'
                        },
                        type: 'column'
                    }, {
                        name : 'Heures Creuses',
                        color: 'blue',
                        dataLabels: {
                            enabled: true,
                            color: '#FFFFFF'
                        },
                        type: 'column'
                    }],
                    //exporting: {
                    //    url: 'http://export.highcharts.com/index-utf8-encode.php'
                    //}
                }
                // Load data asynchronously using jQuery. On success, add the data
                // to the options and initiate the chart.
                // This data is obtained by exporting a GA custom report to TSV.
                // http://api.jquery.com/jQuery.get/
               
                jQuery.get('data2.php?periode='+GetUrlParameter('periode'), null, function(tsv) {
                    var lines = [];
                    HCHP = [];
                    HCHC = [];
                    date = [];
                    try {
                        // split the data return into lines and parse them
                        tsv = tsv.split(/\n/g);
                        jQuery.each(tsv, function(i, line) {
                            line = line.split(/\t/);
                            //date = Date.parse(line[0].replace(/-/g,'/').replace(/\.\d*$/,'') +' UTC');
                            //date = Date.parse(line[1] +' UTC');
                            if (line[1] != '') {
                                date.push([line[1]]);
                            }
                            if (line[2] != '') {
                                HCHP.push([line[1],    parseFloat(line[2].replace(',', ''),10) ]);   
                            }
                            if (line[3] != '') {
                                HCHC.push([line[1],    parseFloat(line[3].replace(',', ''),10) ]);
                            }
                        });
                    } catch (e) {  }
                    options.series[0].data = HCHP;
                    options.series[1].data = HCHC;
                    options.xAxis[0].categories = date;
                   
                    chart = new Highcharts.Chart(options);
                });
            });
</script>
</head>
<body>
<style>
input[type="submit"]{
width:100px;
height:30px;
margin-left:20px;
font-size:1em;
font-weight:bold;
border:none;
color:#cecece;
text-shadow:0px -1px 0px #000;
background:#1f2026;
background:-moz-linear-gradient(top,#1f2026,#15161a);
background:-webkit-gradient(linear,left top,left bottom,from(#1f2026),to(#15161a));
-webkit-border-radius:5px;
   -moz-border-radius:5px;
        border-radius:5px;
-webkit-box-shadow:0px 0px 1px #000;
   -moz-box-shadow:0px 0px 1px #000;
        box-shadow:0px 0px 1px #000;
}
input[type="submit"]:hover{
background:#343640;
background:-moz-linear-gradient(top,#343640,#15161a);
background:-webkit-gradient(linear,left top,left bottom,from(#343640),to(#15161a));
}
</style>
<div id="container" style="width: 100%; height: 400px; margin: 0 auto"></div>
                    <br /><br />
    <form method="GET" action="<?php echo $_SERVER['PHP_SELF'];?>" style="text-align: center;" >
        <input type="submit" value="jours" name="periode">
        <input type="submit" value="semaines" name="periode">
        <input type="submit" value="mois" name="periode">
    </form>
</body>
</html>


index.php et index2.php appel respectivement data.php et data2.php pour extraire le données de la base de donnée. L'avantage est que l'extraction des données de fait en parallèle de l'affichage.

data.php :
<?php
if (isset($_GET['periode'])) {
  $periode = $_GET['periode'] ;
} else  $periode = "8jours" ;

$con = mysql_connect("xxxxx","
xxxxx","xxxxx");

if (!$con) {
  die('Could not connect: ' . mysql_error());
}

mysql_select_db("
xxxxx", $con);


switch ($periode) {
    case "1jour":
        $result = mysql_query("SELECT * FROM teleinfo WHERE TO_DAYS(NOW()) - TO_DAYS(temps) < 1 ORDER BY id ");
        break;
    case "8jours":
        $result = mysql_query("SELECT * FROM teleinfo WHERE TO_DAYS(NOW()) - TO_DAYS(temps) < 8 ORDER BY id ");
        break;
    case "1mois":
        $result = mysql_query("SELECT * FROM teleinfo WHERE TO_DAYS(NOW()) - TO_DAYS(temps) < 31 ORDER BY id ");
        break;
    case "6mois":
        $result = mysql_query("SELECT * FROM teleinfo WHERE TO_DAYS(NOW()) - TO_DAYS(temps) < 180 ORDER BY id ");
        break;
    case "1an":
        $result = mysql_query("SELECT * FROM teleinfo WHERE TO_DAYS(NOW()) - TO_DAYS(temps) < 365 ORDER BY id ");
        break;
    default:
        $result = mysql_query("SELECT * FROM teleinfo WHERE TO_DAYS(NOW()) - TO_DAYS(temps) < 1 ORDER BY id ");
        break;
}

while($row = mysql_fetch_array($result)) {
  echo $row['temps']. "\t" . $row['ptec']. "\t" . $row['papp']. "\n";
}
mysql_close($con);
?>



data2.php :
<?php
if (isset($_GET['periode'])) {
  $periode = $_GET['periode'] ;
} else  $periode = "jours" ;

$con = mysql_connect("
xxxxx","xxxxx","xxxxx");

if (!$con) {
  die('Could not connect: ' . mysql_error());
}

mysql_select_db("
xxxxx", $con);


switch ($periode) {
    case "jours":
        $result = mysql_query("SELECT temps, DATE_FORMAT(temps, '%a %e' ) AS 'periode', ROUND( ((MAX( `hchp` ) - MIN( `hchp` ) ) /1000), 1), ROUND( ((MAX( `hchc` ) - MIN( `hchc` ) ) /1000), 1) FROM teleinfo GROUP BY periode ORDER BY id");
        break;
    case "semaines":
        $result = mysql_query("SELECT temps, DATE_FORMAT( temps, 'sem %v' ) AS 'periode', ROUND( ((MAX( `hchp` ) - MIN( `hchp` ) ) /1000), 1), ROUND( ((MAX( `hchc` ) - MIN( `hchc` ) ) /1000), 1) FROM teleinfo GROUP BY periode ORDER BY id");
        break;
    case "mois":
        $result = mysql_query("SELECT temps, DATE_FORMAT( temps, '%b' ) AS 'periode', ROUND( ((MAX( `hchp` ) - MIN( `hchp` ) ) /1000), 1), ROUND( ((MAX( `hchc` ) - MIN( `hchc` ) ) /1000), 1) FROM teleinfo GROUP BY periode ORDER BY id");
        break;
    default:
        $result = mysql_query("SELECT temps, DATE_FORMAT( temps, '%a %e' ) AS 'periode', ROUND( ((MAX( `hchp` ) - MIN( `hchp` ) ) /1000), 1), ROUND( ((MAX( `hchc` ) - MIN( `hchc` ) ) /1000), 1) FROM teleinfo GROUP BY periode ORDER BY id");
        break;
}


while($row = mysql_fetch_array($result)) {
  echo $row['temps'] . "\t" . $row[1]. "\t" . $row['2']. "\t" . $row['3']. "\n";
}
mysql_close($con);
?>


Il faut de plus un répertoire js/ contenant les fichiers que vous trouverez dans le framework sur le site :
js/jquery-1.7.2.min.js
(ou plus récent)

js/highcharts.js
js/themes/gray.js

mardi 28 août 2012

Téléinformation 4/5 (Base de données)

Et enfin ,la partie sauvegarde/affichage.
Ceci est possible sur un site hébergé ou bien sur un NAS en local.
Les pré-requis sont d'avoir une base de donnée (MySQL pour ma part) et PHP.

Commençons par la base de données.
J'ai donc une base de données définie comme cela :

Voici le script SQL pour créer la base :

CREATE TABLE IF NOT EXISTS `teleinfo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `temps` datetime DEFAULT NULL,
  `hchp` bigint(9) DEFAULT NULL,
  `hchc` bigint(9) DEFAULT NULL,
  `ptec` text CHARACTER SET latin1 COLLATE latin1_general_ci,
  `papp` int(5) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7317 ;


Une fois la table créée, il faut avoir les fichiers php qui vont bien pour que la vera puisse insérer les élément dans le table.
Comme vu dans le poste précédent, la vera appel le fichier update.php qui est le suivant :

<?php
// Connexion MySql et requète.
$serveur="xxxxxx";
$login="xxxxxx";
$base="xxxxxx";
$pass="xxxxxx";
$table="teleinfo";

if(!isset($_GET["HCHP"])) {
    $hchp= "NULL";
}else {
    $hchp= $_GET["HCHP"];
}

if(!isset($_GET["HCHC"])) {
    $hchc= "NULL";
}else {
    $hchc= $_GET["HCHC"];
}

if(!isset($_GET["PTEC"])) {
    $ptec= "NULL";
}elseif ($_GET["PTEC"] == "HP..") {
    $ptec= "HP";
}elseif ($_GET["PTEC"] == "HC..") {
    $ptec= "HC";
}

if(!isset($_GET["PAPP"])) {
    $papp= "NULL";
}else {
    $papp= $_GET["PAPP"];
}

$con = mysql_connect($serveur, $login, $pass);
if (!$con)
  {
  die('Could not connect: ' . mysql_error());
  }

mysql_select_db($base) or die("Erreur de connexion a la base de donnees $base");
mysql_query("SET NAMES 'utf8'");

$requete = mysql_query("INSERT INTO $table (temps,hchp,hchc,ptec,papp) VALUES(NOW(),$hchp,$hchc,'$ptec',$papp)");
?>


Enfin il faut un la vera envera à intervalle régulier dans le base de données les valeurs issues de la carte arduino contenant le compteur EDF HP, HC, la tranche horaire, la puissance instantannée consommée. La date y sera ajoutée lors de l'insertion dans la base.

Le prochain message sera sur l'affichage.

Téléinformation 3/5 (VERA)

Passons maintenant à la vera.
Dans Apps > Develop Apps > Edit Startup Lua j'ai rajouté une fonction pour me permettre d'extraire les valeurs des champs XML.
Voici la fonction en question à rajouter telle quelle:

function extractElement(tag, xml, default)
    local pattern = "<"..tag..">(.*)</"..tag..">"
    local result = (xml:match(pattern) or default)
    return result
end



Maintenant j'ai créé un virtual container nommé EDF. Noter son ID pour la scéne de mise à jour.

Et enfin, je créé une scène qui, à intervalle régulier, va me récupérer les infos de mon arduino et me les afficher dans mon virtual container ainsi que m'envoyer les info sur mon site WEB pour l'affichage de l'historique

 Ma scène se compose exclusivement d'un code LUUP qui se déclenche à intervalle régulier toutes les 10 min mais peut être modifié à volonté suivant la précision que l'on souhaite.
Nous verrons dans le prochain message la mise en oeuvre de la partie WEB.

luup.log("Update VContainer EDF teleinfo")
local SID_Vc = "urn:upnp-org:serviceId:VContainer1"

local lul_cmd = "http://192.168.1.202/"
local code, res = luup.inet.wget(lul_cmd,10, "" ,"")
if (code == 0) then
  local hchp= extractElement("HCHP", res, "N/A")
  luup.variable_set(SID_Vc, "VariableName1","HCHP (KW)", VMOD_CONT_EDF)
  luup.variable_set(SID_Vc, "Variable1",math.floor(hchp/1000),VMOD_CONT_EDF)

  local hchc= extractElement("HCHC", res, "N/A")
  luup.variable_set(SID_Vc, "VariableName2","HCHC (KW)", VMOD_CONT_EDF)
  luup.variable_set(SID_Vc, "Variable2",math.floor(hchc/1000),VMOD_CONT_EDF)

  local ptec= extractElement("PTEC", res, "N/A")
  luup.variable_set(SID_Vc, "VariableName3","PTEC", VMOD_CONT_EDF)
  luup.variable_set(SID_Vc, "Variable3",ptec,VMOD_CONT_EDF)

  local papp= extractElement("PAPP", res, "N/A")
  luup.variable_set(SID_Vc, "VariableName4","PAPP (W)", VMOD_CONT_EDF)
  luup.variable_set(SID_Vc, "Variable4",papp,VMOD_CONT_EDF)

   luup.log("Save EDF to my web site")
   local lul_update = 'http://www.mywebsite.com/EDF/update.php?HCHP=' .. hchp .. '&HCHC=' .. hchc .. '&PTEC=' .. ptec .. '&PAPP=' .. papp .. ''
   luup.inet.wget(lul_update,6, "" ,"")
   return true
else
   luup.log("EDF teleinfo ERROR : " .. code)
   return false
end


Ce qui donne le device suivant :

Téléinformation 2/5 (Arduino SW)


#include <SoftwareSerial.h>
#include <SPI.h>
#include <Ethernet.h>

SoftwareSerial cptSerial(2,3);

//#define DebugL1        //envoie seulement pour le débug sur l'USB
//#define DebugL2        //envoie tout sur l'USB

//*****************************************************************************************
  byte inByte = 0 ;        // caractère entrant téléinfo
  char buffteleinfo[21] = "";
  byte bufflen = 0;
 
// declarations Teleinfo
  byte isousc = 0;        // Intensité souscrite, A
  unsigned int papp = 0;  // Puissance apparente, VA

  char ptec[4] = "";      // Période Tarifaire en cours, 4 alphanumériques (HC.. ou HP..)

  unsigned int iinst = 0;      // Monophasé - Intensité Instantanée, A  (intensité efficace instantanée)
   
  unsigned long hchc = 0;
  unsigned long hchp = 0;

#define debtrame 0x02
#define debligne 0x0A
#define finligne 0x0D


byte mac[] = {0x54,0x55,0x58,0x10,0x00,0x26};    // MAC address of Arduino
IPAddress ip(192,168,1, 202);                    // IP address of Arduino

EthernetServer server(80);

// ************** initialisation *******************************
void setup()
{
 // initialisation du port 0-1 lecture Téléinfo
    Serial.begin(1200);
    cptSerial.begin(1200);    // le mode 7 bit parité pair se fait plus loin

 // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();

#ifdef DebugL1
    Serial.print("-- Teleinfo Arduino UNO --");
#endif
}

// ************** boucle principale *******************************

void loop()                     // Programme en boucle
{

  read_teleinfo();
  read_web();

}

///////////////////////////////////////////////////////////////////
// Calcul Checksum teleinfo
///////////////////////////////////////////////////////////////////
char chksum(char *buff, int len)
{
  int i;
  char sum = 0;
    for (i=1; i<(len-2); i++) sum = sum + buff[i];
    sum = (sum & 0x3F) + 0x20;
    return(sum);
}

///////////////////////////////////////////////////////////////////
// Analyse de la ligne de Teleinfo
///////////////////////////////////////////////////////////////////
void traitbuf_cpt(char *buff, int len)
{

  if (strncmp("HCHP ", &buff[1] , 5)==0){
      hchp = atol(&buff[6]);
  #ifdef DebugL1
      Serial.print("- Index Heures Pleines: "); Serial.println(hchp,DEC);
  #endif       
  }

  else if (strncmp("HCHC ", &buff[1] , 5)==0){
      hchc = atol(&buff[6]);
  #ifdef DebugL1
      Serial.print("- Index Heures Creuses: ");Serial.println(hchc,DEC);
  #endif       
  }

  else if (strncmp("IINST ", &buff[1] , 6)==0){
      iinst = atol(&buff[7]);
  #ifdef DebugL1
      Serial.print("- I iNStantannee : "); Serial.println(iinst,DEC);    // valeur à l'ampère près donc à 240W près => pas terrible
  #endif    
  }

  else if (strncmp("PAPP ", &buff[1] , 5)==0){
      papp = atol(&buff[6]);
  #ifdef DebugL1
      Serial.print("- Puissance apparente : ");Serial.println(papp,DEC);
  #endif       
  }

  else if (strncmp("PTEC ", &buff[1] , 5)==0){
        strncpy(ptec, &buff[6], 4);
        ptec[4]='\0';
  #ifdef DebugL1
        Serial.print("- Periode Tarifaire En Cours : "); Serial.println(ptec);
  #endif       
  }
    
}

///////////////////////////////////////////////////////////////////
// Lecture trame teleinfo (ligne par ligne)
///////////////////////////////////////////////////////////////////
void read_teleinfo()
{
  // si une donnée est dispo sur le port série
  if (cptSerial.available() > 0)
  {
  // recupère le caractère dispo
    inByte = (cptSerial.read()& 0x7F);      // le 0X7F pour avoir en 7 bits au lieu de 8

#ifdef DebugL2   
    Serial.print(char(inByte));  // echo des trames sur l'USB (choisir entre les messages ou l'echo des trames)
#endif

    if (inByte == debtrame) bufflen = 0; // test le début de trame
    if (inByte == debligne) // test si c'est le caractère de début de ligne
    {
      bufflen = 0;
    } 
    buffteleinfo[bufflen] = inByte;
    bufflen++;
    if (bufflen > 21)bufflen=0;       // longueur max du buffer (21 pour lire trame ADCO)
    if (inByte == finligne && bufflen > 5) // si Fin de ligne trouvée
    {
      if (chksum(buffteleinfo,bufflen-1)== buffteleinfo[bufflen-2]) // Test du Checksum
      {
        traitbuf_cpt(buffteleinfo,bufflen-1); // ChekSum OK => Analyse de la Trame
      }
    }
  }
}

///////////////////////////////////////////////////////////////////
// Création page Web client
///////////////////////////////////////////////////////////////////
void read_web()
{
    // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    #ifdef DebugL1   
      Serial.println("new request");
    #endif
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        #ifdef DebugL1
          Serial.write(c);
        #endif
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
          client.println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
      client.println("<ARDUINO>");
          client.print("<HCHC>");
          client.print(hchc,DEC);
          client.print("</HCHC>");
          client.print("<HCHP>");
          client.print(hchp,DEC);
          client.print("</HCHP>");
          client.print("<IINST>");
          client.print(iinst,DEC);
          client.print("</IINST>");   
          client.print("<PAPP>");
          client.print(papp,DEC);
          client.print("</PAPP>");
          client.print("<PTEC>");
          client.print(ptec);
          client.print("</PTEC>");
          client.println("</ARDUINO>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    #ifdef DebugL1
      Serial.println("client disonnected");
    #endif
  }
}

Téléinformation 1/5 (Arduino HW)

C'est parti pour le tuto sur la téléinformation couplée à la micasaverde VERA.


Pour la partie hardware, j'ai donc une arduino UNO, une ethernet shield W5100 et une carte supplémentaire dont voici le schéma. J'ai pas trouvé plus simple comme schéma et ça fonctionne parfaitement.
Le schéma viens de là : http://www.chaleurterre.com/forum/viewtopic.php?p=51607#51607

Pour l'optocoupleur, j'ai mis ça : http://fr.farnell.com/jsp/search/productdetail.jsp?SKU=1045384
0.5€ HT le circuit + 2 résistances, c'est pas la ruine.

Ensuite il reste le code de l'arduino, la config de la vera et le site WEB pour avoir l'historique