Surveiller des sites automatiquement (http 200) avec Google Sheets et un script

Surveiller des sites automatiquement (http 200) avec Google Sheets et un script

Nous allons voir comment lire le statut HTTP d’un site internet avec Google Sheets et envoyer un email automatique en cas d’anomalie.

J’ai rencontré des soucis (non résolus 10 jours après mon premier signalement…) avec mon hébergement Plesk. Il arrive que la base de données de l’hébergement soit en panne et on n’a aucun moyen de le savoir sans essayer d’accéder à l’un des sites de l’hébergement. Les systèmes habituels de vérification par « ping » ne donne pas satisfaction car les sites répondent à un ping mais sont inaccessible depuis un navigateur (le code HTTP n’est pas 200). Comme mon fournisseur d’hébergement se montre incapable d’accepter qu’il y a un problème ou au moins de générer une alerte automatique en cas de panne de la base de données, j’ai décidé de créer un système d’alerte automatique.

Obtenir le code HTTP de réponse d’un site avec Google Sheets

Je me suis inspirée de cet article : How to Pull an HTTP Response Code in Google Sheet.

J’ai créé un fichier Google Sheets dans lequel j’ai placé le tableau suivant :

site url statut
parcours-P parcours-performance.com =VALUE(HTTPResponse(B3))
knowledge PP knowledge.parcours-performance.com =VALUE(HTTPResponse(B4))

Ce qui donne ce qui suit dans Google Sheets :

Google Sheets : surveiller le code httpde sites

Google Sheets : surveiller le code httpde sites

 

Avec l’éditeur de scripts (menu « Outils »), j’ai créé la fonction HTTPResponse .

/*****************************************************************
* check websites for http response
*****************************************************************/

function HTTPResponse( uri )
{
 /* source https://atulhost.com/how-to-pull-an-http-response-code-in-google-sheet */
 var response_code ;
try {
 response_code = UrlFetchApp .fetch( uri ) .getResponseCode() .toString() ;
 }
catch( error ) {
 response_code = error .toString() .match( / returned code (\d\d\d)\./ )[1] ;
 }
finally {
 return response_code ;
 }
}

J’ai ensuite cliqué sur « enregistrer ».

Lorsque je retourne dans ma feuille de calcul, si les sites fonctionnent, je vois « 200 » dans la troisième colonne de mon tableau, celle qui contient =VALUE(HTTPResponse(Bx)) .

Régler la fréquence de vérification

Je veux vérifier au moins toutes les heures que les sites sont opérationnels.

Dans l’éditeur de scripts, je sélectionne (A) la fonction HTTPResponse puis je clique sur le bouton « déclencheur du projet actuel » (B). Ensuite, je régle le déclenhement pour que le script s’exécute à chaque heure :

Régler le déclencheur d'un script Google Sheets

Régler le déclencheur d’un script Google Sheets

Déclencher un script Google Sheets toutes les heures

Déclencher un script Google Sheets toutes les heures

Générer un mail automatique en cas d’anomalie avec Google Sheets

Pour cette partie, je me suis beaucoup inspirée de « Automating Google Spreadsheets – Email Reminders« .

Dans l’éditeur de script, j’ai placé la fonction checkStatut() :

/*****************************************************************
* Send an alert if somme http responses are not 200 OK
*****************************************************************/
function checkStatut() {
  
  /* source https://www.withoutthesarcasm.com/automating-google-spreadsheets-email-reminders/ */
  
  // get the spreadsheet object
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  // set the first sheet as active
  SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
  // fetch this sheet
  var sheet = spreadsheet.getActiveSheet();
   
  // figure out what the last row is
  var lastRow = sheet.getLastRow();
 
  // the rows are indexed starting at 1, and the second row
  // is the headers, so start with row 3
  var startRow = 3;
 
  // grab column 3 (the 'statut' column) 
  // getRange(row, column, numRows, numColumns)
  var range = sheet.getRange(startRow, 3,lastRow-startRow+1,1 );
  var numRows = range.getNumRows();
  var statut_values = range.getValues();

  // Now, grab the site name column (2)
  range = sheet.getRange(startRow, 2, lastRow-startRow+1, 1);
  var site_name_values = range.getValues();
  var warning_count = 0;
  var msg = "";
   
  // Loop over statut values
  for (var i = 0; i <= numRows - 1; i++) {
    var statut = statut_values[i][0];
    if(statut != 200) {
      var site_name = site_name_values[i][0];
       
      msg = msg + "Site : "+site_name+" ne fonctionne pas HTTP code "+statut+" .\n";
      warning_count++;
    }
  }
   
  if(warning_count) {
    MailApp.sendEmail("mail@parcours-performance.com", 
        "Des sites en panne", msg);
  }
};

Cette fonction identifie le bon onglet (0) de la feuille de calcul puis lit toutes les données de statut. Lorsqu’un statut n’est pas égal à 200 (OK), la fonction lit le nom du site correspondant. La fonction crée un message (msg) avec tous les dysfonctionnements puis, s’il y a des alertes, m’envoie un mail pour m’en informer.

Le déclencheur de la fonction est un changement dans la feuille de calcul (lorsque  HTTPResponse se déclenche et indique une réponse différente de ce qui précédait) :

Déclencher un script Google Sheets lorsque la feuille change

Déclencher un script Google Sheets lorsque la feuille change

 

J’ai vérifié que ça fonctionne en placant « 404 » dans l’une des cellules de statut et je reçois bien un mail d’alerte.

Et maintenant

Je suis en train de regarder comment changer d’hébergeur mais je dispose maintenant d’un système d’alerte des anomalies. Si je reçois un mail, je me connecte à mon interface client et je redémarre le VPS. En quelques minutes tous mes sites fonctionnent de nouveau.

Transformer un site WordPress Multisite en site individuel

Transformer un site WordPress Multisite en site individuel

Dans ce dernier article de la série , nous allons voir comment ressortir un site d’un multisite WordPress.

Le fonctionnement multisite de WordPress est très pratique et simple mais je suis contrainte de scinder un multisite (heureusement encore peu fourni) car je transfère le site sur un VPS avec Plesk et il est pour l’instant impossible d’avoir plusieurs domaines distincts avec des certificats Let’s Encrypt distincts sur un seul hébergement Plesk…

Les spécificités du multisite

Si on veut sortir un site d’un multisite, il faut le « détricoter » :

  • Pour les fichiers, il faut remettre toutes les extensions du site principal dans le site devenu orphelin et il faut également lui transférer ses fichiers médias. C’est simple à faire.
  • Dans la base de données, c’est plus compliqué. Il y a des tables spécifiques au site à séparer mais certaines sont partagées entre tous les sites du multisite. C’est là que le détricotage est un peu fastidieux.

Trouver l’identifiant du site à sortir

Dans le tableau de bord du multisite, aller sur mes sites > Admin du Réseau > Sites.

Passer la souris sur le nom du site à déplacer (disons « subdomain.com »). Son url complète s’affiche en bas de la fenêtre, sous la forme https://domaine.comwp-admin/network/site-info.php?id=3. Ici l’identifiant est donc « 3 ». On en aura besoin pour la suite.

christmas project #3 : advent boxes

Sauvegarder le multisite

Sauvegarder les fichiers

Avec Filezilla : sauvegarder le répertoire /www/wp-content/uploads/sites/3  (3 est l’identifiant du site que l’on veut sortir).

Sauvegarder la base de données

Nota du 23/11/216 : pour des raisons que j’ignore, l’export via PHPMyAdmin provoque parfois une erreur : les index et auto-incrémentations ne sont pas transférés. Dans ce cas, il faut aller dans l’interface client de l’hébergement OVH original et demander une sauvegarde de la base de données (un dump) que l’on reçoit quelques minutes plus tard par mail. Cette sauvegarde s’importe ensuite sans souci dans la base Plesk.

Noter les informations du site

On a intérêt à bien noter (copies d’écran) les informations suivantes :

  • quel est le nom du thème (stargazer pour moi) et ses réglages ?
  • quelles sont les extensions utilisées et faisant l’objet d’un réglage spécifique ? Pour mon cas, Cookie Notice, Floating Social Bar
  • Quels sont les utilisateurs de ce site ?

Installer WordPress sur un nouvel hébergement

J’utilise maintenant un VPS avec Plesk for Resellers. J’installe donc WordPress conformément à Transférer un hébergement mutualisé OVH sur un VPS Plesk d’OVH.

Transférer les fichiers

Dans l’installation de WordPress, copier /www/wp-content/uploads/sites/3 de l’ancien site vers /www/wp-content/uploads/  dans le nouveau. Je copie aussi les fichiers de tous les plugins et thèmes que je veux utiliser. C’est plus rapide qu’une installation par le tableau de bord.

Transférer les bons éléments de la base de données

Sauvegarder la base de donnée du site cible

Disons que son prefixe est ‘cible_ ‘.

Importer la base de données du multisite d’origine

En principe elle n’a pas les mêmes préfixes (‘source_’ ) et ne va pas supprimer les tables du site cible.

Supprimer les tables ‘source_’

Les seules qu’on conserve sont :

  • source_3_options ;
  • source_options ;
  • source_usermeta ;
  • source_users.

Supprimer les tables du site cible

On ne touche pas à cible_options, cible_usermeta et cible_users) et on supprime :

  • cible_comments
  • cible_links
  • cible_postmeta
  • cible_posts
  • cible_termmeta
  • cible_terms
  • cible_term_relationships
  • cible_term_taxonomy

Renommer les tables

  • source_comments en cible_comments
  • source_links en cible_links
  • source_postmeta en cible_postmeta
  • source_posts en cible_posts
  • source_termmeta en cible_termmeta
  • source_terms en cible_terms
  • source_term_relationships en cible_term_relationships
  • source_term_taxonomy en cible_term_taxonomy

Modifier à la main certaines entrées de cible_options

Il faut faire du sur mesure… Le site que je détricotais était heureusement très simple. J’ai simplement dû aller chercher dans la table source_3_options  les valeurs des éléments qui nous semblent mériter d’être transféré et copier-coller la valeur dans l’option de même nom de la table cible_options .

Conserver une trace de certaines entrées

Certaines entrées n’existent pas encore puisqu’il faut activer le thème ou l’extension, puis faire une petite modification des réglages pour qu’elles se créent.

J’ai copié-collé dans un éditeur de texte les valeurs de current_theme, theme_mods_stargazer et cookie_notice_options pour les avoir plus tard.

Modifier les enregistrements DNS

Pointer le domaine subdomain.com vers le nouvel hébergement.

Avec whatsmydns.net, voir la propagation du nouveau DNS.

Créer le certificat Let’s encrypt de subdomain.com (en cochant l’option www).

Faire les derniers réglages

Pour une raison que j’ignore, Chrome conserve longtemps l’ancienne adresse IP du site. J’ai trouvé que c’était très irritant puis maintenant c’est très pratique !

Je tape subdomain.com dans firefox (réglé pour ne conserver aucun historique) et il affiche le nouveau site. Je peux me connecter à son tableau de bord.

Pendant ce temps, Chrome continue à afficher l’ancien site et si on se connecte, on se connecte à l’ancien tableau de bord. C’est pratique si on ne trouve pas les bonnes infos dans la base de données.

Modifier à la main les données

J’ai activé le thème stargazer puis fait une toute petite modification de son apparence. Ainsi, theme_mods_stargazer apparait maintenant dans cible_options. Je peux y copier-coller la valeur qui était dans la table du site source. Et automatiquement tous les réglages sont repris (sauf pour l’image de header, qu’il faut désactiver puis réactiver pour qu’elle s’affiche).

Dans les réglages de l’extension cookie-notice, j’ai également fait une toute petite modification. Dans la table cible_options, l’option cookie_notice_options est maintenant visible. Je peux aussi y copier-coller la valeur qui était dans la table source-options.

Pour le reste, j’ai copié-collé les réglages entre l’ancien site visible sur chrome et le nouveau visible sur firefox.

Rajouter les utilisateurs du site source

Il faut rajouter à la main les utilisateurs du site source. Comme on a conservé les tables source_3_usermeta et source_3_users, on peut assez facilement retrouver les bonnes informations.

Et malheureusement si l’id des users a changé, on risque d’être obligé d’aller réaffecter les contenus aux bons users…

Modifier wp-config.php et .htaccess

Vu que le site créé est crypté (certificat Let’s encrypt), il faut modifier certains éléments. Et je veux aussi interdire l’édition de fichiers dans le tableau de bord WordPress et limiter le nombre de révisions à 5.

Dans wp-config.php (avant la ligne  /* That’s all, stop editing! Happy blogging. */  ), ajouter les lignes suivantes :

// Forcer l'accès SSL (https) pour le tableau de bord WordPress
define('FORCE_SSL_ADMIN', true);

// interdire l'édition de fichiers dans le tdb WordPress
define('DISALLOW_FILE_EDIT', TRUE);

define('WP_POST_REVISIONS', 5);
// max 5 stored revisions per posts

Et dans .htaccess, le contenu devrait être le suivant :

RewriteEngine on
 
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
 
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

Et maintenant ?

Une fois que la propagation des DNS est terminée (il vaut mieux attendre 24h), je peux supprimer le site dans son multisite source. Notre site est maintenant autonome.

 

PHP : obtenir automatiquement le chemin d’accès

J’essaie de toujours créer des chemins relatifs, pour éviter de devoir modifier des documents si leur racine change.
Pour lire les données de mon Pi sur un site web en PHP, j’avais besoin de trouver automatiquement l’url du site, avec son protocole http ou https selon les cas.
Je me suis inspirée de PHP Document Root, Path and URL detection.

Dans un fichier php, il suffit de placer le code suivant pour savoir à quoi chaque élément correspond :

	<?php
	// http://blog.lavoie.sl/2013/02/php-document-root-path-and-url-detection.html
	$base_dir  = __DIR__; // Absolute path to your installation, ex: /var/www/mywebsite
	$doc_root  = preg_replace("!${_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']); # ex: /var/www
	$base_url  = preg_replace("!^${doc_root}!", '', $base_dir); # ex: '' or '/mywebsite'
	$protocol  = empty($_SERVER['HTTPS']) ? 'http' : 'https';
	$port      = $_SERVER['SERVER_PORT'];
	$disp_port = ($protocol == 'http' && $port == 80 || $protocol == 'https' && $port == 443) ? '' : ":$port";
	$domain    = $_SERVER['SERVER_NAME'];
	$full_url  = "${protocol}://${domain}${disp_port}${base_url}"; # Ex: 'http://example.com', 'https://example.com/mywebsite', etc.
	?>


<table>
<tbody>
<tr>
<td width="102">$base_dir</td>
<td width="512"><?php echo $base_dir  ; ?></td>
</tr>
<tr>
<td width="102">$doc_root</td>
<td width="512"><?php echo $doc_root  ; ?></td>
</tr>
<tr>
<td width="102">$base_url</td>
<td width="512"><?php echo $base_url  ; ?></td>
</tr>
<tr>
<td width="102">$protocol</td>
<td width="512"><?php echo $protocol  ; ?></td>
</tr>
<tr>
<td width="102">$port</td>
<td width="512"><?php echo $port  ; ?></td>
</tr>
<tr>
<td width="102">$disp_port</td>
<td width="512"><?php echo $disp_port  ; ?></td>
</tr>
<tr>
<td width="102">$domain</td>
<td width="512"><?php echo $domain  ; ?></td>
</tr>
<tr>
<td width="102">$full_url</td>
<td width="512"><?php echo $full_url  ; ?></td>
</tr>
</tbody>
</table>

On obtient le résultat suivant :

$base_dir /var/www/vhosts/domaine.com/pi.domaine.com
$doc_root /var/www/vhosts/domaine.com/pi.domaine.com
$base_url
$protocol https
$port 443
$disp_port
$domain pi.domaine.com
$full_url https://pi.domaine.com

A quoi ça sert ?

Si je veux que le fichier PHP ailler chercher un fichier css dans un répertoire /css, il me suffit maintenant d’ajouter dans <head> :

	<?php
	// http://blog.lavoie.sl/2013/02/php-document-root-path-and-url-detection.html
	$base_dir  = __DIR__; // Absolute path to your installation, ex: /var/www/mywebsite
	$doc_root  = preg_replace("!${_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']); # ex: /var/www
	$base_url  = preg_replace("!^${doc_root}!", '', $base_dir); # ex: '' or '/mywebsite'
	$protocol  = empty($_SERVER['HTTPS']) ? 'http' : 'https';
	$port      = $_SERVER['SERVER_PORT'];
	$disp_port = ($protocol == 'http' && $port == 80 || $protocol == 'https' && $port == 443) ? '' : ":$port";
	$domain    = $_SERVER['SERVER_NAME'];
	$full_url  = "${protocol}://${domain}${disp_port}${base_url}"; # Ex: 'http://example.com', 'https://example.com/mywebsite', etc.
	?>
   <link rel="stylesheet" href="<?php echo $full_url . '/css/pi-stylesheet.css' ; ?>">

 

Exemple de mentions légales pour un site dispensé de déclaration

Cet exemple est mis en ligne pour illustrer l’article Déclarer ses fichiers à la CNIL pour les sites sans aucune activité marchande, qui sont dispensés de déclaration CNIL . Pour les activités faisant l’objet d’une déclaration simplifiée voir les exemples de mentions légales  pour une société, et pour une entreprise individuelle.

Attention, je ne garantis pas leur conformité légale. A ma connaissance elles sont conformes aux règles en vigueur au 18 octobre 2016 mais vous devriez consulter un avocat avant de les mettre en ligne.

Je vous autorise à copier tout ou partie de ce texte.

Editeur

Ce site internet est édité par :

Prénom NOM, ADRESSE

Tél TEL – MAIL

 

Directeur de la publication : DIRECTEUR

Copyrights

Droits d’auteur / Copyright : ORGANISME

L’accès au site SITE vous confère un droit d’usage privé et non exclusif de ce site. Le présent site et l’ensemble des éléments qui y sont édités incluant notamment les textes, photographies, illustrations, logos, marques, … sont la propriété de ORGANISME au titre des législations sur les droits d’auteur et de la propriété intellectuelle.
Sauf autorisation expresse du Directeur de la publication, la modification, la reproduction, la représentation et le téléchargement de tout ou partie de ce site, sur quelque support que ce soit, pour un usage autre que privé, sont interdits.

Hébergement

OVH, Siège social : 2 rue Kellermann – 59100 Roubaix – France

Données personnelles

Les données personnelles recueillies à partir de tout formulaire de ce site font l’objet d’un traitement informatique destiné à DIRECTEUR (gérante de l’entreprise) pour répondre aux demandes de contact ou pour envoyer une lettre d’information hebdomadaire.

Conformément à la loi « informatique et libertés » du 6 janvier 1978 modifiée, vous disposez d’un droit d’accès et de rectification aux informations qui vous concernent.

Vous pouvez accéder aux informations vous concernant en vous adressant à : MAIL. Pour en savoir plus, consultez vos droits sur le site de la CNIL.

Déclaration CNIL

Le site SITE fait l’objet d’une dispense de déclaration à la CNIL (Dispense n°7 : Délibération n°2006-138 du 9 mai 2006 décidant de la dispense de déclaration des traitements constitués à des fins d’information ou de communication externe).

CGV

Sans (site non marchand)

Certificat SSL Let’s Encrypt sur un VPS Plesk

Certificat SSL Let’s Encrypt sur un VPS Plesk

Je n’ai plus de VPS Plesk depuis un bout de temps. Je laisse cet article en ligne pour information mais je ne pourrai pas répondre aux questions éventuelles.
Nous avons déjà vu comment transformer un site http en site https dans l’article migration d’un site WordPress en http vers https (SSL). Ici nous allons voir comment faire dans un hébergement Plesk VPS Classic de chez OVH. Il y a de petites différences avec un site d’un hébergement mutualisé OVH.

L’intérêt de passer en https

J’invite tous les anglophones à lire attentivement cet article de Wired. Il explique bien pourquoi tous les propriétaires de site devraient immédiatement chercher à passer leurs sites en https. Mais il va plus loin en montrant l’importance de l’interface utilisateur pour que les internautes comprennent les risques pris lorsqu’ils intéragissent avec un site non crypté. Le témoignage de l’Iranien est particulièrement édifiant.

https://www.wired.com/2016/11/googles-chrome-hackers-flip-webs-security-model/

Obtenir un certificat SSL Let’s encrypt

La documentation de Plesk est incomplète sur ce sujet, mais le processus est très simple.

Il suffit de cliquer sur le lien « Let’s Encrypt » :

Plesk : obtenir un certificat gratuit Let's Encrypt

Pour les réglages, je coche « inclure www.domaine.com » même si je redirige www sur la version sans préfixe (attention ça n’est pas coché dans la copie d’écran ci-dessous mais il faut le faire) :

Plesk : régler le certificat gratuit Let's Encrypt

 

Une fois qu’on a cliqué sur « installer », on a au bout de quelques secondes un message en vert disant que le certificat est installé.

Transformer un site en HTTPS

On peut suivre les instructions, à partir de l’étape 2 de l’article initial  migration d’un site WordPress en http vers https (SSL).

le contenu à ajouter dans .htaccess fonctionne aussi dans Plesk.

Et maintenant ?

Il faut vérifier que les redirections fonctionnent correctement. Un internaute doit pouvoir taper les url suivantes et être dirigé vers le site https://mon-domaine.com  :

  • www.mon-domaine.com
  • mon-domaine.com
  • http://mon-domaine.com
  • mon-domaine.com/wp-login.php (ou wp-admin.php)

Une fois ces vérifications faites, ça y est, on a un site moderne et sécurisé.

Plesk, créer une tâche planifiée (cron job)

Plesk, créer une tâche planifiée (cron job)

Dans un article précédent (Cron Job sur un hébergement mutualisé OVH), j’ai expliqué comment exécuter un script périodiquement, et automatiquement, dans un hébergement mutualisé OVH pro. Nous allons voir comment le faire sur un serveur mutualisé Plesk (Offre VPS Classic d’OVH).

Documentation Plesk : Planifier des tâches.

Le fichier à exécuter périodiquement

J’utilise le fichier /domicile.mon-domaine.com/cron-suivi-pi.php. Son contenu est semblable à celui de l’article précédent. Ce fichier m’envoie un mail lorsqu’il s’exécute et que certaines conditions sont réunies.

Je l’ai vérifié en plaçant http://domicile.mon-domaine.com/cron-suivi-pi.php  dans un navigateur. Il n’y a pas d’erreurs et les « echo » s’affichent sur la page.

Nota : on a intérêt à activer l’affichage des erreurs : en étant administrateur, aller dans paramètres PHP et mettre display_errors sur « on ».

Réglage des tâches planifiées

Dans l’interface Plesk, Sites Web & Domaines > tâches planifiées, on peut régler le fuseau horaire des taches planifiées :

Plesk, tâche planifiée : régler le fuseau horaire

Plesk, tâche planifiée : régler le fuseau horaire

Planifier la tache

C’est incroyablement simple, ça se passe de commentaires !

La seule chose qui peut être compliquée, c’est si on veut planifier « cron style », comme ici. Pour définir l’heure, on peut alors s’aider de ce générateur de commande cron ou cet autre générateur.

Plesk, régler une tâche planifiée (cron)

Plesk, régler une tâche planifiée (cron)

Vérifier

Dans la liste des tâches planifiées, cliquer sur « exécuter maintenant ».

Plesk, exécuter maintenant un cron

Plesk, exécuter maintenant un cron

Si tout s’est bien passé : un message sur fond vert dans Plesk et pas de mail d’erreur reçu et le mail prévu s’est envoyé (si les conditions sont réunies).

Et voilà, encore une nouvelle manip dans Plesk qui est maîtrisée ! Pour tout savoir sur la prise en main de Plesk, lire les autres articles de cette série .

Interagir avec L’agenda Google via l’API (OAuth 2.0)

Interagir avec L’agenda Google via l’API (OAuth 2.0)

Ce tutoriel explique comment ajouter des événements dans un agenda Google à partir d’un script PHP sur Raspberry Pi. Le script demande l’autorisation de se connecter à l’agenda puis, une fois l’autorisation accordée, crée des événements sur l’agenda lorsqu’on le souhaite.

Nous avons créé un agenda « Pi Nautilus » dans l’article Raspberry Pi : envoyer des SMS sans 3G et gratuitement. Cet article explique également comment installer PHP sur un Pi si c’est nécessaire.

Nous allons maintenant écrire un programme, en PHP, qui créera automatiquement un événement dans l’agenda Google.

Télécharger le client PHP de l’API Google

Dans ce dépôt GitHub, suivre les instructions « Download the release » :

  • cliquer sur le lien ‘the releases
  • dans le chapitre « Downloads », sélectionner un fichier qui a un nom du genre google-api-php-client-[RELEASE_NAME].zip (pour moi google-api-php-client-2.0.3_PHP54.zip)
  • extraire le fichier zip
  • Copier les fichiers extraits dans un répertoire php-google-api-client  (placé dans notre répertoire de travail, pour moi /home/jf/exec).

Paramétrer un projet dans la console Google Api

La principale source d’informations que j’ai utilisé est PHP Quickstart, par Google.

Se connecter à la console Google API.

Créer un projet

Créer un projet, par exemple « Api Google Calendar » (noter le nom choisi)

Créer un projet dans la console Google Api

Créer un projet dans la console Google Api

 

Activer l’API Google Calendar

Activer l'API Google Calendar

Activer l’API Google Calendar

Obtenir des identifiants

Au sein du projet, aller dans le menu « identifiants ». Ne pas cliquer sur la fenêtre « API identifiants » mais aller dans l’onglet « Ecran d’autorisation OAuth ».

Google calendar API : écran d'autorisation OAuth

Google calendar API : écran d’autorisation OAuth

Maintenant, on peut cliquer sur le bouton « créer des identifiants », on choisit « ID client OAuth » puis « autre ». On lui donne un nom « client Pi calendar » et on crée l’ID :

Google calendar API : ajouter un client

Google calendar API : ajouter un client

Une fois le client créé, une fenêtre s’affiche avec notre ID client et son code secret. Les copier et les coller dans un document. On voit maintenant une liste des clients créés. Télécharger le fichier JSON en cliquant sur le bouton à droite de la ligne :

Google calendar API : télécharger la clé JSON

Google calendar API : télécharger la clé JSON

La clé doit être placée dans un répertoire /home/jf/exec/certificates  et renommée client_secret.json .

On en profite pour créer un répertoire /home/jf/exec/credentials , qui doit être vide.

Vérifier l’organisation du répertoire de travail

Mon répertoire de travail est /home/jf/exec.

A l’intérieur, j’y trouve trois répertoires :

  • certificates, qui contient client_secret.json ;
  • credentials, qui est vide pour l’instant ;
  • php-google-api-client, qui contient la bibliothèque PHP de client de l’API Google, comme dans cette copie d’écran :
Organisation des fichiers pour utiliser l'API Google

Organisation des fichiers pour utiliser l’API Google

Maintenant, on peut créer notre premier script pour intéragir avec notre agenda Google.

Créer un script PHP pour modifier l’agenda

Obtenir l’identifiant de l’agenda à modifier

L’id du calendrier est montrée lorsque je clique sur paramètres (onglet détails) :

Obtenir l'identifiant d'un agenda Google

Obtenir l’identifiant d’un agenda Google

A ce stade on a noté les informations suivantes (AAAA est composé de 44 caractères [a-z][0-9], BBBB de 24 caractères [A-Z][a-z][0-9], CCCC 26 caractères [a-z][0-9]) :

Nom du projet Api Google Calendar
Nom du produit Pi calendars by ALD
ID client AAAA.apps.googleusercontent.com
code secret client BBBB
ID agenda  parcours-performance.com_CCCC@group.calendar.google.com

Ecrire un premier script

J’ai utilisé principalement le script PHP proposé par PHP Quickstart, de Google, ainsi qu’un bout de code trouvé sur la page consacrée à Events: quickAdd.

Attention : si vous utilisez le script PHP proposé dans PHP Quickstart, il faut noter que le code est prévu pour lire le contenu de l’agenda, pas y écrire.

Si on veut pouvoir accéder en lecture ET écriture, il faut modifier la ligne contenant « define( ‘SCOPES’,… », et remplacer CALENDAR_READONLY par CALENDAR. 

Et si on avait déjà obtenu une autorisation quand SCOPES était réglé sur CALENDAR_READONLY, il faut supprimer le fichier JSON dans le répertoire credentials avant de l’éxécuter de nouveau. Sinon, on a une autorisation en lecture seule et on demande l’écriture, ce qui provoque une erreur.  

Créer un fichier al-pi-create-google-calendar-event.php  dans notre répertoire de travail /home/jf/exec.

Dans ce fichier – en mode encodage UTF8, retours de ligne LINUX – placer le code suivant (remplacer l’id du calendrier par votre id) :

#!/usr/bin/php

<?php
require_once __DIR__ . '/php-google-api-client/vendor/autoload.php';


define('APPLICATION_NAME', 'Pi calendars by ALD');
define('CREDENTIALS_PATH', __DIR__ . '/credentials/calendar-php-quickstart.json');
define('CLIENT_SECRET_PATH', __DIR__ . '/credentials/client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at __DIR__ . '/credentials/calendar-php-quickstart.json
define('SCOPES', implode(' ', array(
  Google_Service_Calendar::CALENDAR) // CALENDAR_READONLY
));



if (php_sapi_name() != 'cli') {
  throw new Exception('This application must be run on the command line.');
}

// data for the function
$title = "19.8°C chez Pi Nautilus";
$cal_id = "parcours-performance.com_CCCC@group.calendar.google.com" ;

$create_event = al_pi_create_quick_event( $title, $cal_id ) ;
echo "event ID : " . $create_event . "\r\n" ;


function al_pi_create_quick_event( $title, $cal_id ) {
	
	// Get the API client and construct the service object.
	$client = getClient();
	$service = new Google_Service_Calendar($client);

	// https://developers.google.com/google-apps/calendar/v3/reference/events/quickAdd

	$optParams = Array(
			'sendNotifications' => true,
	);

	$createdEvent = $service->events->quickAdd(
		$cal_id,
		$title,
		$optParams
	);

	return $createdEvent->getId();
	
}

/**
 * Returns an authorized API client.
 * @return Google_Client the authorized client object
 */
function getClient() {
  $client = new Google_Client();
  $client->setApplicationName(APPLICATION_NAME);
  $client->setScopes(SCOPES);
  $client->setAuthConfig(CLIENT_SECRET_PATH);
  $client->setAccessType('offline');

  // Load previously authorized credentials from a file.
  $credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
  if (file_exists($credentialsPath)) {
    $accessToken = json_decode(file_get_contents($credentialsPath), true);
  } else {
    // Request authorization from the user.
    $authUrl = $client->createAuthUrl();
    printf("Open the following link in your browser:\n%s\n", $authUrl);
    print 'Enter verification code: ';
    $authCode = trim(fgets(STDIN));

    // Exchange authorization code for an access token.
    $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);

    // Store the credentials to disk.
    if(!file_exists(dirname($credentialsPath))) {
      mkdir(dirname($credentialsPath), 0700, true);
    }
    file_put_contents($credentialsPath, json_encode($accessToken));
    printf("Credentials saved to %s\n", $credentialsPath);
  }
  $client->setAccessToken($accessToken);

  // Refresh the token if it's expired.
  if ($client->isAccessTokenExpired()) {
    $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
    file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
  }
  return $client;
}

/**
 * Expands the home directory alias '~' to the full path.
 * @param string $path the path to expand.
 * @return string the expanded path.
 */
function expandHomeDirectory($path) {
  $homeDirectory = getenv('HOME');
  if (empty($homeDirectory)) {
    $homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
  }
  return str_replace('~', realpath($homeDirectory), $path);
}


?>

En SSH, se connecter au Pi (Nautilus pour moi)

ssh root@nautilus

Se placer dans le répertoire de travail puis exécuter le fichier :

cd /home/jf/exec
./al-pi-create-google-calendar-event.php

Un message commençant par « Open the following link in your browser: » s’affiche sur l’écran de notre Pi. On copie le lien et on le colle dans un navigateur. Ca nous renvoie à une page dans laquelle je dois autoriser le partage. On copie le code et on le colle dans l’invite de commande du Pi. Le script sauvegarde notre autorisation dans le répertoire défini (/home/jf/exec/credentials) puis nous communique l’event ID :

Google API : autorisation OAuth en mode ligne de commande

Google API : autorisation OAuth en mode ligne de commande

Nous avons été autorisé à interagir avec le calendrier Google et notre premier événement à été créé. A partir de maintenant, nous n’aurons plus besoin d’obtenir de nouveau l’autorisation de l’agenda pour y intervenir.

Et maintenant ?

Maintenant que nous savons comment interagir avec une API Google, on peut en principe faire la même chose avec d’autres API, telles que celle de Google Sheet pour stocker des informations dans un tableur Google.

Raspberry Pi : envoyer des SMS sans 3G et gratuitement

Raspberry Pi : envoyer des SMS sans 3G et gratuitement

Pour un projet, j’ai besoin d’envoyer des SMS lorsque certaines conditions sont réunies. Les tutoriels sur l’envoi de SMS par Raspberry Pi prévoient l’utilisation d’une clé 3G et une carte SD d’un opérateur mobile pour que le Pi dispose d’un numéro de téléphone mobile et puisse envoyer des SMS.

J’ai finalement trouvé 3 solutions :

  • lorsque le destinataire du SMS dispose d’un abonnement FREE, on utilise l’API de notification SMS FREE. C’est la solution la plus simple.
  • Sinon, on peut utiliser IFTTT pour envoyer des SMS lorsque certains événements se produisent. Je l’ai fait pendant longtemps. Le gros inconvénient est que IFTTT n’est pas fiable. Il arrive qu’on ne reçoive le SMS que le lendemain. Cà n’est pas acceptable lorsqu’on veut pouvoir alerter.
  • Enfin, on peut utiliser un agenda google, y créer un événement dès que les conditions prévues sont réunies. Si on a correctement paramétré l’agenda, il enverra un SMS à un destinataire.

Je présente ici les 3 solutions, avec un script PHP placé sur un Raspberry Pi.

Avant de commencer : installer PHP sur le Raspberry Pi

Pour savoir si PHP est installé :

php -v

Si il n’est pas installé :

apt-get update
apt-get upgrade
sudo apt-get install php5 libapache2-mod-php5 -y

Et si curl n’est pas installé :

apt-get install php5-curl

La solution pour un mobile Free

Cette solution très simple ne fonctionne que pour envoyer un SMS à un téléphone FREE.

Obtenir les identifiants de l’API Free

On suit les instructions de « Nouvelle option « Notifications par SMS » chez Free Mobile » pour activer l’option (gratuite) et obtenir une clé d’identification au service. On note aussi notre identifiant d’utilisateur Free Mobile. On obtient les informations suivantes (fausses évidemment mais ressemblantes) :

Utilisateur 12345678
Clé d’Identification KZuaj37069LOSn

Tester l’envoi de SMS via un navigateur

Mettre l’url suivante dans un navigateur internet :

https://smsapi.free-mobile.fr/sendmsg?user=12345678&pass=KZuaj37069LOSn&msg=Bonjour%20Monde%20!

Je reçois un SMS avec « Bonjour Monde ! » comme contenu.

Créer un script PHP pour envoyer le SMS à partir d’un Pi

Créer un fichier test-free-sms.php, avec droits 744 contenant le code suivant :

#!/usr/bin/php

<?php

/* MODIFIER VOS INFORMATIONS ici */
$free_mobile_id = 'YOUR_ID' ;
$free_mobile_key = 'YOUR_KEY' ;

$message = "Bonjour à vous !" ;

$sms_free = al_pi_send_free_mobile_sms( $free_mobile_id, $free_mobile_key, $message  ) ; 

print_r( $sms_free ) ;


function al_pi_send_free_mobile_sms( $id, $key, $txt) {

	/* on doit constituer une url du type
	* https://smsapi.free-mobile.fr/sendmsg?user=12345678&pass=KZuaj37069LOSn&msg=Bonjour%20Monde%20!
	*/
	$url = 'https://smsapi.free-mobile.fr/sendmsg?user=' ;
	$url .= $id ;
	$url .= '&pass=' ;
	$url .= $key ;
	$url .= '&msg=' ;
	$url .= rawurlencode( $txt ) ;

	// envoyer l'url avec une commande CURL
	$ch = curl_init( $url )  ;   
	$timeout = 5;
	
	curl_setopt( $ch, CURLOPT_URL,$url );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );			// return web page = true	
	curl_setopt($ch, CURLOPT_VERBOSE, 1);
	curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout );  	// time-out on connect
	curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 120 );		// time-out on response

	$data = curl_exec( $ch );
	
	// vérifier que tout s'est bien passé 
	// http://php.net/manual/fr/function.curl-getinfo.php
	if(!curl_errno($ch)) {
		$info = curl_getinfo($ch);
		print_r( $info ) ;
	}	
	
	curl_close( $ch );
	return $info;

}

Avant d’exécuter le code, placer vos identifiants en haut du code. Puis, dans le Pi, en ligne de commande, exécuter :

./test-free-sms.php

Je reçois un SMS dans lequel le « à » a disparu si j’ai oublié d’encoder le fichier en utf8.

Et le contenu de $sms_free est :

On pourra donc créer un message selon le résultat en ajoutant :

if ( $sms_free['http_code'] === 200 ) {
	echo "success \r\n" ; 
} else {
	echo "echec \r\n" ; 
}

Et voilà pour cette solution simple.

La solution avec IFTTT

Pour que les recettes IFTTT fonctionnent, il faut les créer : bouton « create recipe » puis :

  1. cliquer sur « THIS »
  2. Choose trigger channel : ‘maker’ (noter la clé de maker)
  3. Cliquer sur receive a web request
  4. event name = ‘Pi_Manquant’ puis “create trigger”.
  5. cliquer sur “THAT”
  6. Channel ‘Android SMS’ puis cliquer sur “send an SMS” et indiquer le numéro de mobile (avec le code 33 pour la france avant, sans le 0, 33611111111) puis définir les paramètres, en particulier comment utiliser value1, value2 et value3.

Ensuite il « suffit » d’envoyer la requête sous la forme suivante pour que l’événement soit déclenché et la recette IFTTT se réalise !

http://maker.ifttt.com/trigger/Pi_Manquant/with/key/YOUR_KEY?value1=fuel&value2=%22Sunday%2004%2010%202015%2006:20:01%20CEST%22&value3=2400

Noter aussi qu’IFTTT permet de faire plein de choses, comme nous prévenir qu’il va pleuvoir demain ou, plus utile, envoyer un mail lorsque notre mobile reçoit un SMS.

On crée un fichier test-ifttt.php contenant :

#!/usr/bin/php

<?php

/* MODIFIER VOS INFORMATIONS ici */
$maker_channel_key = 'VOTRE_CLE' ;

$event = 'pi_missing' ;
$value1 = "Pi hostname" ;
$value2 = "VALEUR 2" ;
$value3 = "valeur 3" ;

$ifttt = al_pi_send_ifttt( $maker_channel_key, $event, $value1, $value2, $value3  ) ; 

if ( $ifttt['http_code'] === 200 ) {
	echo "success \r\n" ; 
} else {
	echo "echec \r\n" ; 
}


function al_pi_send_ifttt( $key, $event, $val1, $val2, $val3 ) {

	/* on doit constituer une url du type
	* http://maker.ifttt.com/trigger/Pi_Manquant/with/key/YOUR_KEY?value1=fuel&value2=%22Sunday%2004%2010%202015%2006:20:01%20CEST%22&value3=2400
	*/

	// encoder les valeurs
	$data = '?value1=' ;
	$data .= urlencode( $val1 );
	$data .= "&value2='";
	$data .= urlencode( $val2 );
	$data .= "'&value3=";
	$data .= urlencode( $val3 );
		
	// encoder l'url complète
	$url = 'http://maker.ifttt.com/trigger/' ;
	$url .= rawurlencode( $event ) ;
	$url .='/with/key/';
	$url .= rawurlencode( $key ) ;
	$url .= $data ;

	// envoyer l'url avec une commande CURL
	$ch = curl_init( $url )  ;   
	$timeout = 5;
	
	curl_setopt( $ch, CURLOPT_URL,$url );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );			// return web page = true	
	curl_setopt($ch, CURLOPT_VERBOSE, 1);
	curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout );  	// time-out on connect
	curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 120 );		// time-out on response

	$data = curl_exec( $ch );
	
	// vérifier que tout s'est bien passé 
	// http://php.net/manual/fr/function.curl-getinfo.php
	if(!curl_errno($ch)) {
		$info = curl_getinfo($ch);
		// print_r( $info ) ;
	}	
	
	curl_close( $ch );
	return $info;

}

Ensuite dans la ligne de commande du Pi :

./test-ifttt.php

Et on déclenche l’événement

Sur ifttt.com, on peut voir le log de chaque « recette ». Par exemple j’ai vu que l’événement Maker Event « pi_missing » s’est bien déclenché. Mais le SMS arrivera quand IFTTT voudra bien… (c’est gratuit, on ne doit pas se plaindre).

Je trouve par contre que IFTTT fonctionne très bien avec la chaîne GMAIL et envoie des mails immédiatement. Mais si on doit envoyer un message à quelqu’un qui n’a pas de forfait de données sur son téléphone, IFTTT peut quand même être utile, même s’il n’est pas fiable.

La solution avec un agenda Google

Créer un calendrier « spécial Pi » sur google agenda

Dans mon agenda Google, dans la barre latérale de gauche, cliquer sur la flèche à droite de « Mes agendas » et choisir « créer un agenda ». Donner un nom à l’agenda (par exemple « Pi Nautilus ») puis « Créer ». L’agenda est maintenant visible sur le côté gauche, dans la liste des agendas.

Modifier les notifications

Cliquer sur la flèche à droite de l’agenda « Pi Nautilus » et choisir « paramètres » puis aller dans l’onglet « modifier les notifications ».

Agenda Google : régler pour notifier par SMS

Si on veut définir un autre numéro de téléphone comme destinataire du SMS, on clique sur le lien « configuration du mobile ».

A ce stade, si quelqu’un crée ou modifie un événement, le téléphone défini reçoit un SMS.

On peut créer des événements automatiquement par un programme. Cette solution, dans laquelle un Pi crée un événement, lorsque certaines conditions sont réunies, est expliquée dans l’article Interagir avec L&rsquo;agenda Google via l&rsquo;API (OAuth 2.0) .

Et maintenant ?

Vivement que tous les opérateurs de téléphonie mobile fassent comme Free et proposent une API d’envoi de SMS !

Plesk, un site avec des fichiers html ou php, sans CMS

Plesk, un site avec des fichiers html ou php, sans CMS

J’hébergeais sur OVH un site assez simple, qui suit le bon fonctionnement de mes Raspberry Pi. Comme j’ai migré l’hébergement OVH sur un VPS OVH avec Plesk, j’ai également dû déplacer ce site.

J’explique donc ici comment installer un site composé de fichiers php et css dans un hébergement Plesk. Ce site n’a pas de base de données et n’utilise pas de gestionnaire de contenus type WordPress.

Créer un sous-domaine et y transférer les fichiers

J’ai ajouté un sous-domaine dans mon compte Plesk, par exemple domicile.mon-domaine.com.

J’y ai transféré les fichiers de l’hébergement initial en ftp. J’ai placé les fichiers dans un répertoire temporaire ‘temp-al’.

Placer les fichiers au bon endroit

Dans Plesk, tel qu’il est paramétré, les fichiers doivent être rangés comme suit :

  • css dans le répertoire domicile.mon-domaine.com/css
  • php ou html directement dans domicile.mon-domaine.com/
  • favicon.ico à la racine (image 256x256px)
NOTA : mon VPS Plesk étant sous linux, les fichiers doivent tous être avec des fins de ligne en mode linux, et pas windows. Sinon ça ne fonctionne pas. 

Donner l’accès au site

Lorsque le sous-domaine a été créé, Plesk y a placé un fichier index.html. Pour que ce soit index.php qui soit exécuté, il suffit de supprimer le fichier index.html.

Et maintenant, dans un navigateur, http://domicile.mon-domaine.com ouvre bien sur un site défini par le contenu de index.php.

Afficher les erreurs

En tant qu’administrateur, on peut modifier les paramètres PHP du sous-domaine et régler « display_error » sur « on ».

Et voilà !

Plesk, accéder en FTP aux hébergements

Plesk, accéder en FTP aux hébergements

Nous allons voir ici comment se connecter en FTP à un hébergement Plesk, avec des outils comme net2ftp ou filezilla. La documentation Plesk (Accès FTP au site Web) est complète, j’indique juste ici quels sont les paramètres de connexion dans net2ftp ou Filezilla.

Utiliser net2ftp

Attention, il ne faut utiliser que des net2ftp sécurisés et fiables, comme ceux qui sont proposés par les hébergements OVH (ou aussi par un hébergement Plesk si on actionne le service).

Les identifiants et mots de passe FTP des hébergements Plesk sont définis comme indiqué dans ce document Plesk. Le serveur est simplement le nom de domaine concerné sans rien devant (domaine1.com par exemple)

Utiliser Filezilla

Voici le paramétrage (plesk-id et le mot de passe ont été définis dans comptes FTP du domaine mon-domaine.com) :

ftp-vers-site-plesk

Et maintenant

On peut lire d’autres articles de cette série ici :