else: # assuming mjpeg
camera_config['@proto'] = 'mjpeg'
camera_config['@url'] = device_details['url']
+ _set_default_simple_mjpeg_camera(camera_id, camera_config)
# write the configuration to file
set_camera(camera_id, camera_config)
return ui
-def camera_ui_to_dict(ui, old_config=None):
+def motion_camera_ui_to_dict(ui, old_config=None):
old_config = dict(old_config or {})
main_config = get_main() # needed for surveillance password
return old_config
-def camera_dict_to_ui(data):
+def motion_camera_dict_to_ui(data):
ui = {
# device
'name': data['@name'],
return ui
+def simple_mjpeg_camera_ui_to_dict(ui, old_config=None):
+ old_config = dict(old_config or {})
+
+ data = {
+ # device
+ '@name': ui['name'],
+ '@enabled': ui['enabled'],
+ }
+
+ old_config.update(data)
+
+ return old_config
+
+
+def simple_mjpeg_camera_dict_to_ui(data):
+ ui = {
+ 'name': data['@name'],
+ 'enabled': data['@enabled'],
+ 'id': data['@id'],
+ 'proto': 'mjpeg',
+ 'url': data['@url']
+ }
+
+ return ui
+
+
def backup():
logging.debug('generating config backup file')
data.setdefault('on_event_end', '')
+def _set_default_simple_mjpeg_camera(camera_id, data):
+ data.setdefault('@name', 'Camera' + str(camera_id))
+ data.setdefault('@enabled', False)
+ data.setdefault('@id', camera_id)
+
+
def get_additional_structure(camera, separators=False):
if _additional_structure_cache.get((camera, separators)) is None:
logging.debug('loading additional config structure for %s' % ('camera' if camera else 'main'))
local_config = config.get_camera(camera_id)
if utils.local_motion_camera(local_config):
- ui_config = config.camera_dict_to_ui(local_config)
+ ui_config = config.motion_camera_dict_to_ui(local_config)
self.finish_json(ui_config)
remote.get_config(local_config, on_response)
else: # assuming simple mjpeg camera
- pass # TODO implement me
+ ui_config = config.simple_mjpeg_camera_dict_to_ui(local_config)
+
+ self.finish_json(ui_config)
else:
logging.debug('getting main config')
local_config = config.get_camera(camera_id)
if utils.local_motion_camera(local_config):
- local_config = config.camera_ui_to_dict(ui_config, local_config)
+ local_config = config.motion_camera_ui_to_dict(ui_config, local_config)
config.set_camera(camera_id, local_config)
on_finish(None, False)
else: # assuming simple mjpeg camera
- pass # TODO implement me
+ local_config = config.simple_mjpeg_camera_ui_to_dict(ui_config, local_config)
+
+ config.set_camera(camera_id, local_config)
+
+ on_finish(None, False) # (no error, motion doesn't need restart)
def set_main_config(ui_config):
logging.debug('setting main config...')
if not utils.local_motion_camera(local_config):
continue
- ui_config = config.camera_dict_to_ui(local_config)
- local_config = config.camera_ui_to_dict(ui_config, local_config)
+ ui_config = config.motion_camera_dict_to_ui(local_config)
+ local_config = config.motion_camera_ui_to_dict(ui_config, local_config)
config.set_camera(camera_id, local_config)
continue
if utils.local_motion_camera(local_config):
- ui_config = config.camera_dict_to_ui(local_config)
+ ui_config = config.motion_camera_dict_to_ui(local_config)
cameras.append(ui_config)
check_finished()
on_response_builder(camera_id, local_config)(error=True)
else: # assuming simple mjpeg camera
- pass # TODO implement me
+ ui_config = config.simple_mjpeg_camera_dict_to_ui(local_config)
+ cameras.append(ui_config)
+ check_finished()
if length[0] == 0:
self.finish_json({'cameras': []})
else:
motionctl.start()
- ui_config = config.camera_dict_to_ui(camera_config)
+ ui_config = config.motion_camera_dict_to_ui(camera_config)
self.finish_json(ui_config)
remote.get_config(camera_config, on_response)
else: # assuming simple mjpeg camera
- #ui_config = config.camera_dict_to_ui(camera_config)
- # TODO use a special mjpeg function to generate ui_config
+ ui_config = config.simple_mjpeg_camera_dict_to_ui(camera_config)
+
self.finish_json(ui_config)
@BaseHandler.auth(admin=True)
def frame(self, camera_id):
camera_config = config.get_camera(camera_id)
- if utils.local_motion_camera(camera_config) or self.get_argument('title', None) is not None:
+ if utils.local_motion_camera(camera_config) or utils.simple_mjpeg_camera(camera_config) or self.get_argument('title', None) is not None:
self.render('main.html',
frame=True,
camera_id=camera_id,
camera_config=camera_config,
title=self.get_argument('title', ''))
- # issue a fake camera_ui_to_dict() call to transform
+ # issue a fake motion_camera_ui_to_dict() call to transform
# the remote UI values into motion config directives
- remote_config = config.camera_ui_to_dict(remote_ui_config)
+ remote_config = config.motion_camera_ui_to_dict(remote_ui_config)
self.render('main.html',
frame=True,
remote.get_config(camera_config, on_response)
- else: # assuming simple mjpeg camera
- pass # TODO implement me
-
@BaseHandler.auth()
def download(self, camera_id, filename):
logging.debug('downloading picture %(filename)s of camera %(id)s' % {
cameraFrameDiv[0].refreshDivider = 0;
cameraFrameDiv[0].streamingFramerate = parseInt(cameraFrameDiv.attr('streaming_framerate')) || 1;
cameraFrameDiv[0].streamingServerResize = cameraFrameDiv.attr('streaming_server_resize') == 'True';
+ cameraFrameDiv[0].proto = cameraFrameDiv.attr('proto');
+ cameraFrameDiv[0].url = cameraFrameDiv.attr('url');
progressImg.attr('src', staticUrl + 'img/camera-progress.gif');
cameraProgress.addClass('visible');
var img = $cameraFrame.find('img.camera')[0];
var cameraId = cameraFrame.id.substring(6);
+ if (cameraFrame.proto == 'mjpeg') {
+ /* no manual refresh for simple mjpeg cameras */
+ img.src = cameraFrame.url;
+ return;
+ }
+
/* at a refresh interval of 50ms, the refresh rate is limited to 20 fps */
var count = 1000 / (refreshInterval * cameraFrame.streamingFramerate);
if (count <= 2) {
}
var dict = {
- /* video device */
'enabled': $('#videoDeviceSwitch')[0].checked,
'name': $('#deviceNameEntry').val(),
+ 'proto': $('#deviceTypeEntry')[0].proto,
+
+ /* video device */
'light_switch_detect': $('#lightSwitchDetectSwitch')[0].checked,
'auto_brightness': $('#autoBrightnessSwitch')[0].checked,
'rotation': $('#rotationSelect').val(),
}
function markHideIfNull(field, elemId) {
- if (field == null || dict[field] == null) {
- var elem = $('#' + elemId);
- var sectionDiv = elem.parents('tr:eq(0), div.settings-section-title:eq(0)');
- if (sectionDiv.length) { /* element is a section */
- sectionDiv.add(sectionDiv.next()).each(function () {this._hideNull = true;});
- }
- else { /* element is a config option */
- elem.parents('tr:eq(0)').each(function () {this._hideNull = true;});
- }
+ var elem = $('#' + elemId);
+ var sectionDiv = elem.parents('tr:eq(0), div.settings-section-title:eq(0)');
+ var hideNull = field == null || dict[field] == null;
+
+ if (sectionDiv.length) { /* element is a section */
+ sectionDiv.add(sectionDiv.next()).each(function () {this._hideNull = hideNull;});
+ }
+ else { /* element is a config option */
+ elem.parents('tr:eq(0)').each(function () {this._hideNull = hideNull;});
}
}
$('#deviceNameEntry').val(dict['name']); markHideIfNull('name', 'deviceNameEntry');
$('#deviceUriEntry').val(dict['device_url']); markHideIfNull('device_url', 'deviceUriEntry');
$('#deviceTypeEntry').val(prettyType); markHideIfNull(prettyType, 'deviceTypeEntry');
+ $('#deviceTypeEntry')[0].proto = dict['proto'];
$('#lightSwitchDetectSwitch')[0].checked = dict['light_switch_detect']; markHideIfNull('light_switch_detect', 'lightSwitchDetectSwitch');
$('#autoBrightnessSwitch')[0].checked = dict['auto_brightness']; markHideIfNull('auto_brightness', 'autoBrightnessSwitch');
if (this.config.proto == 'netcam' || this.config.proto == 'v4l2') {
instance = '';
}
- else { /* motioneye */
+ else if (this.config.proto == 'motioneye') {
instance = this.config.host || '';
if (this.config.port) {
instance += ':' + this.config.port;
}
}
+ else { /* assuming simple mjpeg camera */
+ return;
+ }
(cameraIdsByInstance[instance] = cameraIdsByInstance[instance] || []).push(this.config.id);
});
configureButton.hide();
}
+ /* no media buttons for simple mjpeg cameras */
+ if (cameraConfig['proto'] == 'mjpeg') {
+ picturesButton.hide();
+ moviesButton.hide();
+ }
+
cameraFrameDiv.attr('id', 'camera' + cameraId);
cameraFrameDiv[0].refreshDivider = 0;
cameraFrameDiv[0].config = cameraConfig;
}
});
});
+
+ if (cameraFrameDiv[0].config['proto'] == 'mjpeg') {
+ /* manually trigger the load event on simple mjpeg cameras */
+ cameraImg.load();
+ }
}
function refreshCameraFrames() {
cameraFrames.each(function () {
if (!this.img) {
this.img = $(this).find('img.camera')[0];
+ if (this.config['proto'] == 'mjpeg') {
+ this.img.src = this.config['url'];
+ }
+ }
+
+ if (this.config['proto'] == 'mjpeg') {
+ return; /* no manual refresh for simple mjpeg cameras */
}
/* at a refresh interval of 50ms, the refresh rate is limited to 20 fps */
</div>
{% else %}
<div class="camera-frame" id="camera{{camera_id}}"
- streaming_framerate="{{camera_config['stream_maxrate']}}" streaming_server_resize="{{camera_config['@webcam_server_resize']}}">
+ streaming_framerate="{{camera_config['stream_maxrate']}}" streaming_server_resize="{{camera_config['@webcam_server_resize']}}"
+ proto="{{camera_config['@proto']}}" url="{{camera_config['@url']}}">
<div class="camera-container">
<div class="camera-placeholder"><img class="no-camera" src="{{STATIC_URL}}img/no-camera.svg"></div><img