2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.folderwatcher.internal.handler;
15 import static org.openhab.binding.folderwatcher.internal.FolderWatcherBindingConstants.CHANNEL_NEWFILE;
18 import java.io.IOException;
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.concurrent.ScheduledFuture;
22 import java.util.concurrent.TimeUnit;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.folderwatcher.internal.api.S3Actions;
27 import org.openhab.binding.folderwatcher.internal.common.WatcherCommon;
28 import org.openhab.binding.folderwatcher.internal.config.S3BucketWatcherConfiguration;
29 import org.openhab.core.OpenHAB;
30 import org.openhab.core.io.net.http.HttpClientFactory;
31 import org.openhab.core.thing.ChannelUID;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.ThingStatus;
34 import org.openhab.core.thing.ThingStatusDetail;
35 import org.openhab.core.thing.binding.BaseThingHandler;
36 import org.openhab.core.types.Command;
37 import org.openhab.core.types.RefreshType;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * The {@link S3BucketWatcherHandler} is responsible for handling commands, which are
43 * sent to one of the channels.
45 * @author Alexandr Salamatov - Initial contribution
48 public class S3BucketWatcherHandler extends BaseThingHandler {
49 private final Logger logger = LoggerFactory.getLogger(S3BucketWatcherHandler.class);
50 private S3BucketWatcherConfiguration config = new S3BucketWatcherConfiguration();
51 private File currentS3ListingFile = new File(OpenHAB.getUserDataFolder() + File.separator + "FolderWatcher"
52 + File.separator + thing.getUID().getAsString().replace(':', '_') + ".data");
53 private @Nullable ScheduledFuture<?> executionJob;
54 private List<String> previousS3Listing = new ArrayList<>();
55 private HttpClientFactory httpClientFactory;
56 private @Nullable S3Actions s3;
58 public S3BucketWatcherHandler(Thing thing, HttpClientFactory httpClientFactory) {
60 this.httpClientFactory = httpClientFactory;
64 public void handleCommand(ChannelUID channelUID, Command command) {
65 logger.debug("Channel {} triggered with command {}", channelUID.getId(), command);
66 if (command instanceof RefreshType) {
67 refreshS3BucketInformation();
72 public void initialize() {
73 config = getConfigAs(S3BucketWatcherConfiguration.class);
75 if (config.s3Anonymous) {
76 s3 = new S3Actions(httpClientFactory, config.s3BucketName, config.awsRegion);
78 s3 = new S3Actions(httpClientFactory, config.s3BucketName, config.awsRegion, config.awsKey,
83 previousS3Listing = WatcherCommon.initStorage(currentS3ListingFile, config.s3BucketName);
84 } catch (IOException e) {
85 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
86 logger.debug("Can't write file {}: {}", currentS3ListingFile, e.getMessage());
90 if (refreshS3BucketInformation()) {
91 if (config.pollIntervalS3 > 0) {
92 updateStatus(ThingStatus.ONLINE);
93 executionJob = scheduler.scheduleWithFixedDelay(this::refreshS3BucketInformation, config.pollIntervalS3,
94 config.pollIntervalS3, TimeUnit.SECONDS);
96 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
97 "Polling interval must be greater then 0 seconds");
103 private boolean refreshS3BucketInformation() {
104 List<String> currentS3Listing = new ArrayList<>();
106 currentS3Listing = s3.listBucket(config.s3Path);
107 List<String> difS3Listing = new ArrayList<>(currentS3Listing);
108 difS3Listing.removeAll(previousS3Listing);
109 difS3Listing.forEach(file -> triggerChannel(CHANNEL_NEWFILE, file));
111 if (!difS3Listing.isEmpty()) {
112 WatcherCommon.saveNewListing(difS3Listing, currentS3ListingFile);
114 previousS3Listing = new ArrayList<>(currentS3Listing);
115 } catch (Exception e) {
116 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Can't connect to the bucket");
117 logger.debug("Can't connect to the bucket: {}", e.getMessage());
124 public void dispose() {
125 ScheduledFuture<?> executionJob = this.executionJob;
126 if (executionJob != null) {
127 executionJob.cancel(true);
128 this.executionJob = null;