Station météo - Application web PHP

Présentation

Il s’agit de réaliser une application web qui permet de visualiser les mesures d’un capteur sélectionné.

Lire le document sur les base de données.

Base de données

Les données associées à chaque capteur sont stockées dans une base de données MySQL meteo :

DROP DATABASE IF EXISTS `meteo`;
CREATE DATABASE `meteo` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
USE `meteo`;

--
-- Structure de la table `capteurs`
--

CREATE TABLE IF NOT EXISTS `capteurs` (
  `idCapteur` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `nom` varchar(255) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  `unite` varchar(16) DEFAULT NULL,
--   `unite` enum('°C','',''),
  PRIMARY KEY (`idCapteur`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Contenu de la table `capteurs`
--

INSERT INTO `capteurs` (`idCapteur`, `nom`, `description`, `unite`) VALUES
(1, 'température', '', '°C'),
(2, 'anémomètre', '', 'km/h');

--
-- Structure de la table `mesures`
--

CREATE TABLE IF NOT EXISTS `mesures` (
  `idMesure` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `mesure` double NOT NULL,
  `date` date NOT NULL,
  `horodatage` time NOT NULL,  
  `idCapteur` int(11) unsigned NOT NULL,
  PRIMARY KEY (`idMesure`),
  CONSTRAINT fk_capteurs_idCapteur
  FOREIGN KEY (idCapteur)
  REFERENCES capteurs(idCapteur)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Contenu de la table `mesures`
--

INSERT INTO `mesures` (`idMesure`, `mesure`, `date`, `horodatage`, `idCapteur`) VALUES
(1, 25, '2015-04-16', '13:45:00', 1),
(2, 2.3, '2015-04-16', '13:45:00', 2),
(3, 24.7, '2015-04-16', '14:00:00', 1),
(4, 4.5, '2015-04-16', '14:00:00', 2),
(5, 23.8, '2015-04-16', '14:15:00', 1),
(6, 23.8, '2015-04-16', '14:15:00', 2),
(7, 23.3, '2015-04-16', '14:30:00', 1),
(8, 22.6, '2015-04-16', '14:45:00', 1),
(9, 24.6, '2015-04-16', '15:00:00', 1),
(10, 25.5, '2015-04-16', '15:15:00', 1),
(11, 26.1, '2015-04-16', '15:30:00', 1),
(12, 27.4, '2015-04-16', '15:45:00', 1),
(13, 26.2, '2015-04-16', '16:00:00', 1);

Contraintes d’environnement

Ressource Version
OS GNU Linux (Ubuntu 12.04.5 LTS)
EDI Geany
SERVEUR Apache
PHP PHP 5.x
SGBDR MySQL

Ressources

PHP

PHP est un langage de programmation de scripts côté serveur permettant de produire des pages web dynamiques.

Les scripts PHP :

  • sont de simples fichiers “texte” (extension conseillée .php) à créer avec un éditeur de texte
  • contiennent du code PHP mélangeables à du code HTML
  • sont exécutés côté serveur par un “interpréteur” php (parser php)

Généralement, PHP sert à produire des pages web dynamiques et donc à récupérer et traiter des informations issues d’une base de données, d’un système de fichiers (contenu de fichiers et de l’arborescence) ou plus simplement des données envoyées par le navigateur (url, formulaire, …).

Le code PHP doit être inséré entre des balises <?php et ?>. Le script doit porter une extension reconnue par le serveur (extension conseillée .php).

Un simple script PHP :

<HTML>
   <HEAD>
      <!-- Un titre -->
      <TITLE>Exemple 1</TITLE>
   </HEAD>
   <BODY>
    <?php
    // forme la plus simple, recommandée
    echo '<P>Hello World!</P>';
    ?>
   </BODY>
</HTML>

Pour réaliser un développement PHP, il vous faut la chaîne complète client/serveur HTTP. Plusieurs solutions s’offrent à vous :

  • le serveur est présent en local sur votre machine de développement (localhost). Le plus souvent sous Linux, la racine des documents du serveur se trouvent en /var/www/ . Et l’accès par le navigateur se fait à l’adresse : http://localhost/ ou http://votre-adresse-ip/
  • le serveur est présent sur l’intranet de votre structure de développement (entreprise, école, université, domicile, …). Le serveur de la section est configuré pour un accès pour chaque compte. La racine se trouve dans votre répertoire personnel $HOME/public_html/ et l’accès client se fait par exemple à l’adresse : http://192.168.52.85/~$LOGIN/
  • le serveur est présent sur l’Internet, le plus souvent chez un hébergeur. Dans ce cas, il faut transférer les documents de votre poste de développement vers le serveur Internet (le plus souvent en FTP).

Remarque : LAMP est un acronyme désignant un ensemble de logiciels libres permettant de construire des serveurs de sites web. L’acronyme original se réfère aux logiciels suivants : Linux (l’OS GNU/Linux), Apache (le serveur Web), MySQL (le serveur de base de données) et PHP (le langage de script). Il existe aussi une architecture WAMP utilisée pour développer des sites web sur une machine Windows .

Le code PHP est composé par des appels à des fonctions, dans le but d’affecter des valeurs à des variables, le tout encadré dans des conditions, des boucles.

  • Les instructions sont séparées par des ;
  • les variables sont toujours préfixées par un $
  • Les blocs d’instructions sont délimités par les caractères { et }

PHP supporte les commentaires de type C, C++ et Shell Unix (aussi appelé style Perl) : //, /* */ et #.

Un exemple de script PHP :

<?php
// URL : http://localhost/helloworld-2.php?lang=fr
$lang = strtolower($_GET['lang']); // appel de la fonction strtolower()

if ($lang === 'fr') # test du type ET de la valeur
{
    $message = 'Bonjour le monde !'; /* une chaîne de caractères protégée */
}
elseif ($lang == 'en') # test de la valeur seulement
{
    $message =  "Hello"." World!"; // une concaténation de chaînes de caractères avec le .
}
else
{
    $message =  "Je ne vois pas quelle est votre langue $lang !"; // une chaîne de caractères non protégée
}

echo "<b>".$message."</b><br>"; // affiche (en gras) le contenu de la variable message
?>

Manuel PHP : https://php.net/manual/fr/

JQuery Mobile

JQuery Mobile est un framework d’interface optimisé pour les appareils mobiles tactiles. Son objectif est de permettre de rapidement développer des applications mobiles ou des applications web monopage en réponse à la grande diversité des Smartphones et tablettes sur le marché. Il est développé par l’équipe du projet JQuery. Il s’appuie sur l’utilisation des technologies du web : HTML5, CSS3, DOM, Javascript, Ajax.

De manière générale, on développe des documents HTML5 et jQuery Mobile ajoute des éléments et des attributs de style adaptées aux terminaux mobiles.

Les bibliothèques de jQuery Mobile sont requises et on peut :

  • soit stockées en local sur votre serveur
  • soit directement sur le serveur public jQuery.com

On effectue l’importation dans l’en-tête du document :

  • de la feuille de style spécifique mobile (.css)
  • de la bibliothèque JavaScript jQuery (.js)
  • de la bibliothèque JavaScript jQuery Mobile (.js)
<!DOCTYPE html> 
<html lang="fr"> 
    <head> 
        <title>Un titre !</title> 
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1"> 
        <!-- les bibliothèques pour jQuery Mobile -->
        <!-- <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" /> -->
        <!-- <script src="http://code.jquery.com/jquery-1.6.4.min.js"></script> -->
        <!-- <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script> -->
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
        <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
    </head> 
    <body>
    </body>
</html>

Vous pouvez structurer l’application web suivant deux approches :

  • monopage : un document par page et on utilise des liens et l’id de la page (href=“page2.html#page2”)
  • multipages : un document contient n pages et on utilise les ancres de la balise a à partir de l’id des pages (href=“#page2”)

Les pages sont créés à partir de la balise section dans le document. On exploite ensuite les attributs fournis par JQuery Mobile :

  • data-role : précise la nature du bloc (page|header|content|footer)
  • data-position : spécifie où l’élément doit être positionné (top|bottom|right|left)
  • data-inset : spécifie si l’élément doit être contenu dans les marges ou à l’extérieur de celles-ci (true|false)
  • data-transition : spécifie quelle transition utiliser lors du chargement de nouvelles pages (slide|slideup|slidedown|pop|flip|fade)
  • data-theme : spécifie le thème graphique à utiliser pour les éléments d’un conteneur (a|b|c|d|e)

Une simple page :

<!DOCTYPE html> 
<html lang="fr"> 
    <head> 
        <title>Un site pour Mobile</title> 
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1"> 
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
        <script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
        <style type="text/css">
        .center { text-align:center; }
        .margesinternes { margin:0.5em; }
        </style>
    </head> 
    <body>      
        <!-- une page -->
        <section id="page1" data-role="page" data-add-back-btn="true">
            <!-- en-tête -->
            <header data-role="header"><h1>Titre du site</h1></header>
            <h2 class="center">
                Un titre niveau 2
            </h2>     
            <h3 class="center">
                Un titre niveau 3
            </h3>
            <p class="center">
                <!-- un logo -->
                <img src="logo-montagne.jpg" alt="Un logo !" width="160" height="124" />
            </p>
            
            <!-- une vue dépliante -->
            <div data-role="collapsible" data-content-theme="a">
                <h3>La station</h3>
                <p>...</p>
                <img src="pistes.png" alt="" width="" height=""/>
            </div>                
            
            <div data-role="collapsible" data-content-theme="b">
                <h3>Ski de fond</h3>
                <p>Le domaine nordique est un paradis pour les fondeurs ...</p>            
            </div>    
            
            <div data-role="collapsible" data-content-theme="c">
                <h3>Ski alpin</h3>
                <p>La station vous offre une garantie d’enneigement ... </p>
                <!-- une grille à 2 colonnes -->
                <div class="ui-grid-a ui-responsive">
                    <div class="ui-block-a">
                        <div class="margesinternes">                       
                            <h3>Tarifs</h3>                        
                            <p>...</p>
                        </div>
                    </div>
                    <div class="ui-block-b">
                        <div class="margesinternes">
                            <h3>Les pistes</h3>                        
                            <img src="skieur.png" alt="" width="" height=""/>
                        </div>
                    </div>
                </div>
            </div>            
            
            <div data-role="collapsible" data-content-theme="d">
                <h3>Snowkite</h3>
                <p>Le snowkite est à la portée de tous ceux qui recherchent de nouvelles sensations sur la neige en skis ou en surf ...</p>            
                <img src="snow.png" alt="" width="" height=""/>
            </div>            
            
            <!-- une vue en liste -->
            <ul data-role="listview" data-inset="true">
                <li>
                  <a href="#page2" data-transition="slide">                  
                  <h3>En savoir plus ...</h3>
                  <p><img class="margesimg" src="station.png" alt="" /></p>
                  </a>              
                </li>
            </ul>
            <p></p>
            <!-- un pied de page -->
            <footer data-role="footer"><h1>©&nbsp;2016&nbsp;</h1></footer>
        </section>

        <!-- une deuxième page -->
        <section id="page2" data-role="page">
            <header data-role="header"><h1>Titre du site</h1></header>
            <h2 class="center">
                Un titre niveau 2
            </h2>     
            <h3 class="center">
                Un titre niveau 3
            </h3>
            <p class="center">
                <!-- un logo -->
                <img src="logo-montagne.jpg" alt="Un logo !" width="160" height="124" />
            </p>
            
            <div class="content" data-role="content">                
                <p class="center">Contact : 04.04.04.04.04</p>
                <p class="center">Horaires d'ouverture : <br/>
                du 1er Decembre au 31 Mars,<br/>
                de 9h à 12h et de 13h30 à 17h30.</p>                
            </div>
            
            <!-- des boutons -->
            <div class="center" data-role="controlgroup" data-type="horizontal" data-mini="true">
                <a href="#page1" data-role="button" data-icon="back" data-iconpos="left">Retour</a>
                <a href="mailto:info%40neige.com" data-role="button" data-icon="forward" data-iconpos="right" target="_blank">info(at)neige.com</a>
            </div>
            <footer data-role="footer" data-position="fixed"><h1>©&nbsp;2016&nbsp;</h1></footer>
        </section>
        
    </body>
</html>

On peut utiliser le navigateur Firefox ou l’extension Ripple Emulator pour Chrome par exemple pour tester ou directement un smartphone.

Travail demandé

  1. Vérifier la présence du serveur web Apache.
// Présence des paquets Apache et de son module PHP
$ dpkg -l | grep -i apache

// Présence des paquets PHP (au moins php5-common et php5-mysql)
$ dpkg -l | grep -i php

// Le serveur web Apache est-il démarré ?
$ sudo service apache2 status

Normalement, le serveur est déjà installé sinon il faudra installer les paquets suivants :

$ sudo apt-get install apache2 apache2-bin apache2-data apache2-utils libapache2-mod-php5 php5-common php5-mysql
  1. Créer l’application demandée.
  1. Créer un script index.php dans /var/www/meteo/ et compléter le formulaire :
<!DOCTYPE html> 
<html lang="fr"> 
    <head> 
        <title>StationMétéo-PHP</title> 
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1"> 
        <!-- les bibliothèques pour jQuery Mobile -->
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
        <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
    </head> 
    <body>
        <!-- une page -->
        <section id="page1" data-role="page" data-add-back-btn="true">
            <!-- une en-tête -->
            <header data-role="header">
                <h1>StationMétéo</h1>
            </header>
            <!-- un contenu -->
            <div data-role="main" class="ui-content">
                <!-- cf. http://demos.jquerymobile.com/1.4.3/forms/ -->
                <form method="post" action="index.php">                        
                    <!-- TODO -->
                </form>
            </div>            
            <!-- un pied de page -->
            <footer data-role="footer" data-position="fixed">                   
                <h1>©&nbsp;2016&nbsp;La Salle Avignon</h1>
            </footer>
        </section>       
    </body>
</html>

Lien : http://demos.jquerymobile.com/1.4.3/forms/

  1. Compléter le script index.php afin de finaliser le formulaire à partir des données contenues dans la table capteurs de la base de données meteo.

Exemple de script qui exécute une requête SELECT :

<!DOCTYPE html> 
<html lang="fr"> 
    <head> 
        <title>StationMétéo-PHP</title> 
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1"> 
        <!-- les bibliothèques pour jQuery Mobile -->
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
        <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
    </head> 
    <body>
        <!-- une page -->
        <section id="page1" data-role="page" data-add-back-btn="true">
            <!-- en-tête -->
            <header data-role="header">
                <h1>StationMétéo</h1>
            </header>
            
            <div data-role="main" class="ui-content">                                        
                <?php
                $mysqli = new mysqli("localhost", "root", "password", "meteo");

                if ($mysqli->connect_error) 
                {
                    die('Echec de connexion au serveur de base de données : ' . $mysqli->connect_error . '(' . $mysqli->connect_errno . ') ');
                }

                if ($result = $mysqli->query("SELECT idCapteur, nom FROM capteurs ORDER BY nom ASC"))
                { 
                   printf("La requête a retourné %d enregistrement(s).<br /><br />\n", $result->num_rows);
                   while($row = $result->fetch_array()) 
                   {
                      $idCapteur = $row["idCapteur"];
                      $nom = utf8_encode($row["nom"]); 
                      echo "$idCapteur - $nom<br />";
                      echo "<pre>"; var_dump($row); echo "</pre>";                       
                   }

                   /* Libération des résultats */
                   $result->free();
                }                    
                
                $mysqli->close();
                ?>
            </div>
            
            <!-- un pied de page -->
            <footer data-role="footer" data-position="fixed">                   
                <h1>©&nbsp;2016&nbsp;tv</h1>
            </footer>
        </section>       
    </body>
</html>
  1. Compléter le script index.php afin de traiter les données reçues du formulaire. Ici, les données sont reçues côté serveur dans la variable superglobale $_POST.
<!DOCTYPE html> 
<html lang="fr"> 
    <head> 
        <title>StationMétéo-PHP</title> 
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1"> 
        <!-- les bibliothèques pour jQuery Mobile -->
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
        <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
    </head> 
    <body>
        <!-- une page -->
        <section id="page1" data-role="page" data-add-back-btn="true">
            <!-- en-tête -->
            <header data-role="header">
                <h1>StationMétéo</h1>
            </header>
            
            <div data-role="main" class="ui-content">
                                        
                <?php
                // Affihage de débuggage de la variable superglobale $_POST
                echo "<pre>"; var_dump($_POST); echo "</pre>"; 

                // Pas de capteur sélectionné (ou vide ) ?
                if(!IsSet($_POST["idcapteur"]) || Empty($_POST["idcapteur"]))
                {
                    // Récuperer les capteurs à partir de la base de données                    
                    // ...
                    
                    $choix = "1";
                }
                else
                {
                    // Récuperer les mesures pour le $_POST["idcapteur"] capteur choisi
                    // ...
                    
                    $retour = "<a href=\"".$_SERVER['PHP_SELF']."\" data-ajax=\"false\">Retour</a>";
                    
                    $choix = "2";
                }
                ?>
                
                <?php
                if($choix == "1")
                {
                ?>
                    <!-- afficher le formulaire -->
                    <form method="post" action="index.php">                        
                        <!-- Exemple pour le test -->
                        <input type="text" name="idcapteur" id="idcapteur">
                        <input type="submit" value="Envoyer" />
                    </form>
                <?php
                }
                elseif($choix == "2")
                {
                    echo $retour;
                ?>
                    <!-- afficher les mesures dans une table -->
                <?php                    
                }
                else
                {
                    echo "Erreur !<br>";
                }
                ?>
            
            </div>
            
            <!-- un pied de page -->
            <footer data-role="footer" data-position="fixed">                   
                <h1>©&nbsp;2016&nbsp;tv</h1>
            </footer>
        </section>       
    </body>
</html>
  1. Compléter le script index.php afin d’afficher les mesures dans une table.

Exemple d’affichage de données dans une table :

<table data-role="table" class="ui-responsive">
    <thead>
        <tr>
            <th>Heure</th>
            <th>Mesure</th>
            <th>Unité</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>13:45:00</td>
            <td>25</td>
            <td>°C</td>
        </tr>
        <tr>
            <td>14:00:00</td>
            <td>24.7</td>
            <td>°C</td>
        </tr>
        <!-- etc ... -->
    </tbody>
</table>

Lien : http://www.w3schools.com/jquerymobile/jquerymobile_tables.asp

Retour au sommaire