sendSMS

Il m'arrive de zapper des rendez-vous (tout ce qu'il y a de plus normal). Du coup je me suis dit que ça serait bien si je pouvais être notifié des choses à faire le moment venu. Qu'à cela ne tienne, j'ai réfléchi au sujet (oui, ça m'arrive de temps en temps). J'en suis arrivé à la conclusion qu'il me fallait implémenter trois objectifs fonctionnels :

  • todo : pour créer les tâches à faire
  • scheduler : pour plannifier ces tâches
  • notifier : pour notifier l'utilisateur

Les deux premiers points pouvant être simplifiés par un message et une ligne dans la crontab, je me suis focalisé uniquement sur le notifier (d'où ce projet que je présente).

Analyse et conception

Pour être notifié n'importe où et n'importe quand, la solution que j'ai choisi est l'envoi de SMS. Pour information, voici les autres solutions que je n'ai pas retenu :

  • l'envoi de mail : nécessite d'avoir un équipement tout le temps connecté sur internet (ce qui n'est pas mon cas)
  • une application embarqué sur un gadget ou un téléphone : trop long et plus compliqué à développer (en ce qui me concerne)

Je suis chez Free Mobile, du coup je peux utiliser une API gratuite pour m'envoyer des SMS (merci mon entourage pour l'information). Celle-ci attend une requête HTTP de type POST ou GET contenant les trois paramètres suivant :

  • user : login d'accès au portail Free Mobile
  • pass : clé d'identification au service (générer à l'activation de l'option "Notifications par SMS)
  • msg : message à envoyer

Pour utiliser ce service il faut l'activer sur son espace Free Mobile. Pour se faire, aller dans Gérer mon compte > Mes Options > Notifications par SMS puis cliquer sur Activer.

J'ai choisi de développer cette utilitaire en bash pour aller au plus vite (habitude d'usage professionnel). Je me suis inspiré de sendmail pour trouver son nom sendsms (pourquoi chercher à faire compliqué ?).

J'ai décidé que sendsms permettrait d'envoyer un SMS en spécifiant les paramètres de deux manières différentes :

  • en ligne de commande (à la suite du nom du programme)
  • via un fichier de configuration général et/ou lié à l'usager (pour gagner du temps)

J'y rajoute des options de confort tel que l'aide et la version.

Codage

Pour gérer ces paramètres j'utilise getopts qui est nativement intégré au bash :

while getopts ":hvf:u:p:" option; do
  case ${option} in
    h) cli.usage ;;
    v) cli.version ;;
    f) [ -f ${OPTARG} ] && UCF=${OPTARG} || cli.error "-f ${OPTARG}: file doesn't exist" ;;
    u) CONFIG[user]="${OPTARG}" ;;
    p) CONFIG[password]="${OPTARG}" ;;
    :) cli.error "-${OPTARG}: required an argument" ;;
    \?) cli.error "-${OPTARG}: unknown option" ;;
  esac
done

shift $((OPTIND-1))

[ "$#" -ne "0" ] && CONFIG[message]="${*}"

-u et -p permettant respectivement de passer les valeurs des paramètres user et pass directement dans la ligne de commande. Je rajoute la possibilité de spécifier un fichier de configuration (-f <file>). Nous y retrouvons aussi les options d'aide (-h) et de version (-v). : et ? correspondant à la gestion des erreurs. Le message à envoyer étant tout ce qui reste, je supprime toute les précédantes options/valeurs via la commande shift $((OPTIND-1)) et je le récupère (CONFIG[message]="${*}").

Pour parser les paramètres depuis un fichier de configuration de type .INI :

for file in ${SCF} ${UCF}; do
  if [ -f ${file} ]; then
    while read line; do
      if [[ $line == ?*"="?* ]]; then
        [ ${CONFIG[${line%%=*}]+a} ] && CONFIG[${line%%=*}]=${line##*=}
      fi
    done < <( sed -r 's/\s+//g' ${file} )
  fi
done

${SCF} et ${UCF} sont des variables contenant les chemins des fichiers de configuration général et utilisateur.

Pour envoyer la requête HTTP, j'ai choisi d'utiliser curl :

curl -s -w "%{http_code}\n" "https://smsapi.free-mobile.fr/sendmsg?user=${CONFIG[user]}&pass=${CONFIG[password]}&msg=${CONFIG[message]}"
  • -s : option de curl qui active le mode silencieux pour ne pas polluer l'affichage sur le terminal
  • -w "%{http_code}" : option de curl qui permet d'afficher le code de réponse HTTP (utile pour savoir si tout c'est bien passer et faire la gestion des erreurs)
  • ${CONFIG[*]} : un tableau associatif bash qui contient les valeurs des paramètres user, pass et msg

Pour gérer les erreurs de communication avec l'API, je récupère l'entrée standard produite par curl et j'analyse les codes de retour :

case ${rc} in
  200) echo "${rc}: Success"; exit 0 ;;
  400) echo "${rc}: One of needed parameters is missed or incorrect"; exit 1 ;;
  402) echo "${rc}: Too many request sent, please wait few time"; exit 1 ;;
  403) echo "${rc}: Access denied, check your credentials"; exit 1 ;;
  500) echo "${rc}: SMS API got an internal error, try again later"; exit 1 ;;
  *) echo "${rc}: Unknown error"; exit 1 ;;
esac

Un point que je n'ai pas abordé : j'ai récupéré un script sed sur le net pour "encoder" le message au format url. Cela m'a était utile pour corriger un problème avec les caractères spéciaux. (Désolé pour l'auteur, mais je n'ai pas retrouvé son nom)

Usage et maintenance

Récupérer le projet sur GitHub et suivre la procédure d'installation.

Créer son fichier de configuration ~/.sendsms.conf :

user=Login
password=PrivateKey

Enjoy :

sendsms "faire un post pour présenter ce projet"

Et si vous décelé un BUG, ne pas hésiter à me le remonter.

Conclusion

Ca c'est fait ! Il me reste plus que 2243 autre mini-projets à faire et présenter ! (nan je blague... Quoique...)

J'espère que ce projet vous à intéréssé. N'hésiter pas à me faire un retour. Normalement il y en aura plein d'autres qui suivront en parrallèle de divers articles.

By @Mikael FLORA in
Tags : #dev, #bash, #script, #shell, #network,