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

Wyświetl plik

@ -1,104 +1,104 @@
<div class="col-sm-12"> <div class="col-sm-12">
<div class="col-sm-6"> <div class="col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><span class="panel_label">GPS</span></div> <div class="panel-heading"><span class="panel_label">GPS</span></div>
<div class="panel-body"> <div class="panel-body">
<div class="row"> <div class="row">
<span class="col-xs-12"> <span class="col-xs-12">
<div class="map-container"> <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 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'}"> <div class="mark-position" ng-style="{left: map_mark_x+'px', top: map_mark_y+'px'}">
<span class="fa fa-crosshairs"></span> <span class="fa fa-crosshairs"></span>
</div> </div>
</div> </div>
</div> </div>
</span> </span>
</div> </div>
<div class="separator"></div> <div class="separator"></div>
<div class="row"> <div class="row">
<strong class="col-xs-6 text-center">Location:</strong> <strong class="col-xs-6 text-center">Location:</strong>
<strong class="col-xs-6 text-center">Track:</strong> <strong class="col-xs-6 text-center">Track:</strong>
</div> </div>
<div class="row"> <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_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> <span class="col-xs-6 text-center">{{gps_track}}&deg; @ {{gps_speed}} KTS</span>
</div> </div>
</div> </div>
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<span class="panel_label">Satellites</span> <span class="panel_label">Satellites</span>
</div> </div>
<div class="panel-body towers-page"> <div class="panel-body towers-page">
<div class="row"> <div class="row">
<span class="col-xs-3"><strong>Satellite</strong></span> <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-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>Elevation</strong></span>
<span class="col-xs-3 text-right"><strong>Azimuth</strong></span> <span class="col-xs-3 text-right"><strong>Azimuth</strong></span>
<span class="col-xs-3 text-right"><strong>Signal</strong></span> <span class="col-xs-3 text-right"><strong>Signal</strong></span>
</div> </div>
<div class="row" ng-repeat="satellite in data_list | orderBy: 'SatelliteNMEA'"> <div class="row" ng-repeat="satellite in data_list | orderBy: 'SatelliteNMEA'">
<div class="separator"></div> <div class="separator"></div>
<span class="col-xs-3">{{satellite.SatelliteID}}<span ng-show="satellite.InSolution">&nbsp;&#x2705;</span></span> <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-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.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.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> <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> </div>
<div class="separator"></div> <div class="separator"></div>
<div class="panel-footer"> <div class="panel-footer">
<div class="row"> <div class="row">
<label class="col-xs-6">GPS solution:</label> <label class="col-xs-6">GPS solution:</label>
<span class="col-xs-6">{{SolutionText}}</span> <span class="col-xs-6">{{SolutionText}}</span>
</div> </div>
<div class="row"> <div class="row">
<label class="col-xs-6">Summary:</label> <label class="col-xs-6">Summary:</label>
<span class="col-xs-6">{{Satellites}} in solution; {{GPS_satellites_seen}} seen; {{GPS_satellites_tracked}} tracked</span> <span class="col-xs-6">{{Satellites}} in solution; {{GPS_satellites_seen}} seen; {{GPS_satellites_tracked}} tracked</span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><span class="panel_label">AHRS</span></div> <div class="panel-heading"><span class="panel_label">AHRS</span></div>
<div class="panel-body"> <div class="panel-body">
<div class="row"> <div class="row">
<span class="col-xs-12"> <span class="col-xs-12">
<div id="ahrs_display"> <div id="ahrs_display">
<object id="attitude_indicator" data="../img/ai.svg" type="image/svg+xml"> <object id="attitude_indicator" data="../img/ai.svg" type="image/svg+xml">
Your browser doesn't support svg. Your browser doesn't support svg.
</object> </object>
</div> </div>
</span> </span>
</div> </div>
<div class="separator"></div> <div class="separator"></div>
<div class="row"> <div class="row">
<strong class="col-xs-3 text-center">Heading:</strong> <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">Pitch:</strong>
<strong class="col-xs-3 text-center">Roll:</strong> <strong class="col-xs-3 text-center">Roll:</strong>
<strong class="col-xs-3 text-center">P-Alt:</strong> <strong class="col-xs-3 text-center">P-Alt:</strong>
</div> </div>
<div class="row"> <div class="row">
<span class="col-xs-3 text-center">{{ahrs_heading}}&deg;</span> <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_pitch}}&deg;</span>
<span class="col-xs-3 text-center">{{ahrs_roll}}&deg;</span> <span class="col-xs-3 text-center">{{ahrs_roll}}&deg;</span>
<span class="col-xs-3 text-center">{{ahrs_alt}} ft</span> <span class="col-xs-3 text-center">{{ahrs_alt}} ft</span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- <!--
<div class="col-sm-12"> <div class="col-sm-12">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading">Raw GPS / AHRS Data</div> <div class="panel-heading">Raw GPS / AHRS Data</div>
<div class="panel-body"> <div class="panel-body">
<pre>{{raw_data}}</pre> <pre>{{raw_data}}</pre>
</div> </div>
</div> </div>
</div> </div>
--> -->

Wyświetl plik

@ -1,180 +1,180 @@
angular.module('appControllers').controller('GPSCtrl', GPSCtrl); // get the main module contollers set angular.module('appControllers').controller('GPSCtrl', GPSCtrl); // get the main module contollers set
GPSCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies GPSCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
// create our controller function with all necessary logic // create our controller function with all necessary logic
function GPSCtrl($rootScope, $scope, $state, $http, $interval) { function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.$parent.helppage = 'plates/gps-help.html'; $scope.$parent.helppage = 'plates/gps-help.html';
$scope.data_list = []; $scope.data_list = [];
var status = {}; var status = {};
var display_area_size = -1; var display_area_size = -1;
function sizeMap() { function sizeMap() {
var width = 0; var width = 0;
var el = document.getElementById("map_display").parentElement; var el = document.getElementById("map_display").parentElement;
width = el.offsetWidth; // was (- (2 * el.offsetLeft)) width = el.offsetWidth; // was (- (2 * el.offsetLeft))
if (width !== display_area_size) { if (width !== display_area_size) {
display_area_size = width; display_area_size = width;
$scope.map_width = width; $scope.map_width = width;
$scope.map_height = width *0.5; $scope.map_height = width *0.5;
} }
return width; return width;
} }
function setGeoReferenceMap(la, lo) { function setGeoReferenceMap(la, lo) {
// Mercator projection // Mercator projection
// var map = "img/world.png"; // var map = "img/world.png";
var map_width = 2530; var map_width = 2530;
var map_height = 1603; var map_height = 1603;
var map_zero_x = 1192; var map_zero_x = 1192;
var map_zero_y = 1124; var map_zero_y = 1124;
var font_size = 18; // size of font used for marker var font_size = 18; // size of font used for marker
sizeMap(); sizeMap();
var div_width = $scope.map_width; var div_width = $scope.map_width;
var div_height = $scope.map_height; var div_height = $scope.map_height;
// longitude: just scale and shift // longitude: just scale and shift
var x = (map_width * (180 + lo) / 360) - (map_width/2 - map_zero_x); // longitude_shift; var x = (map_width * (180 + lo) / 360) - (map_width/2 - map_zero_x); // longitude_shift;
// latitude: using the Mercator projection // latitude: using the Mercator projection
la_rad = la * Math.PI / 180; // convert from degrees to radians 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) 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 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>'; // 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"> // <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_x = map_width - Math.round(x - (div_width / 2));
$scope.map_pos_y = map_height - Math.round(y - (div_height / 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_x = Math.round((div_width - (font_size * 0.85)) / 2);
$scope.map_mark_y = Math.round((div_height - font_size) / 2); $scope.map_mark_y = Math.round((div_height - font_size) / 2);
} }
function loadStatus(data) { // mySituation function loadStatus(data) { // mySituation
status = angular.fromJson(data); status = angular.fromJson(data);
// consider using angular.extend() // consider using angular.extend()
$scope.raw_data = angular.toJson(data, true); // makes it pretty $scope.raw_data = angular.toJson(data, true); // makes it pretty
$scope.Satellites = status.Satellites; $scope.Satellites = status.Satellites;
$scope.GPS_satellites_tracked = status.SatellitesTracked; $scope.GPS_satellites_tracked = status.SatellitesTracked;
$scope.GPS_satellites_seen = status.SatellitesSeen; $scope.GPS_satellites_seen = status.SatellitesSeen;
$scope.Quality = status.Quality; $scope.Quality = status.Quality;
var solutionText = "No Fix"; var solutionText = "No Fix";
if (status.Quality == 2) { if (status.Quality == 2) {
solutionText = "GPS + SBAS (WAAS / EGNOS)"; solutionText = "GPS + SBAS (WAAS / EGNOS)";
} else if (status.Quality == 1) { } else if (status.Quality == 1) {
solutionText = "3D GPS" solutionText = "3D GPS"
} }
$scope.SolutionText = solutionText; $scope.SolutionText = solutionText;
$scope.gps_accuracy = status.Accuracy.toFixed(1); $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 $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 // 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"]; // 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]; // $scope.gps_accuracy = accuracies[status.NACp];
// "LastFixLocalTime":"2015-10-11T16:47:03.523085162Z" // "LastFixLocalTime":"2015-10-11T16:47:03.523085162Z"
$scope.gps_lat = status.Lat.toFixed(5); // result is string $scope.gps_lat = status.Lat.toFixed(5); // result is string
$scope.gps_lon = status.Lng.toFixed(5); // result is string $scope.gps_lon = status.Lng.toFixed(5); // result is string
$scope.gps_alt = Math.round(status.Alt); $scope.gps_alt = Math.round(status.Alt);
$scope.gps_track = status.TrueCourse; $scope.gps_track = status.TrueCourse;
$scope.gps_speed = status.GroundSpeed; $scope.gps_speed = status.GroundSpeed;
$scope.gps_vert_speed = status.GPSVertVel.toFixed(1); $scope.gps_vert_speed = status.GPSVertVel.toFixed(1);
// "LastGroundTrackTime":"0001-01-01T00:00:00Z" // "LastGroundTrackTime":"0001-01-01T00:00:00Z"
/* not currently used /* not currently used
$scope.ahrs_temp = status.Temp; $scope.ahrs_temp = status.Temp;
*/ */
$scope.ahrs_alt = Math.round(status.Pressure_alt); $scope.ahrs_alt = Math.round(status.Pressure_alt);
$scope.ahrs_heading = Math.round(status.Gyro_heading); $scope.ahrs_heading = Math.round(status.Gyro_heading);
// pitch and roll are in degrees // pitch and roll are in degrees
$scope.ahrs_pitch = Math.round(status.Pitch); $scope.ahrs_pitch = Math.round(status.Pitch);
$scope.ahrs_roll = Math.round(status.Roll); $scope.ahrs_roll = Math.round(status.Roll);
// "LastAttitudeTime":"2015-10-11T16:47:03.534615187Z" // "LastAttitudeTime":"2015-10-11T16:47:03.534615187Z"
setGeoReferenceMap(status.Lat, status.Lng); setGeoReferenceMap(status.Lat, status.Lng);
// $scope.$apply(); // $scope.$apply();
} }
function getStatus() { function getStatus() {
// Simple GET request example (note: responce is asynchronous) // Simple GET request example (note: responce is asynchronous)
$http.get(URL_GPS_GET). $http.get(URL_GPS_GET).
then(function (response) { then(function (response) {
loadStatus(response.data); loadStatus(response.data);
ahrs.animate(0.1, $scope.ahrs_pitch, $scope.ahrs_roll, $scope.ahrs_heading); ahrs.animate(0.1, $scope.ahrs_pitch, $scope.ahrs_roll, $scope.ahrs_heading);
// $scope.$apply(); // $scope.$apply();
}, function (response) { }, function (response) {
$scope.raw_data = "error getting gps / ahrs status"; $scope.raw_data = "error getting gps / ahrs status";
}); });
} }
function getSatellites() { function getSatellites() {
// Simple GET request example (note: response is asynchronous) // Simple GET request example (note: response is asynchronous)
$http.get(URL_SATELLITES_GET). $http.get(URL_SATELLITES_GET).
then(function (response) { then(function (response) {
loadSatellites(response.data); loadSatellites(response.data);
}, function (response) { }, function (response) {
$scope.raw_data = "error getting satellite data"; $scope.raw_data = "error getting satellite data";
}); });
} }
function setSatellite(obj, new_satellite) { function setSatellite(obj, new_satellite) {
new_satellite.SatelliteNMEA = obj.SatelliteNMEA; 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.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.Elevation = obj.Elevation; // Angle above local horizon, -xx to +90
new_satellite.Azimuth = obj.Azimuth; // Bearing (degrees true), 0-359 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.Signal = obj.Signal; // Signal strength, 0 - 99; -99 indicates no reception
new_satellite.InSolution = obj.InSolution; // is this satellite in the position solution new_satellite.InSolution = obj.InSolution; // is this satellite in the position solution
} }
function loadSatellites(data) { function loadSatellites(data) {
if (($scope === undefined) || ($scope === null)) if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page 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 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.raw_data = angular.toJson(data, true);
$scope.data_list.length = 0; // clear array $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 // 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) { for (var key in satellites) {
//if (satellites[key].Messages_last_minute > 0) { //if (satellites[key].Messages_last_minute > 0) {
var new_satellite = {}; var new_satellite = {};
setSatellite(satellites[key], new_satellite); setSatellite(satellites[key], new_satellite);
$scope.data_list.push(new_satellite); // add to start of array $scope.data_list.push(new_satellite); // add to start of array
//} //}
} }
// $scope.$apply(); // $scope.$apply();
} }
var updateStatus = $interval(function () { var updateStatus = $interval(function () {
// refresh GPS/AHRS status once each 200 milliseconds (aka polling) // refresh GPS/AHRS status once each 200 milliseconds (aka polling)
getStatus(); getStatus();
getSatellites(); getSatellites();
}, (2 * 100), 0, false); }, (2 * 100), 0, false);
$state.get('gps').onEnter = function () { $state.get('gps').onEnter = function () {
// everything gets handled correctly by the controller // everything gets handled correctly by the controller
}; };
$state.get('gps').onExit = function () { $state.get('gps').onExit = function () {
// stop polling for gps/ahrs status // stop polling for gps/ahrs status
$interval.cancel(updateStatus); $interval.cancel(updateStatus);
}; };
// GPS/AHRS Controller tasks go here // GPS/AHRS Controller tasks go here
var ahrs = new ahrsRenderer("ahrs_display"); var ahrs = new ahrsRenderer("ahrs_display");
ahrs.init(); ahrs.init();
ahrs.orientation(0, 0, 90); ahrs.orientation(0, 0, 90);
} }

Wyświetl plik

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

Wyświetl plik

@ -1,241 +1,241 @@
angular.module('appControllers').controller('TrafficCtrl', TrafficCtrl); // get the main module contollers set angular.module('appControllers').controller('TrafficCtrl', TrafficCtrl); // get the main module contollers set
TrafficCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies TrafficCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
// create our controller function with all necessary logic // create our controller function with all necessary logic
function TrafficCtrl($rootScope, $scope, $state, $http, $interval) { function TrafficCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.$parent.helppage = 'plates/traffic-help.html'; $scope.$parent.helppage = 'plates/traffic-help.html';
$scope.data_list = []; $scope.data_list = [];
$scope.data_list_invalid = []; $scope.data_list_invalid = [];
function utcTimeString(epoc) { function utcTimeString(epoc) {
var time = ""; var time = "";
var val; var val;
var d = new Date(epoc); var d = new Date(epoc);
val = d.getUTCHours(); val = d.getUTCHours();
time += (val < 10 ? "0" + val : "" + val); time += (val < 10 ? "0" + val : "" + val);
val = d.getUTCMinutes(); val = d.getUTCMinutes();
time += ":" + (val < 10 ? "0" + val : "" + val); time += ":" + (val < 10 ? "0" + val : "" + val);
val = d.getUTCSeconds(); val = d.getUTCSeconds();
time += ":" + (val < 10 ? "0" + val : "" + val); time += ":" + (val < 10 ? "0" + val : "" + val);
time += "Z"; time += "Z";
return time; return time;
} }
/* /*
function dmsString(val) { function dmsString(val) {
return [0 | val, return [0 | val,
'° ', '° ',
0 | (val < 0 ? val = -val : val) % 1 * 60, 0 | (val < 0 ? val = -val : val) % 1 * 60,
"' ", "' ",
0 | val * 60 % 1 * 60, 0 | val * 60 % 1 * 60,
'"'].join(''); '"'].join('');
} }
*/ */
// chop off seconds for space // chop off seconds for space
function dmsString(val) { function dmsString(val) {
var deg; var deg;
var min; var min;
deg = 0 | val; deg = 0 | val;
min = 0 | (val < 0 ? val = -val : val) % 1 * 60; min = 0 | (val < 0 ? val = -val : val) % 1 * 60;
return [deg*deg < 100 ? "0" + deg : deg, return [deg*deg < 100 ? "0" + deg : deg,
'° ', '° ',
min < 10 ? "0" + min : min, min < 10 ? "0" + min : min,
"' "].join(''); "' "].join('');
} }
function setAircraft(obj, new_traffic) { function setAircraft(obj, new_traffic) {
new_traffic.icao_int = obj.Icao_addr; new_traffic.icao_int = obj.Icao_addr;
new_traffic.targettype = obj.TargetType; new_traffic.targettype = obj.TargetType;
new_traffic.signal = obj.SignalLevel; new_traffic.signal = obj.SignalLevel;
new_traffic.addr_symb ='\u2708'; new_traffic.addr_symb ='\u2708';
if (new_traffic.targettype > 3) { if (new_traffic.targettype > 3) {
new_traffic.addr_symb ='\ud83d\udce1'; new_traffic.addr_symb ='\ud83d\udce1';
} }
new_traffic.icao = obj.Icao_addr.toString(16).toUpperCase(); new_traffic.icao = obj.Icao_addr.toString(16).toUpperCase();
new_traffic.tail = obj.Tail; new_traffic.tail = obj.Tail;
new_traffic.reg = obj.Reg; new_traffic.reg = obj.Reg;
if (obj.Squawk == 0) { if (obj.Squawk == 0) {
new_traffic.squawk = "----"; new_traffic.squawk = "----";
} else { } else {
new_traffic.squawk = obj.Squawk; new_traffic.squawk = obj.Squawk;
} }
new_traffic.addr_type = obj.Addr_type; new_traffic.addr_type = obj.Addr_type;
new_traffic.lat = dmsString(obj.Lat); new_traffic.lat = dmsString(obj.Lat);
new_traffic.lon = dmsString(obj.Lng); new_traffic.lon = dmsString(obj.Lng);
var n = Math.round(obj.Alt / 25) * 25; var n = Math.round(obj.Alt / 25) * 25;
new_traffic.alt = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); new_traffic.alt = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
var s = Math.round(obj.Speed / 5) * 5; var s = Math.round(obj.Speed / 5) * 5;
if (obj.Speed_valid) { if (obj.Speed_valid) {
new_traffic.speed = s.toString(); new_traffic.speed = s.toString();
new_traffic.heading = Math.round(obj.Track / 5) * 5; new_traffic.heading = Math.round(obj.Track / 5) * 5;
} else { } else {
new_traffic.speed = "---"; new_traffic.speed = "---";
new_traffic.heading = "---"; new_traffic.heading = "---";
} }
new_traffic.vspeed = Math.round(obj.Vvel / 100) * 100 new_traffic.vspeed = Math.round(obj.Vvel / 100) * 100
var timestamp = Date.parse(obj.Timestamp); var timestamp = Date.parse(obj.Timestamp);
new_traffic.time = utcTimeString(timestamp); new_traffic.time = utcTimeString(timestamp);
new_traffic.age = obj.Age; new_traffic.age = obj.Age;
new_traffic.ageLastAlt = obj.AgeLastAlt; new_traffic.ageLastAlt = obj.AgeLastAlt;
new_traffic.src = obj.Last_source; // 1=ES, 2=UAT new_traffic.src = obj.Last_source; // 1=ES, 2=UAT
new_traffic.bearing = Math.round(obj.Bearing); // degrees true new_traffic.bearing = Math.round(obj.Bearing); // degrees true
new_traffic.dist = (obj.Distance/1852); // nautical miles new_traffic.dist = (obj.Distance/1852); // nautical miles
// return new_aircraft; // return new_aircraft;
} }
function connect($scope) { function connect($scope) {
if (($scope === undefined) || ($scope === null)) if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page return; // we are getting called once after clicking away from the status page
if (($scope.socket === undefined) || ($scope.socket === null)) { if (($scope.socket === undefined) || ($scope.socket === null)) {
socket = new WebSocket(URL_TRAFFIC_WS); socket = new WebSocket(URL_TRAFFIC_WS);
$scope.socket = socket; // store socket in scope for enter/exit usage $scope.socket = socket; // store socket in scope for enter/exit usage
} }
$scope.ConnectState = "Disconnected"; $scope.ConnectState = "Disconnected";
socket.onopen = function (msg) { socket.onopen = function (msg) {
// $scope.ConnectStyle = "label-success"; // $scope.ConnectStyle = "label-success";
$scope.ConnectState = "Connected"; $scope.ConnectState = "Connected";
}; };
socket.onclose = function (msg) { socket.onclose = function (msg) {
// $scope.ConnectStyle = "label-danger"; // $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Disconnected"; $scope.ConnectState = "Disconnected";
$scope.$apply(); $scope.$apply();
setTimeout(connect, 1000); setTimeout(connect, 1000);
}; };
socket.onerror = function (msg) { socket.onerror = function (msg) {
// $scope.ConnectStyle = "label-danger"; // $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Problem"; $scope.ConnectState = "Problem";
$scope.$apply(); $scope.$apply();
}; };
socket.onmessage = function (msg) { socket.onmessage = function (msg) {
console.log('Received traffic update.') console.log('Received traffic update.')
var message = JSON.parse(msg.data); var message = JSON.parse(msg.data);
$scope.raw_data = angular.toJson(msg.data, true); $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 // 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 validIdx = -1;
var invalidIdx = -1; var invalidIdx = -1;
for (var i = 0, len = $scope.data_list.length; i < len; i++) { for (var i = 0, len = $scope.data_list.length; i < len; i++) {
if ($scope.data_list[i].icao_int === message.Icao_addr) { if ($scope.data_list[i].icao_int === message.Icao_addr) {
setAircraft(message, $scope.data_list[i]); setAircraft(message, $scope.data_list[i]);
validIdx = i; validIdx = i;
break; break;
} }
} }
for (var i = 0, len = $scope.data_list_invalid.length; i < len; i++) { for (var i = 0, len = $scope.data_list_invalid.length; i < len; i++) {
if ($scope.data_list_invalid[i].icao_int === message.Icao_addr) { if ($scope.data_list_invalid[i].icao_int === message.Icao_addr) {
setAircraft(message, $scope.data_list_invalid[i]); setAircraft(message, $scope.data_list_invalid[i]);
invalidIdx = i; invalidIdx = i;
break; break;
} }
} }
if ((validIdx < 0) && (message.Position_valid)) { if ((validIdx < 0) && (message.Position_valid)) {
var new_traffic = {}; var new_traffic = {};
setAircraft(message, new_traffic); setAircraft(message, new_traffic);
$scope.data_list.unshift(new_traffic); // add to start of valid array. $scope.data_list.unshift(new_traffic); // add to start of valid array.
} }
if ((invalidIdx < 0) && (!message.Position_valid)) { if ((invalidIdx < 0) && (!message.Position_valid)) {
var new_traffic = {}; var new_traffic = {};
setAircraft(message, new_traffic); setAircraft(message, new_traffic);
$scope.data_list_invalid.unshift(new_traffic); // add to start of invalid array. $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. // Handle the negative cases of those above - where an aircraft moves from "valid" to "invalid" or vice-versa.
if ((validIdx >= 0) && !message.Position_valid) { if ((validIdx >= 0) && !message.Position_valid) {
// Position is not valid any more. Remove from "valid" table. // Position is not valid any more. Remove from "valid" table.
$scope.data_list.splice(validIdx, 1); $scope.data_list.splice(validIdx, 1);
} }
if ((invalidIdx >= 0) && message.Position_valid) { if ((invalidIdx >= 0) && message.Position_valid) {
// Position is now valid. Remove from "invalid" table. // Position is now valid. Remove from "invalid" table.
$scope.data_list_invalid.splice(invalidIdx, 1); $scope.data_list_invalid.splice(invalidIdx, 1);
} }
$scope.$apply(); $scope.$apply();
}; };
} }
var getClock = $interval(function () { var getClock = $interval(function () {
$http.get(URL_STATUS_GET). $http.get(URL_STATUS_GET).
then(function (response) { then(function (response) {
globalStatus = angular.fromJson(response.data); globalStatus = angular.fromJson(response.data);
var tempClock = new Date(Date.parse(globalStatus.Clock)); var tempClock = new Date(Date.parse(globalStatus.Clock));
var clockString = tempClock.toUTCString(); var clockString = tempClock.toUTCString();
$scope.Clock = clockString; $scope.Clock = clockString;
var tempUptimeClock = new Date(Date.parse(globalStatus.UptimeClock)); var tempUptimeClock = new Date(Date.parse(globalStatus.UptimeClock));
var uptimeClockString = tempUptimeClock.toUTCString(); var uptimeClockString = tempUptimeClock.toUTCString();
$scope.UptimeClock = uptimeClockString; $scope.UptimeClock = uptimeClockString;
var tempLocalClock = new Date; var tempLocalClock = new Date;
$scope.LocalClock = tempLocalClock.toUTCString(); $scope.LocalClock = tempLocalClock.toUTCString();
$scope.SecondsFast = (tempClock-tempLocalClock)/1000; $scope.SecondsFast = (tempClock-tempLocalClock)/1000;
$scope.GPS_connected = globalStatus.GPS_connected; $scope.GPS_connected = globalStatus.GPS_connected;
}, function (response) { }, function (response) {
// nop // nop
}); });
}, 500, 0, false); }, 500, 0, false);
// perform cleanup every 10 seconds // perform cleanup every 10 seconds
var clearStaleTraffic = $interval(function () { var clearStaleTraffic = $interval(function () {
// remove stale aircraft = anything more than 59 seconds without a position update // remove stale aircraft = anything more than 59 seconds without a position update
var cutoff = 59; var cutoff = 59;
// Clean up "valid position" table. // Clean up "valid position" table.
for (var i = $scope.data_list.length; i > 0; i--) { for (var i = $scope.data_list.length; i > 0; i--) {
if ($scope.data_list[i - 1].age >= cutoff) { if ($scope.data_list[i - 1].age >= cutoff) {
$scope.data_list.splice(i - 1, 1); $scope.data_list.splice(i - 1, 1);
} }
} }
// Clean up "invalid position" table. // Clean up "invalid position" table.
for (var i = $scope.data_list_invalid.length; i > 0; i--) { 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)) { 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); $scope.data_list_invalid.splice(i - 1, 1);
} }
} }
}, (1000 * 10), 0, false); }, (1000 * 10), 0, false);
$state.get('traffic').onEnter = function () { $state.get('traffic').onEnter = function () {
// everything gets handled correctly by the controller // everything gets handled correctly by the controller
}; };
$state.get('traffic').onExit = function () { $state.get('traffic').onExit = function () {
// disconnect from the socket // disconnect from the socket
if (($scope.socket !== undefined) && ($scope.socket !== null)) { if (($scope.socket !== undefined) && ($scope.socket !== null)) {
$scope.socket.close(); $scope.socket.close();
$scope.socket = null; $scope.socket = null;
} }
// stop stale traffic cleanup // stop stale traffic cleanup
$interval.cancel(clearStaleTraffic); $interval.cancel(clearStaleTraffic);
}; };
// Traffic Controller tasks // Traffic Controller tasks
connect($scope); // connect - opens a socket and listens for messages 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 angular.module('appControllers').controller('WeatherCtrl', WeatherCtrl); // get the main module contollers set
WeatherCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies WeatherCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
// create our controller function with all necessary logic // create our controller function with all necessary logic
function WeatherCtrl($rootScope, $scope, $state, $http, $interval) { function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
var CONF_WATCHLIST = "KBOS KATL KORD KLAX"; // we default to 4 major airports var CONF_WATCHLIST = "KBOS KATL KORD KLAX"; // we default to 4 major airports
var MAX_DATALIST = 10; var MAX_DATALIST = 10;
$scope.$parent.helppage = 'plates/weather-help.html'; $scope.$parent.helppage = 'plates/weather-help.html';
$scope.data_list = []; $scope.data_list = [];
$scope.watch_list = []; $scope.watch_list = [];
$scope.data_count = 0; $scope.data_count = 0;
$scope.watch_count = 0; $scope.watch_count = 0;
function updateWatchList() { function updateWatchList() {
$scope.watching = CONF_WATCHLIST; $scope.watching = CONF_WATCHLIST;
// Simple GET request example (note: responce is asynchronous) // Simple GET request example (note: responce is asynchronous)
$http.get(URL_SETTINGS_GET). $http.get(URL_SETTINGS_GET).
then(function (response) { then(function (response) {
settings = angular.fromJson(response.data); settings = angular.fromJson(response.data);
$scope.watching = settings.WatchList.toUpperCase(); $scope.watching = settings.WatchList.toUpperCase();
}, function (response) { }, function (response) {
// nop // nop
}); });
}; };
function inList(word, sentence) { 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' // since the watch list is just one long string, we cheat and see if the word in anywhere in the 'sentence'
if ((sentence) && (word)) { if ((sentence) && (word)) {
return sentence.includes(word); return sentence.includes(word);
} }
return false; return false;
} }
function parseFlightCondition(msg, body) { function parseFlightCondition(msg, body) {
if ((msg !== "METAR") && (msg !== "SPECI")) if ((msg !== "METAR") && (msg !== "SPECI"))
return ""; return "";
// check the visibility: a value preceeding 'SM' which is either a fraction or a whole number // 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 // 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 // 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' // test for special case of 'X X/X'
var exp = new RegExp("([0-9]) ([0-9])/([0-9])SM"); var exp = new RegExp("([0-9]) ([0-9])/([0-9])SM");
var match = exp.exec(body); var match = exp.exec(body);
if ((match !== null) && (match.length === 4)) { if ((match !== null) && (match.length === 4)) {
visability = parseInt(match[1]) + (parseInt(match[2]) / parseInt(match[3])); visability = parseInt(match[1]) + (parseInt(match[2]) / parseInt(match[3]));
} else { } else {
exp = new RegExp("([0-9/]{1,5}?)SM"); exp = new RegExp("([0-9/]{1,5}?)SM");
match = exp.exec(body); match = exp.exec(body);
if (match === null) if (match === null)
return ""; return "";
// the only way we have 3 or more characters is if the '/' is present which means we need to do extra checking // 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) if (match[1].length === 3)
return "LIFR"; return "LIFR";
// do we have a usable visability distance // do we have a usable visability distance
var visability = parseInt(match[1]); var visability = parseInt(match[1]);
if (visability === 0) if (visability === 0)
return ""; return "";
} }
// ceiling is at either the BKN or OVC layer // ceiling is at either the BKN or OVC layer
exp = new RegExp("BKN([0-9]{3})"); exp = new RegExp("BKN([0-9]{3})");
match = exp.exec(body); match = exp.exec(body);
if (match === null) { if (match === null) {
exp = new RegExp("OVC([0-9]{3})"); exp = new RegExp("OVC([0-9]{3})");
match = exp.exec(body); match = exp.exec(body);
} }
var ceiling = 999; var ceiling = 999;
if (match !== null) if (match !== null)
ceiling = parseInt(match[1]); ceiling = parseInt(match[1]);
if ((visability > 5) && (ceiling > 30)) if ((visability > 5) && (ceiling > 30))
return "VFR"; return "VFR";
if ((visability >= 3) && (ceiling >= 10)) if ((visability >= 3) && (ceiling >= 10))
return "MVFR"; return "MVFR";
if ((visability >= 1) && (ceiling >= 5)) if ((visability >= 1) && (ceiling >= 5))
return "IFR"; return "IFR";
return "LIFR"; return "LIFR";
} }
function deltaTimeString(epoc) { function deltaTimeString(epoc) {
var time = ""; var time = "";
var val; var val;
var d = new Date(epoc); 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 val = d.getUTCDate() - 1; // we got here by subtrracting two dates so we have a delta, not a day of month
if (val > 0) if (val > 0)
time += (val < 10 ? "0" + val : "" + val) + "d "; time += (val < 10 ? "0" + val : "" + val) + "d ";
val = d.getUTCHours(); val = d.getUTCHours();
if (val > 0) { if (val > 0) {
time += (val < 10 ? "0" + val : "" + val) + "h "; time += (val < 10 ? "0" + val : "" + val) + "h ";
} else { } else {
if (time.length > 0) if (time.length > 0)
time += "00h "; time += "00h ";
} }
val = d.getUTCMinutes(); val = d.getUTCMinutes();
time += (val < 10 ? "0" + val : "" + val) + "m "; time += (val < 10 ? "0" + val : "" + val) + "m ";
// ADS-B weather is only accurate to minutes // ADS-B weather is only accurate to minutes
// val = d.getUTCSeconds(); // val = d.getUTCSeconds();
// time += (val < 10 ? "0" + val : "" + val) + "s"; // time += (val < 10 ? "0" + val : "" + val) + "s";
return time; return time;
} }
function parseShortDatetime(sdt) { function parseShortDatetime(sdt) {
var d = new Date(); var d = new Date();
var s = String(sdt); var s = String(sdt);
if (s.length < 7) if (s.length < 7)
return 0; return 0;
d.setUTCDate(parseInt(s.substring(0, 2))); d.setUTCDate(parseInt(s.substring(0, 2)));
d.setUTCHours(parseInt(s.substring(2, 4))); d.setUTCHours(parseInt(s.substring(2, 4)));
if (s.length > 7) { // TAF datetime range if (s.length > 7) { // TAF datetime range
d.setUTCMinutes(0); d.setUTCMinutes(0);
} else { } else {
d.setUTCMinutes(parseInt(s.substring(4, 6))); d.setUTCMinutes(parseInt(s.substring(4, 6)));
} }
d.setUTCSeconds(0); d.setUTCSeconds(0);
d.setUTCMilliseconds(0); d.setUTCMilliseconds(0);
return d; return d;
} }
function setDataItem(obj, data_item) { function setDataItem(obj, data_item) {
if (obj.Type === "TAF.AMD") { if (obj.Type === "TAF.AMD") {
data_item.type = "TAF"; data_item.type = "TAF";
data_item.update = true; data_item.update = true;
} else { } else {
data_item.type = obj.Type; data_item.type = obj.Type;
data_item.update = false; data_item.update = false;
} }
data_item.flight_condition = parseFlightCondition(obj.Type, obj.Data); data_item.flight_condition = parseFlightCondition(obj.Type, obj.Data);
data_item.location = obj.Location; data_item.location = obj.Location;
s = obj.Time; s = obj.Time;
// data_item.time = s.substring(0, 2) + '-' + s.substring(2, 4) + ':' + s.substring(4, 6) + 'Z'; // 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 // 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(obj.LocaltimeReceived);
var dNow = new Date(); var dNow = new Date();
var dThen = parseShortDatetime(obj.Time); var dThen = parseShortDatetime(obj.Time);
data_item.age = dThen.getTime(); data_item.age = dThen.getTime();
var diff_ms = Math.abs(dThen - dNow); var diff_ms = Math.abs(dThen - dNow);
// If time is more than two days away, don't attempt to display data age. // If time is more than two days away, don't attempt to display data age.
if (diff_ms > (1000*60*60*24*2)) { if (diff_ms > (1000*60*60*24*2)) {
data_item.time = "?"; data_item.time = "?";
} else if (dThen > dNow) { } else if (dThen > dNow) {
data_item.time = deltaTimeString(dThen - dNow) + " from now"; data_item.time = deltaTimeString(dThen - dNow) + " from now";
} else { } else {
data_item.time = deltaTimeString(dNow - dThen) + " old"; data_item.time = deltaTimeString(dNow - dThen) + " old";
} }
// data_item.received = utcTimeString(obj.LocaltimeReceived); // data_item.received = utcTimeString(obj.LocaltimeReceived);
data_item.data = obj.Data; data_item.data = obj.Data;
} }
function connect($scope) { function connect($scope) {
if (($scope === undefined) || ($scope === null)) if (($scope === undefined) || ($scope === null))
return; // we are getting called once after clicking away from the status page return; // we are getting called once after clicking away from the status page
if (($scope.socket === undefined) || ($scope.socket === null)) { if (($scope.socket === undefined) || ($scope.socket === null)) {
socket = new WebSocket(URL_WEATHER_WS); socket = new WebSocket(URL_WEATHER_WS);
$scope.socket = socket; // store socket in scope for enter/exit usage $scope.socket = socket; // store socket in scope for enter/exit usage
} }
$scope.ConnectState = "Disconnected"; $scope.ConnectState = "Disconnected";
socket.onopen = function (msg) { socket.onopen = function (msg) {
// $scope.ConnectStyle = "label-success"; // $scope.ConnectStyle = "label-success";
$scope.ConnectState = "Connected"; $scope.ConnectState = "Connected";
}; };
socket.onclose = function (msg) { socket.onclose = function (msg) {
// $scope.ConnectStyle = "label-danger"; // $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Disconnected"; $scope.ConnectState = "Disconnected";
$scope.$apply(); $scope.$apply();
setTimeout(connect, 1000); setTimeout(connect, 1000);
}; };
socket.onerror = function (msg) { socket.onerror = function (msg) {
// $scope.ConnectStyle = "label-danger"; // $scope.ConnectStyle = "label-danger";
$scope.ConnectState = "Problem"; $scope.ConnectState = "Problem";
$scope.$apply(); $scope.$apply();
}; };
socket.onmessage = function (msg) { socket.onmessage = function (msg) {
console.log('Received data_list update.'); console.log('Received data_list update.');
$scope.raw_data = angular.toJson(msg.data, true); $scope.raw_data = angular.toJson(msg.data, true);
var message = JSON.parse(msg.data); 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 // 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; var found = false;
if (inList(message.Location, $scope.watching)) { if (inList(message.Location, $scope.watching)) {
for (var i = 0, len = $scope.watch_list.length; i < len; i++) { 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)) { if (($scope.watch_list[i].type === message.Type) && ($scope.watch_list[i].location === message.Location)) {
setDataItem(message, $scope.watch_list[i]); setDataItem(message, $scope.watch_list[i]);
found = true; found = true;
break; break;
} }
} }
if (!found) { if (!found) {
var new_data_item = {}; var new_data_item = {};
setDataItem(message, new_data_item); setDataItem(message, new_data_item);
$scope.watch_list.unshift(new_data_item); // add to start of array $scope.watch_list.unshift(new_data_item); // add to start of array
} }
} }
// add to scrolling data_list // add to scrolling data_list
{ {
var new_data_item = {}; var new_data_item = {};
setDataItem(message, new_data_item); setDataItem(message, new_data_item);
$scope.data_list.unshift(new_data_item); // add to start of array $scope.data_list.unshift(new_data_item); // add to start of array
if ($scope.data_list.length > MAX_DATALIST) if ($scope.data_list.length > MAX_DATALIST)
$scope.data_list.pop(); // remove last from array $scope.data_list.pop(); // remove last from array
} }
$scope.data_count = $scope.data_list.length; $scope.data_count = $scope.data_list.length;
$scope.watch_count = $scope.watch_list.length; $scope.watch_count = $scope.watch_list.length;
$scope.$apply(); $scope.$apply();
}; };
} }
// perform cleanup every 5 minutes // perform cleanup every 5 minutes
var clearStaleMessages = $interval(function () { var clearStaleMessages = $interval(function () {
// remove stale data = anything more than 30 minutes old // remove stale data = anything more than 30 minutes old
var dirty = false; var dirty = false;
var cutoff = Date.now() - (30 * 60 * 1000); var cutoff = Date.now() - (30 * 60 * 1000);
for (var i = len = $scope.watch_list.length; i > 0; i--) { for (var i = len = $scope.watch_list.length; i > 0; i--) {
if ($scope.watch_list[i - 1].age < cutoff) { if ($scope.watch_list[i - 1].age < cutoff) {
$scope.watch_list.splice(i - 1, 1); $scope.watch_list.splice(i - 1, 1);
dirty = true; dirty = true;
} }
} }
if (dirty) { if (dirty) {
$scope.raw_data = ""; $scope.raw_data = "";
$scope.$apply(); $scope.$apply();
} }
}, (5 * 60 * 1000), 0, false); }, (5 * 60 * 1000), 0, false);
$state.get('weather').onEnter = function () { $state.get('weather').onEnter = function () {
// everything gets handled correctly by the controller // everything gets handled correctly by the controller
updateWatchList(); updateWatchList();
}; };
$state.get('weather').onExit = function () { $state.get('weather').onExit = function () {
// disconnect from the socket // disconnect from the socket
if (($scope.socket !== undefined) && ($scope.socket !== null)) { if (($scope.socket !== undefined) && ($scope.socket !== null)) {
$scope.socket.close(); $scope.socket.close();
$scope.socket = null; $scope.socket = null;
} }
// stop stale message cleanup // stop stale message cleanup
$interval.cancel(clearStaleMessages); $interval.cancel(clearStaleMessages);
}; };
// Weather Controller tasks // Weather Controller tasks
updateWatchList(); updateWatchList();
connect($scope); // connect - opens a socket and listens for messages 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 text-center">
<div class="list-group-item list-group-item-home"> <div class="list-group-item list-group-item-home">
<h2>Logs</h2> <h2>Logs</h2>
</div> </div>
<div class="list-group-item list-group-item-home"> <div class="list-group-item list-group-item-home">
<div> <div>
<i class="fa fa-cloud feature-icon text-primary"></i> <i class="fa fa-cloud feature-icon text-primary"></i>
</div> </div>
<div> <div>
<a target="_blank" href="../logs/stratux.log">stratux.log</a> <a target="_blank" href="../logs/stratux.log">stratux.log</a>
</div> </div>
<div> <div>
<a target="_blank" href="../view_logs/">SDR, AHRS, and GPS logs</a> <a target="_blank" href="../view_logs/">SDR, AHRS, and GPS logs</a>
</div> </div>
<div> <div>
(Enable device logging on "Settings" page) (Enable device logging on "Settings" page)
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<pre>{{userAgent}}</pre> <pre>{{userAgent}}</pre>
<pre>{{deviceViewport}}</pre> <pre>{{deviceViewport}}</pre>
</div> </div>

Wyświetl plik

@ -1,33 +1,33 @@
<div class="section text-left help-page"> <div class="section text-left help-page">
<p>The <strong>Settings</strong> page provides both control and configuration of your Stratux device.</p> <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>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 <p class="text-warning">NOTE: Only hardware toggled on here, will appear on the
<stron>Status</stron> page.</p> <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. <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"> <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>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> <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> </ul>
<p>The <strong>Configuration</strong> section lets you adjust the default operation of your Stratux device.</p> <p>The <strong>Configuration</strong> section lets you adjust the default operation of your Stratux device.</p>
<ul class="list-simple"> <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>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>
<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. <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/> <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> <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>
<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. <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/> <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> <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>
<li>Addiitonal settings will be added in future releases.</li> <li>Addiitonal settings will be added in future releases.</li>
</ul> </ul>
<p>The <strong>System</strong> section lets you safely shutdown or reboot your Stratux device.</p> <p>The <strong>System</strong> section lets you safely shutdown or reboot your Stratux device.</p>
<ul> <ul>
<li><strong>Shutdown</strong> will immediately shutdown the Stratux. You may then safely remove power.</li> <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> <li><strong>Reboot</strong> will immediately reboot the Stratux. After the reboot you may have to rejoin the WiFi connection to reconnect.</li>
</ul> </ul>
</div> </div>

Wyświetl plik

@ -1,13 +1,13 @@
<div class="section text-left help-page"> <div class="section text-left help-page">
<p>The <strong>Status</strong> page provides an overview of your Stratux device.</p> <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>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> <p>Depending on the hardware you have installed in your Stratux, status messages will be shown for the following:</p>
<ul class="list-simple"> <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>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> <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> </ul>
<p class="text-warning">Devices must be manually enabled on the <strong>Settings</strong> page.</p> <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> <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> </div>

Wyświetl plik

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

Wyświetl plik

@ -1,25 +1,25 @@
<div class="section text-left help-page"> <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>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> <p>For each aircraft, the list includes the following details:</p>
<ul> <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> <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"> <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-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-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-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-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-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> <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> </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>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>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>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>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>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>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>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>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> <li><strong>Age</strong> - Age of the last position report, seconds.</li>
</ul> </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> <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> </div>

Wyświetl plik

@ -1,161 +1,161 @@
<div class="col-sm-12"> <div class="col-sm-12">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<span class="panel_label">ADS-B and TIS-B Traffic</span> <span class="panel_label">ADS-B and TIS-B Traffic</span>
<span ng-show="ConnectState == 'Connected'" class="label label-success">{{ConnectState}}</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-hide="ConnectState == 'Connected'" class="label label-danger">{{ConnectState}}</span>
</div> </div>
<div class="panel-body traffic-page"> <div class="panel-body traffic-page">
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<span class="col-xs-3" ng-hide="showReg"><strong>Callsign</strong></span> <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-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-hide="showSquawk"><strong>Code</strong></span>
<span class="col-xs-2" ng-show="showSquawk"><strong>Squawk</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-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-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> <span class="col-xs-2 text-right" ng-show="GPS_connected && RelDist"><strong>Bearing</strong></span>
</div> </div>
<div class="col-sm-6"> <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-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>Speed</strong></span>
<span class="col-xs-2 text-right"><strong>Course</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>Power</strong></span>
<span class="col-xs-2 text-right"><strong>Age</strong></span> <span class="col-xs-2 text-right"><strong>Age</strong></span>
</div> </div>
</div> </div>
<div class="row" ng-repeat="aircraft in data_list | orderBy: 'dist'"> <div class="row" ng-repeat="aircraft in data_list | orderBy: 'dist'">
<div class="separator"></div> <div class="separator"></div>
<div class="col-sm-6"> <div class="col-sm-6">
<span class="col-xs-3" ng-hide="showReg"> <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-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 ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span> </span>
<span class="col-xs-3" ng-show="showReg"> <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-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 ng-hide="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span> </span>
<span class="col-xs-2"> <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 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 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>
<span class="col-xs-5 text-right" ng-hide="GPS_connected && RelDist">{{aircraft.lat}} {{aircraft.lon}}</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-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> <span class="col-xs-2 text-right" ng-show="GPS_connected && RelDist">{{aircraft.bearing}}&deg;</span>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<span class="col-xs-3 text-right">{{aircraft.alt}}</span> <span class="col-xs-3 text-right">{{aircraft.alt}}</span>
<span class="col-xs-1 small col-padding-shift-right text-muted"> <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-ascent"></span>{{aircraft.vspeed}}</span>
<span ng-show="aircraft.vspeed < 0"><span class="fa fa-descent"></span>{{0-aircraft.vspeed}}</span> <span ng-show="aircraft.vspeed < 0"><span class="fa fa-descent"></span>{{0-aircraft.vspeed}}</span>
</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">{{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"><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.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> <span class="col-xs-2 text-right">{{aircraft.age.toFixed(1)}}<span style="font-size:50%">s</span></span>
</div> </div>
</div> </div>
</div> </div>
<div class="panel-body traffic-footer"> <div class="panel-body traffic-footer">
<div class="separator"></div> <div class="separator"></div>
<div class="row"> <div class="row">
<div class="col-sm-4"> <div class="col-sm-4">
<label class="control-label col-xs-6">Show Tail Number</label> <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> <span class="col-xs-3"><ui-switch ng-model='showReg' settings-change></ui-switch></span>
</div> </div>
<div class="col-sm-4"> <div class="col-sm-4">
<label class="control-label col-xs-6">Show Squawk</label> <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> <span class="col-xs-3"><ui-switch ng-model='showSquawk' settings-change></ui-switch></span>
</div> </div>
<div class="col-sm-4"> <div class="col-sm-4">
<label class="control-label col-xs-6" ng-show="GPS_connected">Show Distance</label> <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> <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> <span class="col-xs-3"><ui-switch ng-model='RelDist' settings-change></ui-switch></span>
</div> </div>
<!-- <!--
<div class="col-sm-4"> <div class="col-sm-4">
<label class="control-label col-xs-6">GPS Status</label> <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-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> <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> </div>
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<span class="panel_label">Basic Mode S and No-Position Messages</span> <span class="panel_label">Basic Mode S and No-Position Messages</span>
</div> </div>
<div class="panel-body traffic-page"> <div class="panel-body traffic-page">
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<span class="col-xs-4" ng-hide="showReg"><strong>Callsign</strong></span> <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-4" ng-show="showReg"><strong>Tail Num</strong></span>
<span class="col-xs-3"><strong>Code</strong></span> <span class="col-xs-3"><strong>Code</strong></span>
<span class="col-xs-3"><strong>Squawk</strong></span> <span class="col-xs-3"><strong>Squawk</strong></span>
</div> </div>
<div class="col-sm-6"> <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-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>Speed</strong></span>
<span class="col-xs-2 text-right"><strong>Course</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>Power</strong></span>
<span class="col-xs-2 text-right"><strong>Age</strong></span> <span class="col-xs-2 text-right"><strong>Age</strong></span>
</div> </div>
</div> </div>
<div class="row" ng-repeat="aircraft in data_list_invalid | orderBy: 'icao'"> <div class="row" ng-repeat="aircraft in data_list_invalid | orderBy: 'icao'">
<div class="separator"></div> <div class="separator"></div>
<div class="col-sm-6"> <div class="col-sm-6">
<span class="col-xs-4" ng-hide="showReg"> <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-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 ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span> </span>
<span class="col-xs-4" ng-show="showReg"> <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-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 ng-hide="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</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" 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> <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>
<div class="col-sm-6"> <div class="col-sm-6">
<span class="col-xs-3 text-right">{{aircraft.alt}}</span> <span class="col-xs-3 text-right">{{aircraft.alt}}</span>
<span class="col-xs-1 small col-padding-shift-right text-muted"> <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-ascent"></span>{{aircraft.vspeed}}</span>
<span ng-show="aircraft.vspeed < 0"><span class="fa fa-descent"></span>{{0-aircraft.vspeed}}</span> <span ng-show="aircraft.vspeed < 0"><span class="fa fa-descent"></span>{{0-aircraft.vspeed}}</span>
</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">{{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"><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.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> <span class="col-xs-2 text-right">{{aircraft.ageLastAlt.toFixed(1)}}<span style="font-size:50%">s</span></span>
</div> </div>
</div> </div>
</div> </div>
<div class="panel-body traffic-footer"> <div class="panel-body traffic-footer">
<div class="separator"></div> <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> <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>
</div> </div>
<!-- <!--
<div class="col-sm-12"> <div class="col-sm-12">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading">Raw Traffic Data</div> <div class="panel-heading">Raw Traffic Data</div>
<div class="panel-body"> <div class="panel-body">
<pre>{{raw_data}}</pre> <pre>{{raw_data}}</pre>
</div> </div>
</div> </div>
</div> </div>
--> -->

Wyświetl plik

@ -1,10 +1,10 @@
<div class="section text-left help-page"> <div class="section text-left help-page">
<p>The <strong>Weather</strong> page provides a list of recent reports received.</p> <p>The <strong>Weather</strong> page provides a list of recent reports received.</p>
<p>There are two lists available for reference:</p> <p>There are two lists available for reference:</p>
<ul> <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>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> <li><strong>Recent Reports</strong> contains the most recent 10 reports received of any type for any location</li>
</ul> </ul>
<p><span class="fa fa-asterisk icon-blue"></span> The Watch List setting is found on the <strong>Settings</strong> page.</p> <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> <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> </div>

Wyświetl plik

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