Born to be wired

 SMS automatisé – Bonus round

Le thème de l’envoi automatisé de SMS, je pensais l’avoir traité en long en large et en travers, alors je m’étais jugé que je n’en reparlerais plus. Il faut dire que ça marchait plutôt bien. Ça fonctionnait tellement bien, que parfois, je recevais même des mignons petits messages de gentils inconnus qui s’étaient malencontreusement plantés de numéro, dans ce genre là :

sms-spam

Et il faut le dire, parfois, dans ce cas-là, j’hésitais à répondre. Et parfois, dans ce cas-là, le choix de réponse était cornélien, comme si cela entrainait des répercussions capitales sur tout le reste de ma longue et héroïque quête de l’aventure humaine :

sms-by-npc-rpg

Bref, au delà des enfantillages, deux évènements se sont produits dans les dernières semaines et m’ont incité a rédiger une brève suite à cette série d’articles.

Évènement n°1 : le modem GSM qui se vautre

Qui se vautre, c’est un peu exagéré. Je devrais plutôt dire « qui se bloque ». Du point de vue de l’utilisateur, c’est pareil. Restons réaliste : il s’agit pour ma part d’un produit chinois pas cher destiné à envoyer 2 SMS par an à tout casser, je n’espérais donc pas une continuité de service à 100% sur l’année. J’ai ainsi constaté, après de longs mois d’inutilisation, qu’un SMS inséré en base de données dans la boîte d’envoi refusait de partir, et que son statut passait en erreur. Un redémarrage de smsd ne résolvait pas le problème. Un déchargement du module pl2303, qui gère la communication USB avec le modem GSM, non plus. Par contre, le fait de couper l’alimentation du modem GSM par débranchement/rebranchement du cordon USB remettait le modem en état de traiter l’envoi du SMS.

Alors, évidemment, hors de question d’aller triturer les cordons USB à l’intérieur de ma trappe à serveur tous les 3 mois. Il fallait trouver une manière logicielle de réinitialiser le modem, par coupure de l’alimentation du port USB adéquat, sans impacter les périphériques connectés sur les autres ports USB. Ceci est possible grâce au programme qui suit, trouvé sur le net et subtilement adapté pour mes besoins : (usbreset.c)

/* usbreset -- send a USB port reset to a USB device */

/*
        INSTRUCTIONS

    Compile the program:
    $ cc usbreset.c -o usbreset

    Get the Bus and Device ID of the USB device you want to reset:
    $ lsusb
    Bus 002 Device 006: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port

    Make our compiled program executable:
    $ chmod +x usbreset

    Execute the program with sudo privilege; make necessary substitution
    for Bus and Device ids as found by running the lsusb command:
    $ sudo ./usbreset /dev/bus/usb/002/006

*/

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>

#include <linux/usbdevice_fs.h>


int main(int argc, char **argv)
{
    const char *filename;
    int fd;
    int rc;

    if (argc != 2) {
        fprintf(stderr, "Usage: usbreset device-filename\n");
        return 1;
    }
    filename = argv[1];

    fd = open(filename, O_WRONLY);
    if (fd < 0) {
        perror("Error opening output file");
        return 1;
    }

    printf("Resetting USB device %s\n", filename);
    rc = ioctl(fd, USBDEVFS_RESET, 0);
    if (rc < 0) {
        perror("Error in ioctl");
        return 1;
    }
    printf("Reset successful\n");

    close(fd);
    return 0;
}

Pour ma part, j’ai créé un shell de lancement supplémentaire, qui recherche le device a redémarrer parmi la liste des devices USB connectés (le modem Wavecom est identifié par la chaîne PL2303), et qui lance usbreset avec les bons paramètres. Ça donne ce qui suit (à adapter en fonction du chipset identifiant le device USB à réinitialiser, et des chemins relatifs des exécutables) :

#!/bin/bash

DIR=$(cd $(dirname $0);pwd)
NEEDLE=PL2303
USBDEV=/dev/bus/usb/$(/usr/bin/lsusb | grep ${NEEDLE} | cut -d: -f1 | sed -r 's#Bus ([0-9]{3}) Device ([0-9]{3})#\1/\2#')

if [ -c "${USBDEV}" ] ; then
        if [ -x "${DIR}/../bin/usbreset" ] ; then
                ${DIR}/../bin/usbreset "${USBDEV}"
        else
                echo "Binary file usbreset not found, operation aborded." >&2
                exit 2
        fi
else
        echo "USB device for ${NEEDLE} not found, operation aborded." >&2
        exit 1
fi

Il ne reste plus qu’à scruter la base de données à intervalles réguliers, par exemple au niveau de la boite d’envoi. Si un SMS est vu avec un code retour erroné :

  1. On arrête smsd
  2. On réinitialise les attributs du SMS en base de données et son code retour, pour qu’il soit traité à nouveau
  3. On lance le script de réinitialisation du port USB
  4. On redémarre smsd
  5. On attend quelques secondes que le SMS soit à nouveau traité
  6. S’il n’a pas été correctement traité, on positionne un statut complémentaire (code d’erreur ou autre) afin que cette boucle ne soit pas itérée à l’infini, le problème pouvant être tout autre (modem cramé / pas de réseau / plus de crédit…)

C’est un mode de supervision basique et perfectible, mais il a le mérite d’exister. Avouons qu’il serait dommage de louper le seul SMS automatisé que vous recevrez par an (en dehors de ceux qui vous informent des soldes chez But ou Zara, et de celui du petit plaisantin geek qui vous souhaite une bonne année), le seul SMS automatisé vraiment important, celui qui vous signale que votre congel n’est plus alimenté en électricité, que votre maison est en feu ou à la merci de cambrioleurs indélicats, simplement à cause d’un petit blocage du modem GSM. Voila qui résout la problématique.

Évènement n°2 : l’arrivée du service de notification par SMS de Free Mobile

Xavier, si tu nous regardes, tu es pour moi un modèle d’admiration. Pourquoi ? Parce que Free a sorti fin juillet, j’admets que ça date un peu, un nouveau service accessible gratuitement à tous ses abonnés Free Mobile. Ce service permet à l’abonné Free Mobile de recevoir, sur le numéro de téléphone mobile lié à son compte, un SMS dont le texte est à la discrétion de l’utilisateur, et cet envoi peut être déclenché par une simple requête web.

Une API minimaliste qui s’avère être une solution formidable pour ceux qui ne souhaitent pas se lancer dans l’achat du modem GSM, d’autant plus qu’elle est accessible même pour le forfait 2 euros. En résumé, le service de notification par SMS de Free Mobile constitue un atout indéniable pour les bidouilleurs férus de domotique.

Si on compare brièvement les deux solutions, on notera principalement que le modem GSM offre plus de souplesse puisqu’il permet l’envoi de SMS vers n’importe quel numéro, et qu’il permet la réception de SMS en plus de l’envoi, possibilités non offertes par le service de notification de Free Mobile. D’un autre côté, si on opte pour la solution modem GSM, il faut investir un peu d’argent dans l’appareil et dans le crédit de SMS associé au compte SIM. Autre aspect à prendre en compte, même si le service offert par Free Mobile s’avère d’un grand secours pour un complément pécuniaire nul, rien n’oblige la société à maintenir ce service dans le futur.

Ce sont donc deux solutions qui possèdent chacune leurs atouts et qui peuvent être utilisées en complément l’une de l’autre, ce que je ne manquerai pas de faire.

OK, c’est bien gentil, mais comment on procède ?

Il suffit de se rendre sur la page de gestion de son compte Free Mobile et d’activer le service « Notification par SMS ». Une clé d’identification est alors générée, elle sera a utiliser avec l’identifiant de l’abonné.

freemobile-sms-notification-instructions

Il est alors possible d’utiliser ces informations pour déclencher l’envoi du SMS de notification par une simple page web. Le principe est évidemment automatisable, c’est le but, par un script écrit dans le langage de votre choix. Ici, un exemple en shell/PHP écrit et testé en 15 minutes :

#!/bin/bash
SMSUSER=12345678
SMSPASS=VL9PavlBHInVwz
SMSMESG='Youpi ! Envoyons des SMS de notification avec Free !'
SMSURL='https://smsapi.free-mobile.fr/sendmsg?user='${SMSUSER}'&pass='${SMSPASS}'&msg='$(php -r 'print rawurlencode($argv[1])."\n";' -- "${SMSMESG}")
HTTPCODE=$(curl -k -s -o /dev/null -m 15 -w '%{http_code}' "${SMSURL}")
ERRORCODE=$?

if [ "${ERRORCODE}" != 0 ] ; then
        exit 2
else
        if [ "${HTTPCODE}" != 200 ] ; then
                exit 3
        else
                exit 0
        fi
fi

Script qui entraine immédiatement l’arrivée du SMS suivant sur mon mobile :

What else ?

What else ?

C’est sur ces derniers mots que je conclus cet article bonus. En d’autres termes, c’est tout pour aujourd’hui. Dans mon prochain article, je détaillerai une petite installation que j’ai mise en place à domicile, et qui un jour peut-être permettra de sauver une vie.

 2 commentaires pour “SMS automatisé – Bonus round”

  1.  Flo

    Salut Vince a quand le prochain post ?? 😉

  2.  AlphaK

    T’es matinal toi ! 🙂
    À vrai dire j’ai beaucoup d’idées de sujet, mais peu de temps et d’énergie pour les rédiger proprement. On peut quand même espérer au moins un post pour le mois de février. À très vite IRL 🙂

 Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.