diff --git a/python2/homesfr.py b/python2/homesfr.py index 6717927..9ebd0a0 100644 --- a/python2/homesfr.py +++ b/python2/homesfr.py @@ -34,6 +34,7 @@ REMOTE_CONTROLER = 'REMOTE' KEYPAD_CONTROLER = 'KEYPAD' PRESENCE_CAMERA_DETECTOR = 'PIR_CAMERA' +# This part of code must be the one to adapt to make work the underneath part from cookielib import CookieJar import urllib2 as request from urllib2 import HTTPError @@ -41,28 +42,119 @@ from urllib import urlencode from xml.etree import ElementTree as ET from datetime import datetime -def bytes2file (b): +# Python2 and 3 adaptations +# BEGIN +def str2bytes (s): ''' - Gives a file-like class from a Bytes + Bind to the bytes build-in function ''' - from io import BytesIO - r = BytesIO () - r.write (b) - r.seek (0) - return (r) + return (bytes (s)) +# END -def bytes2image (b): - ''' - Gives a Image object from bytes - Uses the bytes2file function - ''' - from PIL import Image - f = bytes2file (b) - r = Image () - r.open (f) - return (r) +# The next must stay a copy from the python3 library, starting from class Common -class HomeSFR (): +class Common (): + ''' + 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 = '/accueil' # 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_detectionsensibility = 'DP' # from 1 to 4 + self.camera_get_config_recording = 'REC24' + 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_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 + + def bytes2file (self, b): + ''' + Gives a file-like class from a Bytes + ''' + from io import BytesIO + r = BytesIO () + r.write (b) + r.seek (0) + return (r) + + def bytes2image (self, b): + ''' + Gives a Image object from bytes + Uses the bytes2file function + ''' + from PIL import Image + f = self.bytes2file (b) + r = Image.open (f) + return (r) + +class HomeSFR (Common): def __init__ (self, username = None, password = None, cookies = None, debug = False, autologin = True): ''' Sets the class with username and password couple, or cookies @@ -71,6 +163,7 @@ class HomeSFR (): 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) @@ -97,49 +190,7 @@ class HomeSFR (): else: self.cookies = cookies self.opener = request.build_opener (request.HTTPCookieProcessor (self.cookies)) - - # Specific configuration - self.base_url = 'https://home.sfr.fr' - - # path to login test - self.auth_path = '/mysensors' - self.auth_ok = '/accueil' # 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' - self.sensors_label = 'Sensor' - self.sensors_label_id = 'id' - - # 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 - # mac=00:0e:8f:c9:59:44&flip=0&led_mode=0&alert_pan=1&rec24=0&da=1&dp=4&name=Salon - self.cameras_list = '/homescope/mycams' - self.camera_snapshot = '/homescope/snapshot' - self.camera_video = '/homescope/flv' - self.camera_get_config_path = '/homescope/camsettings' - 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, - + def __str__ (self): ''' Shows name, version, defined user and debug state @@ -178,7 +229,7 @@ class HomeSFR (): data = self.auth_extra_fields data [self.auth_user_field] = self.username data [self.auth_pass_field] = self.password - data = bytes (urlencode (data)) + data = str2bytes (urlencode (data)) if self.DEBUG: print ('Cookies ' + str( len(self.cookies))) print ('Sending data ' + str (data)) @@ -243,7 +294,7 @@ class HomeSFR (): r = self.base_url + self.mode_get_path if self.DEBUG: print ('Getting ' + r) - a = bytes2file (self.opener.open (r).read ()) + a = self.bytes2file (self.opener.open (r).read ()) b = ET.parse (a).getroot () c = b.get (self.mode_get_label) if self.DEBUG: @@ -263,7 +314,7 @@ class HomeSFR (): if (self.autologin and self.test_login () == False): self.login () r = self.base_url + self.sensors_list - a = bytes2file (self.opener.open (r).read ()) + a = self.bytes2file (self.opener.open (r).read ()) b = ET.parse (a) r = [] for i in b.findall (self.sensors_label): @@ -275,29 +326,11 @@ class HomeSFR (): 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 ''' - def build_tree (element): - r = {} - if self.DEBUG: - print ('Diving in the element ' + element.tag) - for i in element.getchildren (): - if i.getchildren () == []: - r.update ({i.tag: i.text}) - else: - r.update ({i.tag: build_tree (i)}) - return (r) if (self.autologin and self.test_login () == False): self.login () - r = self.base_url + self.sensors_list - a = bytes2file (self.opener.open (r).read ()) - b = ET.parse (a) - r = None - for i in b.findall (self.sensors_label): - if self.DEBUG: - print ('Testing sensors ' + i.get (self.sensors_label_id)) - if (i.get (self.sensors_label_id) == id): - r = build_tree (i) - break - return (Sensor (r)) + r = Sensor (id, self.opener) + r.refresh () + return (r) def get_all_sensors (self): ''' @@ -307,32 +340,52 @@ class HomeSFR (): 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 + ''' + if (self.autologin and self.test_login () == False): + self.login () + r = Camera (id, self.opener) + r.refresh () + return (r) -class Sensor: +class Sensor (Common): ''' Class used to read easily the sensors ''' - def __init__ (self, sensor_dict): + def __init__ (self, id, opener): ''' Initialize the class with the dict producted by HomeSFR.get_sensors () ''' + Common.__init__ (self) - self.sensor_dict = sensor_dict - - # Field names - self.type_field = 'deviceType' - self.model_field = 'deviceModel' - self.version_field = 'deviceVersion' - self.name_field = 'name' - self.longname_field = 'long_name' - self.namegender_field = 'name_gender' # Only usefull for French for the moment - self.batterylevel_field = 'batteryLevel' - self.signal_field = 'signalLevel' - self.lasttrigger_field = 'lastTriggerTime' - self.lasttrigger_dateformat = '%Y-%m-%d %H:%M:%S' - self.status_field = 'status' - self.status_value_ok = 'OK' - # I don't have any other value for the moment + self.id = id + self.sensor_dict = None + self.opener = opener + + def refresh (self): + ''' + Gets or refresh the data for the sensor + ''' + def build_tree (element): + r = {} + for i in element.getchildren (): + if i.getchildren () == []: + r.update ({i.tag: i.text}) + else: + r.update ({i.tag: build_tree (i)}) + return (r) + r = self.base_url + self.sensors_list + a = self.bytes2file (self.opener.open (r).read ()) + a.seek (0) + b = ET.parse (a) + self.sensor_dict = None + for i in b.findall (self.sensors_label): + if (i.get (self.sensors_label_id) == self.id): + self.sensor_dict = build_tree (i) + break def get_raw (self): ''' @@ -340,72 +393,97 @@ class Sensor: ''' return (self.sensor_dict) + def get_mac (self): + ''' + Returns the sensor's model, if any, None either + ''' + return (self.sensor_dict [self.sensors_mac_field]) + def get_type (self): ''' Returns the sensor's type ''' - return (self.sensor_dict [self.type_field]) + return (self.sensor_dict [self.sensors_type_field]) def get_model (self): ''' Returns the sensor's model, if any, None either ''' - return (self.sensor_dict [self.model_field]) + return (self.sensor_dict [self.sensors_model_field]) def get_version (self): ''' Returns the sensor's version ''' - return (self.sensor_dict [self.version_field]) + return (self.sensor_dict [self.sensors_version_field]) def get_name (self): ''' Returns the sensor's name ''' - return (self.sensor_dict [self.name_field]) + return (self.sensor_dict [self.sensors_name_field]) def get_longname (self): ''' Returns the sensor's type name in system's language and the sensor's name ''' - return (self.sensor_dict [self.longname_field]) + return (self.sensor_dict [self.sensors_longname_field]) def get_namegender (self): ''' Return M for male and F for female. Only usefull for languages with gender on nouns ''' - return (self.sensor_dict [self.namegender_field]) + return (self.sensor_dict [self.sensors_namegender_field]) def get_batterylevel (self): ''' Returns the sensor's battery level, out of 10 It seems that batteryless sensors return 255 ''' - return (int (self.sensor_dict [self.batterylevel_field])) + return (int (self.sensor_dict [self.sensors_batterylevel_field])) def get_signal (self): ''' Returns the sensor's signal quality, out of 10 ''' - return (int (self.sensor_dict [self.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.lasttrigger_field] + 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.lasttrigger_dateformat) + b = datetime.strptime (a, self.sensors_lasttrigger_dateformat) except ValueError: return (0) - r = int (b.strftime ('%s')) + r = int (b.timestamp ()) return (r) def get_status (self): ''' Returns True is the sensor is OK, False either ''' - return (self.sensor_dict [self.status_field] == self.status_value_ok) \ No newline at end of file + 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): + ''' + Get a snapshot from the camera + Return a PIL.Image object + ''' + r = self.base_url + self.camera_snapshot + '?' + self.camera_snapshot_mac + '=' + self.get_mac () + a = self.bytes2image (self.opener.open (r).read ()) + return (a) \ No newline at end of file diff --git a/python3/homesfr.py b/python3/homesfr.py index f0153e8..dae9e99 100644 --- a/python3/homesfr.py +++ b/python3/homesfr.py @@ -7,6 +7,7 @@ This is a wrap aroud website, this could stop working without prior notice ''' # TODO: +## Put common ressources in the Common class ## Manage cameras ### Get image ### Get video @@ -39,28 +40,117 @@ from xml.etree import ElementTree as ET from urllib.error import HTTPError from datetime import datetime -def bytes2file (b): +# Python2 and 3 adaptations +# BEGIN +def str2bytes (s): ''' - Gives a file-like class from a Bytes + Bind to the bytes build-in function ''' - from io import BytesIO - r = BytesIO () - r.write (b) - r.seek (0) - return (r) + return (bytes (s, 'UTF8')) +# END -def bytes2image (b): +class Common (): ''' - Gives a Image object from bytes - Uses the bytes2file function + Common ressources to the library's classes ''' - from PIL import Image - f = bytes2file (b) - r = Image () - r.open (f) - return (r) + + def __init__ (self): + + # Specific configuration + + self.base_url = 'https://home.sfr.fr' + + # path to login test + self.auth_path = '/mysensors' + self.auth_ok = '/accueil' # 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_detectionsensibility = 'DP' # from 1 to 4 + self.camera_get_config_recording = 'REC24' + 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_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 -class HomeSFR (): + def bytes2file (self, b): + ''' + Gives a file-like class from a Bytes + ''' + from io import BytesIO + r = BytesIO () + r.write (b) + r.seek (0) + return (r) + + def bytes2image (self, b): + ''' + Gives a Image object from bytes + Uses the bytes2file function + ''' + from PIL import Image + f = self.bytes2file (b) + r = Image.open (f) + return (r) + +class HomeSFR (Common): def __init__ (self, username = None, password = None, cookies = None, debug = False, autologin = True): ''' Sets the class with username and password couple, or cookies @@ -69,6 +159,7 @@ class HomeSFR (): 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) @@ -95,48 +186,6 @@ class HomeSFR (): else: self.cookies = cookies self.opener = request.build_opener (request.HTTPCookieProcessor (self.cookies)) - - # Specific configuration - self.base_url = 'https://home.sfr.fr' - - # path to login test - self.auth_path = '/mysensors' - self.auth_ok = '/accueil' # 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' - self.sensors_label = 'Sensor' - self.sensors_label_id = 'id' - - # 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 - # mac=00:0e:8f:c9:59:44&flip=0&led_mode=0&alert_pan=1&rec24=0&da=1&dp=4&name=Salon - self.cameras_list = '/homescope/mycams' - self.camera_snapshot = '/homescope/snapshot' - self.camera_video = '/homescope/flv' - self.camera_get_config_path = '/homescope/camsettings' - 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, def __str__ (self): ''' @@ -176,7 +225,7 @@ class HomeSFR (): data = self.auth_extra_fields data [self.auth_user_field] = self.username data [self.auth_pass_field] = self.password - data = bytes (urlencode (data), 'UTF8') + data = str2bytes (urlencode (data)) if self.DEBUG: print ('Cookies ' + str( len(self.cookies))) print ('Sending data ' + str (data)) @@ -241,7 +290,7 @@ class HomeSFR (): r = self.base_url + self.mode_get_path if self.DEBUG: print ('Getting ' + r) - a = bytes2file (self.opener.open (r).readall ()) + a = self.bytes2file (self.opener.open (r).read ()) b = ET.parse (a).getroot () c = b.get (self.mode_get_label) if self.DEBUG: @@ -261,7 +310,7 @@ class HomeSFR (): if (self.autologin and self.test_login () == False): self.login () r = self.base_url + self.sensors_list - a = bytes2file (self.opener.open (r).readall ()) + a = self.bytes2file (self.opener.open (r).read ()) b = ET.parse (a) r = [] for i in b.findall (self.sensors_label): @@ -273,29 +322,11 @@ class HomeSFR (): 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 ''' - def build_tree (element): - r = {} - if self.DEBUG: - print ('Diving in the element ' + element.tag) - for i in element.getchildren (): - if i.getchildren () == []: - r.update ({i.tag: i.text}) - else: - r.update ({i.tag: build_tree (i)}) - return (r) if (self.autologin and self.test_login () == False): self.login () - r = self.base_url + self.sensors_list - a = bytes2file (self.opener.open (r).readall ()) - b = ET.parse (a) - r = None - for i in b.findall (self.sensors_label): - if self.DEBUG: - print ('Testing sensors ' + i.get (self.sensors_label_id)) - if (i.get (self.sensors_label_id) == id): - r = build_tree (i) - break - return (Sensor (r)) + r = Sensor (id, self.opener) + r.refresh () + return (r) def get_all_sensors (self): ''' @@ -305,32 +336,52 @@ class HomeSFR (): 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 + ''' + if (self.autologin and self.test_login () == False): + self.login () + r = Camera (id, self.opener) + r.refresh () + return (r) -class Sensor: +class Sensor (Common): ''' Class used to read easily the sensors ''' - def __init__ (self, sensor_dict): + def __init__ (self, id, opener): ''' Initialize the class with the dict producted by HomeSFR.get_sensors () ''' + Common.__init__ (self) - self.sensor_dict = sensor_dict - - # Field names - self.type_field = 'deviceType' - self.model_field = 'deviceModel' - self.version_field = 'deviceVersion' - self.name_field = 'name' - self.longname_field = 'long_name' - self.namegender_field = 'name_gender' # Only usefull for French for the moment - self.batterylevel_field = 'batteryLevel' - self.signal_field = 'signalLevel' - self.lasttrigger_field = 'lastTriggerTime' - self.lasttrigger_dateformat = '%Y-%m-%d %H:%M:%S' - self.status_field = 'status' - self.status_value_ok = 'OK' - # I don't have any other value for the moment + self.id = id + self.sensor_dict = None + self.opener = opener + + def refresh (self): + ''' + Gets or refresh the data for the sensor + ''' + def build_tree (element): + r = {} + for i in element.getchildren (): + if i.getchildren () == []: + r.update ({i.tag: i.text}) + else: + r.update ({i.tag: build_tree (i)}) + return (r) + r = self.base_url + self.sensors_list + a = self.bytes2file (self.opener.open (r).read ()) + a.seek (0) + b = ET.parse (a) + self.sensor_dict = None + for i in b.findall (self.sensors_label): + if (i.get (self.sensors_label_id) == self.id): + self.sensor_dict = build_tree (i) + break def get_raw (self): ''' @@ -338,65 +389,71 @@ class Sensor: ''' return (self.sensor_dict) + def get_mac (self): + ''' + Returns the sensor's model, if any, None either + ''' + return (self.sensor_dict [self.sensors_mac_field]) + def get_type (self): ''' Returns the sensor's type ''' - return (self.sensor_dict [self.type_field]) + return (self.sensor_dict [self.sensors_type_field]) def get_model (self): ''' Returns the sensor's model, if any, None either ''' - return (self.sensor_dict [self.model_field]) + return (self.sensor_dict [self.sensors_model_field]) def get_version (self): ''' Returns the sensor's version ''' - return (self.sensor_dict [self.version_field]) + return (self.sensor_dict [self.sensors_version_field]) def get_name (self): ''' Returns the sensor's name ''' - return (self.sensor_dict [self.name_field]) + return (self.sensor_dict [self.sensors_name_field]) def get_longname (self): ''' Returns the sensor's type name in system's language and the sensor's name ''' - return (self.sensor_dict [self.longname_field]) + return (self.sensor_dict [self.sensors_longname_field]) def get_namegender (self): ''' Return M for male and F for female. Only usefull for languages with gender on nouns ''' - return (self.sensor_dict [self.namegender_field]) + return (self.sensor_dict [self.sensors_namegender_field]) def get_batterylevel (self): ''' Returns the sensor's battery level, out of 10 It seems that batteryless sensors return 255 ''' - return (int (self.sensor_dict [self.batterylevel_field])) + return (int (self.sensor_dict [self.sensors_batterylevel_field])) def get_signal (self): ''' Returns the sensor's signal quality, out of 10 ''' - return (int (self.sensor_dict [self.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.lasttrigger_field] + 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.lasttrigger_dateformat) + b = datetime.strptime (a, self.sensors_lasttrigger_dateformat) except ValueError: return (0) r = int (b.timestamp ()) @@ -406,4 +463,23 @@ class Sensor: ''' Returns True is the sensor is OK, False either ''' - return (self.sensor_dict [self.status_field] == self.status_value_ok) \ No newline at end of file + 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): + ''' + Get a snapshot from the camera + Return a PIL.Image object + ''' + r = self.base_url + self.camera_snapshot + '?' + self.camera_snapshot_mac + '=' + self.get_mac () + a = self.bytes2image (self.opener.open (r).read ()) + return (a) \ No newline at end of file