initial commit for NVR plugin

This commit is contained in:
Ziver Koc 2021-01-26 01:53:11 +01:00
parent 65581f13d5
commit da3ba116da
18 changed files with 964 additions and 0 deletions

View file

@ -0,0 +1,12 @@
repositories {
maven {
url 'https://jitpack.io' // Needed for ffmpeg4j project
}
}
dependencies {
implementation project(':hal-core')
implementation 'com.github.Manevolent:ffmpeg4j:4.1-1.4.4-2' // https://github.com/Manevolent/ffmpeg4j
//implementation 'net.bramp.ffmpeg:ffmpeg:0.6.2' // https://github.com/bramp/ffmpeg-cli-wrapper
}

View file

@ -0,0 +1,123 @@
<h1 class="page-header">Camera Configuration</h1>
<div class="col-md-12">
<div class="panel panel-default drop-shadow">
<div class="panel-heading">Cameras</div>
<div class="panel-body">
<p>This is a list of cameras connected to this node.</p>
<table class="table table-hover table-condensed">
<thead>
<th>Name</th>
<th>Type</th>
<th>Configuration</th>
<th>
<button class="btn btn-default btn-xs pull-right" data-toggle="modal"
data-target="#cameraModal"
data-action="create_camera">
<span class="glyphicon glyphicon-plus"></span>
</button>
</th>
</thead>
{{#cameras}}
<tr>
<td>{{.getName()}}</td>
<td>{{.getType()}}</td>
<td>{{.getDeviceConfig()}}</td>
<td>
<form method="POST">
<input type="hidden" name="id" value="{{.getId()}}">
<div class="btn-toolbar pull-right">
<button type="button" class="btn btn-default btn-xs" data-toggle="modal"
data-target="#cameraModal"
data-action="modify_camera"
data-id="{{.getId()}}"
data-name="{{.getName()}}"
data-type="{{.getType()}}"
{{#.getDeviceConfigurator().getConfiguration()}}
data-{{.getName()}}="{{.getString()}}"
{{/.getDeviceConfigurator().getConfiguration()}}
>
<span class="glyphicon glyphicon-pencil"></span>
</button>
<button type="submit" class="btn btn-danger btn-xs" name="action" value="remove_camera">
<span class="glyphicon glyphicon-trash"></span>
</button>
</div>
</form>
</td>
</tr>
{{/cameras}}
</table>
</div>
</div>
</div>
<!------------- MODALS --------------->
<script>
$(function(){
initDynamicModalForm("cameraModal", "camera-data-conf", "camera-data-conf-template");
});
</script>
<div class="modal fade" id="cameraModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
<h4 class="modal-title">Camera</h4>
</div>
<form method="POST">
<div class="modal-body">
<input type="hidden" id="action" name="action">
<input type="hidden" id="id" name="id">
<div class="form-group">
<label class="control-label">Name:</label>
<input type="text" class="form-control" name="name">
</div>
<div class="form-group">
<label class="control-label">Type:</label>
<select class="form-control" name="type">
{{#availableCameras}}
<option>{{.getName()}}</option>
{{/availableCameras}}
</select>
</div>
<hr>
<div id="camera-data-conf">
<!-- Dynamic form -->
</div>
</div>
<div class="modal-footer">
<button type="reset" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
<div id="camera-data-conf-template" class="hidden">
{{#cameraConf}}
<div id="{{.clazz.getName()}}">
{{#.params}}
<div class="form-group">
<label class="control-label">{{.getNiceName()}}:</label>
{{#.isTypeString()}}<input type="text" class="form-control" name="{{.getName()}}">{{/#.isTypeString()}}
{{#.isTypeInt()}}<input type="number" class="form-control" name="{{.getName()}}">{{/#.isTypeInt()}}
{{#.isTypeBoolean()}}<input type="checkbox" name="{{.getName()}}" value="true">{{/#.isTypeBoolean()}}
{{#.isTypeEnum()}}
<select class="form-control" name="{{.getName()}}">
{{#.getPossibleValues()}}<option>{{.}}</option>{{/.getPossibleValues()}}
</select>
{{/#.isTypeEnum()}}
</div>
{{/.params}}
</div>
{{/cameraConf}}
</div>

View file

@ -0,0 +1,42 @@
<h1 class="page-header">Details for <a href="#">{{camera.getName()}}</a></h1>
<div class="col-md-12">
<video width="100%" height="480" controls>
<source src="rtsp://admin:xxxx@192.168.10.223:554/H.264">
Your browser does not support the video tag.
</video>
</div>
<div class="col-md-5">
<div class="panel panel-default drop-shadow">
<div class="panel-heading">Configuration</div>
<div class="panel-body">
<table class="table table-hover table-condensed">
<thead>
<tr>
<th class="text-right">Camera ID:</th>
<th>{{camera.getId()}}</th>
</tr>
<tr>
<th class="text-right">Name:</th>
<th>{{camera.getName()}}</th>
</tr>
</thead>
<tr>
<th class="text-right">Type:</th>
<td>{{camera.getDeviceData().getClass().getSimpleName()}}</td>
</tr>
<tr>
<th class="text-right">Owner:</th>
<td>{{camera.getUser().getUsername()}} <p></td>
</tr>
{{#camera.getDeviceConfigurator().getConfiguration()}}
<tr>
<th class="text-right">{{.getNiceName()}}:</th>
<td>{{.getString()}}</td>
</tr>
{{/camera.getDeviceConfigurator().getConfiguration()}}
</table>
</div>
</div>
</div>

View file

@ -0,0 +1,39 @@
<h1 class="page-header">Camera Monitor</h1>
<style>
.monitor-view {
padding: 0px;
line-height: 0px;
}
</style>
<div class="container">
<div class="row">
<div class="monitor-view col-md-6">
<video width="100%" height="480" controls>
<source src="rtsp://admin:xxxx@192.168.10.223:554/H.264">
Your browser does not support the video tag.
</video>
</div>
<div class="monitor-view col-md-6">
<video width="100%" height="480" controls>
<source src="rtsp://admin:xxxx@192.168.10.223:554/H.264">
Your browser does not support the video tag.
</video>
</div>
</div>
<div class="row">
<div class="monitor-view col-md-6">
<video width="100%" height="480" controls>
<source src="rtsp://admin:xxxx@192.168.10.223:554/H.264">
Your browser does not support the video tag.
</video>
</div>
<div class="monitor-view col-md-6">
<video width="100%" height="480" controls>
<source src="rtsp://admin:xxx@192.168.10.223:554/H.264">
Your browser does not support the video tag.
</video>
</div>
</div>
</div>

View file

@ -0,0 +1,26 @@
<h1 class="page-header">Camera Overview</h1>
<div class="col-md-12">
<div class="panel panel-default drop-shadow">
<div class="panel-heading">Cameras</div>
<div class="panel-body">
<table class="table table-hover table-condensed">
<thead>
<th class="col-md-4">Name</th>
<th class="col-md-3">Type</th>
<th class="col-md-2">Data</th>
<th class="col-md-2">Last Update</th>
</thead>
{{#cameras}}
<tr>
<td><a href="?id={{.getId()}}">{{.getName()}}</a></td>
<td>{{.getDeviceConfig().getClass().getSimpleName()}}</td>
<td>{{.getDeviceData()}}</td>
<td><span class="timestamp">{{.getDeviceData().getTimestamp()}}</span></td>
</tr>
{{/cameras}}
</table>
</div>
</div>
</div>

View file

@ -0,0 +1,48 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr;
import se.hal.intf.HalAbstractController;
import se.hal.plugin.nvr.device.HalCameraConfig;
import se.hal.plugin.nvr.device.HalCameraReportListener;
public interface HalCameraController extends HalAbstractController {
/**
* Will register a camera to be handled by this controller.
*/
void register(HalCameraConfig cameraConfig);
/**
* Deregisters a camera from this controller, the controller
* will no longer handle camera device.
*/
void deregister(HalCameraConfig cameraConfig);
/**
* Set a listener that will receive all reports from the the registered camera.
*/
void setListener(HalCameraReportListener listener);
}

View file

@ -0,0 +1,29 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr;
public class StreamRecorder {
}

View file

@ -0,0 +1,56 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr.device;
import se.hal.intf.HalAbstractController;
import se.hal.struct.AbstractDevice;
import zutil.db.DBConnection;
import zutil.db.bean.DBBean;
import java.sql.SQLException;
import java.util.List;
public class Camera extends AbstractDevice<Camera, HalCameraConfig, HalCameraData> {
public static List<Camera> getCameras(DBConnection db) throws SQLException{
return DBBean.load(db, Camera.class);
}
public static Camera getCamera(DBConnection db, long id) throws SQLException {
return DBBean.load(db, Camera.class, id);
}
@Override
public Class<? extends HalAbstractController> getController() {
return getDeviceConfig().getCameraControllerClass();
}
@Override
protected HalCameraData getLatestDeviceData(DBConnection db) {
return null;
}
}

View file

@ -0,0 +1,36 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr.device;
import se.hal.plugin.nvr.HalCameraController;
public interface HalCameraConfig {
/**
* @return the Controller class where CameraData should be registered on
*/
Class<? extends HalCameraController> getCameraControllerClass();
}

View file

@ -0,0 +1,40 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr.device;
import se.hal.intf.HalDeviceData;
public class HalCameraData extends HalDeviceData {
@Override
public double getData() {
return 0;
}
@Override
public void setData(double data) {
}
}

View file

@ -0,0 +1,10 @@
package se.hal.plugin.nvr.device;
import se.hal.plugin.nvr.HalCameraController;
/**
* Listener to be called by the {@link HalCameraController} to report that a camera event has been observed.
*/
public interface HalCameraReportListener {
}

View file

@ -0,0 +1,134 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr.page;
import se.hal.ControllerManager;
import se.hal.HalContext;
import se.hal.intf.HalWebPage;
import se.hal.page.HalAlertManager;
import se.hal.plugin.nvr.device.Camera;
import se.hal.struct.ClassConfigurationData;
import se.hal.struct.User;
import zutil.ObjectUtil;
import zutil.db.DBConnection;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
import zutil.parser.Templator;
import java.util.ArrayList;
import java.util.Map;
import java.util.logging.Logger;
public class CameraConfigWebPage extends HalWebPage {
private static final Logger logger = LogUtil.getLogger();
private static final String TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/camera_config.tmpl";
private ArrayList<ClassConfigurationData> cameraConfigurations;
public CameraConfigWebPage() {
super("camera_config");
super.getRootNav().createSubNav("Settings").createSubNav(this.getId(), "Camera Settings").setWeight(200);
cameraConfigurations = new ArrayList<>();
for(Class c : ControllerManager.getInstance().getAvailableEvents())
cameraConfigurations.add(new ClassConfigurationData(c));
}
@Override
public Templator httpRespond(
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request)
throws Exception{
DBConnection db = HalContext.getDB();
User localUser = User.getLocalUser(db);
// Save new input
if(request.containsKey("action")){
int id = (ObjectUtil.isEmpty(request.get("id")) ? -1 : Integer.parseInt(request.get("id")));
Camera camera;
switch(request.get("action")) {
case "create_camera":
logger.info("Creating new camera: " + request.get("name"));
camera = new Camera();
camera.setName(request.get("name"));
camera.setType(request.get("type"));
camera.setUser(localUser);
camera.getDeviceConfigurator().setValues(request).applyConfiguration();
camera.save(db);
//ControllerManager.getInstance().register(camera);
HalAlertManager.getInstance().addAlert(new HalAlertManager.HalAlert(
HalAlertManager.AlertLevel.SUCCESS, "Successfully created new camera: " + camera.getName(), HalAlertManager.AlertTTL.ONE_VIEW));
break;
case "modify_camera":
camera = Camera.getCamera(db, id);
if (camera != null) {
logger.info("Modifying camera: " + camera.getName());
camera.setName(request.get("name"));
camera.setType(request.get("type"));
camera.setUser(localUser);
camera.getDeviceConfigurator().setValues(request).applyConfiguration();
camera.save(db);
HalAlertManager.getInstance().addAlert(new HalAlertManager.HalAlert(
HalAlertManager.AlertLevel.SUCCESS, "Successfully saved camera: "+camera.getName(), HalAlertManager.AlertTTL.ONE_VIEW));
} else {
logger.warning("Unknown camera id: " + id);
HalAlertManager.getInstance().addAlert(new HalAlertManager.HalAlert(
HalAlertManager.AlertLevel.ERROR, "Unknown camera id: " + id, HalAlertManager.AlertTTL.ONE_VIEW));
}
break;
case "remove_camera":
camera = Camera.getCamera(db, id);
if (camera != null) {
logger.info("Removing camera: " + camera.getName());
//ControllerManager.getInstance().deregister(camera);
camera.delete(db);
HalAlertManager.getInstance().addAlert(new HalAlertManager.HalAlert(
HalAlertManager.AlertLevel.SUCCESS, "Successfully removed camera: "+camera.getName(), HalAlertManager.AlertTTL.ONE_VIEW));
} else {
logger.warning("Unknown camera id: " + id);
HalAlertManager.getInstance().addAlert(new HalAlertManager.HalAlert(
HalAlertManager.AlertLevel.ERROR, "Unknown camera id: "+id, HalAlertManager.AlertTTL.ONE_VIEW));
}
break;
}
}
// Output
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
tmpl.set("cameras", Camera.getCameras(db));
return tmpl;
}
}

View file

@ -0,0 +1,83 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr.page;
import se.hal.HalContext;
import se.hal.intf.HalWebPage;
import se.hal.plugin.nvr.device.Camera;
import se.hal.struct.Event;
import se.hal.util.DeviceNameComparator;
import zutil.ObjectUtil;
import zutil.db.DBConnection;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
import zutil.parser.Templator;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public class CameraOverviewWebPage extends HalWebPage {
private static final Logger logger = LogUtil.getLogger();
private static final int HISTORY_LIMIT = 200;
private static final String OVERVIEW_TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/camera_overview.tmpl";
private static final String DETAIL_TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/camera_detail.tmpl";
public CameraOverviewWebPage(){
super("camera_overview");
super.getRootNav().createSubNav("Surveillance").createSubNav(this.getId(), "Overview");
}
@Override
public Templator httpRespond(
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request)
throws Exception{
DBConnection db = HalContext.getDB();
int id = (ObjectUtil.isEmpty(request.get("id")) ? -1 : Integer.parseInt(request.get("id")));
// Save new input
if (id >= 0) {
Camera camera = Camera.getCamera(db, id);
Templator tmpl = new Templator(FileUtil.find(DETAIL_TEMPLATE));
tmpl.set("camera", camera);
return tmpl;
}
else {
List<Event> events = Event.getLocalEvents(db);
Collections.sort(events, DeviceNameComparator.getInstance());
Templator tmpl = new Templator(FileUtil.find(OVERVIEW_TEMPLATE));
tmpl.set("events", events);
return tmpl;
}
}
}

View file

@ -0,0 +1,53 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr.page;
import se.hal.HalContext;
import se.hal.intf.HalWebPage;
import se.hal.plugin.nvr.device.Camera;
import zutil.db.DBConnection;
import zutil.io.file.FileUtil;
import zutil.parser.Templator;
import java.util.Map;
public class MonitoringWebPage extends HalWebPage {
private static final String TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/camera_monitor.tmpl";
public MonitoringWebPage() {
super("camera_monitor");
super.getRootNav().createSubNav("Surveillance").createSubNav(this.getId(), "Monitoring").setWeight(-100);
}
@Override
public Templator httpRespond(Map<String, Object> session, Map<String, String> cookie, Map<String, String> request) throws Exception {
DBConnection db = HalContext.getDB();
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
//tmpl.set("cameras", Camera.getCameras(db));
return tmpl;
}
}

View file

@ -0,0 +1,10 @@
{
"version": 0.1,
"name": "Hal-NVR",
"description": "A Network Video Recorder plugin for recording network streams.",
"interfaces": [
{"se.hal.intf.HalWebPage": "se.hal.plugin.nvr.page.CameraConfigWebPage"},
{"se.hal.intf.HalWebPage": "se.hal.plugin.nvr.page.CameraOverviewWebPage"},
{"se.hal.intf.HalWebPage": "se.hal.plugin.nvr.page.MonitoringWebPage"}
]
}

View file

@ -0,0 +1,45 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr.rtsp;
import se.hal.plugin.nvr.HalCameraController;
import se.hal.plugin.nvr.device.HalCameraConfig;
public class RTSPCameraConfig implements HalCameraConfig {
private String rtspUrl;
public RTSPCameraConfig() {}
public RTSPCameraConfig(String rtspUrl) {
this.rtspUrl = rtspUrl;
}
@Override
public Class<? extends HalCameraController> getCameraControllerClass() {
return RTSPController.class;
}
}

View file

@ -0,0 +1,88 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr.rtsp;
import se.hal.plugin.nvr.HalCameraController;
import se.hal.plugin.nvr.device.HalCameraConfig;
import se.hal.plugin.nvr.device.HalCameraReportListener;
import zutil.log.LogUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
public class RTSPController implements HalCameraController {
private static final Logger logger = LogUtil.getLogger();
private static final String CONFIG_RECORDING_PATH = "nvr.recording_path";
private List<RTSPCameraConfig> cameras = new ArrayList<>();
private HalCameraReportListener listener;
public RTSPController() {}
// ----------------------------------------------------
// Lifecycle methods
// ----------------------------------------------------
@Override
public void initialize() throws Exception {
}
@Override
public void close() {
}
// ----------------------------------------------------
// Data methods
// ----------------------------------------------------
@Override
public void register(HalCameraConfig cameraConfig) {
if (cameraConfig instanceof RTSPCameraConfig)
cameras.add((RTSPCameraConfig) cameraConfig);
}
@Override
public void deregister(HalCameraConfig cameraConfig) {
cameras.remove(cameraConfig);
}
@Override
public int size() {
return cameras.size();
}
@Override
public void setListener(HalCameraReportListener listener) {
this.listener = listener;
}
}

View file

@ -0,0 +1,90 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2021 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package se.hal.plugin.nvr;
import com.github.manevolent.ffmpeg4j.FFmpeg;
import com.github.manevolent.ffmpeg4j.FFmpegException;
import com.github.manevolent.ffmpeg4j.FFmpegIO;
import com.github.manevolent.ffmpeg4j.FFmpegInput;
import com.github.manevolent.ffmpeg4j.filter.audio.AudioFilter;
import com.github.manevolent.ffmpeg4j.filter.audio.FFmpegAudioResampleFilter;
import com.github.manevolent.ffmpeg4j.filter.video.FFmpegVideoRescaleFilter;
import com.github.manevolent.ffmpeg4j.filter.video.VideoFilter;
import com.github.manevolent.ffmpeg4j.source.AudioSourceSubstream;
import com.github.manevolent.ffmpeg4j.source.VideoSourceSubstream;
import com.github.manevolent.ffmpeg4j.stream.output.FFmpegTargetStream;
import com.github.manevolent.ffmpeg4j.stream.source.FFmpegSourceStream;
import com.github.manevolent.ffmpeg4j.transcoder.Transcoder;
import java.io.FileOutputStream;
public class RecorderFFmpeg4J {
public static void main(String[] args) throws Exception {
FFmpegIO input = FFmpegIO.openNativeUrlInput("admin:TCZRTY@192.168.10.223:554/H.264");
FFmpegIO output = FFmpegIO.openOutputStream(new FileOutputStream("./video.mp4"), FFmpegIO.DEFAULT_BUFFER_SIZE);
// Open input
FFmpegSourceStream sourceStream = new FFmpegInput(input).open(FFmpeg.getInputFormatByName("h264"));
sourceStream.registerStreams(); // Read the file header, and register substreams in FFmpeg4j
FFmpegTargetStream targetStream = new FFmpegTargetStream(
"h264", // Output format
output,
new FFmpegTargetStream.FFmpegNativeOutput()
);
// Audio
AudioSourceSubstream inoutAudioSubstream =
(AudioSourceSubstream)
sourceStream.getSubstreams().stream().filter(x -> x instanceof AudioSourceSubstream)
.findFirst().orElse(null);
AudioFilter audioFilter = new FFmpegAudioResampleFilter(
inoutAudioSubstream.getFormat(),
null,
FFmpegAudioResampleFilter.DEFAULT_BUFFER_SIZE
);
// Video
VideoSourceSubstream inputVideoSubstream =
(VideoSourceSubstream)
sourceStream.getSubstreams().stream().filter(x -> x instanceof VideoSourceSubstream)
.findFirst().orElse(null);
VideoFilter videoFilter = new FFmpegVideoRescaleFilter(
inputVideoSubstream.getFormat(),
null,
sourceStream.getPixelFormat()
);
if (targetStream.getSubstreams().size() <= 0)
throw new FFmpegException("No substreams to record");
Transcoder.convert(sourceStream, targetStream, audioFilter, videoFilter, 2D);
}
}