Compare commits

..

No commits in common. "b4540504f88cc6b6f34725b3a76300279eae7aa0" and "72e1c94a802432a425067d85f84cf731c103d1ee" have entirely different histories.

1 changed files with 302 additions and 272 deletions

View File

@ -1,120 +1,132 @@
# WARNING: ce code s'appuie sur une API découverte par rétro-ingénérie.
# Il peut cesser de fonctionner sans préavis.
'''
Home by SFR wrapping class
Plain use of your Home by SFR device from a Python 3 library
Warning:
This is a wrap aroud website, this could stop working without prior notice
'''
# TODO:
##
## 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 pour Python 3'
version = '1.3'
name = 'homesfr for Python 3'
version = '1.2'
# Modes utilisables
# Settable modes
MODE_OFF = 0
MODE_CUSTOM = 1
MODE_ON = 2
# Types de capteurs
PRESENCE_DETECTOR = 'PIR_DETECTOR' # https://boutique.home.sfr.fr/detecteur-de-mouvement
MAGNETIC_OPENNING_DETECTOR = 'MAGNETIC' # https://boutique.home.sfr.fr/detecteur-d-ouverture-de-porte-ou-fenetre
SMOKE_DETECTOR = 'SMOKE' # https://boutique.home.sfr.fr/detecteur-de-fumee
SIREN = 'SIREN' # https://boutique.home.sfr.fr/sirene-interieure (et peut-être https://boutique.home.sfr.fr/sirene-exterieure)
REMOTE_CONTROLER = 'REMOTE' # https://boutique.home.sfr.fr/telecommande
KEYPAD_CONTROLER = 'KEYPAD' # https://boutique.home.sfr.fr/clavier-de-commande
PRESENCE_CAMERA_DETECTOR = 'PIR_CAMERA' # https://boutique.home.sfr.fr/camera
base_url = 'https://home.sfr.fr'
# Authentification
auth_path = '/mysensors'
auth_ok_url = 'https://home.sfr.fr/logged'
auth_post_url = 'https://boutique.home.sfr.fr/authentification'
auth_referer = 'https://boutique.home.sfr.fr/authentification?back=service'
auth_user_field = 'email'
auth_pass_field = 'passwd'
auth_extra_fields = {'back': 'service', 'token_sso': '', 'error_sso': '', 'SubmitLogin': 'OK'}
auth_logout_path = '/deconnexion'
# Chemin pour la liste des capteurs
sensors_list = '/mysensors'
# Chemin pour les alertes
alerts_path = '/listalert'
# Détection
mode_get_path = '/mysensors'
mode_get_label = 'alarm_mode'
mode_set_path = '/alarmmode'
mode_set_field = 'action' # Name for GET field
mode_off = 'OFF' # Value for off
mode_custom = 'CUSTOM' # Value for custom
mode_on = 'ON' # Value for on
# Cémera
cameras_list = '/homescope/mycams'
camera_snapshot = '/homescope/snapshot?size=4'
camera_snapshot_mac = 'mac'
camera_video = '/homescope/flv'
camera_video_mac = 'mac'
camera_recordings_list = '/listenr'
camera_recordings_delete = '/delenr'
camera_recordings_start = '/homescope/record'
camera_recordings_stop = '/homescope/stoprecord'
camera_recordings_mac = 'mac'
camera_get_config_path = '/homescope/camsettings'
camera_get_config_mac = 'mac'
camera_get_config_flip = 'FLIP'
camera_get_config_leds = 'LEDMODE'
camera_get_config_petmode = 'pet_mode'
camera_get_config_recording = 'rec24'
camera_get_config_privacy = 'privacy'
camera_get_config_name = 'NAME'
camera_set_config_path = '/homescope/camsettings'
camera_set_config_mac = 'mac'
camera_set_config_flip = 'flip'
camera_set_config_leds = 'led_mode'
camera_set_config_petmode = 'pet_mode'
camera_set_config_recording = 'rec24'
# Le paramètre privacy se gère avec le bouton derrière la caméra.
camera_set_config_name = 'name'
# Capteurs
sensors_list = '/mysensors'
sensors_label = 'Sensor'
sensors_label_id = 'id'
sensors_mac_field = 'deviceMac'
sensors_type_field = 'deviceType'
sensors_model_field = 'deviceModel'
sensors_version_field = 'deviceVersion'
sensors_name_field = 'name'
sensors_longname_field = 'long_name'
sensors_namegender_field = 'name_gender'
sensors_batterylevel_field = 'batteryLevel'
sensors_signal_field = 'signalLevel'
sensors_status_field = 'status'
sensors_status_value_ok = 'OK'
# Capteurs de température et humidité
sensors_temphum_root_field = 'sensorValues'
sensors_temp_name = 'name'
sensors_temp_text = 'Temperature'
sensors_hum_name = 'name'
sensors_hum_text = 'Humidity'
# Fil d'événements
logs_path = '/getlog?page=1&nbparpage=10000' # je pense qu'on récupère tous les événements avec cette valeur
logs_labels = 'LOG'
# Sensors names
PRESENCE_DETECTOR = 'PIR_DETECTOR'
MAGNETIC_OPENNING_DETECTOR = 'MAGNETIC'
SMOKE_DETECTOR = 'SMOKE'
SIREN = 'SIREN'
REMOTE_CONTROLER = 'REMOTE'
KEYPAD_CONTROLER = 'KEYPAD'
PRESENCE_CAMERA_DETECTOR = 'PIR_CAMERA'
def bytes2file (b):
class Common ():
'''
Retourne une classe semblable à un fichier contant b
Common ressources to the library's classes
'''
def __init__ (self):
# Specific configuration
self.base_url = 'https://home.sfr.fr'
# path to login test
self.auth_path = '/mysensors'
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'
self.auth_pass_field = 'passwd'
self.auth_extra_fields = {'back': 'service', 'token_sso': '', 'error_sso': '', 'SubmitLogin': 'OK'}
self.auth_logout_path = '/deconnexion'
# Path to sensors and mode
self.sensors_list = '/mysensors'
# Path to list of alerts
self.alerts_path = '/listalert'
# Path to get and set modes
self.mode_get_path = '/mysensors'
self.mode_get_label = 'alarm_mode'
self.mode_set_path = '/alarmmode'
self.mode_set_field = 'action' # Name for GET field
self.mode_off = 'OFF' # Value for off
self.mode_custom = 'CUSTOM' # Value for custom
self.mode_on = 'ON' # Value for on
# Cameras
self.cameras_list = '/homescope/mycams'
self.camera_snapshot = '/homescope/snapshot'
self.camera_snapshot_mac = 'mac'
self.camera_video = '/homescope/flv'
self.camera_vide_mac = 'mac'
self.camera_recordings_list = '/listenr'
self.camera_recordings_delete = '/delenr'
self.camera_recordings_start = '/homescope/record'
self.camera_recordings_stop = '/homescope/stoprecord'
self.camera_recordings_mac = 'mac'
self.camera_get_config_path = '/homescope/camsettings'
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_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_petmode = 'pet_mode'
self.camera_set_config_recording = 'rec24'
self.camera_set_config_name = 'name'
# Sensors
self.sensors_list = '/mysensors'
self.sensors_label = 'Sensor'
self.sensors_label_id = 'id'
self.sensors_mac_field = 'deviceMac'
self.sensors_type_field = 'deviceType'
self.sensors_model_field = 'deviceModel'
self.sensors_version_field = 'deviceVersion'
self.sensors_name_field = 'name'
self.sensors_longname_field = 'long_name'
self.sensors_namegender_field = 'name_gender' # Only usefull for French for the moment
self.sensors_batterylevel_field = 'batteryLevel'
self.sensors_signal_field = 'signalLevel'
self.sensors_lasttrigger_field = 'lastTriggerTime'
self.sensors_lasttrigger_dateformat = '%Y-%m-%d %H:%M:%S'
self.sensors_status_field = 'status'
self.sensors_status_value_ok = 'OK'
# I don't have any other value for the moment
# Logs
self.logs_path = '/getlog?page=1&nbparpage=10000' # should retrieve all available logs
self.logs_labels = 'LOG'
def bytes2file (self, b):
'''
Gives a file-like class from a Bytes
'''
from io import BytesIO
r = BytesIO ()
@ -122,57 +134,65 @@ def bytes2file (b):
r.seek (0)
return (r)
def bytes2image (b):
def bytes2image (self, b):
'''
Retourne une Image PIL contenant l'image donnée en b
Gives a Image object from bytes
Uses the bytes2file function
'''
from PIL import Image
f = bytes2file (b)
f = self.bytes2file (b)
r = Image.open (f)
return (r)
def get_xml_tree (fp):
'''
Retourne une variable itérable contenant les données d'un arbre XML
'''
def get_xml_elements (self, url, label, id_label = None):
def build_tree (element):
if tuple (element) == ():
return (element.tag, dict (element.items ()), element.text)
r = {}
for i in element.getchildren ():
if i.getchildren () == []:
r.update ({i.tag: i.text})
else:
sub = []
for i in element:
sub.append (build_tree (i))
return (element.tag, dict (element.items ()), sub)
from xml.etree import ElementTree as ET
fp.seek (0)
root = ET.parse (fp).getroot ()
return (build_tree (root))
r.update ({i.tag: build_tree (i)})
return (r)
a = self.bytes2file (self.opener.open (url).read ())
a.seek (0)
b = ET.parse (a)
if id_label is None:
r = []
for i in b.findall (label):
r.append (build_tree (i))
return (tuple (r))
else:
r = {}
for i in b.findall (label):
r.update ({i.get (id_label): build_tree (i)})
return (r)
class HomeSFR ():
class HomeSFR (Common):
def __init__ (self, username = None, password = None, cookies = None, debug = False, autologin = True):
'''
Instancie la classe avec un identifiant et un mot de passe, ou des cookies
On peut définir les identifiants et les cookies, la classe utilisera les cookies par défaut et les identifiants si on n'est pas connecté
debug fourni des informations supplémentaires sur la sortie standard, s'il est à False, cette classe n'envoie rien sur la sortie standard
Sets the class with username and password couple, or cookies
Both user/password and cookies can be set, the cookies will be used first
The debug parameter defines if the class will write debug messages to stdout, if False, the stdout will never be writen by the class
The autologin parameter defines if the class will manage the login by itself, if False, the user must call login () to login and test_login () to check the login
The autologin paramater will always be False if no username and password are defined, and the login () method will always return False
'''
Common.__init__ (self)
self.DEBUG = debug
if self.DEBUG:
print (name + ' ' + version)
print ('Auteurs:')
print ('Authors:')
for i in authors:
print (' - ' + i)
if username is not None:
print ('initalisé avec l\'identifiant ' + username)
print ('init with username ' + username)
if cookies is not None:
print ('initialisé avec des cookies')
print ('init with cookies')
print ('debug = ' + str (debug))
print ('autologin = ' + str (autologin))
if (username is None or password is None) and cookies is None:
raise TypeError ('Vous devez définir des identifiant ou des cookies !')
raise TypeError ('You must define either username AND password or cookies')
self.username = username
self.password = password
if self.username is not None and self.password is not None:
@ -184,299 +204,309 @@ class HomeSFR ():
elif type (cookies) == CookieJar:
self.cookies = cookies
else:
raise TypeError ('Les cookies doivent être de type CookieJar !')
raise TypeError ('Cookies must be CookieJar type.')
self.opener = request.build_opener (request.HTTPCookieProcessor (self.cookies))
def __str__ (self):
'''
Returne des informations sur l'état de l'instance
Shows name, version, defined user and debug state
'''
if self.username is not None:
return (name + ' ' + version + '\nUtilisateur : ' + self.username + '\nDebug : ' + str (self.DEBUG))
return (name + ' ' + version + '\nUser: ' + self.username + '\nDebug: ' + str (self.DEBUG))
else:
return (name + ' ' + version + '\nUtilisateur : Inconnu, authentifié avec des cookies.\nDebug : ' + str (self.DEBUG))
return (name + ' ' + version + '\nUser: Unknown (auth from cookie class)\nDebug: ' + str (self.DEBUG))
def test_login (self):
'''
Retourne l'état de l'authentification
Tests if the client is logged
Return True if it's logged, returns False either
'''
try:
if self.DEBUG:
print ('Test de l\'authentification')
self.opener.open (base_url + auth_path)
print ('Testing login')
self.opener.open (self.base_url + self.auth_path)
except HTTPError:
if self.DEBUG:
print ('Non connecté')
print ('Not connected')
return (False)
if self.DEBUG:
print ('Connecté')
print ('Connected')
return (True)
def login (self):
'''
S'authentifier auprès du service
Retourne True si c'est réussi, False sinon
Si seuls les cookies sont définis, la méthode retournera False, même si nous sommes authentifiés, pour savoir si on est authentifiés, utiliser test_login ()
Logs in the HomeBySFR service
Call this function first or exception will be raised
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 is not None and self.password is not None:
self.opener.open (auth_referer)
data = auth_extra_fields
data [auth_user_field] = self.username
data [auth_pass_field] = self.password
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 ('Envoi de ' + str (data))
a = self.opener.open (auth_post_url, data = data)
print ('Sending data ' + str (data))
a = self.opener.open (self.auth_post_url, data = data)
if self.DEBUG:
print ('Authentification redirigée vers ' + a.geturl ())
return (a.geturl () == auth_ok_url)
print ('Auth redirected to ' + a.geturl ())
return (a.geturl () == self.auth_ok_url)
else:
return (False)
def get_or_autologin (self, url, data = None):
def do_autologin (self):
'''
Fais une requête, si une erreur 403 est retourné, tente une authentification automatiquement (si réglé dans le paramètre autologin), sinon lève une exception
Trigger the autologin
'''
try:
return (self.opener.open (url, data = data))
except HTTPError as e:
if '403' in str (e) and self.autologin:
while (self.autologin and not self.test_login ()):
self.login ()
return (self.opener.open (url, data = data))
else:
raise e
def logout (self):
'''
Se déconnecter
L'instance devrait être supprimée après l'appel de cette fonction
Logs out from HomeBySFR service
The object should be destroyed just after calling this method
'''
if self.DEBUG:
print ('Demande de déconnexion')
self.opener.open (base_url + auth_logout_path)
print ('Sending disconnect')
self.opener.open (self.base_url + self.auth_logout_path)
if self.DEBUG:
print ('Destruction des cookies')
print ('Destroying cookies')
del self.cookies
self.cookies = None
return (None)
def get_cookies (self):
'''
Récupérer les cookies
Il est recommandé de supprimer l'instance après cette fonction
Returns the CookieJar as it is now, for further use
It's strongly recommended to use this method only before a object delete
'''
return (self.cookies)
def set_mode (self, mode):
'''
Modifie le mode de détection
Sets the detection mode
For the current version, use the MODE_OFF, MODE_ON and MODE_CUSTOM constants and always returns True, but raises an exception if a problem happens
'''
self.do_autologin ()
if mode == MODE_OFF:
m = mode_off
m = self.mode_off
elif mode == MODE_CUSTOM:
m = mode_custom
m = self.mode_custom
elif mode == MODE_ON:
m = mode_on
m = self.mode_on
else:
if self.DEBUG:
print ('Vous devriez utiliser les constantes MODE_OFF, MODE_ON et MODE_CUSTOM.')
print ('You should use the MODE_OFF, MODE_ON and MODE_CUSTOM constants to set this.')
raise ValueError
r = base_url + mode_set_path + '?' + mode_set_field + '=' + m
r = self.base_url + self.mode_set_path + '?' + self.mode_set_field + '=' + m
if self.DEBUG:
print ('Demande ' + r)
self.get_or_autologin (r)
print ('Will get ' + r)
self.opener.open (r)
return (True)
def get_mode (self):
'''
Retourne le mode de détection
Gets the detection mode
Returns one of MODE_OFF, MODE_ON and MODE_CUSTOM constants, or None if something went wrong
'''
r = base_url + mode_get_path
self.do_autologin ()
r = self.base_url + self.mode_get_path
if self.DEBUG:
print ('Demande ' + r)
a = bytes2file (self.get_or_autologin (r).read ())
b = get_xml_tree (a) [1]
c = b [mode_get_label]
print ('Getting ' + r)
a = self.bytes2file (self.opener.open (r).read ())
b = ET.parse (a).getroot ()
c = b.get (self.mode_get_label)
if self.DEBUG:
print ('Mode de détection ' + c)
if (c == mode_off):
print ('Got mode ' + c)
if (c == self.mode_off):
return (MODE_OFF)
if (c == mode_custom):
if (c == self.mode_custom):
return (MODE_CUSTOM)
if (c == mode_on):
if (c == self.mode_on):
return (MODE_ON)
return (None)
def list_sensors (self):
'''
Retourne une liste des IDs des capteurs
Returns a list of sensors' ids.
'''
r = base_url + sensors_list
a = bytes2file (self.get_or_autologin (r).read ())
b = get_xml_tree (a)
self.do_autologin ()
r = self.base_url + self.sensors_list
a = self.bytes2file (self.opener.open (r).read ())
b = ET.parse (a)
r = []
for i in b [2]:
try:
r.append (i [1] [sensors_label_id])
except KeyError:
pass
for i in b.findall (self.sensors_label):
r.append (i.get (self.sensors_label_id))
return (list (r))
def get_sensor (self, id):
'''
Retourne un objet Sensor à partir de l'ID
Returns a Sensor object for the sensor id or None if sensor is not found
The available ids can be got from the list_sensors method
'''
r = Sensor (id, self.get_or_autologin)
self.do_autologin ()
r = Sensor (id, self.opener)
r.refresh ()
return (r)
def get_all_sensors (self):
'''
Retourne un tuple d'objet Sensor contenant tous les capteurs
Returns a tuple of sensors as described in the get_sensor method
'''
r = []
for i in self.list_sensors ():
r.append (self.get_sensor (i))
return (tuple (r))
def get_camera (self, id):
'''
Get a Camera object from the sensor's id
'''
self.do_autologin ()
r = Camera (id, self.opener)
r.refresh ()
return (r)
class Sensor ():
def __init__ (self, id, get_or_autologin):
def get_logs (self):
'''
Return the whole logs in a form of tuple of dicts, as returned by the site
'''
self.do_autologin ()
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
'''
def __init__ (self, id, opener):
'''
Initialize the class with the dict producted by HomeSFR.get_sensors ()
'''
Common.__init__ (self)
self.id = id
self.sensor_dict = None
self.get_or_autologin = get_or_autologin
self.opener = opener
def refresh (self):
'''
Mets à jour les données du capteur
Gets or refresh the data for the sensor
'''
r = base_url + sensors_list
r = self.base_url + self.sensors_list
self.sensor_dict = None
for i in get_xml_tree (bytes2file (self.get_or_autologin (r).read ())) [2]:
if i [0] == sensors_label and i [1] [sensors_label_id] == self.id:
self.sensor_dict = i [2]
break
self.sensor_dict = self.get_xml_elements (r, self.sensors_label, self.sensors_label_id) [self.id]
def get_raw (self):
'''
Retourne les données brutes du capteur
Returns the raw dict, as presented in the original XML file
'''
return (self.sensor_dict)
def get_value (self, lst, key):
for i in lst:
if i [0] == key:
return (i [2])
raise KeyError ('no value ' + key)
def get_mac (self):
'''
Retourne l'adresse matérielle du capteur, s'il en a une
Returns the sensor's model, if any, None either
'''
return (self.get_value (self.sensor_dict, sensors_mac_field))
return (self.sensor_dict [self.sensors_mac_field])
def get_type (self):
'''
Retourne le type du capteur
Les types sont ceux définis dans les constantes
Returns the sensor's type
'''
return (self.get_value (self.sensor_dict, sensors_type_field))
return (self.sensor_dict [self.sensors_type_field])
def get_model (self):
'''
Retourne le modèle du capteur
Returns the sensor's model, if any, None either
'''
return (self.get_value (self.sensor_dict, sensors_model_field))
return (self.sensor_dict [self.sensors_model_field])
def get_version (self):
'''
Retourne la version du capteur
Returns the sensor's version
'''
return (self.get_value (self.sensor_dict, sensors_version_field))
return (self.sensor_dict [self.sensors_version_field])
def get_name (self):
'''
Retourne le nom du capteur
Returns the sensor's name
'''
return (self.get_value (self.sensor_dict, sensors_name_field))
return (self.sensor_dict [self.sensors_name_field])
def get_longname (self):
'''
Retourne un nom long du capteur composé de son type en français et de son nom
Returns the sensor's type name in system's language and the sensor's name
'''
return (self.get_value (self.sensor_dict, sensors_longname_field))
return (self.sensor_dict [self.sensors_longname_field])
def get_namegender (self):
'''
Retourne le genre du nom du type de capteur en français
M pour masculin et F pour féminin
Return M for male and F for female.
Only usefull for languages with gender on nouns
'''
return (self.get_value (self.sensor_dict, sensors_namegender_field))
return (self.sensor_dict [self.sensors_namegender_field])
def get_batterylevel (self):
'''
Retourne le niveau de batterie sur 10
Toute autre valeur doit être considérée comme venant d'un capteur n'ayant pas de batterie
Returns the sensor's battery level, out of 10
It seems that batteryless sensors return 255
'''
return (int (self.get_value (self.sensor_dict, sensors_batterylevel_field)))
return (int (self.sensor_dict [self.sensors_batterylevel_field]))
def get_signal (self):
'''
Retourne le niveau de signal sur 10
Tout autre valeur est pour un capteur connecté par câble
Returns the sensor's signal quality, out of 10
'''
return (int (self.get_value (self.sensor_dict, sensors_signal_field)))
return (int (self.sensor_dict [self.sensors_signal_field]))
def get_lasttrigger (self):
'''
Return the timestamp of the sensor's last triger
The sensors always trigger, even when the alarm's mode is off
'''
a = self.sensor_dict [self.sensors_lasttrigger_field]
# Try because camera return the date '0000-00-00 00:00:00' that is ununderstandable
try:
b = datetime.strptime (a, self.sensors_lasttrigger_dateformat)
except ValueError:
return (0)
r = int (b.timestamp ())
return (r)
def get_status (self):
'''
Retourne True si le capteur est considéré comme opérationnel par le système
Returns True is the sensor is OK, False either
'''
return (self.get_value (self.sensor_dict, sensors_status_field) == sensors_status_value_ok)
return (self.sensor_dict [self.sensors_status_field] == self.sensors_status_value_ok)
def get_camera_snapshot (self):
'''
Retourne une capture de la caméra dans un objet PIL.Image
Get a snapshot from the camera
Return a PIL.Image object
'''
r = base_url + camera_snapshot + '&' + camera_snapshot_mac + '=' + self.get_mac ()
a = bytes2image (self.get_or_autologin (r).read ())
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):
'''
Retourne l'état du mode animaux domestiques
Ce mode réduit la sensibilité du capteur pour éviter des déclanchements d'alarme dus aux animaux
Gets the pet mode value
Pet mode is a setting on movement sensibility, to avoid trigger on pet movements
'''
return (self.sensor_dict [camera_get_config_petmode] == '1')
return (self.sensor_dict [self.camera_get_config_petmode] == '1')
def get_camera_recording (self):
'''
Retourne l'état de l'enregistrement vidéo 24/24
Gets if the camera records or not
'''
return (self.sensor_dict [camera_get_config_recording] == '1')
return (self.sensor_dict [self.camera_get_config_recording] == '1')
def get_camera_privacy (self):
'''
Si cette méthode retourne True, la caméra est paramétrée pour ne pas capture d'image
Gets if the camera records or not
'''
return (self.sensor_dict [camera_get_config_privacy] == '1')
def get_temperature (self):
'''
Retourne la température donnée par le capteur
'''
a = self.get_value (self.sensor_dict, sensors_temphum_root_field)
for i in a:
if i [1] [sensors_temp_name] == sensors_temp_text:
return (float (i [2].replace ('°C', '')))
def get_humidity (self):
'''
Retourne l'humidité donnée par le capteur
'''
a = self.get_value (self.sensor_dict, sensors_temphum_root_field)
for i in a:
if i [1] [sensors_hum_name] == sensors_hum_text:
return (int (i [2].replace ('%', '')))
return (self.sensor_dict [self.camera_get_config_privacy] == '1')