]> git.basschouten.com Git - openhab-addons.git/blob
b5892f42e9df1cf92a610bf7f106c697c2ece659
[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.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     protected static final char PLUS_SIGN_TEMPERATURE = '0';
34     protected static final char MINUS_SIGN_TEMPERATURE = '1';
35
36     /*
37      * WS - WIND SPEED
38      */
39     protected static final int WS_WILDTYPE_IN_MPS = 0;
40     protected 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     protected static final int HV_LESS_THAN_1_LIMIT = 10;
63     protected static final int HV_LESS_THAN_10_LIMIT = 60;
64     protected static final int HV_LESS_THAN_50_LIMIT = 84;
65     protected static final int HV_LESS_THAN_1_HP_LIMIT = 93;
66     protected static final int HV_LESS_THAN_10_HP_LIMIT = 96;
67     protected static final int HV_LESS_THAN_50_HP_LIMIT = 98;
68
69     public static enum HorizontalVisibility {
70         UNDEFINED,
71         LESS_THAN_1,
72         LESS_THAN_10,
73         LESS_THAN_50,
74         MORE_THAN_50
75     }
76
77     private 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     private void setDateHourAndWindIndicator() {
111         String dayHourAndWindIndicator = "";
112
113         if (this instanceof SynopLand && stringArray.size() > 1) {
114             dayHourAndWindIndicator = stringArray.get(1);
115         } else if (stringArray.size() > 2) {
116             dayHourAndWindIndicator = stringArray.get(2);
117         }
118
119         if (!isValidString(dayHourAndWindIndicator)) {
120             return;
121         }
122
123         setHourOfObservation(dayHourAndWindIndicator);
124         setWindIndicator(dayHourAndWindIndicator);
125     }
126
127     private void setHourOfObservation(String str) {
128         try {
129             hour = Integer.parseInt(str.substring(2, 4));
130         } catch (NumberFormatException e) {
131             hour = INITIAL_VALUE;
132         }
133         try {
134             day = Integer.parseInt(str.substring(0, 2));
135         } catch (NumberFormatException e) {
136             day = INITIAL_VALUE;
137         }
138     }
139
140     private void setWindIndicator(String str) {
141         try {
142             windIndicator = Character.getNumericValue(str.charAt(4));
143         } catch (NumberFormatException e) {
144             windIndicator = INITIAL_VALUE;
145         }
146     }
147
148     private void setHorizontalVisibility() {
149         setHorizontalVisibilityInt();
150
151         if (horizontalVisibilityInt != INITIAL_VALUE) {
152
153             if (horizontalVisibilityInt < HV_LESS_THAN_1_LIMIT || horizontalVisibilityInt < HV_LESS_THAN_1_HP_LIMIT) {
154                 horizontalVisibility = HorizontalVisibility.LESS_THAN_1;
155             } else if (horizontalVisibilityInt < HV_LESS_THAN_10_LIMIT
156                     || horizontalVisibilityInt < HV_LESS_THAN_10_HP_LIMIT) {
157                 horizontalVisibility = HorizontalVisibility.LESS_THAN_10;
158             } else if (horizontalVisibilityInt < HV_LESS_THAN_50_LIMIT
159                     || horizontalVisibilityInt < HV_LESS_THAN_50_HP_LIMIT) {
160                 horizontalVisibility = HorizontalVisibility.LESS_THAN_50;
161             } else {
162                 horizontalVisibility = HorizontalVisibility.MORE_THAN_50;
163             }
164         } else {
165             horizontalVisibility = HorizontalVisibility.UNDEFINED;
166         }
167     }
168
169     protected abstract void setHorizontalVisibilityInt();
170
171     private void setTemperature() {
172         setTemperatureString();
173         temperature = INITIAL_VALUE;
174         String temperatureString = this.temperatureString;
175         if (temperatureString != null) {
176             char firstChar = temperatureString.charAt(0);
177             try {
178                 float temp = Float.parseFloat(temperatureString.substring(1, 4)) / 10;
179                 temperature = firstChar == PLUS_SIGN_TEMPERATURE ? temp
180                         : firstChar == MINUS_SIGN_TEMPERATURE ? -temp : INITIAL_VALUE;
181             } catch (NumberFormatException ignore) {
182             }
183         }
184     }
185
186     protected abstract void setTemperatureString();
187
188     private void setWindAndOvercast() {
189         setWindString();
190         if (windString != null) {
191             String gustyFlag = windString.substring(0, 2);
192             if ("00".equals(gustyFlag)) {
193                 setWindSpeed(true);
194             } else {
195                 setOcta();
196                 setWindDirection();
197                 setWindSpeed(false);
198             }
199         } else {
200             windDirection = INITIAL_VALUE;
201             windSpeed = INITIAL_VALUE;
202         }
203     }
204
205     private void setOcta() {
206         if (windString != null) {
207             octa = Character.getNumericValue(windString.charAt(0));
208         } else {
209             octa = -1;
210         }
211     }
212
213     private void setWindDirection() {
214         if (windString != null) {
215             String windDirectionString = windString.substring(1, 3);
216
217             if (windDirectionString.equals("99") || windDirectionString.equals("||")) {
218                 windDirection = INITIAL_VALUE;
219             } else {
220                 try {
221                     windDirection = Integer.parseInt(windDirectionString) * 10;
222                 } catch (NumberFormatException e) {
223                     windDirection = INITIAL_VALUE;
224                 }
225             }
226         }
227     }
228
229     private void setWindSpeed(boolean gustyWind) {
230         String speedString = null;
231         if (windString != null) {
232             speedString = windString.substring(gustyWind ? 2 : 3, 5);
233             try {
234                 windSpeed = Integer.parseInt(speedString);
235             } catch (NumberFormatException e) {
236                 windSpeed = INITIAL_VALUE;
237             }
238         }
239     }
240
241     protected abstract void setWindString();
242
243     private void setPressure() {
244         setPressureString();
245
246         if (pressureString != null) {
247
248             String pressureTemp = pressureString.substring(1, 5);
249
250             if (pressureTemp.charAt(0) == '0') {
251                 pressureTemp = '1' + pressureTemp;
252             }
253
254             try {
255                 pressure = (float) Integer.parseInt(pressureTemp) / 10;
256             } catch (NumberFormatException e) {
257                 pressure = INITIAL_VALUE;
258             }
259         }
260     }
261
262     protected abstract void setPressureString();
263
264     protected boolean isValidString(String str) {
265         return (str.length() == VALID_STRING_LENGTH);
266     }
267
268     public int getYear() {
269         return year;
270     }
271
272     public int getMonth() {
273         return month;
274     }
275
276     public int getDay() {
277         return day;
278     }
279
280     public int getHour() {
281         return hour;
282     }
283
284     public int getWindIndicator() {
285         return windIndicator;
286     }
287
288     public HorizontalVisibility getHorizontalVisibility() {
289         return horizontalVisibility;
290     }
291
292     public float getTemperature() {
293         return temperature;
294     }
295
296     public int getWindDirection() {
297         return windDirection;
298     }
299
300     public int getWindSpeed() {
301         return windSpeed;
302     }
303
304     public float getPressure() {
305         return pressure;
306     }
307
308     public int getOcta() {
309         return octa;
310     }
311
312     public Unit<Speed> getWindUnit() {
313         return (getWindIndicator() == WS_WILDTYPE_IN_MPS || getWindIndicator() == WS_ANEMOMETER_IN_MPS)
314                 ? Units.METRE_PER_SECOND
315                 : Units.KNOT;
316     }
317 }