Compare commits

8 Commits

Author SHA1 Message Date
Gilles MOREL
72e1c94a80 Traduction du README en français
Cette bibliothèque ne sert que pour un service français fourni en France.
2020-09-27 15:22:55 +02:00
Gilles MOREL
8fb1eac749 Correction du style 2020-09-26 07:55:57 +02:00
Gilles MOREL
b338230b37 Récupération des paramètres de la caméra
J'ai aussi enlevé la classe Camera pour intégrer les méthodes dans la classe Sensor.
2020-09-26 07:51:52 +02:00
Gilles MOREL
f5e8e4bdf0 Mise à jour de l'authentification 2020-09-20 12:00:45 +02:00
Gilles MOREL
952cf74b8e Passage à la version 1.1 2019-11-23 21:41:27 +01:00
Gilles MOREL
aff562b61b Mise à jour du point d'entrée d'authentification 2019-11-23 21:38:36 +01:00
Gilles MOREL
3f4b3cd1aa Correction du style
Oublis de la validation précédente
2019-01-15 23:02:35 +01:00
Gilles MOREL
92d0f18f3a Correction du style
Le style a été un peu corrigé à l'aide de pycodestyle
2018-02-22 21:29:53 +01:00
2 changed files with 64 additions and 53 deletions

View File

@@ -1,13 +1,13 @@
# What's this?
# Qu'est-ce que c'est ?
This is a set of libraries to control your Home by SFR account.
They all work around the website.
Il s'agit d'une bibliothèque qui permet d'accéder au système Home by SFR.
Le code s'appuie sur les appels fait sur le [site](https://home.sfr.fr). De fait, sa conception a été faite par rétro-ingénérie et peut cesser de fonctionner sans préavis.
# What's Home by SFR?
# Qu'est-ce que Home by SFR ?
Home by SFR is a security and automation service provided by the French Internet provider SFR.
The library was only tested for the French version because I don't know if it exists elsewhere
Home by SFR est un service de sécurité et de domotique fourni par SFR.
Cette bibliothèque ne peut utiliser que le service fourni par SFR en France.
# Licence
These libraries are under GNU GPL v3.
Voir la [licence](LICENSE) pour plus de détails.

View File

@@ -10,11 +10,18 @@ This is a wrap aroud website, this could stop working without prior notice
## Manage cameras
### Get video
from urllib import request
from http.cookiejar import CookieJar
from urllib.parse import urlencode
from xml.etree import ElementTree as ET
from urllib.error import HTTPError
from datetime import datetime
authors = (
'Gilles "Almtesh" Émilien MOREL',
)
)
name = 'homesfr for Python 3'
version = '1.0'
version = '1.2'
# Settable modes
MODE_OFF = 0
@@ -30,12 +37,6 @@ REMOTE_CONTROLER = 'REMOTE'
KEYPAD_CONTROLER = 'KEYPAD'
PRESENCE_CAMERA_DETECTOR = 'PIR_CAMERA'
from urllib import request
from http.cookiejar import CookieJar
from urllib.parse import urlencode
from xml.etree import ElementTree as ET
from urllib.error import HTTPError
from datetime import datetime
class Common ():
'''
@@ -50,7 +51,7 @@ class Common ():
# path to login test
self.auth_path = '/mysensors'
self.auth_ok = '/accueil' # if logged
self.auth_ok_url = 'https://home.sfr.fr/logged' # if logged
self.auth_post_url = 'https://boutique.home.sfr.fr/authentification'
self.auth_referer = 'https://boutique.home.sfr.fr/authentification?back=service'
self.auth_user_field = 'email'
@@ -88,14 +89,15 @@ class Common ():
self.camera_get_config_mac = 'mac'
self.camera_get_config_flip = 'FLIP'
self.camera_get_config_leds = 'LEDMODE' # set to 0 to turn the leds on
self.camera_get_config_detectionsensibility = 'DP' # from 1 to 4
self.camera_get_config_recording = 'REC24'
self.camera_get_config_petmode = 'pet_mode'
self.camera_get_config_recording = 'rec24'
self.camera_get_config_privacy = 'privacy'
self.camera_get_config_name = 'NAME'
self.camera_set_config_path = '/homescope/camsettings'
self.camera_set_config_mac = 'mac'
self.camera_set_config_flip = 'flip'
self.camera_set_config_leds = 'led_mode' # set to 0 to turn the leds on
self.camera_set_config_detectionsensibility = 'dp' # from 1 to 4
self.camera_set_config_petmode = 'pet_mode'
self.camera_set_config_recording = 'rec24'
self.camera_set_config_name = 'name'
@@ -142,7 +144,7 @@ class Common ():
r = Image.open (f)
return (r)
def get_xml_elements (self,url, label, id_label=None):
def get_xml_elements (self, url, label, id_label = None):
def build_tree (element):
r = {}
for i in element.getchildren ():
@@ -154,7 +156,7 @@ class Common ():
a = self.bytes2file (self.opener.open (url).read ())
a.seek (0)
b = ET.parse (a)
if id_label == None:
if id_label is None:
r = []
for i in b.findall (label):
r.append (build_tree (i))
@@ -165,6 +167,7 @@ class Common ():
r.update ({i.get (id_label): build_tree (i)})
return (r)
class HomeSFR (Common):
def __init__ (self, username = None, password = None, cookies = None, debug = False, autologin = True):
'''
@@ -181,22 +184,22 @@ class HomeSFR (Common):
print ('Authors:')
for i in authors:
print (' - ' + i)
if username != None:
if username is not None:
print ('init with username ' + username)
if cookies != None:
if cookies is not None:
print ('init with cookies')
print ('debug = ' + str (debug))
print ('autologin = ' + str (autologin))
if (username == None or password == None) and cookies == None:
if (username is None or password is None) and cookies is None:
raise TypeError ('You must define either username AND password or cookies')
self.username = username
self.password = password
if self.username != None and self.password != None:
if self.username is not None and self.password is not None:
self.autologin = autologin
else:
self.autologin = False
if cookies == None:
if cookies is None:
self.cookies = CookieJar ()
elif type (cookies) == CookieJar:
self.cookies = cookies
@@ -208,7 +211,7 @@ class HomeSFR (Common):
'''
Shows name, version, defined user and debug state
'''
if self.username != None:
if self.username is not None:
return (name + ' ' + version + '\nUser: ' + self.username + '\nDebug: ' + str (self.DEBUG))
else:
return (name + ' ' + version + '\nUser: Unknown (auth from cookie class)\nDebug: ' + str (self.DEBUG))
@@ -237,19 +240,19 @@ class HomeSFR (Common):
Returns True if the login was a success, False either
This method will always return False if no username and password are defined
'''
if self.username != None and self.password != None:
if self.username is not None and self.password is not None:
self.opener.open (self.auth_referer)
data = self.auth_extra_fields
data [self.auth_user_field] = self.username
data [self.auth_pass_field] = self.password
data = bytes (urlencode (data), 'UTF8')
if self.DEBUG:
print ('Cookies ' + str( len(self.cookies)))
print ('Cookies ' + str (len (self.cookies)))
print ('Sending data ' + str (data))
a = self.opener.open (self.auth_post_url, data = data)
if self.DEBUG:
print ('Auth redirected to ' + a.geturl ())
return (a.geturl () == self.base_url + self.auth_ok)
return (a.geturl () == self.auth_ok_url)
else:
return (False)
@@ -257,7 +260,7 @@ class HomeSFR (Common):
'''
Trigger the autologin
'''
if (self.autologin and self.test_login () == False):
while (self.autologin and not self.test_login ()):
self.login ()
def logout (self):
@@ -362,8 +365,6 @@ class HomeSFR (Common):
Get a Camera object from the sensor's id
'''
self.do_autologin ()
if (self.autologin and self.test_login () == False):
self.login ()
r = Camera (id, self.opener)
r.refresh ()
return (r)
@@ -376,6 +377,7 @@ class HomeSFR (Common):
a = self.base_url + self.logs_path
return (self.get_xml_elements (a, self.logs_labels))
class Sensor (Common):
'''
Class used to read easily the sensors
@@ -481,17 +483,7 @@ class Sensor (Common):
'''
return (self.sensor_dict [self.sensors_status_field] == self.sensors_status_value_ok)
class Camera (Sensor):
'''
Class used to manipulate easily cameras
'''
def __init__ (self, sensor_dict, opener):
'''
Initialize the class with the dict producted by HomeSFR.get_camera ()
'''
Sensor.__init__ (self, sensor_dict, opener)
def get_snapshot (self):
def get_camera_snapshot (self):
'''
Get a snapshot from the camera
Return a PIL.Image object
@@ -499,3 +491,22 @@ class Camera (Sensor):
r = self.base_url + self.camera_snapshot + '?' + self.camera_snapshot_mac + '=' + self.get_mac ()
a = self.bytes2image (self.opener.open (r).read ())
return (a)
def get_camera_petmode (self):
'''
Gets the pet mode value
Pet mode is a setting on movement sensibility, to avoid trigger on pet movements
'''
return (self.sensor_dict [self.camera_get_config_petmode] == '1')
def get_camera_recording (self):
'''
Gets if the camera records or not
'''
return (self.sensor_dict [self.camera_get_config_recording] == '1')
def get_camera_privacy (self):
'''
Gets if the camera records or not
'''
return (self.sensor_dict [self.camera_get_config_privacy] == '1')