]> www.vanbest.org Git - motioneye-debian/commitdiff
remote config fixes
authorCalin Crisan <ccrisan@gmail.com>
Sun, 6 Oct 2013 08:05:05 +0000 (11:05 +0300)
committerCalin Crisan <ccrisan@gmail.com>
Sun, 6 Oct 2013 08:05:05 +0000 (11:05 +0300)
doc/todo.txt
src/config.py
src/handlers.py
src/motionctl.py
static/js/main.js

index 46666f878248a29f03d982b762ed9af59b5ac51f..fd41383980f7e56e7ddace68d4ee50ae6cc76ae9 100644 (file)
@@ -2,6 +2,7 @@
 -> bug: adding a remote device does not provide the available resolutions
  
 -> bug: if updating a remote camera config, local motion will get restarted
+-> bug: when renaming the camera, the left/right texts set "Camera" should also change
 -> make camera frames positions configurable
 -> hide horrible 404 image on cameras
 -> prevent Request closed errors by stopping mjpg clients before stopping motion
index 89f7f094eeee677e284bf661a2be60f682199fda..3dae27dd5158e744865deeabe251d795ed4b9df9 100644 (file)
@@ -7,7 +7,6 @@ import re
 from collections import OrderedDict
 
 import settings
-import v4l2ctl
 
 
 _CAMERA_CONFIG_FILE_NAME = 'thread-%(id)s.conf'
@@ -143,7 +142,7 @@ def has_enabled_cameras():
     
     camera_ids = get_camera_ids()
     cameras = [get_camera(camera_id) for camera_id in camera_ids]
-    return bool([c for c in cameras if c['@enabled']])
+    return bool([c for c in cameras if c['@enabled'] and c['@proto'] == 'v4l2'])
 
 
 def get_camera(camera_id, as_lines=False):
@@ -193,7 +192,7 @@ def get_camera(camera_id, as_lines=False):
 def set_camera(camera_id, data):
     # TODO use a cache
     
-    if data.get('@proto') == 'v4l2':
+    if data['@proto'] == 'v4l2':
         _set_default_motion_camera(data)
         
         # set the enabled status in main config
@@ -208,6 +207,10 @@ def set_camera(camera_id, data):
     
         main_config['thread'] = threads
         
+        del data['@enabled']
+        if '@id' in data:
+            del data['@id']
+        
         set_main(main_config)
 
     # read the actual configuration from file
@@ -251,9 +254,6 @@ def set_camera(camera_id, data):
 def add_camera(device_details):
     # TODO use a cache
     
-    device = device_details.get('device')
-    proto = device_details.get('proto')
-        
     # determine the last camera id
     camera_ids = get_camera_ids()
 
@@ -264,23 +264,27 @@ def add_camera(device_details):
     logging.info('adding new camera with id %(id)s...' % {'id': camera_id})
     
     # add the default camera config
+    proto = device_details['proto']
+        
     data = OrderedDict()
-    data['@name'] = 'Camera' + str(camera_id)
     data['@proto'] = proto
-    data['@enabled'] = True
-    
-    for k, v in device_details.items():
-        data['@' + k] = v
+    data['@enabled'] = device_details.get('enabled', True)
     
     if proto == 'v4l2':
-        data['videodevice'] = device
-        # find a suitable resolution
-        for (w, h) in v4l2ctl.list_resolutions(device): # TODO move/copy this code to handler/get_config
-            if w > 300:
-                data['width'] = w
-                data['height'] = h
-                break
-            
+        data['@name'] = 'Camera' + str(camera_id)
+        data['videodevice'] = device_details['device']
+        if 'width' in device_details:
+            data['width'] = device_details['width']
+            data['height'] = device_details['height']
+        
+    else:
+        data['@host'] = device_details['host']
+        data['@port'] = device_details['port']
+        data['@username'] = device_details['username']
+        data['@password'] = device_details['password']
+        data['@remote_camera_id'] = device_details['remote_camera_id']
+        data['@enabled'] = device_details.get('enabled', True)
+
     # write the configuration to file
     set_camera(camera_id, data)
     
index a650469d1c69f2ec4910ef4029106e219eba7453..b81e84d597c218c4ce669aecce4eff1ea3195b81 100644 (file)
@@ -86,14 +86,13 @@ class ConfigHandler(BaseHandler):
         if camera_id:
             logging.debug('getting config for camera %(id)s' % {'id': camera_id})
             
-            camera_ids = config.get_camera_ids()
-            if camera_id not in camera_ids:
+            if camera_id not in config.get_camera_ids():
                 raise HTTPError(404, 'no such camera')
             
             camera_config = config.get_camera(camera_id)
             if camera_config['@proto'] != 'v4l2':
                 try:
-                    remote_data = remote.get_config(
+                    remote_ui_config = remote.get_config(
                             camera_config.get('@host'),
                             camera_config.get('@port'),
                             camera_config.get('@username'),
@@ -102,17 +101,21 @@ class ConfigHandler(BaseHandler):
                     
                 except Exception as e:
                     return self.finish_json({'error': unicode(e)})       
-        
-                remote_data = self._camera_ui_to_dict(remote_data)
+
+                local_data = camera_config        
+                camera_config = self._camera_ui_to_dict(remote_ui_config)
+                camera_config['@proto'] = local_data['@proto']
+                camera_config['@enabled'] = local_data['@enabled']
                 
-                camera_config.update(remote_data) 
-            
             ui_config = self._camera_dict_to_ui(camera_config)
             
             if camera_config['@proto'] == 'v4l2':
                 resolutions = v4l2ctl.list_resolutions(camera_config['videodevice'])
                 resolutions = [(str(w) + 'x' + str(h)) for (w, h) in resolutions]
                 ui_config['available_resolutions'] = resolutions
+            
+            else:
+                ui_config['available_resolutions'] = remote_ui_config['available_resolutions']
                 
             self.finish_json(ui_config)
             
@@ -124,60 +127,43 @@ class ConfigHandler(BaseHandler):
     
     def set_config(self, camera_id):
         try:
-            data = json.loads(self.request.body)
+            ui_config = json.loads(self.request.body)
             
         except Exception as e:
             logging.error('could not decode json: %(msg)s' % {'msg': unicode(e)})
             
             raise
         
-        restart = bool(data.get('last'))
-        if restart and motionctl.running():
-            motionctl.stop()
-        
-        try:
-            if camera_id:
-                logging.debug('setting config for camera %(id)s' % {'id': camera_id})
-                
-                camera_ids = config.get_camera_ids()
-                if camera_id not in camera_ids:
-                    raise HTTPError(404, 'no such camera')
+        if camera_id:
+            logging.debug('setting config for camera %(id)s' % {'id': camera_id})
+            
+            camera_ids = config.get_camera_ids()
+            if camera_id not in camera_ids:
+                raise HTTPError(404, 'no such camera')
+            
+            camera_config = config.get_camera(camera_id)
+            if camera_config['@proto'] == 'v4l2':
+                camera_config = self._camera_ui_to_dict(ui_config)
+                camera_config['@proto'] = 'v4l2'
+                config.set_camera(camera_id, camera_config)
                 
-                camera_config = config.get_camera(camera_id)
-                if camera_config['@proto'] == 'v4l2':
-                    data = self._camera_ui_to_dict(data)
-                    config.set_camera(camera_id, data)
-                    
-                else:
-                    remote.set_config(
-                            camera_config.get('@host'),
-                            camera_config.get('@port'),
-                            camera_config.get('@username'),
-                            camera_config.get('@password'),
-                            camera_config.get('@remote_camera_id'),
-                            data)
-    
             else:
-                logging.debug('setting main config')
-                
-                try:
-                    data = json.loads(self.request.body)
-                    
-                except Exception as e:
-                    logging.error('could not decode json: %(msg)s' % {'msg': unicode(e)})
-                    
-                    raise
-                
-                data = self._main_ui_to_dict(data)
-                config.set_main(data)
+                remote.set_config(
+                        camera_config.get('@host'),
+                        camera_config.get('@port'),
+                        camera_config.get('@username'),
+                        camera_config.get('@password'),
+                        camera_config.get('@remote_camera_id'),
+                        ui_config)
 
-        except:
-            raise
-        
-        finally:
-            if restart:
-                if config.has_enabled_cameras():
-                    motionctl.start()
+        else:
+            logging.debug('setting main config')
+            
+            main_config = self._main_ui_to_dict(ui_config)
+            config.set_main(main_config)
+
+        if not ui_config.get('norestart'):
+            motionctl.restart()
 
     def set_preview(self, camera_id):
         try:
@@ -223,7 +209,7 @@ class ConfigHandler(BaseHandler):
         username = self.get_argument('username', None)
         password = self.get_argument('password', None)
         
-        if host: # remote
+        if host: # remote listing
             try:
                 cameras = remote.list_cameras(host, port, username, password)
                 
@@ -233,17 +219,25 @@ class ConfigHandler(BaseHandler):
         else:
             cameras = []
             for camera_id in config.get_camera_ids():
-                data = config.get_camera(camera_id)
-                if data['@proto'] == 'v4l2':
-                    data = self._camera_dict_to_ui(data)
+                camera_config = config.get_camera(camera_id)
+                if camera_config['@proto'] == 'v4l2':
+                    name = camera_config['@name']
                     
-                else:
-                    data = {
-                        'name': data['@name']
-                    }
+                else: # remote camera
+                    try:
+                        remote_camera_config = remote.get_config(
+                                camera_config.get('@host'),
+                                camera_config.get('@port'),
+                                camera_config.get('@username'),
+                                camera_config.get('@password'),
+                                camera_config.get('@remote_camera_id'))
+                        
+                    except:
+                        continue
                     
-                data['id'] = camera_id
-                cameras.append(data)
+                    name = remote_camera_config['name']
+
+                cameras.append({'name': name, 'id': camera_id})
 
         self.finish_json({'cameras': cameras})
     
@@ -271,31 +265,50 @@ class ConfigHandler(BaseHandler):
             
             raise
 
-        camera_id, data = config.add_camera(device_details)
+        proto = device_details['proto']
+        if proto == 'v4l2':
+            # find a suitable resolution
+            for (w, h) in v4l2ctl.list_resolutions(device_details['device']):
+                if w > 300:
+                    device_details['width'] = w
+                    device_details['height'] = h
+                    break
+
+        camera_id, camera_config = config.add_camera(device_details)
+
+        if proto == 'v4l2':
+            motionctl.restart()
+        
+        else:
+            try:
+                remote_ui_config = remote.get_config(
+                        device_details.get('host'),
+                        device_details.get('port'),
+                        device_details.get('username'),
+                        device_details.get('password'),
+                        device_details.get('remote_camera_id'))
+                
+            except Exception as e:
+                return self.finish_json({'error': unicode(e)})       
+
+            local_data = camera_config
+            camera_config = self._camera_ui_to_dict(remote_ui_config)
+            camera_config['@enabled'] = local_data['@enabled']
+            camera_config['@proto'] = local_data['@proto']
         
-        data['@id'] = camera_id
+        camera_config['@id'] = camera_id
         
-        if motionctl.running() and data['@proto'] == 'v4l2':
-            motionctl.stop()
+        ui_config = self._camera_dict_to_ui(camera_config)
         
-        if config.has_enabled_cameras() and data['@proto'] == 'v4l2':
-            motionctl.start()
-            
-        try:
-            remote_data = remote.get_config(
-                    device_details.get('host'),
-                    device_details.get('port'),
-                    device_details.get('username'),
-                    device_details.get('password'),
-                    device_details.get('remote_camera_id'))
+        if camera_config['@proto'] == 'v4l2':
+            resolutions = v4l2ctl.list_resolutions(camera_config['videodevice'])
+            resolutions = [(str(w) + 'x' + str(h)) for (w, h) in resolutions]
+            ui_config['available_resolutions'] = resolutions
             
-        except Exception as e:
-            return self.finish_json({'error': unicode(e)})       
-
-        remote_data = self._camera_ui_to_dict(remote_data)
-        remote_data.update(data)
+        else:
+            ui_config['available_resolutions'] = remote_ui_config['available_resolutions']
         
-        self.finish_json(self._camera_dict_to_ui(remote_data))
+        self.finish_json(ui_config)
     
     def rem_camera(self, camera_id):
         logging.debug('removing camera %(id)s' % {'id': camera_id})
@@ -303,11 +316,8 @@ class ConfigHandler(BaseHandler):
         local = config.get_camera(camera_id).get('@proto') == 'v4l2'
         config.rem_camera(camera_id)
         
-        if motionctl.running() and local:
-            motionctl.stop()
-        
-        if config.has_enabled_cameras() and local:
-            motionctl.start()
+        if local:
+            motionctl.restart()
         
     def _main_ui_to_dict(self, ui):
         return {
index 62b0e983f7306fbdaf145e8eb8aa6d5689962913..548330fc5f6fc219c29d1d4afaa1ac452ff8f3f6 100644 (file)
@@ -5,6 +5,7 @@ import signal
 import subprocess
 import time
 
+import config
 import settings
 
 
@@ -100,6 +101,14 @@ def running():
     return False
 
 
+def restart():
+    if running():
+        stop()
+    
+    if config.has_enabled_cameras():
+        start()
+
+
 def _get_pid():
     motion_pid_path = os.path.join(settings.RUN_PATH, 'motion.pid')
     
index 989c341b6efcaa186bd9c121b9f89a0e344d641e..b4856f733e70da0851a51c93d1a4fb6cc69c7076 100644 (file)
@@ -746,7 +746,7 @@ function doApply() {
     for (var i = 0; i < configs.length; i++) {
         var config = configs[i];
         if (i === configs.length - 1) {
-            config.config['last'] = true;
+            config.config['last'] = true; // TODO not used, to be replaced by norestart
         }
         ajax('POST', '/config/' + config.key + '/set/', config.config, function (data) {
             if (data == null || data.error) {
@@ -1218,7 +1218,7 @@ function doCloseCamera(cameraId) {
         }
         
         data['enabled'] = false;
-        data['last'] = true;
+        data['last'] = true;// TODO not used, to be replaced by norestart
         ajax('POST', '/config/' + cameraId + '/set/', data, function (data) {
             if (data == null || data.error) {
                 return; // TODO handle error