]> git.basschouten.com Git - openhab-addons.git/blob
380eaa2d13059036b5903329a81e5f5fbe90a9c9
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.netatmo.internal.handler.capability;
14
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.netatmo.internal.api.NetatmoException;
24 import org.openhab.binding.netatmo.internal.api.SecurityApi;
25 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FloodLightMode;
26 import org.openhab.binding.netatmo.internal.api.dto.HomeData;
27 import org.openhab.binding.netatmo.internal.api.dto.HomeDataModule;
28 import org.openhab.binding.netatmo.internal.api.dto.HomeDataPerson;
29 import org.openhab.binding.netatmo.internal.api.dto.HomeEvent;
30 import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule;
31 import org.openhab.binding.netatmo.internal.api.dto.HomeStatusPerson;
32 import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus;
33 import org.openhab.binding.netatmo.internal.api.dto.NAObject;
34 import org.openhab.binding.netatmo.internal.deserialization.NAObjectMap;
35 import org.openhab.binding.netatmo.internal.handler.CommonInterface;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * The {@link SecurityCapability} is the base class for handler able to handle security features
41  *
42  * @author GaĆ«l L'hopital - Initial contribution
43  *
44  */
45 @NonNullByDefault
46 class SecurityCapability extends RestCapability<SecurityApi> {
47     private final Logger logger = LoggerFactory.getLogger(SecurityCapability.class);
48
49     private static final Map<String, HomeEvent> eventBuffer = new HashMap<>();
50
51     SecurityCapability(CommonInterface handler) {
52         super(handler, SecurityApi.class);
53     }
54
55     @Override
56     protected void updateHomeData(HomeData homeData) {
57         NAObjectMap<HomeDataPerson> persons = homeData.getPersons();
58         NAObjectMap<HomeDataModule> modules = homeData.getModules();
59         handler.getActiveChildren().forEach(childHandler -> {
60             String childId = childHandler.getId();
61             persons.getOpt(childId).ifPresentOrElse(personData -> {
62                 personData.setIgnoredForThingUpdate(true);
63                 childHandler.setNewData(personData);
64             }, () -> {
65                 modules.getOpt(childId).ifPresent(childData -> {
66                     childData.setIgnoredForThingUpdate(true);
67                     childHandler.setNewData(childData);
68                 });
69                 modules.values().stream().filter(module -> childId.equals(module.getBridge()))
70                         .forEach(bridgedModule -> {
71                             childHandler.setNewData(bridgedModule);
72                         });
73             });
74         });
75     }
76
77     @Override
78     protected void updateHomeStatus(HomeStatus homeStatus) {
79         NAObjectMap<HomeStatusPerson> persons = homeStatus.getPersons();
80         NAObjectMap<HomeStatusModule> modules = homeStatus.getModules();
81         handler.getActiveChildren().forEach(childHandler -> {
82             String childId = childHandler.getId();
83             persons.getOpt(childId).ifPresentOrElse(personData -> childHandler.setNewData(personData), () -> {
84                 modules.getOpt(childId).ifPresentOrElse(childData -> {
85                     childHandler.setNewData(childData);
86                     modules.values().stream().filter(module -> childId.equals(module.getBridge()))
87                             .forEach(bridgedModule -> {
88                                 childHandler.setNewData(bridgedModule);
89                             });
90
91                 }, () -> {
92                     // This module is not present in the homestatus data, so it is considered as unreachable
93                     HomeStatusModule module = new HomeStatusModule();
94                     module.setReachable(false);
95                     childHandler.setNewData(module);
96                 });
97             });
98         });
99     }
100
101     @Override
102     protected void updateHomeEvent(HomeEvent homeEvent) {
103         String personId = homeEvent.getPersonId();
104         if (personId != null) {
105             handler.getActiveChildren().stream().filter(handler -> personId.equals(handler.getId())).findFirst()
106                     .ifPresent(handler -> {
107                         homeEvent.setIgnoredForThingUpdate(true);
108                         handler.setNewData(homeEvent);
109                     });
110         }
111         String cameraId = homeEvent.getCameraId();
112         handler.getActiveChildren().stream().filter(handler -> cameraId.equals(handler.getId())).findFirst()
113                 .ifPresent(handler -> {
114                     homeEvent.setIgnoredForThingUpdate(true);
115                     handler.setNewData(homeEvent);
116                 });
117     }
118
119     @Override
120     protected List<NAObject> updateReadings(SecurityApi api) {
121         List<NAObject> result = new ArrayList<>();
122         try {
123             Collection<HomeEvent> lastEvents = api.getHomeEvents(handler.getId());
124             lastEvents.stream().forEach(event -> {
125                 HomeEvent previousEvent = eventBuffer.get(event.getCameraId());
126                 if (previousEvent == null || previousEvent.getTime().isBefore(event.getTime())) {
127                     eventBuffer.put(event.getCameraId(), event);
128                 }
129                 String personId = event.getPersonId();
130                 if (personId != null) {
131                     previousEvent = eventBuffer.get(personId);
132                     if (previousEvent == null || previousEvent.getTime().isBefore(event.getTime())) {
133                         eventBuffer.put(personId, event);
134                     }
135                 }
136             });
137         } catch (NetatmoException e) {
138             logger.warn("Error retrieving last events for home '{}' : {}", handler.getId(), e.getMessage());
139         }
140         return result;
141     }
142
143     public @Nullable HomeEvent getLastPersonEvent(String personId) {
144         HomeEvent event = eventBuffer.get(personId);
145         if (event == null) {
146             Collection<HomeEvent> events = requestPersonEvents(personId);
147             if (!events.isEmpty()) {
148                 event = events.iterator().next();
149                 eventBuffer.put(personId, event);
150             }
151         }
152         return event;
153     }
154
155     public @Nullable HomeEvent getLastDeviceEvent(String cameraId, String deviceType) {
156         HomeEvent event = eventBuffer.get(cameraId);
157         if (event == null) {
158             Collection<HomeEvent> events = requestDeviceEvents(cameraId, deviceType);
159             if (!events.isEmpty()) {
160                 event = events.iterator().next();
161                 eventBuffer.put(cameraId, event);
162             }
163         }
164         return event;
165     }
166
167     private Collection<HomeEvent> requestDeviceEvents(String cameraId, String deviceType) {
168         return getApi().map(api -> {
169             try {
170                 return api.getDeviceEvents(handler.getId(), cameraId, deviceType);
171             } catch (NetatmoException e) {
172                 logger.warn("Error retrieving last events of camera '{}' : {}", cameraId, e.getMessage());
173                 return null;
174             }
175         }).orElse(List.of());
176     }
177
178     private Collection<HomeEvent> requestPersonEvents(String personId) {
179         return getApi().map(api -> {
180             try {
181                 return api.getPersonEvents(handler.getId(), personId);
182             } catch (NetatmoException e) {
183                 logger.warn("Error retrieving last events of person '{}' : {}", personId, e.getMessage());
184                 return null;
185             }
186         }).orElse(List.of());
187     }
188
189     public void setPersonAway(String personId, boolean away) {
190         getApi().ifPresent(api -> {
191             try {
192                 api.setPersonAwayStatus(handler.getId(), personId, away);
193                 handler.expireData();
194             } catch (NetatmoException e) {
195                 logger.warn("Error setting person away/at home '{}' : {}", personId, e.getMessage());
196             }
197         });
198     }
199
200     public @Nullable String ping(String vpnUrl) {
201         return getApi().map(api -> {
202             return api.ping(vpnUrl);
203         }).orElse(null);
204     }
205
206     public void changeStatus(@Nullable String localURL, boolean status) {
207         if (localURL == null) {
208             logger.info("Monitoring changes can only be done on local camera.");
209             return;
210         }
211         getApi().ifPresent(api -> {
212             try {
213                 api.changeStatus(localURL, status);
214                 handler.expireData();
215             } catch (NetatmoException e) {
216                 logger.warn("Error changing camera monitoring status '{}' : {}", status, e.getMessage());
217             }
218         });
219     }
220
221     public void changeFloodlightMode(String cameraId, FloodLightMode mode) {
222         getApi().ifPresent(api -> {
223             try {
224                 api.changeFloodLightMode(handler.getId(), cameraId, mode);
225                 handler.expireData();
226             } catch (NetatmoException e) {
227                 logger.warn("Error changing Presence floodlight mode '{}' : {}", mode, e.getMessage());
228             }
229         });
230     }
231 }