Cleaning resource files

Bulletproofed icon servlet

Signed-off-by: Gaël L'hopital <gael@lhopital.org>
This commit is contained in:
Gaël L'hopital 2024-11-19 14:13:59 +01:00
parent 9aa3255ada
commit 58ef294232
9 changed files with 31 additions and 177 deletions

View File

@ -25,6 +25,7 @@ import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.airparif.internal.api.AirParifApi.Appreciation;
import org.openhab.binding.airparif.internal.api.AirParifApi.Pollen;
import org.openhab.binding.airparif.internal.api.PollenAlertLevel;
import org.openhab.core.i18n.TranslationProvider;
@ -97,13 +98,13 @@ public class AirParifIconProvider implements IconProvider {
}
String iconName = "icon/%s.svg".formatted(category);
if (category.equals(AQ_ICON) && ordinal != -1) {
if (category.equals(AQ_ICON) && ordinal != -1 && ordinal < Appreciation.values().length - 2) {
iconName = iconName.replace(".", "-%d.".formatted(ordinal));
}
URL iconResource = bundle.getEntry(iconName);
String result;
String result = "";
try (InputStream stream = iconResource.openStream()) {
result = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
@ -113,7 +114,6 @@ public class AirParifIconProvider implements IconProvider {
}
} catch (IOException e) {
logger.warn("Unable to load ressource '{}': {}", iconResource.getPath(), e.getMessage());
result = "";
}
return result.isEmpty() ? null : new ByteArrayInputStream(result.getBytes());

View File

@ -33,6 +33,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.airparif.internal.api.AirParifApi.Pollen;
import org.openhab.binding.airparif.internal.api.AirParifApi.Scope;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State;
@ -209,6 +210,10 @@ public class AirParifDto {
return unit != null ? new QuantityType<>(getValue(), unit) : UnDefType.NULL;
}
public State getDate() {
return new DateTimeType(date);
}
public double getValue() {
return values[0];
}

View File

@ -1,36 +0,0 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.airparif.internal.api;
import java.util.HashMap;
import java.util.Objects;
import org.openhab.binding.airparif.internal.api.AirParifApi.Appreciation;
/**
* Class association between air quality appreciation and its color
*
* @author Gaël L'hopital - Initial contribution
*/
public class ColorMap extends HashMap<Appreciation, String> {
private static final long serialVersionUID = -605462873565278453L;
private static Appreciation fromApiName(String searched) {
return Objects.requireNonNull(Appreciation.AS_SET.stream().filter(mt -> searched.equals(mt.apiName)).findFirst()
.orElse(Appreciation.UNKNOWN));
}
public String put(String key, String value) {
return super.put(fromApiName(key), value);
}
}

View File

@ -19,7 +19,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.airparif.internal.AirParifException;
import org.openhab.binding.airparif.internal.api.AirParifDto.PollutantConcentration;
import org.openhab.binding.airparif.internal.api.ColorMap;
import org.openhab.binding.airparif.internal.api.PollenAlertLevel;
import org.openhab.core.i18n.TimeZoneProvider;
import org.osgi.service.component.annotations.Activate;
@ -47,7 +46,6 @@ public class AirParifDeserializer {
gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
.registerTypeAdapter(PollenAlertLevel.class, new PollenAlertLevelDeserializer())
.registerTypeAdapterFactory(new StrictEnumTypeAdapterFactory())
.registerTypeAdapter(ColorMap.class, new ColorMapDeserializer())
.registerTypeAdapter(PollutantConcentration.class, new PollutantConcentrationDeserializer())
.registerTypeAdapter(LocalDate.class,
(JsonDeserializer<LocalDate>) (json, type, context) -> LocalDate

View File

@ -1,42 +0,0 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.airparif.internal.deserialization;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.airparif.internal.api.ColorMap;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
/**
* Specialized deserializer for ColorMap class
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
class ColorMapDeserializer implements JsonDeserializer<ColorMap> {
@Override
public @Nullable ColorMap deserialize(JsonElement json, Type clazz, JsonDeserializationContext context) {
ColorMap result = new ColorMap();
Set<Map.Entry<String, JsonElement>> entrySet = json.getAsJsonObject().entrySet();
entrySet.forEach(entry -> result.put(entry.getKey(), entry.getValue().getAsString()));
return result;
}
}

View File

@ -30,7 +30,6 @@ import org.openhab.binding.airparif.internal.api.AirParifDto.Route;
import org.openhab.binding.airparif.internal.api.PollenAlertLevel;
import org.openhab.binding.airparif.internal.api.Pollutant;
import org.openhab.binding.airparif.internal.config.LocationConfiguration;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelGroupUID;
@ -110,8 +109,7 @@ public class LocationHandler extends BaseThingHandler implements HandlerUtils {
ChannelGroupUID groupUID = new ChannelGroupUID(thing.getUID(), pollutant.name().toLowerCase());
updateState(new ChannelUID(groupUID, CHANNEL_MESSAGE), concentration.getMessage());
if (!pollutant.hasUnit()) {
updateState(new ChannelUID(groupUID, CHANNEL_TIMESTAMP),
new DateTimeType(concentration.date()));
updateState(new ChannelUID(groupUID, CHANNEL_TIMESTAMP), concentration.getDate());
updateState(new ChannelUID(groupUID, CHANNEL_ALERT), new DecimalType(maxAlert));
} else {
updateState(new ChannelUID(groupUID, CHANNEL_VALUE), concentration.getQuantity());

View File

@ -38,21 +38,21 @@ channel-group-type.airparif.air-quality-bulletin.label = Air Quality Bulletin
channel-group-type.airparif.air-quality-bulletin.channel.comment.label = Message
channel-group-type.airparif.air-quality-bulletin.channel.comment.description = General message for the air quality bulletin
channel-group-type.airparif.air-quality-bulletin.channel.no2-max.label = NO2 Max
channel-group-type.airparif.air-quality-bulletin.channel.no2-max.description = Maximum level of NO2 concentation
channel-group-type.airparif.air-quality-bulletin.channel.no2-max.description = Maximum level of NO2 concentration
channel-group-type.airparif.air-quality-bulletin.channel.no2-min.label = NO2 Min
channel-group-type.airparif.air-quality-bulletin.channel.no2-min.description = Minimum level of NO2 concentation
channel-group-type.airparif.air-quality-bulletin.channel.no2-min.description = Minimum level of NO2 concentration
channel-group-type.airparif.air-quality-bulletin.channel.o3-max.label = O3 Max
channel-group-type.airparif.air-quality-bulletin.channel.o3-max.description = Maximum level of O3 concentation
channel-group-type.airparif.air-quality-bulletin.channel.o3-max.description = Maximum level of O3 concentration
channel-group-type.airparif.air-quality-bulletin.channel.o3-min.label = O3 Min
channel-group-type.airparif.air-quality-bulletin.channel.o3-min.description = Minimum level of O3 concentation
channel-group-type.airparif.air-quality-bulletin.channel.o3-min.description = Minimum level of O3 concentration
channel-group-type.airparif.air-quality-bulletin.channel.pm10-max.label = PM 10 Max
channel-group-type.airparif.air-quality-bulletin.channel.pm10-max.description = Maximum level of PM 10 concentation
channel-group-type.airparif.air-quality-bulletin.channel.pm10-max.description = Maximum level of PM 10 concentration
channel-group-type.airparif.air-quality-bulletin.channel.pm10-min.label = PM 10 Min
channel-group-type.airparif.air-quality-bulletin.channel.pm10-min.description = Minimum level of PM 10 concentation
channel-group-type.airparif.air-quality-bulletin.channel.pm10-min.description = Minimum level of PM 10 concentration
channel-group-type.airparif.air-quality-bulletin.channel.pm25-max.label = PM 2.5 Max
channel-group-type.airparif.air-quality-bulletin.channel.pm25-max.description = Maximum level of PM 2.5 concentation
channel-group-type.airparif.air-quality-bulletin.channel.pm25-max.description = Maximum level of PM 2.5 concentration
channel-group-type.airparif.air-quality-bulletin.channel.pm25-min.label = PM 2.5 Min
channel-group-type.airparif.air-quality-bulletin.channel.pm25-min.description = Minimum level of PM 2.5 concentation
channel-group-type.airparif.air-quality-bulletin.channel.pm25-min.description = Minimum level of PM 2.5 concentration
channel-group-type.airparif.bridge-pollens.label = Pollen information for the region
channel-group-type.airparif.bridge-pollens.channel.begin-validity.label = Begin Validity
channel-group-type.airparif.bridge-pollens.channel.begin-validity.description = Current bulletin validity start
@ -73,9 +73,9 @@ channel-group-type.airparif.pollutant-mpc.channel.message.label = Message
channel-group-type.airparif.pollutant-mpc.channel.message.description = Polllutant concentration alert message
channel-group-type.airparif.pollutant-mpc.channel.value.label = Concentration
channel-group-type.airparif.pollutant-mpc.channel.value.description = Concentration of the given pollutant
channel-group-type.airparif.pollutant-ndx.label = Global Pollutant Index
channel-group-type.airparif.pollutant-ndx.channel.alert.label = Alert Level
channel-group-type.airparif.pollutant-ndx.channel.alert.description = Alert Level associated to highest pollutant concentration
channel-group-type.airparif.pollutant-ndx.label = ATMO Index
channel-group-type.airparif.pollutant-ndx.channel.alert.label = Index
channel-group-type.airparif.pollutant-ndx.channel.alert.description = ATMO Index associated to highest pollutant concentration
channel-group-type.airparif.pollutant-ndx.channel.message.label = Message
channel-group-type.airparif.pollutant-ndx.channel.message.description = Alert message associated to the value of the index
channel-group-type.airparif.pollutant-ndx.channel.timestamp.label = Timestamp
@ -223,75 +223,6 @@ channel-group-type.airparif.pollens-group.channel.comment.description = Current
channel-group-type.airparif.pollens-group.channel.end-validity.label = End Validity
channel-group-type.airparif.pollens-group.channel.end-validity.description = Current bulletin validity ending
# channel types
channel-type.airparif.alert-level.state.option.0 = Good
channel-type.airparif.alert-level.state.option.1 = Average
channel-type.airparif.alert-level.state.option.2 = Degrated
channel-type.airparif.alert-level.state.option.3 = Bad
channel-type.airparif.alert-level.state.option.4 = Extremely Bad
channel-type.airparif.avalanches.label = Avalanches
channel-type.airparif.avalanches.description = Avalanche alert level
channel-type.airparif.avalanches.state.option.0 = No special vigilance
channel-type.airparif.avalanches.state.option.1 = Be attentive
channel-type.airparif.avalanches.state.option.2 = Be very vigilant
channel-type.airparif.avalanches.state.option.3 = Absolute vigilance
channel-type.airparif.canicule.label = Heat Wave
channel-type.airparif.canicule.description = High temperature alert level
channel-type.airparif.canicule.state.option.0 = No special vigilance
channel-type.airparif.canicule.state.option.1 = Be attentive
channel-type.airparif.canicule.state.option.2 = Be very vigilant
channel-type.airparif.canicule.state.option.3 = Absolute vigilance
channel-type.airparif.condition-icon.label = Icon
channel-type.airparif.condition-icon.description = Pictogram associated with the alert level.
channel-type.airparif.grand-froid.label = Extreme Cold
channel-type.airparif.grand-froid.description = Negative temperature alert level
channel-type.airparif.grand-froid.state.option.0 = No special vigilance
channel-type.airparif.grand-froid.state.option.1 = Be attentive
channel-type.airparif.grand-froid.state.option.2 = Be very vigilant
channel-type.airparif.grand-froid.state.option.3 = Absolute vigilance
channel-type.airparif.inondation.label = Flood
channel-type.airparif.inondation.description = Flood alert level
channel-type.airparif.inondation.state.option.0 = No special vigilance
channel-type.airparif.inondation.state.option.1 = Be attentive
channel-type.airparif.inondation.state.option.2 = Be very vigilant
channel-type.airparif.inondation.state.option.3 = Absolute vigilance
channel-type.airparif.neige.label = Snow
channel-type.airparif.neige.description = Snow event alert level
channel-type.airparif.neige.state.option.0 = No special vigilance
channel-type.airparif.neige.state.option.1 = Be attentive
channel-type.airparif.neige.state.option.2 = Be very vigilant
channel-type.airparif.neige.state.option.3 = Absolute vigilance
channel-type.airparif.orage.label = Storm
channel-type.airparif.orage.description = Storm alert level
channel-type.airparif.orage.state.option.0 = No special vigilance
channel-type.airparif.orage.state.option.1 = Be attentive
channel-type.airparif.orage.state.option.2 = Be very vigilant
channel-type.airparif.orage.state.option.3 = Absolute vigilance
channel-type.airparif.pluie-inondation.label = Rain Flood
channel-type.airparif.pluie-inondation.description = Flood caused by rainfall alert level
channel-type.airparif.pluie-inondation.state.option.0 = No special vigilance
channel-type.airparif.pluie-inondation.state.option.1 = Be attentive
channel-type.airparif.pluie-inondation.state.option.2 = Be very vigilant
channel-type.airparif.pluie-inondation.state.option.3 = Absolute vigilance
channel-type.airparif.pollen-level.label = Pollen Level
channel-type.airparif.pollen-level.state.option.0 = None
channel-type.airparif.pollen-level.state.option.1 = Low
channel-type.airparif.pollen-level.state.option.2 = Average
channel-type.airparif.pollen-level.state.option.3 = High
channel-type.airparif.vague-submersion.label = Wave Submersion
channel-type.airparif.vague-submersion.description = Submersion wave alert level
channel-type.airparif.vague-submersion.state.option.0 = No special vigilance
channel-type.airparif.vague-submersion.state.option.1 = Be attentive
channel-type.airparif.vague-submersion.state.option.2 = Be very vigilant
channel-type.airparif.vague-submersion.state.option.3 = Absolute vigilance
channel-type.airparif.vent.label = Wind
channel-type.airparif.vent.description = Wind event alert level
channel-type.airparif.vent.state.option.0 = No special vigilance
channel-type.airparif.vent.state.option.1 = Be attentive
channel-type.airparif.vent.state.option.2 = Be very vigilant
channel-type.airparif.vent.state.option.3 = Absolute vigilance
# discovery result
discovery.airparif.location.local.label = Air Quality Report

View File

@ -31,35 +31,35 @@
</channel>
<channel id="no2-min" typeId="mpc-value">
<label>NO2 Min</label>
<description>Minimum level of NO2 concentation</description>
<description>Minimum level of NO2 concentration</description>
</channel>
<channel id="no2-max" typeId="mpc-value">
<label>NO2 Max</label>
<description>Maximum level of NO2 concentation</description>
<description>Maximum level of NO2 concentration</description>
</channel>
<channel id="o3-min" typeId="mpc-value">
<label>O3 Min</label>
<description>Minimum level of O3 concentation</description>
<description>Minimum level of O3 concentration</description>
</channel>
<channel id="o3-max" typeId="mpc-value">
<label>O3 Max</label>
<description>Maximum level of O3 concentation</description>
<description>Maximum level of O3 concentration</description>
</channel>
<channel id="pm10-min" typeId="mpc-value">
<label>PM 10 Min</label>
<description>Minimum level of PM 10 concentation</description>
<description>Minimum level of PM 10 concentration</description>
</channel>
<channel id="pm10-max" typeId="mpc-value">
<label>PM 10 Max</label>
<description>Maximum level of PM 10 concentation</description>
<description>Maximum level of PM 10 concentration</description>
</channel>
<channel id="pm25-min" typeId="mpc-value">
<label>PM 2.5 Min</label>
<description>Minimum level of PM 2.5 concentation</description>
<description>Minimum level of PM 2.5 concentration</description>
</channel>
<channel id="pm25-max" typeId="mpc-value">
<label>PM 2.5 Max</label>
<description>Maximum level of PM 2.5 concentation</description>
<description>Maximum level of PM 2.5 concentration</description>
</channel>
</channels>
</channel-group-type>
@ -83,7 +83,7 @@
</channel-group-type>
<channel-group-type id="pollutant-ndx">
<label>Global Pollutant Index</label>
<label>ATMO Index</label>
<channels>
<channel id="message" typeId="comment">
<label>Message</label>
@ -94,8 +94,8 @@
<description>Timestamp of the evaluation</description>
</channel>
<channel id="alert" typeId="appreciation">
<label>Alert Level</label>
<description>Alert Level associated to highest pollutant concentration</description>
<label>Index</label>
<description>ATMO Index associated to highest pollutant concentration</description>
</channel>
</channels>
</channel-group-type>