]> git.basschouten.com Git - openhab-addons.git/blob
c3ffe6cf49e1810be431dcab2b50d51b2503c9d6
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.folderwatcher.internal.handler;
14
15 import static org.openhab.binding.folderwatcher.internal.FolderWatcherBindingConstants.CHANNEL_NEWFILE;
16
17 import java.io.File;
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;
23
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.api.exception.APIException;
28 import org.openhab.binding.folderwatcher.internal.common.WatcherCommon;
29 import org.openhab.binding.folderwatcher.internal.config.S3BucketWatcherConfiguration;
30 import org.openhab.core.OpenHAB;
31 import org.openhab.core.io.net.http.HttpClientFactory;
32 import org.openhab.core.thing.ChannelUID;
33 import org.openhab.core.thing.Thing;
34 import org.openhab.core.thing.ThingStatus;
35 import org.openhab.core.thing.ThingStatusDetail;
36 import org.openhab.core.thing.binding.BaseThingHandler;
37 import org.openhab.core.types.Command;
38 import org.openhab.core.types.RefreshType;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * The {@link S3BucketWatcherHandler} is responsible for handling commands, which are
44  * sent to one of the channels.
45  *
46  * @author Alexandr Salamatov - Initial contribution
47  */
48 @NonNullByDefault
49 public class S3BucketWatcherHandler extends BaseThingHandler {
50     private final Logger logger = LoggerFactory.getLogger(S3BucketWatcherHandler.class);
51     private S3BucketWatcherConfiguration config = new S3BucketWatcherConfiguration();
52     private File currentS3ListingFile = new File(OpenHAB.getUserDataFolder() + File.separator + "FolderWatcher"
53             + File.separator + thing.getUID().getAsString().replace(':', '_') + ".data");
54     private @Nullable ScheduledFuture<?> executionJob;
55     private List<String> previousS3Listing = new ArrayList<>();
56     private HttpClientFactory httpClientFactory;
57     private @Nullable S3Actions s3;
58
59     public S3BucketWatcherHandler(Thing thing, HttpClientFactory httpClientFactory) {
60         super(thing);
61         this.httpClientFactory = httpClientFactory;
62     }
63
64     @Override
65     public void handleCommand(ChannelUID channelUID, Command command) {
66         logger.debug("Channel {} triggered with command {}", channelUID.getId(), command);
67         if (command instanceof RefreshType) {
68             refreshS3BucketInformation();
69         }
70     }
71
72     @Override
73     public void initialize() {
74         config = getConfigAs(S3BucketWatcherConfiguration.class);
75         try {
76             if (config.s3Anonymous) {
77                 s3 = new S3Actions(httpClientFactory, config.s3BucketName, config.awsRegion);
78             } else {
79                 s3 = new S3Actions(httpClientFactory, config.s3BucketName, config.awsRegion, config.awsKey,
80                         config.awsSecret);
81             }
82         } catch (APIException e) {
83             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, e.getMessage());
84             return;
85         }
86
87         try {
88             previousS3Listing = WatcherCommon.initStorage(currentS3ListingFile, config.s3BucketName);
89         } catch (IOException e) {
90             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
91             logger.debug("Can't write file {}: {}", currentS3ListingFile, e.getMessage());
92             return;
93         }
94
95         if (refreshS3BucketInformation()) {
96             if (config.pollIntervalS3 > 0) {
97                 executionJob = scheduler.scheduleWithFixedDelay(this::refreshS3BucketInformation, config.pollIntervalS3,
98                         config.pollIntervalS3, TimeUnit.SECONDS);
99             } else {
100                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
101                         "Polling interval must be greater then 0 seconds");
102                 return;
103             }
104         }
105     }
106
107     private boolean refreshS3BucketInformation() {
108         List<String> currentS3Listing = new ArrayList<>();
109         try {
110             currentS3Listing = s3.listBucket(config.s3Path);
111             updateStatus(ThingStatus.ONLINE);
112             List<String> difS3Listing = new ArrayList<>(currentS3Listing);
113             difS3Listing.removeAll(previousS3Listing);
114             difS3Listing.forEach(file -> triggerChannel(CHANNEL_NEWFILE, file));
115
116             if (!difS3Listing.isEmpty()) {
117                 WatcherCommon.saveNewListing(difS3Listing, currentS3ListingFile);
118             }
119             previousS3Listing = new ArrayList<>(currentS3Listing);
120         } catch (Exception e) {
121             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Can't connect to the bucket");
122             logger.debug("Can't connect to the bucket: {}", e.getMessage());
123             return false;
124         }
125         return true;
126     }
127
128     @Override
129     public void dispose() {
130         ScheduledFuture<?> executionJob = this.executionJob;
131         if (executionJob != null) {
132             executionJob.cancel(true);
133             this.executionJob = null;
134         }
135     }
136 }