added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.ftpupload-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-binding-ftpupload" description="FTP Upload Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.ftpupload/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link FtpUploadBinding} class defines common constants, which are
* used across the whole binding.
*
* @author Pauli Anttila - Initial contribution
*/
@NonNullByDefault
public class FtpUploadBindingConstants {
public static final String BINDING_ID = "ftpupload";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_IMAGERECEIVER = new ThingTypeUID(BINDING_ID, "imagereceiver");
// List of all Channel ids
public static final String IMAGE = "image";
public static final String IMAGE_RECEIVED_TRIGGER = "image-received";
// List of all channel parameters
public static final String PARAM_FILENAME_PATTERN = "filename";
public static final String EVENT_IMAGE_RECEIVED = "IMAGE_RECEIVED";
}

View File

@@ -0,0 +1,131 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal;
import static org.openhab.binding.ftpupload.internal.FtpUploadBindingConstants.THING_TYPE_IMAGERECEIVER;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.ftpserver.FtpServerConfigurationException;
import org.apache.ftpserver.ftplet.FtpException;
import org.openhab.binding.ftpupload.internal.ftp.FtpServer;
import org.openhab.binding.ftpupload.internal.handler.FtpUploadHandler;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingStatusInfo;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link FtpUploadHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Pauli Anttila - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.ftpupload")
public class FtpUploadHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(FtpUploadHandlerFactory.class);
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_IMAGERECEIVER);
private final int DEFAULT_PORT = 2121;
private final int DEFAULT_IDLE_TIMEOUT = 60;
private FtpServer ftpServer;
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}
@Override
protected ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(THING_TYPE_IMAGERECEIVER)) {
if (ftpServer.getStartUpErrorReason() != null) {
thing.setStatusInfo(new ThingStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
ftpServer.getStartUpErrorReason()));
}
return new FtpUploadHandler(thing, ftpServer);
}
return null;
}
@Override
protected synchronized void activate(ComponentContext componentContext) {
super.activate(componentContext);
ftpServer = new FtpServer();
modified(componentContext);
}
@Override
protected synchronized void deactivate(ComponentContext componentContext) {
stopFtpServer();
ftpServer = null;
super.deactivate(componentContext);
}
protected synchronized void modified(ComponentContext componentContext) {
stopFtpServer();
Dictionary<String, Object> properties = componentContext.getProperties();
int port = DEFAULT_PORT;
int idleTimeout = DEFAULT_IDLE_TIMEOUT;
if (properties.get("port") != null) {
String strPort = properties.get("port").toString();
if (StringUtils.isNotEmpty(strPort)) {
try {
port = Integer.valueOf(strPort);
} catch (NumberFormatException e) {
logger.warn("Invalid port number '{}', using default port {}", strPort, port);
}
}
}
if (properties.get("idleTimeout") != null) {
String strIdleTimeout = properties.get("idleTimeout").toString();
if (StringUtils.isNotEmpty(strIdleTimeout)) {
try {
idleTimeout = Integer.valueOf(strIdleTimeout);
} catch (NumberFormatException e) {
logger.warn("Invalid idle timeout '{}', using default timeout {}", strIdleTimeout, idleTimeout);
}
}
}
try {
logger.debug("Starting FTP server, port={}, idleTimeout={}", port, idleTimeout);
ftpServer.startServer(port, idleTimeout);
} catch (FtpException | FtpServerConfigurationException e) {
logger.warn("FTP server starting failed, reason: {}", e.getMessage());
}
}
private void stopFtpServer() {
logger.debug("Stopping FTP server");
ftpServer.stopServer();
}
}

View File

@@ -0,0 +1,35 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal.config;
/**
* Configuration class for {@link FtpUploadBinding} device.
*
* @author Pauli Anttila - Initial contribution
*/
public class FtpUploadConfig {
public String userName;
public String password;
@Override
public String toString() {
String str = "";
str += "userName = " + userName;
str += ", password = *****";
return str;
}
}

View File

@@ -0,0 +1,87 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal.ftp;
import java.util.List;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.AuthorizationRequest;
import org.apache.ftpserver.ftplet.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Simple FTP user implementation.
*
*
* @author Pauli Anttila - Initial contribution
*/
public class FTPUser implements User {
private static Logger logger = LoggerFactory.getLogger(FTPUser.class);
private final String login;
private int idleTimeout;
public FTPUser(String login, int idleTimeout) {
this.login = login;
this.idleTimeout = idleTimeout;
}
@Override
public AuthorizationRequest authorize(final AuthorizationRequest authRequest) {
logger.trace("authorize: {}", authRequest);
return authRequest;
}
@Override
public boolean getEnabled() {
logger.trace("getEnabled");
return true;
}
@Override
public String getHomeDirectory() {
logger.trace("getHomeDirectory");
return "/";
}
@Override
public int getMaxIdleTime() {
logger.trace("getMaxIdleTime");
return idleTimeout;
}
@Override
public String getName() {
logger.trace("getName");
return this.login;
}
@Override
public List<Authority> getAuthorities() {
logger.trace("getAuthorities");
return null;
}
@Override
public List<Authority> getAuthorities(Class<? extends Authority> arg0) {
logger.trace("getAuthorities: {}", arg0);
return null;
}
@Override
public String getPassword() {
logger.trace("getPassword");
return null;
}
}

View File

@@ -0,0 +1,123 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal.ftp;
import java.util.HashMap;
import java.util.Map;
import org.apache.ftpserver.ftplet.Authentication;
import org.apache.ftpserver.ftplet.AuthenticationFailedException;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.User;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.usermanager.UsernamePasswordAuthentication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Simple FTP user manager implementation.
*
*
* @author Pauli Anttila - Initial contribution
*/
public class FTPUserManager implements UserManager {
private final Logger logger = LoggerFactory.getLogger(FTPUserManager.class);
private int idleTimeout;
private Map<String, UsernamePassword> authenticationData = new HashMap<>();
@Override
public User authenticate(final Authentication inAuth) throws AuthenticationFailedException {
logger.trace("authenticate: {}", inAuth);
UsernamePasswordAuthentication upa = (UsernamePasswordAuthentication) inAuth;
String login = upa.getUsername();
String password = upa.getPassword();
if (!autheticate(login, password)) {
throw new AuthenticationFailedException();
}
return new FTPUser(login, idleTimeout);
}
private boolean autheticate(String login, String password) {
boolean result = false;
if (login != null && password != null) {
UsernamePassword credential = authenticationData.get(login);
if (credential != null) {
if (login.equals(credential.getUsername()) && password.equals(credential.getPassword())) {
return true;
}
}
}
return result;
}
public void setIdleTimeout(int idleTimeout) {
this.idleTimeout = idleTimeout;
}
public synchronized void addAuthenticationCredentials(String username, String password)
throws IllegalArgumentException {
if (authenticationData.containsKey(username)) {
throw new IllegalArgumentException("Credentials for user '" + username + "' already exists!");
}
authenticationData.put(username, new UsernamePassword(username, password));
}
public synchronized void removeAuthenticationCredentials(String username) {
authenticationData.remove(username);
}
@Override
public User getUserByName(final String login) throws FtpException {
logger.trace("getUserByName: {}", login);
return new FTPUser(login, idleTimeout);
}
@Override
public void delete(String arg0) throws FtpException {
logger.trace("delete: {}", arg0);
}
@Override
public boolean doesExist(String arg0) throws FtpException {
logger.trace("doesExist: {}", arg0);
return false;
}
@Override
public String getAdminName() throws FtpException {
logger.trace("getAdminName");
return null;
}
@Override
public String[] getAllUserNames() throws FtpException {
logger.trace("getAllUserNames");
return null;
}
@Override
public boolean isAdmin(String arg0) throws FtpException {
logger.trace("isAdmin: {}", arg0);
return false;
}
@Override
public void save(User arg0) throws FtpException {
logger.trace("save: {}", arg0);
}
}

View File

@@ -0,0 +1,206 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal.ftp;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.ftpserver.FtpServerConfigurationException;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.DefaultFtplet;
import org.apache.ftpserver.ftplet.FileSystemFactory;
import org.apache.ftpserver.ftplet.FileSystemView;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpRequest;
import org.apache.ftpserver.ftplet.FtpSession;
import org.apache.ftpserver.ftplet.FtpStatistics;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.ftplet.FtpletContext;
import org.apache.ftpserver.ftplet.FtpletResult;
import org.apache.ftpserver.ftplet.User;
import org.apache.ftpserver.listener.Listener;
import org.apache.ftpserver.listener.ListenerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Simple FTP server implementation to receive files via FTP.
*
*
* @author Pauli Anttila - Initial contribution
*/
public class FtpServer {
private final Logger logger = LoggerFactory.getLogger(FtpServer.class);
private int port;
int idleTimeout;
private org.apache.ftpserver.FtpServer server;
private List<FtpServerEventListener> listeners;
private MyFTPLet myFTPLet;
private FTPUserManager FTPUserManager;
private String ftpStartUpErrorReason;
public FtpServer() {
listeners = new ArrayList<>();
FTPUserManager = new FTPUserManager();
}
public void startServer(int port, int idleTimeout) throws FtpException {
stopServer();
this.port = port;
this.idleTimeout = idleTimeout;
FTPUserManager.setIdleTimeout(idleTimeout);
initServer();
}
public void stopServer() {
if (server != null) {
server.stop();
}
}
public String getStartUpErrorReason() {
return ftpStartUpErrorReason;
}
public synchronized void addEventListener(FtpServerEventListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
public synchronized void addAuthenticationCredentials(String username, String password)
throws IllegalArgumentException {
FTPUserManager.addAuthenticationCredentials(username, password);
}
public synchronized void removeAuthenticationCredentials(String username) {
FTPUserManager.removeAuthenticationCredentials(username);
}
public synchronized void removeEventListener(FtpServerEventListener listener) {
listeners.remove(listener);
}
private void sendMsgToListeners(String userName, String filename, byte[] data) {
Iterator<FtpServerEventListener> iterator = listeners.iterator();
while (iterator.hasNext()) {
try {
iterator.next().fileReceived(userName, filename, data);
} catch (Exception e) {
// catch all exceptions give all handlers a fair chance of handling the messages
logger.debug("Event listener invoking error: {}", e.getMessage());
}
}
}
public void printStats() {
FtpStatistics ftpStats = myFTPLet.getStats();
logger.debug("TotalConnectionNumber: {}", ftpStats.getTotalConnectionNumber());
logger.debug("TotalLoginNumber: {}", ftpStats.getTotalLoginNumber());
logger.debug("TotalFailedLoginNumber: {}", ftpStats.getTotalFailedLoginNumber());
logger.debug("TotalUploadNumber: {}", ftpStats.getTotalUploadNumber());
logger.debug("TotalUploadSize: {}", ftpStats.getTotalUploadSize());
logger.debug("CurrentConnectionNumber: {}", ftpStats.getCurrentConnectionNumber());
logger.debug("CurrentLoginNumber: {}", ftpStats.getCurrentLoginNumber());
}
private void initServer() throws FtpException {
FtpServerFactory serverFactory = new FtpServerFactory();
ListenerFactory listenerFactory = new ListenerFactory();
listenerFactory.setPort(port);
listenerFactory.setIdleTimeout(idleTimeout);
Listener listener = listenerFactory.createListener();
serverFactory.addListener("default", listener);
Map<String, Ftplet> ftplets = new LinkedHashMap<>();
myFTPLet = new MyFTPLet();
ftplets.put("ftplet", myFTPLet);
serverFactory.setFtplets(ftplets);
serverFactory.setFileSystem(new FileSystemFactory() {
@Override
public FileSystemView createFileSystemView(User user) throws FtpException {
logger.debug("createFileSystemView: {}", user.getName());
return new SimpleFileSystemView();
}
});
// set the user manager
serverFactory.setUserManager(FTPUserManager);
server = serverFactory.createServer();
try {
server.start();
ftpStartUpErrorReason = null;
} catch (FtpException | FtpServerConfigurationException e) {
ftpStartUpErrorReason = "Failed to start FTP server";
if (!e.getMessage().isEmpty()) {
ftpStartUpErrorReason += ": " + e.getMessage();
}
throw e;
}
}
private class MyFTPLet extends DefaultFtplet {
FtpletContext ftpletContext;
public FtpStatistics getStats() {
return ftpletContext.getFtpStatistics();
}
@Override
public void init(FtpletContext ftpletContext) throws FtpException {
this.ftpletContext = ftpletContext;
}
@Override
public void destroy() {
logger.trace("destroy");
}
@Override
public FtpletResult onConnect(FtpSession session) throws FtpException, IOException {
logger.debug("User connected to FtpServer");
return super.onConnect(session);
}
@Override
public FtpletResult onUploadEnd(final FtpSession session, final FtpRequest request)
throws FtpException, IOException {
String userRoot = session.getUser().getHomeDirectory();
String currDir = session.getFileSystemView().getWorkingDirectory().getAbsolutePath();
String fileName = request.getArgument();
logger.debug("File {} upload to FTP server", userRoot + currDir + "/" + fileName);
SimpleFtpFile file = (SimpleFtpFile) session.getFileSystemView().getFile(fileName);
byte[] data = file.getData();
sendMsgToListeners(session.getUser().getName(), fileName, data);
return FtpletResult.SKIP;
}
}
}

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal.ftp;
import org.eclipse.jdt.annotation.NonNull;
/**
* This interface defines interface to receive data from FTP server.
*
* @author Pauli Anttila - Initial contribution
*/
public interface FtpServerEventListener {
/**
* Procedure for receive raw data from FTP server.
*
* @param userName User name.
* @param filename Received filename.
* @param data Received raw data.
*/
void fileReceived(@NonNull String userName, @NonNull String filename, byte[] data);
}

View File

@@ -0,0 +1,66 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal.ftp;
import org.apache.ftpserver.ftplet.FileSystemView;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Simple FTP file system view implementation.
*
*
* @author Pauli Anttila - Initial contribution
*/
public class SimpleFileSystemView implements FileSystemView {
private Logger logger = LoggerFactory.getLogger(SimpleFileSystemView.class);
SimpleFtpFile file = new SimpleFtpFile();
@Override
public boolean changeWorkingDirectory(String arg0) throws FtpException {
logger.trace("changeWorkingDirectory: {}", arg0);
return true;
}
@Override
public void dispose() {
logger.trace("dispose");
}
@Override
public FtpFile getFile(String arg0) throws FtpException {
logger.trace("getFile: {}", arg0);
return file;
}
@Override
public FtpFile getHomeDirectory() throws FtpException {
logger.trace("getHomeDirectory");
return new SimpleFtpFile();
}
@Override
public FtpFile getWorkingDirectory() throws FtpException {
logger.trace("getWorkingDirectory");
return new SimpleFtpFile();
}
@Override
public boolean isRandomAccessible() throws FtpException {
logger.trace("isRandomAccessible");
return false;
}
}

View File

@@ -0,0 +1,192 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal.ftp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.apache.ftpserver.ftplet.FtpFile;
import org.openhab.core.util.HexUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Simple FTP file implementation.
*
*
* @author Pauli Anttila - Initial contribution
*/
public class SimpleFtpFile implements FtpFile {
private Logger logger = LoggerFactory.getLogger(SimpleFtpFile.class);
MyOutputStream file;
public byte[] getData() {
return file.getData();
}
@Override
public InputStream createInputStream(long arg0) throws IOException {
logger.trace("createInputStream: {}", arg0);
return null;
}
@Override
public OutputStream createOutputStream(long arg0) throws IOException {
logger.trace("createOutputStream: {}", arg0);
file = new MyOutputStream();
return file;
}
@Override
public boolean delete() {
logger.trace("delete");
return false;
}
@Override
public boolean doesExist() {
logger.trace("doesExist");
return false;
}
@Override
public String getAbsolutePath() {
logger.trace("getAbsolutePath");
return "/";
}
@Override
public String getGroupName() {
logger.trace("getGroupName");
return null;
}
@Override
public long getLastModified() {
logger.trace("getLastModified");
return 0;
}
@Override
public int getLinkCount() {
logger.trace("getLinkCount");
return 0;
}
@Override
public String getName() {
logger.trace("getName");
return "";
}
@Override
public String getOwnerName() {
logger.trace("getOwnerName");
return null;
}
@Override
public long getSize() {
logger.trace("getSize");
return 0;
}
@Override
public boolean isDirectory() {
logger.trace("isDirectory");
return false;
}
@Override
public boolean isFile() {
logger.trace("isFile");
return false;
}
@Override
public boolean isHidden() {
logger.trace("isHidden");
return false;
}
@Override
public boolean isReadable() {
logger.trace("isReadable");
return false;
}
@Override
public boolean isRemovable() {
logger.trace("isRemovable");
return false;
}
@Override
public boolean isWritable() {
logger.trace("isWritable");
return true;
}
@Override
public List<FtpFile> listFiles() {
logger.trace("listFiles");
return null;
}
@Override
public boolean mkdir() {
logger.trace("mkdir");
return false;
}
@Override
public boolean move(FtpFile arg0) {
logger.trace("move: {}", arg0);
return false;
}
@Override
public boolean setLastModified(long arg0) {
logger.trace("setLastModified: {}", arg0);
return false;
}
@Override
public Object getPhysicalFile() {
logger.trace("getPhysicalFile");
return null;
}
private class MyOutputStream extends OutputStream {
private StringBuilder data = new StringBuilder();
@Override
public void write(int b) throws IOException {
data.append(String.format("%02X", (byte) b));
}
public byte[] getData() {
try {
byte[] d = HexUtils.hexToBytes(data.toString());
logger.debug("File len: {}", d.length);
return d;
} catch (IllegalArgumentException e) {
logger.debug("Exception occured during data conversion: {}", e.getMessage());
}
return null;
}
}
}

View File

@@ -0,0 +1,44 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal.ftp;
/**
* Simple wrapper class to store user name and password pairs.
*
* @author Pauli Anttila - Initial contribution
*/
class UsernamePassword {
private String username;
private String password;
UsernamePassword(String username, String password) {
this.setUsername(username);
this.setPassword(password);
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@@ -0,0 +1,139 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.ftpupload.internal.handler;
import static org.openhab.binding.ftpupload.internal.FtpUploadBindingConstants.*;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.openhab.binding.ftpupload.internal.config.FtpUploadConfig;
import org.openhab.binding.ftpupload.internal.ftp.FtpServer;
import org.openhab.binding.ftpupload.internal.ftp.FtpServerEventListener;
import org.openhab.core.io.net.http.HttpUtil;
import org.openhab.core.library.types.RawType;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link FtpUploadHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Pauli Anttila - Initial contribution
*/
public class FtpUploadHandler extends BaseThingHandler implements FtpServerEventListener {
private Logger logger = LoggerFactory.getLogger(FtpUploadHandler.class);
private FtpUploadConfig configuration;
private FtpServer ftpServer;
public FtpUploadHandler(Thing thing, FtpServer ftpServer) {
super(thing);
this.ftpServer = ftpServer;
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("handleCommand for channel {}: {}", channelUID.getId(), command.toString());
logger.debug("Command sending not supported by this binding");
if (command.equals(RefreshType.REFRESH)) {
ftpServer.printStats();
}
}
@Override
public void initialize() {
logger.debug("Initializing handler for FTP Upload Binding");
configuration = getConfigAs(FtpUploadConfig.class);
logger.debug("Using configuration: {}", configuration.toString());
ftpServer.addEventListener(this);
try {
ftpServer.addAuthenticationCredentials(configuration.userName, configuration.password);
} catch (IllegalArgumentException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
}
updateStatus(ThingStatus.ONLINE);
}
@Override
public void dispose() {
ftpServer.removeAuthenticationCredentials(configuration.userName);
ftpServer.removeEventListener(this);
}
@Override
public void fileReceived(String userName, String filename, byte[] data) {
if (configuration.userName.equals(userName)) {
updateStatus(ThingStatus.ONLINE);
updateChannels(filename, data);
updateTriggers(filename);
}
}
private String guessMimeTypeFromData(byte[] data) {
String mimeType = HttpUtil.guessContentTypeFromData(data);
logger.debug("Mime type guess from content: {}", mimeType);
if (mimeType == null) {
mimeType = RawType.DEFAULT_MIME_TYPE;
}
logger.debug("Mime type: {}", mimeType);
return mimeType;
}
private void updateChannels(String filename, byte[] data) {
for (Channel channel : thing.getChannels()) {
String channelConf = (String) channel.getConfiguration().get(PARAM_FILENAME_PATTERN);
if (channelConf != null) {
if (filenameMatch(filename, channelConf)) {
if ("Image".equals(channel.getAcceptedItemType())) {
updateState(channel.getUID().getId(), new RawType(data, guessMimeTypeFromData(data)));
}
}
}
}
}
private void updateTriggers(String filename) {
for (Channel channel : thing.getChannels()) {
String channelConf = (String) channel.getConfiguration().get(PARAM_FILENAME_PATTERN);
if (channelConf != null) {
if (filenameMatch(filename, channelConf)) {
if ("TRIGGER".equals(channel.getKind().toString())) {
triggerChannel(channel.getUID().getId(), EVENT_IMAGE_RECEIVED);
}
}
}
}
}
private boolean filenameMatch(String filename, String pattern) {
try {
return Pattern.compile(pattern).matcher(filename).find();
} catch (PatternSyntaxException e) {
logger.warn("Invalid filename pattern '{}', reason: {}", pattern, e.getMessage());
}
return false;
}
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="ftpupload" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>FTP Upload Binding</name>
<description>This binding is for receiving files via FTP.</description>
<author>Pauli Anttila</author>
<config-description>
<parameter name="port" type="integer" min="1" max="65535">
<label>TCP Port</label>
<description>TCP port of the FTP server</description>
<default>2121</default>
</parameter>
<parameter name="idleTimeout" type="integer" min="0" max="65535">
<label>Idle Timeout</label>
<description>The number of seconds before an inactive client is disconnected. If this value is set to 0, the idle
time is disabled.</description>
<default>60</default>
</parameter>
</config-description>
</binding:binding>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="ftpupload"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="imagereceiver" extensible="image-channel, image-received">
<label>Image Receiver</label>
<description>Receive image files via FTP.</description>
<channels>
<channel id="image" typeId="image-channel"/>
<channel id="image-received" typeId="image-received"/>
</channels>
<config-description>
<parameter name="userName" type="text" required="true">
<label>User Name</label>
<description>Username</description>
</parameter>
<parameter name="password" type="text" required="true">
<label>Password</label>
<description>Password</description>
<context>password</context>
</parameter>
</config-description>
</thing-type>
<channel-type id="image-channel">
<item-type>Image</item-type>
<label>Image</label>
<description>Image received via FTP</description>
<state readOnly="true"></state>
<config-description>
<parameter name="filename" type="text" required="true">
<label>Filename</label>
<description>Filename to match received files. Supports regular expression patterns.</description>
<default>.*</default>
</parameter>
</config-description>
</channel-type>
<channel-type id="image-received">
<kind>trigger</kind>
<label>Image File Received Trigger Channel</label>
<event>
<options>
<option value="IMAGE_RECEIVED">Image received</option>
</options>
</event>
<config-description>
<parameter name="filename" type="text" required="true">
<label>Filename</label>
<description>Filename to match received files. Supports regular expression patterns.</description>
<default>.*</default>
</parameter>
</config-description>
</channel-type>
</thing:thing-descriptions>