From da3ba116dac69e962cc3298322b17536a24dc868 Mon Sep 17 00:00:00 2001 From: Ziver Koc Date: Tue, 26 Jan 2021 01:53:11 +0100 Subject: [PATCH] initial commit for NVR plugin --- plugins/hal-nvr/build.gradle | 12 ++ .../resource/resource/web/camera_config.tmpl | 123 ++++++++++++++++ .../resource/resource/web/camera_detail.tmpl | 42 ++++++ .../resource/resource/web/camera_monitor.tmpl | 39 +++++ .../resource/web/camera_overview.tmpl | 26 ++++ .../hal/plugin/nvr/HalCameraController.java | 48 +++++++ .../src/se/hal/plugin/nvr/StreamRecorder.java | 29 ++++ .../src/se/hal/plugin/nvr/device/Camera.java | 56 ++++++++ .../plugin/nvr/device/HalCameraConfig.java | 36 +++++ .../hal/plugin/nvr/device/HalCameraData.java | 40 ++++++ .../nvr/device/HalCameraReportListener.java | 10 ++ .../plugin/nvr/page/CameraConfigWebPage.java | 134 ++++++++++++++++++ .../nvr/page/CameraOverviewWebPage.java | 83 +++++++++++ .../plugin/nvr/page/MonitoringWebPage.java | 53 +++++++ .../hal-nvr/src/se/hal/plugin/nvr/plugin.json | 10 ++ .../hal/plugin/nvr/rtsp/RTSPCameraConfig.java | 45 ++++++ .../hal/plugin/nvr/rtsp/RTSPController.java | 88 ++++++++++++ .../se/hal/plugin/nvr/RecorderFFmpeg4J.java | 90 ++++++++++++ 18 files changed, 964 insertions(+) create mode 100644 plugins/hal-nvr/build.gradle create mode 100644 plugins/hal-nvr/resource/resource/web/camera_config.tmpl create mode 100644 plugins/hal-nvr/resource/resource/web/camera_detail.tmpl create mode 100644 plugins/hal-nvr/resource/resource/web/camera_monitor.tmpl create mode 100644 plugins/hal-nvr/resource/resource/web/camera_overview.tmpl create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/HalCameraController.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/StreamRecorder.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/device/Camera.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraConfig.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraData.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraReportListener.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/page/CameraConfigWebPage.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/page/CameraOverviewWebPage.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/page/MonitoringWebPage.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/plugin.json create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/rtsp/RTSPCameraConfig.java create mode 100644 plugins/hal-nvr/src/se/hal/plugin/nvr/rtsp/RTSPController.java create mode 100644 plugins/hal-nvr/test/se/hal/plugin/nvr/RecorderFFmpeg4J.java diff --git a/plugins/hal-nvr/build.gradle b/plugins/hal-nvr/build.gradle new file mode 100644 index 00000000..20085bc1 --- /dev/null +++ b/plugins/hal-nvr/build.gradle @@ -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 +} diff --git a/plugins/hal-nvr/resource/resource/web/camera_config.tmpl b/plugins/hal-nvr/resource/resource/web/camera_config.tmpl new file mode 100644 index 00000000..f82fd508 --- /dev/null +++ b/plugins/hal-nvr/resource/resource/web/camera_config.tmpl @@ -0,0 +1,123 @@ +

Camera Configuration

+ +
+
+
Cameras
+
+

This is a list of cameras connected to this node.

+ + + + + + + + + {{#cameras}} + + + + + + + {{/cameras}} +
NameTypeConfiguration + +
{{.getName()}}{{.getType()}}{{.getDeviceConfig()}} +
+ + +
+ + + +
+
+
+
+
+
+ + + + + + + + + diff --git a/plugins/hal-nvr/resource/resource/web/camera_detail.tmpl b/plugins/hal-nvr/resource/resource/web/camera_detail.tmpl new file mode 100644 index 00000000..3e3f7007 --- /dev/null +++ b/plugins/hal-nvr/resource/resource/web/camera_detail.tmpl @@ -0,0 +1,42 @@ +

Details for {{camera.getName()}}

+ +
+ +
+ +
+
+
Configuration
+
+ + + + + + + + + + + + + + + + + + + + {{#camera.getDeviceConfigurator().getConfiguration()}} + + + + + {{/camera.getDeviceConfigurator().getConfiguration()}} +
Camera ID:{{camera.getId()}}
Name:{{camera.getName()}}
Type:{{camera.getDeviceData().getClass().getSimpleName()}}
Owner:{{camera.getUser().getUsername()}}

{{.getNiceName()}}:{{.getString()}}
+
+
+
diff --git a/plugins/hal-nvr/resource/resource/web/camera_monitor.tmpl b/plugins/hal-nvr/resource/resource/web/camera_monitor.tmpl new file mode 100644 index 00000000..45f57780 --- /dev/null +++ b/plugins/hal-nvr/resource/resource/web/camera_monitor.tmpl @@ -0,0 +1,39 @@ +

Camera Monitor

+ + + +
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
\ No newline at end of file diff --git a/plugins/hal-nvr/resource/resource/web/camera_overview.tmpl b/plugins/hal-nvr/resource/resource/web/camera_overview.tmpl new file mode 100644 index 00000000..ce467306 --- /dev/null +++ b/plugins/hal-nvr/resource/resource/web/camera_overview.tmpl @@ -0,0 +1,26 @@ +

Camera Overview

+ +
+
+
Cameras
+
+ + + + + + + + + {{#cameras}} + + + + + + + {{/cameras}} +
NameTypeDataLast Update
{{.getName()}}{{.getDeviceConfig().getClass().getSimpleName()}}{{.getDeviceData()}}{{.getDeviceData().getTimestamp()}}
+
+
+
diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/HalCameraController.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/HalCameraController.java new file mode 100644 index 00000000..158eaf5f --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/HalCameraController.java @@ -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); +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/StreamRecorder.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/StreamRecorder.java new file mode 100644 index 00000000..1e63f732 --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/StreamRecorder.java @@ -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 { + +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/device/Camera.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/device/Camera.java new file mode 100644 index 00000000..6332c301 --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/device/Camera.java @@ -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 { + + public static List 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 getController() { + return getDeviceConfig().getCameraControllerClass(); + } + + @Override + protected HalCameraData getLatestDeviceData(DBConnection db) { + return null; + } +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraConfig.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraConfig.java new file mode 100644 index 00000000..88d80f23 --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraConfig.java @@ -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 getCameraControllerClass(); + +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraData.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraData.java new file mode 100644 index 00000000..08a48d32 --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraData.java @@ -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) { + + } +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraReportListener.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraReportListener.java new file mode 100644 index 00000000..40107ac1 --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/device/HalCameraReportListener.java @@ -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 { + +} \ No newline at end of file diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/page/CameraConfigWebPage.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/page/CameraConfigWebPage.java new file mode 100644 index 00000000..c50d2b23 --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/page/CameraConfigWebPage.java @@ -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 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 session, + Map cookie, + Map 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; + + } +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/page/CameraOverviewWebPage.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/page/CameraOverviewWebPage.java new file mode 100644 index 00000000..77c62320 --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/page/CameraOverviewWebPage.java @@ -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 session, + Map cookie, + Map 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 events = Event.getLocalEvents(db); + Collections.sort(events, DeviceNameComparator.getInstance()); + + Templator tmpl = new Templator(FileUtil.find(OVERVIEW_TEMPLATE)); + tmpl.set("events", events); + return tmpl; + } + } +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/page/MonitoringWebPage.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/page/MonitoringWebPage.java new file mode 100644 index 00000000..5b2800b6 --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/page/MonitoringWebPage.java @@ -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 session, Map cookie, Map request) throws Exception { + DBConnection db = HalContext.getDB(); + + Templator tmpl = new Templator(FileUtil.find(TEMPLATE)); + //tmpl.set("cameras", Camera.getCameras(db)); + + return tmpl; + } +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/plugin.json b/plugins/hal-nvr/src/se/hal/plugin/nvr/plugin.json new file mode 100644 index 00000000..4f8881ba --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/plugin.json @@ -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"} + ] +} \ No newline at end of file diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/rtsp/RTSPCameraConfig.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/rtsp/RTSPCameraConfig.java new file mode 100644 index 00000000..8f0f010c --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/rtsp/RTSPCameraConfig.java @@ -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 getCameraControllerClass() { + return RTSPController.class; + } +} diff --git a/plugins/hal-nvr/src/se/hal/plugin/nvr/rtsp/RTSPController.java b/plugins/hal-nvr/src/se/hal/plugin/nvr/rtsp/RTSPController.java new file mode 100644 index 00000000..fbd882b7 --- /dev/null +++ b/plugins/hal-nvr/src/se/hal/plugin/nvr/rtsp/RTSPController.java @@ -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 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; + } + +} diff --git a/plugins/hal-nvr/test/se/hal/plugin/nvr/RecorderFFmpeg4J.java b/plugins/hal-nvr/test/se/hal/plugin/nvr/RecorderFFmpeg4J.java new file mode 100644 index 00000000..db537b13 --- /dev/null +++ b/plugins/hal-nvr/test/se/hal/plugin/nvr/RecorderFFmpeg4J.java @@ -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); + } +} \ No newline at end of file