[Synopanalyzer] Adding French localization, correction on overcast channel (#10113)

* Adding French localization of the binding
* Correction on overcast channel
* Correcting nullable issues

Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
Gaël L'hopital 2021-02-17 11:50:14 +01:00 committed by GitHub
parent cb9a118581
commit da5c4c8650
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 85 additions and 42 deletions

View File

@ -42,11 +42,12 @@ import org.slf4j.LoggerFactory;
*/
@NonNullByDefault
public class SynopAnalyzerDiscoveryService extends AbstractDiscoveryService {
private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerDiscoveryService.class);
private static final int DISCOVER_TIMEOUT_SECONDS = 5;
private LocationProvider locationProvider;
private final StationDB stationDB;
private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerDiscoveryService.class);
private final Map<Integer, Double> distances = new HashMap<>();
private final LocationProvider locationProvider;
private final StationDB stationDB;
/**
* Creates a SynopAnalyzerDiscoveryService with enabled autostart.
@ -84,8 +85,8 @@ public class SynopAnalyzerDiscoveryService extends AbstractDiscoveryService {
Integer nearestId = result.entrySet().iterator().next().getKey();
Optional<Station> station = stationDB.stations.stream().filter(s -> s.idOmm == nearestId).findFirst();
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_SYNOP, Integer.toString(nearestId)))
.withLabel("Synop : " + station.get().usualName)
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_SYNOP, nearestId.toString()))
.withLabel(String.format("Synop : %s", station.get().usualName))
.withProperty(SynopAnalyzerConfiguration.STATION_ID, nearestId)
.withRepresentationProperty(SynopAnalyzerConfiguration.STATION_ID).build());
}

View File

@ -29,7 +29,7 @@ public enum Overcast {
public static Overcast fromOcta(int octa) {
if (octa == 0) {
return Overcast.CLEAR_SKY;
} else if (octa > 0 && octa < 8) {
} else if (octa > 0 && octa < 9) {
return Overcast.CLOUDY;
} else if (octa == 9) {
return Overcast.SKY_NOT_VISIBLE;

View File

@ -18,9 +18,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Collections;
import java.nio.charset.StandardCharsets;
import java.util.Hashtable;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@ -55,28 +54,25 @@ import com.google.gson.Gson;
@NonNullByDefault
public class SynopAnalyzerHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerHandlerFactory.class);
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_SYNOP);
private final LocationProvider locationProvider;
private final Gson gson;
private @NonNullByDefault({}) StationDB stationDB;
private final Gson gson = new Gson();
private @Nullable StationDB stationDB;
private @Nullable ServiceRegistration<?> serviceReg;
@Activate
public SynopAnalyzerHandlerFactory(@Reference LocationProvider locationProvider) {
this.locationProvider = locationProvider;
this.gson = new Gson();
}
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
return THING_SYNOP.equals(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
return thingTypeUID.equals(THING_SYNOP) ? new SynopAnalyzerHandler(thing, locationProvider, stationDB) : null;
return supportsThingType(thing.getThingTypeUID()) ? new SynopAnalyzerHandler(thing, locationProvider, stationDB)
: null;
}
@Override
@ -84,14 +80,14 @@ public class SynopAnalyzerHandlerFactory extends BaseThingHandlerFactory {
super.activate(componentContext);
try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/db/stations.json");
Reader reader = new InputStreamReader(is, "UTF-8");) {
Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8);) {
stationDB = gson.fromJson(reader, StationDB.class);
registerDiscoveryService();
StationDB stations = gson.fromJson(reader, StationDB.class);
registerDiscoveryService(stations);
this.stationDB = stations;
logger.debug("Discovery service for Synop Stations registered.");
} catch (IOException e) {
logger.warn("Unable to read synop stations database");
stationDB = new StationDB();
}
}
@ -101,8 +97,8 @@ public class SynopAnalyzerHandlerFactory extends BaseThingHandlerFactory {
super.deactivate(componentContext);
}
private void registerDiscoveryService() {
SynopAnalyzerDiscoveryService discoveryService = new SynopAnalyzerDiscoveryService(stationDB, locationProvider);
private void registerDiscoveryService(StationDB stations) {
SynopAnalyzerDiscoveryService discoveryService = new SynopAnalyzerDiscoveryService(stations, locationProvider);
serviceReg = bundleContext.registerService(DiscoveryService.class.getName(), discoveryService,
new Hashtable<>());

View File

@ -28,12 +28,12 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.measure.quantity.Speed;
import javax.ws.rs.HttpMethod;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.synopanalyser.internal.synop.Overcast;
import org.openhab.binding.synopanalyser.internal.synop.StationDB;
import org.openhab.binding.synopanalyser.internal.synop.StationDB.Station;
import org.openhab.binding.synopanalyser.internal.synop.Synop;
import org.openhab.binding.synopanalyser.internal.synop.SynopLand;
import org.openhab.binding.synopanalyser.internal.synop.SynopMobile;
@ -77,12 +77,11 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(SynopAnalyzerHandler.class);
private @Nullable ScheduledFuture<?> executionJob;
// private @NonNullByDefault({}) SynopAnalyzerConfiguration configuration;
private @NonNullByDefault({}) String formattedStationId;
private final LocationProvider locationProvider;
private final StationDB stationDB;
private final @Nullable StationDB stationDB;
public SynopAnalyzerHandler(Thing thing, LocationProvider locationProvider, StationDB stationDB) {
public SynopAnalyzerHandler(Thing thing, LocationProvider locationProvider, @Nullable StationDB stationDB) {
super(thing);
this.locationProvider = locationProvider;
this.stationDB = stationDB;
@ -95,20 +94,18 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
logger.info("Scheduling Synop update thread to run every {} minute for Station '{}'",
configuration.refreshInterval, formattedStationId);
if (thing.getProperties().isEmpty()) {
discoverAttributes(configuration.stationId);
StationDB stations = stationDB;
if (thing.getProperties().isEmpty() && stations != null) {
discoverAttributes(stations, configuration.stationId);
}
executionJob = scheduler.scheduleWithFixedDelay(this::updateSynopChannels, 0, configuration.refreshInterval,
TimeUnit.MINUTES);
updateStatus(ThingStatus.UNKNOWN);
}
protected void discoverAttributes(int stationId) {
final Map<String, String> properties = new HashMap<>();
Optional<Station> station = stationDB.stations.stream().filter(s -> stationId == s.idOmm).findFirst();
station.ifPresent(s -> {
protected void discoverAttributes(StationDB stations, int stationId) {
stations.stations.stream().filter(s -> stationId == s.idOmm).findFirst().ifPresent(s -> {
Map<String, String> properties = new HashMap<>();
properties.put("Usual name", s.usualName);
properties.put("Location", s.getLocation());
@ -119,9 +116,8 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
properties.put("Distance", new QuantityType<>(distance, SIUnits.METRE).toString());
}
updateProperties(properties);
});
updateProperties(properties);
}
private Optional<Synop> getLastAvailableSynop() {
@ -129,7 +125,7 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
String url = forgeURL();
try {
String answer = HttpUtil.executeUrl("GET", url, REQUEST_TIMEOUT_MS);
String answer = HttpUtil.executeUrl(HttpMethod.GET, url, REQUEST_TIMEOUT_MS);
List<String> messages = Arrays.asList(answer.split("\n"));
if (!messages.isEmpty()) {
String message = messages.get(messages.size() - 1);
@ -159,7 +155,9 @@ public class SynopAnalyzerHandler extends BaseThingHandler {
synop.ifPresent(theSynop -> {
getThing().getChannels().forEach(channel -> {
String channelId = channel.getUID().getId();
updateState(channelId, getChannelState(channelId, theSynop));
if (isLinked(channelId)) {
updateState(channelId, getChannelState(channelId, theSynop));
}
});
});
}

View File

@ -0,0 +1,44 @@
# binding
binding.synopanalyzer.name = Extension Synop Analyzer
binding.synopanalyzer.description = Synop Analyzer permet de télécharger et interpréter les messages SYNOP.
# thing type
thing-type.synopanalyzer.synopanalyzer.label = Message Synop
thing-type.synopanalyzer.synopanalyzer.description = Décodage du dernier message d'une station Synop.
# channel types
channel-type.synopanalyzer.wind-speed-beaufort.label = Beaufort
channel-type.synopanalyzer.wind-speed-beaufort.description = Force du vent sur l'échelle Beaufort.
channel-type.synopanalyzer.wind-direction.label = Direction du vent
channel-type.synopanalyzer.wind-direction.description = Equivalent cardinal de la direction du vent.
# Only translating those that needs a french adaptation (containing "W")
channel-type.synopanalyzer.wind-direction.state.option.SSW = SSO
channel-type.synopanalyzer.wind-direction.state.option.SW = SO
channel-type.synopanalyzer.wind-direction.state.option.WSW = OSO
channel-type.synopanalyzer.wind-direction.state.option.W = O
channel-type.synopanalyzer.wind-direction.state.option.WNW = ONO
channel-type.synopanalyzer.wind-direction.state.option.NW = NO
channel-type.synopanalyzer.wind-direction.state.option.NNW = NNO
channel-type.synopanalyzer.octa.label = Octa
channel-type.synopanalyzer.octa.description = Evaluation de la couverture nuageuse.
channel-type.synopanalyzer.attenuation-factor.label = Coefficient d'atténuation
channel-type.synopanalyzer.attenuation-factor.description = Atténuation générée par la couverture nuageuse.
channel-type.synopanalyzer.overcast.label = Couverture nuageuse
channel-type.synopanalyzer.overcast.description = Appréciation de la couverture nuageuse.
channel-type.synopanalyzer.overcast.state.option.CLEAR_SKY = Ciel dégagé
channel-type.synopanalyzer.overcast.state.option.CLOUDY = Nuageux
channel-type.synopanalyzer.overcast.state.option.SKY_NOT_VISIBLE = Ciel non visible
channel-type.synopanalyzer.horizontal-visibility.label = Visibilité horizontale
channel-type.synopanalyzer.horizontal-visibility.description = Ordre de grandeur de la visibilité horizontale.
channel-type.synopanalyzer.horizontal-visibility.state.option.LESS_THAN_1 = Moins de 1 km
channel-type.synopanalyzer.horizontal-visibility.state.option.LESS_THAN_10 = Entre 1 et 10 km
channel-type.synopanalyzer.horizontal-visibility.state.option.LESS_THAN_50 = Entre 10 et 50 km
channel-type.synopanalyzer.horizontal-visibility.state.option.MORE_THAN_50 = Plus de 50 km
channel-type.synopanalyzer.time-utc.label = Horodatage
channel-type.synopanalyzer.time-utc.description = Heure d'observation des mesures relevées

View File

@ -6,14 +6,14 @@
<thing-type id="synopanalyzer">
<label>Synop Message</label>
<description>The Synop Analyzer binding decodes Synop messages</description>
<description>This is the interpretation of the last message of a given station.</description>
<channels>
<channel id="temperature" typeId="system.outdoor-temperature"/>
<channel id="pressure" typeId="system.barometric-pressure"/>
<channel id="wind-angle" typeId="system.wind-direction"/>
<channel id="wind-direction" typeId="wind-direction"/>
<channel id="wind-speed" typeId="system.wind-speed"/>
<channel id="wind-direction" typeId="wind-direction"/>
<channel id="wind-speed-beaufort" typeId="wind-speed-beaufort"/>
<channel id="overcast" typeId="overcast"/>
<channel id="octa" typeId="octa"/>
@ -75,14 +75,16 @@
<channel-type id="octa">
<item-type>Number</item-type>
<label>Octa</label>
<description>Octa</description>
<description>Cloud cover estimation.</description>
<category>sun_clouds</category>
<state readOnly="true" pattern="%d/8" min="0" max="8"/>
</channel-type>
<channel-type id="attenuation-factor">
<channel-type id="attenuation-factor" advanced="true">
<item-type>Number</item-type>
<label>Mitigation Factor</label>
<description>Cloud layer mitigation factor</description>
<category>sun_clouds</category>
<state readOnly="true" pattern="%.1f" max="1" min="0"/>
</channel-type>
@ -90,6 +92,7 @@
<item-type>String</item-type>
<label>Overcast</label>
<description>Overcast</description>
<category>sun_clouds</category>
<state readOnly="true" pattern="%s">
<options>
<option value="CLEAR_SKY">Clear sky</option>
@ -117,6 +120,7 @@
<item-type>DateTime</item-type>
<label>Observation Time</label>
<description>Timestamp when data was observed</description>
<category>time</category>
<state readOnly="true"/>
</channel-type>