io.rhiot.gateway.camel.webcam.WebcamComponent Maven / Gradle / Ivy
The newest version!
/**
* Licensed to the Rhiot under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.rhiot.gateway.camel.webcam;
import java.awt.*;
import java.lang.reflect.Constructor;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
import com.github.sarxos.webcam.*;
import com.github.sarxos.webcam.ds.v4l4j.V4l4jDriver;
import io.rhiot.utils.install.DefaultInstaller;
import io.rhiot.utils.install.Installer;
import io.rhiot.utils.process.DefaultProcessManager;
import io.rhiot.utils.process.ProcessManager;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.impl.UriEndpointComponent;
import org.slf4j.Logger;
import static java.lang.Thread.sleep;
import static org.apache.commons.lang3.SystemUtils.IS_OS_LINUX;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Represents the component that manages {@link WebcamEndpoint}.
*/
public class WebcamComponent extends UriEndpointComponent implements WebcamDiscoveryListener {
private static final Logger LOG = getLogger(WebcamComponent.class);
private Map webcams = new HashMap<>();
private int timeout = 30000;
private String driver;
private int webcamRestartInterval = 5000;
private boolean webcamStarted;
private String v4l2WebcamLoadingCommand = WebcamConstants.V4L2_WEBCAM_LOADING_COMMAND;
private Installer installer;
private String requiredPackages = WebcamConstants.WEBCAM_DEPENDENCIES_LINUX;
private ProcessManager processManager;
private boolean ignoreInstallerProblems = true;
public WebcamComponent() {
super(WebcamEndpoint.class);
}
public WebcamComponent(CamelContext context) {
super(context, WebcamEndpoint.class);
}
protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception {
Endpoint endpoint = new WebcamEndpoint(uri, this);
setProperties(endpoint, parameters);
return endpoint;
}
// Life-cycle
@Override
protected void doStart() throws Exception {
super.doStart();
installer = resolveInstaller();
String requiredPackages = getRequiredPackages();
try {
if (!installer.install(requiredPackages) && !ignoreInstallerProblems) {
throw new IllegalStateException("Unable to start webcam, failed to install dependencies");
}
} catch (Exception ex) {
if(ignoreInstallerProblems) {
LOG.warn(ex.getMessage());
} else {
throw ex;
}
}
//Use the provided webcam/s
if (getWebcams().size() == 0) {
loadWebcamDriver();
List webcamList = Webcam.getWebcams(timeout);
if (webcamList == null || webcamList.size() == 0) {
throw new IllegalStateException("No webcams found");
}
webcamList.forEach(w -> webcams.put(w.getDevice().getName(), w));
LOG.info("Detected webcams : {}", webcams.keySet());
}
}
protected void loadWebcamDriver() {
if (webcamStarted) {
return;
}
try {
// use specified driver
if (getDriver() != null) {
Class clazz = (Class) Class.forName(getDriver());
Constructor constructor = clazz.getConstructor();
WebcamDriver driver = constructor.newInstance();
LOG.debug("Using specified driver [{}]", driver);
Webcam.setDriver(driver);
webcamStarted = true;
} else if (IS_OS_LINUX) {
try {
processManager = resolveProcessManager();
do {
LOG.debug("Loading v4l2 module");
List v4l2Result = processManager.executeAndJoinOutput("/bin/sh", "-c", getV4l2WebcamLoadingCommand());
if (v4l2Result.contains("FATAL: Module bcm2835-v4l2 not found.")) {
throw new RuntimeException("Video for Linux module is not installed");
} else if (v4l2Result.contains("ERROR: could not insert 'bcm2835_v4l2': Operation not permitted")){
throw new RuntimeException("User has insufficient privileges to load Video for Linux module");
}
processManager.executeAndJoinOutput("/bin/sh", "-c", WebcamConstants.V4L2_SET_FORMAT_JPEG_COMMAND);
v4l2Result = processManager.executeAndJoinOutput("/bin/sh", "-c", WebcamConstants.V4L2_LIST_DEVICES_COMMAND);
LOG.info("Result of V4L2 listing devices {}", v4l2Result);
List failureToOpen = v4l2Result.stream().filter(e -> e.contains("Failed to open")).collect(Collectors.toList());
if (failureToOpen.size() == 0) {
webcamStarted = true;
Webcam.setDriver(new V4l4jDriver());
} else {
throw new RuntimeException(failureToOpen.get(0));
}
sleep(webcamRestartInterval);
} while (!webcamStarted);
} catch (Error e) {
LOG.error("Failed to install and configure the v4l driver", e);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected ProcessManager resolveProcessManager() {
LOG.debug("Started resolving ProcessManager...");
if(processManager != null) {
LOG.debug("ProcessManager has been set on the component level. Camel will use it: {}", processManager);
return processManager;
}
Set processManagers = getCamelContext().getRegistry().findByType(ProcessManager.class);
if(processManagers.isEmpty()) {
LOG.debug("No ProcessManager found in the registry - creating new DefaultProcessManager.");
return new DefaultProcessManager();
} else if(processManagers.size() == 1) {
return processManagers.iterator().next();
} else {
return new DefaultProcessManager();
}
}
protected Installer resolveInstaller() {
LOG.debug("Started resolving Installer...");
if(installer != null) {
LOG.debug("Installer has been set on the component level. Camel will use it: {}", installer);
return installer;
}
Set installers = getCamelContext().getRegistry().findByType(Installer.class);
if(installers.isEmpty()) {
LOG.debug("No Installer found in the registry - creating new DefaultInstaller.");
return new DefaultInstaller();
} else if(installers.size() == 1) {
return installers.iterator().next();
} else {
return new DefaultInstaller();
}
}
@Override
protected void doStop() throws Exception {
webcams.values().forEach(w -> w.close());
super.doStop();
}
// Webcam listeners
@Override
public void webcamFound(WebcamDiscoveryEvent event) {
Webcam webcam = event.getWebcam();
LOG.debug("Discovered webcam : {}", webcam.getDevice().getName());
webcams.put(webcam.getDevice().getName(), webcam);
}
@Override
public void webcamGone(WebcamDiscoveryEvent event) {
LOG.info("Webcam : {} is gone", event.getWebcam().getDevice().getName());
webcams.remove(event.getWebcam().getDevice().getName());
}
/**
* Returns the webcam by name, null if not found.
* @param name webcam name
* @return webcam instance
*/
public Webcam getWebcam(String name, Dimension dimension) {
if (name == null) {
return getWebcam(dimension);
}
Webcam webcam = webcams.get(name);
openWebcam(webcam, dimension);
return webcam;
}
/**
* Returns the first webcam.
*/
public Webcam getWebcam(Dimension dimension) {
if (webcams.size() == 0) {
throw new IllegalStateException("No webcams found");
}
Webcam webcam = webcams.values().iterator().next();
openWebcam(webcam, dimension);
return webcam;
}
private Webcam openWebcam(Webcam webcam, Dimension dimension) {
//Once started another endpoint may want to change from low res to high res, for example
if (webcam.isOpen() && isStarted() && !dimension.equals(webcam.getViewSize())) {
webcam.close();
}
if (!webcam.isOpen() && dimension != null) {
webcam.setCustomViewSizes(new Dimension[]{dimension});
webcam.setViewSize(dimension);
webcam.open(true);
} else if (!webcam.isOpen()) {
webcam.open(true);
}
return webcam;
}
/**
* Returns the list of webcams
*/
protected List getWebcamNames(){
return new ArrayList(webcams.keySet());
}
public Map getWebcams() {
return webcams;
}
public void setWebcams(Map webcams) {
this.webcams = webcams;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public ProcessManager getProcessManager() {
return processManager;
}
public void setProcessManager(ProcessManager processManager) {
this.processManager = processManager;
}
public String getV4l2WebcamLoadingCommand() {
return v4l2WebcamLoadingCommand;
}
public void setV4l2WebcamLoadingCommand(String v4l2WebcamLoadingCommand) {
this.v4l2WebcamLoadingCommand = v4l2WebcamLoadingCommand;
}
public Installer getInstaller() {
return installer;
}
public void setInstaller(Installer installer) {
this.installer = installer;
}
public String getRequiredPackages() {
return requiredPackages;
}
public void setRequiredPackages(String requiredPackages) {
this.requiredPackages = requiredPackages;
}
public boolean isIgnoreInstallerProblems() {
return ignoreInstallerProblems;
}
public void setIgnoreInstallerProblems(boolean ignoreInstallerProblems) {
this.ignoreInstallerProblems = ignoreInstallerProblems;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy