Skip to content

Commit

Permalink
[astro] add localized seasons (openhab#7876)
Browse files Browse the repository at this point in the history
Closes openhab#5732 

Signed-off-by: Gaël L'hopital <[email protected]>
  • Loading branch information
clinique authored and andrewfg committed Aug 31, 2020
1 parent 489d4a6 commit 62e50ff
Show file tree
Hide file tree
Showing 21 changed files with 159 additions and 144 deletions.
2 changes: 2 additions & 0 deletions bundles/org.openhab.binding.astro/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ All Things require the parameter `geolocation` (as `<latitude>,<longitude>[,<alt
The altitude segment is optional and sharpens results provided by the Radiation group.
Optionally, a refresh `interval` (in seconds) can be defined to also calculate positional data like azimuth and elevation.

Season calculation can be switched from equinox based calculation to meteorological based (starting on the first day of the given month).
This is done by setting `useMeteorologicalSeason` to true in the advanced setting of the sun.

## Channels

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public void unregisterHandler(Thing thing) {
ASTRO_THING_HANDLERS.remove(thing.getUID().toString());
}

public static AstroThingHandler getHandler(String thingUid) {
public static @Nullable AstroThingHandler getHandler(String thingUid) {
return ASTRO_THING_HANDLERS.get(thingUid);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class SeasonCalc {
/**
* Returns the seasons of the year of the specified calendar.
*/
public Season getSeason(Calendar calendar, double latitude) {
public Season getSeason(Calendar calendar, double latitude, boolean useMeteorologicalSeason) {
int year = calendar.get(Calendar.YEAR);
boolean isSouthernHemisphere = latitude < 0.0;
Season season = currentSeason;
Expand All @@ -52,11 +52,26 @@ public Season getSeason(Calendar calendar, double latitude) {
currentYear = year;
}

if (useMeteorologicalSeason) {
atMidnightOfFirstMonthDay(season.getSpring());
atMidnightOfFirstMonthDay(season.getSummer());
atMidnightOfFirstMonthDay(season.getAutumn());
atMidnightOfFirstMonthDay(season.getWinter());
}

season.setName(!isSouthernHemisphere ? getCurrentSeasonNameNorthern(calendar)
: getCurrentSeasonNameSouthern(calendar));
return season;
}

private void atMidnightOfFirstMonthDay(Calendar calendar) {
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}

/**
* Returns the current season name for the northern hemisphere.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,13 @@ private boolean isSunUpAllDay(Calendar calendar, double latitude, double longitu
/**
* Calculates all sun rise and sets at the specified coordinates.
*/
public Sun getSunInfo(Calendar calendar, double latitude, double longitude, Double altitude) {
return getSunInfo(calendar, latitude, longitude, altitude, false);
public Sun getSunInfo(Calendar calendar, double latitude, double longitude, Double altitude,
boolean useMeteorologicalSeason) {
return getSunInfo(calendar, latitude, longitude, altitude, false, useMeteorologicalSeason);
}

private Sun getSunInfo(Calendar calendar, double latitude, double longitude, Double altitude, boolean onlyAstro) {
private Sun getSunInfo(Calendar calendar, double latitude, double longitude, Double altitude, boolean onlyAstro,
boolean useMeteorologicalSeason) {
double lw = -longitude * DEG2RAD;
double phi = latitude * DEG2RAD;
double j = DateTimeUtils.midnightDateToJulianDate(calendar) + 0.5;
Expand Down Expand Up @@ -201,7 +203,8 @@ private Sun getSunInfo(Calendar calendar, double latitude, double longitude, Dou
sun.setDaylight(daylightRange);

// morning night
Sun sunYesterday = getSunInfo(addDays(calendar, -1), latitude, longitude, altitude, true);
Sun sunYesterday = getSunInfo(addDays(calendar, -1), latitude, longitude, altitude, true,
useMeteorologicalSeason);
Range morningNightRange = null;
if (sunYesterday.getAstroDusk().getEnd() != null
&& DateUtils.isSameDay(sunYesterday.getAstroDusk().getEnd(), calendar)) {
Expand All @@ -227,7 +230,8 @@ private Sun getSunInfo(Calendar calendar, double latitude, double longitude, Dou
if (isSunUpAllDay) {
sun.setNight(new Range());
} else {
Sun sunTomorrow = getSunInfo(addDays(calendar, 1), latitude, longitude, altitude, true);
Sun sunTomorrow = getSunInfo(addDays(calendar, 1), latitude, longitude, altitude, true,
useMeteorologicalSeason);
sun.setNight(new Range(sun.getAstroDusk().getEnd(), sunTomorrow.getAstroDawn().getStart()));
}

Expand All @@ -246,7 +250,7 @@ private Sun getSunInfo(Calendar calendar, double latitude, double longitude, Dou
sun.setZodiac(zodiacCalc.getZodiac(calendar));

SeasonCalc seasonCalc = new SeasonCalc();
sun.setSeason(seasonCalc.getSeason(calendar, latitude));
sun.setSeason(seasonCalc.getSeason(calendar, latitude, useMeteorologicalSeason));

// phase
for (Entry<SunPhaseName, Range> rangeEntry : sun.getAllRanges().entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class AstroThingConfig {
public @Nullable Double altitude;
public @Nullable Double latitude;
public @Nullable Double longitude;
public boolean useMeteorologicalSeason;
public int interval = 300;
private @Nullable String thingUid;

Expand Down Expand Up @@ -66,6 +67,6 @@ public void setThingUid(String thingUid) {
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("thing", thingUid)
.append("geolocation", geolocation).append("altitude", altitude).append("interval", interval)
.toString();
.append("useMeteorologicalSeason", useMeteorologicalSeason).toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

Expand Down Expand Up @@ -49,7 +50,7 @@
public class AstroDiscoveryService extends AbstractDiscoveryService {
private static final int DISCOVER_TIMEOUT_SECONDS = 2;
private static final int LOCATION_CHANGED_CHECK_INTERVAL = 60;

private static final Set<String> METEO_BASED_COUNTRIES = new HashSet<>(Arrays.asList("NZ", "AU"));
private static final ThingUID SUN_THING = new ThingUID(THING_TYPE_SUN, LOCAL);
private static final ThingUID MOON_THING = new ThingUID(THING_TYPE_MOON, LOCAL);

Expand Down Expand Up @@ -110,10 +111,13 @@ protected void stopBackgroundDiscovery() {

public void createResults(PointType location) {
String propGeolocation;
String country = localeProvider.getLocale().getCountry();
propGeolocation = String.format("%s,%s,%s", location.getLatitude(), location.getLongitude(),
location.getAltitude());
thingDiscovered(DiscoveryResultBuilder.create(SUN_THING).withLabel("Local Sun")
.withProperty("geolocation", propGeolocation).withRepresentationProperty("geolocation").build());
.withProperty("geolocation", propGeolocation)
.withProperty("useMeteorologicalSeason", METEO_BASED_COUNTRIES.contains(country))
.withRepresentationProperty("geolocation").build());
thingDiscovered(DiscoveryResultBuilder.create(MOON_THING).withLabel("Local Moon")
.withProperty("geolocation", propGeolocation).withRepresentationProperty("geolocation").build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,6 @@ private void initializeSun() {
Double latitude = thingConfig.latitude;
Double longitude = thingConfig.longitude;
sun = sunCalc.getSunInfo(Calendar.getInstance(), latitude != null ? latitude : 0,
longitude != null ? longitude : 0, thingConfig.altitude);
longitude != null ? longitude : 0, thingConfig.altitude, thingConfig.useMeteorologicalSeason);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@
*/
package org.openhab.binding.astro.internal.job;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* This class contains the default methods required for different jobs
*
* @author Amit Kumar Mondal - Initial contribution
*/
@NonNullByDefault
public abstract class AbstractJob implements Job {

private final String thingUID;

public AbstractJob(String thingUID) {
checkArgument(thingUID != null, "The thingUID must not be null");
this.thingUID = thingUID;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
import java.util.List;
import java.util.stream.Collectors;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* {@link CompositeJob} comprises multiple {@link Job}s to be executed in order
*
* @author Markus Rathgeb - Initial contribution
* @author Amit Kumar Mondal - Minor modifications
*/
@NonNullByDefault
public final class CompositeJob extends AbstractJob {

private final List<Job> jobs;
Expand All @@ -35,8 +38,6 @@ public final class CompositeJob extends AbstractJob {
*/
public CompositeJob(String thingUID, List<Job> jobs) {
super(thingUID);
checkArgument(jobs != null, "Jobs must not be null");
checkArgument(!jobs.isEmpty(), "Jobs must not be empty");

this.jobs = jobs;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static org.openhab.binding.astro.internal.AstroBindingConstants.*;
import static org.openhab.binding.astro.internal.job.Job.scheduleEvent;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.astro.internal.handler.AstroThingHandler;
import org.openhab.binding.astro.internal.model.Eclipse;
import org.openhab.binding.astro.internal.model.Moon;
Expand All @@ -27,6 +28,7 @@
* @author Gerhard Riegler - Initial contribution
* @author Amit Kumar Mondal - Implementation to be compliant with ESH Scheduler
*/
@NonNullByDefault
public final class DailyJobMoon extends AbstractJob {

private final AstroThingHandler handler;
Expand All @@ -40,7 +42,6 @@ public final class DailyJobMoon extends AbstractJob {
*/
public DailyJobMoon(String thingUID, AstroThingHandler handler) {
super(thingUID);
checkArgument(handler != null, "The handler must not be null");
this.handler = handler;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static org.openhab.binding.astro.internal.job.Job.*;
import static org.openhab.binding.astro.internal.model.SunPhaseName.*;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.astro.internal.handler.AstroThingHandler;
import org.openhab.binding.astro.internal.model.Planet;
import org.openhab.binding.astro.internal.model.Sun;
Expand All @@ -27,6 +28,7 @@
* @author Gerhard Riegler - Initial contribution
* @author Amit Kumar Mondal - Implementation to be compliant with ESH Scheduler
*/
@NonNullByDefault
public final class DailyJobSun extends AbstractJob {

private final AstroThingHandler handler;
Expand All @@ -41,7 +43,6 @@ public final class DailyJobSun extends AbstractJob {
*/
public DailyJobSun(String thingUID, AstroThingHandler handler) {
super(thingUID);
checkArgument(handler != null, "The handler must not be null");
this.handler = handler;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
*/
package org.openhab.binding.astro.internal.job;

import static org.openhab.binding.astro.internal.job.Job.checkNull;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.astro.internal.AstroHandlerFactory;
import org.openhab.binding.astro.internal.handler.AstroThingHandler;

Expand All @@ -23,6 +22,7 @@
* @author Gerhard Riegler - Initial contribution
* @author Amit Kumar Mondal - Implementation to be compliant with ESH Scheduler
*/
@NonNullByDefault
public final class EventJob extends AbstractJob {

private final String channelID;
Expand All @@ -39,19 +39,18 @@ public final class EventJob extends AbstractJob {
*/
public EventJob(String thingUID, String channelID, String event) {
super(thingUID);
checkArgument(channelID != null, "The channelID must not be null");
checkArgument(event != null, "The event must not be null");
this.channelID = channelID;
this.event = event;
}

@Override
public void run() {
AstroThingHandler astroHandler = AstroHandlerFactory.getHandler(getThingUID());
if (checkNull(astroHandler, "AstroThingHandler is null")) {
return;
if (astroHandler != null) {
astroHandler.triggerEvent(channelID, event);
} else {
LOGGER.trace("AstroThingHandler is null");
}
astroHandler.triggerEvent(channelID, event);
}

@Override
Expand Down
Loading

0 comments on commit 62e50ff

Please sign in to comment.