Fixed build dist containing the correct structure and be able to build zip files explicitly.
Also fixed some compile warnings
This commit is contained in:
parent
c7f0d4e8b3
commit
1779916d97
111 changed files with 254 additions and 162 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2016 Daniel Collin, Ziver Koc
|
Copyright (c) 2016-2025 Daniel Collin, Ziver Koc
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
51
build.gradle
51
build.gradle
|
|
@ -65,6 +65,11 @@ subprojects {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.compilerArgs << "-Xlint:deprecation"
|
||||||
|
//options.compilerArgs << "-Xlint:unchecked"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
@ -78,34 +83,44 @@ dependencies {
|
||||||
}
|
}
|
||||||
|
|
||||||
distributions {
|
distributions {
|
||||||
distTar.enabled = false
|
|
||||||
distZip.enabled = false
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
contents {
|
contents {
|
||||||
|
// from root project
|
||||||
from 'hal.conf.example'
|
from 'hal.conf.example'
|
||||||
from 'logging.properties'
|
from 'logging.properties'
|
||||||
|
from 'run.sh'
|
||||||
|
|
||||||
from sourceSets.main.output.resourcesDir
|
// from subprojects
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task copyRecources(type: Copy) {
|
|
||||||
doFirst{
|
|
||||||
System.out.println("Copying resource files...")
|
|
||||||
}
|
|
||||||
|
|
||||||
project.subprojects.each { subProject ->
|
project.subprojects.each { subProject ->
|
||||||
from "${subProject.projectDir}/resources"
|
into('bin') {
|
||||||
|
from "${subProject.projectDir}/resources/bin"
|
||||||
|
}
|
||||||
|
into('web') {
|
||||||
|
from "${subProject.projectDir}/resources/web"
|
||||||
|
}
|
||||||
|
into('resources') {
|
||||||
|
from ("${subProject.projectDir}/resources") {
|
||||||
|
exclude 'bin'
|
||||||
|
exclude 'web'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
into(sourceSets.main.output.resourcesDir)
|
distTar.enabled = false
|
||||||
}
|
distZip.enabled = false
|
||||||
|
assemble.dependsOn(installDist)
|
||||||
|
|
||||||
jar.dependsOn(copyRecources)
|
project.gradle.startParameter.taskNames.each { taskName ->
|
||||||
copyRecources.mustRunAfter(processResources)
|
if (taskName == 'distZip') {
|
||||||
|
distZip.enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClass = 'se.hal.HalServer'
|
mainClass = 'se.hal.HalServer'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startScripts.enabled = false
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,3 @@
|
||||||
<!--
|
|
||||||
~ The MIT License (MIT)
|
|
||||||
~
|
|
||||||
~ Copyright (c) 2025 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<h1 class="page-header">Event Configuration</h1>
|
<h1 class="page-header">Event Configuration</h1>
|
||||||
|
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,3 @@
|
||||||
<!--
|
|
||||||
~ The MIT License (MIT)
|
|
||||||
~
|
|
||||||
~ Copyright (c) 2025 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,3 @@
|
||||||
<!--
|
|
||||||
~ The MIT License (MIT)
|
|
||||||
~
|
|
||||||
~ Copyright (c) 2025 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<h1 class="page-header">Sensor Configuration</h1>
|
<h1 class="page-header">Sensor Configuration</h1>
|
||||||
|
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,27 @@
|
||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 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;
|
package se.hal;
|
||||||
|
|
||||||
import zutil.ObjectUtil;
|
import zutil.ObjectUtil;
|
||||||
|
|
@ -22,6 +46,7 @@ public class HalContext {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
public static final String CONFIG_HTTP_PORT = "hal_core.http_port";
|
public static final String CONFIG_HTTP_PORT = "hal_core.http_port";
|
||||||
public static final String CONFIG_HTTP_EXTERNAL_PORT = "hal_core.http_external_port";
|
public static final String CONFIG_HTTP_EXTERNAL_PORT = "hal_core.http_external_port";
|
||||||
public static final String CONFIG_HTTP_EXTERNAL_DOMAIN = "hal_core.http_external_domain";
|
public static final String CONFIG_HTTP_EXTERNAL_DOMAIN = "hal_core.http_external_domain";
|
||||||
|
|
@ -29,22 +54,25 @@ public class HalContext {
|
||||||
public static final String CONFIG_DNS_LOCAL_DOMAIN = "hal_core.dns_local_domain";
|
public static final String CONFIG_DNS_LOCAL_DOMAIN = "hal_core.dns_local_domain";
|
||||||
public static final String CONFIG_MAP_BACKGROUND_IMAGE = "hal_core.map_bgimage";
|
public static final String CONFIG_MAP_BACKGROUND_IMAGE = "hal_core.map_bgimage";
|
||||||
|
|
||||||
public static final String RESOURCE_ROOT;
|
// Path Constants
|
||||||
|
|
||||||
|
public static final String RUNTIME_ROOT;
|
||||||
static {
|
static {
|
||||||
if (FileUtil.find("build/resources/") != null) // Development environment
|
if (FileUtil.find("build/install/Hal") != null) // Development environment
|
||||||
RESOURCE_ROOT = "build/resources";
|
RUNTIME_ROOT = "build/install/Hal";
|
||||||
else if (FileUtil.find("resources/") != null) // Release package environment
|
|
||||||
RESOURCE_ROOT = "resources";
|
|
||||||
else
|
else
|
||||||
RESOURCE_ROOT = ".";
|
RUNTIME_ROOT = ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String RESOURCE_WEB_ROOT = HalContext.RESOURCE_ROOT + "/web";
|
public static final String RESOURCE_ROOT = HalContext.RUNTIME_ROOT + "/resources";
|
||||||
|
public static final String RESOURCE_WEB_ROOT = HalContext.RUNTIME_ROOT + "/web";
|
||||||
|
public static final String RESOURCE_BIN_ROOT = HalContext.RUNTIME_ROOT + "/bin";
|
||||||
|
|
||||||
private static final String CONF_FILE = "hal.conf";
|
private static final String CONF_FILE = RUNTIME_ROOT + "/hal.conf";
|
||||||
static final String DB_FILE = "hal.db";
|
static final String DB_FILE = RUNTIME_ROOT + "/hal.db";
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
|
|
||||||
private static DBConnection db; // TODO: Should probably be a db pool as we have multiple threads accessing the DB
|
private static DBConnection db; // TODO: Should probably be a db pool as we have multiple threads accessing the DB
|
||||||
|
|
||||||
private static HashMap<String,String> registeredConf = new HashMap<>();
|
private static HashMap<String,String> registeredConf = new HashMap<>();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,27 @@
|
||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 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;
|
package se.hal.plugin.nvr.rtsp;
|
||||||
|
|
||||||
import se.hal.HalContext;
|
import se.hal.HalContext;
|
||||||
|
|
@ -21,11 +45,11 @@ import java.util.logging.Logger;
|
||||||
public class RTSPCameraRecorder implements Runnable {
|
public class RTSPCameraRecorder implements Runnable {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
private static final File FFMPEG_BINARY_PATH = FileUtil.find(HalContext.RESOURCE_ROOT + "/bin/");
|
private static final File FFMPEG_BINARY_PATH = FileUtil.find(HalContext.RESOURCE_BIN_ROOT);
|
||||||
|
|
||||||
private RTSPCameraConfig camera;
|
private RTSPCameraConfig camera;
|
||||||
private String storagePath;
|
private String storagePath;
|
||||||
private Process process;
|
private Process ffmpegProcess;
|
||||||
|
|
||||||
|
|
||||||
public RTSPCameraRecorder(RTSPCameraConfig camera, String storagePath) {
|
public RTSPCameraRecorder(RTSPCameraConfig camera, String storagePath) {
|
||||||
|
|
@ -64,42 +88,46 @@ public class RTSPCameraRecorder implements Runnable {
|
||||||
"-var_stream_map \"v:0,a:0,name:Source v:1,a:1,name:720p v:2,a:2,name:360p\""
|
"-var_stream_map \"v:0,a:0,name:Source v:1,a:1,name:720p v:2,a:2,name:360p\""
|
||||||
);*/
|
);*/
|
||||||
ffmpegOutput.addAdditionalArg(
|
ffmpegOutput.addAdditionalArg(
|
||||||
"-c:v:0 libx264 -x264-params \"nal-hrd=cbr:force-cfr=1\" -b:v:0 5M -maxrate:v:0 5M -minrate:v:0 5M -bufsize:v:0 10M -preset veryfast -g 25 -sc_threshold 0"
|
"-c:v:0", "libx264",
|
||||||
|
"-x264-params", "nal-hrd=cbr:force-cfr=1",
|
||||||
|
"-b:v:0", "5M",
|
||||||
|
"-maxrate:v:0", "5M",
|
||||||
|
"-minrate:v:0", "5M",
|
||||||
|
"-bufsize:v:0", "10M",
|
||||||
|
"-preset", "veryfast",
|
||||||
|
"-g", "25",
|
||||||
|
"-sc_threshold", "0"
|
||||||
);
|
);
|
||||||
ffmpegOutput.addAdditionalArg("-f hls",
|
ffmpegOutput.addAdditionalArg("-f", "hls",
|
||||||
"-hls_time 2", // segment length in seconds
|
"-hls_time", "2", // segment length in seconds
|
||||||
//"-hls_playlist_type event", // Do not delete old segments
|
//"-hls_playlist_type", "event", // Do not delete old segments
|
||||||
"-hls_flags independent_segments+delete_segments",
|
"-hls_flags", "independent_segments+delete_segments",
|
||||||
"-hls_segment_type mpegts",
|
"-hls_segment_type", "mpegts",
|
||||||
"-hls_segment_filename \"" + new File(storagePath, "stream_%v/data%02d.ts").getPath() + "\"",
|
"-hls_segment_filename", new File(storagePath, "stream_%v/data%02d.ts").getPath(),
|
||||||
"-master_pl_name \"playlist.m3u8\""
|
"-master_pl_name", "playlist.m3u8"
|
||||||
);
|
);
|
||||||
|
|
||||||
FFmpeg ffmpeg = new FFmpeg();
|
FFmpeg ffmpeg = new FFmpeg();
|
||||||
ffmpeg.setLogLevel(FFmpegConstants.FFmpegLogLevel.ERROR);
|
ffmpeg.setLogLevel(FFmpegConstants.FFmpegLogLevel.ERROR);
|
||||||
ffmpeg.addInput(ffmpegInput);
|
ffmpeg.addInput(ffmpegInput);
|
||||||
ffmpeg.addOutput(ffmpegOutput);
|
ffmpeg.addOutput(ffmpegOutput);
|
||||||
String cmdParams = ffmpeg.buildCommand();
|
|
||||||
|
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
// Execute command
|
// Execute command
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
|
||||||
File cmdPath = OSALBinaryManager.getPath(FFMPEG_BINARY_PATH, "ffmpeg");
|
|
||||||
|
|
||||||
String cmd = cmdPath.getParent() + File.separator + cmdParams;
|
|
||||||
logger.finest("Executing ffmpeg: " + cmd);
|
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (process != null) process.destroyForcibly();
|
if (ffmpegProcess != null) ffmpegProcess.destroyForcibly();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
process = Runtime.getRuntime().exec(cmd);
|
File cmdPath = OSALBinaryManager.getPath(FFMPEG_BINARY_PATH, "ffmpeg");
|
||||||
BufferedReader output = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
ffmpegProcess = ffmpeg.execute(cmdPath);
|
||||||
|
|
||||||
while (process.isAlive()) {
|
BufferedReader output = new BufferedReader(new InputStreamReader(ffmpegProcess.getInputStream()));
|
||||||
|
|
||||||
|
while (ffmpegProcess.isAlive()) {
|
||||||
String line;
|
String line;
|
||||||
while ((line = output.readLine()) != null) {
|
while ((line = output.readLine()) != null) {
|
||||||
logger.finest("[Cam: " + camera.getRtspUrl() + "] " + line);
|
logger.finest("[Cam: " + camera.getRtspUrl() + "] " + line);
|
||||||
|
|
@ -107,6 +135,7 @@ public class RTSPCameraRecorder implements Runnable {
|
||||||
|
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
output.close();
|
output.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "RTSP Stream recording thread has crashed for: " + camera.getRtspUrl(), e);
|
logger.log(Level.SEVERE, "RTSP Stream recording thread has crashed for: " + camera.getRtspUrl(), e);
|
||||||
|
|
@ -124,10 +153,10 @@ public class RTSPCameraRecorder implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
if (process != null) {
|
if (ffmpegProcess != null) {
|
||||||
logger.info("Killing ffmpeg instance.");
|
logger.info("Killing FFmpeg instance.");
|
||||||
camera = null;
|
camera = null;
|
||||||
process.destroy();
|
ffmpegProcess.destroyForcibly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,27 @@
|
||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 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.raspberry.hardware;
|
package se.hal.plugin.raspberry.hardware;
|
||||||
|
|
||||||
import com.pi4j.io.gpio.*;
|
import com.pi4j.io.gpio.*;
|
||||||
|
|
@ -32,7 +56,7 @@ public class RPiInteruptPulseFlankCounter implements Runnable, GpioPinListenerDi
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
this.gpioPin = gpioPin;
|
this.gpioPin = gpioPin;
|
||||||
|
|
||||||
// setup a thread pool for executing jobs
|
// Setup a thread pool for executing jobs
|
||||||
this.executorPool = Executors.newCachedThreadPool();
|
this.executorPool = Executors.newCachedThreadPool();
|
||||||
|
|
||||||
//Enable non privileged access to the GPIO pins (no sudo required from now)
|
//Enable non privileged access to the GPIO pins (no sudo required from now)
|
||||||
|
|
@ -45,9 +69,6 @@ public class RPiInteruptPulseFlankCounter implements Runnable, GpioPinListenerDi
|
||||||
} catch(IllegalArgumentException e) {
|
} catch(IllegalArgumentException e) {
|
||||||
logger.log(Level.SEVERE, "", e);
|
logger.log(Level.SEVERE, "", e);
|
||||||
throw e;
|
throw e;
|
||||||
}catch(UnsatisfiedLinkError e) {
|
|
||||||
logger.log(Level.SEVERE, "", e);
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// provision gpio pin as an input pin with its internal pull up resistor enabled
|
// provision gpio pin as an input pin with its internal pull up resistor enabled
|
||||||
|
|
@ -73,9 +94,8 @@ public class RPiInteruptPulseFlankCounter implements Runnable, GpioPinListenerDi
|
||||||
@Override
|
@Override
|
||||||
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
|
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
|
||||||
if (event.getState() == PinState.LOW) { //low = light went on
|
if (event.getState() == PinState.LOW) { //low = light went on
|
||||||
//System.out.println("IR LED turned ON");
|
|
||||||
//logger.log(Level.INFO, "IR LED turned on");
|
//logger.log(Level.INFO, "IR LED turned on");
|
||||||
synchronized(impulseCount) {
|
synchronized(this) {
|
||||||
impulseCount++;
|
impulseCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -84,19 +104,24 @@ public class RPiInteruptPulseFlankCounter implements Runnable, GpioPinListenerDi
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
long startTime = System.nanoTime();
|
long startTime = System.nanoTime();
|
||||||
synchronized(impulseCount) {
|
|
||||||
|
synchronized(this) {
|
||||||
impulseCount = 0; //reset the impulse count
|
impulseCount = 0; //reset the impulse count
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!executorPool.isShutdown()) {
|
while (!executorPool.isShutdown()) {
|
||||||
sleepNano(nanoSecondsSleep); //sleep for some time. This variable will be modified every loop to compensate for the loop time spent.
|
sleepNano(nanoSecondsSleep); //sleep for some time. This variable will be modified every loop to compensate for the loop time spent.
|
||||||
int count = -1;
|
int count = -1;
|
||||||
synchronized(impulseCount) {
|
|
||||||
|
synchronized(this) {
|
||||||
count = impulseCount;
|
count = impulseCount;
|
||||||
impulseCount = 0;
|
impulseCount = 0;
|
||||||
}
|
}
|
||||||
save(System.currentTimeMillis(), count); //save the impulse count
|
|
||||||
|
report(count, System.currentTimeMillis()); //save the impulse count
|
||||||
long estimatedNanoTimeSpent = System.nanoTime() - startTime; //this is where the loop ends
|
long estimatedNanoTimeSpent = System.nanoTime() - startTime; //this is where the loop ends
|
||||||
startTime = System.nanoTime(); //this is where the loop starts from now on
|
startTime = System.nanoTime(); //this is where the loop starts from now on
|
||||||
|
|
||||||
if (estimatedNanoTimeSpent > 0) { //if no overflow
|
if (estimatedNanoTimeSpent > 0) { //if no overflow
|
||||||
long nanoSecondsTooMany = estimatedNanoTimeSpent - (REPORT_TIMEOUT*1000000L);
|
long nanoSecondsTooMany = estimatedNanoTimeSpent - (REPORT_TIMEOUT*1000000L);
|
||||||
//System.out.println("the look took ~" + estimatedNanoTimeSpent + "ns. That is " + nanoSecondsTooMany/1000000L + "ms off");
|
//System.out.println("the look took ~" + estimatedNanoTimeSpent + "ns. That is " + nanoSecondsTooMany/1000000L + "ms off");
|
||||||
|
|
@ -107,10 +132,10 @@ public class RPiInteruptPulseFlankCounter implements Runnable, GpioPinListenerDi
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sleep for [ns] nanoseconds
|
* Sleep for [ns] nanoseconds
|
||||||
* @param ns
|
*
|
||||||
|
* @param ns nanoseconds to sleep
|
||||||
*/
|
*/
|
||||||
private void sleepNano(long ns) {
|
private void sleepNano(long ns) {
|
||||||
//System.out.println("will go to sleep for " + ns + "ns");
|
|
||||||
try{
|
try{
|
||||||
Thread.sleep(ns/1000000L, (int)(ns%1000000L));
|
Thread.sleep(ns/1000000L, (int)(ns%1000000L));
|
||||||
}catch(InterruptedException e) {
|
}catch(InterruptedException e) {
|
||||||
|
|
@ -119,25 +144,21 @@ public class RPiInteruptPulseFlankCounter implements Runnable, GpioPinListenerDi
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the data to the database.
|
* Report back some data to Hal Core,
|
||||||
* This method should block the caller as short time as possible.
|
|
||||||
* This method should try block the same amount of time every time it is called.
|
|
||||||
* Try to make the time spent in the method the same for every call (low variation).
|
|
||||||
*
|
*
|
||||||
* @param timestamp_end
|
* @param data The data to report back to Hal.
|
||||||
* @param data
|
* @param timestamp The timestamp of the received data
|
||||||
*/
|
*/
|
||||||
private void save(final long timestamp_end, final int data) {
|
private void report(final int data, final long timestamp) {
|
||||||
//offload the timed loop by not doing the db interaction in this thread.
|
// Offload the timed loop by not doing the db interaction in this thread.
|
||||||
executorPool.execute(new Runnable() {
|
executorPool.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
logger.log(Level.INFO, "Reporting data. timestamp_end="+timestamp_end+", data="+data);
|
logger.log(Level.INFO, "Reporting data. timestamp_end=" + timestamp + ", data=" + data);
|
||||||
controller.sendDataReport(
|
controller.sendDataReport(
|
||||||
new RPiPowerConsumptionSensor(gpioPin),
|
new RPiPowerConsumptionSensor(gpioPin),
|
||||||
new PowerConsumptionSensorData(
|
new PowerConsumptionSensorData(data, timestamp)
|
||||||
timestamp_end, data
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Ziver
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2025 Ziver Koc
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -113,7 +115,7 @@ public class TellstickParser {
|
||||||
|
|
||||||
public static void registerProtocol(Class<? extends TellstickProtocol> protClass) {
|
public static void registerProtocol(Class<? extends TellstickProtocol> protClass) {
|
||||||
try {
|
try {
|
||||||
registerProtocol(protClass.newInstance());
|
registerProtocol(protClass.getDeclaredConstructor().newInstance());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, null, e);
|
logger.log(Level.SEVERE, null, e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,27 @@
|
||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 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.zigbee;
|
package se.hal.plugin.zigbee;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -110,7 +134,7 @@ public class ZigbeeController implements HalSensorController,
|
||||||
// Register extensions
|
// Register extensions
|
||||||
|
|
||||||
ZigBeeDiscoveryExtension discoveryExtension = new ZigBeeDiscoveryExtension();
|
ZigBeeDiscoveryExtension discoveryExtension = new ZigBeeDiscoveryExtension();
|
||||||
discoveryExtension.setUpdatePeriod(86400); // in seconds, 24h
|
discoveryExtension.setUpdateMeshPeriod(86400); // in seconds, 24h
|
||||||
|
|
||||||
networkManager.addExtension(discoveryExtension);
|
networkManager.addExtension(discoveryExtension);
|
||||||
networkManager.addExtension(new ZigBeeOtaUpgradeExtension());
|
networkManager.addExtension(new ZigBeeOtaUpgradeExtension());
|
||||||
|
|
@ -404,7 +428,7 @@ public class ZigbeeController implements HalSensorController,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attributeUpdated(ZclAttribute attribute, Object value) {
|
public void attributeUpdated(ZclAttribute attribute, Object value) {
|
||||||
logger.finer("[Node: " + endpoint.getIeeeAddress() + ", Endpoint: " + endpoint.getEndpointId() + ", Cluster: " + attribute.getCluster().getId() + "] Attribute " + config.getClass().getSimpleName() + " updated: id=" + attribute.getId() + ", attribute_name=" + attribute.getName() + ", value=" + attribute.getLastValue());
|
logger.finer("[Node: " + endpoint.getIeeeAddress() + ", Endpoint: " + endpoint.getEndpointId() + ", Cluster: " + attribute.getClusterType().getId() + "] Attribute " + config.getClass().getSimpleName() + " updated: id=" + attribute.getId() + ", attribute_name=" + attribute.getName() + ", value=" + attribute.getLastValue());
|
||||||
|
|
||||||
HalDeviceData data = config.getDeviceData(endpoint, attribute);
|
HalDeviceData data = config.getDeviceData(endpoint, attribute);
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue