mirror of
https://github.com/danieldemus/openhab-addons
synced 2026-07-29 12:34:21 +02:00
[astro] Switching radiation to immutable and Instant (#19949)
* Switching radiation to immutable and Instant Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
+2
-1
@@ -51,9 +51,10 @@ import org.slf4j.LoggerFactory;
|
|||||||
public class AstroActions implements ThingActions {
|
public class AstroActions implements ThingActions {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(AstroActions.class);
|
private final Logger logger = LoggerFactory.getLogger(AstroActions.class);
|
||||||
private @Nullable AstroThingHandler handler;
|
|
||||||
private final TimeZoneProvider timeZoneProvider;
|
private final TimeZoneProvider timeZoneProvider;
|
||||||
|
|
||||||
|
private @Nullable AstroThingHandler handler;
|
||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public AstroActions(@Reference TimeZoneProvider timeZoneProvider) {
|
public AstroActions(@Reference TimeZoneProvider timeZoneProvider) {
|
||||||
this.timeZoneProvider = timeZoneProvider;
|
this.timeZoneProvider = timeZoneProvider;
|
||||||
|
|||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2026 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.astro.internal.calc;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.astro.internal.model.Radiation;
|
||||||
|
import org.openhab.binding.astro.internal.util.MathUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the color temperature and brightness depending upon sun positional information
|
||||||
|
*
|
||||||
|
* @author Gaël L'hopital - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class RadiationCalc {
|
||||||
|
private static final double SC = 1367; // Solar constant in W/m²
|
||||||
|
|
||||||
|
public static Radiation calculate(ZonedDateTime now, double elevation, @Nullable Double altitude) {
|
||||||
|
double altitudeRatio = (altitude != null) ? 1 / Math.pow((1 - (6.5 / 288) * (altitude / 1000.0)), 5.256) : 1;
|
||||||
|
double sinAlpha = MathUtils.sinDeg(elevation);
|
||||||
|
|
||||||
|
LocalDate date = now.toLocalDate();
|
||||||
|
|
||||||
|
int dayOfYear = date.getDayOfYear();
|
||||||
|
int daysInYear = date.lengthOfYear(); // 365 or 366
|
||||||
|
|
||||||
|
// Direct Solar Radiation (in W/m²) at the atmosphere entry
|
||||||
|
// At sunrise/sunset - calculations limits are reached
|
||||||
|
double rOut = (elevation > 3 ? SC * (0.034 * Math.cos(MathUtils.TWO_PI * dayOfYear / daysInYear) + 1) : 0)
|
||||||
|
* sinAlpha;
|
||||||
|
|
||||||
|
// 0.6 = transmissivity coefficient
|
||||||
|
double m = Math.pow(0.6, (Math.sqrt(1229 + Math.pow(614 * sinAlpha, 2)) - 614 * sinAlpha) * altitudeRatio);
|
||||||
|
|
||||||
|
// Direct radiation after atmospheric layer
|
||||||
|
double rDir = rOut * m;
|
||||||
|
|
||||||
|
// Diffuse Radiation
|
||||||
|
double rDiff = rOut * (0.271 - 0.294 * m);
|
||||||
|
|
||||||
|
return new Radiation(rDir, rDiff);
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-39
@@ -28,7 +28,6 @@ import org.eclipse.jdt.annotation.Nullable;
|
|||||||
import org.openhab.binding.astro.internal.model.Eclipse;
|
import org.openhab.binding.astro.internal.model.Eclipse;
|
||||||
import org.openhab.binding.astro.internal.model.EclipseType;
|
import org.openhab.binding.astro.internal.model.EclipseType;
|
||||||
import org.openhab.binding.astro.internal.model.Position;
|
import org.openhab.binding.astro.internal.model.Position;
|
||||||
import org.openhab.binding.astro.internal.model.Radiation;
|
|
||||||
import org.openhab.binding.astro.internal.model.Range;
|
import org.openhab.binding.astro.internal.model.Range;
|
||||||
import org.openhab.binding.astro.internal.model.Season;
|
import org.openhab.binding.astro.internal.model.Season;
|
||||||
import org.openhab.binding.astro.internal.model.Sun;
|
import org.openhab.binding.astro.internal.model.Sun;
|
||||||
@@ -45,9 +44,6 @@ import org.openhab.binding.astro.internal.util.MathUtils;
|
|||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SunCalc {
|
public class SunCalc {
|
||||||
private static final double J2000 = 2451545.0;
|
|
||||||
private static final double SC = 1367; // Solar constant in W/m²
|
|
||||||
|
|
||||||
private static final double M0 = Math.toRadians(357.5291);
|
private static final double M0 = Math.toRadians(357.5291);
|
||||||
private static final double M1 = Math.toRadians(0.98560028);
|
private static final double M1 = Math.toRadians(0.98560028);
|
||||||
private static final double J0 = 0.0009;
|
private static final double J0 = 0.0009;
|
||||||
@@ -93,37 +89,6 @@ public class SunCalc {
|
|||||||
position.setAzimuth(azimuth + 180);
|
position.setAzimuth(azimuth + 180);
|
||||||
position.setElevation(elevation);
|
position.setElevation(elevation);
|
||||||
position.setShadeLength(shadeLength);
|
position.setShadeLength(shadeLength);
|
||||||
|
|
||||||
setRadiationInfo(calendar, elevation, altitude, sun);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates sun radiation data.
|
|
||||||
*/
|
|
||||||
private void setRadiationInfo(Calendar calendar, double elevation, @Nullable Double altitude, Sun sun) {
|
|
||||||
double sinAlpha = MathUtils.sinDeg(elevation);
|
|
||||||
|
|
||||||
int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
|
|
||||||
int daysInYear = calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
|
|
||||||
|
|
||||||
// Direct Solar Radiation (in W/m²) at the atmosphere entry
|
|
||||||
// At sunrise/sunset - calculations limits are reached
|
|
||||||
double rOut = (elevation > 3) ? SC * (0.034 * MathUtils.cosDeg(360 * dayOfYear / daysInYear) + 1) : 0;
|
|
||||||
double altitudeRatio = (altitude != null) ? 1 / Math.pow((1 - (6.5 / 288) * (altitude / 1000.0)), 5.256) : 1;
|
|
||||||
double m = (Math.sqrt(1229 + Math.pow(614 * sinAlpha, 2)) - 614 * sinAlpha) * altitudeRatio;
|
|
||||||
|
|
||||||
// Direct radiation after atmospheric layer
|
|
||||||
// 0.6 = Coefficient de transmissivité
|
|
||||||
double rDir = rOut * Math.pow(0.6, m) * sinAlpha;
|
|
||||||
|
|
||||||
// Diffuse Radiation
|
|
||||||
double rDiff = rOut * (0.271 - 0.294 * Math.pow(0.6, m)) * sinAlpha;
|
|
||||||
double rTot = rDir + rDiff;
|
|
||||||
|
|
||||||
Radiation radiation = sun.getRadiation();
|
|
||||||
radiation.setDirect(rDir);
|
|
||||||
radiation.setDiffuse(rDiff);
|
|
||||||
radiation.setTotal(rTot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -306,15 +271,15 @@ public class SunCalc {
|
|||||||
// all the following methods are translated to java based on the javascript
|
// all the following methods are translated to java based on the javascript
|
||||||
// calculations of http://www.suncalc.net
|
// calculations of http://www.suncalc.net
|
||||||
private double getJulianCycle(double j, double lw) {
|
private double getJulianCycle(double j, double lw) {
|
||||||
return Math.round(j - J2000 - J0 - lw / MathUtils.TWO_PI);
|
return Math.round(j - DateTimeUtils.JD_J2000 - J0 - lw / MathUtils.TWO_PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getApproxSolarTransit(double ht, double lw, double n) {
|
private double getApproxSolarTransit(double ht, double lw, double n) {
|
||||||
return J2000 + J0 + (ht + lw) / MathUtils.TWO_PI + n;
|
return DateTimeUtils.JD_J2000 + J0 + (ht + lw) / MathUtils.TWO_PI + n;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getSolarMeanAnomaly(double js) {
|
private double getSolarMeanAnomaly(double js) {
|
||||||
return M0 + M1 * (js - J2000);
|
return M0 + M1 * (js - DateTimeUtils.JD_J2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getEquationOfCenter(double m) {
|
private double getEquationOfCenter(double m) {
|
||||||
@@ -338,7 +303,7 @@ public class SunCalc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private double getSiderealTime(double j, double lw) {
|
private double getSiderealTime(double j, double lw) {
|
||||||
return TH0 + TH1 * (j - J2000) - lw;
|
return TH0 + TH1 * (j - DateTimeUtils.JD_J2000) - lw;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getAzimuth(double th, double a, double phi, double d) {
|
private double getAzimuth(double th, double a, double phi, double d) {
|
||||||
|
|||||||
+4
-1
@@ -19,6 +19,7 @@ import static org.openhab.core.types.RefreshType.REFRESH;
|
|||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -344,7 +345,9 @@ public abstract class AstroThingHandler extends BaseThingHandler {
|
|||||||
public void schedule(Job job, Instant eventAt) {
|
public void schedule(Job job, Instant eventAt) {
|
||||||
long sleepTime = Instant.now().until(eventAt, ChronoUnit.MILLIS);
|
long sleepTime = Instant.now().until(eventAt, ChronoUnit.MILLIS);
|
||||||
schedule(job, sleepTime);
|
schedule(job, sleepTime);
|
||||||
logger.debug("Scheduled {} in {}ms (at {})", job, sleepTime, eventAt);
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Scheduled {} in {}ms (at {})", job, sleepTime, eventAt.atZone(ZoneId.systemDefault()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tidyScheduledFutures() {
|
private void tidyScheduledFutures() {
|
||||||
|
|||||||
+5
-1
@@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.astro.internal.handler;
|
package org.openhab.binding.astro.internal.handler;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@@ -22,6 +23,7 @@ import java.util.TimeZone;
|
|||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.astro.internal.calc.CircadianCalc;
|
import org.openhab.binding.astro.internal.calc.CircadianCalc;
|
||||||
|
import org.openhab.binding.astro.internal.calc.RadiationCalc;
|
||||||
import org.openhab.binding.astro.internal.calc.SunCalc;
|
import org.openhab.binding.astro.internal.calc.SunCalc;
|
||||||
import org.openhab.binding.astro.internal.job.DailyJobSun;
|
import org.openhab.binding.astro.internal.job.DailyJobSun;
|
||||||
import org.openhab.binding.astro.internal.job.Job;
|
import org.openhab.binding.astro.internal.job.Job;
|
||||||
@@ -68,12 +70,14 @@ public class SunHandler extends AstroThingHandler {
|
|||||||
Double longitude = thingConfig.longitude;
|
Double longitude = thingConfig.longitude;
|
||||||
Double altitude = thingConfig.altitude;
|
Double altitude = thingConfig.altitude;
|
||||||
Calendar calendar = Calendar.getInstance(zone, locale);
|
Calendar calendar = Calendar.getInstance(zone, locale);
|
||||||
|
ZonedDateTime now = Instant.now().atZone(zoneId);
|
||||||
sunCalc.setPositionalInfo(calendar, latitude != null ? latitude : 0, longitude != null ? longitude : 0,
|
sunCalc.setPositionalInfo(calendar, latitude != null ? latitude : 0, longitude != null ? longitude : 0,
|
||||||
altitude != null ? altitude : 0, sun);
|
altitude != null ? altitude : 0, sun);
|
||||||
|
|
||||||
sun.getEclipse().setElevations(this, timeZoneProvider);
|
sun.getEclipse().setElevations(this, timeZoneProvider);
|
||||||
|
|
||||||
sun.setCircadian(CircadianCalc.calculate(calendar, sun.getRise(), sun.getSet(), sun.getNoon()));
|
sun.setCircadian(CircadianCalc.calculate(calendar, sun.getRise(), sun.getSet(), sun.getNoon()));
|
||||||
|
sun.setRadiation(RadiationCalc.calculate(now, sun.getPosition().getElevationAsDouble(), altitude));
|
||||||
|
|
||||||
this.sun = sun;
|
this.sun = sun;
|
||||||
|
|
||||||
@@ -138,6 +142,6 @@ public class SunHandler extends AstroThingHandler {
|
|||||||
|
|
||||||
public @Nullable Radiation getRadiationAt(ZonedDateTime date) {
|
public @Nullable Radiation getRadiationAt(ZonedDateTime date) {
|
||||||
Sun localSun = getPositionedSunAt(date);
|
Sun localSun = getPositionedSunAt(date);
|
||||||
return localSun.getRadiation();
|
return RadiationCalc.calculate(date, localSun.getPosition().getElevationAsDouble(), thingConfig.altitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-33
@@ -13,9 +13,12 @@
|
|||||||
package org.openhab.binding.astro.internal.model;
|
package org.openhab.binding.astro.internal.model;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.library.dimension.Intensity;
|
import org.openhab.core.library.dimension.Intensity;
|
||||||
import org.openhab.core.library.types.QuantityType;
|
import org.openhab.core.library.types.QuantityType;
|
||||||
import org.openhab.core.library.unit.Units;
|
import org.openhab.core.library.unit.Units;
|
||||||
|
import org.openhab.core.types.State;
|
||||||
|
import org.openhab.core.types.UnDefType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the calculated direct, diffuse and total
|
* Holds the calculated direct, diffuse and total
|
||||||
@@ -25,59 +28,39 @@ import org.openhab.core.library.unit.Units;
|
|||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class Radiation {
|
public class Radiation {
|
||||||
|
public static final Radiation NULL = new Radiation();
|
||||||
|
|
||||||
private double direct;
|
private final double direct;
|
||||||
private double diffuse;
|
private final double diffuse;
|
||||||
private double total;
|
|
||||||
|
|
||||||
public Radiation() {
|
private Radiation() {
|
||||||
|
this(Double.NaN, Double.NaN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Radiation(double direct, double diffuse, double total) {
|
public Radiation(double direct, double diffuse) {
|
||||||
this.direct = direct;
|
this.direct = direct;
|
||||||
this.diffuse = diffuse;
|
this.diffuse = diffuse;
|
||||||
this.total = total;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the direct radiation.
|
|
||||||
*/
|
|
||||||
public void setDirect(double direct) {
|
|
||||||
this.direct = direct;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the diffuse radiation.
|
|
||||||
*/
|
|
||||||
public void setDiffuse(double diffuse) {
|
|
||||||
this.diffuse = diffuse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the total radiation.
|
|
||||||
*/
|
|
||||||
public void setTotal(double total) {
|
|
||||||
this.total = total;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total radiation.
|
* Returns the total radiation.
|
||||||
*/
|
*/
|
||||||
public QuantityType<Intensity> getTotal() {
|
public @Nullable QuantityType<Intensity> getTotal() {
|
||||||
return new QuantityType<>(total, Units.IRRADIANCE);
|
return Double.isNaN(direct) || Double.isNaN(diffuse) ? null
|
||||||
|
: new QuantityType<>(direct + diffuse, Units.IRRADIANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the direct radiation.
|
* Returns the direct radiation.
|
||||||
*/
|
*/
|
||||||
public QuantityType<Intensity> getDirect() {
|
public State getDirect() {
|
||||||
return new QuantityType<>(direct, Units.IRRADIANCE);
|
return Double.isNaN(direct) ? UnDefType.UNDEF : new QuantityType<>(direct, Units.IRRADIANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the diffuse radiation.
|
* Returns the diffuse radiation.
|
||||||
*/
|
*/
|
||||||
public QuantityType<Intensity> getDiffuse() {
|
public State getDiffuse() {
|
||||||
return new QuantityType<>(diffuse, Units.IRRADIANCE);
|
return Double.isNaN(diffuse) ? UnDefType.UNDEF : new QuantityType<>(diffuse, Units.IRRADIANCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -36,7 +36,7 @@ public class Sun extends RiseSet implements Planet {
|
|||||||
|
|
||||||
private Eclipse eclipse = new Eclipse(EclipseKind.PARTIAL, EclipseKind.TOTAL, EclipseKind.RING);
|
private Eclipse eclipse = new Eclipse(EclipseKind.PARTIAL, EclipseKind.TOTAL, EclipseKind.RING);
|
||||||
|
|
||||||
private Radiation radiation = new Radiation();
|
private Radiation radiation = Radiation.NULL;
|
||||||
|
|
||||||
private SunPhase phase = new SunPhase();
|
private SunPhase phase = new SunPhase();
|
||||||
|
|
||||||
@@ -239,6 +239,10 @@ public class Sun extends RiseSet implements Planet {
|
|||||||
return radiation;
|
return radiation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRadiation(Radiation radiation) {
|
||||||
|
this.radiation = radiation;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the sun position.
|
* Sets the sun position.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user