# 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)
+# enables shutdown and rebooting after changing system settings (such as wifi settings or system updates)
ENABLE_REBOOT = False
# the timeout in seconds to use when talking to a SMTP server
import config
import mediafiles
import motionctl
+import powerctl
import remote
import settings
import smbctl
self.render('main.html',
wpa_supplicant=settings.WPA_SUPPLICANT_CONF,
+ enable_reboot=settings.ENABLE_REBOOT,
timezones=timezones,
hostname=socket.gethostname())
self.finish_json(result)
+class PowerHandler(BaseHandler):
+ @BaseHandler.auth(admin=True)
+ def post(self, op):
+ if op == 'shutdown':
+ powerctl.shut_down()
+
+ elif op == 'reboot':
+ powerctl.reboot()
+
+
class VersionHandler(BaseHandler):
def get(self):
self.render('version.html',
--- /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 logging
+import os
+import subprocess
+
+
+def _find_prog(prog):
+ try:
+ return subprocess.check_output('which %s' % prog, shell=True).strip()
+
+ except subprocess.CalledProcessError: # not found
+ return None
+
+
+def _exec_prog(prog):
+ logging.info('executing "%s"' % prog)
+
+ return os.system(prog) == 0
+
+
+def shut_down():
+ logging.info('shutting down')
+
+ prog = _find_prog('poweroff')
+ if prog:
+ return _exec_prog(prog)
+
+ prog = _find_prog('shutdown')
+ if prog:
+ return _exec_prog(prog + ' -h now')
+
+ prog = _find_prog('systemctl')
+ if prog:
+ return _exec_prog(prog + ' poweroff')
+
+ prog = _find_prog('init')
+ if prog:
+ return _exec_prog(prog + ' 0')
+
+ return False
+
+
+def reboot():
+ logging.info('rebooting')
+
+ prog = _find_prog('reboot')
+ if prog:
+ return _exec_prog(prog)
+
+ prog = _find_prog('shutdown')
+ if prog:
+ return _exec_prog(prog + ' -r now')
+
+ prog = _find_prog('systemctl')
+ if prog:
+ return _exec_prog(prog + ' reboot')
+
+ prog = _find_prog('init')
+ if prog:
+ return _exec_prog(prog + ' 6')
+
+ return False
(r'^/movie/(?P<camera_id>\d+)/(?P<op>list)/?$', handlers.MovieHandler),
(r'^/movie/(?P<camera_id>\d+)/(?P<op>download|preview)/(?P<filename>.+)/?$', handlers.MovieHandler),
(r'^/update/?$', handlers.UpdateHandler),
+ (r'^/power/(?P<op>shutdown|reboot)/?$', handlers.PowerHandler),
(r'^/version/?$', handlers.VersionHandler),
(r'^.*$', handlers.NotFoundHandler),
],
margin-top: 3px;
}
-div.update-button {
+div.update-button,
+div.shut-down-button,
+div.reboot-button {
position: relative;
- width: 4em;
height: 1.5em;
line-height: 1.5em;
text-align: center;
margin: 2px 0px;
color: white;
font-size: 1em;
- background-color: #317CAD;
border-radius: 3px;
transition: all 0.1s linear;
}
+div.update-button {
+ width: 4em;
+ background: #317CAD;
+}
+
+div.shut-down-button {
+ width: 8em;
+ background: #c0392b;
+}
+
+div.reboot-button {
+ width: 8em;
+ background: #c0392b;
+}
+
div.update-button:HOVER {
- background-color: #3498db;
+ background: #3498db;
+}
+
+div.shut-down-button:HOVER {
+ background: #D43F2F;
+}
+
+div.reboot-button:HOVER {
+ background: #D43F2F;
}
div.update-button:ACTIVE {
- background-color: #317CAD;
+ background: #317CAD;
+}
+
+div.shut-down-button:ACTIVE {
+ background: #B03427;
+}
+
+div.reboot-button:ACTIVE {
+ background: #B03427;
}
div.settings-top-bar.open #cameraSelect {
doApply();
});
+ /* shut down button */
+ $('#shutDownButton').click(function () {
+ doShutDown();
+ });
+
+ /* reboot button */
+ $('#rebootButton').click(function () {
+ doReboot();
+ });
+
/* whenever the window is resized,
* if a modal dialog is visible, it should be repositioned */
$(window).resize(updateModalDialogPosition);
});
}
+function doShutDown() {
+ runConfirmDialog('Really shut down?', function () {
+ ajax('POST', '/power/shutdown/');
+ });
+}
+
+function doReboot() {
+ runConfirmDialog('Really reboot?', function () {
+ ajax('POST', '/power/reboot/');
+ });
+}
+
function doRemCamera() {
if (Object.keys(pushConfigs).length) {
return runAlertDialog('Please apply the modified settings first!');
<td class="settings-item-value"><div class="button update-button" id="updateButton">Check</div></td>
<td><span class="help-mark" title="checks for new versions and performs updates">?</span></td>
</tr>
+ <tr class="settings-item advanced-setting{% if not enable_reboot %} hidden{% endif %}">
+ <td class="settings-item-label"><span class="settings-item-label">Power</span></td>
+ <td class="settings-item-value"><div class="button shut-down-button" id="shutDownButton">Shut Down</div></td>
+ <td><span class="help-mark" title="shuts down the system">?</span></td>
+ </tr>
+ <tr class="settings-item advanced-settingg{% if not enable_reboot %} hidden{% endif %}">
+ <td class="settings-item-label"></td>
+ <td class="settings-item-value"><div class="button reboot-button" id="rebootButton">Reboot</div></td>
+ <td><span class="help-mark" title="reboots the system">?</span></td>
+ </tr>
</table>
<div class="settings-section-title advanced-setting{% if not wpa_supplicant %} hidden{% endif %}"><input type="checkbox" class="styled section wifi" id="wifiSwitch">Wireless Network</div>