Skip to content

Commit

Permalink
Merge pull request #99 from mrjones-plip/69-yarrr-pirate-weather-is-h…
Browse files Browse the repository at this point in the history
…ere-darksky-be-walkin-th-plank

Support other forecast APIs
  • Loading branch information
mrjones-plip authored May 21, 2023
2 parents e3aa850 + dce41e2 commit f087605
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 41 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ venv
config.php
config.csv
datadarksky.cache
forecast.cache
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ to DIY a weather station.

Goals for this project are:

* Use cheap hardware (e.g. Rasberry Pi)
* Use cheap hardware (e.g. Rasberry Pi from 2017)
* Show live weather from local, wireless sensors
* Show time
* Show today's sunset/sunrise times
* Show weather forecast from [Dark Sky API](https://darksky.net/dev/)
* Show weather forecast from a forecast API ([Dark Sky](https://darksky.net/dev/) or [Pirate Weather](pirateweather.net/))

## Hardware

Expand All @@ -32,7 +32,7 @@ Here's the parts I used and prices at time of publishing (March 2017):
* $43 - [Rasberry Pi 3 Model B and Power Adapter](http://amzn.to/2nklto3)
* $11 - [8GB Micro SD card](http://amzn.to/2nRE9Pt)

Total for this is $127, so, erm, not that cheap. Ideally you'd have a lot of
Total for this is $127, so, erm, not _that_ cheap. Ideally you'd have a lot of
parts around you could re-use for this project. As well, you could reduce the price by going with a
3.5" screen ([only $17](http://amzn.to/2mCIxlg)) and Pi B+ ([only $30](http://amzn.to/2n5nioJ))
. For the B+ you'd have to use ethernet or bring your own USB WiFi
Expand Down Expand Up @@ -128,7 +128,7 @@ of creating your own config file. Here we see ID 231:
Specifically, your latitude (`lat`),
longitude (`lon`) and labels which you
got in the step above running `rtl_433`. As well, you'll need to sign up for an API key
on [Dark Sky](https://darksky.net/dev/register) and put that in for the `darksky` value below.
on [Dark Sky](https://darksky.net/dev/register) or [Pirate Weather](pirateweather.net/) and put that in for the `forecast_api` value below.
If you want static icons instead of
animated ones, set 'animate' to `false` instead of `true` like below. Here's a sample:
```
Expand All @@ -137,8 +137,11 @@ animated ones, set 'animate' to `false` instead of `true` like below. Here's a s
lat,31.775554
lon,-81.822436
# set your darksky API token - should be a 32 char alpa numeric
darksky,aabbccddeeffgghhiijj112233445566
# set your forecast API token - should be a 32-40 char alpha numeric
forecast_api_token,aabbccddeeffgghhiijj112233445566
# set your forecast API URL
forecast_api_url,https://api.pirateweather.net
# should we show animated icons for forecast? should be "true" or "false"
animate,true
Expand Down Expand Up @@ -295,10 +298,10 @@ IP address of your server:
## Development
Check out this repo, ``cd`` into and start a web server:
Check out this repo, `cd` into the `html` directory and start a web server:
```
sudo php -S localhost:8000
php -S localhost:8000
```
The rtl_433 works great on Ubuntu for desktop/laptop development. Manually kick off the input
Expand Down Expand Up @@ -339,6 +342,9 @@ Use your IDE of choice to edit and point your browser at ``localhost:8000``
PRs and Issues welcome!

## Version History
* 0.10.0 - Apr 3,2023
* Support Pirate Weather by default #69
* Move to SemVer versioning (MAJOR.MINOR.PATCH)
* 0.9.10 - Jul 20,2020
* Convert to more JSON, less HTML over AJAX calls #89
* Allow big clock mode by clicking time #82
Expand Down
9 changes: 7 additions & 2 deletions config.dist.csv
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
lat,31.775554
lon,-81.822436

# set your darksky API token - should be a 32 char alpa numeric
darksky,aabbccddeeffgghhiijj112233445566
# set your forecast API token from either Dark Sky or Pirate Weather
forecast_api_token,aabbccddeeffgghhiijj112233445566

# set your provider for forecasts (must end in an:
# pirate weather: https://api.pirateweather.net
# dark sky: https://api.darksky.net
forecast_api_url,https://api.pirateweather.net

# should we show animated icons for forecast? should be "true" or "false"
animate,true
Expand Down
2 changes: 1 addition & 1 deletion html/ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
$today = date('Y-m-d', time());
$time = date('g:i A', time());
$date = date('D M j', time());
$forecast = getDarkSkyData();
$forecast = getForecastData();

switch ($_GET['content']){
case "forecast":
Expand Down
53 changes: 29 additions & 24 deletions html/get_data.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ function getValidConfigs(){
return array(
'lat',
'lon',
'darksky',
'forecast_api_token',
'forecast_api_url',
'labels',
'animate',
'dataPath',
Expand Down Expand Up @@ -68,9 +69,13 @@ function configIsValid($validateApi = false)
$valid['valid'] = false;
$valid['reason'] .= 'Missing required option. ';
}
if (!isset($YANPIWS['darksky']) || strlen($YANPIWS['darksky']) != 32){
if (!isset($YANPIWS['forecast_api_url']) || strlen($YANPIWS['forecast_api_url']) < 10){
$valid['valid'] = false;
$valid['reason'] .= 'Dark Sky API Key is wrong length or missing. ';
$valid['reason'] .= 'Forecast API URL is wrong length or missing. (<pre>forecast_api_url</pre>)';
}
if (!isset($YANPIWS['forecast_api_token']) || strlen($YANPIWS['forecast_api_token']) < 32 || strlen($YANPIWS['forecast_api_token']) > 41){
$valid['valid'] = false;
$valid['reason'] .= 'Forecast API Key is wrong length or missing. (<pre>forecast_api_token</pre>)';
}
if(!isset($YANPIWS['lat'])) {
$valid['valid'] = false;
Expand Down Expand Up @@ -121,13 +126,13 @@ function configIsValid($validateApi = false)
$valid['reason'] .= 'DataPath does not exist or is not writable. ';
}
if ($validateApi){
$http = curl_init(getDarkSkyUrl(true));
$http = curl_init(getForecastUrl(true));
curl_setopt($http, CURLOPT_NOBODY , true);
curl_exec($http);
$http_status = curl_getinfo($http, CURLINFO_HTTP_CODE);
if ($http_status != 200){
$valid['valid'] = false;
$valid['reason'] .= 'Dark Sky API call failed: Either invalid API key or invalid Lat/Long ' .
$valid['reason'] .= 'Forecast API call failed: Either invalid API key or invalid Lat/Long ' .
"(status: $http_status). ";
}
}
Expand Down Expand Up @@ -300,17 +305,17 @@ function getHumidityHtml($tempLine, $useLabel = false)
}

/**
* Get the age in human time (sec, min, hour etc) of the dark sky cache
* Get the age in human time (sec, min, hour etc) of the Forecast cache
* @param $returnSeconds boolean to return int of seconds if true, otherwise string of human time
*/
function getCacheAge($returnSeconds = false){
global $YANPIWS;
$path = $YANPIWS['dataPath'];
$darkskytime = filemtime($path . 'darksky.cache');
$forecast_cache_time = filemtime($path . 'forecast.cache');
if (!$returnSeconds) {
return getHumanTime(time() - $darkskytime);
return getHumanTime(time() - $forecast_cache_time);
} else {
return (time() - $darkskytime);
return (time() - $forecast_cache_time);
}
}

Expand Down Expand Up @@ -367,21 +372,21 @@ function getSunriseHtml($time)
}

/**
* get data from dark sky. will cache data and refresh it every 10 minutes
* get data from Forecast API. will cache data and refresh it every 10 minutes
*
* @return stdClass of either resutls or very lightly populated error object
*/
function getDarkSkyData()
function getForecastData()
{
global $YANPIWS;
$path = $YANPIWS['dataPath'];
$cache = $path . 'darksky.cache';
$cache = $path . 'forecast.cache';
$hourAgo = time() - (60*10); // 10 minutes
$data = false;
$configStatus = configIsValid();
if($configStatus['valid'] === true) {
if ((!is_file($cache) || filectime($cache) < $hourAgo)) {
$http = curl_init(getDarkSkyUrl());
$http = curl_init(getForecastUrl());
curl_setopt($http, CURLOPT_RETURNTRANSFER, 1);
$dataFromRemote = curl_exec($http);
$http_status = curl_getinfo($http, CURLINFO_HTTP_CODE);
Expand All @@ -406,11 +411,11 @@ function getDarkSkyData()
}

/**
* Simple wrapper to concat the string for the Dark Sky API endpoint
* Simple wrapper to concat the string for the Forecast API endpoint
*
* @return string of URL
*/
function getDarkSkyUrl($useTestLatLong = false){
function getForecastUrl($useTestLatLong = false){
global $YANPIWS;
if ($useTestLatLong){
$lat = "31.775554";
Expand All @@ -419,13 +424,13 @@ function getDarkSkyUrl($useTestLatLong = false){
$lat = $YANPIWS['lat'];
$lon = $YANPIWS['lon'];
}
return 'https://api.darksky.net/forecast/' . $YANPIWS['darksky'] . '/' . $lat . ',' . $lon;
return $YANPIWS['forecast_api_url'] . '/forecast/' . $YANPIWS['forecast_api_token'] . '/' . $lat . ',' . $lon;
}

/**
* expects the $data->daily object from getDarkSkyData(), returns $days (default 5) of forecast HTML
* expects the $data->daily object from getForecastData(), returns $days (default 5) of forecast HTML
*
* @param null $daily $data->daily object from getDarkSkyData()
* @param null $daily $data->daily object from getForecastData()
* @param int $days how many days of forecast to return
* @return string of HTML
*/
Expand All @@ -437,7 +442,7 @@ function getDailyForecastHtml($daily = null, $days = 5)
if ($daily == null) {
// show rain for error
$html .= "<img src='./skycons/rain.png' class='errorImg' /> ";
$html .= "No Dark Sky Data for forecast.";
$html .= "No Data for forecast.";
} else {
$count = 1;
foreach ($daily->data as $day) {
Expand Down Expand Up @@ -468,17 +473,17 @@ function getDailyForecastHtml($daily = null, $days = 5)
}

/**
* expects the $data->daily object from getDarkSkyData(), returns $days (default 5) of forecast HTML
* expects the $data->daily object from getForecastData(), returns $days (default 5) of forecast HTML
*
* @param null $daily $data->daily object from getDarkSkyData()
* @param null $daily $data->daily object from getForecastData()
* @param int $days how many days of forecast to return
* @return string of HTML
*/
function getDailyForecast($daily = null, $days = 5)
{
$result = array();
if ($daily == null) {
$result['result'] = "No Dark Sky Data for forecast.";
$result['result'] = "No Data for forecast.";
} else {

$count = 1;
Expand Down Expand Up @@ -541,9 +546,9 @@ function getHumanTime($s)


/**
* expects the $data->currently object from getDarkSkyData(), returns windspeed HTML
* expects the $data->currently object from getForecastData(), returns windspeed HTML
*
* @param null $daily $data->currently object from getDarkSkyData()
* @param null $daily $data->currently object from getForecastData()
* @return string of HTML
*/
function getCurrentWind($currentlyObject)
Expand Down
2 changes: 1 addition & 1 deletion html/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require_once 'get_data.php';
getConfig();

$forecast = getDarkSkyData();
$forecast = getForecastData();
$status = configIsValid();
$statusHtml = '';
if ($status['valid'] != true) {
Expand Down
8 changes: 4 additions & 4 deletions html/stats.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
$address = 'NA';
}

$darkskytime= getCacheAge();
$cachetime= getCacheAge();
?>
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
Expand All @@ -29,10 +29,10 @@
<p>
<a href="/" class="homeLink"><- Weather</a>
</p>
<a href="https://github.com/mrjones-plip/YANPIWS">YANPIS 0.9.10</a> - Released Jul 26, 2020<br />
<a href="https://darksky.net/poweredby/">Powered by Dark Sky</a><br />
<a href="https://github.com/mrjones-plip/YANPIWS">YANPIWS 0.10.0</a> - Released Apr 3, 2023<br />
<a href="http://pirateweather.net/en/latest/#introduction/">Powered by Pirate Weather</a><br />
<?php echo $currentTempHtml ?>
Dark Sky Cache Age: <?php echo $darkskytime ?><br/>
Forecast Cache Age: <?php echo $cachetime ?><br/>
IP: <?php echo $address ?>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion html/temps.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<?php
require_once 'get_data.php';
getConfig();
$forecast = getDarkSkyData();
$forecast = getForecastData();
$status = configIsValid();

// get two days worth of data and merge them so we can ensure we have a
Expand Down

0 comments on commit f087605

Please sign in to comment.