* Correcting a SAT finding.
Adding alert levels compatible with MeteoAlarm and Vigicrues
* Adressing code review.
* spotless apply
Signed-off-by: clinique <gael@lhopital.org>
// List of all Channel id's
public static final String UV_INDEX = "UVIndex";
+ public static final String ALERT_LEVEL = "Alert";
public static final String UV_COLOR = "UVColor";
public static final String UV_MAX = "UVMax";
public static final String UV_MAX_TIME = "UVMaxTime";
super(message);
}
+ private boolean checkMatches(String message) {
+ String currentMessage = getMessage();
+ return currentMessage != null && currentMessage.startsWith(message);
+ }
+
public boolean isApiKeyError() {
- return this.getMessage().startsWith(ERROR_WRONG_KEY);
+ return checkMatches(ERROR_WRONG_KEY);
}
public boolean isQuotaError() {
- return this.getMessage().startsWith(ERROR_QUOTA_EXCEEDED);
+ return checkMatches(ERROR_QUOTA_EXCEEDED);
}
}
import org.openhab.binding.openuv.internal.handler.OpenUVReportHandler;
import org.openhab.core.i18n.LocationProvider;
import org.openhab.core.i18n.TimeZoneProvider;
-import org.openhab.core.library.types.DecimalType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
@Reference LocationProvider locationProvider) {
this.locationProvider = locationProvider;
this.gson = new GsonBuilder()
- .registerTypeAdapter(DecimalType.class,
- (JsonDeserializer<DecimalType>) (json, type, jsonDeserializationContext) -> DecimalType
- .valueOf(json.getAsJsonPrimitive().getAsString()))
.registerTypeAdapter(ZonedDateTime.class,
(JsonDeserializer<ZonedDateTime>) (json, type, jsonDeserializationContext) -> ZonedDateTime
.parse(json.getAsJsonPrimitive().getAsString())
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
+import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.openhab.binding.openuv.internal.config.SafeExposureConfiguration;
import org.openhab.binding.openuv.internal.json.OpenUVResult;
import org.openhab.core.library.types.DateTimeType;
+import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.PointType;
import org.openhab.core.library.types.QuantityType;
*/
@NonNullByDefault
public class OpenUVReportHandler extends BaseThingHandler {
+ private static final DecimalType ALERT_GREEN = DecimalType.ZERO;
+ private static final DecimalType ALERT_YELLOW = new DecimalType(1);
+ private static final DecimalType ALERT_ORANGE = new DecimalType(2);
+ private static final DecimalType ALERT_RED = new DecimalType(3);
+ private static final DecimalType ALERT_PURPLE = new DecimalType(4);
+ private static final State ALERT_UNDEF = HSBType.fromRGB(179, 179, 179);
+
+ private static final Map<State, State> ALERT_COLORS = Map.of(ALERT_GREEN, HSBType.fromRGB(85, 139, 47),
+ ALERT_YELLOW, HSBType.fromRGB(249, 168, 37), ALERT_ORANGE, HSBType.fromRGB(239, 108, 0), ALERT_RED,
+ HSBType.fromRGB(183, 28, 28), ALERT_PURPLE, HSBType.fromRGB(106, 27, 154));
+
private final Logger logger = LoggerFactory.getLogger(OpenUVReportHandler.class);
private @NonNullByDefault({}) OpenUVBridgeHandler bridgeHandler;
if (channelTypeUID != null) {
switch (channelTypeUID.getId()) {
case UV_INDEX:
- updateState(channelUID, openUVData.getUv());
+ updateState(channelUID, asDecimalType(openUVData.getUv()));
+ break;
+ case ALERT_LEVEL:
+ updateState(channelUID, asAlertLevel(openUVData.getUv()));
break;
case UV_COLOR:
- updateState(channelUID, getAsHSB(openUVData.getUv().intValue()));
+ updateState(channelUID,
+ ALERT_COLORS.getOrDefault(asAlertLevel(openUVData.getUv()), ALERT_UNDEF));
break;
case UV_MAX:
- updateState(channelUID, openUVData.getUvMax());
+ updateState(channelUID, asDecimalType(openUVData.getUvMax()));
break;
case OZONE:
updateState(channelUID, new QuantityType<>(openUVData.getOzone(), SmartHomeUnits.DOBSON_UNIT));
}
}
- private State getAsHSB(int uv) {
+ private State asDecimalType(int uv) {
+ if (uv >= 1) {
+ return new DecimalType(uv);
+ }
+ return UnDefType.NULL;
+ }
+
+ private State asAlertLevel(int uv) {
if (uv >= 11) {
- return HSBType.fromRGB(106, 27, 154);
+ return ALERT_PURPLE;
} else if (uv >= 8) {
- return HSBType.fromRGB(183, 28, 28);
+ return ALERT_RED;
} else if (uv >= 6) {
- return HSBType.fromRGB(239, 108, 0);
+ return ALERT_ORANGE;
} else if (uv >= 3) {
- return HSBType.fromRGB(249, 168, 37);
- } else {
- return HSBType.fromRGB(85, 139, 47);
+ return ALERT_YELLOW;
+ } else if (uv >= 1) {
+ return ALERT_GREEN;
}
+ return UnDefType.NULL;
}
}
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.DateTimeType;
-import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
@NonNullByDefault
public class OpenUVResult {
private final ZonedDateTime DEFAULT_ZDT = ZonedDateTime.of(LocalDateTime.MIN, ZoneId.systemDefault());
- private DecimalType uv = new DecimalType(0);
+ private double uv;
private ZonedDateTime uvTime = DEFAULT_ZDT;
- private DecimalType uvMax = new DecimalType(0);
+ private double uvMax;
private ZonedDateTime uvMaxTime = DEFAULT_ZDT;
- private DecimalType ozone = new DecimalType(0);
+ private double ozone;
private ZonedDateTime ozoneTime = DEFAULT_ZDT;
private SafeExposureTime safeExposureTime = new SafeExposureTime();
- public DecimalType getUv() {
- return uv;
+ public int getUv() {
+ return (int) uv;
}
- public DecimalType getUvMax() {
- return uvMax;
+ public int getUvMax() {
+ return (int) uvMax;
}
- public DecimalType getOzone() {
+ public double getOzone() {
return ozone;
}
<channels>
<channel id="UVIndex" typeId="UVIndex"/>
+ <channel id="Alert" typeId="Alert"/>
<channel id="UVColor" typeId="UVColor"/>
<channel id="UVMax" typeId="UVMax"/>
<channel id="UVMaxTime" typeId="UVMaxTime"/>
<item-type>Number</item-type>
<label>UV Index</label>
<description>UV Index</description>
- <state readOnly="true" pattern="%.2f/16" min="0" max="16"/>
+ <state readOnly="true" pattern="%d/16" min="0" max="16"/>
</channel-type>
<channel-type id="UVMax" advanced="true">
<item-type>Number</item-type>
<label>UV Max</label>
<description>Max UV Index for the day (at solar noon)</description>
- <state readOnly="true" pattern="%.2f/16" min="0" max="16"/>
+ <state readOnly="true" pattern="%d/16" min="0" max="16"/>
</channel-type>
<channel-type id="Ozone">
<channel-type id="OzoneTime" advanced="true">
<item-type>DateTime</item-type>
<label>Ozone Observation Time</label>
- <description>Latest OMI ozone update time</description>
+ <description>Latest OMI ozone update timestamp.</description>
+ <category>time</category>
<state readOnly="true" pattern="%1$tF %1$tR"/>
</channel-type>
<item-type>DateTime</item-type>
<label>UV Max Time</label>
<description>Max UV Index time (solar noon)</description>
+ <category>time</category>
<state readOnly="true" pattern="%1$tF %1$tR"/>
</channel-type>
<channel-type id="UVTime" advanced="true">
<item-type>DateTime</item-type>
<label>UV Time</label>
- <description>UV Index time</description>
+ <description>UV Index timestamp.</description>
+ <category>time</category>
<state readOnly="true" pattern="%1$tF %1$tR"/>
</channel-type>
<channel-type id="UVColor" advanced="true">
<item-type>Color</item-type>
- <label>UV Color</label>
- <description>Color associated to given UV Index.</description>
+ <label>UV Alert Color</label>
+ <description>Color associated to given UV Index alert level.</description>
<state readOnly="true"/>
</channel-type>
<description>Triggers when current UV Index reaches maximum of the day</description>
</channel-type>
+ <channel-type id="Alert">
+ <item-type>Number</item-type>
+ <label>UV Alert</label>
+ <state readOnly="true">
+ <options>
+ <option value="0">Low</option>
+ <option value="1">Medium</option>
+ <option value="2">High</option>
+ <option value="3">Very high</option>
+ <option value="4">Extreme</option>
+ </options>
+ </state>
+ </channel-type>
+
</thing:thing-descriptions>