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)
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):
# 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
# 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
import motionctl
import settings
import smbctl
+import tzctl
import update
import utils
import v4l2ctl
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
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
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', '')
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)
import json
import logging
import os
+import pytz
import socket
from tornado.web import RequestHandler, HTTPError, asynchronous
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())
--- /dev/null
+
+# 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
<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>