]> www.vanbest.org Git - motioneye-debian/commitdiff
initial work on timezone support
authorCalin Crisan <ccrisan@gmail.com>
Thu, 10 Jul 2014 13:47:00 +0000 (16:47 +0300)
committerCalin Crisan <ccrisan@gmail.com>
Thu, 10 Jul 2014 13:47:00 +0000 (16:47 +0300)
motioneye.py
settings_default.py
src/config.py
src/handlers.py
src/tzctl.py [new file with mode: 0644]
templates/main.html

index 0b1327000a61ed1b5bee5d2114c9648db48531d5..15e50ee694fea0b8bcd53a20dd97a2078a6cf776 100755 (executable)
@@ -47,10 +47,6 @@ def _configure_settings():
     set_default_setting('LOG_LEVEL', logging.INFO)
     set_default_setting('LISTEN', '0.0.0.0')
     set_default_setting('PORT', 8765)
-    set_default_setting('WPA_SUPPLICANT_CONF', None)
-    set_default_setting('SMB_SHARES', False)
-    set_default_setting('SMB_MOUNT_ROOT', '/media')
-    set_default_setting('ENABLE_REBOOT', False)
     set_default_setting('MOUNT_CHECK_INTERVAL', 300)
     set_default_setting('MOTION_CHECK_INTERVAL', 10)
     set_default_setting('CLEANUP_INTERVAL', 43200)
@@ -59,6 +55,11 @@ def _configure_settings():
     set_default_setting('MJPG_CLIENT_TIMEOUT', 10)
     set_default_setting('PICTURE_CACHE_SIZE', 8)
     set_default_setting('PICTURE_CACHE_LIFETIME', 60)
+    set_default_setting('SMB_SHARES', False)
+    set_default_setting('SMB_MOUNT_ROOT', '/media')
+    set_default_setting('WPA_SUPPLICANT_CONF', None)
+    set_default_setting('LOCAL_TIME_FILE', None)
+    set_default_setting('ENABLE_REBOOT', False)
     
     length = len(sys.argv) - 1
     for i in xrange(length):
index 283447c0e097639f25173fb2458332550fbd354d..2faf74cd21d10f9eedd82605cfff70d63d6571bc 100644 (file)
@@ -29,18 +29,6 @@ LISTEN = '0.0.0.0'
 # change the port according to your requirements/restrictions
 PORT = 8765
 
-# path to a wpa_supplicant.conf file if wifi settings UI is desired (requires root) 
-WPA_SUPPLICANT_CONF = None
-
-# enable SMB shares (requires root) 
-SMB_SHARES = False
-
-# the directory where the SMB mounts will be created
-SMB_MOUNT_ROOT = '/media'
-
-# enables rebooting after changing system settings (such as wifi settings or system updates)
-ENABLE_REBOOT = False
-
 # interval in seconds at which motionEye checks the SMB mounts
 MOUNT_CHECK_INTERVAL = 300
 
@@ -64,3 +52,18 @@ PICTURE_CACHE_SIZE = 8
 
 # the number of seconds that a cached picture is valid
 PICTURE_CACHE_LIFETIME = 60
+
+# enable SMB shares (requires root) 
+SMB_SHARES = False
+
+# the directory where the SMB mounts will be created
+SMB_MOUNT_ROOT = '/media'
+
+# path to a wpa_supplicant.conf file if wifi settings UI is desired
+WPA_SUPPLICANT_CONF = None
+
+# path to a localtime file if time zone settings UI is desired
+LOCAL_TIME_FILE = None
+
+# enables rebooting after changing system settings (such as wifi settings or system updates)
+ENABLE_REBOOT = False
index 85ddad24b33cdc98e0042345c6dd15eaa40a6128..5e042e7d8550a7e1c7e3d6f37a76a2d00dc022f8 100644 (file)
@@ -26,6 +26,7 @@ import diskctl
 import motionctl
 import settings
 import smbctl
+import tzctl
 import update
 import utils
 import v4l2ctl
@@ -89,6 +90,9 @@ def get_main(as_lines=False):
     if settings.WPA_SUPPLICANT_CONF:
         _get_wifi_settings(main_config)
         
+    if settings.LOCAL_TIME_FILE:
+        _get_localtime_settings(main_config)
+        
     _set_default_motion(main_config)
     
     _main_config_cache = main_config
@@ -105,6 +109,9 @@ def set_main(main_config):
     if settings.WPA_SUPPLICANT_CONF:
         _set_wifi_settings(main_config)
         
+    if settings.LOCAL_TIME_FILE:
+        _set_localtime_settings(main_config)
+        
     config_file_path = os.path.join(settings.CONF_PATH, _MAIN_CONFIG_FILE_NAME)
     
     # read the actual configuration from file
@@ -1102,6 +1109,7 @@ def _set_default_motion(data):
     data.setdefault('@admin_password', '')
     data.setdefault('@normal_username', 'user')
     data.setdefault('@normal_password', '')
+    data.setdefault('@timezone', 'UTC')
 
     data.setdefault('@wifi_enabled', False)
     data.setdefault('@wifi_name', '')
@@ -1334,3 +1342,14 @@ def _set_wifi_settings(data):
         conf_file.write(line)
 
     conf_file.close()
+
+
+def _get_localtime_settings(data):
+    time_zone = tzctl.get_time_zone()
+    data['@time_zone'] = time_zone
+
+
+def _set_localtime_settings(data):
+    time_zone = data.pop('@time_zone')
+    if time_zone:
+        tzctl.set_time_zone(time_zone)
index ff51fc29d884bf74c6aa0ad0b48d86b475ccfa70..dbfb230d5966be01a717b17f61775eb4194a4ac6 100644 (file)
@@ -20,6 +20,7 @@ import datetime
 import json
 import logging
 import os
+import pytz
 import socket
 
 from tornado.web import RequestHandler, HTTPError, asynchronous
@@ -145,8 +146,13 @@ class NotFoundHandler(BaseHandler):
 class MainHandler(BaseHandler):
     @BaseHandler.auth()
     def get(self):
+        timezones = []
+        if settings.LOCAL_TIME_FILE:
+            timezones = pytz.common_timezones
+
         self.render('main.html',
                 wpa_supplicant=settings.WPA_SUPPLICANT_CONF,
+                timezones=timezones,
                 hostname=socket.gethostname())
 
 
diff --git a/src/tzctl.py b/src/tzctl.py
new file mode 100644 (file)
index 0000000..04e97af
--- /dev/null
@@ -0,0 +1,110 @@
+
+# Copyright (c) 2013 Calin Crisan
+# This file is part of motionEye.
+#
+# motionEye is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+
+import hashlib
+import logging
+import os
+import settings
+import subprocess
+
+
+def _get_time_zone_symlink():
+    file = settings.LOCAL_TIME_FILE
+    
+    for i in xrange(8): # recursively follow the symlinks @UnusedVariable
+        try:
+            file = os.readlink(file)
+
+        except OSError:
+            break
+    
+    if file and file.startswith('/usr/share/zoneinfo/'):
+        file = file[21:]
+    
+    else:
+        file = None
+
+    time_zone = file or None
+    if time_zone:
+        logging.debug('found time zone by symlink method: %s' % time_zone)
+    
+    return time_zone
+
+
+def _get_time_zone_md5():
+    try:
+        output = subprocess.check_output('cd /usr/share/zoneinfo; find * -type f | xargs md5sum', shell=True)
+
+    except Exception as e:
+        logging.error('getting md5 of zoneinfo files failed: %s' % e)
+
+        return None
+    
+    lines = [l for l in output.split('\n') if l]
+    lines = [l.split(None, 1) for l in lines]
+    time_zone_by_md5 = dict(lines)
+
+    try:
+        with open(settings.LOCAL_TIME_FILE, 'r') as f:
+            data = f.read()
+    
+    except Exception as e:
+        logging.error('failed to read local time file: %s' % e)
+        
+        return None
+
+    md5 = hashlib.md5(data).hexdigest()
+    time_zone = time_zone_by_md5.get(md5)
+    
+    if time_zone:
+        logging.debug('found time zone by md5 method: %s' % time_zone)
+    
+    return time_zone
+
+
+def get_time_zone():
+    time_zone = _get_time_zone_symlink() or _get_time_zone_md5()
+    if not time_zone:
+        logging.error('could not find local time zone')
+
+    return time_zone
+
+
+def set_time_zone(time_zone):
+    zoneinfo_file = '/usr/share/zoneinfo/' + time_zone
+    if not os.path.exists(zoneinfo_file):
+        logging.error('%s file does not exist' % zoneinfo_file)
+        
+        return False
+
+    logging.debug('linking "%s" to "%s"...' % (settings.LOCAL_TIME_FILE, zoneinfo_file))
+
+    try:
+        os.remove(settings.LOCAL_TIME_FILE)
+    
+    except:
+        pass # nevermind
+    
+    try:
+        os.symlink(zoneinfo_file, settings.LOCAL_TIME_FILE)
+        
+        return True
+    
+    except Exception as e:
+        logging.error('failed to link "%s" to "%s": %s' % (settings.LOCAL_TIME_FILE, zoneinfo_file, e))
+        
+        return False
index f41488166d1c50f46d94c0ce16aadce998174cfa..b9390cd0d69bb4494420be61b79b5f549d882269 100644 (file)
                         <td class="settings-item-value"><input type="password" class="styled general" id="normalPasswordEntry"></td>
                         <td><span class="help-mark" title="the password for the surveillance user">?</span></td>
                     </tr>
+                    <tr class="settings-item {% if not timezones %}hidden{% endif %}">
+                        <td class="settings-item-label"><span class="settings-item-label">Time Zone</span></td>
+                        <td class="settings-item-value">
+                            <select class="styled motion-movies" id="timeZoneSelect">
+                                {% for timezone in timezones %}
+                                <option value="{{timezone}}">{{timezone}}</option>
+                                {% endfor %}
+                            </select>
+                        </td>
+                        <td><span class="help-mark" title="selecting the right timezone assures a correct timestamp displayed on pictures and movies">?</span></td>
+                    </tr>
                     <tr class="settings-item advanced-setting">
                         <td colspan="100"><div class="settings-item-separator"></div></td>
                     </tr>