]> git.basschouten.com Git - openhab-addons.git/blob
525ecff577222c9511fc5ac7971dc42e76486d0c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.synopanalyzer.internal.synop;
14
15 import java.util.List;
16
17 import javax.measure.Unit;
18 import javax.measure.quantity.Speed;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.core.library.unit.Units;
23
24 /**
25  * The {@link Synop} is the ancestor common class for analyzing
26  * Synop messages
27  *
28  * @author Jonarzz - Initial contribution
29  */
30 @NonNullByDefault
31 public abstract class Synop {
32     protected static final int INITIAL_VALUE = -1000;
33     private static final char PLUS_SIGN_TEMPERATURE = '0';
34     private static final char MINUS_SIGN_TEMPERATURE = '1';
35
36     /*
37      * WS - WIND SPEED
38      */
39     private static final int WS_WILDTYPE_IN_MPS = 0;
40     private static final int WS_ANEMOMETER_IN_MPS = 1;
41
42     /*
43      * HV - HORIZONTAL VISIBILITY [IN KILOMETERS]
44      * VALUES FROM "00" TO "50" AND FROM "56" TO "99"
45      * 00 MEANS HV = BELOW 0,1
46      * DECIMAL SCOPE MEANS HV = XX / 10
47      * UNIT SCOPE MEANS HV = XX - 50
48      * 89 MEANS HV = OVER 70
49      * 90-99 ROUGHLY NUMBERING :
50      * 90 - < 0,05 km
51      * 91 >= 0,05 < 0,2 km
52      * 92 >= 0,2 < 0,5 km
53      * 93 >= 0,5 < 1,0 km
54      * 94 >= 1,0 < 2,0 km
55      * 95 >= 2,0 < 4,0 km
56      * 96 >= 4,0 < 10,0 km
57      * 97 >= 10,0 < 20,0 km
58      * 98 >= 20,0 < 50,0 km
59      * 99 - > 50 km
60      * HP - high precision
61      */
62     private static final int HV_LESS_THAN_1_LIMIT = 10;
63     private static final int HV_LESS_THAN_10_LIMIT = 60;
64     private static final int HV_LESS_THAN_50_LIMIT = 84;
65     private static final int HV_LESS_THAN_1_HP_LIMIT = 93;
66     private static final int HV_LESS_THAN_10_HP_LIMIT = 96;
67     private static final int HV_LESS_THAN_50_HP_LIMIT = 98;
68
69     public enum HorizontalVisibility {
70         UNDEFINED,
71         LESS_THAN_1,
72         LESS_THAN_10,
73         LESS_THAN_50,
74         MORE_THAN_50
75     }
76
77     private static final int VALID_STRING_LENGTH = 5;
78
79     protected final List<String> stringArray;
80
81     private int year;
82     private int month;
83     private int day;
84     private int hour;
85     private int windIndicator;
86
87     private HorizontalVisibility horizontalVisibility = HorizontalVisibility.UNDEFINED;
88     private float temperature;
89
90     private int octa;
91     private int windDirection;
92     private int windSpeed;
93     private float pressure;
94
95     protected int horizontalVisibilityInt = INITIAL_VALUE;
96     protected @Nullable String temperatureString;
97     protected @Nullable String windString;
98     protected @Nullable String pressureString;
99
100     public Synop(List<String> stringArray) {
101         this.stringArray = stringArray;
102
103         setDateHourAndWindIndicator();
104         setHorizontalVisibility();
105         setTemperature();
106         setWindAndOvercast();
107         setPressure();
108     }
109
110     protected abstract void setTemperatureString();
111
112     protected abstract void setHorizontalVisibilityInt();
113
114     protected abstract void setPressureString();
115
116     protected abstract void setWindString();
117
118     private void setDateHourAndWindIndicator() {
119         String dayHourAndWindIndicator = "";
120
121         if (this instanceof SynopLand && stringArray.size() > 1) {
122             dayHourAndWindIndicator = stringArray.get(1);
123         } else if (stringArray.size() > 2) {
124             dayHourAndWindIndicator = stringArray.get(2);
125         }
126
127         if (!isValidString(dayHourAndWindIndicator)) {
128             return;
129         }
130
131         setHourOfObservation(dayHourAndWindIndicator);
132         setWindIndicator(dayHourAndWindIndicator);
133     }
134
135     private void setHourOfObservation(String str) {
136         try {
137             hour = Integer.parseInt(str.substring(2, 4));
138         } catch (NumberFormatException e) {
139             hour = INITIAL_VALUE;
140         }
141         try {
142             day = Integer.parseInt(str.substring(0, 2));
143         } catch (NumberFormatException e) {
144             day = INITIAL_VALUE;
145         }
146     }
147
148     private void setWindIndicator(String str) {
149         try {
150             windIndicator = Character.getNumericValue(str.charAt(4));
151         } catch (NumberFormatException e) {
152             windIndicator = INITIAL_VALUE;
153         }
154     }
155
156     private void setHorizontalVisibility() {
157         setHorizontalVisibilityInt();
158         if (horizontalVisibilityInt != INITIAL_VALUE) {
159             if (horizontalVisibilityInt < HV_LESS_THAN_1_LIMIT || horizontalVisibilityInt < HV_LESS_THAN_1_HP_LIMIT) {
160                 horizontalVisibility = HorizontalVisibility.LESS_THAN_1;
161             } else if (horizontalVisibilityInt < HV_LESS_THAN_10_LIMIT
162                     || horizontalVisibilityInt < HV_LESS_THAN_10_HP_LIMIT) {
163                 horizontalVisibility = HorizontalVisibility.LESS_THAN_10;
164             } else if (horizontalVisibilityInt < HV_LESS_THAN_50_LIMIT
165                     || horizontalVisibilityInt < HV_LESS_THAN_50_HP_LIMIT) {
166                 horizontalVisibility = HorizontalVisibility.LESS_THAN_50;
167             } else {
168                 horizontalVisibility = HorizontalVisibility.MORE_THAN_50;
169             }
170         } else {
171             horizontalVisibility = HorizontalVisibility.UNDEFINED;
172         }
173     }
174
175     private void setTemperature() {
176         setTemperatureString();
177         temperature = INITIAL_VALUE;
178         String temperatureString = this.temperatureString;
179         if (temperatureString != null) {
180             char firstChar = temperatureString.charAt(0);
181             try {
182                 float temp = Float.parseFloat(temperatureString.substring(1, 4)) / 10;
183                 temperature = firstChar == PLUS_SIGN_TEMPERATURE ? temp
184                         : firstChar == MINUS_SIGN_TEMPERATURE ? -temp : INITIAL_VALUE;
185             } catch (NumberFormatException ignore) {
186             }
187         }
188     }
189
190     private void setWindAndOvercast() {
191         setWindString();
192         String localWind = windString;
193         if (localWind != null) {
194             String gustyFlag = localWind.substring(0, 2);
195             if ("00".equals(gustyFlag)) {
196                 setWindSpeed(true);
197             } else {
198                 setOcta();
199                 setWindDirection();
200                 setWindSpeed(false);
201             }
202         } else {
203             windDirection = INITIAL_VALUE;
204             windSpeed = INITIAL_VALUE;
205         }
206     }
207
208     private void setOcta() {
209         String localWind = windString;
210         if (localWind != null) {
211             octa = Character.getNumericValue(localWind.charAt(0));
212         } else {
213             octa = -1;
214         }
215     }
216
217     private void setWindDirection() {
218         String localWind = windString;
219         if (localWind != null) {
220             String windDirectionString = localWind.substring(1, 3);
221
222             if ("99".equals(windDirectionString) || "||".equals(windDirectionString)) {
223                 windDirection = INITIAL_VALUE;
224             } else {
225                 try {
226                     windDirection = Integer.parseInt(windDirectionString) * 10;
227                 } catch (NumberFormatException e) {
228                     windDirection = INITIAL_VALUE;
229                 }
230             }
231         }
232     }
233
234     private void setWindSpeed(boolean gustyWind) {
235         String speedString = null;
236         String localWind = windString;
237         if (localWind != null) {
238             speedString = localWind.substring(gustyWind ? 2 : 3, 5);
239             try {
240                 windSpeed = Integer.parseInt(speedString);
241             } catch (NumberFormatException e) {
242                 windSpeed = INITIAL_VALUE;
243             }
244         }
245     }
246
247     private void setPressure() {
248         setPressureString();
249         String localPressure = pressureString;
250         if (localPressure != null) {
251             String pressureTemp = localPressure.substring(1, 5);
252             if (pressureTemp.charAt(0) == '0') {
253                 pressureTemp = '1' + pressureTemp;
254             }
255             try {
256                 pressure = (float) Integer.parseInt(pressureTemp) / 10;
257             } catch (NumberFormatException e) {
258                 pressure = INITIAL_VALUE;
259             }
260         }
261     }
262
263     protected boolean isValidString(String str) {
264         return (str.length() == VALID_STRING_LENGTH);
265     }
266
267     public int getYear() {
268         return year;
269     }
270
271     public int getMonth() {
272         return month;
273     }
274
275     public int getDay() {
276         return day;
277     }
278
279     public int getHour() {
280         return hour;
281     }
282
283     public int getWindIndicator() {
284         return windIndicator;
285     }
286
287     public HorizontalVisibility getHorizontalVisibility() {
288         return horizontalVisibility;
289     }
290
291     public float getTemperature() {
292         return temperature;
293     }
294
295     public @Nullable Integer getWindDirection() {
296         return windDirection != INITIAL_VALUE ? windDirection : null;
297     }
298
299     public int getWindSpeed() {
300         return windSpeed;
301     }
302
303     public float getPressure() {
304         return pressure;
305     }
306
307     public int getOcta() {
308         return octa;
309     }
310
311     public Unit<Speed> getWindUnit() {
312         return (getWindIndicator() == WS_WILDTYPE_IN_MPS || getWindIndicator() == WS_ANEMOMETER_IN_MPS)
313                 ? Units.METRE_PER_SECOND
314                 : Units.KNOT;
315     }
316 }