]> git.basschouten.com Git - openhab-addons.git/blob
69cdd0271101080e7eb8e1994a8b648706cfe6d3
[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.mybmw.internal.utils;
14
15 import java.time.Instant;
16 import java.time.ZoneId;
17 import java.time.ZonedDateTime;
18 import java.time.format.DateTimeFormatter;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.mybmw.internal.dto.charge.Time;
23 import org.openhab.core.library.types.DateTimeType;
24 import org.openhab.core.library.types.StringType;
25 import org.openhab.core.types.State;
26 import org.openhab.core.types.UnDefType;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * The {@link Converter} Conversion Helpers
32  *
33  * @author Bernd Weymann - Initial contribution
34  * @author Martin Grassl - extract some methods to other classes
35  */
36 @NonNullByDefault
37 public interface Converter {
38     static final Logger LOGGER = LoggerFactory.getLogger(Converter.class);
39
40     static final String SPLIT_HYPHEN = "-";
41     static final String SPLIT_BRACKET = "\\(";
42
43     static State zonedToLocalDateTime(@Nullable String input, ZoneId timezone) {
44         if (input != null && !input.isEmpty()) {
45             try {
46                 String localTimeString = Instant.parse(input).atZone(timezone)
47                         .format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
48                 return DateTimeType.valueOf(localTimeString);
49             } catch (Exception e) {
50                 LOGGER.debug("Unable to parse date {} - {}", input, e.getMessage());
51                 return UnDefType.UNDEF;
52             }
53         } else {
54             return UnDefType.UNDEF;
55         }
56     }
57
58     /**
59      * converts a string into a unified format
60      * - string is Capitalized
61      * - null is empty string
62      * - single character remains
63      * 
64      * @param input
65      * @return
66      */
67     static String toTitleCase(@Nullable String input) {
68         if (input == null || input.isEmpty()) {
69             return toTitleCase(Constants.UNDEF);
70         } else if (input.length() == 1) {
71             return input;
72         } else {
73             // first, replace all underscores with spaces and make it lower case
74             String lower = input.replaceAll(Constants.UNDERLINE, Constants.SPACE).toLowerCase();
75
76             //
77             String converted = toTitleCase(lower, Constants.SPACE);
78             converted = toTitleCase(converted, SPLIT_HYPHEN);
79             converted = toTitleCase(converted, SPLIT_BRACKET);
80             return converted;
81         }
82     }
83
84     private static String toTitleCase(String input, String splitter) {
85         // first, split all parts by the splitting string
86         String[] arr = input.split(splitter);
87
88         StringBuilder sb = new StringBuilder();
89         for (int i = 0; i < arr.length; i++) {
90             if (i > 0) {
91                 sb.append(splitter.replaceAll("\\\\", Constants.EMPTY));
92             }
93             sb.append(Character.toUpperCase(arr[i].charAt(0))).append(arr[i].substring(1));
94         }
95         return sb.toString().trim();
96     }
97
98     /**
99      * Measure distance between 2 coordinates
100      *
101      * @param sourceLatitude
102      * @param sourceLongitude
103      * @param destinationLatitude
104      * @param destinationLongitude
105      * @return distance
106      */
107     static double measureDistance(double sourceLatitude, double sourceLongitude, double destinationLatitude,
108             double destinationLongitude) {
109         double earthRadius = 6378.137; // Radius of earth in KM
110         double dLat = destinationLatitude * Math.PI / 180 - sourceLatitude * Math.PI / 180;
111         double dLon = destinationLongitude * Math.PI / 180 - sourceLongitude * Math.PI / 180;
112         double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(sourceLatitude * Math.PI / 180)
113                 * Math.cos(destinationLatitude * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
114         double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
115         return earthRadius * c;
116     }
117
118     /**
119      * Easy function but there's some measures behind:
120      * Guessing the range of the Vehicle on Map. If you can drive x kilometers with
121      * your Vehicle it's not feasible to
122      * project this x km Radius on Map. The roads to be taken are causing some
123      * overhead because they are not a straight
124      * line from Location A to B.
125      * I've taken some measurements to calculate the overhead factor based on Google
126      * Maps
127      * Berlin - Dresden: Road Distance: 193 air-line Distance 167 = Factor 87%
128      * Kassel - Frankfurt: Road Distance: 199 air-line Distance 143 = Factor 72%
129      * After measuring more distances you'll find out that the outcome is between
130      * 70% and 90%. So
131      *
132      * This depends also on the roads of a concrete route but this is only a guess
133      * without any Route Navigation behind
134      *
135      * In future it's foreseen to replace this with BMW RangeMap Service which isn't
136      * running at the moment.
137      *
138      * @param range
139      * @return mapping from air-line distance to "real road" distance
140      */
141     static int guessRangeRadius(double range) {
142         return (int) (range * 0.8);
143     }
144
145     /**
146      * checks if a string is a valid integer
147      * 
148      * @param fullString
149      * @return
150      */
151     static int parseIntegerString(String fullString) {
152         int index = -1;
153         try {
154             index = Integer.parseInt(fullString);
155         } catch (NumberFormatException nfe) {
156         }
157         return index;
158     }
159
160     static State getConnectionState(boolean connected) {
161         if (connected) {
162             return StringType.valueOf(Constants.CONNECTED);
163         } else {
164             return StringType.valueOf(Constants.UNCONNECTED);
165         }
166     }
167
168     static String getCurrentISOTime() {
169         return ZonedDateTime.now().format(DateTimeFormatter.ISO_INSTANT);
170     }
171
172     static String getTime(Time t) {
173         StringBuffer time = new StringBuffer();
174         if (t.getHour() < 10) {
175             time.append("0");
176         }
177         time.append(Integer.toString(t.getHour())).append(":");
178         if (t.getMinute() < 10) {
179             time.append("0");
180         }
181         time.append(Integer.toString(t.getMinute()));
182         return time.toString();
183     }
184 }