2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.solarwatt.internal.discovery;
15 import static org.openhab.binding.solarwatt.internal.SolarwattBindingConstants.*;
17 import java.util.HashMap;
19 import java.util.concurrent.ScheduledFuture;
20 import java.util.concurrent.TimeUnit;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.solarwatt.internal.domain.model.BatteryConverter;
25 import org.openhab.binding.solarwatt.internal.domain.model.Device;
26 import org.openhab.binding.solarwatt.internal.domain.model.EVStation;
27 import org.openhab.binding.solarwatt.internal.domain.model.GridFlow;
28 import org.openhab.binding.solarwatt.internal.domain.model.Inverter;
29 import org.openhab.binding.solarwatt.internal.domain.model.Location;
30 import org.openhab.binding.solarwatt.internal.domain.model.PVPlant;
31 import org.openhab.binding.solarwatt.internal.domain.model.PowerMeter;
32 import org.openhab.binding.solarwatt.internal.handler.EnergyManagerHandler;
33 import org.openhab.core.config.discovery.AbstractDiscoveryService;
34 import org.openhab.core.config.discovery.DiscoveryResult;
35 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
36 import org.openhab.core.config.discovery.DiscoveryService;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.ThingTypeUID;
39 import org.openhab.core.thing.ThingUID;
40 import org.openhab.core.thing.binding.ThingHandler;
41 import org.openhab.core.thing.binding.ThingHandlerService;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
46 * Discovery service to discover devices attached to the energy manager.
48 * @author Sven Carstens - Initial contribution
51 public class SolarwattDevicesDiscoveryService extends AbstractDiscoveryService
52 implements ThingHandlerService, DiscoveryService {
54 private static final int TIMEOUT_SECONDS = 20;
56 private final Logger logger = LoggerFactory.getLogger(SolarwattDevicesDiscoveryService.class);
57 private @Nullable EnergyManagerHandler energyManagerHandler;
60 * Job which will do the background scanning
62 private final EnergymanagerScan scanningRunnable;
65 * Schedule for scanning
67 private @Nullable ScheduledFuture<?> scanningJob;
69 public SolarwattDevicesDiscoveryService() {
70 super(TIMEOUT_SECONDS);
71 this.scanningRunnable = new EnergymanagerScan();
77 public void setThingHandler(final @Nullable ThingHandler handler) {
78 if (handler instanceof EnergyManagerHandler) {
79 this.energyManagerHandler = (EnergyManagerHandler) handler;
84 public @Nullable ThingHandler getThingHandler() {
85 return this.energyManagerHandler;
89 public void deactivate() {
90 this.stopBackgroundDiscovery();
94 protected void startBackgroundDiscovery() {
95 ScheduledFuture<?> localScanningJob = this.scanningJob;
96 if (localScanningJob == null || localScanningJob.isCancelled()) {
97 this.scanningJob = this.scheduler.scheduleWithFixedDelay(this.scanningRunnable, 5, 5 * 60,
103 protected void stopBackgroundDiscovery() {
104 ScheduledFuture<?> localScanningJob = this.scanningJob;
105 if (localScanningJob != null && !localScanningJob.isCancelled()) {
106 localScanningJob.cancel(true);
107 this.scanningJob = null;
112 protected synchronized void startScan() {
113 this.removeOlderResults(this.getTimestampOfLastScan());
114 final EnergyManagerHandler localEnergyManagerHandler = this.energyManagerHandler;
116 if (localEnergyManagerHandler == null
117 || localEnergyManagerHandler.getThing().getStatus() != ThingStatus.ONLINE) {
118 this.logger.warn("Energymanager handler not available: {}", localEnergyManagerHandler);
121 this.scanForDeviceThings();
125 * Scans for device things.
127 * Walks through the list of devices and adds discovery results for the supported devices.
129 private void scanForDeviceThings() {
130 EnergyManagerHandler localEnergyManagerHandler = this.energyManagerHandler;
131 if (localEnergyManagerHandler != null) {
132 final Map<String, Device> devices = localEnergyManagerHandler.getDevices();
134 final ThingUID bridgeUID = localEnergyManagerHandler.getThing().getUID();
136 if (devices == null) {
137 this.logger.warn("No device data for solarwatt devices in discovery for energy manager {}.", bridgeUID);
139 devices.forEach((key, entry) -> {
140 if (entry instanceof BatteryConverter) {
141 this.discover(bridgeUID, entry, THING_TYPE_BATTERYCONVERTER);
142 } else if (entry instanceof Inverter) {
143 this.discover(bridgeUID, entry, THING_TYPE_INVERTER);
144 } else if (entry instanceof PowerMeter) {
145 this.discover(bridgeUID, entry, THING_TYPE_POWERMETER);
146 } else if (entry instanceof EVStation) {
147 this.discover(bridgeUID, entry, THING_TYPE_EVSTATION);
148 } else if (entry instanceof Location) {
149 this.discover(bridgeUID, entry, THING_TYPE_LOCATION);
150 } else if (entry instanceof PVPlant) {
151 this.discover(bridgeUID, entry, THING_TYPE_PVPLANT);
152 } else if (entry instanceof GridFlow) {
153 this.discover(bridgeUID, entry, THING_TYPE_GRIDFLOW);
161 * Create a discovery result and add to result.
163 * @param bridgeID to which this device belongs
164 * @param entry describing the device
165 * @param typeUID for matching thing
167 private void discover(final ThingUID bridgeID, final Device entry, final ThingTypeUID typeUID) {
168 final ThingUID thingUID = new ThingUID(typeUID, bridgeID, this.rewriteGuid(entry.getGuid()));
169 final Map<String, Object> properties = new HashMap<>(5);
171 properties.put(THING_PROPERTIES_GUID, entry.getGuid());
172 final DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(bridgeID)
173 .withRepresentationProperty(THING_PROPERTIES_GUID).withProperties(properties)
174 .withLabel("Solarwatt " + entry.getLabel()).build();
175 this.thingDiscovered(discoveryResult);
179 * Rewrite energy manager guids to be acceptable to openhab.
181 * @param emGuid from energy manager
182 * @return guid for openhab
184 private String rewriteGuid(String emGuid) {
185 return emGuid.replaceAll(":", "-");
188 public class EnergymanagerScan implements Runnable {
191 SolarwattDevicesDiscoveryService.this.startScan();