# Module `lib.webpage.motionpage`

Function define the web page to see the camera streaming

Expand source code

    # Distributed under Pycameresp License
    # Copyright (c) 2023 Remi BERTHOLET
    """ Function define the web page to see the camera streaming """
    import server.httpserver
    from htmltemplate          import *
    import webpage.mainpage
    import webpage.streamingpage
    import video.video
    import motion.motioncore
    import tools.lang
    import tools.info
    import tools.features

    zone_config = video.video.CameraConfig()

    def zone_masking(config, disabled):
            """ displays an html page to hide certain area of the camera, in order to ignore movements """
            _ = motion.motioncore.SnapConfig.get()

            width   = motion.motioncore.SnapConfig.get().diff_x
            height  = motion.motioncore.SnapConfig.get().diff_y
            maxi    = motion.motioncore.SnapConfig.get().max
            if disabled:
                    buttons = b""
            else:
                    buttons = b"""
                            <p>Colors squares where motion detection is ignored</p>
                            <button type="button" class="btn btn-outline-primary" onclick="onClearZoneMasking()" >Clear</button>
                            &nbsp;<button type="button" class="btn btn-outline-primary" onclick="onSetZoneMasking()" >Set</button><br>
                            &nbsp;<input type="hidden" name="mask" id="mask" value="">"""
            result= Tag(b"""
                            %s
                            <style>
                                    .zoneMask
                                    {
                                            -webkit-appearance: none;
                                            -moz-appearance: none;
                                            appearance: none;
                                            background-color: #EFEFEF;
                                            opacity: 0.14;
                                    }
                                    .zoneMask:checked
                                    {
                                            background-color: #1460ff;
                                            opacity: 0.80;
                                    }
                            </style>
                            <script>
                                    var videoStream      = document.getElementById("video-stream");
                                    var videoStreamWidth = videoStream.offsetWidth;

                                    function onVideoStreamDisplayed()
                                    {
                                            onLoadZoneMasking();
                                            resizeZoneMasking();
                                    }

                                    videoStream.addEventListener('load', onVideoStreamDisplayed);

                                    if (window.addEventListener)
                                    {
                                            window.addEventListener ("resize", onResizeEvent, true);
                                    }

                                    function onResizeEvent()
                                    {
                                            if(videoStream.offsetWidth != videoStreamWidth)
                                            {
                                                    videoStreamWidth = videoStream.offsetWidth;
                                                    resizeZoneMasking();
                                            }
                                    }

                                    function resizeZoneMasking()
                                    {
                                            var cellWidth  = (videoStream.offsetWidth  / 20) - 2.;

                                            for (id = 0; id < %d; id++)
                                            {
                                                    var cell = document.getElementById(id);
                                                    cell.style.width  = cellWidth + "px";
                                                    cell.style.height = cellWidth + "px";
                                            }
                                    }

                                    var initMask='%s';
                                    var disabled = %d;
                                    function check(box)
                                    {
                                            if (pressed)
                                            {
                                                    if (state == -1)
                                                    {
                                                            state = 1-box.checked;
                                                    }
                                                    box.checked = state;
                                            }
                                    }

                                    var pressed=0;
                                    var state=0;
                                    document.body.onmousedown = function() {pressed=1;state=-1;}
                                    document.body.onmouseup   = function() {pressed=0;state=-1;}

                                    function onLoadZoneMasking()
                                    {
                                            var table = document.getElementById("zone_masking");
                                            var id = 0;
                                            for (line = 0; line < %d; line ++)
                                            {
                                                    var row = table.insertRow(line);
                                                    for (column = 0; column < %d; column ++)
                                                    {
                                                            var tag = 'type="checkbox" class="zoneMask" onmousemove="check(this)" id="'+id+'"';
                                                            if (initMask.charAt(id) == "/")
                                                            {
                                                                    tag += " checked ";
                                                            }
                                                            if (disabled)
                                                            {
                                                                    tag += " disabled ";
                                                            }

                                                            row.insertCell(column).innerHTML = '<input ' + tag + ' />';
                                                            id += 1;
                                                    }
                                            }
                                    }
                                    function onValidZoneMasking()
                                    {
                                            var result = ""
                                            for (id = 0; id < %d; id ++)
                                            {
                                                    var cell = document.getElementById(id);
                                                    if (cell.checked)
                                                    {
                                                            result += "/";
                                                    }
                                                    else
                                                    {
                                                            result += " ";
                                                    }
                                            }
                                            document.getElementById('mask').value = result;
                                    }
                                    function onClearZoneMasking()
                                    {
                                            for (id = 0; id < %d; id ++)
                                            {
                                                    var cell = document.getElementById(id);
                                                    cell.checked = 0;
                                            }
                                    }
                                    function onSetZoneMasking()
                                    {
                                            for (id = 0; id < %d; id ++)
                                            {
                                                    var cell = document.getElementById(id);
                                                    cell.checked = 1;
                                            }
                                    }
                            </script>
    """%(buttons,maxi,config.mask,disabled,height,width,maxi,maxi,maxi))
            return result

    @server.httpserver.HttpServer.add_route(b'/motion/config', menu=tools.lang.menu_motion, item=tools.lang.item_motion, available=tools.info.iscamera() and video.video.Camera.is_activated() and tools.features.features.motion)
    async def motion_page(request, response, args):
            """ Motion configuration page """
            zone_config.framesize  = b"%dx%d"%(motion.motioncore.SnapConfig.get().width, motion.motioncore.SnapConfig.get().height)
            zone_config.quality = 30
            webpage.streamingpage.Streaming.set_config(zone_config)

            # Read motion config
            config = motion.motioncore.MotionConfig()

            # Keep activated status
            disabled, action, submit = webpage.mainpage.manage_default_button(request, config, onclick=b"onValidZoneMasking()")

            page = webpage.mainpage.main_frame(request, response, args, tools.lang.motion_detection_configuration,
                    Form([
                            Switch(text=tools.lang.activated, name=b"activated", checked=config.activated, disabled=disabled),
                            webpage.streamingpage.Streaming.get_html(request),
                            zone_masking(config, disabled),
                            Slider(text=tools.lang.detects_a_movement,          name=b"differences_detection",        min=b"1",  max=b"64", step=b"1",  value=b"%d"%config.differences_detection,         disabled=disabled),
                            Slider(text=tools.lang.motion_detection_sensitivity,          name=b"sensitivity",        min=b"0",  max=b"100", step=b"5",  value=b"%d"%config.sensitivity,         disabled=disabled),
                            Switch(text=tools.lang.notification_motion, name=b"notify",       checked=config.notify,       disabled=disabled),
                            Switch(text=tools.lang.notification_state,  name=b"notify_state", checked=config.notify_state, disabled=disabled),
                            Switch(text=tools.lang.suspends_motion_detection,                name=b"suspend_on_presence",     checked=config.suspend_on_presence, disabled=disabled),
                            Switch(text=tools.lang.permanent_detection,                      name=b"permanent_detection",     checked=config.permanent_detection, disabled=disabled),
                            Switch(text=tools.lang.turn_on_flash,                            name=b"light_compensation",      checked=config.light_compensation,  disabled=disabled),
                            submit
                    ]))
            await response.send_page(page)

    @server.httpserver.HttpServer.add_route(b'/motion/onoff', menu=tools.lang.menu_motion, item=tools.lang.item_motion_onoff, available=tools.info.iscamera() and video.video.Camera.is_activated() and tools.features.features.motion)
    async def motion_on_off(request, response, args):
            """ Motion command page """
            config = motion.motioncore.MotionConfig()
            config.load()
            command = request.params.get(b"action",b"none")
            if command == b"on":
                    config.activated = True
                    config.save()
            elif command == b"off":
                    config.activated = False
                    config.save()

            page = webpage.mainpage.main_frame(request, response, args, tools.lang.motion_onoff,
                    Form([
                            Submit(text=tools.lang.motion_off if config.activated else tools.lang.motion_on,  name=b"action", value=b"off" if config.activated else b"on" )
                    ]))
            await response.send_page(page)

## Functions

`async def motion_on_off(request, response, args)`

  Motion command page

  Expand source code

      @server.httpserver.HttpServer.add_route(b'/motion/onoff', menu=tools.lang.menu_motion, item=tools.lang.item_motion_onoff, available=tools.info.iscamera() and video.video.Camera.is_activated() and tools.features.features.motion)
      async def motion_on_off(request, response, args):
              """ Motion command page """
              config = motion.motioncore.MotionConfig()
              config.load()
              command = request.params.get(b"action",b"none")
              if command == b"on":
                      config.activated = True
                      config.save()
              elif command == b"off":
                      config.activated = False
                      config.save()

              page = webpage.mainpage.main_frame(request, response, args, tools.lang.motion_onoff,
                      Form([
                              Submit(text=tools.lang.motion_off if config.activated else tools.lang.motion_on,  name=b"action", value=b"off" if config.activated else b"on" )
                      ]))
              await response.send_page(page)

`async def motion_page(request, response, args)`

  Motion configuration page

  Expand source code

      @server.httpserver.HttpServer.add_route(b'/motion/config', menu=tools.lang.menu_motion, item=tools.lang.item_motion, available=tools.info.iscamera() and video.video.Camera.is_activated() and tools.features.features.motion)
      async def motion_page(request, response, args):
              """ Motion configuration page """
              zone_config.framesize  = b"%dx%d"%(motion.motioncore.SnapConfig.get().width, motion.motioncore.SnapConfig.get().height)
              zone_config.quality = 30
              webpage.streamingpage.Streaming.set_config(zone_config)

              # Read motion config
              config = motion.motioncore.MotionConfig()

              # Keep activated status
              disabled, action, submit = webpage.mainpage.manage_default_button(request, config, onclick=b"onValidZoneMasking()")

              page = webpage.mainpage.main_frame(request, response, args, tools.lang.motion_detection_configuration,
                      Form([
                              Switch(text=tools.lang.activated, name=b"activated", checked=config.activated, disabled=disabled),
                              webpage.streamingpage.Streaming.get_html(request),
                              zone_masking(config, disabled),
                              Slider(text=tools.lang.detects_a_movement,          name=b"differences_detection",        min=b"1",  max=b"64", step=b"1",  value=b"%d"%config.differences_detection,         disabled=disabled),
                              Slider(text=tools.lang.motion_detection_sensitivity,          name=b"sensitivity",        min=b"0",  max=b"100", step=b"5",  value=b"%d"%config.sensitivity,         disabled=disabled),
                              Switch(text=tools.lang.notification_motion, name=b"notify",       checked=config.notify,       disabled=disabled),
                              Switch(text=tools.lang.notification_state,  name=b"notify_state", checked=config.notify_state, disabled=disabled),
                              Switch(text=tools.lang.suspends_motion_detection,                name=b"suspend_on_presence",     checked=config.suspend_on_presence, disabled=disabled),
                              Switch(text=tools.lang.permanent_detection,                      name=b"permanent_detection",     checked=config.permanent_detection, disabled=disabled),
                              Switch(text=tools.lang.turn_on_flash,                            name=b"light_compensation",      checked=config.light_compensation,  disabled=disabled),
                              submit
                      ]))
              await response.send_page(page)

`def zone_masking(config, disabled)`

  displays an html page to hide certain area of the camera, in order to ignore movements

  Expand source code

      def zone_masking(config, disabled):
              """ displays an html page to hide certain area of the camera, in order to ignore movements """
              _ = motion.motioncore.SnapConfig.get()

              width   = motion.motioncore.SnapConfig.get().diff_x
              height  = motion.motioncore.SnapConfig.get().diff_y
              maxi    = motion.motioncore.SnapConfig.get().max
              if disabled:
                      buttons = b""
              else:
                      buttons = b"""
                              <p>Colors squares where motion detection is ignored</p>
                              <button type="button" class="btn btn-outline-primary" onclick="onClearZoneMasking()" >Clear</button>
                              &nbsp;<button type="button" class="btn btn-outline-primary" onclick="onSetZoneMasking()" >Set</button><br>
                              &nbsp;<input type="hidden" name="mask" id="mask" value="">"""
              result= Tag(b"""
                              %s
                              <style>
                                      .zoneMask
                                      {
                                              -webkit-appearance: none;
                                              -moz-appearance: none;
                                              appearance: none;
                                              background-color: #EFEFEF;
                                              opacity: 0.14;
                                      }
                                      .zoneMask:checked
                                      {
                                              background-color: #1460ff;
                                              opacity: 0.80;
                                      }
                              </style>
                              <script>
                                      var videoStream      = document.getElementById("video-stream");
                                      var videoStreamWidth = videoStream.offsetWidth;

                                      function onVideoStreamDisplayed()
                                      {
                                              onLoadZoneMasking();
                                              resizeZoneMasking();
                                      }

                                      videoStream.addEventListener('load', onVideoStreamDisplayed);

                                      if (window.addEventListener)
                                      {
                                              window.addEventListener ("resize", onResizeEvent, true);
                                      }

                                      function onResizeEvent()
                                      {
                                              if(videoStream.offsetWidth != videoStreamWidth)
                                              {
                                                      videoStreamWidth = videoStream.offsetWidth;
                                                      resizeZoneMasking();
                                              }
                                      }

                                      function resizeZoneMasking()
                                      {
                                              var cellWidth  = (videoStream.offsetWidth  / 20) - 2.;

                                              for (id = 0; id < %d; id++)
                                              {
                                                      var cell = document.getElementById(id);
                                                      cell.style.width  = cellWidth + "px";
                                                      cell.style.height = cellWidth + "px";
                                              }
                                      }

                                      var initMask='%s';
                                      var disabled = %d;
                                      function check(box)
                                      {
                                              if (pressed)
                                              {
                                                      if (state == -1)
                                                      {
                                                              state = 1-box.checked;
                                                      }
                                                      box.checked = state;
                                              }
                                      }

                                      var pressed=0;
                                      var state=0;
                                      document.body.onmousedown = function() {pressed=1;state=-1;}
                                      document.body.onmouseup   = function() {pressed=0;state=-1;}

                                      function onLoadZoneMasking()
                                      {
                                              var table = document.getElementById("zone_masking");
                                              var id = 0;
                                              for (line = 0; line < %d; line ++)
                                              {
                                                      var row = table.insertRow(line);
                                                      for (column = 0; column < %d; column ++)
                                                      {
                                                              var tag = 'type="checkbox" class="zoneMask" onmousemove="check(this)" id="'+id+'"';
                                                              if (initMask.charAt(id) == "/")
                                                              {
                                                                      tag += " checked ";
                                                              }
                                                              if (disabled)
                                                              {
                                                                      tag += " disabled ";
                                                              }

                                                              row.insertCell(column).innerHTML = '<input ' + tag + ' />';
                                                              id += 1;
                                                      }
                                              }
                                      }
                                      function onValidZoneMasking()
                                      {
                                              var result = ""
                                              for (id = 0; id < %d; id ++)
                                              {
                                                      var cell = document.getElementById(id);
                                                      if (cell.checked)
                                                      {
                                                              result += "/";
                                                      }
                                                      else
                                                      {
                                                              result += " ";
                                                      }
                                              }
                                              document.getElementById('mask').value = result;
                                      }
                                      function onClearZoneMasking()
                                      {
                                              for (id = 0; id < %d; id ++)
                                              {
                                                      var cell = document.getElementById(id);
                                                      cell.checked = 0;
                                              }
                                      }
                                      function onSetZoneMasking()
                                      {
                                              for (id = 0; id < %d; id ++)
                                              {
                                                      var cell = document.getElementById(id);
                                                      cell.checked = 1;
                                              }
                                      }
                              </script>
      """%(buttons,maxi,config.mask,disabled,height,width,maxi,maxi,maxi))
              return result