]> git.basschouten.com Git - openhab-addons.git/blob
67a8bd8da717b179ab260e7da6690fdc01c04135
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.teleinfo.internal.handler;
14
15 import static org.openhab.binding.teleinfo.internal.TeleinfoBindingConstants.*;
16
17 import java.util.Map.Entry;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.teleinfo.internal.data.Frame;
22 import org.openhab.binding.teleinfo.internal.data.Phase;
23 import org.openhab.binding.teleinfo.internal.data.Pricing;
24 import org.openhab.binding.teleinfo.internal.reader.io.serialport.InvalidFrameException;
25 import org.openhab.binding.teleinfo.internal.reader.io.serialport.Label;
26 import org.openhab.binding.teleinfo.internal.reader.io.serialport.ValueType;
27 import org.openhab.core.library.types.DateTimeType;
28 import org.openhab.core.library.types.QuantityType;
29 import org.openhab.core.library.types.StringType;
30 import org.openhab.core.thing.Bridge;
31 import org.openhab.core.thing.Channel;
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.ThingStatusInfo;
37 import org.openhab.core.thing.binding.BaseThingHandler;
38 import org.openhab.core.types.Command;
39 import org.openhab.core.types.UnDefType;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * The {@link TeleinfoElectricityMeterHandler} class defines a skeleton for Electricity Meters handlers.
45  *
46  * @author Nicolas SIBERIL - Initial contribution
47  */
48 @NonNullByDefault
49 public class TeleinfoElectricityMeterHandler extends BaseThingHandler implements TeleinfoControllerHandlerListener {
50
51     private final Logger logger = LoggerFactory.getLogger(TeleinfoElectricityMeterHandler.class);
52     protected TeleinfoElectricityMeterConfiguration configuration = new TeleinfoElectricityMeterConfiguration();
53     private boolean wasLastFrameShort = false;
54
55     public TeleinfoElectricityMeterHandler(Thing thing) {
56         super(thing);
57     }
58
59     @Override
60     public void initialize() {
61         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, ERROR_OFFLINE_CONTROLLER_OFFLINE);
62
63         Bridge bridge = getBridge();
64         logger.debug("bridge = {}", bridge);
65         if (bridge != null) {
66             bridgeStatusChanged(bridge.getStatusInfo());
67         }
68         configuration = getConfigAs(TeleinfoElectricityMeterConfiguration.class);
69     }
70
71     @Override
72     public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
73         TeleinfoAbstractControllerHandler controllerHandler = getControllerHandler();
74         if (bridgeStatusInfo.getStatus() != ThingStatus.ONLINE) {
75             if (controllerHandler != null) {
76                 controllerHandler.removeListener(this);
77             }
78             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, ERROR_OFFLINE_CONTROLLER_OFFLINE);
79             return;
80         }
81
82         if (controllerHandler != null) {
83             controllerHandler.addListener(this);
84             updateStatus(ThingStatus.ONLINE);
85         }
86     }
87
88     @Override
89     public void dispose() {
90         TeleinfoAbstractControllerHandler controllerHandler = getControllerHandler();
91         if (controllerHandler != null) {
92             controllerHandler.removeListener(this);
93         }
94         super.dispose();
95     }
96
97     private @Nullable TeleinfoAbstractControllerHandler getControllerHandler() {
98         Bridge bridge = getBridge();
99         return bridge != null ? (TeleinfoAbstractControllerHandler) bridge.getHandler() : null;
100     }
101
102     @Override
103     public void handleCommand(ChannelUID channelUID, Command command) {
104         // no commands supported
105     }
106
107     @Override
108     protected void updateStatus(ThingStatus status, ThingStatusDetail statusDetail, @Nullable String description) {
109         super.updateStatus(status, statusDetail, description);
110
111         if (!(ThingStatus.ONLINE.equals(status))) {
112             for (Channel channel : getThing().getChannels()) {
113                 if (!CHANNEL_LAST_UPDATE.equals(channel.getUID().getId())) {
114                     updateState(channel.getUID(), UnDefType.UNDEF);
115                 }
116             }
117         }
118     }
119
120     @Override
121     protected void updateStatus(ThingStatus status, ThingStatusDetail statusDetail) {
122         this.updateStatus(status, statusDetail, null);
123     }
124
125     @Override
126     protected void updateStatus(ThingStatus status) {
127         this.updateStatus(status, ThingStatusDetail.NONE, null);
128     }
129
130     @Override
131     public void onFrameReceived(Frame frame) {
132         String adco = configuration.getAdco();
133         if (adco.equalsIgnoreCase(frame.get(Label.ADCO))) {
134             updateStatesForChannels(frame);
135         }
136     }
137
138     private void updateStatesForChannels(Frame frame) {
139         for (Entry<Label, String> entry : frame.getLabelToValues().entrySet()) {
140             Label label = entry.getKey();
141             if (!label.getChannelName().equals(NOT_A_CHANNEL)) {
142                 if (label == Label.PTEC) {
143                     updateState(label.getChannelName(), StringType.valueOf(entry.getValue().replace(".", "")));
144                 } else if (label.getType() == ValueType.STRING) {
145                     updateState(label.getChannelName(), StringType.valueOf(entry.getValue()));
146                 } else if (label.getType() == ValueType.INTEGER) {
147                     updateState(label.getChannelName(),
148                             QuantityType.valueOf(Integer.parseInt(entry.getValue()), label.getUnit()));
149                 }
150             }
151         }
152         try {
153             if (frame.getPricing() == Pricing.TEMPO) {
154                 updateState(CHANNEL_TEMPO_FRAME_PROGRAMME_CIRCUIT_1, StringType.valueOf(frame.getProgrammeCircuit1()));
155                 updateState(CHANNEL_TEMPO_FRAME_PROGRAMME_CIRCUIT_2, StringType.valueOf(frame.getProgrammeCircuit2()));
156             }
157         } catch (InvalidFrameException e) {
158             logger.warn("Can not find pricing option.");
159         }
160
161         try {
162             Phase phase = frame.getPhase();
163             if (phase == Phase.ONE_PHASED) {
164                 updateStateForMissingAlert(frame, Label.ADPS);
165             } else if (phase == Phase.THREE_PHASED) {
166                 if (!wasLastFrameShort) {
167                     updateStateForMissingAlert(frame, Label.ADIR1);
168                     updateStateForMissingAlert(frame, Label.ADIR2);
169                     updateStateForMissingAlert(frame, Label.ADIR3);
170                 }
171                 wasLastFrameShort = frame.isShortFrame();
172             }
173         } catch (InvalidFrameException e) {
174             logger.warn("Can not find phase.");
175         }
176
177         updateState(CHANNEL_LAST_UPDATE, new DateTimeType());
178     }
179
180     private void updateStateForMissingAlert(Frame frame, Label label) {
181         if (!frame.getLabelToValues().containsKey(label)) {
182             updateState(label.getChannelName(), UnDefType.NULL);
183         }
184     }
185 }