N'ayant rien trouvé du coté de Somfy pour s'interfacer avec le monde extérieur, j'ai écrit un petit bout de python qui se connecte à l'interface web de l'alarme pour récupérer son état. Ainsi, je peux l'envoyer à l'eedomus pour gérer des choses.
Par exemple, quand l'alarme se met en route, les volets descendent.
Je tiens à préciser que c'est une solution de secours, ce n'est clairement pas viable. L'idée du script est de se connecter toute les minutes sur l'alarme. Pensez à utiliser une crontab.
Quand est-ce que Somfy proposera un mode push !!!!!!!!!
- Code : Tout sélectionner
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import mechanize
class SomfyException(Exception):
def __init__(self, value):
Exception.__init__(self, value)
self.value = value
def __str__(self):
return repr(self.value)
class Somfy:
def __init__(self, config):
self.config = config
self.browser = mechanize.Browser()
def __enter__(self):
self.login()
return self
def __exit__(self, type, value, traceback):
self.logout()
def login(self):
login_response = self.browser.open(self.config.get('somfy', 'url') + "/m_login.htm")
login_html = login_response.read()
login_soup = self._beautiful_it_and_check_error(login_html)
authentication_code = login_soup.find('form').find('table').findAll('tr')[5].findAll('b')[0].find(text=True)
self.browser.select_form(nr=0)
self.browser["password"] = self.config.get('somfy', 'password')
self.browser["key"] = self.config.get('somfy', 'key_%s' % authentication_code)
self.browser.submit()
def logout(self):
self.browser.open(self.config.get('somfy', 'url') + "/m_logout.htm")
def set_zone_a(self):
self.browser.open(self.config.get('somfy', 'url') + "/mu_pilotage.htm")
self.browser.select_form(nr = 0)
self.browser.submit()
def set_zone_b(self):
self.browser.open(self.config.get('somfy', 'url') + "/mu_pilotage.htm")
self.browser.select_form(nr = 1)
self.browser.submit()
def set_zone_c(self):
self.browser.open(self.config.get('somfy', 'url') + "/mu_pilotage.htm")
self.browser.select_form(nr = 2)
self.browser.submit()
def set_all_zone(self):
self.browser.open(self.config.get('somfy', 'url') + "/mu_pilotage.htm")
self.browser.select_form(nr =3)
self.browser.submit()
def unset_all_zone(self):
self.browser.open(self.config.get('somfy', 'url') + "/mu_pilotage.htm")
self.browser.select_form(nr =4)
self.browser.submit()
def get_state(self):
state_response = self.browser.open(self.config.get('somfy', 'url') + "/mu_etat.htm")
state_html = state_response.read()
state_soup = self._beautiful_it_and_check_error(state_html)
result = self.get_general_state(state_soup.findAll('table')[0])
result.update(self.get_zone_state(state_soup.findAll('table')[0]))
return result
def get_zone_state(self, state_soup):
zone_state = state_soup.findAll('table')[2].findAll('tr')
def get_zone_a():
return { "zone_a" : zone_state[0].find(text=True) }
def get_zone_b():
return { "zone_b" : zone_state[1].find(text=True) }
def get_zone_c():
return { "zone_c" : zone_state[2].find(text=True) }
result = get_zone_a()
result.update(get_zone_b())
result.update(get_zone_c())
return result
def get_general_state(self, state_soup):
general_state = state_soup.findAll('table')[1].findAll('tr')
def get_battery_state():
return { "battery" : general_state[0].find(text=True) }
def get_communication_state():
return { "communication" : general_state[1].find(text=True) }
def get_door_state():
return { u"door" : general_state[2].find(text=True) }
def get_alarm_state():
return { "alarm" : general_state[4].find(text=True) }
def get_material_state():
return { "material" : general_state[6].find(text=True) }
result = get_battery_state()
result.update(get_communication_state())
result.update(get_door_state())
result.update(get_alarm_state())
result.update(get_material_state())
return result
def _beautiful_it_and_check_error(self, html):
soup = BeautifulSoup(''.join(html))
self._check_error(soup)
return soup
def _check_error(self, soup):
if soup.find("div", {"class": "error"}):
error_code = soup.find('div').findAll('b')[0].find(text=True)
if '(0x0904)' == error_code:
raise SomfyException("Nombre d'essais maximum atteint")
if '(0x1100)' == error_code:
raise SomfyException("Code errone")
if '(0x0902)' == error_code:
raise SomfyException("Session deja ouverte")
if '(0x0812)' == error_code:
raise SomfyException("Mauvais login/password")
if '(0x0903)' == error_code:
raise SomfyException("Droit d'acces insuffisant")