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>
<button type="button" class="btn btn-outline-primary" onclick="onSetZoneMasking()" >Set</button><br>
<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> <button type="button" class="btn btn-outline-primary" onclick="onSetZoneMasking()" >Set</button><br> <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