]> git.basschouten.com Git - openhab-addons.git/blob
3e47191f374219df49c44d1fb838f3ff4c27f9a2
[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.homewizard.internal;
14
15 import java.io.IOException;
16 import java.util.concurrent.ScheduledFuture;
17 import java.util.concurrent.TimeUnit;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.core.io.net.http.HttpUtil;
22 import org.openhab.core.library.types.DateTimeType;
23 import org.openhab.core.library.types.QuantityType;
24 import org.openhab.core.library.unit.SIUnits;
25 import org.openhab.core.library.unit.Units;
26 import org.openhab.core.thing.ChannelUID;
27 import org.openhab.core.thing.Thing;
28 import org.openhab.core.thing.ThingStatus;
29 import org.openhab.core.thing.ThingStatusDetail;
30 import org.openhab.core.thing.binding.BaseThingHandler;
31 import org.openhab.core.types.Command;
32
33 import com.google.gson.FieldNamingPolicy;
34 import com.google.gson.Gson;
35 import com.google.gson.GsonBuilder;
36
37 /**
38  * The {@link HomeWizardHandler} is responsible for handling commands, which are
39  * sent to one of the channels.
40  *
41  * @author DaniĆ«l van Os - Initial contribution
42  */
43 @NonNullByDefault
44 public class HomeWizardHandler extends BaseThingHandler {
45
46     private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
47             .create();
48
49     private HomeWizardConfiguration config = new HomeWizardConfiguration();
50     private @Nullable ScheduledFuture<?> pollingJob;
51
52     private String apiURL = "";
53     private String meterModel = "";
54     private int meterVersion = 0;
55
56     /**
57      * Constructor
58      *
59      * @param thing The thing to handle
60      */
61     public HomeWizardHandler(Thing thing) {
62         super(thing);
63     }
64
65     /**
66      * Not listening to any commands.
67      */
68     @Override
69     public void handleCommand(ChannelUID channelUID, Command command) {
70     }
71
72     /**
73      * If a host has been specified start polling it
74      */
75     @Override
76     public void initialize() {
77         config = getConfigAs(HomeWizardConfiguration.class);
78         if (configure()) {
79             pollingJob = scheduler.scheduleWithFixedDelay(this::pollingCode, 0, config.refreshDelay, TimeUnit.SECONDS);
80         }
81     }
82
83     /**
84      * Check the current configuration
85      *
86      * @return true if the configuration is ok to start polling, false otherwise
87      */
88     private boolean configure() {
89         if (config.ipAddress.trim().isEmpty()) {
90             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
91                     "Missing ipAddress/host configuration");
92             return false;
93         } else {
94             updateStatus(ThingStatus.UNKNOWN);
95             apiURL = String.format("http://%s/api/v1/data", config.ipAddress.trim());
96             return true;
97         }
98     }
99
100     /**
101      * dispose: stop the poller
102      */
103     @Override
104     public void dispose() {
105         var job = pollingJob;
106         if (job != null) {
107             job.cancel(true);
108         }
109         pollingJob = null;
110     }
111
112     /**
113      * The actual polling loop
114      */
115     private void pollingCode() {
116         final String result;
117
118         try {
119             result = HttpUtil.executeUrl("GET", apiURL, 30000);
120         } catch (IOException e) {
121             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
122                     String.format("Unable to query P1 Meter: %s", e.getMessage()));
123             return;
124         }
125
126         if (result.trim().isEmpty()) {
127             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
128                     "P1 Meter API returned empty status");
129             return;
130         }
131
132         P1Payload payload = gson.fromJson(result, P1Payload.class);
133         if (payload == null) {
134             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
135                     "Unable to parse response from P1 meter");
136             return;
137         }
138
139         if ("".equals(payload.getMeterModel())) {
140             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Results from API are empty");
141             return;
142         }
143
144         updateStatus(ThingStatus.ONLINE);
145
146         if (!meterModel.equals(payload.getMeterModel())) {
147             meterModel = payload.getMeterModel();
148             updateProperty(HomeWizardBindingConstants.PROPERTY_METER_MODEL, meterModel);
149         }
150
151         if (meterVersion != payload.getSmrVersion()) {
152             meterVersion = payload.getSmrVersion();
153             updateProperty(HomeWizardBindingConstants.PROPERTY_METER_VERSION, String.format("%d", meterVersion));
154         }
155
156         updateState(HomeWizardBindingConstants.CHANNEL_ENERGY_IMPORT_T1,
157                 new QuantityType<>(payload.getTotalEnergyImportT1Kwh(), Units.KILOWATT_HOUR));
158         updateState(HomeWizardBindingConstants.CHANNEL_ENERGY_IMPORT_T2,
159                 new QuantityType<>(payload.getTotalEnergyImportT2Kwh(), Units.KILOWATT_HOUR));
160         updateState(HomeWizardBindingConstants.CHANNEL_ENERGY_EXPORT_T1,
161                 new QuantityType<>(payload.getTotalEnergyExportT1Kwh(), Units.KILOWATT_HOUR));
162         updateState(HomeWizardBindingConstants.CHANNEL_ENERGY_EXPORT_T2,
163                 new QuantityType<>(payload.getTotalEnergyExportT2Kwh(), Units.KILOWATT_HOUR));
164
165         updateState(HomeWizardBindingConstants.CHANNEL_ACTIVE_POWER,
166                 new QuantityType<>(payload.getActivePowerW(), Units.WATT));
167         updateState(HomeWizardBindingConstants.CHANNEL_ACTIVE_POWER_L1,
168                 new QuantityType<>(payload.getActivePowerL1W(), Units.WATT));
169         updateState(HomeWizardBindingConstants.CHANNEL_ACTIVE_POWER_L2,
170                 new QuantityType<>(payload.getActivePowerL2W(), Units.WATT));
171         updateState(HomeWizardBindingConstants.CHANNEL_ACTIVE_POWER_L3,
172                 new QuantityType<>(payload.getActivePowerL3W(), Units.WATT));
173
174         updateState(HomeWizardBindingConstants.CHANNEL_TOTAL_GAS,
175                 new QuantityType<>(payload.getTotalGasM3(), SIUnits.CUBIC_METRE));
176
177         // 210119164000
178         long dtv = payload.getGasTimestamp();
179         long seconds = dtv % 100;
180
181         dtv /= 100;
182         long minutes = dtv % 100;
183
184         dtv /= 100;
185         long hours = dtv % 100;
186
187         dtv /= 100;
188         long day = dtv % 100;
189
190         dtv /= 100;
191         long month = dtv % 100;
192
193         dtv /= 100;
194         long year = dtv + 2000; // Where (When?) have I seen this before?
195
196         DateTimeType dtt = DateTimeType
197                 .valueOf(String.format("%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hours, minutes, seconds));
198         updateState(HomeWizardBindingConstants.CHANNEL_GAS_TIMESTAMP, dtt);
199     }
200 }