Introduction

Aujourd’hui je vous propose de communiquer par SMS avec Domoticz via un modem USB 3G. D’autres tutoriaux existent, utilisant un téléphone comme passerelle. Ici, nul besoin d’un téléphone. En revanche nous allons utiliser un modem USB 3G, qui aura l’avantage de servir exclusivement aux échanges SMS. Le gros avantage du SMS par rapport aux autres notifications, c’est que cela ne dépend pas de la connexion internet. Ainsi, même si votre box internet tombe en panne, Domoticz sera toujours en mesure de communiquer. Voici les pré-requis:
  • Avoir Domoticz installé sur une distribution Linux. Dans mon cas il tourne sur un Raspberry Pi 3.
  • Avoir un modem USB. J’utilise un Huawei E220. Il date un peu, mais en principe n’importe quel modem USB 3G devrait faire l’affaire.
  • Avoir une carte SIM dédiée à cet usage.
Voici à quoi ressemble le Huawei E220:  

Installation

Il faut donc dans un premier temps insérer la carte SIM dans le modem, puis connecter celui-ci en USB sur la machine hébergeant Domoticz. Ceci n’est pas obligatoire, le modem pourrait très bien être sur une autre machine, mais c’est plus simple à réaliser. Nous allons ensuite passer par des commandes Linux, afin d’utiliser ce modem et l’interfacer avec Domoticz. La commande dmesg devrait vous retourner le port sur lequel est branché le modem, du type ttyUSB0, ttyUSB1… Le problème, c’est qu’au redémarrage, le port peut changer. Nous allons devoir utiliser un périphérique USB persistant. Taper la commande suivante: sudo lsusb -v | more Noter les paramètres suivants:
*idVendor
*idProduct
*iSerial (si c'est 0, vous pouvez l'ignorer)
Par exemple, pour le Huawei E220, nous avons:
idVendor           0x12d1 Huawei Technologies Co., Ltd.
idProduct          0x1003 E220 HSDPA Modem / E230/E270/E870 HSDPA/HSUPA Modem
iSerial            0
  Ensuite créer (ou modifier s’il existe) le fichier /etc/udev/rules.d/99-usb-serial.rules: sudo nano /etc/udev/rules.d/99-usb-serial.rules Ajouter la ligne suivante: SUBSYSTEM== »tty », ATTRS{idVendor}== »12d1″, ATTRS{idProduct}== »1003″, SYMLINK+= »ttyUSB31″ En prenant soin évidemment de remplacer le valeurs par celles retournées par la commande précédente. Ensuite redémarrer le système! Sous Linux: sudo shutdown -r now Maintenant, le modem sera toujours sur le port USB /dev/ttyUSB31.  

Envoyer des SMS

Pour envoyer et recevoir des SMS, nous utiliserons Gammu. Ce logiciel permet d’envoyer des SMS, et de déclencher des scripts lors de la réception de SMS. Connectez-vous dessus avec un terminal et mettez à jour la liste des paquets. Ensuite installez gammu et gammu-smsd:
sudo apt-get update
sudo apt-get -y install gammu gammu-smsd
Il faut ensuite indiquer à Gammu quel port USB utiliser en éditant le fichier /etc/gammu-smsdrc :
[gammu]
#Please configure this!
port = /dev/ttyUSB31
connection = at
# Debugging
#logformat = textall
Si vous n’avez pas désactivé le code PIN, vous devrez rajouter la ligne suivante : pin = XXXX Il faut bien entendu démarrer le service pour la prise en compte des paramètres modifiés : sudo service gammu-smsd start Vous pouvez maintenant tester l’envoi de SMS avec la commande : sudo -u gammu gammu-smsd-inject TEXT 06xxxxxxxx -text « MESSAGE » En remplaçant « MESSAGE » par le message de votre choix. Si cela ne fonctionne pas, vérifiez que l’utilisateur linux sous lequel vous êtes peut faire un « sudo -u gammu ». Pour tester l’envoi d’un SMS depuis Domoticz, vous pouvez mettre ceci dans un script LUA:
os.execute ('sudo -u gammu gammu-smsd-inject TEXT "+336xxxxxxxx" -text "TEST"')
 

Recevoir des SMS

Voilà, Domoticz sait vous envoyer des SMS. Passons maintenant à la réception des SMS. Pour cela il faut revenir au fichier /etc/gammu-smsdrc. A la fin du fichier, placer: runonreceive = /root/gammu/receivesms.py Puis relancer gammu: sudo /etc/init.d/gammu-smsd restart Ce fichier sera exécuté à chaque réception de SMS, avec 2 variables:
$SMS_1_NUMBER -- c'est le numéro de l'expéditeur
$SMS_1_TEXT -- c'est le contenu du message
Avant tout, dans Domoticz, créer une variable « sms » de type « chaîne » et noter son index. Voici un exemple de fichier receivesms.py:
!/usr/bin/python
import os
import sys
import urllib

#Mise a jour dans Domoticz
DOMO_IP="127.0.0.1" # Addresse IP de Domoticz
DOMO_PORT="8080" # Port de Domoticz
IDX="11" # Index de la variable "sms"

urllib.urlopen("http://"+DOMO_IP+":"+DOMO_PORT+"/json.htm?type=command&param=updateuservariable&idx="+IDX+"&vname=sms&vtype=2&vvalue="+urllib.quote(os.environ['SMS_1_TEXT'])+";"+urllib.quote(os.environ['SMS_1_NUMBER']))
Explications: à chaque réception de sms, le script va mettre à jour une variable « sms » dans Domoticz. Ensuite nous créerons un script qui réagira au changement de cette variable. Note: il faut rendre le fichier receivesms.py exécutable: sudo chmod +x /root/gammu/receivesms.py Je vous invite à lire cette page qui vous donnera un exemple de script LUA pour la réception de sms et l’interaction avec Domoticz. Voici un exemple simplifié:
-- script_variable_sms.lua
--
-- un smartphone connecté au réseau wifi de la maison
-- avec l'application 'sms gateway ultimate' installée
-- https://play.google.com/store/apps/details?id=com.icecoldapps.smsgatewayultimate
--
-- dès qu'un sms est reçu, l'application met à jour une variable utilisateur nommée 'sms' via la requette json suivante
-- http://USER:PASS@IP:PORT/json.htm?type=command&param=updateuservariable&idx=IDX&vname=sms&vtype=2&vvalue=%body%;%from%
--
-- dès que la variable 'sms' est modifiée, ce script est exécuté.
-- suivant une correspondance avec l'un des messages de la liste ci dessous,
-- si la personne y est autorisée,
-- l'action associée est lancée
--
-- un message de réponse est retourné
--
-- la commande 'Help' retourne un SMS contenant la liste
--

--------------------------------
------ Tableau à éditer ------
--------------------------------
-- liste des messages à comprendre et leurs actions associées
local liste={}
--liste['message'] = "action"
liste['Help'] =          	[[   reponse = 'Je comprend: '..sendAll()   ]]   -- ne pas toucher cette ligne

liste['Ping'] =       	[[   reponse = 'Pong!'   ]]

-- liste des utilisateurs autorisés
local user={}
user['Toto'] = '+336xxxxxxxx'
user['Tata'] = '+336yyyyyyyy'

-- réponses par défaut
local good = 'Ok..'                                 -- réponse en cas de commande correcte
local notGood = 'Je ne comprends pas, essayez \'Help\''      -- réponse en cas de commande non comprise
local guess = 'Je ne vous connais pas !'               -- réponse aux utilisateurs non autorisés

--------------------------------
-- Fin du tableau à éditer --
--------------------------------

function spairs(t)
    local keys = {}
    for k in pairs(t) do keys[#keys+1] = k end
   table.sort(keys)
   local i = 0
   return function()
      i = i + 1
      if keys[i] then
         return keys[i], t[keys[i]]
      end
   end
end

function url_encode(str)
  if (str) then
    str = string.gsub (str, "\n", "\r\n")
    str = string.gsub (str, "([^%w %-%_%.%~])",
        function (c) return string.format ("%%%02X", string.byte(c)) end)
    str = string.gsub (str, " ", "+")
  end
  return str   
end

function sendAll()
   for message, action in spairs(liste) do
      if message ~= 'Help' then
         if rst == nil then
            rst = message
         else
            rst = rst..'\n'..message
         end
      end      
   end
   return rst
end

commandArray = {}

if(uservariablechanged['sms']) then
   sms,from = uservariables['sms']:match("([^;]+);([^;]+)")
   local msg = "print('SMS reçu du N° '..from..' : \"'..sms..'\"')"
    for name, number in pairs(user) do
        reponse = guess
        if number == from then
            print('SMS reçu de '..name..' : \"'..sms..'\"')
            reponse = notGood
            msg = "print('SMS, commande invalide')"
            for message, action in pairs(liste) do
                if sms == message then
                    reponse = good
                    msg = "print('SMS, commande correcte')"
                    load(action)()
                    break
                end
            end
            break
        end   
    end
    load(msg)()
    print('SMS : reponse -> '..reponse)
    os.execute ('sudo -u gammu gammu-smsd-inject TEXT "'..from..'" -text "'..reponse..'"')
end

return commandArray
Grâce à ce script, lorsque la variable « sms » sera mise à jour, Domoticz saura la lire et répondre en conséquence, s’il connaît le numéro ou non. Et voilà, vous avez un Domoticz qui sait envoyer et recevoir des SMS!  

Recevoir toutes les notifications de Domoticz par SMS

Si vous voulez recevoir toutes les notifications de Domoticz par SMS, rien de plus simple! Je vous propose un exemple de script qui peut être appelé par Domoticz pour envoyer un SMS:
#!/usr/bin/python
import sys
import os
import datetime

now = datetime.datetime.now()

text = "["+now.strftime("%d/%m/%Y @ %H:%M")+"] "+sys.argv[1]

phone_numbers = ["+336xxxxxxxx"],["+336yyyyyyyy"]

for number in phone_numbers:
	command = "sudo -u gammu gammu-smsd-inject TEXT "+number+" -text \""+text+"\""
	os.system(command)
Dans Domoticz, allez dans Réglages, Paramètres, puis sur l’onglet Notifications. Dans la partie « HTTP personnalisé/Action », cochez « Activé » et renseignez le script sendsms.py dans « URL/Action »: Sauvegardez, et Domoticz vous enverra toutes les notifications par SMS!

Reset du modem

Dernier point: comme je l’ai dit plus haut, cela devrait fonctionner avec n’importe quel modem USB. Ceci dit, je n’ai testé qu’avec le Huawei E220. Avec ce modem, j’ai rencontré quelques difficultés au début. En effet, au bout de quelques jours, il perdait la connexion, m’obligeant à le débrancher puis le rebrancher physiquement pour le réinitialiser (un redémarrage du système ne solutionnait pas le problème). J’ai trouvé une autre solution par un script de réinitialisation que je lance chaque nuit. Cela fonctionne pour ce modem, je ne sais pas si c’est utile et si ça fonctionne pour d’autres. Tout d’abord, il faut installer minicom: sudo apt-get install minicom Ensuite créer un script pour minicom qui va envoyer les commandes de réinitialisation au modem. Je l’ai appelé modem_reset.minicom :
send AT+CFUN=0
sleep 3
send AT+CFUN=0
sleep 3
send AT+CFUN=1
sleep 3
! killall -9 minicom
Puis créer un script shell qui va appeler ce script, en prenant soin de stopper puis relancer gammu-smsd. Je l’ai appelé modem_reset:
#!/bin/bash
TERM=vt100
export TERM
sudo /etc/init.d/gammu-smsd stop
sleep 5
/usr/bin/minicom -D /dev/ttyUSB31 -S /root/modem_reset.minicom
sleep 5
sudo /etc/init.d/gammu-smsd start
Ne pas oublier de rendre ce script exécutable: chmod +x modem_reset Enfin mettre un cron qui va lancer cette tâches toutes les nuits, par exemple à 4h25 du matin (sudo crontab -e): 25 4 * * * /root/modem_reset > /root/modem_reset.log Explications: Ce script va arrêter gammu-smsd (qui prend le contrôle exclusif du modem), envoyer au modem des commandes de réinitialisation, puis relancer gammu-smsd.

Laisser un commentaire