Replace windoze CRLF with Linux LF in web files

pull/578/head
Eric Westphal 2017-01-07 22:45:19 -05:00
rodzic 22867df1f4
commit 816411b3ee
15 zmienionych plików z 1516 dodań i 1516 usunięć

Wyświetl plik

@ -1,21 +1,21 @@
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Developer Mode Items</span>
</div>
<div class="panel-body">
<div class="panel-group col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">Restart Stratux application</div>
<div class="panel-body">
<div class="form-group reset-flow">
<div class="col-xs-12">
<a ng-click="postRestart()" ui-turn-off="modalRestartApp" class="btn btn-primary">Restart Application</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Developer Mode Items</span>
</div>
<div class="panel-body">
<div class="panel-group col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">Restart Stratux application</div>
<div class="panel-body">
<div class="form-group reset-flow">
<div class="col-xs-12">
<a ng-click="postRestart()" ui-turn-off="modalRestartApp" class="btn btn-primary">Restart Application</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

Wyświetl plik

@ -1,104 +1,104 @@
<div class="col-sm-12">
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading"><span class="panel_label">GPS</span></div>
<div class="panel-body">
<div class="row">
<span class="col-xs-12">
<div class="map-container">
<div id="map_display" class="world-map" ng-attr-style="background-position:{{map_pos_x + 'px ' + map_pos_y + 'px'}}; width:{{map_width}}px; height:{{map_height}}px;">
<div class="mark-position" ng-style="{left: map_mark_x+'px', top: map_mark_y+'px'}">
<span class="fa fa-crosshairs"></span>
</div>
</div>
</div>
</span>
</div>
<div class="separator"></div>
<div class="row">
<strong class="col-xs-6 text-center">Location:</strong>
<strong class="col-xs-6 text-center">Track:</strong>
</div>
<div class="row">
<span class="col-xs-6 text-center">{{gps_lat}}, {{gps_lon}} &plusmn; {{gps_accuracy}} m <br> {{gps_alt}} &plusmn; {{gps_vert_accuracy}} ft @ {{gps_vert_speed}} ft/min</span>
<span class="col-xs-6 text-center">{{gps_track}}&deg; @ {{gps_speed}} KTS</span>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Satellites</span>
</div>
<div class="panel-body towers-page">
<div class="row">
<span class="col-xs-3"><strong>Satellite</strong></span>
<!--<span class="col-xs-2 text-right"><strong>NMEA Code</strong></span>-->
<span class="col-xs-3 text-right"><strong>Elevation</strong></span>
<span class="col-xs-3 text-right"><strong>Azimuth</strong></span>
<span class="col-xs-3 text-right"><strong>Signal</strong></span>
</div>
<div class="row" ng-repeat="satellite in data_list | orderBy: 'SatelliteNMEA'">
<div class="separator"></div>
<span class="col-xs-3">{{satellite.SatelliteID}}<span ng-show="satellite.InSolution">&nbsp;&#x2705;</span></span>
<!--<span class="col-xs-2 text-right">{{satellite.SatelliteNMEA}}</span>-->
<span class="col-xs-3 text-right">{{satellite.Elevation < -5 ? "---" : satellite.Elevation}}&deg;</span>
<span class="col-xs-3 text-right">{{satellite.Azimuth < 0 ? "---" : satellite.Azimuth}}&deg;</span>
<span class="col-xs-3 text-right">{{satellite.Signal < 1 ? "---" : satellite.Signal}}<span style="font-size:50%">&nbsp;dB-Hz</span></span>
</div>
</div>
<div class="separator"></div>
<div class="panel-footer">
<div class="row">
<label class="col-xs-6">GPS solution:</label>
<span class="col-xs-6">{{SolutionText}}</span>
</div>
<div class="row">
<label class="col-xs-6">Summary:</label>
<span class="col-xs-6">{{Satellites}} in solution; {{GPS_satellites_seen}} seen; {{GPS_satellites_tracked}} tracked</span>
</div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading"><span class="panel_label">AHRS</span></div>
<div class="panel-body">
<div class="row">
<span class="col-xs-12">
<div id="ahrs_display">
<object id="attitude_indicator" data="../img/ai.svg" type="image/svg+xml">
Your browser doesn't support svg.
</object>
</div>
</span>
</div>
<div class="separator"></div>
<div class="row">
<strong class="col-xs-3 text-center">Heading:</strong>
<strong class="col-xs-3 text-center">Pitch:</strong>
<strong class="col-xs-3 text-center">Roll:</strong>
<strong class="col-xs-3 text-center">P-Alt:</strong>
</div>
<div class="row">
<span class="col-xs-3 text-center">{{ahrs_heading}}&deg;</span>
<span class="col-xs-3 text-center">{{ahrs_pitch}}&deg;</span>
<span class="col-xs-3 text-center">{{ahrs_roll}}&deg;</span>
<span class="col-xs-3 text-center">{{ahrs_alt}} ft</span>
</div>
</div>
</div>
</div>
</div>
<!--
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">Raw GPS / AHRS Data</div>
<div class="panel-body">
<pre>{{raw_data}}</pre>
</div>
</div>
</div>
-->
<div class="col-sm-12">
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading"><span class="panel_label">GPS</span></div>
<div class="panel-body">
<div class="row">
<span class="col-xs-12">
<div class="map-container">
<div id="map_display" class="world-map" ng-attr-style="background-position:{{map_pos_x + 'px ' + map_pos_y + 'px'}}; width:{{map_width}}px; height:{{map_height}}px;">
<div class="mark-position" ng-style="{left: map_mark_x+'px', top: map_mark_y+'px'}">
<span class="fa fa-crosshairs"></span>
</div>
</div>
</div>
</span>
</div>
<div class="separator"></div>
<div class="row">
<strong class="col-xs-6 text-center">Location:</strong>
<strong class="col-xs-6 text-center">Track:</strong>
</div>
<div class="row">
<span class="col-xs-6 text-center">{{gps_lat}}, {{gps_lon}} &plusmn; {{gps_accuracy}} m <br> {{gps_alt}} &plusmn; {{gps_vert_accuracy}} ft @ {{gps_vert_speed}} ft/min</span>
<span class="col-xs-6 text-center">{{gps_track}}&deg; @ {{gps_speed}} KTS</span>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Satellites</span>
</div>
<div class="panel-body towers-page">
<div class="row">
<span class="col-xs-3"><strong>Satellite</strong></span>
<!--<span class="col-xs-2 text-right"><strong>NMEA Code</strong></span>-->
<span class="col-xs-3 text-right"><strong>Elevation</strong></span>
<span class="col-xs-3 text-right"><strong>Azimuth</strong></span>
<span class="col-xs-3 text-right"><strong>Signal</strong></span>
</div>
<div class="row" ng-repeat="satellite in data_list | orderBy: 'SatelliteNMEA'">
<div class="separator"></div>
<span class="col-xs-3">{{satellite.SatelliteID}}<span ng-show="satellite.InSolution">&nbsp;&#x2705;</span></span>
<!--<span class="col-xs-2 text-right">{{satellite.SatelliteNMEA}}</span>-->
<span class="col-xs-3 text-right">{{satellite.Elevation < -5 ? "---" : satellite.Elevation}}&deg;</span>
<span class="col-xs-3 text-right">{{satellite.Azimuth < 0 ? "---" : satellite.Azimuth}}&deg;</span>
<span class="col-xs-3 text-right">{{satellite.Signal < 1 ? "---" : satellite.Signal}}<span style="font-size:50%">&nbsp;dB-Hz</span></span>
</div>
</div>
<div class="separator"></div>
<div class="panel-footer">
<div class="row">
<label class="col-xs-6">GPS solution:</label>
<span class="col-xs-6">{{SolutionText}}</span>
</div>
<div class="row">
<label class="col-xs-6">Summary:</label>
<span class="col-xs-6">{{Satellites}} in solution; {{GPS_satellites_seen}} seen; {{GPS_satellites_tracked}} tracked</span>
</div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading"><span class="panel_label">AHRS</span></div>
<div class="panel-body">
<div class="row">
<span class="col-xs-12">
<div id="ahrs_display">
<object id="attitude_indicator" data="../img/ai.svg" type="image/svg+xml">
Your browser doesn't support svg.
</object>
</div>
</span>
</div>
<div class="separator"></div>
<div class="row">
<strong class="col-xs-3 text-center">Heading:</strong>
<strong class="col-xs-3 text-center">Pitch:</strong>
<strong class="col-xs-3 text-center">Roll:</strong>
<strong class="col-xs-3 text-center">P-Alt:</strong>
</div>
<div class="row">
<span class="col-xs-3 text-center">{{ahrs_heading}}&deg;</span>
<span class="col-xs-3 text-center">{{ahrs_pitch}}&deg;</span>
<span class="col-xs-3 text-center">{{ahrs_roll}}&deg;</span>
<span class="col-xs-3 text-center">{{ahrs_alt}} ft</span>
</div>
</div>
</div>
</div>
</div>
<!--
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">Raw GPS / AHRS Data</div>
<div class="panel-body">
<pre>{{raw_data}}</pre>
</div>
</div>
</div>
-->

Wyświetl plik

@ -1,180 +1,180 @@
angular.module('appControllers').controller('GPSCtrl', GPSCtrl); // get the main module contollers set
GPSCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
// create our controller function with all necessary logic
function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.$parent.helppage = 'plates/gps-help.html';
$scope.data_list = [];
var status = {};
var display_area_size = -1;
function sizeMap() {
var width = 0;
var el = document.getElementById("map_display").parentElement;
width = el.offsetWidth; // was (- (2 * el.offsetLeft))
if (width !== display_area_size) {
display_area_size = width;
$scope.map_width = width;
$scope.map_height = width *0.5;
}
return width;
}
function setGeoReferenceMap(la, lo) {
// Mercator projection
// var map = "img/world.png";
var map_width = 2530;
var map_height = 1603;
var map_zero_x = 1192;
var map_zero_y = 1124;
var font_size = 18; // size of font used for marker
sizeMap();
var div_width = $scope.map_width;
var div_height = $scope.map_height;
// longitude: just scale and shift
var x = (map_width * (180 + lo) / 360) - (map_width/2 - map_zero_x); // longitude_shift;
// latitude: using the Mercator projection
la_rad = la * Math.PI / 180; // convert from degrees to radians
merc_n = Math.log(Math.tan((la_rad / 2) + (Math.PI / 4))); // do the Mercator projection (w/ equator of 2pi units)
var y = (map_height / 2) - (map_width * merc_n / (2 * Math.PI)) - (map_height/2 - map_zero_y); // fit it to our map
// dot = '<div style="position:absolute; width:' + dot_size + 'px; height:' + dot_size + 'px; top:' + y + 'px; left:' + x + 'px; background:#ff7f00;"></div>';
// <img src="map-world-medium.png" style="position:absolute;top:0px;left:0px">
$scope.map_pos_x = map_width - Math.round(x - (div_width / 2));
$scope.map_pos_y = map_height - Math.round(y - (div_height / 2));
$scope.map_mark_x = Math.round((div_width - (font_size * 0.85)) / 2);
$scope.map_mark_y = Math.round((div_height - font_size) / 2);
}
function loadStatus(data) { // mySituation
status = angular.fromJson(data);
// consider using angular.extend()
$scope.raw_data = angular.toJson(data, true); // makes it pretty
$scope.Satellites = status.Satellites;
$scope.GPS_satellites_tracked = status.SatellitesTracked;
$scope.GPS_satellites_seen = status.SatellitesSeen;
$scope.Quality = status.Quality;
var solutionText = "No Fix";
if (status.Quality == 2) {
solutionText = "GPS + SBAS (WAAS / EGNOS)";
} else if (status.Quality == 1) {
solutionText = "3D GPS"
}
$scope.SolutionText = solutionText;
$scope.gps_accuracy = status.Accuracy.toFixed(1);
$scope.gps_vert_accuracy = (status.AccuracyVert*3.2808).toFixed(1); // accuracy is in meters, need to display in ft
// NACp should be an integer value in the range of 0 .. 11
// var accuracies = ["≥ 10 NM", "< 10 NM", "< 4 NM", "< 2 NM", "< 1 NM", "< 0.5 NM", "< 0.3 NM", "< 0.1 NM", "< 100 m", "< 30 m", "< 10 m", "< 3 m"];
// $scope.gps_accuracy = accuracies[status.NACp];
// "LastFixLocalTime":"2015-10-11T16:47:03.523085162Z"
$scope.gps_lat = status.Lat.toFixed(5); // result is string
$scope.gps_lon = status.Lng.toFixed(5); // result is string
$scope.gps_alt = Math.round(status.Alt);
$scope.gps_track = status.TrueCourse;
$scope.gps_speed = status.GroundSpeed;
$scope.gps_vert_speed = status.GPSVertVel.toFixed(1);
// "LastGroundTrackTime":"0001-01-01T00:00:00Z"
/* not currently used
$scope.ahrs_temp = status.Temp;
*/
$scope.ahrs_alt = Math.round(status.Pressure_alt);
$scope.ahrs_heading = Math.round(status.Gyro_heading);
// pitch and roll are in degrees
$scope.ahrs_pitch = Math.round(status.Pitch);
$scope.ahrs_roll = Math.round(status.Roll);
// "LastAttitudeTime":"2015-10-11T16:47:03.534615187Z"
setGeoReferenceMap(status.Lat, status.Lng);
// $scope.$apply();
}
function getStatus() {
// Simple GET request example (note: responce is asynchronous)
$http.get(URL_GPS_GET).
then(function (response) {
loadStatus(response.data);
ahrs.animate(0.1, $scope.ahrs_pitch, $scope.ahrs_roll, $scope.ahrs_heading);
// $scope.$apply();
}, function (response) {
$scope.raw_data = "error getting gps / ahrs status";
});
}
function getSatellites() {
// Simple GET request example (note: response is asynchronous)
$http.get(URL_SATELLITES_GET).
then(function (response) {
loadSatellites(response.data);
}, function (response) {
$scope.raw_data = "error getting satellite data";
});
}
function setSatellite(obj, new_satellite) {
new_satellite.SatelliteNMEA = obj.SatelliteNMEA;
new_satellite.SatelliteID = obj.SatelliteID; // Formatted code indicating source and PRN code. e.g. S138==WAAS satellite 138, G2==GPS satellites 2
new_satellite.Elevation = obj.Elevation; // Angle above local horizon, -xx to +90
new_satellite.Azimuth = obj.Azimuth; // Bearing (degrees true), 0-359
new_satellite.Signal = obj.Signal; // Signal strength, 0 - 99; -99 indicates no reception
new_satellite.InSolution = obj.InSolution; // is this satellite in the position solution
}
function loadSatellites(data) {
if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page
var satellites = data; // it seems the json was already converted to an object list by the http request
$scope.raw_data = angular.toJson(data, true);
$scope.data_list.length = 0; // clear array
// we need to use an array so AngularJS can perform sorting; it also means we need to loop to find a tower in the towers set
for (var key in satellites) {
//if (satellites[key].Messages_last_minute > 0) {
var new_satellite = {};
setSatellite(satellites[key], new_satellite);
$scope.data_list.push(new_satellite); // add to start of array
//}
}
// $scope.$apply();
}
var updateStatus = $interval(function () {
// refresh GPS/AHRS status once each 200 milliseconds (aka polling)
getStatus();
getSatellites();
}, (2 * 100), 0, false);
$state.get('gps').onEnter = function () {
// everything gets handled correctly by the controller
};
$state.get('gps').onExit = function () {
// stop polling for gps/ahrs status
$interval.cancel(updateStatus);
};
// GPS/AHRS Controller tasks go here
var ahrs = new ahrsRenderer("ahrs_display");
ahrs.init();
ahrs.orientation(0, 0, 90);
}
angular.module('appControllers').controller('GPSCtrl', GPSCtrl); // get the main module contollers set
GPSCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
// create our controller function with all necessary logic
function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.$parent.helppage = 'plates/gps-help.html';
$scope.data_list = [];
var status = {};
var display_area_size = -1;
function sizeMap() {
var width = 0;
var el = document.getElementById("map_display").parentElement;
width = el.offsetWidth; // was (- (2 * el.offsetLeft))
if (width !== display_area_size) {
display_area_size = width;
$scope.map_width = width;
$scope.map_height = width *0.5;
}
return width;
}
function setGeoReferenceMap(la, lo) {
// Mercator projection
// var map = "img/world.png";
var map_width = 2530;
var map_height = 1603;
var map_zero_x = 1192;
var map_zero_y = 1124;
var font_size = 18; // size of font used for marker
sizeMap();
var div_width = $scope.map_width;
var div_height = $scope.map_height;
// longitude: just scale and shift
var x = (map_width * (180 + lo) / 360) - (map_width/2 - map_zero_x); // longitude_shift;
// latitude: using the Mercator projection
la_rad = la * Math.PI / 180; // convert from degrees to radians
merc_n = Math.log(Math.tan((la_rad / 2) + (Math.PI / 4))); // do the Mercator projection (w/ equator of 2pi units)
var y = (map_height / 2) - (map_width * merc_n / (2 * Math.PI)) - (map_height/2 - map_zero_y); // fit it to our map
// dot = '<div style="position:absolute; width:' + dot_size + 'px; height:' + dot_size + 'px; top:' + y + 'px; left:' + x + 'px; background:#ff7f00;"></div>';
// <img src="map-world-medium.png" style="position:absolute;top:0px;left:0px">
$scope.map_pos_x = map_width - Math.round(x - (div_width / 2));
$scope.map_pos_y = map_height - Math.round(y - (div_height / 2));
$scope.map_mark_x = Math.round((div_width - (font_size * 0.85)) / 2);
$scope.map_mark_y = Math.round((div_height - font_size) / 2);
}
function loadStatus(data) { // mySituation
status = angular.fromJson(data);
// consider using angular.extend()
$scope.raw_data = angular.toJson(data, true); // makes it pretty
$scope.Satellites = status.Satellites;
$scope.GPS_satellites_tracked = status.SatellitesTracked;
$scope.GPS_satellites_seen = status.SatellitesSeen;
$scope.Quality = status.Quality;
var solutionText = "No Fix";
if (status.Quality == 2) {
solutionText = "GPS + SBAS (WAAS / EGNOS)";
} else if (status.Quality == 1) {
solutionText = "3D GPS"
}
$scope.SolutionText = solutionText;
$scope.gps_accuracy = status.Accuracy.toFixed(1);
$scope.gps_vert_accuracy = (status.AccuracyVert*3.2808).toFixed(1); // accuracy is in meters, need to display in ft
// NACp should be an integer value in the range of 0 .. 11
// var accuracies = ["≥ 10 NM", "< 10 NM", "< 4 NM", "< 2 NM", "< 1 NM", "< 0.5 NM", "< 0.3 NM", "< 0.1 NM", "< 100 m", "< 30 m", "< 10 m", "< 3 m"];
// $scope.gps_accuracy = accuracies[status.NACp];
// "LastFixLocalTime":"2015-10-11T16:47:03.523085162Z"
$scope.gps_lat = status.Lat.toFixed(5); // result is string
$scope.gps_lon = status.Lng.toFixed(5); // result is string
$scope.gps_alt = Math.round(status.Alt);
$scope.gps_track = status.TrueCourse;
$scope.gps_speed = status.GroundSpeed;
$scope.gps_vert_speed = status.GPSVertVel.toFixed(1);
// "LastGroundTrackTime":"0001-01-01T00:00:00Z"
/* not currently used
$scope.ahrs_temp = status.Temp;
*/
$scope.ahrs_alt = Math.round(status.Pressure_alt);
$scope.ahrs_heading = Math.round(status.Gyro_heading);
// pitch and roll are in degrees
$scope.ahrs_pitch = Math.round(status.Pitch);
$scope.ahrs_roll = Math.round(status.Roll);
// "LastAttitudeTime":"2015-10-11T16:47:03.534615187Z"
setGeoReferenceMap(status.Lat, status.Lng);
// $scope.$apply();
}
function getStatus() {
// Simple GET request example (note: responce is asynchronous)
$http.get(URL_GPS_GET).
then(function (response) {
loadStatus(response.data);
ahrs.animate(0.1, $scope.ahrs_pitch, $scope.ahrs_roll, $scope.ahrs_heading);
// $scope.$apply();
}, function (response) {
$scope.raw_data = "error getting gps / ahrs status";
});
}
function getSatellites() {
// Simple GET request example (note: response is asynchronous)
$http.get(URL_SATELLITES_GET).
then(function (response) {
loadSatellites(response.data);
}, function (response) {
$scope.raw_data = "error getting satellite data";
});
}
function setSatellite(obj, new_satellite) {
new_satellite.SatelliteNMEA = obj.SatelliteNMEA;
new_satellite.SatelliteID = obj.SatelliteID; // Formatted code indicating source and PRN code. e.g. S138==WAAS satellite 138, G2==GPS satellites 2
new_satellite.Elevation = obj.Elevation; // Angle above local horizon, -xx to +90
new_satellite.Azimuth = obj.Azimuth; // Bearing (degrees true), 0-359
new_satellite.Signal = obj.Signal; // Signal strength, 0 - 99; -99 indicates no reception
new_satellite.InSolution = obj.InSolution; // is this satellite in the position solution
}
function loadSatellites(data) {
if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page
var satellites = data; // it seems the json was already converted to an object list by the http request
$scope.raw_data = angular.toJson(data, true);
$scope.data_list.length = 0; // clear array
// we need to use an array so AngularJS can perform sorting; it also means we need to loop to find a tower in the towers set
for (var key in satellites) {
//if (satellites[key].Messages_last_minute > 0) {
var new_satellite = {};
setSatellite(satellites[key], new_satellite);
$scope.data_list.push(new_satellite); // add to start of array
//}
}
// $scope.$apply();
}
var updateStatus = $interval(function () {
// refresh GPS/AHRS status once each 200 milliseconds (aka polling)
getStatus();
getSatellites();
}, (2 * 100), 0, false);
$state.get('gps').onEnter = function () {
// everything gets handled correctly by the controller
};
$state.get('gps').onExit = function () {
// stop polling for gps/ahrs status
$interval.cancel(updateStatus);
};
// GPS/AHRS Controller tasks go here
var ahrs = new ahrsRenderer("ahrs_display");
ahrs.init();
ahrs.orientation(0, 0, 90);
}

Wyświetl plik

@ -1,11 +1,11 @@
angular.module('appControllers').controller('LogsCtrl', LogsCtrl); // get the main module contollers set
LogsCtrl.$inject = ['$scope', '$state', '$http']; // Inject my dependencies
// create our controller function with all necessary logic
function LogsCtrl($scope, $state, $http) {
$scope.$parent.helppage = 'plates/logs-help.html';
// just a couple environment variables that may bve useful for dev/debugging but otherwise not significant
$scope.userAgent = navigator.userAgent;
$scope.deviceViewport = 'screen = ' + window.screen.width + ' x ' + window.screen.height;
}
angular.module('appControllers').controller('LogsCtrl', LogsCtrl); // get the main module contollers set
LogsCtrl.$inject = ['$scope', '$state', '$http']; // Inject my dependencies
// create our controller function with all necessary logic
function LogsCtrl($scope, $state, $http) {
$scope.$parent.helppage = 'plates/logs-help.html';
// just a couple environment variables that may bve useful for dev/debugging but otherwise not significant
$scope.userAgent = navigator.userAgent;
$scope.deviceViewport = 'screen = ' + window.screen.width + ' x ' + window.screen.height;
}

Wyświetl plik

@ -1,201 +1,201 @@
angular.module('appControllers').controller('SettingsCtrl', SettingsCtrl); // get the main module contollers set
SettingsCtrl.$inject = ['$rootScope', '$scope', '$state', '$location', '$window', '$http']; // Inject my dependencies
// create our controller function with all necessary logic
function SettingsCtrl($rootScope, $scope, $state, $location, $window, $http) {
$scope.$parent.helppage = 'plates/settings-help.html';
var toggles = ['UAT_Enabled', 'ES_Enabled', 'Ping_Enabled', 'GPS_Enabled', 'Sensors_Enabled', 'DisplayTrafficSource', 'DEBUG', 'ReplayLog'];
var settings = {};
for (i = 0; i < toggles.length; i++) {
settings[toggles[i]] = undefined;
}
$scope.update_files = '';
function loadSettings(data) {
settings = angular.fromJson(data);
// consider using angular.extend()
$scope.rawSettings = angular.toJson(data, true);
$scope.visible_serialout = false;
if ((settings.SerialOutputs !== undefined) && (settings.SerialOutputs !== null) && (settings.SerialOutputs['/dev/serialout0'] !== undefined)) {
$scope.Baud = settings.SerialOutputs['/dev/serialout0'].Baud;
$scope.visible_serialout = true;
}
$scope.UAT_Enabled = settings.UAT_Enabled;
$scope.ES_Enabled = settings.ES_Enabled;
$scope.Ping_Enabled = settings.Ping_Enabled;
$scope.GPS_Enabled = settings.GPS_Enabled;
$scope.Sensors_Enabled = settings.Sensors_Enabled;
$scope.DisplayTrafficSource = settings.DisplayTrafficSource;
$scope.DEBUG = settings.DEBUG;
$scope.ReplayLog = settings.ReplayLog;
$scope.PPM = settings.PPM;
$scope.WatchList = settings.WatchList;
$scope.OwnshipModeS = settings.OwnshipModeS;
$scope.DeveloperMode = settings.DeveloperMode;
}
function getSettings() {
// Simple GET request example (note: responce is asynchronous)
$http.get(URL_SETTINGS_GET).
then(function (response) {
loadSettings(response.data);
// $scope.$apply();
}, function (response) {
$scope.rawSettings = "error getting settings";
for (i = 0; i < toggles.length; i++) {
settings[toggles[i]] = false;
}
});
};
function setSettings(msg) {
// Simple POST request example (note: responce is asynchronous)
$http.post(URL_SETTINGS_SET, msg).
then(function (response) {
loadSettings(response.data);
// $scope.$apply();
}, function (response) {
$scope.rawSettings = "error setting settings";
for (i = 0; i < toggles.length; i++) {
settings[toggles[i]] = false;
}
});
}
getSettings();
$scope.$watchGroup(toggles, function (newValues, oldValues, scope) {
var newsettings = {}
var dirty = false;
for (i = 0; i < newValues.length; i++) {
if ((newValues[i] !== undefined) && (settings[toggles[i]] !== undefined)) {
if (newValues[i] !== settings[toggles[i]]) {
settings[toggles[i]] = newValues[i];
newsettings[toggles[i]] = newValues[i];
dirty = true;
};
}
}
if (dirty) {
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
});
$scope.updateppm = function () {
settings["PPM"] = 0
if (($scope.PPM !== undefined) && ($scope.PPM !== null) && ($scope.PPM !== settings["PPM"])) {
settings["PPM"] = parseInt($scope.PPM);
newsettings = {
"PPM": settings["PPM"]
};
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
};
$scope.updateBaud = function () {
settings["Baud"] = 0
if (($scope.Baud !== undefined) && ($scope.Baud !== null) && ($scope.Baud !== settings["Baud"])) {
settings["Baud"] = parseInt($scope.Baud);
newsettings = {
"Baud": settings["Baud"]
};
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
};
$scope.updatewatchlist = function () {
if ($scope.WatchList !== settings["WatchList"]) {
settings["WatchList"] = "";
if ($scope.WatchList !== undefined) {
settings["WatchList"] = $scope.WatchList.toUpperCase();
}
newsettings = {
"WatchList": settings["WatchList"]
};
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
};
$scope.updatemodes = function () {
if ($scope.OwnshipModeS !== settings["OwnshipModeS"]) {
settings["OwnshipModeS"] = $scope.OwnshipModeS.toUpperCase();
newsettings = {
"OwnshipModeS": $scope.OwnshipModeS.toUpperCase()
};
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
};
$scope.postShutdown = function () {
$window.location.href = "/";
$location.path('/home');
$http.post(URL_SHUTDOWN).
then(function (response) {
// do nothing
// $scope.$apply();
}, function (response) {
// do nothing
});
};
$scope.postReboot = function () {
$window.location.href = "/";
$location.path('/home');
$http.post(URL_REBOOT).
then(function (response) {
// do nothing
// $scope.$apply();
}, function (response) {
// do nothing
});
};
$scope.setUploadFile = function (files) {
$scope.update_files = files;
$scope.$apply();
}
$scope.resetUploadFile = function () {
$scope.update_files = '';
$scope.$apply();
}
$scope.uploadFile = function () {
var fd = new FormData();
//Take the first selected file
var file = $scope.update_files[0];
// check for empty string
if (file === undefined || file === null) {
alert ("update file not selected")
return;
}
var filename = file.name;
// check for expected file naming convention
var re = /^update.*\.sh$/;
if (!re.exec(filename)) {
alert ("file does not appear to be an update")
return;
}
fd.append("update_file", file);
$http.post(URL_UPDATE_UPLOAD, fd, {
withCredentials: true,
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity
}).success(function (data) {
alert("success. wait 60 seconds and refresh home page to verify new version.");
window.location.replace("/");
}).error(function (data) {
alert("error");
});
};
};
angular.module('appControllers').controller('SettingsCtrl', SettingsCtrl); // get the main module contollers set
SettingsCtrl.$inject = ['$rootScope', '$scope', '$state', '$location', '$window', '$http']; // Inject my dependencies
// create our controller function with all necessary logic
function SettingsCtrl($rootScope, $scope, $state, $location, $window, $http) {
$scope.$parent.helppage = 'plates/settings-help.html';
var toggles = ['UAT_Enabled', 'ES_Enabled', 'Ping_Enabled', 'GPS_Enabled', 'Sensors_Enabled', 'DisplayTrafficSource', 'DEBUG', 'ReplayLog'];
var settings = {};
for (i = 0; i < toggles.length; i++) {
settings[toggles[i]] = undefined;
}
$scope.update_files = '';
function loadSettings(data) {
settings = angular.fromJson(data);
// consider using angular.extend()
$scope.rawSettings = angular.toJson(data, true);
$scope.visible_serialout = false;
if ((settings.SerialOutputs !== undefined) && (settings.SerialOutputs !== null) && (settings.SerialOutputs['/dev/serialout0'] !== undefined)) {
$scope.Baud = settings.SerialOutputs['/dev/serialout0'].Baud;
$scope.visible_serialout = true;
}
$scope.UAT_Enabled = settings.UAT_Enabled;
$scope.ES_Enabled = settings.ES_Enabled;
$scope.Ping_Enabled = settings.Ping_Enabled;
$scope.GPS_Enabled = settings.GPS_Enabled;
$scope.Sensors_Enabled = settings.Sensors_Enabled;
$scope.DisplayTrafficSource = settings.DisplayTrafficSource;
$scope.DEBUG = settings.DEBUG;
$scope.ReplayLog = settings.ReplayLog;
$scope.PPM = settings.PPM;
$scope.WatchList = settings.WatchList;
$scope.OwnshipModeS = settings.OwnshipModeS;
$scope.DeveloperMode = settings.DeveloperMode;
}
function getSettings() {
// Simple GET request example (note: responce is asynchronous)
$http.get(URL_SETTINGS_GET).
then(function (response) {
loadSettings(response.data);
// $scope.$apply();
}, function (response) {
$scope.rawSettings = "error getting settings";
for (i = 0; i < toggles.length; i++) {
settings[toggles[i]] = false;
}
});
};
function setSettings(msg) {
// Simple POST request example (note: responce is asynchronous)
$http.post(URL_SETTINGS_SET, msg).
then(function (response) {
loadSettings(response.data);
// $scope.$apply();
}, function (response) {
$scope.rawSettings = "error setting settings";
for (i = 0; i < toggles.length; i++) {
settings[toggles[i]] = false;
}
});
}
getSettings();
$scope.$watchGroup(toggles, function (newValues, oldValues, scope) {
var newsettings = {}
var dirty = false;
for (i = 0; i < newValues.length; i++) {
if ((newValues[i] !== undefined) && (settings[toggles[i]] !== undefined)) {
if (newValues[i] !== settings[toggles[i]]) {
settings[toggles[i]] = newValues[i];
newsettings[toggles[i]] = newValues[i];
dirty = true;
};
}
}
if (dirty) {
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
});
$scope.updateppm = function () {
settings["PPM"] = 0
if (($scope.PPM !== undefined) && ($scope.PPM !== null) && ($scope.PPM !== settings["PPM"])) {
settings["PPM"] = parseInt($scope.PPM);
newsettings = {
"PPM": settings["PPM"]
};
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
};
$scope.updateBaud = function () {
settings["Baud"] = 0
if (($scope.Baud !== undefined) && ($scope.Baud !== null) && ($scope.Baud !== settings["Baud"])) {
settings["Baud"] = parseInt($scope.Baud);
newsettings = {
"Baud": settings["Baud"]
};
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
};
$scope.updatewatchlist = function () {
if ($scope.WatchList !== settings["WatchList"]) {
settings["WatchList"] = "";
if ($scope.WatchList !== undefined) {
settings["WatchList"] = $scope.WatchList.toUpperCase();
}
newsettings = {
"WatchList": settings["WatchList"]
};
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
};
$scope.updatemodes = function () {
if ($scope.OwnshipModeS !== settings["OwnshipModeS"]) {
settings["OwnshipModeS"] = $scope.OwnshipModeS.toUpperCase();
newsettings = {
"OwnshipModeS": $scope.OwnshipModeS.toUpperCase()
};
// console.log(angular.toJson(newsettings));
setSettings(angular.toJson(newsettings));
}
};
$scope.postShutdown = function () {
$window.location.href = "/";
$location.path('/home');
$http.post(URL_SHUTDOWN).
then(function (response) {
// do nothing
// $scope.$apply();
}, function (response) {
// do nothing
});
};
$scope.postReboot = function () {
$window.location.href = "/";
$location.path('/home');
$http.post(URL_REBOOT).
then(function (response) {
// do nothing
// $scope.$apply();
}, function (response) {
// do nothing
});
};
$scope.setUploadFile = function (files) {
$scope.update_files = files;
$scope.$apply();
}
$scope.resetUploadFile = function () {
$scope.update_files = '';
$scope.$apply();
}
$scope.uploadFile = function () {
var fd = new FormData();
//Take the first selected file
var file = $scope.update_files[0];
// check for empty string
if (file === undefined || file === null) {
alert ("update file not selected")
return;
}
var filename = file.name;
// check for expected file naming convention
var re = /^update.*\.sh$/;
if (!re.exec(filename)) {
alert ("file does not appear to be an update")
return;
}
fd.append("update_file", file);
$http.post(URL_UPDATE_UPLOAD, fd, {
withCredentials: true,
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity
}).success(function (data) {
alert("success. wait 60 seconds and refresh home page to verify new version.");
window.location.replace("/");
}).error(function (data) {
alert("error");
});
};
};

Wyświetl plik

@ -1,241 +1,241 @@
angular.module('appControllers').controller('TrafficCtrl', TrafficCtrl); // get the main module contollers set
TrafficCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
// create our controller function with all necessary logic
function TrafficCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.$parent.helppage = 'plates/traffic-help.html';
$scope.data_list = [];
$scope.data_list_invalid = [];
function utcTimeString(epoc) {
var time = "";
var val;
var d = new Date(epoc);
val = d.getUTCHours();
time += (val < 10 ? "0" + val : "" + val);
val = d.getUTCMinutes();
time += ":" + (val < 10 ? "0" + val : "" + val);
val = d.getUTCSeconds();
time += ":" + (val < 10 ? "0" + val : "" + val);
time += "Z";
return time;
}
/*
function dmsString(val) {
return [0 | val,
'° ',
0 | (val < 0 ? val = -val : val) % 1 * 60,
"' ",
0 | val * 60 % 1 * 60,
'"'].join('');
}
*/
// chop off seconds for space
function dmsString(val) {
var deg;
var min;
deg = 0 | val;
min = 0 | (val < 0 ? val = -val : val) % 1 * 60;
return [deg*deg < 100 ? "0" + deg : deg,
'° ',
min < 10 ? "0" + min : min,
"' "].join('');
}
function setAircraft(obj, new_traffic) {
new_traffic.icao_int = obj.Icao_addr;
new_traffic.targettype = obj.TargetType;
new_traffic.signal = obj.SignalLevel;
new_traffic.addr_symb ='\u2708';
if (new_traffic.targettype > 3) {
new_traffic.addr_symb ='\ud83d\udce1';
}
new_traffic.icao = obj.Icao_addr.toString(16).toUpperCase();
new_traffic.tail = obj.Tail;
new_traffic.reg = obj.Reg;
if (obj.Squawk == 0) {
new_traffic.squawk = "----";
} else {
new_traffic.squawk = obj.Squawk;
}
new_traffic.addr_type = obj.Addr_type;
new_traffic.lat = dmsString(obj.Lat);
new_traffic.lon = dmsString(obj.Lng);
var n = Math.round(obj.Alt / 25) * 25;
new_traffic.alt = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
var s = Math.round(obj.Speed / 5) * 5;
if (obj.Speed_valid) {
new_traffic.speed = s.toString();
new_traffic.heading = Math.round(obj.Track / 5) * 5;
} else {
new_traffic.speed = "---";
new_traffic.heading = "---";
}
new_traffic.vspeed = Math.round(obj.Vvel / 100) * 100
var timestamp = Date.parse(obj.Timestamp);
new_traffic.time = utcTimeString(timestamp);
new_traffic.age = obj.Age;
new_traffic.ageLastAlt = obj.AgeLastAlt;
new_traffic.src = obj.Last_source; // 1=ES, 2=UAT
new_traffic.bearing = Math.round(obj.Bearing); // degrees true
new_traffic.dist = (obj.Distance/1852); // nautical miles
// return new_aircraft;
}
function connect($scope) {
if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page
if (($scope.socket === undefined) || ($scope.socket === null)) {
socket = new WebSocket(URL_TRAFFIC_WS);
$scope.socket = socket; // store socket in scope for enter/exit usage
}
$scope.ConnectState = "Disconnected";
socket.onopen = function (msg) {
// $scope.ConnectStyle = "label-success";
$scope.ConnectState = "Connected";
};
socket.onclose = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Disconnected";
$scope.$apply();
setTimeout(connect, 1000);
};
socket.onerror = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Problem";
$scope.$apply();
};
socket.onmessage = function (msg) {
console.log('Received traffic update.')
var message = JSON.parse(msg.data);
$scope.raw_data = angular.toJson(msg.data, true);
// we need to use an array so AngularJS can perform sorting; it also means we need to loop to find an aircraft in the traffic set
var validIdx = -1;
var invalidIdx = -1;
for (var i = 0, len = $scope.data_list.length; i < len; i++) {
if ($scope.data_list[i].icao_int === message.Icao_addr) {
setAircraft(message, $scope.data_list[i]);
validIdx = i;
break;
}
}
for (var i = 0, len = $scope.data_list_invalid.length; i < len; i++) {
if ($scope.data_list_invalid[i].icao_int === message.Icao_addr) {
setAircraft(message, $scope.data_list_invalid[i]);
invalidIdx = i;
break;
}
}
if ((validIdx < 0) && (message.Position_valid)) {
var new_traffic = {};
setAircraft(message, new_traffic);
$scope.data_list.unshift(new_traffic); // add to start of valid array.
}
if ((invalidIdx < 0) && (!message.Position_valid)) {
var new_traffic = {};
setAircraft(message, new_traffic);
$scope.data_list_invalid.unshift(new_traffic); // add to start of invalid array.
}
// Handle the negative cases of those above - where an aircraft moves from "valid" to "invalid" or vice-versa.
if ((validIdx >= 0) && !message.Position_valid) {
// Position is not valid any more. Remove from "valid" table.
$scope.data_list.splice(validIdx, 1);
}
if ((invalidIdx >= 0) && message.Position_valid) {
// Position is now valid. Remove from "invalid" table.
$scope.data_list_invalid.splice(invalidIdx, 1);
}
$scope.$apply();
};
}
var getClock = $interval(function () {
$http.get(URL_STATUS_GET).
then(function (response) {
globalStatus = angular.fromJson(response.data);
var tempClock = new Date(Date.parse(globalStatus.Clock));
var clockString = tempClock.toUTCString();
$scope.Clock = clockString;
var tempUptimeClock = new Date(Date.parse(globalStatus.UptimeClock));
var uptimeClockString = tempUptimeClock.toUTCString();
$scope.UptimeClock = uptimeClockString;
var tempLocalClock = new Date;
$scope.LocalClock = tempLocalClock.toUTCString();
$scope.SecondsFast = (tempClock-tempLocalClock)/1000;
$scope.GPS_connected = globalStatus.GPS_connected;
}, function (response) {
// nop
});
}, 500, 0, false);
// perform cleanup every 10 seconds
var clearStaleTraffic = $interval(function () {
// remove stale aircraft = anything more than 59 seconds without a position update
var cutoff = 59;
// Clean up "valid position" table.
for (var i = $scope.data_list.length; i > 0; i--) {
if ($scope.data_list[i - 1].age >= cutoff) {
$scope.data_list.splice(i - 1, 1);
}
}
// Clean up "invalid position" table.
for (var i = $scope.data_list_invalid.length; i > 0; i--) {
if (($scope.data_list_invalid[i - 1].age >= cutoff) || ($scope.data_list_invalid[i - 1].ageLastAlt >= cutoff)) {
$scope.data_list_invalid.splice(i - 1, 1);
}
}
}, (1000 * 10), 0, false);
$state.get('traffic').onEnter = function () {
// everything gets handled correctly by the controller
};
$state.get('traffic').onExit = function () {
// disconnect from the socket
if (($scope.socket !== undefined) && ($scope.socket !== null)) {
$scope.socket.close();
$scope.socket = null;
}
// stop stale traffic cleanup
$interval.cancel(clearStaleTraffic);
};
// Traffic Controller tasks
connect($scope); // connect - opens a socket and listens for messages
angular.module('appControllers').controller('TrafficCtrl', TrafficCtrl); // get the main module contollers set
TrafficCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
// create our controller function with all necessary logic
function TrafficCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.$parent.helppage = 'plates/traffic-help.html';
$scope.data_list = [];
$scope.data_list_invalid = [];
function utcTimeString(epoc) {
var time = "";
var val;
var d = new Date(epoc);
val = d.getUTCHours();
time += (val < 10 ? "0" + val : "" + val);
val = d.getUTCMinutes();
time += ":" + (val < 10 ? "0" + val : "" + val);
val = d.getUTCSeconds();
time += ":" + (val < 10 ? "0" + val : "" + val);
time += "Z";
return time;
}
/*
function dmsString(val) {
return [0 | val,
'° ',
0 | (val < 0 ? val = -val : val) % 1 * 60,
"' ",
0 | val * 60 % 1 * 60,
'"'].join('');
}
*/
// chop off seconds for space
function dmsString(val) {
var deg;
var min;
deg = 0 | val;
min = 0 | (val < 0 ? val = -val : val) % 1 * 60;
return [deg*deg < 100 ? "0" + deg : deg,
'° ',
min < 10 ? "0" + min : min,
"' "].join('');
}
function setAircraft(obj, new_traffic) {
new_traffic.icao_int = obj.Icao_addr;
new_traffic.targettype = obj.TargetType;
new_traffic.signal = obj.SignalLevel;
new_traffic.addr_symb ='\u2708';
if (new_traffic.targettype > 3) {
new_traffic.addr_symb ='\ud83d\udce1';
}
new_traffic.icao = obj.Icao_addr.toString(16).toUpperCase();
new_traffic.tail = obj.Tail;
new_traffic.reg = obj.Reg;
if (obj.Squawk == 0) {
new_traffic.squawk = "----";
} else {
new_traffic.squawk = obj.Squawk;
}
new_traffic.addr_type = obj.Addr_type;
new_traffic.lat = dmsString(obj.Lat);
new_traffic.lon = dmsString(obj.Lng);
var n = Math.round(obj.Alt / 25) * 25;
new_traffic.alt = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
var s = Math.round(obj.Speed / 5) * 5;
if (obj.Speed_valid) {
new_traffic.speed = s.toString();
new_traffic.heading = Math.round(obj.Track / 5) * 5;
} else {
new_traffic.speed = "---";
new_traffic.heading = "---";
}
new_traffic.vspeed = Math.round(obj.Vvel / 100) * 100
var timestamp = Date.parse(obj.Timestamp);
new_traffic.time = utcTimeString(timestamp);
new_traffic.age = obj.Age;
new_traffic.ageLastAlt = obj.AgeLastAlt;
new_traffic.src = obj.Last_source; // 1=ES, 2=UAT
new_traffic.bearing = Math.round(obj.Bearing); // degrees true
new_traffic.dist = (obj.Distance/1852); // nautical miles
// return new_aircraft;
}
function connect($scope) {
if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page
if (($scope.socket === undefined) || ($scope.socket === null)) {
socket = new WebSocket(URL_TRAFFIC_WS);
$scope.socket = socket; // store socket in scope for enter/exit usage
}
$scope.ConnectState = "Disconnected";
socket.onopen = function (msg) {
// $scope.ConnectStyle = "label-success";
$scope.ConnectState = "Connected";
};
socket.onclose = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Disconnected";
$scope.$apply();
setTimeout(connect, 1000);
};
socket.onerror = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Problem";
$scope.$apply();
};
socket.onmessage = function (msg) {
console.log('Received traffic update.')
var message = JSON.parse(msg.data);
$scope.raw_data = angular.toJson(msg.data, true);
// we need to use an array so AngularJS can perform sorting; it also means we need to loop to find an aircraft in the traffic set
var validIdx = -1;
var invalidIdx = -1;
for (var i = 0, len = $scope.data_list.length; i < len; i++) {
if ($scope.data_list[i].icao_int === message.Icao_addr) {
setAircraft(message, $scope.data_list[i]);
validIdx = i;
break;
}
}
for (var i = 0, len = $scope.data_list_invalid.length; i < len; i++) {
if ($scope.data_list_invalid[i].icao_int === message.Icao_addr) {
setAircraft(message, $scope.data_list_invalid[i]);
invalidIdx = i;
break;
}
}
if ((validIdx < 0) && (message.Position_valid)) {
var new_traffic = {};
setAircraft(message, new_traffic);
$scope.data_list.unshift(new_traffic); // add to start of valid array.
}
if ((invalidIdx < 0) && (!message.Position_valid)) {
var new_traffic = {};
setAircraft(message, new_traffic);
$scope.data_list_invalid.unshift(new_traffic); // add to start of invalid array.
}
// Handle the negative cases of those above - where an aircraft moves from "valid" to "invalid" or vice-versa.
if ((validIdx >= 0) && !message.Position_valid) {
// Position is not valid any more. Remove from "valid" table.
$scope.data_list.splice(validIdx, 1);
}
if ((invalidIdx >= 0) && message.Position_valid) {
// Position is now valid. Remove from "invalid" table.
$scope.data_list_invalid.splice(invalidIdx, 1);
}
$scope.$apply();
};
}
var getClock = $interval(function () {
$http.get(URL_STATUS_GET).
then(function (response) {
globalStatus = angular.fromJson(response.data);
var tempClock = new Date(Date.parse(globalStatus.Clock));
var clockString = tempClock.toUTCString();
$scope.Clock = clockString;
var tempUptimeClock = new Date(Date.parse(globalStatus.UptimeClock));
var uptimeClockString = tempUptimeClock.toUTCString();
$scope.UptimeClock = uptimeClockString;
var tempLocalClock = new Date;
$scope.LocalClock = tempLocalClock.toUTCString();
$scope.SecondsFast = (tempClock-tempLocalClock)/1000;
$scope.GPS_connected = globalStatus.GPS_connected;
}, function (response) {
// nop
});
}, 500, 0, false);
// perform cleanup every 10 seconds
var clearStaleTraffic = $interval(function () {
// remove stale aircraft = anything more than 59 seconds without a position update
var cutoff = 59;
// Clean up "valid position" table.
for (var i = $scope.data_list.length; i > 0; i--) {
if ($scope.data_list[i - 1].age >= cutoff) {
$scope.data_list.splice(i - 1, 1);
}
}
// Clean up "invalid position" table.
for (var i = $scope.data_list_invalid.length; i > 0; i--) {
if (($scope.data_list_invalid[i - 1].age >= cutoff) || ($scope.data_list_invalid[i - 1].ageLastAlt >= cutoff)) {
$scope.data_list_invalid.splice(i - 1, 1);
}
}
}, (1000 * 10), 0, false);
$state.get('traffic').onEnter = function () {
// everything gets handled correctly by the controller
};
$state.get('traffic').onExit = function () {
// disconnect from the socket
if (($scope.socket !== undefined) && ($scope.socket !== null)) {
$scope.socket.close();
$scope.socket = null;
}
// stop stale traffic cleanup
$interval.cancel(clearStaleTraffic);
};
// Traffic Controller tasks
connect($scope); // connect - opens a socket and listens for messages
};

Wyświetl plik

@ -1,261 +1,261 @@
angular.module('appControllers').controller('WeatherCtrl', WeatherCtrl); // get the main module contollers set
WeatherCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
// create our controller function with all necessary logic
function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
var CONF_WATCHLIST = "KBOS KATL KORD KLAX"; // we default to 4 major airports
var MAX_DATALIST = 10;
$scope.$parent.helppage = 'plates/weather-help.html';
$scope.data_list = [];
$scope.watch_list = [];
$scope.data_count = 0;
$scope.watch_count = 0;
function updateWatchList() {
$scope.watching = CONF_WATCHLIST;
// Simple GET request example (note: responce is asynchronous)
$http.get(URL_SETTINGS_GET).
then(function (response) {
settings = angular.fromJson(response.data);
$scope.watching = settings.WatchList.toUpperCase();
}, function (response) {
// nop
});
};
function inList(word, sentence) {
// since the watch list is just one long string, we cheat and see if the word in anywhere in the 'sentence'
if ((sentence) && (word)) {
return sentence.includes(word);
}
return false;
}
function parseFlightCondition(msg, body) {
if ((msg !== "METAR") && (msg !== "SPECI"))
return "";
// check the visibility: a value preceeding 'SM' which is either a fraction or a whole number
// we don't care what value of fraction since anything below 1SM is LIFR
// BTW: now I know why no one wants to parse METARs - ther can be spaces in the numbers ARGH
// test for special case of 'X X/X'
var exp = new RegExp("([0-9]) ([0-9])/([0-9])SM");
var match = exp.exec(body);
if ((match !== null) && (match.length === 4)) {
visability = parseInt(match[1]) + (parseInt(match[2]) / parseInt(match[3]));
} else {
exp = new RegExp("([0-9/]{1,5}?)SM");
match = exp.exec(body);
if (match === null)
return "";
// the only way we have 3 or more characters is if the '/' is present which means we need to do extra checking
if (match[1].length === 3)
return "LIFR";
// do we have a usable visability distance
var visability = parseInt(match[1]);
if (visability === 0)
return "";
}
// ceiling is at either the BKN or OVC layer
exp = new RegExp("BKN([0-9]{3})");
match = exp.exec(body);
if (match === null) {
exp = new RegExp("OVC([0-9]{3})");
match = exp.exec(body);
}
var ceiling = 999;
if (match !== null)
ceiling = parseInt(match[1]);
if ((visability > 5) && (ceiling > 30))
return "VFR";
if ((visability >= 3) && (ceiling >= 10))
return "MVFR";
if ((visability >= 1) && (ceiling >= 5))
return "IFR";
return "LIFR";
}
function deltaTimeString(epoc) {
var time = "";
var val;
var d = new Date(epoc);
val = d.getUTCDate() - 1; // we got here by subtrracting two dates so we have a delta, not a day of month
if (val > 0)
time += (val < 10 ? "0" + val : "" + val) + "d ";
val = d.getUTCHours();
if (val > 0) {
time += (val < 10 ? "0" + val : "" + val) + "h ";
} else {
if (time.length > 0)
time += "00h ";
}
val = d.getUTCMinutes();
time += (val < 10 ? "0" + val : "" + val) + "m ";
// ADS-B weather is only accurate to minutes
// val = d.getUTCSeconds();
// time += (val < 10 ? "0" + val : "" + val) + "s";
return time;
}
function parseShortDatetime(sdt) {
var d = new Date();
var s = String(sdt);
if (s.length < 7)
return 0;
d.setUTCDate(parseInt(s.substring(0, 2)));
d.setUTCHours(parseInt(s.substring(2, 4)));
if (s.length > 7) { // TAF datetime range
d.setUTCMinutes(0);
} else {
d.setUTCMinutes(parseInt(s.substring(4, 6)));
}
d.setUTCSeconds(0);
d.setUTCMilliseconds(0);
return d;
}
function setDataItem(obj, data_item) {
if (obj.Type === "TAF.AMD") {
data_item.type = "TAF";
data_item.update = true;
} else {
data_item.type = obj.Type;
data_item.update = false;
}
data_item.flight_condition = parseFlightCondition(obj.Type, obj.Data);
data_item.location = obj.Location;
s = obj.Time;
// data_item.time = s.substring(0, 2) + '-' + s.substring(2, 4) + ':' + s.substring(4, 6) + 'Z';
// we may not get an accurate base time on the stratux device so we use the device time as our base
// var dNow = new Date(obj.LocaltimeReceived);
var dNow = new Date();
var dThen = parseShortDatetime(obj.Time);
data_item.age = dThen.getTime();
var diff_ms = Math.abs(dThen - dNow);
// If time is more than two days away, don't attempt to display data age.
if (diff_ms > (1000*60*60*24*2)) {
data_item.time = "?";
} else if (dThen > dNow) {
data_item.time = deltaTimeString(dThen - dNow) + " from now";
} else {
data_item.time = deltaTimeString(dNow - dThen) + " old";
}
// data_item.received = utcTimeString(obj.LocaltimeReceived);
data_item.data = obj.Data;
}
function connect($scope) {
if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page
if (($scope.socket === undefined) || ($scope.socket === null)) {
socket = new WebSocket(URL_WEATHER_WS);
$scope.socket = socket; // store socket in scope for enter/exit usage
}
$scope.ConnectState = "Disconnected";
socket.onopen = function (msg) {
// $scope.ConnectStyle = "label-success";
$scope.ConnectState = "Connected";
};
socket.onclose = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Disconnected";
$scope.$apply();
setTimeout(connect, 1000);
};
socket.onerror = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Problem";
$scope.$apply();
};
socket.onmessage = function (msg) {
console.log('Received data_list update.');
$scope.raw_data = angular.toJson(msg.data, true);
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)) {
setDataItem(message, $scope.watch_list[i]);
found = true;
break;
}
}
if (!found) {
var new_data_item = {};
setDataItem(message, new_data_item);
$scope.watch_list.unshift(new_data_item); // add to start of array
}
}
// add to scrolling data_list
{
var new_data_item = {};
setDataItem(message, new_data_item);
$scope.data_list.unshift(new_data_item); // add to start of array
if ($scope.data_list.length > MAX_DATALIST)
$scope.data_list.pop(); // remove last from array
}
$scope.data_count = $scope.data_list.length;
$scope.watch_count = $scope.watch_list.length;
$scope.$apply();
};
}
// perform cleanup every 5 minutes
var clearStaleMessages = $interval(function () {
// remove stale data = anything more than 30 minutes old
var dirty = false;
var cutoff = Date.now() - (30 * 60 * 1000);
for (var i = len = $scope.watch_list.length; i > 0; i--) {
if ($scope.watch_list[i - 1].age < cutoff) {
$scope.watch_list.splice(i - 1, 1);
dirty = true;
}
}
if (dirty) {
$scope.raw_data = "";
$scope.$apply();
}
}, (5 * 60 * 1000), 0, false);
$state.get('weather').onEnter = function () {
// everything gets handled correctly by the controller
updateWatchList();
};
$state.get('weather').onExit = function () {
// disconnect from the socket
if (($scope.socket !== undefined) && ($scope.socket !== null)) {
$scope.socket.close();
$scope.socket = null;
}
// stop stale message cleanup
$interval.cancel(clearStaleMessages);
};
// Weather Controller tasks
updateWatchList();
connect($scope); // connect - opens a socket and listens for messages
angular.module('appControllers').controller('WeatherCtrl', WeatherCtrl); // get the main module contollers set
WeatherCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
// create our controller function with all necessary logic
function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
var CONF_WATCHLIST = "KBOS KATL KORD KLAX"; // we default to 4 major airports
var MAX_DATALIST = 10;
$scope.$parent.helppage = 'plates/weather-help.html';
$scope.data_list = [];
$scope.watch_list = [];
$scope.data_count = 0;
$scope.watch_count = 0;
function updateWatchList() {
$scope.watching = CONF_WATCHLIST;
// Simple GET request example (note: responce is asynchronous)
$http.get(URL_SETTINGS_GET).
then(function (response) {
settings = angular.fromJson(response.data);
$scope.watching = settings.WatchList.toUpperCase();
}, function (response) {
// nop
});
};
function inList(word, sentence) {
// since the watch list is just one long string, we cheat and see if the word in anywhere in the 'sentence'
if ((sentence) && (word)) {
return sentence.includes(word);
}
return false;
}
function parseFlightCondition(msg, body) {
if ((msg !== "METAR") && (msg !== "SPECI"))
return "";
// check the visibility: a value preceeding 'SM' which is either a fraction or a whole number
// we don't care what value of fraction since anything below 1SM is LIFR
// BTW: now I know why no one wants to parse METARs - ther can be spaces in the numbers ARGH
// test for special case of 'X X/X'
var exp = new RegExp("([0-9]) ([0-9])/([0-9])SM");
var match = exp.exec(body);
if ((match !== null) && (match.length === 4)) {
visability = parseInt(match[1]) + (parseInt(match[2]) / parseInt(match[3]));
} else {
exp = new RegExp("([0-9/]{1,5}?)SM");
match = exp.exec(body);
if (match === null)
return "";
// the only way we have 3 or more characters is if the '/' is present which means we need to do extra checking
if (match[1].length === 3)
return "LIFR";
// do we have a usable visability distance
var visability = parseInt(match[1]);
if (visability === 0)
return "";
}
// ceiling is at either the BKN or OVC layer
exp = new RegExp("BKN([0-9]{3})");
match = exp.exec(body);
if (match === null) {
exp = new RegExp("OVC([0-9]{3})");
match = exp.exec(body);
}
var ceiling = 999;
if (match !== null)
ceiling = parseInt(match[1]);
if ((visability > 5) && (ceiling > 30))
return "VFR";
if ((visability >= 3) && (ceiling >= 10))
return "MVFR";
if ((visability >= 1) && (ceiling >= 5))
return "IFR";
return "LIFR";
}
function deltaTimeString(epoc) {
var time = "";
var val;
var d = new Date(epoc);
val = d.getUTCDate() - 1; // we got here by subtrracting two dates so we have a delta, not a day of month
if (val > 0)
time += (val < 10 ? "0" + val : "" + val) + "d ";
val = d.getUTCHours();
if (val > 0) {
time += (val < 10 ? "0" + val : "" + val) + "h ";
} else {
if (time.length > 0)
time += "00h ";
}
val = d.getUTCMinutes();
time += (val < 10 ? "0" + val : "" + val) + "m ";
// ADS-B weather is only accurate to minutes
// val = d.getUTCSeconds();
// time += (val < 10 ? "0" + val : "" + val) + "s";
return time;
}
function parseShortDatetime(sdt) {
var d = new Date();
var s = String(sdt);
if (s.length < 7)
return 0;
d.setUTCDate(parseInt(s.substring(0, 2)));
d.setUTCHours(parseInt(s.substring(2, 4)));
if (s.length > 7) { // TAF datetime range
d.setUTCMinutes(0);
} else {
d.setUTCMinutes(parseInt(s.substring(4, 6)));
}
d.setUTCSeconds(0);
d.setUTCMilliseconds(0);
return d;
}
function setDataItem(obj, data_item) {
if (obj.Type === "TAF.AMD") {
data_item.type = "TAF";
data_item.update = true;
} else {
data_item.type = obj.Type;
data_item.update = false;
}
data_item.flight_condition = parseFlightCondition(obj.Type, obj.Data);
data_item.location = obj.Location;
s = obj.Time;
// data_item.time = s.substring(0, 2) + '-' + s.substring(2, 4) + ':' + s.substring(4, 6) + 'Z';
// we may not get an accurate base time on the stratux device so we use the device time as our base
// var dNow = new Date(obj.LocaltimeReceived);
var dNow = new Date();
var dThen = parseShortDatetime(obj.Time);
data_item.age = dThen.getTime();
var diff_ms = Math.abs(dThen - dNow);
// If time is more than two days away, don't attempt to display data age.
if (diff_ms > (1000*60*60*24*2)) {
data_item.time = "?";
} else if (dThen > dNow) {
data_item.time = deltaTimeString(dThen - dNow) + " from now";
} else {
data_item.time = deltaTimeString(dNow - dThen) + " old";
}
// data_item.received = utcTimeString(obj.LocaltimeReceived);
data_item.data = obj.Data;
}
function connect($scope) {
if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page
if (($scope.socket === undefined) || ($scope.socket === null)) {
socket = new WebSocket(URL_WEATHER_WS);
$scope.socket = socket; // store socket in scope for enter/exit usage
}
$scope.ConnectState = "Disconnected";
socket.onopen = function (msg) {
// $scope.ConnectStyle = "label-success";
$scope.ConnectState = "Connected";
};
socket.onclose = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Disconnected";
$scope.$apply();
setTimeout(connect, 1000);
};
socket.onerror = function (msg) {
// $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Problem";
$scope.$apply();
};
socket.onmessage = function (msg) {
console.log('Received data_list update.');
$scope.raw_data = angular.toJson(msg.data, true);
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)) {
setDataItem(message, $scope.watch_list[i]);
found = true;
break;
}
}
if (!found) {
var new_data_item = {};
setDataItem(message, new_data_item);
$scope.watch_list.unshift(new_data_item); // add to start of array
}
}
// add to scrolling data_list
{
var new_data_item = {};
setDataItem(message, new_data_item);
$scope.data_list.unshift(new_data_item); // add to start of array
if ($scope.data_list.length > MAX_DATALIST)
$scope.data_list.pop(); // remove last from array
}
$scope.data_count = $scope.data_list.length;
$scope.watch_count = $scope.watch_list.length;
$scope.$apply();
};
}
// perform cleanup every 5 minutes
var clearStaleMessages = $interval(function () {
// remove stale data = anything more than 30 minutes old
var dirty = false;
var cutoff = Date.now() - (30 * 60 * 1000);
for (var i = len = $scope.watch_list.length; i > 0; i--) {
if ($scope.watch_list[i - 1].age < cutoff) {
$scope.watch_list.splice(i - 1, 1);
dirty = true;
}
}
if (dirty) {
$scope.raw_data = "";
$scope.$apply();
}
}, (5 * 60 * 1000), 0, false);
$state.get('weather').onEnter = function () {
// everything gets handled correctly by the controller
updateWatchList();
};
$state.get('weather').onExit = function () {
// disconnect from the socket
if (($scope.socket !== undefined) && ($scope.socket !== null)) {
$scope.socket.close();
$scope.socket = null;
}
// stop stale message cleanup
$interval.cancel(clearStaleMessages);
};
// Weather Controller tasks
updateWatchList();
connect($scope); // connect - opens a socket and listens for messages
};

Wyświetl plik

@ -1,23 +1,23 @@
<div class="list-group text-center">
<div class="list-group-item list-group-item-home">
<h2>Logs</h2>
</div>
<div class="list-group-item list-group-item-home">
<div>
<i class="fa fa-cloud feature-icon text-primary"></i>
</div>
<div>
<a target="_blank" href="../logs/stratux.log">stratux.log</a>
</div>
<div>
<a target="_blank" href="../view_logs/">SDR, AHRS, and GPS logs</a>
</div>
<div>
(Enable device logging on "Settings" page)
</div>
</div>
</div>
<div class="col-sm-6">
<pre>{{userAgent}}</pre>
<pre>{{deviceViewport}}</pre>
</div>
<div class="list-group text-center">
<div class="list-group-item list-group-item-home">
<h2>Logs</h2>
</div>
<div class="list-group-item list-group-item-home">
<div>
<i class="fa fa-cloud feature-icon text-primary"></i>
</div>
<div>
<a target="_blank" href="../logs/stratux.log">stratux.log</a>
</div>
<div>
<a target="_blank" href="../view_logs/">SDR, AHRS, and GPS logs</a>
</div>
<div>
(Enable device logging on "Settings" page)
</div>
</div>
</div>
<div class="col-sm-6">
<pre>{{userAgent}}</pre>
<pre>{{deviceViewport}}</pre>
</div>

Wyświetl plik

@ -1,33 +1,33 @@
<div class="section text-left help-page">
<p>The <strong>Settings</strong> page provides both control and configuration of your Stratux device.</p>
<p>Use the toggles in the <strong>Hardware</strong> section to control which devices are active.</p>
<p class="text-warning">NOTE: Only hardware toggled on here, will appear on the
<stron>Status</stron> page.</p>
<p>The <strong>Diagnostics</strong> section helps with debugging and communicating with the Stratux project contributors via GitHub and the reddit subgroup.
<ul class="list-simple">
<li>Toggling <strong>Traffic Source</strong> adds text for traffic targets within your navigation application. Traffic received via UAT will display <code>u</code> while traffic received via 1090 will display <code>e</code>.</li>
<li>Toggling <strong>Record Logs</strong> enables logging to a series of files for your Stratux device including data recorded for UAT traffic and weather, 1090 traffic, GPS messages, and AHRS messages. The log files are accessible from the <strong>Logs</strong> menu available on the left.</li>
</ul>
<p>The <strong>Configuration</strong> section lets you adjust the default operation of your Stratux device.</p>
<ul class="list-simple">
<li>To avoid having your own aircraft appear as traffic, and scare the bejeezus our of you, you may provide your <strong>Mode S code</strong>. You can find this value in the FAA N-Number Registry for your aircraft. You should use the hexadecimal value (not the octal value) for this setting. No validation is done so please ensure you enter your valide Mode S value.
</li>
<li>The <strong>Weather</strong> page uses a user-defined <strong>Watch List</strong> to filter the large volume of ADS-B weather messages for display. Define a list of identifiers (airport, VOR, etc) separated by a spaces. For example <code>KBOS EEN LAH LKP</code>. You may change this list at any time and the <strong>Weather</strong> page will start watching for the updated list immediately.
<br/>
<span class="text-warning">NOTE: To save your changes, you must either tap somehwere else on the page or hit <code>ENTER</code> or <code>RETURN</code> or <code>GO</code> (or whatever your keyboard indicates).</span>
</li>
<li>The SDR (software defined radio) receiver support an adjustment in the form of a <strong>PPM Correction</strong>. From the Raspberry Pi, you may use the command <code>kal -g 48 -s GSM850</code> to scan for available channels in your area. Then use the command <code>kal -g 48 -c <em>channel#</em></code> to calculate the PPM.
<br/>
<span class="text-warning">NOTE: You will need to perform all commands as <code>root</code> by issuing the command: <code>sudo su -</code>. You will need to stop the Stratux software before running the calibration process. You can stop all of the Stratux processes with the command: <code>pkill screen</code>.</span>
</li>
<li>Addiitonal settings will be added in future releases.</li>
</ul>
<p>The <strong>System</strong> section lets you safely shutdown or reboot your Stratux device.</p>
<ul>
<li><strong>Shutdown</strong> will immediately shutdown the Stratux. You may then safely remove power.</li>
<li><strong>Reboot</strong> will immediately reboot the Stratux. After the reboot you may have to rejoin the WiFi connection to reconnect.</li>
</ul>
<div class="section text-left help-page">
<p>The <strong>Settings</strong> page provides both control and configuration of your Stratux device.</p>
<p>Use the toggles in the <strong>Hardware</strong> section to control which devices are active.</p>
<p class="text-warning">NOTE: Only hardware toggled on here, will appear on the
<stron>Status</stron> page.</p>
<p>The <strong>Diagnostics</strong> section helps with debugging and communicating with the Stratux project contributors via GitHub and the reddit subgroup.
<ul class="list-simple">
<li>Toggling <strong>Traffic Source</strong> adds text for traffic targets within your navigation application. Traffic received via UAT will display <code>u</code> while traffic received via 1090 will display <code>e</code>.</li>
<li>Toggling <strong>Record Logs</strong> enables logging to a series of files for your Stratux device including data recorded for UAT traffic and weather, 1090 traffic, GPS messages, and AHRS messages. The log files are accessible from the <strong>Logs</strong> menu available on the left.</li>
</ul>
<p>The <strong>Configuration</strong> section lets you adjust the default operation of your Stratux device.</p>
<ul class="list-simple">
<li>To avoid having your own aircraft appear as traffic, and scare the bejeezus our of you, you may provide your <strong>Mode S code</strong>. You can find this value in the FAA N-Number Registry for your aircraft. You should use the hexadecimal value (not the octal value) for this setting. No validation is done so please ensure you enter your valide Mode S value.
</li>
<li>The <strong>Weather</strong> page uses a user-defined <strong>Watch List</strong> to filter the large volume of ADS-B weather messages for display. Define a list of identifiers (airport, VOR, etc) separated by a spaces. For example <code>KBOS EEN LAH LKP</code>. You may change this list at any time and the <strong>Weather</strong> page will start watching for the updated list immediately.
<br/>
<span class="text-warning">NOTE: To save your changes, you must either tap somehwere else on the page or hit <code>ENTER</code> or <code>RETURN</code> or <code>GO</code> (or whatever your keyboard indicates).</span>
</li>
<li>The SDR (software defined radio) receiver support an adjustment in the form of a <strong>PPM Correction</strong>. From the Raspberry Pi, you may use the command <code>kal -g 48 -s GSM850</code> to scan for available channels in your area. Then use the command <code>kal -g 48 -c <em>channel#</em></code> to calculate the PPM.
<br/>
<span class="text-warning">NOTE: You will need to perform all commands as <code>root</code> by issuing the command: <code>sudo su -</code>. You will need to stop the Stratux software before running the calibration process. You can stop all of the Stratux processes with the command: <code>pkill screen</code>.</span>
</li>
<li>Addiitonal settings will be added in future releases.</li>
</ul>
<p>The <strong>System</strong> section lets you safely shutdown or reboot your Stratux device.</p>
<ul>
<li><strong>Shutdown</strong> will immediately shutdown the Stratux. You may then safely remove power.</li>
<li><strong>Reboot</strong> will immediately reboot the Stratux. After the reboot you may have to rejoin the WiFi connection to reconnect.</li>
</ul>
</div>

Wyświetl plik

@ -1,13 +1,13 @@
<div class="section text-left help-page">
<p>The <strong>Status</strong> page provides an overview of your Stratux device.</p>
<p>The current state of you device is shown at the top - <code>Connected</code> in green or <code>Disconected</code>in red.</p>
<p>Depending on the hardware you have installed in your Stratux, status messages will be shown for the following:</p>
<ul class="list-simple">
<li><strong>Messages</strong> is the number of messages received by the UAT (978 MHz) and 1090 MHz radios. "Current" is the 60-second rolling total for each receiver; "Peak" is the maximum 60-second total. The 1090 total includes all 1090 MHz Mode S messages received, including all-call and TCAS interrogations that do not carry ADS-B position information. If a UAT radio is receiving uplinks from one or more ground-based transceivers (GBT), this will be indicated under <strong>UAT Towers</strong>, with more details available on the Towers page.</li>
<li><strong>GPS</strong> indicates the connection status of any attached GPS receivers. Reported data includes the type of position solution, the number of satellites used in that solution, the number of satellites being received, and the number of satellites tracked in the GPS almanac data. Position and accuracy details can be viewed on the <strong>GPS/AHRS</strong> page.</li>
</ul>
<p class="text-warning">Devices must be manually enabled on the <strong>Settings</strong> page.</p>
<p>Additional statistics include the number of detected software-defined radios (SDRs), number of current DHCP network clients, uptime, temperature of the Raspberry Pi CPU, and the current clock settings on both the Raspberry Pi and the device / browser used to view this page.</p>
<div class="section text-left help-page">
<p>The <strong>Status</strong> page provides an overview of your Stratux device.</p>
<p>The current state of you device is shown at the top - <code>Connected</code> in green or <code>Disconected</code>in red.</p>
<p>Depending on the hardware you have installed in your Stratux, status messages will be shown for the following:</p>
<ul class="list-simple">
<li><strong>Messages</strong> is the number of messages received by the UAT (978 MHz) and 1090 MHz radios. "Current" is the 60-second rolling total for each receiver; "Peak" is the maximum 60-second total. The 1090 total includes all 1090 MHz Mode S messages received, including all-call and TCAS interrogations that do not carry ADS-B position information. If a UAT radio is receiving uplinks from one or more ground-based transceivers (GBT), this will be indicated under <strong>UAT Towers</strong>, with more details available on the Towers page.</li>
<li><strong>GPS</strong> indicates the connection status of any attached GPS receivers. Reported data includes the type of position solution, the number of satellites used in that solution, the number of satellites being received, and the number of satellites tracked in the GPS almanac data. Position and accuracy details can be viewed on the <strong>GPS/AHRS</strong> page.</li>
</ul>
<p class="text-warning">Devices must be manually enabled on the <strong>Settings</strong> page.</p>
<p>Additional statistics include the number of detected software-defined radios (SDRs), number of current DHCP network clients, uptime, temperature of the Raspberry Pi CPU, and the current clock settings on both the Raspberry Pi and the device / browser used to view this page.</p>
</div>

Wyświetl plik

@ -1,148 +1,148 @@
<div class="col-sm-12">
<div class="text-center">
<a ng-click="VersionClick()" class="btn btn-hidden"<strong>Version: <span>{{Version}} ({{Build}})</span></strong></a>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Status</span>
<span ng-show="ConnectState == 'Connected'" class="label label-success">{{ConnectState}}</span>
<span ng-hide="ConnectState == 'Connected'" class="label label-danger">{{ConnectState}}</span>
<span ng-show="DeveloperMode == true" class="label label-warning">Developer Mode</span>
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="row">
<div class="col-sm-6 label_adj">
<strong class="col-xs-5">Recent Clients:</strong>
<span class="col-xs-7">{{Connected_Users}}</span>
</div>
</div>
<div class="row">
<div class="col-sm-6 label_adj">
<strong class="col-xs-5">SDR devices:</strong>
<span class="col-xs-7">{{Devices}}</span>
</div>
<div class="col-sm-6 label_adj" ng-class="{'section_invisible': !visible_ping}">
<strong class="col-xs-5">Ping device:</strong>
<span ng-show="Ping_connected == true" class="label label-success">Connected</span>
<span ng-hide="Ping_connected == true" class="label label-danger">Disconnected</span>
</div>
</div>
<div class="separator"></div>
<div class="row">
<label class="col-xs-4">Messages</label>
<label class="col-xs-6">Current</label>
<label class="col-xs-2 text-right">Peak</label>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<span class="col-xs-1"></span>
<label class="col-xs-3">UAT:</label>
<span class="col-xs-6"><div class="bar_container"><div class="bar_display traffic-style2" ng-attr-style="width:{{UAT_messages_max ? 100*UAT_messages_last_minute / UAT_messages_max : 0}}%">{{UAT_messages_last_minute}}</div></div></span>
<span class="col-xs-2 text-right">{{UAT_messages_max}}</span>
</div>
<div class="row" ng-class="{'section_invisible': !visible_es}">
<span class="col-xs-1"></span>
<label class="col-xs-3">1090ES:</label>
<span class="col-xs-6"><div class="bar_container"><div class="bar_display traffic-style1" ng-attr-style="width:{{ES_messages_max ? 100*ES_messages_last_minute / ES_messages_max : 0}}%;">{{ES_messages_last_minute}}</div></div></span>
<span class="col-xs-2 text-right">{{ES_messages_max}}</span>
</div>
<!--
<div id="uat_products" style="display: none;">
<div class="row"><span class="col-xs-1">&nbsp;</span></div>
<div class="row">
<label class="col-xs-6">UAT Products</label>
<label class="col-xs-3 text-right">Last Minute</label>
<label class="col-xs-3"></label>
</div>
<div>{{product_rows}}</div>
</div>
-->
<div class="row" ng-class="{ 'section_invisible': (!visible_gps && !visible_uat)}">
<span class="col-xs-1">&nbsp;</span>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<label class="col-xs-6">UAT Towers:</label>
<span class="col-xs-6">{{UAT_Towers}}</span>
</div>
<div class="row" ng-class="{'section_invisible': !visible_gps}">
<label class="col-xs-6">GPS solution:</label>
<span class="col-xs-6">{{GPS_solution}}{{GPS_position_accuracy}}</span>
</div>
<div class="row" ng-class="{'section_invisible': !visible_gps}">
<label class="col-xs-6">GPS satellites:</label>
<span class="col-xs-6">{{GPS_satellites_locked}} in solution; {{GPS_satellites_seen}} seen; {{GPS_satellites_tracked}} tracked</span>
</div>
<div class="row"><span class="col-xs-1">&nbsp;</span></div>
<div class="separator"></div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-6">
<span><strong>UAT Statistics</strong></span>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-12">
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">METARS</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">TAFS</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">NEXRAD</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">PIREP</span>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-12">
<span align="center" class="col-xs-3">{{UAT_METAR_total}}</span>
<span align="center" class="col-xs-3">{{UAT_TAF_total}}</span>
<span align="center" class="col-xs-3">{{UAT_NEXRAD_total}}</span>
<span align="center" class="col-xs-3">{{UAT_PIREP_total}}</span>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-12">
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">SIGMET</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">NOTAMS</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">Other</span>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-12">
<span align="center" class="col-xs-3">{{UAT_SIGMET_total}}</span>
<span align="center" class="col-xs-3">{{UAT_NOTAM_total}}</span>
<span align="center" class="col-xs-3">{{UAT_OTHER_total}}</span>
</div>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="separator"></div>
<div class="row"><span class="col-xs-1">&nbsp;</span></div>
<div class="separator"></div>
<div class="row">
<div class="col-sm-4 label_adj">
<span class="col-xs-5"><strong>Uptime:</strong></span>
<span class="col-xs-7">{{Uptime}}</span>
</div>
<div class="col-sm-4 label_adj">
<span class="col-xs-5"><strong>CPU Temp:</strong></span>
<span class="col-xs-7">{{CPUTemp}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" ng-class="{'section_invisible': !visible_errors}">
<span class="panel_label">Errors</span>
</div>
<div class="panel-body" ng-class="{'section_invisible': !visible_errors}">
<ul>
<li class="status-error" ng-repeat="err in Errors">
<span class="fa fa-exclamation-triangle icon-red"></span> <span class="icon-red">{{err}}</span>
</li>
</ul>
</div>
</div>
</div>
<div class="col-sm-12">
<div class="text-center">
<a ng-click="VersionClick()" class="btn btn-hidden"<strong>Version: <span>{{Version}} ({{Build}})</span></strong></a>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Status</span>
<span ng-show="ConnectState == 'Connected'" class="label label-success">{{ConnectState}}</span>
<span ng-hide="ConnectState == 'Connected'" class="label label-danger">{{ConnectState}}</span>
<span ng-show="DeveloperMode == true" class="label label-warning">Developer Mode</span>
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="row">
<div class="col-sm-6 label_adj">
<strong class="col-xs-5">Recent Clients:</strong>
<span class="col-xs-7">{{Connected_Users}}</span>
</div>
</div>
<div class="row">
<div class="col-sm-6 label_adj">
<strong class="col-xs-5">SDR devices:</strong>
<span class="col-xs-7">{{Devices}}</span>
</div>
<div class="col-sm-6 label_adj" ng-class="{'section_invisible': !visible_ping}">
<strong class="col-xs-5">Ping device:</strong>
<span ng-show="Ping_connected == true" class="label label-success">Connected</span>
<span ng-hide="Ping_connected == true" class="label label-danger">Disconnected</span>
</div>
</div>
<div class="separator"></div>
<div class="row">
<label class="col-xs-4">Messages</label>
<label class="col-xs-6">Current</label>
<label class="col-xs-2 text-right">Peak</label>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<span class="col-xs-1"></span>
<label class="col-xs-3">UAT:</label>
<span class="col-xs-6"><div class="bar_container"><div class="bar_display traffic-style2" ng-attr-style="width:{{UAT_messages_max ? 100*UAT_messages_last_minute / UAT_messages_max : 0}}%">{{UAT_messages_last_minute}}</div></div></span>
<span class="col-xs-2 text-right">{{UAT_messages_max}}</span>
</div>
<div class="row" ng-class="{'section_invisible': !visible_es}">
<span class="col-xs-1"></span>
<label class="col-xs-3">1090ES:</label>
<span class="col-xs-6"><div class="bar_container"><div class="bar_display traffic-style1" ng-attr-style="width:{{ES_messages_max ? 100*ES_messages_last_minute / ES_messages_max : 0}}%;">{{ES_messages_last_minute}}</div></div></span>
<span class="col-xs-2 text-right">{{ES_messages_max}}</span>
</div>
<!--
<div id="uat_products" style="display: none;">
<div class="row"><span class="col-xs-1">&nbsp;</span></div>
<div class="row">
<label class="col-xs-6">UAT Products</label>
<label class="col-xs-3 text-right">Last Minute</label>
<label class="col-xs-3"></label>
</div>
<div>{{product_rows}}</div>
</div>
-->
<div class="row" ng-class="{ 'section_invisible': (!visible_gps && !visible_uat)}">
<span class="col-xs-1">&nbsp;</span>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<label class="col-xs-6">UAT Towers:</label>
<span class="col-xs-6">{{UAT_Towers}}</span>
</div>
<div class="row" ng-class="{'section_invisible': !visible_gps}">
<label class="col-xs-6">GPS solution:</label>
<span class="col-xs-6">{{GPS_solution}}{{GPS_position_accuracy}}</span>
</div>
<div class="row" ng-class="{'section_invisible': !visible_gps}">
<label class="col-xs-6">GPS satellites:</label>
<span class="col-xs-6">{{GPS_satellites_locked}} in solution; {{GPS_satellites_seen}} seen; {{GPS_satellites_tracked}} tracked</span>
</div>
<div class="row"><span class="col-xs-1">&nbsp;</span></div>
<div class="separator"></div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-6">
<span><strong>UAT Statistics</strong></span>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-12">
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">METARS</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">TAFS</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">NEXRAD</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">PIREP</span>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-12">
<span align="center" class="col-xs-3">{{UAT_METAR_total}}</span>
<span align="center" class="col-xs-3">{{UAT_TAF_total}}</span>
<span align="center" class="col-xs-3">{{UAT_NEXRAD_total}}</span>
<span align="center" class="col-xs-3">{{UAT_PIREP_total}}</span>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-12">
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">SIGMET</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">NOTAMS</span>
<span align="center" style="background-color: #f7f7f7" class="col-xs-3">Other</span>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="col-sm-12">
<span align="center" class="col-xs-3">{{UAT_SIGMET_total}}</span>
<span align="center" class="col-xs-3">{{UAT_NOTAM_total}}</span>
<span align="center" class="col-xs-3">{{UAT_OTHER_total}}</span>
</div>
</div>
</div>
<div class="row" ng-class="{'section_invisible': !visible_uat}">
<div class="separator"></div>
<div class="row"><span class="col-xs-1">&nbsp;</span></div>
<div class="separator"></div>
<div class="row">
<div class="col-sm-4 label_adj">
<span class="col-xs-5"><strong>Uptime:</strong></span>
<span class="col-xs-7">{{Uptime}}</span>
</div>
<div class="col-sm-4 label_adj">
<span class="col-xs-5"><strong>CPU Temp:</strong></span>
<span class="col-xs-7">{{CPUTemp}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" ng-class="{'section_invisible': !visible_errors}">
<span class="panel_label">Errors</span>
</div>
<div class="panel-body" ng-class="{'section_invisible': !visible_errors}">
<ul>
<li class="status-error" ng-repeat="err in Errors">
<span class="fa fa-exclamation-triangle icon-red"></span> <span class="icon-red">{{err}}</span>
</li>
</ul>
</div>
</div>
</div>

Wyświetl plik

@ -1,25 +1,25 @@
<div class="section text-left help-page">
<p>The <strong>Traffic</strong> page provides a list of all aircraft position reports received within the last 60 seconds. Each time a new aircraft is detected, it is added to the list. Each time a new report is received for an existing aircraft, the list is updated. If a valid position for an aircraft has not been received within the last 60 seconds, the aircraft is removed from the list.</p>
<p>For each aircraft, the list includes the following details:</p>
<ul>
<li><strong>Callsign</strong> is the aircraft callsign or tail number. Unknown callsigns will be shown as <span class="label traffic-style11">[--N/A--]</span>. Color and symbol indicates traffic source:</li>
<ul class="list-simple">
<li><span class="label traffic-style11">&#x2708; ADSB1090</span> 1090 MHz air-to-air ADS-B traffic is displayed with a medium blue background and airplane symbol.</li>
<li><span class="label traffic-style12">&#x2708; ADSR1090</span> 1090 MHz ground-to-air ADS-R rebroadcasts are displayed with a light cyan background and airplane symbol.</li>
<li><span class="label traffic-style14">&#x1f4e1; TISB1090</span> 1090 MHZ TIS-B traffic is displayed with a light cyan background and antenna symbol.</li>
<li><span class="label traffic-style21">&#x2708; ADSB978</span> 978 MHz air-to-air ADS-B traffic is displayed with a light tan background and airplane symbol.</li>
<li><span class="label traffic-style22">&#x2708; ADSR978</span> 978 MHz ground-to-air ADS-R rebroadcasts are displayed with a gold background and airplane symbol.</li>
<li><span class="label traffic-style24">&#x1f4e1; TISB978</span> 978 MHz TIS-B traffic is displayed with a gold background and antenna symbol.</li>
</ul>
<li><strong>Code</strong> is the ICAO 24-bit code (ADS-B/ADS-R targets), 24-bit FAA-assigned track file ID (TIS-B), or Mode C squawk code, if <strong>Show Squawk</strong> is enabled, and if a squawk code has been received for that target.</li>
<li><strong>Location</strong> - Reported latitude and longitude, DD° mm'.</li>
<li><strong>Dist</strong> - Calculated distance to target in nautical miles. Requires GPS position and <strong>Show Distance</strong> slider to be enabled.</li>
<li><strong>Bearing</strong> - Calculated bearing to target in degrees true. Requires GPS position and <strong>Show Distance</strong> slider to be enabled.</li>
<li><strong>Altitude</strong> - Reported pressure altitude, feet MSL. Climb or descent rate is also shown if not in level flight.</li>
<li><strong>Speed</strong> - Reported ground speed, rounded to the nearest 5 knots. Invalid or missing values are shown as '---'.</li>
<li><strong>Course</strong> - Reported true course, rounded to the nearest 5°. Invalid or missing values are shown as '---'</li>
<li><strong>Power</strong> - Signal strength in dB. The maximum signal is about +1.4 dB. For typical unamplified SDRs, the minimum detection threshold is about -35 dB for altitude reports, and -30 dB for position reports.</li>
<li><strong>Age</strong> - Age of the last position report, seconds.</li>
</ul>
<p>Additionally, if <strong>1090 MHz</strong> is enabled on the <strong>Settings</strong> page, most users will see reports from aircraft in the <strong>Basic Mode S and No-Position Messages</strong> table. These are targets that do not transmitting ADS-B position. Instead, Stratux is picking up altitude, squawk code, and occasionally velocity reports from non-ADS-B Mode S reports. These include air-to-air TCAS messages and radar interrogations, and typically make up the majority of all 1090 messages received.</p>
<div class="section text-left help-page">
<p>The <strong>Traffic</strong> page provides a list of all aircraft position reports received within the last 60 seconds. Each time a new aircraft is detected, it is added to the list. Each time a new report is received for an existing aircraft, the list is updated. If a valid position for an aircraft has not been received within the last 60 seconds, the aircraft is removed from the list.</p>
<p>For each aircraft, the list includes the following details:</p>
<ul>
<li><strong>Callsign</strong> is the aircraft callsign or tail number. Unknown callsigns will be shown as <span class="label traffic-style11">[--N/A--]</span>. Color and symbol indicates traffic source:</li>
<ul class="list-simple">
<li><span class="label traffic-style11">&#x2708; ADSB1090</span> 1090 MHz air-to-air ADS-B traffic is displayed with a medium blue background and airplane symbol.</li>
<li><span class="label traffic-style12">&#x2708; ADSR1090</span> 1090 MHz ground-to-air ADS-R rebroadcasts are displayed with a light cyan background and airplane symbol.</li>
<li><span class="label traffic-style14">&#x1f4e1; TISB1090</span> 1090 MHZ TIS-B traffic is displayed with a light cyan background and antenna symbol.</li>
<li><span class="label traffic-style21">&#x2708; ADSB978</span> 978 MHz air-to-air ADS-B traffic is displayed with a light tan background and airplane symbol.</li>
<li><span class="label traffic-style22">&#x2708; ADSR978</span> 978 MHz ground-to-air ADS-R rebroadcasts are displayed with a gold background and airplane symbol.</li>
<li><span class="label traffic-style24">&#x1f4e1; TISB978</span> 978 MHz TIS-B traffic is displayed with a gold background and antenna symbol.</li>
</ul>
<li><strong>Code</strong> is the ICAO 24-bit code (ADS-B/ADS-R targets), 24-bit FAA-assigned track file ID (TIS-B), or Mode C squawk code, if <strong>Show Squawk</strong> is enabled, and if a squawk code has been received for that target.</li>
<li><strong>Location</strong> - Reported latitude and longitude, DD° mm'.</li>
<li><strong>Dist</strong> - Calculated distance to target in nautical miles. Requires GPS position and <strong>Show Distance</strong> slider to be enabled.</li>
<li><strong>Bearing</strong> - Calculated bearing to target in degrees true. Requires GPS position and <strong>Show Distance</strong> slider to be enabled.</li>
<li><strong>Altitude</strong> - Reported pressure altitude, feet MSL. Climb or descent rate is also shown if not in level flight.</li>
<li><strong>Speed</strong> - Reported ground speed, rounded to the nearest 5 knots. Invalid or missing values are shown as '---'.</li>
<li><strong>Course</strong> - Reported true course, rounded to the nearest 5°. Invalid or missing values are shown as '---'</li>
<li><strong>Power</strong> - Signal strength in dB. The maximum signal is about +1.4 dB. For typical unamplified SDRs, the minimum detection threshold is about -35 dB for altitude reports, and -30 dB for position reports.</li>
<li><strong>Age</strong> - Age of the last position report, seconds.</li>
</ul>
<p>Additionally, if <strong>1090 MHz</strong> is enabled on the <strong>Settings</strong> page, most users will see reports from aircraft in the <strong>Basic Mode S and No-Position Messages</strong> table. These are targets that do not transmitting ADS-B position. Instead, Stratux is picking up altitude, squawk code, and occasionally velocity reports from non-ADS-B Mode S reports. These include air-to-air TCAS messages and radar interrogations, and typically make up the majority of all 1090 messages received.</p>
</div>

Wyświetl plik

@ -1,161 +1,161 @@
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">ADS-B and TIS-B Traffic</span>
<span ng-show="ConnectState == 'Connected'" class="label label-success">{{ConnectState}}</span>
<span ng-hide="ConnectState == 'Connected'" class="label label-danger">{{ConnectState}}</span>
</div>
<div class="panel-body traffic-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-3" ng-hide="showReg"><strong>Callsign</strong></span>
<span class="col-xs-3" ng-show="showReg"><strong>Tail Num</strong></span>
<span class="col-xs-2" ng-hide="showSquawk"><strong>Code</strong></span>
<span class="col-xs-2" ng-show="showSquawk"><strong>Squawk</strong></span>
<span class="col-xs-5 text-right" ng-hide="GPS_connected && RelDist"><strong>Location</strong></span>
<span class="col-xs-3 text-right" ng-show="GPS_connected && RelDist"><strong>Dist</strong></span>
<span class="col-xs-2 text-right" ng-show="GPS_connected && RelDist"><strong>Bearing</strong></span>
</div>
<div class="col-sm-6">
<span class="col-xs-3 text-right"><strong>Altitude</strong></span><span class="col-xs-1">&nbsp;</span>
<span class="col-xs-2 text-right"><strong>Speed</strong></span>
<span class="col-xs-2 text-right"><strong>Course</strong></span>
<span class="col-xs-2 text-right"><strong>Power</strong></span>
<span class="col-xs-2 text-right"><strong>Age</strong></span>
</div>
</div>
<div class="row" ng-repeat="aircraft in data_list | orderBy: 'dist'">
<div class="separator"></div>
<div class="col-sm-6">
<span class="col-xs-3" ng-hide="showReg">
<span ng-show="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.tail}}</strong></span>
<span ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-3" ng-show="showReg">
<span ng-show="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.reg}}</strong></span>
<span ng-hide="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-2">
<span style="font-size:80%" ng-hide="showSquawk">{{aircraft.icao}}<span style="font-size:50%">{{aircraft.addr_type == 3 ? "&nbsp;(TFID)" : ""}}</span></span>
<span ng-show="showSquawk"><span ng-show="aircraft.squawk < 1000">0</span><span ng-show="aircraft.squawk < 100">0</span><span ng-show="aircraft.squawk < 10">0</span>{{aircraft.squawk}}</span>
</span>
<span class="col-xs-5 text-right" ng-hide="GPS_connected && RelDist">{{aircraft.lat}} {{aircraft.lon}}</span>
<span class="col-xs-3 text-right" ng-show="GPS_connected && RelDist">{{aircraft.dist.toFixed(1)}}<span style="font-size:50%">NM</span></span>
<span class="col-xs-2 text-right" ng-show="GPS_connected && RelDist">{{aircraft.bearing}}&deg;</span>
</div>
<div class="col-sm-6">
<span class="col-xs-3 text-right">{{aircraft.alt}}</span>
<span class="col-xs-1 small col-padding-shift-right text-muted">
<span ng-show="aircraft.vspeed > 0"><span class="fa fa-ascent"></span>{{aircraft.vspeed}}</span>
<span ng-show="aircraft.vspeed < 0"><span class="fa fa-descent"></span>{{0-aircraft.vspeed}}</span>
</span>
<span class="col-xs-2 text-right">{{aircraft.speed}}<span style="font-size:50%">KTS</span></span>
<span class="col-xs-2 text-right"><span ng-show="aircraft.heading < 10">0</span><span ng-show="aircraft.heading < 100">0</span>{{aircraft.heading}}&deg;</span>
<span class="col-xs-2 text-right">{{aircraft.signal.toFixed(2)}}<span style="font-size:50%">dB</span></span>
<span class="col-xs-2 text-right">{{aircraft.age.toFixed(1)}}<span style="font-size:50%">s</span></span>
</div>
</div>
</div>
<div class="panel-body traffic-footer">
<div class="separator"></div>
<div class="row">
<div class="col-sm-4">
<label class="control-label col-xs-6">Show Tail Number</label>
<span class="col-xs-3"><ui-switch ng-model='showReg' settings-change></ui-switch></span>
</div>
<div class="col-sm-4">
<label class="control-label col-xs-6">Show Squawk</label>
<span class="col-xs-3"><ui-switch ng-model='showSquawk' settings-change></ui-switch></span>
</div>
<div class="col-sm-4">
<label class="control-label col-xs-6" ng-show="GPS_connected">Show Distance</label>
<label class="control-label text-muted col-xs-6" ng-hide="GPS_connected">Show Distance N/A</label>
<span class="col-xs-3"><ui-switch ng-model='RelDist' settings-change></ui-switch></span>
</div>
<!--
<div class="col-sm-4">
<label class="control-label col-xs-6">GPS Status</label>
<span ng-show="GPS_connected" class="label label-success col-xs-3" style="font-size:100%; display:block; height: 34px; line-height: 34px">Valid</span>
<span ng-hide="GPS_connected" class="label label-danger col-xs-3" style="font-size:100%; display:block; height: 34px; line-height: 34px">No Fix</span>
</div>
-->
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Basic Mode S and No-Position Messages</span>
</div>
<div class="panel-body traffic-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-4" ng-hide="showReg"><strong>Callsign</strong></span>
<span class="col-xs-4" ng-show="showReg"><strong>Tail Num</strong></span>
<span class="col-xs-3"><strong>Code</strong></span>
<span class="col-xs-3"><strong>Squawk</strong></span>
</div>
<div class="col-sm-6">
<span class="col-xs-3 text-right"><strong>Altitude</strong></span><span class="col-xs-1">&nbsp;</span>
<span class="col-xs-2 text-right"><strong>Speed</strong></span>
<span class="col-xs-2 text-right"><strong>Course</strong></span>
<span class="col-xs-2 text-right"><strong>Power</strong></span>
<span class="col-xs-2 text-right"><strong>Age</strong></span>
</div>
</div>
<div class="row" ng-repeat="aircraft in data_list_invalid | orderBy: 'icao'">
<div class="separator"></div>
<div class="col-sm-6">
<span class="col-xs-4" ng-hide="showReg">
<span ng-show="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.tail}}</strong></span>
<span ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-4" ng-show="showReg">
<span ng-show="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.reg}}</strong></span>
<span ng-hide="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-3" style="font-size:80%">{{aircraft.icao}}<span style="font-size:50%">{{aircraft.addr_type == 3 ? "&nbsp;(TFID)" : ""}}</span></span>
<span class="col-xs-3"><span ng-show="aircraft.squawk < 1000">0</span><span ng-show="aircraft.squawk < 100">0</span><span ng-show="aircraft.squawk < 10">0</span>{{aircraft.squawk}}</span>
</div>
<div class="col-sm-6">
<span class="col-xs-3 text-right">{{aircraft.alt}}</span>
<span class="col-xs-1 small col-padding-shift-right text-muted">
<span ng-show="aircraft.vspeed > 0"><span class="fa fa-ascent"></span>{{aircraft.vspeed}}</span>
<span ng-show="aircraft.vspeed < 0"><span class="fa fa-descent"></span>{{0-aircraft.vspeed}}</span>
</span>
<span class="col-xs-2 text-right">{{aircraft.speed}}<span style="font-size:50%">KTS</span></span>
<span class="col-xs-2 text-right"><span ng-show="aircraft.heading < 10">0</span><span ng-show="aircraft.heading < 100">0</span>{{aircraft.heading}}&deg;</span>
<span class="col-xs-2 text-right">{{aircraft.signal.toFixed(2)}}<span style="font-size:50%">dB</span></span>
<span class="col-xs-2 text-right">{{aircraft.ageLastAlt.toFixed(1)}}<span style="font-size:50%">s</span></span>
</div>
</div>
</div>
<div class="panel-body traffic-footer">
<div class="separator"></div>
<span class ="col-sm-12 small">Stratux has not received valid ADS-B position transmissions from the aircraft in this section. They will not appear on your EFB map. See help page for details.</span>
</div>
</div>
</div>
<!--
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">Raw Traffic Data</div>
<div class="panel-body">
<pre>{{raw_data}}</pre>
</div>
</div>
</div>
-->
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">ADS-B and TIS-B Traffic</span>
<span ng-show="ConnectState == 'Connected'" class="label label-success">{{ConnectState}}</span>
<span ng-hide="ConnectState == 'Connected'" class="label label-danger">{{ConnectState}}</span>
</div>
<div class="panel-body traffic-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-3" ng-hide="showReg"><strong>Callsign</strong></span>
<span class="col-xs-3" ng-show="showReg"><strong>Tail Num</strong></span>
<span class="col-xs-2" ng-hide="showSquawk"><strong>Code</strong></span>
<span class="col-xs-2" ng-show="showSquawk"><strong>Squawk</strong></span>
<span class="col-xs-5 text-right" ng-hide="GPS_connected && RelDist"><strong>Location</strong></span>
<span class="col-xs-3 text-right" ng-show="GPS_connected && RelDist"><strong>Dist</strong></span>
<span class="col-xs-2 text-right" ng-show="GPS_connected && RelDist"><strong>Bearing</strong></span>
</div>
<div class="col-sm-6">
<span class="col-xs-3 text-right"><strong>Altitude</strong></span><span class="col-xs-1">&nbsp;</span>
<span class="col-xs-2 text-right"><strong>Speed</strong></span>
<span class="col-xs-2 text-right"><strong>Course</strong></span>
<span class="col-xs-2 text-right"><strong>Power</strong></span>
<span class="col-xs-2 text-right"><strong>Age</strong></span>
</div>
</div>
<div class="row" ng-repeat="aircraft in data_list | orderBy: 'dist'">
<div class="separator"></div>
<div class="col-sm-6">
<span class="col-xs-3" ng-hide="showReg">
<span ng-show="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.tail}}</strong></span>
<span ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-3" ng-show="showReg">
<span ng-show="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.reg}}</strong></span>
<span ng-hide="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-2">
<span style="font-size:80%" ng-hide="showSquawk">{{aircraft.icao}}<span style="font-size:50%">{{aircraft.addr_type == 3 ? "&nbsp;(TFID)" : ""}}</span></span>
<span ng-show="showSquawk"><span ng-show="aircraft.squawk < 1000">0</span><span ng-show="aircraft.squawk < 100">0</span><span ng-show="aircraft.squawk < 10">0</span>{{aircraft.squawk}}</span>
</span>
<span class="col-xs-5 text-right" ng-hide="GPS_connected && RelDist">{{aircraft.lat}} {{aircraft.lon}}</span>
<span class="col-xs-3 text-right" ng-show="GPS_connected && RelDist">{{aircraft.dist.toFixed(1)}}<span style="font-size:50%">NM</span></span>
<span class="col-xs-2 text-right" ng-show="GPS_connected && RelDist">{{aircraft.bearing}}&deg;</span>
</div>
<div class="col-sm-6">
<span class="col-xs-3 text-right">{{aircraft.alt}}</span>
<span class="col-xs-1 small col-padding-shift-right text-muted">
<span ng-show="aircraft.vspeed > 0"><span class="fa fa-ascent"></span>{{aircraft.vspeed}}</span>
<span ng-show="aircraft.vspeed < 0"><span class="fa fa-descent"></span>{{0-aircraft.vspeed}}</span>
</span>
<span class="col-xs-2 text-right">{{aircraft.speed}}<span style="font-size:50%">KTS</span></span>
<span class="col-xs-2 text-right"><span ng-show="aircraft.heading < 10">0</span><span ng-show="aircraft.heading < 100">0</span>{{aircraft.heading}}&deg;</span>
<span class="col-xs-2 text-right">{{aircraft.signal.toFixed(2)}}<span style="font-size:50%">dB</span></span>
<span class="col-xs-2 text-right">{{aircraft.age.toFixed(1)}}<span style="font-size:50%">s</span></span>
</div>
</div>
</div>
<div class="panel-body traffic-footer">
<div class="separator"></div>
<div class="row">
<div class="col-sm-4">
<label class="control-label col-xs-6">Show Tail Number</label>
<span class="col-xs-3"><ui-switch ng-model='showReg' settings-change></ui-switch></span>
</div>
<div class="col-sm-4">
<label class="control-label col-xs-6">Show Squawk</label>
<span class="col-xs-3"><ui-switch ng-model='showSquawk' settings-change></ui-switch></span>
</div>
<div class="col-sm-4">
<label class="control-label col-xs-6" ng-show="GPS_connected">Show Distance</label>
<label class="control-label text-muted col-xs-6" ng-hide="GPS_connected">Show Distance N/A</label>
<span class="col-xs-3"><ui-switch ng-model='RelDist' settings-change></ui-switch></span>
</div>
<!--
<div class="col-sm-4">
<label class="control-label col-xs-6">GPS Status</label>
<span ng-show="GPS_connected" class="label label-success col-xs-3" style="font-size:100%; display:block; height: 34px; line-height: 34px">Valid</span>
<span ng-hide="GPS_connected" class="label label-danger col-xs-3" style="font-size:100%; display:block; height: 34px; line-height: 34px">No Fix</span>
</div>
-->
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Basic Mode S and No-Position Messages</span>
</div>
<div class="panel-body traffic-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-4" ng-hide="showReg"><strong>Callsign</strong></span>
<span class="col-xs-4" ng-show="showReg"><strong>Tail Num</strong></span>
<span class="col-xs-3"><strong>Code</strong></span>
<span class="col-xs-3"><strong>Squawk</strong></span>
</div>
<div class="col-sm-6">
<span class="col-xs-3 text-right"><strong>Altitude</strong></span><span class="col-xs-1">&nbsp;</span>
<span class="col-xs-2 text-right"><strong>Speed</strong></span>
<span class="col-xs-2 text-right"><strong>Course</strong></span>
<span class="col-xs-2 text-right"><strong>Power</strong></span>
<span class="col-xs-2 text-right"><strong>Age</strong></span>
</div>
</div>
<div class="row" ng-repeat="aircraft in data_list_invalid | orderBy: 'icao'">
<div class="separator"></div>
<div class="col-sm-6">
<span class="col-xs-4" ng-hide="showReg">
<span ng-show="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.tail}}</strong></span>
<span ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-4" ng-show="showReg">
<span ng-show="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.reg}}</strong></span>
<span ng-hide="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-3" style="font-size:80%">{{aircraft.icao}}<span style="font-size:50%">{{aircraft.addr_type == 3 ? "&nbsp;(TFID)" : ""}}</span></span>
<span class="col-xs-3"><span ng-show="aircraft.squawk < 1000">0</span><span ng-show="aircraft.squawk < 100">0</span><span ng-show="aircraft.squawk < 10">0</span>{{aircraft.squawk}}</span>
</div>
<div class="col-sm-6">
<span class="col-xs-3 text-right">{{aircraft.alt}}</span>
<span class="col-xs-1 small col-padding-shift-right text-muted">
<span ng-show="aircraft.vspeed > 0"><span class="fa fa-ascent"></span>{{aircraft.vspeed}}</span>
<span ng-show="aircraft.vspeed < 0"><span class="fa fa-descent"></span>{{0-aircraft.vspeed}}</span>
</span>
<span class="col-xs-2 text-right">{{aircraft.speed}}<span style="font-size:50%">KTS</span></span>
<span class="col-xs-2 text-right"><span ng-show="aircraft.heading < 10">0</span><span ng-show="aircraft.heading < 100">0</span>{{aircraft.heading}}&deg;</span>
<span class="col-xs-2 text-right">{{aircraft.signal.toFixed(2)}}<span style="font-size:50%">dB</span></span>
<span class="col-xs-2 text-right">{{aircraft.ageLastAlt.toFixed(1)}}<span style="font-size:50%">s</span></span>
</div>
</div>
</div>
<div class="panel-body traffic-footer">
<div class="separator"></div>
<span class ="col-sm-12 small">Stratux has not received valid ADS-B position transmissions from the aircraft in this section. They will not appear on your EFB map. See help page for details.</span>
</div>
</div>
</div>
<!--
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">Raw Traffic Data</div>
<div class="panel-body">
<pre>{{raw_data}}</pre>
</div>
</div>
</div>
-->

Wyświetl plik

@ -1,10 +1,10 @@
<div class="section text-left help-page">
<p>The <strong>Weather</strong> page provides a list of recent reports received.</p>
<p>There are two lists available for reference:</p>
<ul>
<li><strong>Watch List</strong> contains all weather received for locations included in your watch list <span class="fa fa-asterisk icon-blue"></span></li>
<li><strong>Recent Reports</strong> contains the most recent 10 reports received of any type for any location</li>
</ul>
<p><span class="fa fa-asterisk icon-blue"></span> The Watch List setting is found on the <strong>Settings</strong> page.</p>
<p class="text-warning">NOTE: When this page becomes active (aka it is selected from the menu) it will display only new weather. Older weather and existing weather will not appear until their next report.</p>
<div class="section text-left help-page">
<p>The <strong>Weather</strong> page provides a list of recent reports received.</p>
<p>There are two lists available for reference:</p>
<ul>
<li><strong>Watch List</strong> contains all weather received for locations included in your watch list <span class="fa fa-asterisk icon-blue"></span></li>
<li><strong>Recent Reports</strong> contains the most recent 10 reports received of any type for any location</li>
</ul>
<p><span class="fa fa-asterisk icon-blue"></span> The Watch List setting is found on the <strong>Settings</strong> page.</p>
<p class="text-warning">NOTE: When this page becomes active (aka it is selected from the menu) it will display only new weather. Older weather and existing weather will not appear until their next report.</p>
</div>

Wyświetl plik

@ -1,92 +1,92 @@
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Weather</span>
<span ng-show="ConnectState == 'Connected'" class="label label-success">{{ConnectState}}</span>
<span ng-hide="ConnectState == 'Connected'" class="label label-danger">{{ConnectState}}</span>
</div>
</div>
<div class="panel-group" ui-state="weatherAccordion" ui-default="1">
<div class="panel panel-default">
<div class="panel-heading" ui-set="{'weatherAccordion':1}">
<div class="panel-title">Watching <span class="text-normal">{{watching}}</span> ({{watch_count}})</div>
</div>
<div ui-if="weatherAccordion == 1">
<div class="panel-body weather-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-3"><strong>Location</strong></span>
<span class="col-xs-3">Type</span>
<span class="col-xs-6 text-right">Time</span>
</div>
<div class="col-sm-6">
<span class="col-xs-2">&nbsp;</span>
<span class="col-xs-10">Report</span>
</div>
</div>
<div class="row" ng-repeat="weather in watch_list | orderBy: -age">
<div class="separator"></div>
<div class="col-sm-12">
<span class="col-xs-3"><strong>{{weather.location}}</strong></span>
<span class="col-xs-3" align="center">
<div align="center" ng-class="weather.flight_condition ? ' label label-success flight_condition_{{weather.flight_condition}}' : 'label label-success report_{{weather.type}}'">{{weather.type}}</div>
</span>
<span class="col-xs-4">&nbsp;</span>
<span class="col-xs-2 text-right" style="background-color: {{weather.backcolor}}">{{weather.time}}</span>
</div>
<div class="col-sm-12">
<span class="col-xs-10">{{weather.data}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" ui-set="{'weatherAccordion':2}">
<div class="panel-title">Recent Reports ({{data_count}})</div>
</div>
<div ui-if="weatherAccordion == 2">
<div class="panel-body weather-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-3"><strong>Location</strong></span>
<span class="col-xs-3">Type</span>
<span class="col-xs-6 text-right">Time</span>
</div>
<div class="col-sm-6">
<span class="col-xs-2">&nbsp;</span>
<span class="col-xs-10">Report</span>
</div>
</div>
<div class="row" ng-repeat="weather in data_list | orderBy: -age">
<div class="separator"></div>
<div class="col-sm-12">
<span class="col-xs-3"><strong>{{weather.location}}</strong></span>
<span class="col-xs-3" align="center">
<div align="center" ng-class="weather.flight_condition ? ' label label-success flight_condition_{{weather.flight_condition}}' : 'label label-success report_{{weather.type}}'">{{weather.type}}</div>
</span>
<span class="col-xs-4">&nbsp;</span>
<span class="col-xs-2 text-right" style="background-color: {{weather.backcolor}}">{{weather.time}}</span>
</div>
<div class="col-sm-12">
<span class="col-xs-10">{{weather.data}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">Raw Weather Data</div>
<div class="panel-body">
<pre>{{raw_data}}</pre>
</div>
</div>
</div>
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel_label">Weather</span>
<span ng-show="ConnectState == 'Connected'" class="label label-success">{{ConnectState}}</span>
<span ng-hide="ConnectState == 'Connected'" class="label label-danger">{{ConnectState}}</span>
</div>
</div>
<div class="panel-group" ui-state="weatherAccordion" ui-default="1">
<div class="panel panel-default">
<div class="panel-heading" ui-set="{'weatherAccordion':1}">
<div class="panel-title">Watching <span class="text-normal">{{watching}}</span> ({{watch_count}})</div>
</div>
<div ui-if="weatherAccordion == 1">
<div class="panel-body weather-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-3"><strong>Location</strong></span>
<span class="col-xs-3">Type</span>
<span class="col-xs-6 text-right">Time</span>
</div>
<div class="col-sm-6">
<span class="col-xs-2">&nbsp;</span>
<span class="col-xs-10">Report</span>
</div>
</div>
<div class="row" ng-repeat="weather in watch_list | orderBy: -age">
<div class="separator"></div>
<div class="col-sm-12">
<span class="col-xs-3"><strong>{{weather.location}}</strong></span>
<span class="col-xs-3" align="center">
<div align="center" ng-class="weather.flight_condition ? ' label label-success flight_condition_{{weather.flight_condition}}' : 'label label-success report_{{weather.type}}'">{{weather.type}}</div>
</span>
<span class="col-xs-4">&nbsp;</span>
<span class="col-xs-2 text-right" style="background-color: {{weather.backcolor}}">{{weather.time}}</span>
</div>
<div class="col-sm-12">
<span class="col-xs-10">{{weather.data}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" ui-set="{'weatherAccordion':2}">
<div class="panel-title">Recent Reports ({{data_count}})</div>
</div>
<div ui-if="weatherAccordion == 2">
<div class="panel-body weather-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-3"><strong>Location</strong></span>
<span class="col-xs-3">Type</span>
<span class="col-xs-6 text-right">Time</span>
</div>
<div class="col-sm-6">
<span class="col-xs-2">&nbsp;</span>
<span class="col-xs-10">Report</span>
</div>
</div>
<div class="row" ng-repeat="weather in data_list | orderBy: -age">
<div class="separator"></div>
<div class="col-sm-12">
<span class="col-xs-3"><strong>{{weather.location}}</strong></span>
<span class="col-xs-3" align="center">
<div align="center" ng-class="weather.flight_condition ? ' label label-success flight_condition_{{weather.flight_condition}}' : 'label label-success report_{{weather.type}}'">{{weather.type}}</div>
</span>
<span class="col-xs-4">&nbsp;</span>
<span class="col-xs-2 text-right" style="background-color: {{weather.backcolor}}">{{weather.time}}</span>
</div>
<div class="col-sm-12">
<span class="col-xs-10">{{weather.data}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">Raw Weather Data</div>
<div class="panel-body">
<pre>{{raw_data}}</pre>
</div>
</div>
</div>
-->