Adding weather data

This commit is contained in:
2021-09-04 21:37:37 +02:00
parent 7800885e0b
commit 13bb9f2399
14 changed files with 218 additions and 27 deletions

View File

@@ -0,0 +1,3 @@
ALTER TABLE messages ADD weather_icon VARCHAR(30) AFTER posted_on;
ALTER TABLE messages ADD weather_cond VARCHAR(30) AFTER weather_icon;
ALTER TABLE messages ADD weather_temp DECIMAL(3,1) AFTER weather_cond;

View File

@@ -3,6 +3,7 @@
namespace Franzz\Spot;
use Franzz\Objects\PhpObject;
use Franzz\Objects\Db;
use Franzz\Objects\Translator;
use \Settings;
/**
@@ -17,6 +18,16 @@ class Feed extends PhpObject {
const FEED_TYPE_JSON = '/message.json';
const FEED_MAX_REFRESH = 5 * 60; //Seconds
//Weather
const WEATHER_HOOK = 'https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline';
const WEATHER_PARAM = array(
'key' => Settings::WEATHER_TOKEN,
'unitGroup' => 'metric',
'lang' => 'en',
'include' => 'current',
'iconSet' => 'icons2'
);
//DB Tables
const SPOT_TABLE = 'spots';
const FEED_TABLE = 'feeds';
@@ -95,17 +106,35 @@ class Feed extends PhpObject {
public function getMessages($asConstraints=array()) {
$asInfo = array(
'select' => array(Db::getId(self::MSG_TABLE), 'ref_msg_id', 'type', 'latitude', 'longitude', 'site_time', 'timezone', 'unix_time'),
'select' => array(
Db::getId(self::MSG_TABLE), 'ref_msg_id', 'type', //ID
'latitude', 'longitude', //Position
'site_time', 'timezone', 'unix_time', //Time
'weather_icon', 'weather_cond', 'weather_temp' //Weather
),
'from' => self::MSG_TABLE,
'join' => array(self::FEED_TABLE => Db::getId(self::FEED_TABLE)),
'constraint'=> array(Db::getId(self::FEED_TABLE, true) => $this->getFeedId()),
'constOpe' => array(Db::getId(self::FEED_TABLE, true) => "="),
'orderBy' => array('site_time'=>'ASC')
);
if(!empty($asConstraints)) $asInfo = array_merge($asInfo, $asConstraints);
return $this->oDb->selectRows($asInfo);
$asResult = $this->oDb->selectRows($asInfo);
/* Temporary lookup - Start */
$iCount = 0;
foreach($asResult as &$asMsg) {
if($asMsg['weather_icon'] == '' && $iCount < 3) {
$asWeather = $this->getWeather(array($asMsg['latitude'], $asMsg['longitude']), $asMsg['unix_time']);
$asMsg = array_merge($asMsg, $asWeather);
$this->oDb->updateRow(self::MSG_TABLE, $asMsg[Db::getId(self::MSG_TABLE)], $asWeather, false);
$iCount++;
}
}
/* Temporary lookup - End */
return $asResult;
}
public function getLastMessageId($asConstraints=array()) {
@@ -181,7 +210,12 @@ class Feed extends PhpObject {
$iMsgId = $this->oDb->selectId(self::MSG_TABLE, array('ref_msg_id'=>$asMsg['ref_msg_id']));
if(!$iMsgId) {
//First Catch
$asMsg['posted_on'] = $sNow;
//Weather Data
$asMsg = array_merge($asMsg, $this->getWeather(array($asMsg['latitude'], $asMsg['longitude']), $asMsg['unix_time']));
$this->oDb->insertRow(self::MSG_TABLE, $asMsg);
$bNewMsg = true;
}
@@ -194,6 +228,20 @@ class Feed extends PhpObject {
return $bNewMsg;
}
private function getWeather($asLatLng, $iTimeStamp) {
$sApiUrl = self::WEATHER_HOOK.'/'.$asLatLng[0].','.$asLatLng[1].'/'.$iTimeStamp.'?'.http_build_query(self::WEATHER_PARAM);
$asWeather = json_decode(file_get_contents($sApiUrl), true);
//Get Condition ID
$sCondKey = (new Translator(self::WEATHER_PARAM['lang']))->getTranslationKey($asWeather['currentConditions']['conditions']);
return array(
'weather_icon' => $asWeather['currentConditions']['icon'],
'weather_cond' => $sCondKey,
'weather_temp' => floatval($asWeather['currentConditions']['temp'])
);
}
private function retrieveFeed() {
$sContent = '[]';
if($this->sRefFeedId !='') {

View File

@@ -88,7 +88,7 @@ class Spot extends Main
(
'tables' => array
(
Feed::MSG_TABLE => array('ref_msg_id', Db::getId(Feed::FEED_TABLE), 'type', 'latitude', 'longitude', 'iso_time', 'site_time', 'timezone', 'unix_time', 'content', 'battery_state', 'posted_on'),
Feed::MSG_TABLE => array('ref_msg_id', Db::getId(Feed::FEED_TABLE), 'type', 'latitude', 'longitude', 'iso_time', 'site_time', 'timezone', 'unix_time', 'content', 'battery_state', 'posted_on', 'weather_icon', 'weather_cond', 'weather_temp'),
Feed::FEED_TABLE => array('ref_feed_id', Db::getId(Feed::SPOT_TABLE), Db::getId(Project::PROJ_TABLE), 'name', 'description', 'status', 'last_update'),
Feed::SPOT_TABLE => array('ref_spot_id', 'name', 'model'),
Project::PROJ_TABLE => array('name', 'codename', 'active_from', 'active_to'),
@@ -133,7 +133,10 @@ class Spot extends Main
'min_zoom' => "TINYINT UNSIGNED",
'max_zoom' => "TINYINT UNSIGNED",
'attribution' => "VARCHAR(100)",
'gravatar' => "LONGTEXT"
'gravatar' => "LONGTEXT",
'weather_icon' => "VARCHAR(30)",
'weather_cond' => "VARCHAR(30)",
'weather_temp' => "DECIMAL(3,1)"
),
'constraints' => array
(

View File

@@ -114,3 +114,47 @@ legend = Legend
credits_project = Spotty Project
credits_git = Git Repository
credits_license = under GPLv3 license
weather_type_1 = Blowing Or Drifting Snow
weather_type_2 = Drizzle
weather_type_3 = Heavy Drizzle
weather_type_4 = Light Drizzle
weather_type_5 = Heavy Drizzle/Rain
weather_type_6 = Light Drizzle/Rain
weather_type_7 = Duststorm
weather_type_8 = Fog
weather_type_9 = Freezing Drizzle/Freezing Rain
weather_type_10 = Heavy Freezing Drizzle/Freezing Rain
weather_type_11 = Light Freezing Drizzle/Freezing Rain
weather_type_12 = Freezing Fog
weather_type_13 = Heavy Freezing Rain
weather_type_14 = Light Freezing Rain
weather_type_15 = Funnel Cloud/Tornado
weather_type_16 = Hail Showers
weather_type_17 = Ice
weather_type_18 = Lightning Without Thunder
weather_type_19 = Mist
weather_type_20 = Precipitation In Vicinity
weather_type_21 = Rain
weather_type_22 = Heavy Rain And Snow
weather_type_23 = Light Rain And Snow
weather_type_24 = Rain Showers
weather_type_25 = Heavy Rain
weather_type_26 = Light Rain
weather_type_27 = Sky Coverage Decreasing
weather_type_28 = Sky Coverage Increasing
weather_type_29 = Sky Unchanged
weather_type_30 = Smoke Or Haze
weather_type_31 = Snow
weather_type_32 = Snow And Rain Showers
weather_type_33 = Snow Showers
weather_type_34 = Heavy Snow
weather_type_35 = Light Snow
weather_type_36 = Squalls
weather_type_37 = Thunderstorm
weather_type_38 = Thunderstorm Without Precipitation
weather_type_39 = Diamond Dust
weather_type_40 = Hail
weather_type_41 = Overcast
weather_type_42 = Partially cloudy
weather_type_43 = Clear

View File

@@ -114,3 +114,47 @@ legend = Légende
credits_project = Projet Spotty
credits_git = Dépôt Git
credits_license = sous licence GPLv3
weather_type_1 = Poudrerie ou neige à la dérive
weather_type_2 = Bruine
weather_type_3 = Bruine lourde
weather_type_4 = Bruine légère
weather_type_5 = Forte bruine / pluie
weather_type_6 = Légère bruine / pluie
weather_type_7 = Tempête de poussière
weather_type_8 = Brouillard
weather_type_9 = Bruine verglaçante / Pluie verglaçante
weather_type_10 = Forte bruine verglaçante / pluie verglaçante
weather_type_11 = Légère bruine verglaçante / pluie verglaçante
weather_type_12 = Brouillard verglaçant
weather_type_13 = Forte pluie verglaçante
weather_type_14 = Légère pluie verglaçante
weather_type_15 = Nuage d'entonnoir / Tornade
weather_type_16 = Douches de grêle
weather_type_17 = La glace
weather_type_18 = Foudre sans tonnerre
weather_type_19 = Brouillard
weather_type_20 = Précipitations à proximité
weather_type_21 = Pluie
weather_type_22 = Forte pluie et neige
weather_type_23 = Légère pluie et neige
weather_type_24 = Averses de pluie
weather_type_25 = Forte pluie
weather_type_26 = Pluie légère
weather_type_27 = Couverture du ciel en baisse
weather_type_28 = Augmentation de la couverture du ciel
weather_type_29 = Ciel inchangé
weather_type_30 = Fumée ou brume
weather_type_31 = Neige
weather_type_32 = Averses de neige et de pluie
weather_type_33 = Douches de neige
weather_type_34 = Beaucoup de neige
weather_type_35 = Neige légère
weather_type_36 = Grains
weather_type_37 = Orage
weather_type_38 = Orage sans précipitations
weather_type_39 = La poussière de diamant
weather_type_40 = Saluer
weather_type_41 = Couvert
weather_type_42 = Partiellement nuageux
weather_type_43 = Clair

View File

@@ -623,6 +623,12 @@ function addSpotMessages(aoMessages) {
.append(oSpot.lang('local_time', oMsg.formatted_time_local)));
}
//Weather
$Tooltip.append($('<p>', {'class':'weather', 'title':oSpot.lang(oMsg.weather_cond)})
.addIcon('fa-'+oMsg.weather_icon+' fa-fw fa-lg', true)
.append(oMsg.weather_temp+'°C')
);
//Tooltip: Medias
if(oMsg.medias) {
var $Medias = $('<div>', {'class':'medias'});
@@ -812,10 +818,11 @@ function getPost(asPost) {
.append($('<p>').addIcon('fa-time', true).append(sAbsTime))
.append(bTimeDiff?$('<p>').addIcon('fa-timezone', true).append(oSpot.lang('local_time', sAbsTimeLocal)):'')
.append($('<a>', {'class':'drill'})
.append($('<span>', {'class':'weather', 'title':oSpot.lang(asPost.weather_cond)}).addIcon('fa-'+asPost.weather_icon, true).append(asPost.weather_temp+'°C'))
.append($('<img>', {'class':'staticmap', title: oSpot.lang('click_zoom'), src: getWmtsApiUrl('static', asPost.latitude, asPost.longitude, 13)}))
.append($('<span>', {'class': 'drill-icon fa-stack'})
.addIcon('fa-message-in fa-stack-1x fa-rotate-270')
.addIcon('fa-message fa-stack-2x')
.addIcon('fa-message-in fa-stack-1x fa-rotate-270')
)
.click(function(){
var $Parent = $(this).parent();

View File

@@ -25,5 +25,4 @@
* Add mail frequency slider
* Use WMTS servers directly when not using Geo Caching Server
* Allow HEIF picture format
* Meteo on message
* pbf map format (https://www.arcgis.com/home/item.html?id=7dc6cea0b1764a1f9af2e679f642f0f5)

View File

@@ -315,7 +315,7 @@ $.prototype.addIcon = function(sIcon, bMargin, sStyle)
{
bMargin = bMargin || false;
sStyle = sStyle || '';
return $(this).prepend($('<i>', {'class':'fa'+sStyle+' '+sIcon+(bMargin?' push':'')}));
return $(this).append($('<i>', {'class':'fa'+sStyle+' '+sIcon+(bMargin?' push':'')}));
};
$.prototype.defaultVal = function(sDefaultValue)

View File

@@ -15,5 +15,6 @@ class Settings
const MAIL_FROM = '';
const MAIL_USER = '';
const MAIL_PASS = '';
const WEATHER_TOKEN = ''; //visualcrossing.com
const DEBUG = true;
}

View File

@@ -92,3 +92,28 @@ $fa-css-prefix: fa;
/* Admin */
.#{$fa-css-prefix}-new:before { content: fa-content($fa-var-plus); }
.#{$fa-css-prefix}-refresh:before { content: fa-content($fa-var-sync); }
/* Weather */
.#{$fa-css-prefix}-temperature:before { content: fa-content($fa-var-thermometer-three-quarters); }
.#{$fa-css-prefix}-clear-day:before { content: fa-content($fa-var-sun); }
.#{$fa-css-prefix}-clear-night:before { content: fa-content($fa-var-moon-stars); }
.#{$fa-css-prefix}-cloudy:before { content: fa-content($fa-var-clouds); }
.#{$fa-css-prefix}-fog:before { content: fa-content($fa-var-fog); }
.#{$fa-css-prefix}-hail:before { content: fa-content($fa-var-cloud-hail); }
.#{$fa-css-prefix}-partly-cloudy-day:before { content: fa-content($fa-var-cloud-sun); }
.#{$fa-css-prefix}-partly-cloudy-night:before { content: fa-content($fa-var-cloud-moon); }
.#{$fa-css-prefix}-rain-snow-showers-day:before { content: fa-content($fa-var-cloud-sun-rain); }
.#{$fa-css-prefix}-rain-snow-showers-night:before { content: fa-content($fa-var-cloud-moon-rain); }
.#{$fa-css-prefix}-rain-snow:before { content: fa-content($fa-var-cloud-sleet); }
.#{$fa-css-prefix}-rain:before { content: fa-content($fa-var-cloud-rain); }
.#{$fa-css-prefix}-showers-day:before { content: fa-content($fa-var-cloud-sun-rain); }
.#{$fa-css-prefix}-showers-night:before { content: fa-content($fa-var-cloud-moon-rain); }
.#{$fa-css-prefix}-sleet:before { content: fa-content($fa-var-cloud-sleet); }
.#{$fa-css-prefix}-snow-showers-day:before { content: fa-content($fa-var-cloud-snow); }
.#{$fa-css-prefix}-snow-showers-night:before { content: fa-content($fa-var-cloud-snow); }
.#{$fa-css-prefix}-snow:before { content: fa-content($fa-var-cloud-snow); }
.#{$fa-css-prefix}-thunder-rain:before { content: fa-content($fa-var-thunderstorm); }
.#{$fa-css-prefix}-thunder-showers-day:before { content: fa-content($fa-var-thunderstorm-sun); }
.#{$fa-css-prefix}-thunder-showers-night:before { content: fa-content($fa-var-thunderstorm-moon); }
.#{$fa-css-prefix}-thunder:before { content: fa-content($fa-var-thunderstorm); }
.#{$fa-css-prefix}-wind:before { content: fa-content($fa-var-wind); }

View File

@@ -1,6 +1,8 @@
//Feed width
$elem-spacing: 0.5rem;
$block-spacing: 1rem;
$block-radius: 3px;
$block-shadow: 3px;
$panel-width: 30%;
$panel-width-max: "400px + 3 * #{$block-spacing}";
@@ -175,7 +177,7 @@ $legend-color: $post-color;
img {
max-width: 200px;
max-height: 100px;
border-radius: 3px;
border-radius: $block-radius;
image-orientation: from-image;
transition: All 0.2s;
}
@@ -219,7 +221,7 @@ $legend-color: $post-color;
.leaflet-control {
background-color: rgba(255, 255, 255, 0.6);
font-family: Roboto, Arial, sans-serif;
border-radius: 3px;
border-radius: $block-radius;
border: none;
margin: $block-spacing;
box-shadow: 0 1px 7px rgba(0, 0, 0, .4);
@@ -410,7 +412,7 @@ $legend-color: $post-color;
margin-bottom: $block-spacing;
background: $post-bg;
color: $post-color;
border-radius: 3px;
border-radius: $block-radius;
width: calc(100% - #{$block-spacing});
box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.5);
@@ -522,9 +524,21 @@ $legend-color: $post-color;
}
}
.weather {
position: absolute;
top: $block-spacing;
right: $block-spacing;
border-radius: $block-radius;
background: $message-bg;
color: $message-color;
font-size: 1.2em;
cursor: pointer;
padding: $elem-spacing;
}
.staticmap {
width: 100%;
border-radius: 3px;
border-radius: $block-radius;
cursor: pointer;
}
}
@@ -574,7 +588,7 @@ $legend-color: $post-color;
width: 100%;
image-orientation: from-image;
outline: none;
border-radius: 3px;
border-radius: $block-radius;
}
.comment {
@@ -588,7 +602,7 @@ $legend-color: $post-color;
padding: 0.5em;
text-align: justify;
background: rgba(255, 255, 255, 0.6);
border-radius: 0 0 3px 3px;
border-radius: 0 0 $block-radius $block-radius;
transition: opacity 0.3s;
opacity: 1;
}
@@ -611,16 +625,16 @@ $legend-color: $post-color;
}
}
#settings {
left: calc(min(#{$panel-width} + 3px, #{$panel-width-max} + 3px) * -1);
left: calc(min(#{$panel-width} + #{$block-shadow}, #{$panel-width-max} + #{$block-shadow}) * -1);
transition: left 0.5s;
width: calc(#{$panel-width} + 3px); //Add box-shadow
max-width: calc(#{$panel-width-max} + 3px); //Add box-shadow
width: calc(#{$panel-width} + #{$block-shadow}); //Add box-shadow
max-width: calc(#{$panel-width-max} + #{$block-shadow}); //Add box-shadow
#settings-panel {
width: calc(100% - #{$block-spacing} - 3px); //Remove box-shadow
width: calc(100% - #{$block-spacing} - #{$block-shadow}); //Remove box-shadow
margin: $block-spacing;
border-radius: 3px;
box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, .5);
border-radius: $block-radius;
box-shadow: 2px 2px $block-shadow 0px rgba(0, 0, 0, .5);
color: $post-color;
background: rgba(255, 255, 255, 0.8);
display: flex;
@@ -634,7 +648,7 @@ $legend-color: $post-color;
.logo {
background: rgba(255, 255, 255, .4);
padding: 2rem 1rem;
border-radius: 3px 3px 0 0;
border-radius: $block-radius $block-radius 0 0;
img {
width: 100%;

View File

@@ -1,4 +1,7 @@
@media only screen and (max-width: 800px) {
$panel-width: "100% - 44px - 2 * #{$block-spacing}";
.desktop {
display: none;
}
@@ -11,7 +14,7 @@
}
.leaflet-right, .leaflet-left {
width: calc(100% - 44px - 2 * #{$block-spacing});
width: calc(#{$panel-width});
}
.leaflet-control-container .leaflet-bottom.leaflet-right {
@@ -27,15 +30,15 @@
}
#feed, #settings {
width: calc(100% - 44px - 2 * #{$block-spacing});
width: calc(#{$panel-width});
}
#feed {
right: calc((100% - 44px - 2 * #{$block-spacing}) * -1);
right: calc((#{$panel-width}) * -1);
}
#settings {
left: calc((100% - 44px - 2 * #{$block-spacing}) * -1);
left: calc((#{$panel-width}) * -1);
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long