Afficher l'heure sur une page web (lecture I2C et envoi HTML)

De Wiki_du_Réseau_des_Electroniciens_du_CNRS
Aller à la navigationAller à la recherche

Revenir au sommaire du RasberryPi

installation et configuration

rappel -> Installation et configuration d'un serveur WEB <- voir le tutorial

comme éditeur de texte , nous pouvons utiliser "nano" (simple et léger) ou "geany" qui à l'avantage de pouvoir être graphique, déporté et apporte une "coloration syntaxique"

 sudo apt-get update             # toujours la mise a jour des paquets avant l'installation
 sudo apt-get upgrade            # une petite mise a jour de linux

 sudo apt-get install geany      # l'installation de geany

créer son dossier www de travail

Dans son /home/pi : à quoi cela sert-il ? - Pouvoir créer/éditer les fichiers php propres à notre utilisateur ("pi").

Pour se faire, nous allons donc développer nos codes dans un sous dossier personnalisé (nommé www)

 cd            # retour a la racine de notre home
 mkdir www     # création du répertoire www

nous voulons qu'il soit accessible depuis le web, nous faisons donc un lien symbolique vers ce dossier

 sudo ln -s /home/pi/www /var/www/pi 
 # ln (lien) -s (symbolique)  /home/pi/www (dossier source) /var/www/pi (lien)

ce qui signifie que nous pourrons y accéder via l'adresse http://xxx.xxx.xxx.xxx/pi (ou xxx.xxx.xxx.xxx est l'adresse de la carte)

nous allons éditer notre premier fichier php en nous plaçant dans le dossier WEB si on part de notre home :

cd www              # nous entrons dans le dossier www
# ou
cd ~/www            # ~ = /home/pi
# ou
cd /home/pi/www     # la syntaxe complete

Attaquons notre premier code test

Hello World !

Créons donc un fichier php

Plaçons y notre premier bout de code :

Nous allons créer un fichier nommé index.php ( c'est le premier fichier que le serveur apache cherche a distribuer lors d'une requête internet sans spécification de fichier) C'est le point d'entré de notre site.

 geany index.php

en voici le contenu :

 <!DOCTYPE html>
 <html lang="fr" dir="ltr" class="client-nojs">
 <head>
 <title>Affichage de l'heure sur une page web (lecture I2C et envoi HTML) - d'après le Wiki_du_Réseau_des_Electroniciens_du_CNRS</title>
 <meta charset="UTF-8" />
 </meta>
 <body>
 <?                            
  //ici commence le code php
    echo "hello world!";
  //ici se termine le code php
 ?>                            
 </body>
 </html>

Le code test pour exécuter une commande shell

Ma commande shell exécutée par du php

modifions notre fichier index.php

 geany index.php

en voici le nouveau contenu du code php modifié:

 <?
 echo "hello world!</br>";
 $whoami = exec('uname -a');  // "exec" : execute une fonction shell et récupère le résultat dans $whoami.
 echo $whoami;                // "echo" affiche la variable dans la page html
 ?>

Philosophie de codage

Pour bien séparer les parties du programme et soulager le fichier principal, nous allons découper le code en 3 parties minimum.

index.php     : Le fichier principale contenant le code qui interagit avec l'utilisateur et lance les fonctions,
fonctions.php : Le fichier contenant les fonctions les plus utilisées et communes a tout le Raspberry
pcf8583.php   : Le fichier contenant les variables propres à notre cible, ici le RTC pcf8583

les fonctions pour exécuter/interpréter le Shell par le code PHP ( fonctions.php )

Les fonctions shell que nous appelons nous retournent des données au format "chaine de caractère" (string : car récupérés comme une réponse d'une console terminal). La plupart des fonctions que nous souhaitons utiliser sont numériques.

Nous allons donc créer un fichier fonctions.php qui contiendra certaines fonctions de base pour les conversions, calculs, etc... que nous pourrons enrichir au fur et a mesure de notre progression.

Ce fichier pourra être inclus dès que nécessaire dans nos développements PHP par un include('fonctions.php').

geany fonctions.php         # nous sommes dans le dossier /home/pi/www
<?
//fonction de conversion d'une chaine type "0xFF" en valeur numérique type 0xFF
function strToHex($a){
	$s=explode("x",$a);
	return hexdec($s[1]);
}

//fonction de conversion d'une valeur numérique type 0xFF en chaine type "0xFF"
function hexToStr($a){
	$s = dechex($a);
	return '0x'.strtoupper(str_pad($s,2,"0", STR_PAD_LEFT));
}

//fonction OR pour chaine type "0xFF"
function strOr($a,$b){
	$c = hexToStr(strToHex($a) | strToHex($b));
	return $c;
}

//fonction AND pour chaine type "0xFF"
function strAnd($a,$b){
	$c = hexToStr(strToHex($a) & strToHex($b));
	return $c;
}
?>

Nous incluons également des fonctions propres au traitement du bus i2c du RasberryPi.

/* ****************************** */
// Fonctions pour peripherique i2C
/* ****************************** */
function search_i2c($bus){		
	$i2cexist = array();		// initialise la variable temporaire (tableau)
	$i2c_trouve = array();		// initialise la variable temporaire (tableau)
	$list = array();		// initialise la variable temporaire (tableau)
	exec('/usr/sbin/i2cdetect -y '.$bus,$i2cexist);	//execute une fonction shell
	//cherche dans les plages d'adresses 0x10 (on eclate les lignes)
	for($i=1;$i<count($i2cexist);$i++){
		$list = explode(" ",$i2cexist[$i]);
		//affiche chaque peripherique trouvée dans chaque plage de 0x10
		for($j=0x01 ; $j< count($list) ; $j++){
			if (($list[$j] != "--") AND ($list[$j] != "")){
				//	echo "périphérique i2c trouvé adresse :0x".$list[$j]."<br />";
				$i2ctrouve = '0x'.$list[$j];
			} //boucle if
		}//fin boucle for peripherique
	}//fin boucle for plages
	return $i2ctrouve;
}
/* **************************************************************** */
//i2cget <bus> <chip> <register>
function i2cget($bus,$chip,$register){
	exec('/usr/sbin/i2cget -y '.$bus.' '.$chip.' '.$register,$return);	//execute une fonction shell	
return $return;
}

/* **************************************************************** */
//i2cset <bus> <chip> <register> <value>
function i2cset($bus,$chip,$register,$value){
	exec('/usr/sbin/i2cset -y '.$bus.' '.$chip.' '.$register.' '.$value,$return);	//execute une fonction shell	
return $return;
}

Registres du RTC ( pcf8583.php )

Le composant est constitué de registres, pour ne pas alourdir notre page de développement principale, nous déclarons les constantes que nous utilisons dans ce fichier annexe.

<?
/* ***************************************************************** */
// CONSTANTES
/* ***************************************************************** */
	$PCF8583_HOUR_REG=array(
	"flt_heure"	=> "0x3F",	// filtre pour l'heure
	"AM/PM"		=> "0x40",	// Matin:0, Après Midi:1
	"12/24h"	=> "0x80",	// Format : 24h=0
	);

/* ***************************************************************** */
//REGISTER CLOCK MODE
/* ***************************************************************** */
$PCF8583_REG=array(
	"controle"		=> "0x00",	//REG_0x00	:	CONTROL / STATUS
	"centiemes"		=> "0x01",	//REG_0x01	:	HUNDREDTH OF A SECOND
	"secondes"		=> "0x02",	//REG_0x02	:	SECONDS
	"minutes"		=> "0x03",	//REG_0x03	:	MINUTES
	"heures"		=> "0x04",	//REG_0x04	:	HOURS
	"annees"		=> "0x05",	//REG_0x05	:	YEAR / DATE
	"mois"			=> "0x06",	//REG_0x06	:	WEEKDAYS / MONTHS
	"timer"			=> "0x07",	//REG_0x07	:	TIMER
	"alarme_ctrl"	=> "0x08",	//REG_0x08	:	ALARME CONTROL
	"alarme_centi"	=> "0x09",	//REG_0x09	:	HUNDREDTH OF A SECOND ALARM
	"alarme_sec"	=> "0x0A",	//REG_0x0A	:	ALARM SECONDS
	"alarme_mn"		=> "0x0B",	//REG_0x0B	:	ALARM MINUTES
	"alarme_h"		=> "0x0C",	//REG_0x0C	:	ALARM HOURS
	"alarme_date"	=> "0x0D",	//REG_0x0D	:	ALARM DATE
	"alarme_mois"	=> "0x0E",	//REG_0x0E	:	ALARM MONTH 
	"alarme_timer"	=> "0x0F"	//REG_0x0F	:	ALARM TIMER 
	);

?>

Le code principal ( index.php )

Comme nous l'avons déjà indiqué, index.php est une page qui sera renvoyé par le moteur apache vers quelqu'un qui arrive dans le dossier http://xxx.xxx.xxx.xxx/pi

Rappels et commentaires

Ce fichier devra dans un premier temps faire quelques rappels :

<? 
/* **********************************************************************
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * *********************************************************************
 * Nécessite i2c d'installé sur votre RaspberryPi  
 *
 * sudo apt-get install i2c-tools
 * 
 * voir : https://outils.electroniciens.cnrs.fr/wiki/index.php/Raspberry_Pi#Exemples_et_Travaux_Pratiques
 * datasheet : http://www.nxp.com/documents/data_sheet/PCF8583.pdf
 * *********************************************************************/

inclusion des fichiers spécifiques

Le premier rappel de ce fichier est de mettre en garde l'utilisateur de bien être sûr d'avoir i2c-tools d'installé et en rappel donc la procédure d'installation. Ensuite d'inclure les fichier requis, qui sont dans le même dossier.

 
 // Appel aux pages de fonction et de déclaration des registres du PCF8583
 include('fonctions.php');
 include('pcf8583.php');

Constitution de la page WEB

Un page WEB normalement constituée est composée de balises :

 
// Mise en  forme de la page html a construire
echo '<!DOCTYPE html>
<html lang="fr" dir="ltr" class="client-nojs">
	<head>
		<title>Affichage de l\'heure sur une page web(lecture I2C et envoi HTML)- d\'après le WIKI</title>
		<meta charset="UTF-8" :></meta>
		<!-- page rafraichie toutes les 10 secondes -->
		<meta http-equiv="refresh" content="10"></meta>
	</head>
		<body>';

L'inclusion de balises permet de transférer à la fois la structure du document et son contenu permettant un traitement automatisé du contenu.

Nous trouvons donc une balise <HTML> qui déclare l'ouverture et que le code sera interprété tel que du code HTML.

Les balises <HEAD> permettent normalement de fournir, entre autres, une description de votre site par le biais de mots clés et de phrases décrivant votre site afin que les moteurs de recherche le reconnaissent et le référencent au mieux. Elle a d'autres fonctions comme notamment, la redirection automatique vers une URL. Chaque balise ouverte doit être refermée dans le même ordre inverse, nous aurons donc un </HEAD> ensuite.

La balise <BODY> indique que nous somme dans le corps de la page, tout notre code sera ici...

Corps de Code et structure

Structure du corps

Cette partie fera un affichage de données de notre RaspberryPi à travers du code PHP

Affichage
// Debut du code PHP
	echo "Hello World! <hr> il est ".date('H:i:s',time()).' sur le RaspberryPi';
	echo "<br />"; 			//retour a la ligne
	echo "<hr>"; 			//trait séparateur
	
	$whoami = exec('uname -a');	// execute une fonction shell
	echo $whoami;                   // affiche la réponse
	echo "<hr>"; //trait

Les fonctions date , time , exec ou echo sont toutes disponibles sur le site de développement php http://www.php.net/manual/fr/getting-started.php

Déclaration des constantes et variables

Propres a notre page principale, nous déclarons les constantes. Mais figeons également des variables récupérées de notre formulaire ou les figeons à une valeur prédéfinie.

/* **************************************************************** */
// CONSTANTES
/* **************************************************************** */
	$bus = "1";

/* **************************************************************** */
// VARIABLES
/* **************************************************************** */
	$hardware_i2c   = array(); //initialise un tableau vide
	$POST_HEURE     = isset($_POST['heures']) ? $_POST['heures'] : date('H',time());
	$POST_MINUTE    = isset($_POST['minutes']) ? $_POST['minutes'] : date('i',time());
	$POST_SECONDE   = isset($_POST['secondes']) ? $_POST['secondes'] : date('s',time());
	$POST_FORMAT    = isset($_POST['format']) ? $_POST['format'] : date('s',time());
	$POST_AMPM      = isset($_POST['ampm']) ? $_POST['ampm'] : date('s',time());
Exécution des données du formulaire si posté
/* ******************************************************************** */
// programme général faisant appel aux fonctions de la RTC au dessus
/* ******************************************************************** */
	//Recherche les peripheriques sur l'i2c par la fonction SHELL "i2cdetect" sur le bus "$bus"
	$hardware_i2c = search_i2c($bus);
	// affiche le nombre de périphériques et l'adresse trouvée
	echo count($hardware_i2c)." périphérique trouvé <br />";
	echo "- à l'adresse ".$hardware_i2c	.'<hr>';

/* ********************************************************* */
// Une programmation à été demandé par reponse au formulaire FORM
/* ********************************************************* */
	if (isset($_POST['prog'])) {
		//en FORMAT 12H , le bit de poids fort est à 1 sinon on le filtre pour qu'il soit à 0
		if ($POST_FORMAT =='12H') { 
			$REG_TMP_HEURE = StrOr('0x'.$POST_HEURE,"0x80");
		} else {
			$REG_TMP_HEURE = StrAnd('0x'.$POST_HEURE,"0x7F");
		}
		//en FORMAT PM , le bit 0x40 est à 1 sinon on le filtre pour qu'il soit à 0
		if ($POST_AMPM =='AMPM') { 
			$REG_TMP_HEURE = StrOr('0x'.$POST_HEURE,"0x40");
		} else {
			$REG_TMP_HEURE = StrAnd('0x'.$POST_HEURE,"0xBF");
		}
		//Programmation des HEURES, MINUTES et SECONDES vers la RTC
		i2cset($bus, $hardware_i2c, $PCF8583_REG["heures"],$REG_TMP_HEURE);
		i2cset($bus, $hardware_i2c, $PCF8583_REG["minutes"],'0x'.$POST_MINUTE	);
		i2cset($bus, $hardware_i2c, $PCF8583_REG["secondes"],'0x'.$POST_SECONDE	);
		//On affiche que l'heure est progrmmé sur la RTC
		echo '<b><center>heure programmé '.$REG_TMP_HEURE.":".$POST_MINUTE.":".$POST_SECONDE."-".$POST_FORMAT.'</center></b>';
	}
/* ********************************************************* */
Fonctions principales
/* ****************** */
//lit l'heure 
/* ****************** */
// Lit les registres de  la RTC
$REG_SEC	= i2cget($bus,$hardware_i2c,$PCF8583_REG["secondes"]);
$REG_MIN	= i2cget($bus,$hardware_i2c,$PCF8583_REG["minutes"]);
$REG_HEURES	= i2cget($bus,$hardware_i2c,$PCF8583_REG["heures"]);

//cherche si le format est 12 ou 24 heures
$TMP_FORMAT= strAnd($REG_HEURES[0],$PCF8583_HOUR_REG["12/24h"]);
$FORMAT  = ($TMP_FORMAT=="0x80") ? "12H" : "24H";

//cherche si le format est 12 ou 24 heures
$TMP_AMPM= strAnd($REG_HEURES[0],$PCF8583_HOUR_REG["AM/PM"]);
$AMPM  = ($TMP_AMPM=="0x40") ? "PM" : "AM";

//mise en forme des secondes
$TMP_SECONDES= explode("x",$REG_SEC[0]);
$SECONDES	 = $TMP_SECONDES[1];

//mise en forme des minutes
$TMP_MINUTES = explode( "x", $REG_MIN[0] );
$MINUTES	 = $TMP_MINUTES[1];

//Mise en forme de l'heure on ne garde pas le format12/24H ni le AM/PM

$TMP_HEURE	 = explode( "x", strAnd( $REG_HEURES[0], $PCF8583_HOUR_REG["flt_heure"] ) );
$HEURES		 = $TMP_HEURE[1];
	
// (condition) ? instruction si vrai : instruction si faux
// on set le ckecked pour la case radio du format adequate
$check12 = ( $FORMAT == '24H' ) ? '' : 'checked';
$check24 = ( $FORMAT == '24H' ) ? 'checked' : '';

// (condition) ? instruction si vrai : instruction si faux
// on set le ckecked pour la case radio du format adequate
$checkAM = ( $AMPM == 'PM' ) ? '' : 'checked';
$checkPM = ( $AMPM == 'PM' ) ? 'checked' : '';
Le formulaire FORM

C'est ici que les choix seront proposés à l'utilisateur par des champs RADIO, BOUTONS a cliquer, menus déroulants, etc ....

	/* ************************************************************** */
	// envoi de données du formulaire détecté
	/* ************************************************************** */
	echo '<FORM  action="index.php" method="POST">
			Il est <b>'.$HEURES.':'.$MINUTES.':'.$SECONDES.'</b> sur le RTC du port i2c. 
			<INPUT type="submit" name="Rafraichir" value="Rafraichir">
		  </FORM>';

	echo '';
/* ******************************************************************** */
// formulaire d'envoi des données de programmation de l'heure du RTC 
/* ******************************************************************** */

/* ********************************* */
//Zone de mise a l'heure
/* ********************************* */
echo '<FORM action="index.php" method="POST">
		<P>
			<LABEL for="format">FORMAT RTC:</LABEL>
				<INPUT type="radio" id="12H" name="format" value="12H"'.$check12.' />12H /
				<INPUT type="radio" id="24H" name="format" value="24H"'.$check24.'/>24H 
		</P>
		<P>
			<LABEL for="format">FORMAT AM/PM:</LABEL>
				<INPUT type="radio" id="AM" name="ampm" value="AM"'.$checkAM.' />AM /
				<INPUT type="radio" id="PM" name="ampm" value="PM"'.$checkPM.'/>PM 
		</P>
		<P>
			<LABEL for="horloge">HOLORGE RTC:</LABEL>
			<INPUT type="text" col="2" name="heures" value="'.$POST_HEURE.'" style="width:20px;"/> :
			<INPUT type="text" name="minutes" value="'.$POST_MINUTE.'" style="width:20px;"/> :
			<INPUT type="text" name="secondes" value="'.$POST_SECONDE.'" style="width:20px;"/>
			<INPUT type="submit" name="prog" value="Programmer">
		</P>
	 </FORM>';
				
/* ********************************* */
//Controle du RTC
/* ********************************* */
	$CONTROLE= i2cget($bus,$hardware_i2c,$PCF8583_REG["controle"]);
	echo "CONTROLE:".$CONTROLE[0];

		// ici se termine le code PHP

//fermeture de la page HTML
echo	'</body>
</html>';
?>