Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep favorite weather stations #523

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 45 additions & 0 deletions main/gen_gdl90.go
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ func registerADSBTextMessageReceived(msg string) {
}

var wm WeatherMessage
var dataStr string

if (x[0] == "METAR") || (x[0] == "SPECI") {
globalStatus.UAT_METAR_total++
Expand All @@ -773,12 +774,46 @@ func registerADSBTextMessageReceived(msg string) {
wm.Location = x[1]
wm.Time = x[2]
wm.Data = strings.Join(x[3:], " ")
dataStr = wm.Data
wm.LocaltimeReceived = stratuxClock.Time

wmJSON, _ := json.Marshal(&wm)

// Send to weatherUpdate channel for any connected clients.
weatherUpdate.Send(wmJSON)
var wxType string
wxType = x[0]
if wxType == "SPECI" {
wxType = "METAR"
}
if wxType == "TAF.AMD" {
wxType = "TAF"
}
// Update the watch list here
// We look to see if the name is in the list, and if not, we exit
if strings.Contains(globalSettings.WatchList, x[1]) {
// If the list is empty, add this report and return
for wx := range WatchedStations {
// log.Printf("wsplit[1] %s x[1] %s\n",wsplit[1],x[1])
// If the station ID and type match, then overwrite the string
if WatchedStations[wx].MsgType == wxType && WatchedStations[wx].Location == x[1] {
log.Printf("Updated position %d, station %s to %s\n", wx, x[1], msg)
WatchedStations[wx].Time = x[2]
WatchedStations[wx].Data = dataStr
// weatherWatchedUpdate.SendJSON(WatchedStations)
return
}
}
// The type is not in the list, so lets add the string and return
log.Printf("add %s %s to the list, size is %d\n", x[0], x[1], len(WatchedStations))
var thisWatch watchedStationType
thisWatch.MsgType = wxType
thisWatch.Location = x[1]
thisWatch.Time = x[2]
thisWatch.Data = dataStr
WatchedStations = append(WatchedStations, thisWatch)
// weatherWatchedUpdate.SendJSON(WatchedStations)
}
}

func UpdateUATStats(ProductID uint32) {
Expand Down Expand Up @@ -1039,8 +1074,16 @@ type status struct {
Errors []string
}

type watchedStationType struct {
MsgType string
Location string
Time string
Data string
}

var globalSettings settings
var globalStatus status
var WatchedStations []watchedStationType

func defaultSettings() {
globalSettings.UAT_Enabled = true
Expand Down Expand Up @@ -1255,6 +1298,8 @@ func main() {
globalStatus.Version = stratuxVersion
globalStatus.Build = stratuxBuild
globalStatus.Errors = make([]string, 0)
WatchedStations = make([]watchedStationType, 0)

//FlightBox: detect via presence of /etc/FlightBox file.
if _, err := os.Stat("/etc/FlightBox"); !os.IsNotExist(err) {
globalStatus.HardwareBuild = "FlightBox"
Expand Down
31 changes: 31 additions & 0 deletions main/managementinterface.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,33 @@ type SettingMessage struct {
}

// Weather updates channel.
var weatherWatchedUpdate *uibroadcaster
var weatherUpdate *uibroadcaster
var trafficUpdate *uibroadcaster

// Situation updates channel.
var situationUpdate *uibroadcaster

// Raw weather (UATFrame packet stream) update channel.
var weatherRawUpdate *uibroadcaster

func handleWeatherUpdateWS(conn *websocket.Conn) {

timer := time.NewTicker(5 * time.Second)
// weatherWatchedUpdate.AddSocket(conn)
// Connection closes when function returns. Since uibroadcast is writing and we don't need to read anything (for now), just keep it busy.
for {
update, _ := json.Marshal(&WatchedStations)
_, err := conn.Write(update)

if err != nil {
log.Printf("watched weather client disconnected.\n")
break
}
<-timer.C
}
}

/*
The /weather websocket starts off by sending the current buffer of weather messages, then sends updates as they are received.
*/
Expand Down Expand Up @@ -482,6 +506,7 @@ func viewLogs(w http.ResponseWriter, r *http.Request) {
func managementInterface() {
weatherUpdate = NewUIBroadcaster()
trafficUpdate = NewUIBroadcaster()
weatherWatchedUpdate = NewUIBroadcaster()

http.HandleFunc("/", defaultServer)
http.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log"))))
Expand All @@ -505,6 +530,12 @@ func managementInterface() {
Handler: websocket.Handler(handleWeatherWS)}
s.ServeHTTP(w, req)
})
http.HandleFunc("/weatherwatched",
func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{
Handler: websocket.Handler(handleWeatherUpdateWS)}
s.ServeHTTP(w, req)
})
http.HandleFunc("/traffic",
func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{
Expand Down
1 change: 1 addition & 0 deletions web/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var URL_SATELLITES_GET = "http://" + URL_HOST_BASE + "/getSatellites"
var URL_STATUS_WS = "ws://" + URL_HOST_BASE + "/status"
var URL_TRAFFIC_WS = "ws://" + URL_HOST_BASE + "/traffic";
var URL_WEATHER_WS = "ws://" + URL_HOST_BASE + "/weather";
var URL_WEATHER_WATCH_WS = "ws://" + URL_HOST_BASE + "/weatherwatched";
var URL_DEVELOPER_GET = "ws://" + URL_HOST_BASE + "/developer";
var URL_UPDATE_UPLOAD = "http://" + URL_HOST_BASE + "/updateUpload";
var URL_REBOOT = "http://" + URL_HOST_BASE + "/reboot";
Expand Down
105 changes: 103 additions & 2 deletions web/plates/js/weather.js
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,37 @@ function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
data_item.data = obj.Data;
}

function setDataItemWatched(wx, data_item) {

var dataString = "";
var i;

i=0;
c=0;
data_item.type = wx.MsgType;
data_item.update = false;

data_item.flight_condition = parseFlightCondition(wx.MsgType, wx.Data);
data_item.location = wx.Location;

var dNow = new Date();
var dThen = parseShortDatetime(wx.Time);
data_item.age = dThen.getTime();
data_item.time = deltaTimeString(dNow - dThen) + " old";
data_item.data = wx.Data;
}

function setDataItemTest(Data, data_item) {
var msgSplit = Data.split(" ");
data_item.type = msgSplit[0];
data_item.update = true;
data_item.flight_condition = "VFR";
data_item.location=msgSplit[1];
var dNow = new Date();
data_item.age = dNow.getTime();
data_item.data = Data;
}

function connect($scope) {
if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page
Expand Down Expand Up @@ -181,6 +212,7 @@ function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
var message = JSON.parse(msg.data);
// we need to use an array so AngularJS can perform sorting; it also means we need to loop to find an aircraft in the data_list set
var found = false;
/*
if (inList(message.Location, $scope.watching)) {
for (var i = 0, len = $scope.watch_list.length; i < len; i++) {
if (($scope.watch_list[i].type === message.Type) && ($scope.watch_list[i].location === message.Location)) {
Expand All @@ -195,6 +227,7 @@ function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.watch_list.unshift(new_data_item); // add to start of array
}
}
*/
// add to scrolling data_list
{
var new_data_item = {};
Expand All @@ -204,10 +237,73 @@ function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.data_list.pop(); // remove last from array
}
$scope.data_count = $scope.data_list.length;
$scope.watch_count = $scope.watch_list.length;
$scope.$apply();
};
}
};

function connectWatched($scope) {

if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page

if (($scope.socketWatched === undefined) || ($scope.socketWatched === null)) {
socketWatched = new WebSocket(URL_WEATHER_WATCH_WS);
$scope.socketWatched = socketWatched; // store status socket in scope for enter/exit usage
}

$scope.ConnectStateStatus = "Disconnected";

socketWatched.onopen = function (msg) {
// $scope.ConnectStyle = "label-success";
$scope.ConnectStateStatus = "Connected";
};

socketWatched.onclose = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectStateStatus = "Disconnected";
$scope.$apply();
setTimeout(connectWatched, 1000);
};

socketWatched.onerror = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectStateStatus = "Problem";
$scope.$apply();
};

socketWatched.onmessage = function (msg) {
console.log('Received watched weather update.');

$scope.raw_data = angular.toJson(msg.data, true);
var watched = JSON.parse(msg.data)
// Update Status
// Copy watched stations
console.log(watched);
console.log(watched[0]);
for (var j = 0; j < watched.length; j++)
{
found = false;

for (var i = 0; i < $scope.watch_list.length; i++) {
if ((found === false) && ($scope.watch_list[i].type === watched[j].MsgType) && ($scope.watch_list[i].location === watched[j].Location)) {
setDataItemWatched(watched[j], $scope.watch_list[i]);
found = true;
}
}

if (!found) {
var new_data_item = {};
setDataItemWatched(watched[j], new_data_item);
$scope.watch_list.unshift(new_data_item); // add to start of array
}
}

$scope.watch_count = $scope.watch_list.length;
$scope.$apply(); // trigger any needed refreshing of data

};

}

// perform cleanup every 5 minutes
var clearStaleMessages = $interval(function () {
Expand Down Expand Up @@ -239,6 +335,10 @@ function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.socket.close();
$scope.socket = null;
}
if (($scope.socketWatched !== undefined) && ($scope.socketWatched !== null)) {
$scope.socketWatched.close();
$scope.socketWatched = null;
}
// stop stale message cleanup
$interval.cancel(clearStaleMessages);
};
Expand All @@ -248,4 +348,5 @@ function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
// Weather Controller tasks
updateWatchList();
connect($scope); // connect - opens a socket and listens for messages
connectWatched($scope);
};