Skip to content

Commit

Permalink
Merge branch 'release/1.05'
Browse files Browse the repository at this point in the history
  • Loading branch information
darmbrust committed Apr 22, 2020
2 parents 299defa + df6ad88 commit 7d40974
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 26 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ Depending on if/how you have java installed, you may be able to just double-clic

If not, run with
```
java -jar weatherlink<Platform>.jar
java -jar weatherlink<Platform>.jar [ip address]
```
If you don't have java, grab the latest 11 version for your platform:
https://adoptopenjdk.net/releases.html?variant=openjdk11&jvmVariant=hotspot

# First Run
It should be able to auto-locate your WeatherLinkLive, so long as it is on the local network.

If it fails to find your Weather Link Live, you can set the IP address as a command line parameter after the jar file name.

When you first run it, things may be a bit sparse. Data will fill in as it runs.

# Data Store
Expand All @@ -42,6 +44,6 @@ There are lots of TODOs.... useful things I may add (pull requests welcome)

# Release Notes
```
mvn -B gitflow:release-start gitflow:release-finish -DreleaseVersion=1.04 -DdevelopmentVersion=1.05
mvn -B gitflow:release-start gitflow:release-finish -DreleaseVersion=1.05 -DdevelopmentVersion=1.06
```
12 changes: 3 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>net.sagebits.weatherlink</groupId>
<artifactId>weatherlink</artifactId>
<version>1.04</version>
<version>1.05</version>
<packaging>jar</packaging>

<name>WeatherLink Logger and GUI</name>
Expand Down Expand Up @@ -90,15 +90,9 @@
<version>11.2</version>
</dependency>
<dependency>
<groupId>net.straylightlabs</groupId>
<groupId>net.sagebits</groupId>
<artifactId>hola</artifactId>
<version>0.2.1</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
<version>0.2.4-sagebits</version>
</dependency>
</dependencies>

Expand Down
8 changes: 4 additions & 4 deletions src/main/java/net/sagebits/weatherlink/data/DataFetcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.LogManager;
Expand Down Expand Up @@ -48,9 +47,7 @@ public WeatherProperty getDataFor(String wllDeviceId, String sensorId, StoredDat
{
ConcurrentHashMap<StoredDataTypes, WeatherProperty> data = mostRecentData.computeIfAbsent(wllDeviceId + "|" + sensorId, keyAgain -> new ConcurrentHashMap<>());

log.debug("Data requested for {} from {} {}", sdt, wllDeviceId, sensorId);

return data.computeIfAbsent(sdt, keyAgain -> {
WeatherProperty wp = data.computeIfAbsent(sdt, keyAgain -> {
//we don't yet have data we are tracking for this element. See if we have any data to populate with....

//Try to read it from the DB
Expand All @@ -64,6 +61,9 @@ public WeatherProperty getDataFor(String wllDeviceId, String sensorId, StoredDat
return readData;
});

log.debug("Data requested for {} from {} {}, returning {}", sdt, wllDeviceId, sensorId, wp.get());
return wp;

}

/**
Expand Down
23 changes: 18 additions & 5 deletions src/main/java/net/sagebits/weatherlink/data/DataReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import javafx.application.Platform;
import javafx.beans.property.LongProperty;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.SimpleLongProperty;
import net.sagebits.weatherlink.data.live.LiveDataListener;
import net.sagebits.weatherlink.data.periodic.PeriodicData;
import net.straylightlabs.hola.dns.Domain;
Expand Down Expand Up @@ -48,6 +52,8 @@ public class DataReader

private final JsonFactory factory = new JsonFactory();
private final ObjectMapper mapper = new ObjectMapper(factory);

private final LongProperty lastReadAttemptTime = new SimpleLongProperty(System.currentTimeMillis());

/**
* @param wllAddress The IP address of the WeatherLinkLive. If not provided, attempts to auto-discover. This constructor will fail if it cannot be
Expand Down Expand Up @@ -148,7 +154,7 @@ public Thread newThread(Runnable r)
}
catch (Exception e)
{
log.error("Request for live data failed:", e);
log.error("Request for live data failed:" + e);
}

}, 0, 1 ,TimeUnit.HOURS);
Expand All @@ -158,14 +164,15 @@ public Thread newThread(Runnable r)
log.error("Problem setting up for live data", e);
}
}
periodicTask = timed.scheduleAtFixedRate(() -> readData(), 0, this.pollInterval,TimeUnit.SECONDS);
periodicTask = timed.scheduleAtFixedRate(() -> readData(), 1, this.pollInterval,TimeUnit.SECONDS);
}


private void readData()
{
try
{
Platform.runLater(() -> lastReadAttemptTime.set(System.currentTimeMillis()));
String data = readBytes(new URL("http://" + address + ":" + port + "/v1/current_conditions"));
log.trace("Periodic Data: {}", data);

Expand All @@ -180,7 +187,8 @@ private void readData()
}
catch (Exception e)
{
log.warn("Error during periodic data read, delaying and rescheduling", e);
//Don't need a stack trace here
log.warn("Error during periodic data read, delaying and rescheduling: {}", e.toString());
//Its probably busy. Lets sleep for a bit, and give it time to recover.
//Will do this by canceling our current task, and rescheduling after a delay.
ScheduledExecutorService localRef = timed;
Expand Down Expand Up @@ -223,14 +231,19 @@ public void stopReading()
}
}

public ReadOnlyLongProperty getLastReadAttemptTime()
{
return lastReadAttemptTime;
}

public static String readBytes(URL url) throws IOException
{
InputStream is = null;
try
{
URLConnection con = url.openConnection();
con.setReadTimeout(1000);
con.setConnectTimeout(250);
con.setReadTimeout(2000);
con.setConnectTimeout(1000);
con.connect();
is = con.getInputStream();
return new String(is.readAllBytes(), StandardCharsets.UTF_8);
Expand Down
17 changes: 15 additions & 2 deletions src/main/java/net/sagebits/weatherlink/data/WeatherProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,20 @@ public void setTimeStamp(long timeStamp)
}

/**
* Will return the bound timestamp, if bound
* Returns the bound, (live) timestamp, if present and valid and up-to-date, otherwise, returns the local (database) timestamp.
*/
public long getTimeStamp()
{
return boundTo == null ? timeStamp : boundTo.getTimeStamp();
if (boundTo == null || boundTo.asDouble().get() == -100.0)
{
return getLocalTimeStamp();
}
if ((this.timeStamp - 8000) > boundTo.timeStamp)
{
//We don't seem to be getting live updates, return the newer stored data.
return getLocalTimeStamp();
}
return boundTo.getTimeStamp();
}

public long getLocalTimeStamp()
Expand Down Expand Up @@ -104,6 +113,10 @@ public void unbind()
boundTo = null;
}

/**
* Returns the bound, (live) data, if present and valid and up-to-date, otherwise, returns the local (database) data.
* @see javafx.beans.property.ObjectPropertyBase#get()
*/
@Override
public Object get()
{
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/net/sagebits/weatherlink/data/live/LiveData.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import javafx.application.Platform;
import javafx.beans.property.LongProperty;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.SimpleLongProperty;

/**
* Instance class to hold the most current live data at any given time. Use this to get to a set of
Expand All @@ -26,6 +30,8 @@ public class LiveData
//Map weatherLinkLive instances (by their did) to map of condition data (one per sensor id 'lsid')
private ConcurrentHashMap<String, ConcurrentHashMap<String, ConditionsLive>> liveData_= new ConcurrentHashMap<>(2);

private LongProperty lastLiveData = new SimpleLongProperty(0);

private LiveData()
{
//singleton
Expand Down Expand Up @@ -62,12 +68,18 @@ public ConditionsLive getLiveData(String weatherLinkLiveId, String sensorId)
return conditions.computeIfAbsent(sensorId, keyAgain -> new ConditionsLive(sensorId, null));
}

public ReadOnlyLongProperty getLastDataTime()
{
return lastLiveData;
}

protected void update(JsonNode data)
{
String did = Optional.ofNullable(data.get("did")).orElseThrow().asText();
ConcurrentHashMap<String, ConditionsLive> conditions = liveData_.computeIfAbsent(did, keyAgain -> new ConcurrentHashMap<>(2));

final long ts = Long.parseLong(Optional.ofNullable(data.get("ts")).orElseThrow().asText()) * 1000;
Platform.runLater(() -> lastLiveData.set(ts));

ArrayNode conditionsData = Optional.ofNullable((ArrayNode) data.get("conditions")).orElseThrow();
Iterator<JsonNode> condition = conditionsData.elements();
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/net/sagebits/weatherlink/gui/WeatherLauncher.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
package net.sagebits.weatherlink.gui;

import java.util.regex.Pattern;
import org.apache.logging.log4j.LogManager;
import javafx.application.Application;

public class WeatherLauncher
{
public static void main(String[] args)
{
if (args != null && args.length > 0)
{
Pattern p = Pattern.compile("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
if (p.matcher(args[0]).matches())
{
WeatherLinkLiveGUIController.ip = args[0];
LogManager.getLogger(WeatherLauncher.class).debug("Read IP '{}' from command line arg", args[0]);
}
else
{
LogManager.getLogger(WeatherLauncher.class).debug("Passed in param '{}' not an ip, ignoring.", args[0]);
}
}
Application.launch(WeatherLinkLiveGUI.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public class WeatherLinkLiveGUI extends Application
private static Stage mainStage_;
private WeatherLinkLiveGUIController wllc_;


public static Logger logger = LogManager.getLogger(WeatherLinkLiveGUI.class);

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.DoubleSupplier;
import java.util.function.Supplier;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.math3.util.Precision;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -66,6 +68,7 @@
import net.sagebits.weatherlink.data.DataReader;
import net.sagebits.weatherlink.data.StoredDataTypes;
import net.sagebits.weatherlink.data.WeatherProperty;
import net.sagebits.weatherlink.data.live.LiveData;
import net.sagebits.weatherlink.data.periodic.PeriodicData;
import net.sagebits.weatherlink.gui.gapchart.GapLineChart;
import net.sagebits.weatherlink.gui.gapchart.GapNumberAxis;
Expand All @@ -89,6 +92,7 @@ public class WeatherLinkLiveGUIController
private ArrayList<Supplier<Void>> midnightTasks = new ArrayList<>();
private ScheduledExecutorService periodicJobs = Executors.newScheduledThreadPool(2, r -> new Thread(r, "Periodic GUI Jobs"));

protected static String ip = null;

@FXML
void initialize()
Expand All @@ -110,7 +114,7 @@ public void finishInit(Stage mainStage)
log.debug("Data Reader init thread starts");
try
{
dr = new DataReader(Optional.empty());
dr = new DataReader(Optional.ofNullable(StringUtils.isBlank(ip) ? null : ip));
dr.startReading(10, true);
}
catch (Exception e)
Expand Down Expand Up @@ -477,7 +481,7 @@ private Gauge buildQuarterWindGauge(String wllDeviceId, String sensorOutdoorId)
.markers(dayMax, tenMH, twoMH, tenMA, twoMA, oneMA)
.markersVisible(true)
.knobType(KnobType.STANDARD)
.knobColor(Gauge.DARK_COLOR)
.knobColor(Color.RED)
.needleShape(NeedleShape.FLAT)
.needleType(NeedleType.VARIOMETER)
.needleSize(NeedleSize.THIN)
Expand Down Expand Up @@ -540,7 +544,46 @@ private Gauge buildQuarterWindGauge(String wllDeviceId, String sensorOutdoorId)
tenMA.valueProperty().bind(DataFetcher.getInstance().getDataFor(wllDeviceId, sensorOutdoorId, StoredDataTypes.wind_speed_avg_last_10_min).asDouble());
twoMA.valueProperty().bind(DataFetcher.getInstance().getDataFor(wllDeviceId, sensorOutdoorId, StoredDataTypes.wind_speed_avg_last_2_min).asDouble());
oneMA.valueProperty().bind(DataFetcher.getInstance().getDataFor(wllDeviceId, sensorOutdoorId, StoredDataTypes.wind_speed_avg_last_1_min).asDouble());

Tooltip tt = new Tooltip("Mode Pending");
Tooltip.install(gauge, tt);
final SimpleDateFormat sdf = new SimpleDateFormat("h:mm:ss");

final Consumer<Void> updateTooltip = input ->
{
//This will give us a pulse, every read attempt. Don't actually care about the value.
if (currentWind.getTimeStamp() < (System.currentTimeMillis() - 6000))
{
//More than 6 seconds out of date, missed at least 2 live data pulses.
gauge.setKnobColor(Color.BLACK);
tt.setText("Poll Last Update " + sdf.format(new Date(currentWind.getTimeStamp())));
}
else if (currentWind.getTimeStamp() < (System.currentTimeMillis() - 30000))
{
//More than 30 seconds for any data.
gauge.setKnobColor(Color.RED);
tt.setText("Last Update " + sdf.format(new Date(currentWind.getTimeStamp())));
}
else
{
gauge.setKnobColor(Color.GREEN);
tt.setText("Live Last Update " + sdf.format(new Date(currentWind.getTimeStamp())));
}
};

if (dr != null)
{
dr.getLastReadAttemptTime().addListener((value, old, newv) ->
{
updateTooltip.accept(null);
});
}

LiveData.getInstance().getLastDataTime().addListener((value, old, newv) ->
{
updateTooltip.accept(null);
});

return gauge;
}

Expand Down Expand Up @@ -1206,7 +1249,10 @@ public void shutdown()
try
{
periodicJobs.shutdownNow();
dr.stopReading();
if (dr != null)
{
dr.stopReading();
}
}
catch (Exception e)
{
Expand Down

0 comments on commit 7d40974

Please sign in to comment.