]> git.basschouten.com Git - openhab-addons.git/blob
50299eff8bb2fdd97652320266de8fcfd76f03ce
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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 static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
16
17 import java.time.ZonedDateTime;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.openhab.binding.netatmo.internal.api.EnergyApi;
21 import org.openhab.binding.netatmo.internal.api.NetatmoException;
22 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea;
23 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.SetpointMode;
24 import org.openhab.binding.netatmo.internal.api.dto.HomeData;
25 import org.openhab.binding.netatmo.internal.api.dto.HomeDataModule;
26 import org.openhab.binding.netatmo.internal.api.dto.HomeDataRoom;
27 import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule;
28 import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus;
29 import org.openhab.binding.netatmo.internal.api.dto.Room;
30 import org.openhab.binding.netatmo.internal.config.HomeConfiguration;
31 import org.openhab.binding.netatmo.internal.deserialization.NAObjectMap;
32 import org.openhab.binding.netatmo.internal.handler.CommonInterface;
33 import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider;
34 import org.openhab.core.thing.ChannelUID;
35 import org.openhab.core.types.Command;
36 import org.openhab.core.types.StateOption;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /**
41  * The {@link EnergyCapability} is the base class for handler able to handle energy features
42  *
43  * @author GaĆ«l L'hopital - Initial contribution
44  *
45  */
46 @NonNullByDefault
47 public class EnergyCapability extends RestCapability<EnergyApi> {
48     private final Logger logger = LoggerFactory.getLogger(EnergyCapability.class);
49     private final NetatmoDescriptionProvider descriptionProvider;
50
51     private int setPointDefaultDuration = -1;
52     private String energyId = "";
53
54     EnergyCapability(CommonInterface handler, NetatmoDescriptionProvider descriptionProvider) {
55         super(handler, EnergyApi.class);
56         this.descriptionProvider = descriptionProvider;
57     }
58
59     @Override
60     public void initialize() {
61         super.initialize();
62         energyId = handler.getThingConfigAs(HomeConfiguration.class).getIdForArea(FeatureArea.ENERGY);
63     }
64
65     @Override
66     protected void updateHomeData(HomeData homeData) {
67         if (homeData instanceof HomeData.Energy energyData) {
68             NAObjectMap<HomeDataRoom> rooms = energyData.getRooms();
69             NAObjectMap<HomeDataModule> modules = energyData.getModules();
70             handler.getActiveChildren(FeatureArea.ENERGY).forEach(childHandler -> {
71                 String childId = childHandler.getId();
72                 rooms.getOpt(childId)
73                         .ifPresentOrElse(roomData -> childHandler.setNewData(roomData.ignoringForThingUpdate()), () -> {
74                             modules.getOpt(childId).ifPresent(
75                                     childData -> childHandler.setNewData(childData.ignoringForThingUpdate()));
76                             modules.values().stream().filter(module -> childId.equals(module.getBridge()))
77                                     .forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
78                         });
79             });
80             descriptionProvider.setStateOptions(new ChannelUID(thingUID, GROUP_ENERGY, CHANNEL_PLANNING),
81                     energyData.getThermSchedules().stream().map(p -> new StateOption(p.getId(), p.getName())).toList());
82             setPointDefaultDuration = energyData.getThermSetpointDefaultDuration();
83         }
84     }
85
86     @Override
87     protected void updateHomeStatus(HomeStatus energyStatus) {
88         NAObjectMap<Room> rooms = energyStatus.getRooms();
89         NAObjectMap<HomeStatusModule> modules = energyStatus.getModules();
90         handler.getActiveChildren(FeatureArea.ENERGY).forEach(childHandler -> {
91             String childId = childHandler.getId();
92             logger.trace("childId: {}", childId);
93             rooms.getOpt(childId).ifPresentOrElse(roomData -> {
94                 logger.trace("roomData: {}", roomData);
95                 childHandler.setNewData(roomData);
96             }, () -> {
97                 modules.getOpt(childId).ifPresent(moduleData -> {
98                     logger.trace("moduleData: {}", moduleData);
99                     childHandler.setNewData(moduleData);
100                     modules.values().stream().filter(module -> childId.equals(module.getBridge()))
101                             .forEach(bridgedModule -> {
102                                 logger.trace("bridgedModule: {}", bridgedModule);
103                                 childHandler.setNewData(bridgedModule);
104                             });
105                 });
106             });
107         });
108     }
109
110     public void setThermPoint(String roomId, SetpointMode mode, long endtime, double temp) {
111         getApi().ifPresent(api -> {
112             try {
113                 api.setThermpoint(energyId, roomId, mode, endtime, temp);
114                 handler.expireData();
115             } catch (NetatmoException e) {
116                 logger.warn("Error setting room thermostat mode '{}' : {}", mode, e.getMessage());
117             }
118         });
119     }
120
121     public void setRoomThermTemp(String roomId, SetpointMode mode, long endtime, double temp) {
122         setThermPoint(roomId, mode, endtime, temp);
123     }
124
125     public void setRoomThermMode(String roomId, SetpointMode targetMode) {
126         setThermPoint(roomId, targetMode, targetMode == SetpointMode.MAX ? setpointEndTimeFromNow() : 0, 0);
127     }
128
129     public void setRoomThermTemp(String roomId, double temp) {
130         setThermPoint(roomId, SetpointMode.MANUAL, setpointEndTimeFromNow(), temp);
131     }
132
133     @Override
134     public void handleCommand(String channelName, Command command) {
135         getApi().ifPresent(api -> {
136             try {
137                 switch (channelName) {
138                     case CHANNEL_PLANNING:
139                         api.switchSchedule(energyId, command.toString());
140                         break;
141                     case CHANNEL_SETPOINT_MODE:
142                         SetpointMode targetMode = SetpointMode.valueOf(command.toString());
143                         if (targetMode == SetpointMode.MANUAL) {
144                             logger.info("Switch to 'Manual' is done by setting a setpoint temp, command ignored");
145                             return;
146                         }
147                         api.setThermMode(energyId, targetMode.apiDescriptor);
148                         break;
149                 }
150                 handler.expireData();
151             } catch (NetatmoException e) {
152                 logger.warn("Error handling command '{}' : {}", command, e.getMessage());
153             } catch (IllegalArgumentException e) {
154                 logger.warn("Command '{}' sent to channel '{}' is not a valid setpoint mode.", command, channelName);
155             }
156         });
157     }
158
159     private long setpointEndTimeFromNow() {
160         return ZonedDateTime.now().plusMinutes(setPointDefaultDuration).toEpochSecond();
161     }
162 }