]> git.basschouten.com Git - openhab-addons.git/blob
e0d1b2087ce0ae3cf7da661f6e16dd34d4ae3b8f
[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;
14
15 import static org.openhab.binding.teleinfo.internal.TeleinfoBindingConstants.*;
16
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.stream.Collectors;
21 import java.util.stream.Stream;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.teleinfo.internal.dto.Frame;
26 import org.openhab.binding.teleinfo.internal.dto.cbemm.FrameCbemmBaseOption;
27 import org.openhab.binding.teleinfo.internal.dto.cbemm.FrameCbemmEjpOption;
28 import org.openhab.binding.teleinfo.internal.dto.cbemm.FrameCbemmHcOption;
29 import org.openhab.binding.teleinfo.internal.dto.cbemm.FrameCbemmTempoOption;
30 import org.openhab.binding.teleinfo.internal.dto.cbemm.evoicc.FrameCbemmEvolutionIccBaseOption;
31 import org.openhab.binding.teleinfo.internal.dto.cbemm.evoicc.FrameCbemmEvolutionIccEjpOption;
32 import org.openhab.binding.teleinfo.internal.dto.cbemm.evoicc.FrameCbemmEvolutionIccHcOption;
33 import org.openhab.binding.teleinfo.internal.dto.cbemm.evoicc.FrameCbemmEvolutionIccTempoOption;
34 import org.openhab.binding.teleinfo.internal.dto.cbetm.FrameCbetmLongBaseOption;
35 import org.openhab.binding.teleinfo.internal.dto.cbetm.FrameCbetmLongEjpOption;
36 import org.openhab.binding.teleinfo.internal.dto.cbetm.FrameCbetmLongHcOption;
37 import org.openhab.binding.teleinfo.internal.dto.cbetm.FrameCbetmLongTempoOption;
38 import org.openhab.binding.teleinfo.internal.dto.common.FrameAdco;
39 import org.openhab.binding.teleinfo.internal.handler.TeleinfoAbstractControllerHandler;
40 import org.openhab.binding.teleinfo.internal.handler.TeleinfoControllerHandlerListener;
41 import org.openhab.core.config.discovery.AbstractDiscoveryService;
42 import org.openhab.core.config.discovery.DiscoveryResult;
43 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
44 import org.openhab.core.config.discovery.DiscoveryService;
45 import org.openhab.core.thing.ThingTypeUID;
46 import org.openhab.core.thing.ThingUID;
47 import org.openhab.core.thing.binding.ThingHandler;
48 import org.openhab.core.thing.binding.ThingHandlerService;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 /**
53  * The {@link TeleinfoDiscoveryService} class is the service to discover a skeleton for controller handlers.
54  *
55  * @author Nicolas SIBERIL - Initial contribution
56  */
57 @NonNullByDefault
58 public class TeleinfoDiscoveryService extends AbstractDiscoveryService
59         implements TeleinfoControllerHandlerListener, ThingHandlerService, DiscoveryService {
60
61     private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Stream.of(THING_HC_CBEMM_ELECTRICITY_METER_TYPE_UID,
62             THING_BASE_CBEMM_ELECTRICITY_METER_TYPE_UID, THING_TEMPO_CBEMM_ELECTRICITY_METER_TYPE_UID,
63             THING_EJP_CBEMM_ELECTRICITY_METER_TYPE_UID, THING_HC_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID,
64             THING_BASE_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID, THING_TEMPO_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID,
65             THING_EJP_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID, THING_HC_CBETM_ELECTRICITY_METER_TYPE_UID,
66             THING_BASE_CBETM_ELECTRICITY_METER_TYPE_UID, THING_TEMPO_CBETM_ELECTRICITY_METER_TYPE_UID,
67             THING_EJP_CBETM_ELECTRICITY_METER_TYPE_UID).collect(Collectors.toSet());
68
69     private static final int SCAN_DURATION_IN_S = 60;
70
71     private final Logger logger = LoggerFactory.getLogger(TeleinfoDiscoveryService.class);
72     private @Nullable TeleinfoAbstractControllerHandler controllerHandler;
73
74     public TeleinfoDiscoveryService() {
75         super(SCAN_DURATION_IN_S);
76     }
77
78     public TeleinfoDiscoveryService(TeleinfoAbstractControllerHandler controllerHandler) {
79         super(SCAN_DURATION_IN_S);
80         this.controllerHandler = controllerHandler;
81     }
82
83     @Override
84     public Set<ThingTypeUID> getSupportedThingTypes() {
85         return SUPPORTED_THING_TYPES;
86     }
87
88     public void activate() {
89         TeleinfoAbstractControllerHandler controllerHandlerRef = controllerHandler;
90         if (controllerHandlerRef != null) {
91             logger.debug("Teleinfo discovery: Activate {}", controllerHandlerRef.getThing().getUID());
92         } else {
93             logNullControllerHandler();
94         }
95     }
96
97     @Override
98     public void deactivate() {
99         TeleinfoAbstractControllerHandler controllerHandlerRef = controllerHandler;
100         if (controllerHandlerRef != null) {
101             logger.debug("Teleinfo discovery: Deactivate {}", controllerHandlerRef.getThing().getUID());
102         } else {
103             logNullControllerHandler();
104         }
105     }
106
107     @Override
108     protected void startScan() {
109         TeleinfoAbstractControllerHandler controllerHandlerRef = controllerHandler;
110         if (controllerHandlerRef != null) {
111             logger.debug("Teleinfo discovery: Start {}", controllerHandlerRef.getThing().getUID());
112
113             // Start the search for new devices
114             controllerHandlerRef.addListener(this);
115         } else {
116             logNullControllerHandler();
117         }
118     }
119
120     @Override
121     public synchronized void abortScan() {
122         TeleinfoAbstractControllerHandler controllerHandlerRef = controllerHandler;
123         if (controllerHandlerRef != null) {
124             logger.debug("Teleinfo discovery: Abort {}", controllerHandlerRef.getThing().getUID());
125             controllerHandlerRef.removeListener(this);
126             super.abortScan();
127         } else {
128             logNullControllerHandler();
129         }
130     }
131
132     @Override
133     protected synchronized void stopScan() {
134         TeleinfoAbstractControllerHandler controllerHandlerRef = controllerHandler;
135         if (controllerHandlerRef != null) {
136             logger.debug("Teleinfo discovery: Stop {}", controllerHandlerRef.getThing().getUID());
137             controllerHandlerRef.removeListener(this);
138             super.stopScan();
139         } else {
140             logNullControllerHandler();
141         }
142     }
143
144     @Override
145     public void onFrameReceived(TeleinfoAbstractControllerHandler controllerHandler, Frame frame) {
146         detectNewElectricityMeterFromReceivedFrame(frame);
147     }
148
149     private void detectNewElectricityMeterFromReceivedFrame(final Frame frameSample) {
150         TeleinfoAbstractControllerHandler controllerHandlerRef = controllerHandler;
151         if (controllerHandlerRef != null) {
152             logger.debug("New eletricity meter detection from frame {}", frameSample.getId());
153             if (!(frameSample instanceof FrameAdco)) {
154                 throw new IllegalStateException("Teleinfo frame type not supported: " + frameSample.getClass());
155             }
156             final FrameAdco frameAdco = (FrameAdco) frameSample;
157
158             ThingUID thingUID = new ThingUID(getThingTypeUID(frameAdco), frameAdco.getAdco(),
159                     controllerHandlerRef.getThing().getUID().getId());
160
161             final Map<String, Object> properties = getThingProperties(frameAdco);
162             final String representationProperty = THING_ELECTRICITY_METER_PROPERTY_ADCO;
163             DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
164                     .withLabel("Teleinfo ADCO " + frameAdco.getAdco()).withThingType(getThingTypeUID(frameAdco))
165                     .withBridge(controllerHandlerRef.getThing().getUID())
166                     .withRepresentationProperty(representationProperty).build();
167
168             thingDiscovered(discoveryResult);
169         } else {
170             logNullControllerHandler();
171         }
172     }
173
174     private ThingTypeUID getThingTypeUID(final Frame teleinfoFrame) {
175         if (teleinfoFrame instanceof FrameCbemmHcOption) {
176             return THING_HC_CBEMM_ELECTRICITY_METER_TYPE_UID;
177         } else if (teleinfoFrame instanceof FrameCbemmBaseOption) {
178             return THING_BASE_CBEMM_ELECTRICITY_METER_TYPE_UID;
179         } else if (teleinfoFrame instanceof FrameCbemmEjpOption) {
180             return THING_EJP_CBEMM_ELECTRICITY_METER_TYPE_UID;
181         } else if (teleinfoFrame instanceof FrameCbemmTempoOption) {
182             return THING_TEMPO_CBEMM_ELECTRICITY_METER_TYPE_UID;
183         } else if (teleinfoFrame instanceof FrameCbemmEvolutionIccHcOption) {
184             return THING_HC_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID;
185         } else if (teleinfoFrame instanceof FrameCbemmEvolutionIccBaseOption) {
186             return THING_BASE_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID;
187         } else if (teleinfoFrame instanceof FrameCbemmEvolutionIccEjpOption) {
188             return THING_EJP_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID;
189         } else if (teleinfoFrame instanceof FrameCbemmEvolutionIccTempoOption) {
190             return THING_TEMPO_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID;
191         } else if (teleinfoFrame instanceof FrameCbetmLongHcOption) {
192             return THING_HC_CBETM_ELECTRICITY_METER_TYPE_UID;
193         } else if (teleinfoFrame instanceof FrameCbetmLongBaseOption) {
194             return THING_BASE_CBETM_ELECTRICITY_METER_TYPE_UID;
195         } else if (teleinfoFrame instanceof FrameCbetmLongEjpOption) {
196             return THING_EJP_CBETM_ELECTRICITY_METER_TYPE_UID;
197         } else if (teleinfoFrame instanceof FrameCbetmLongTempoOption) {
198             return THING_TEMPO_CBETM_ELECTRICITY_METER_TYPE_UID;
199         } else {
200             throw new IllegalStateException("Teleinfo frame type not supported: " + teleinfoFrame.getClass());
201         }
202     }
203
204     private Map<String, Object> getThingProperties(final Frame teleinfoFrame) {
205         Map<String, Object> properties = new HashMap<String, Object>();
206         if (teleinfoFrame instanceof FrameAdco) {
207             final FrameAdco frameAdco = (FrameAdco) teleinfoFrame;
208             properties.put(THING_ELECTRICITY_METER_PROPERTY_ADCO, frameAdco.getAdco());
209
210             return properties;
211         }
212
213         throw new IllegalStateException("Teleinfo frame type not supported: " + teleinfoFrame.getClass());
214     }
215
216     @Override
217     public void setThingHandler(@Nullable ThingHandler handler) {
218         if (handler instanceof TeleinfoAbstractControllerHandler) {
219             controllerHandler = (TeleinfoAbstractControllerHandler) handler;
220         }
221     }
222
223     @Override
224     public @Nullable ThingHandler getThingHandler() {
225         return controllerHandler;
226     }
227
228     private void logNullControllerHandler() {
229         logger.warn("Null controller handler");
230     }
231 }