Porównaj commity

...

1731 Commity

Autor SHA1 Wiadomość Data
crewdogelectronics 36b5045554
Update README.md
I was today years old when I learned software gets deprecated not depreciated.
2024-09-24 11:55:10 -06:00
crewdogelectronics ea492efca5
Update README.md 2024-09-23 13:17:11 -06:00
crewdogelectronics 5230289042
Update README.md 2024-09-22 22:27:42 -06:00
crewdogelectronics 2844766179
Update README.md 2024-09-22 21:40:51 -06:00
crewdogelectronics 2ce453289c
Update README.md 2024-09-22 21:33:44 -06:00
crewdogelectronics 03312cff4f
Update README.md 2024-09-22 21:25:45 -06:00
crewdogelectronics e90076cae0
Update README.md 2024-09-22 21:19:15 -06:00
crewdogelectronics 4f67598acd
Update README.md 2024-09-22 20:53:16 -06:00
Helno eec0b15d4a
Update README.md 2023-02-26 15:59:49 -05:00
Helno 2d421310bd
Update README.md
Updated pi compatibility statement.
2023-02-26 15:59:33 -05:00
Eric Westphal ec997fbf98
Merge pull request #829 from cyoung/revert-824-bmx160
Revert "Add support for bmx160 MPU"
2020-12-19 09:02:26 -06:00
Eric Westphal ac357d8a28
Revert "Add support for bmx160 MPU" 2020-12-19 10:01:42 -05:00
Helno fb1ef310f5
Merge pull request #824 from westphae/bmx160
Add support for bmx160 MPU
2020-12-16 20:48:08 -05:00
Eric Westphal d9a19c0a7f Add support for bmx160 MPU 2020-11-21 20:28:08 -06:00
cyoung 7eeb32acf6
Merge pull request #817 from cyoung/icm20948
ICM-20948 support.
2020-08-19 16:27:04 -04:00
cyoung e949daed02
Merge pull request #816 from jtremolo/add_dark_mode
Add dark mode
2020-08-19 11:59:53 -04:00
Jordan T b28b002e6b Dynamically change theme css 2020-08-19 10:40:07 -05:00
Jordan T 4241d2a17e Add dark mode switch 2020-08-19 10:38:29 -05:00
Jordan T 463721c93b Add dark mode setting storage 2020-08-19 10:38:19 -05:00
Jordan T fb7a09ba3e Add dark mode switch 2020-08-19 10:38:19 -05:00
Jordan T eb4fc67e22 Move embedded styling to css 2020-08-19 10:36:17 -05:00
cyoung cf28a07c9f
Merge pull request #756 from PepperJo/showheightWGS84
Website: Add height above ellipsoid
2020-05-15 15:21:56 -04:00
cyoung 8859b26653
Merge pull request #794 from wcas/wac/improve-ownship-report-v2
Improve ownship detection for EFBs that care
2020-05-15 15:19:27 -04:00
cyoung e0a22baeac
Merge branch 'master' into wac/improve-ownship-report-v2 2020-05-15 15:19:00 -04:00
cyoung 89e158d29b
Merge pull request #801 from lyusupov/master
UDEV rule for SoftRF Dongle Edition
2020-05-15 15:07:57 -04:00
cyoung 5a47671866
Merge pull request #802 from MatthewH-code/master
Added setting "NoSleep" to disable sleeping
2020-05-15 15:07:06 -04:00
cyoung 1da3dd81f4
Merge pull request #803 from Desarrolloscr/master
Missing closing bracket
2020-05-15 15:06:26 -04:00
cyoung c4e00ccf46
Merge pull request #808 from Blaumeiser/patch-1
Update README.md
2020-05-15 15:05:55 -04:00
cyoung 9db076f8d3 Clean up old Stratus AHRS RE tools.
FF opened their AHRS-over-GDL90, not needed.
2020-04-14 11:07:19 -04:00
cyoung d85695e842 Update goflying module. 2020-03-27 11:25:43 -04:00
Blaumeiser ba27147404
Update README.md
Add Pilots Atlas in the Apple AppStore to the list of supported Apps. I'm the developer of the Pilots Atlas App.
2020-03-01 11:49:32 +01:00
cyoung 8698e90f0a Merge branch 'master' into icm20948 2020-01-15 21:45:24 -05:00
cyoung 6d470ac0f8 Add ICM-20948 sensor module and detection. 2020-01-15 11:51:06 -05:00
Jonathan 115c4c3373 Missing closing bracket 2020-01-07 19:45:19 -06:00
matthewh628 1738345af5 Added setting "NoSleep" to disable sleeping 2020-01-03 10:22:25 -06:00
Linar Yusupov 2a0f638f63
UDEV rule for SoftRF Dongle Edition 2020-01-02 18:22:57 +03:00
cyoung 37911bc692 Remove dhcpd file before creating new symlink. 2019-12-21 12:40:46 -05:00
cyoung be93f4290c Add WiFi "Smart Mode" option.
No default gateway. Allows iOS to choose internet source (cellular or WiFi).
2019-12-21 12:32:02 -05:00
William Castillo 1c92f75c4d Improve ownship detection for EFBs that care 2019-10-27 11:58:18 -05:00
cyoung eebe80d3c7
Merge pull request #793 from wcas/wac/fix-ownship-report
Fix Ownship Target Identity Information
2019-10-14 11:56:04 -04:00
William Castillo cac8dd98d4 Fix Ownship Target Identity Information 2019-10-13 22:23:38 -05:00
cyoung 93de565e4b Pass i2cbus parameter for NewMPU9250(). 2019-09-24 14:05:18 -04:00
cyoung 377d22b403 Remove constant "No suitable device found." log message when no GPS found.
Debug only now.
2019-08-12 16:21:21 -04:00
cyoung 4afdebbc5a Comments on /getSituation AHRS fields. 2019-07-04 13:50:05 -04:00
cyoung ab6b11554c Move "GPS serial connection in use" log print to DEBUG only.
#772.
2019-06-05 10:09:08 -04:00
Helno 88ad123672
added G450 to the jet tests list. 2019-05-04 18:14:28 -04:00
cyoung 50e2b3c997 Typo fix. 2019-04-08 12:42:35 -04:00
cyoung 9afe00dbc7 Add ublox9 handling (same as ublox8) for testing. 2019-04-08 12:20:03 -04:00
cyoung 9e211d849d Use ownship received traffic. 2019-04-02 10:12:32 -04:00
cyoung e162742d68 Clean up dhcpd.conf. 2019-03-20 10:06:07 -04:00
cyoung 3ce29823ed Clarify Pi 3 B+. 2019-02-24 18:04:49 -05:00
cyoung 41383ced4e Clarify sleep mode behavior. 2019-02-05 23:17:48 -05:00
cyoung 8f4a52d739 Call `gracefulShutdown()` before reboot.
Fixes #717.
2019-02-01 16:06:22 -05:00
cyoung 39bb2e3415 Add min/max observed CPU temps.
#728.
2019-01-31 11:45:21 -05:00
cyoung 7026f1975a AUXSV parsing for UAT message types 1,2,5,6. Calculate GnssDiffFromBaroAlt.
#721.
2019-01-31 10:32:35 -05:00
cyoung 5593f389cd Config anonymous SDR to 1090 by default when uatradio is present. 2019-01-31 09:37:29 -05:00
cyoung 659e7860a2 Don't duplicate gen_gdl90 messages in syslog general log.
#765.
2019-01-17 17:09:23 -05:00
cyoung 362a2ffb39 Add stratux logrotate conf.
#765.
2019-01-17 16:56:51 -05:00
cyoung bcceaab2ee Handle multiple signals.
#765.
2019-01-17 16:54:34 -05:00
cyoung 73ae89d137 Re-open logfile on SIGHUP for log rotation.
#765.
2019-01-17 16:49:04 -05:00
cyoung e5916be472 Clean up /root/stratux-update after update. 2018-11-16 16:29:28 -05:00
cyoung 24a5d552c4 Add chmod for permissions on certain files for update. 2018-11-13 19:30:26 -05:00
cyoung 8544d6926f Add prometheus metrics to fancontrol. 2018-11-13 19:24:12 -05:00
cyoung 7aa986fbab Allow AHRS output when GPS fix not valid but in developer mode. 2018-10-29 08:36:58 -04:00
cyoung 9a495c964a Use "GPS fix valid" condition instead of GPS ground track valid for isAHRSValid(). 2018-10-29 08:34:46 -04:00
PepperJo 5974fd2266 Website: Add height above ellipsoid
Add GPS height above WGS-84 ellispoid to the website.

Signed-off-by: PepperJo <pepperjo@japf.ch>
2018-10-24 21:34:54 +02:00
cyoung 1756f77433
Merge pull request #751 from westphae/ahrs_warnings
AHRS Warnings and disable AHRS output when GPS not available, fixes #732.
2018-10-01 13:59:51 -04:00
Eric Westphal 5495b8b265 Add warning messages for pseudo-AHRS and no AHRS 2018-09-30 22:40:45 +00:00
Eric Westphal 9b5c850d9e Enable Connected indicators on Towers and GPS/AHRS web UI pages 2018-09-30 18:23:43 +00:00
Eric Westphal 7a31db058e Remove Calibrate Gyros from Settings page of web UI 2018-09-30 01:56:06 +00:00
Eric Westphal da66dc5461 Merge remote-tracking branch 'cyoung/master' into ahrs_warnings 2018-09-29 21:57:53 +00:00
Eric Westphal de865c6961 Add Gyro Calibration button to AHRS page in web UI 2018-09-29 21:57:30 +00:00
Eric Westphal b42350f1cf ahrs.js code cleanup, improve ahrs error display 2018-09-29 18:46:34 +00:00
cyoung 7340719ae3
Merge pull request #734 from westphae/wifi
Wifi Configuration on Settings Page
2018-09-29 10:08:30 -04:00
Eric Westphal 3b32df7f39 Display AHRS ground mode warning in web UI 2018-09-29 11:06:54 +00:00
cyoung 3d168d0c6c Link against math lib for lowpower_uat.go. 2018-09-27 16:02:59 -04:00
cyoung 5ed17d968a Cleanup. 2018-09-27 15:58:41 -04:00
cyoung ceb9a7dc1a
Merge pull request #750 from cyoung/newradio
Add new UAT radio support.
2018-09-27 15:54:08 -04:00
cyoung b10b1769d8 Merge branch 'master' into newradio 2018-09-27 15:15:39 -04:00
cyoung cd4b756810 Add log output. Change SDR count only for interface. 2018-09-27 14:23:03 -04:00
cyoung 517ad79632 Imports/unused variable fix. 2018-09-27 11:40:22 -04:00
cyoung 96338b413d Add /dev/uatradio on a one second interval. 2018-09-27 11:33:47 -04:00
cyoung beed8e7c1a Remove debug logging. 2018-09-27 11:11:44 -04:00
Helno 77fffa5f13
Update README.md 2018-09-25 19:27:12 -04:00
cyoung d0b447dc7a Add SoftRF udev rules and "ping" code hack (temporary). 2018-09-12 10:09:08 -04:00
cyoung c612444a79 Revert 0d93623b94. 2018-09-11 16:05:40 -04:00
Helno 4f9a02d567
update readme
Remove line about dangerzone and added kwikEFIS to the list of apps that support Stratux
2018-09-04 15:07:06 -04:00
cyoung 260a14ca4c Adds AU tail number decoding from ICAO addr.
Contribution by @armeniki. #736.
2018-08-15 15:02:52 -04:00
cyoung 6c0f75de77 Merge branch 'newradio' of https://github.com/cyoung/stratux into newradio 2018-08-13 22:52:03 -04:00
cyoung 578148e5f2 Change to stratux/serial. 2018-08-13 22:52:01 -04:00
cyoung 2bf1bb6dba Merge remote-tracking branch 'refs/remotes/origin/master' into newradio 2018-08-08 13:04:20 -04:00
Eric Westphal 65e80816c2 Merge branch 'master' into wifi 2018-08-05 22:24:25 -04:00
cyoung 8d9fdd31f7 Add info to main status help page.
Fixes #728.
2018-07-30 10:43:33 -04:00
cyoung 4b0f7f47cf Scope error fix. 2018-07-13 12:03:36 -04:00
cyoung 8703b4c124 Don't relay uncorrectable (rs_errors=9999) messages. 2018-07-10 17:42:44 -04:00
cyoung b0821576fb Merge branch 'master' into newradio 2018-07-10 11:42:44 -04:00
cyoung 6df88abc72 Increase suggested wait time on updates. 2018-06-26 09:39:37 -04:00
cyoung 898463e2ef Merge remote-tracking branch 'refs/remotes/origin/master' into newradio 2018-06-22 14:26:15 -04:00
cyoung 0d93623b94 Comment out ublox8 Glonass / Galileo code. 2018-06-13 15:11:06 -04:00
cyoung fbb64a4345 Cleanup. Add /dev/uatradio rule. 2018-06-13 15:10:11 -04:00
cyoung 2dca39c7d8 Add udev rules. Change start-up sequence (fixes race condition -- receiving UAT packets before init is complete). 2018-06-11 19:02:38 -04:00
cyoung 7142edb3ba Restore RSSI/timestamp parsing. 2018-06-11 16:56:14 -04:00
cyoung 462de2843f Revert back to FEC calculating code. 2018-06-11 16:50:33 -04:00
cyoung 8082df9752 Merge remote-tracking branch 'refs/remotes/origin/master' into newradio 2018-06-11 16:48:42 -04:00
cyoung 8eeb20a9df
Merge pull request #720 from westphae/gyro-heading-fix
Fix gdl90 AHRSGyroHeading reporting.
2018-05-29 18:53:36 -04:00
Eric Westphal 006824ef8d Fix gdl90 AHRSGyroHeading reporting. 2018-05-28 08:30:32 -04:00
cyoung 164b00396f Remove FEC computations on Pi side. 2018-05-21 14:27:34 -04:00
cyoung c0127928af Fan control failsafe temp.
#663
2018-05-10 22:42:41 -04:00
cyoung d8a9d5c1a3 Add signal strength and timestamp parsing. 2018-05-01 13:41:31 -04:00
cyoung 2e8ed95506 Clean up obsolete dangerzone includes. 2018-04-26 14:54:12 -04:00
cyoung b9ac1a394a Initial testing code. 2018-04-25 16:08:46 -04:00
cyoung 92dab38028 gen_gdl90 gracefulShutdown() on system shutdown or reboot request. 2018-04-19 10:37:30 -04:00
cyoung 991f48eaa5 Update ForeFlight version to 10+ for AHRS support. 2018-04-10 16:10:33 -04:00
cyoung ddbd3d5ef8 Change ForeFlight support note in README. 2018-04-06 15:10:17 -04:00
cyoung 54ab7df155 Add new ForeFlight AHRS and ID GDL90 messages. 2018-04-06 15:08:45 -04:00
cyoung 14a21eaa0b RPi3B+ setup. 2018-03-29 22:32:40 -04:00
cyoung 915391fa91 Use "N" or "C" regs derived from Mode-S identifier, or default to "Stratux". 2018-03-09 09:49:03 -05:00
cyoung 99ac28b104 Roll back changes. 2018-01-26 11:15:55 -05:00
cyoung 7338ad4336 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	selfupdate/makeupdate.sh
2018-01-26 10:48:55 -05:00
cyoung cd875f6449 Merge remote-tracking branch 'refs/remotes/origin/ahrs_dev_protocolfun' 2018-01-26 10:44:39 -05:00
cyoung 6a40d979b7 Make PPM setting a developer option.
#79.
2018-01-17 14:10:24 -05:00
cyoung da28af53c0 Simplify "Settings" page.
Only display "Hardware" and "Diagnostic" settings when in developer mode.
2018-01-17 10:55:09 -05:00
cyoung 1a1cf2e93c Delete /var/log/stratux* on update. 2018-01-17 10:33:13 -05:00
cyoung a1ea17e7ca Remove unnecessary debug print. 2018-01-09 16:30:28 -05:00
cyoung 95a80395fd Change CircleCI to test to build master. 2018-01-09 12:14:32 -05:00
cyoung 2abfdd11af Remove test build from CircleCI config. 2018-01-09 12:04:41 -05:00
cyoung b8e149cb61 Cleanup.
#692
2018-01-09 12:00:55 -05:00
cyoung 8b806b8aad Remove "test" directory from go get in gen_gdl90 make. 2018-01-09 11:58:14 -05:00
cyoung 0eb6014341 Install mercurial on CircleCI. 2018-01-09 11:42:50 -05:00
cyoung 56ac7ee8fc Clean gopath on each CircleCI build. 2018-01-09 11:38:16 -05:00
cyoung 36ea8c0d40 Upgrade golang version in CircleCI from 1.6 to 1.9.2. 2018-01-09 11:19:30 -05:00
cyoung c5314de3f2 Clean up unused imports.
#692
2018-01-09 10:41:13 -05:00
cyoung c4b8216a84 Change error prints to use addSingleSystemErrorf().
#692
2018-01-09 10:40:25 -05:00
cyoung 033c3ca1e4 Use addSingleSystemErrorf() instead of tracking error prints individually.
#692.
2018-01-09 10:09:18 -05:00
cyoung df6f844738 Create function that tracks critical system errors and issues them only once.
#692
2018-01-09 09:57:00 -05:00
cyoung 31b3e83ea6 Remove old libimu.so references in selfupdate. 2017-12-28 16:58:04 -05:00
cyoung 607310af24 Change deleted AvSquirrel/dump1090 submodule to mirror at stratux/dump1090 2017-12-28 16:47:38 -05:00
Christopher Young 08f786b4b0 Add some AHRS and maintenance web calls to documents. 2017-11-29 20:16:29 -05:00
Christopher Young bd10be4f63 Add logrotate conf. Keep two days of logs. Run logrotate on boot. 2017-11-17 11:12:20 -05:00
Christopher Young a3fda2aa3c Turn off wireless power management, from D. DeMartini. 2017-11-10 09:57:29 -05:00
cyoung 16b61a37a9
Merge pull request #678 from Helno/patch-2
update readme.md
2017-11-10 09:51:01 -05:00
Helno 2a6beb8478
update readme.md
added additional jet tests.
2017-11-10 09:46:39 -05:00
Christopher Young a0d9a4be25 Merge branch 'master' into ahrs_dev_protocolfun 2017-10-31 22:56:14 -04:00
cyoung bb9cb778d2 Update system uptime warning format. 2017-10-27 16:05:15 -04:00
cyoung cc4127df80 Remove socket listener from fancontrol. Replace with http server. Serve status in JSON format. 2017-10-23 14:58:24 -04:00
cyoung bb9c3c6435 Add NightMode to turn off ACT LED.
#659.
2017-10-17 17:30:03 -04:00
cyoung f28bfffc0a Turn off PPS output (green LED on GPYes).
#659.
2017-10-17 17:23:54 -04:00
cyoung b3ca828086 Use estimate vAcc = 2*hAcc instead of reported vAcc.
Fixes #666.
2017-10-17 16:26:11 -04:00
cyoung b7beee37f0 Change luma usage.
#672.
2017-10-17 14:42:19 -04:00
cyoung 0d4d61cf56 Update oled package to new 'luma' package name.
Fixes #672.
2017-10-17 14:40:01 -04:00
cyoung 9a3fe7c0d1 Clean up log output. 2017-10-12 13:21:55 -04:00
cyoung 8bc7f0c093 Add Merlin auto-detect. 2017-10-12 12:22:52 -04:00
Christopher Young 3b57564490 Cleanup. 2017-10-11 13:37:37 -04:00
Christopher Young 04e6d6af36 Merge branch 'master' into ahrs_dev_protocolfun 2017-10-11 13:29:31 -04:00
Christopher Young 022545dde6 Merge branch 'master' into ahrs_dev_protocolfun
# Conflicts:
#	selfupdate/makeupdate.sh
#	selfupdate/update_footer.sh
2017-10-11 13:18:36 -04:00
Christopher Young 157e456805 Change goflying version. 2017-10-11 13:18:26 -04:00
cyoung 782f22cf54 Update goflying. 2017-10-11 09:22:15 -04:00
cyoung 3ef0c4b31a Update goflying. 2017-10-11 09:20:32 -04:00
cyoung 7ac2aa7478 Move to cyoung/goflying, 'stratux_master' branch. 2017-10-11 09:11:45 -04:00
cyoung 57c783d695 Typo fix. 2017-10-11 08:56:30 -04:00
cyoung 2df716f2f6 Remove unused 'CPULoad' status variable. 2017-10-11 08:40:10 -04:00
cyoung 4fa548b380 stratux.log cleanup. 2017-10-11 08:39:09 -04:00
cyoung b695353d44 Install dhcpd.conf and interfaces file. 2017-10-11 08:33:11 -04:00
cyoung 62b6df682b Remove sqlite log and stratux.log on update. 2017-10-11 08:23:57 -04:00
cyoung 4da6af1905 Add dhcpd.conf and interfaces files to .sh update. 2017-10-11 08:07:30 -04:00
Christopher Young 4de2420803 Clean up cputemp. 2017-10-10 11:27:15 -04:00
Christopher Young ae734f41ba Adapt `ffMonitor()` to ahrs_approx - only send the FF AHRS packets when FF is detected. 2017-10-10 10:05:40 -04:00
Christopher Young fc0fe317ab Merge remote-tracking branch 'origin/master' into ahrs_dev_protocolfun 2017-10-10 09:56:28 -04:00
cyoung 2fc134aa38 Update EFB documentation. 2017-09-26 14:45:36 -04:00
cyoung be67f51eab Remove ahrs_dev branch deployment rule. 2017-09-22 12:49:47 -04:00
cyoung 269ef27b50 Fix outdated imports. Cleanup. 2017-09-22 11:42:57 -04:00
cyoung abe84edfae Fix circleci build test - outdated imports in test/maxgap.go. 2017-09-22 11:20:15 -04:00
cyoung 7f6f1394e0 Activate config change block for $OPT_P (-p option).
Ref #667.
2017-09-22 10:55:54 -04:00
Christopher Young f422ae6578 Remove test CircleCI build. 2017-09-12 10:33:30 -04:00
Christopher Young 2017adf78b Remove tests from "go get".
Tests aren’t automatically built.
2017-09-12 10:20:58 -04:00
Christopher Young 05aa90b125 Clean up fancontrol.
Working on #663.
2017-09-12 08:56:31 -04:00
Christopher Young f8646d9ebe Check system uptime before SDR startup delay.
Throw a system error in developer mode if the uptime is greater than
120s and `sdrWatcher()` is restarted (usually a systemd restart).
2017-08-18 12:56:58 -04:00
Christopher Young 94c6e5a353 Add alias for 192.168.10.1 for normal webui access. 2017-08-15 17:25:53 -04:00
Christopher Young 5ddadfa78d Merge remote-tracking branch 'origin/master' into ahrs_dev_protocolfun 2017-08-15 16:28:45 -04:00
cyoung 032849fab0 Merge pull request #657 from cyoung/ahrs_dev
Sync master with ahrs_dev (minor webui changes).
2017-08-13 16:25:03 -04:00
Christopher Young 28710b59cc Merge remote-tracking branch 'origin/master' into ahrs_dev 2017-08-13 16:24:18 -04:00
Christopher Young 31abc00910 Delay SDR startup by 1m30s. 2017-08-07 16:50:44 -04:00
Christopher Young 36454ad743 Update goflying. 2017-08-04 00:10:24 -04:00
Christopher Young 046dc54f27 Update goflying. 2017-08-03 23:09:11 -04:00
Christopher Young fcf524b03c Merge remote-tracking branch 'origin/master' into ahrs_dev_protocolfun 2017-08-03 23:08:45 -04:00
Eric Westphal 945724c907 Slightly different regex's in javascript validation. 2017-07-30 12:38:44 -04:00
Eric Westphal ed7c1475c2 Merge branch 'master' of github.com:westphae/stratux 2017-07-29 10:41:28 -04:00
Eric Westphal c319d49e74 Angular validation on settings page. 2017-07-29 10:40:29 -04:00
Christopher Young 4b66b518f1 Add link in README to EFB integration guide. 2017-07-22 22:34:35 -04:00
Eric Westphal d48691bdac Fix .js and .html permissions. 2017-07-22 17:04:30 -04:00
Eric Westphal 034e38d4e7 Formatting; re-do grayout of disabled text boxes. 2017-07-22 16:03:35 -04:00
Eric Westphal be692f7a84 Merge remote-tracking branch 'peeps/patch-2' into peeps 2017-07-22 15:31:37 -04:00
peepsnet 8932abf342 Removed Confirm Modal and cleaned up modals 2017-07-22 14:49:15 -04:00
peepsnet dd9afdac33 error checking in SSID and WPA Passphrase 2017-07-22 14:48:11 -04:00
Eric Westphal e96694ced2 Merge remote-tracking branch 'cyoung/master' into ahrs_dev 2017-07-22 13:34:55 -04:00
Eric Westphal c406c344aa Grey out settings text boxes when disabled. 2017-07-22 13:22:58 -04:00
Eric Westphal cc24fb6fef Added Go portion of @peepsnet WiFi handling. 2017-07-22 12:43:32 -04:00
Eric Westphal e5631bd38f A few more changes from @peepsnet. 2017-07-21 17:03:16 -04:00
Eric Westphal 7e74615ce6 Remove hostapd_manager_quiet.sh per @peepsnet. 2017-07-21 16:00:37 -04:00
Eric Westphal ef3c8d526a Whitespace fixes 2017-07-20 17:35:55 -04:00
Eric Westphal 57a1bd9c7c Merge remote-tracking branch 'cyoung/master' into peeps 2017-07-20 17:30:09 -04:00
Eric Westphal be066a67bc Merge remote-tracking branch 'cyoung/ahrs_dev' into ahrs_dev 2017-07-20 17:09:55 -04:00
Eric Westphal 8fadfe0602 Formatting and spelling. 2017-07-18 19:29:50 -04:00
Eric Westphal 5463d334c4 Merge remote-tracking branch 'peeps/master' into peeps
Added new settings from ahrs_dev branch back in.
2017-07-18 18:32:02 -04:00
Christopher Young f6bad36cdc Update README. 2017-07-17 17:49:40 -04:00
cyoung 67058e7ae5 Merge pull request #641 from cyoung/ahrs_dev
AHRS for v1.4r1.
2017-07-17 17:45:31 -04:00
Christopher Young 0d833946f4 Remove redeclared variables. 2017-07-17 17:36:43 -04:00
Christopher Young 284bb0733f Remove redeclared structs. 2017-07-17 17:35:10 -04:00
Christopher Young 6709c9b4e6 Merge remote-tracking branch 'origin/master' into ahrs_dev
# Conflicts:
#	main/gen_gdl90.go
2017-07-17 17:18:12 -04:00
cyoung 68ceffd8f5 Merge pull request #635 from peepsnet/patch-1
Added allow-hotplug eth0
2017-07-17 10:14:49 -04:00
cyoung 765417b7bc Merge pull request #638 from drnic/patch-1
[docs] change snippet to 'javascript' for github markdown
2017-07-17 10:14:02 -04:00
Dr Nic Williams 5cce0a3f30 change snippet to 'javascript' for github markdown
github markdown `json` format doesn't accept comments; but luckily `javascript` format does. This change makes the docs look nice in github.
2017-07-16 19:26:59 +10:00
Eric Westphal aa74554a81 Change sensor switch names. 2017-07-15 22:06:26 -04:00
Eric Westphal 218c312b98 Better initialization of gLoad, slipSkid, rateOfTurn. 2017-07-14 16:46:03 -04:00
peepsnet 3148f810c3 Update __root__stratux-pre-start.sh 2017-07-14 14:47:01 -04:00
peepsnet 8ff30f0980 Set theme jekyll-theme-time-machine 2017-07-14 14:43:09 -04:00
peepsnet ff3e901501 Update __root__stratux-pre-start.sh 2017-07-14 14:29:13 -04:00
peepsnet 95f4d0a278 Update main.js 2017-07-13 09:13:14 -04:00
Eric Westphal 1877e66056 Ensure level signal doesn't block cal channel. 2017-07-12 22:20:23 -04:00
peepsnet 57c6c8ee8b look and feel 2017-07-12 21:13:52 -04:00
Eric Westphal 20877df847 Separate gyro calibration and AHRS level functions. 2017-07-12 13:27:26 -04:00
peepsnet 10475445fd added allow-hotplug eth0
Seems this is useful now that we have the static IP option in developers
2017-07-11 21:07:40 -04:00
peepsnet ed53ecf3d8 typo 2017-07-10 23:01:22 -04:00
peepsnet 5d13c10a58 Updated Help also 2017-07-10 22:56:39 -04:00
peepsnet f5e1ec828f Tweak look feel 2017-07-10 21:42:28 -04:00
peepsnet dca880738d class to grey out div 2017-07-10 20:40:26 -04:00
peepsnet f42bb4d47f cleaned up application constants 2017-07-10 20:39:25 -04:00
peepsnet dc14b9dd80 HTML/JS Prop for WiFI Settings
added js code for error checking and formatting the JSON string for the call to /setSettings
{"WiFiSSID":"stratux","WiFiSecurityEnabled":true,"WiFiPasscode":"h98tdjepi","WiFiChannel":"5"}

 $scope.WiFiSSID = "stratux"; //settings.WiFiSSID;
 $scope.WiFiSecurityEnabled = true; //settings.WiFiSecurityEnabled;
$scope.WiFiPasscode = Math.random().toString(36).substring(4); //settings.WiFiPasscode;
$scope.WiFiChannel = "5"; //settings.WiFiChannel;    

I have hardcoded the values till they are included in the /getSettings JSON string
2017-07-10 20:38:22 -04:00
peepsnet aad4dc53ec HTML/JS Prep for WiFi Settings and StaticIP value fix
FIrst, I added the missing code to pull in the Static IP info the input field from the JSON string

Second and biggest:
This is the code to add the WiFi Settings to the Settings Page. In preparation for the GO code behind the scenes

Before it is live/working a few lines should be removed and the modals cleaned up. 

I had some issues getting the ng-bind working in the modalErrorWiFi modal. There is an update issue. Something about being outside of the digest.  I'm not sure.

The code sends a JSON string:  {"WiFiSSID":"stratux","WiFiSecurityEnabled":true,"WiFiPasscode":"h98tdjepi","WiFiChannel":"5"} to /setSettings

I also did some cleanup in the HTML.
2017-07-10 20:32:40 -04:00
Eric Westphal 90c10195fb Minor log message change. 2017-07-09 17:48:35 -04:00
peepsnet e43f09395f added hostpad_manager_quiet.sh 2017-07-08 18:55:57 -04:00
peepsnet d47bea63c9 added hostpad_manager_quiet.sh 2017-07-08 18:55:07 -04:00
peepsnet 4d26ba2c48 added hostpad_manager_quiet.sh 2017-07-08 18:54:07 -04:00
peepsnet 3bd913ecb6 added hostpad_manager_quiet.sh 2017-07-08 18:52:46 -04:00
peepsnet c8c43e6638 A quiet hostpad_manager script for app calls
# This script is almost identical to hostapd_manager.sh except all the
# screen outputs are supplressed except for error messages. 
#
# Usage:
# hostapd_manager_quiet.sh -s Stratux-N12345 -p SquawkDirty! -c 5
# Command above sets the SSID to "Stratux-N12345, secures the network with the passphrase "SquawkDirty!, and changes the network channel to "5"
#
# hostapd_manager_quiet.sh -o
# Command above opens the network(removes any passphrase)
#
# hostapd_manager_quiet.sh -e
# Command above secures the WiFi network using the default passphrase "SquawkDirtyToMe!"

# Options:
# -s	--Sets the SSID to ${BOLD}ssid${NORM}. -s stratux
# -c	--Sets the channel to chan. -c 1
# -o	--Turns off encryption and sets network to open. Cannot be used with -e or -p.
# -e	--Turns on encryption with passphrase SquawkDirtyToMe!. Cannot be used with -o or -p
# -p	--Turns on encryption with your chosen passphrase pass. 8-63 Printable Characters(ascii 32-126). Cannot be used with -o or -e. -p password!
#
# Important:
# After each call of this script the wifi network will disconnect and restart all associated services to apply the changes
2017-07-08 18:49:23 -04:00
peepsnet 6e9c86eeb6 Merge pull request #10 from cyoung/master
update
2017-07-08 17:57:21 -04:00
Eric Westphal 21278eb265 Level uses calibration accels, retry ccal if nonsense values. 2017-07-08 14:52:10 -04:00
Eric Westphal 572c1d08a5 Minor reorganization. 2017-07-08 13:50:46 -04:00
Eric Westphal 5926b05757 Deleting AHRS logs no longer stops all AHRS logging. 2017-07-07 21:24:49 -04:00
Eric Westphal 5c66d14d00 Re-word AHRS orientation dialog boxes. 2017-07-07 19:56:45 -04:00
Eric Westphal e0faa71b3f Remove 'up' section from orientation procedure. 2017-07-06 19:45:01 -04:00
Eric Westphal ccf04867fb Reduce AI pitch scale. 2017-07-06 19:43:32 -04:00
Christopher Young 0788d4a1a6 Add ahrs_dev deployment circleci rule. 2017-07-06 16:00:09 -04:00
Eric Westphal 4d3235fb4b Minor variable reorganization. 2017-07-04 13:31:04 -04:00
Eric Westphal 1bf2a9d808 Developer UI page allows downloading and deleting AHRS logs. 2017-07-03 19:43:51 -04:00
Eric Westphal e657a400f8 Elongate all the 5 deg marks on AI. 2017-07-01 17:32:23 -04:00
Eric Westphal 5f8ac80ac3 Move sensor orientation quaternion into AHRSProvider. 2017-07-01 17:19:27 -04:00
Eric Westphal 60a4e74503 Ensure AHRS level occurs after orientation. 2017-06-28 20:49:55 -04:00
Eric Westphal d854fb01be Update settings display on web UI after orientation. 2017-06-28 19:09:45 -04:00
Eric Westphal 2a132bb9cc Pass empty initial orientation to NewSimpleAHRS. 2017-06-28 19:08:55 -04:00
Eric Westphal e2c6fa26af Rename InitializeSimple to NewSimpleAHRS. 2017-06-25 11:36:57 -04:00
Eric Westphal b4f437aa3d Remove some old AHRS logging. 2017-06-24 15:51:13 -04:00
Eric Westphal 22fe8cddbe G Load min value doesn't start near zero. 2017-06-24 15:12:10 -04:00
Eric Westphal 993e0c946f Remove unused import. 2017-06-24 14:59:23 -04:00
Eric Westphal fef0ed466f Fix some bad initializations. 2017-06-24 14:46:47 -04:00
cyoung 771a1fe8a8 Merge pull request #625 from cyoung/ahrs_dev
Ahrs dev
2017-06-23 10:48:07 -04:00
Eric Westphal 74909ada85 Ensure SensorQuaternion synced with IMUMapping. 2017-06-22 19:47:25 -04:00
Eric Westphal a2bba208b6 Sensor orientation more reliable. 2017-06-21 22:05:44 -04:00
Eric Westphal c6e01d2ec6 Variable name change. 2017-06-21 22:02:59 -04:00
cyoung af317bc834 Merge pull request #624 from cyoung/ahrs_dev
Ahrs dev
2017-06-21 11:43:47 -04:00
cyoung 3871279473 Merge pull request #619 from jamez70/move_structs
Move structs to the top of the file
2017-06-14 10:33:44 -04:00
Eric Westphal 542a68fc26 Remove AHRS config from developer settings. 2017-06-13 18:14:08 -04:00
Eric Westphal b7cd14debb AHRS algorithm improvements 2017-06-13 17:54:25 -04:00
Eric Westphal 7af6f20884 Maybe make the orientation process more consistent. 2017-06-13 17:48:34 -04:00
Jim Jacobsen 545343332e Move structs to the top of the file 2017-06-11 17:50:34 +00:00
Christopher Young 51fd728cc6 Merge fix. 2017-06-09 10:54:41 -04:00
Christopher Young fd7ce1ec92 Merge remote-tracking branch 'origin/master' into ahrs_dev
# Conflicts:
#	main/gen_gdl90.go
2017-06-09 10:53:41 -04:00
Christopher Young 5f1ebfbe70 Removed ForeFlight GDL90 parsing bug workaround.
#348, 604.
2017-06-09 10:49:25 -04:00
Christopher Young 45e8ea90ac Merge remote-tracking branch 'origin/master' into ahrs_dev 2017-06-06 14:54:57 -04:00
Christopher Young 7fd67ccbc1 Stop fancontrol service before replacing binary.
#612.
2017-06-06 14:48:06 -04:00
root b11b23899d Merge branch 'ahrs_dev' into ahrs_dev_protocolfun 2017-06-05 20:52:02 +00:00
root 4c6573e103 Merge remote-tracking branch 'origin/ahrs_dev_protocolfun' into ahrs_dev 2017-06-05 20:51:44 +00:00
Christopher Young 23921ee384 Type fix. 2017-06-05 16:49:52 -04:00
root 11e09dcf5b Merge branch 'ahrs_dev' into ahrs_dev_protocolfun 2017-06-05 20:41:03 +00:00
root 82f2129d60 Merge remote-tracking branch 'origin/ahrs_dev_protocolfun' into ahrs_dev 2017-06-05 20:40:44 +00:00
Christopher Young a82f376ad0 Typo fix. 2017-06-05 16:37:32 -04:00
root e398ea152b Merge branch 'ahrs_dev' into ahrs_dev_protocolfun 2017-06-05 20:34:00 +00:00
root 78404004ab Merge remote-tracking branch 'origin/ahrs_dev_protocolfun' into ahrs_dev 2017-06-05 20:33:42 +00:00
Christopher Young e9e552a149 Use GPSTrueCourse in GDL90 packet as heading when gyro heading not available.
#612
2017-06-05 16:29:28 -04:00
Christopher Young ca4ae22c42 Change float32 types to float64 types to match AHRS library outputs. 2017-06-05 16:19:45 -04:00
Christopher Young 215b6034d6 Typo fix. 2017-06-05 15:06:11 -04:00
Christopher Young 92da285c55 Add isAHRSInvalidValue(). 2017-06-05 15:03:19 -04:00
Christopher Young ac021ebe6a Conslidate 'ahrs.Invalid' constant references. 2017-06-05 14:55:25 -04:00
Christopher Young e43caad938 Typo fix. 2017-06-05 14:48:10 -04:00
Christopher Young 6e184a9ce7 Merge remote-tracking branch 'origin/master' into ahrs_dev 2017-06-04 00:35:53 -04:00
cyoung e2b3529f95 Merge pull request #611 from peepsnet/master
Hostapd_manager.sh, sdr-tool.sh and  .stxAliases updates
2017-06-04 00:35:34 -04:00
Eric Westphal 255c1695e5 Better rejection of weak GPS in SimpleAHRS static mode. 2017-06-03 15:50:05 -04:00
peepsnet da8c3a74fd Restart Stratux on exit
The script will now restart your stratux service if you exit the script before completing.

And some aesthetics things
2017-06-03 11:27:50 -04:00
Eric Westphal 586d951582 Save sensor orientation for pseudo-installed units. 2017-06-01 17:33:18 -04:00
peepsnet 94d8f8813e Update hostapd_manager.sh 2017-06-01 15:20:01 -04:00
Eric Westphal 84d578ff6c Heading slews more quickly when movement begins. 2017-06-01 14:08:49 -04:00
peepsnet 321273f8d4 added an easy alias for securing/opening WiFI
Added "open" and "secure" as aliases to easily open or secure your WiFi

It simply calls the hostapd_manager.sh script with either -o or -e
2017-06-01 10:49:55 -04:00
peepsnet a72219bae5 Added encryption back to script
Help documentation for hostapd_manager.sh.

Basic usage: hostapd_manager.sh -s ssid -c chan -p pass

The following command line switches are recognized.
-s  --Sets the SSID to ssid. "-s stratux"
-c  --Sets the channel to chan. "-c 1"
-o  --Turns off encryption and sets network to open. Cannot be used with -e or -p.
-e  --Turns on encryption with passphrase SquawkDirtyToMe!. Cannot be used with -o or -p
-p  --Turns on encryption with your chosen passphrase pass. 8-63 Printable Characters(ascii 32-126). Cannot be used with -o or -e. "-p password!"
-q  --Run silently. Still a work in progress, but quieter.
-h  --Displays this help message. No further functions are performed.

Example: hostapd_manager.sh -s Stratux-N3558D -c 5 -p SquawkDirty!
2017-06-01 10:28:22 -04:00
peepsnet 95d0b97564 updating to add encryption back.
It seems to work in my testing!!

#### Stratux HOSTAPD Settings ####


Help documentation for hostapd_manager.sh.

Basic usage: hostapd_manager.sh -s ssid -c chan -p pass

The following command line switches are recognized.
-s  --Sets the SSID to ssid. "-s stratux"
-c  --Sets the channel to chan. "-c 1"
-o  --Turns off encryption and sets network to open. Cannot be used with -e or -p.
-e  --Turns on encryption with passphrase SquawkDirtyToMe!{NORM}. Cannot be used with -o or -p
-p  --Turns on encryption with your chosen passphrase pass. 8-63 Printable Characters(ascii 32-126). Cannot be used with -o or -e. "-p password!"
-q  --Run silently. Still a work in progress, but quieter.
-h  --Displays this help message. No further functions are performed.

Example: hostapd_manager.sh -s Stratux-N3558D -c 5 -p SquawkDirtyToMe!
2017-06-01 10:15:23 -04:00
peepsnet b5f18aa529 Merge pull request #9 from cyoung/master
updating
2017-06-01 10:05:45 -04:00
Christopher Young 9c602d97cf Merge branch 'ahrs_dev' into ahrs_dev_protocolfun 2017-05-31 16:19:16 -04:00
Christopher Young 48bccdc81e Merge remote-tracking branch 'origin/ahrs_dev_protocolfun' into ahrs_dev 2017-05-31 16:18:40 -04:00
Christopher Young 0a60929cab Typo fix. 2017-05-31 15:37:14 -04:00
Christopher Young f4144710e9 Update comments. 2017-05-31 15:34:57 -04:00
Christopher Young c0a79700b8 Change calcGPSValidity() to isGPSGroundTrackValid(). Replace existing isGPSGroundTrackValid() function. 2017-05-31 15:33:19 -04:00
Christopher Young 9839e88e71 Merge remote-tracking branch 'origin/master' into ahrs_dev 2017-05-31 15:21:37 -04:00
Eric Westphal db8d2f3e7f Add a bit more AHRS logging. 2017-05-29 20:32:50 -04:00
Eric Westphal 5f5f236b6e AHRSSimple ensures quaternion has correct sign to avoid split S. 2017-05-29 20:23:15 -04:00
Eric Westphal e421d160b7 Base AHRS GPS Validity on NACp. 2017-05-29 15:56:16 -04:00
Eric Westphal c96f3d4844 Extra AHRS logging from external sources. 2017-05-29 15:53:06 -04:00
Eric Westphal 22ad90fb8a Don't show AHRS info when it's invalid. 2017-05-29 15:50:54 -04:00
Eric Westphal fcc9322a57 Remove minor unneeded logging. 2017-05-29 15:44:34 -04:00
Christopher Young 053d60110f Typo fix. 2017-05-25 21:48:23 -04:00
Christopher Young 5bb15527f4 Merge remote-tracking branch 'origin/master' into ahrs_dev_protocolfun 2017-05-24 21:44:28 -04:00
Christopher Young 506db50fb2 Merge remote-tracking branch 'origin/master' into ahrs_dev 2017-05-24 21:44:11 -04:00
Christopher Young c3e4d613ca Remove full speed defaults.
#599, #595, #593.
2017-05-24 21:42:11 -04:00
Christopher Young daee7316f5 Switch from "BAL" mode to "MS" PWM modes. #599, #595, #593. 2017-05-24 13:25:52 -04:00
Christopher Young 4c854999bb Reduce number of fan modes to 10 from 256. Add five second run-up at startup. #599, #595, #593. 2017-05-24 13:24:46 -04:00
Christopher Young 7c33203672 Add missing files from update scripts. 2017-05-23 17:32:36 -04:00
Christopher Young b812c29996 Update make clean. 2017-05-23 17:11:44 -04:00
Christopher Young 93a2d82f96 Update install and auto-start scripts. 2017-05-23 17:06:50 -04:00
Christopher Young 9989b913bc Change IP Stratux IP address and DHCP range. 2017-05-23 17:04:29 -04:00
Christopher Young 7ac549a540 Typo and path fix. 2017-05-23 17:03:11 -04:00
Christopher Young 3f72b1e18b Remove old AHRS replay tools. Add protocol tools. 2017-05-23 16:56:18 -04:00
Eric Westphal 46233e704c Merge branch 'master' into ahrs_dev 2017-05-21 21:52:02 -04:00
Eric Westphal ac386cb0a1 Add AHRS setting defaults to defaultConfig. 2017-05-21 21:51:40 -04:00
Eric Westphal 436a6ccdb2 Merge branch 'gpsnan' 2017-05-21 20:23:05 -04:00
Eric Westphal 9f7775f580 Merge branch 'gpsnan' into ahrs_dev 2017-05-21 20:22:43 -04:00
Eric Westphal 7e89eb0abb G-Meter invalid zone fixed. 2017-05-21 19:12:41 -04:00
Eric Westphal 3e07390bac GPS map transparent and values -- when no GPS fix. 2017-05-21 17:13:42 -04:00
Eric Westphal b89bf75b07 Merge branch 'master' into glimits 2017-05-20 22:20:32 -04:00
Eric Westphal 6b4ab9b1a4 Merge branch 'master' into gpsnan 2017-05-20 22:19:10 -04:00
Eric Westphal 14e5c49e57 Add fancontrol to .gitignore. 2017-05-20 22:04:57 -04:00
Eric Westphal 51d7530208 Web UI shows -- and inf when GPS values missing. 2017-05-20 21:58:51 -04:00
Eric Westphal d69e195489 Use appropriate defaults for AHRS config. 2017-05-20 08:07:41 -04:00
Eric Westphal 4bc1bbe394 Merge branch 'ahrs_dev' 2017-05-20 07:36:07 -04:00
Eric Westphal 5aefc145ac Initial commit - user can set G limits for own aircraft. 2017-05-20 07:35:40 -04:00
Eric Westphal 9ebe32e6e0 Move SetConfig into AHRSProvider. 2017-05-17 19:41:01 -04:00
Eric Westphal 2a1a938194 Change AHRS Smoothness label. 2017-05-17 19:18:41 -04:00
Eric Westphal 9264dd4908 Merge branch 'ahrs_dev' into eric 2017-05-17 18:28:20 -04:00
Eric Westphal 71094ae189 Merge branch 'ahrs_dev' 2017-05-17 18:28:12 -04:00
Eric Westphal a4a7ea1912 Prevent G Meter from resetting on webpage changes. 2017-05-17 18:27:45 -04:00
Eric Westphal 52e61ca48c Merge remote-tracking branch 'cyoung/ahrs_dev' into eric 2017-05-17 18:26:56 -04:00
Eric Westphal 06f0d2d8f9 Merge remote-tracking branch 'origin/master' 2017-05-17 17:56:53 -04:00
Eric Westphal 8aeb5d285b Web UI G-Meter uses mySituation min/max G Load. 2017-05-17 17:55:42 -04:00
Eric Westphal e8273544ae mySituation tracks min/max G Load. 2017-05-17 17:55:42 -04:00
Eric Westphal c1ca21e8fb Web UI G-Meter uses mySituation min/max G Load. 2017-05-17 17:54:32 -04:00
Eric Westphal 20c1e32ff7 mySituation tracks min/max G Load. 2017-05-17 17:32:05 -04:00
Christopher Young 0678955b01 Merge remote-tracking branch 'origin/master' into ahrs_dev 2017-05-17 17:18:30 -04:00
Christopher Young f2c311db6d If temperature rises after ramping to 100% PWM, then stop controlling the fan and set it to full ON.
#599, #595, #593.
2017-05-17 17:18:00 -04:00
Christopher Young 0d146d1747 Set GDL90 traffic alert bit always when bearing/distance is not available. #580, #582. 2017-05-17 15:25:14 -04:00
Christopher Young 83f0c6843f Suppress detected ownship traffic target, but don't use received data for GDL90 ownship message.
#590.
2017-05-17 15:12:22 -04:00
Christopher Young 069cb9e1fc Undo cab2a81.
See commit comments:
cab2a81
9ca4549ba.

A static build of wiringPi is all that is needed to produce the static
binary. Static linking is needed to produce a working binary on current
production images.
2017-05-16 23:50:35 -04:00
Christopher Young fcfe8adeaf Undo cab2a81c26.
See commit comments:
https://github.com/cyoung/stratux/commit/cab2a81c26f214709f8cda941ff8ea1
9ca4549ba.

A static build of wiringPi is all that is needed to produce the static
binary. Static linking is needed to produce a working binary on current
production images.
2017-05-16 23:40:48 -04:00
Eric Westphal 50a0443f74 Merge branch 'ahrs_dev' into eric 2017-05-16 16:57:28 -04:00
Eric Westphal 1e40573d1e Merge branch 'ahrs_dev' 2017-05-16 16:57:17 -04:00
Eric Westphal 8c0364c04a Move NoSleep instance into . 2017-05-16 16:57:08 -04:00
Eric Westphal 28225dc343 Move AHRS Settings into Developer section. 2017-05-16 16:50:54 -04:00
Eric Westphal a0bea25d68 Merge branch 'ahrs_dev' into eric 2017-05-16 15:05:56 -04:00
Eric Westphal d7cafb0a8a Merge branch 'ahrs_dev' 2017-05-16 15:05:35 -04:00
Eric Westphal 4a038f5317 Headings 0-359 and keep app awake in AHRS-only mode. 2017-05-16 15:05:12 -04:00
Eric Westphal 7cd00ce4b5 Merge remote-tracking branch 'origin/master' into eric 2017-05-16 14:34:45 -04:00
Eric Westphal 834eeefc7c Update goflying submodule to compatible version. 2017-05-16 16:04:03 +00:00
Eric Westphal 115edcef28 Update goflying submodule to compatible version. 2017-05-16 16:03:30 +00:00
Eric Westphal a08d269e4c Merge remote-tracking branch 'cyoung/ahrs_dev' into eric 2017-05-16 10:50:19 -04:00
Christopher Young 3db11bd09d Add goflying submodule. Change imports. 2017-05-15 22:22:32 -04:00
Eric Westphal 58389f8ec5 Merge branch 'ahrs_dev' into eric 2017-05-15 20:35:04 -04:00
Eric Westphal cab2a81c26 Revert Makefile back to non-static fancontrol. 2017-05-15 20:34:55 -04:00
Eric Westphal be84ec785c Merge remote-tracking branch 'cyoung/ahrs_dev' into eric 2017-05-15 07:55:23 -04:00
Eric Westphal ea657208c0 Merge remote-tracking branch 'cyoung/ahrs_dev' into ahrs_dev 2017-05-14 09:44:15 -04:00
Eric Westphal d84a3a0199 Merge branch 'invalid' into eric 2017-05-14 09:25:48 -04:00
Eric Westphal 7add14badf Invalidate GDL90 UDP values when AHRS data invalid. 2017-05-14 09:25:11 -04:00
Eric Westphal 84eea16eed Merge branch 'invalid' into eric 2017-05-14 08:17:26 -04:00
Christopher Young 95fe19902a Merge remote-tracking branch 'origin/master' into ahrs_dev 2017-05-13 18:43:54 -04:00
Christopher Young 7ef5efdd6e Make fancontrol a static executable (for systems without wiringPi installed). 2017-05-13 18:43:43 -04:00
Christopher Young c6e96b5d09 Merge remote-tracking branch 'origin/master' into ahrs_dev
# Conflicts:
#	Makefile
#	main/equations.go
#	main/gen_gdl90.go
2017-05-13 12:37:06 -04:00
Christopher Young d242233e6d Ignore errors on 'remove'. #593. 2017-05-13 12:21:41 -04:00
Christopher Young ae03336a0b Reduce CPU temperature target to 50ºC. #593. 2017-05-13 12:16:20 -04:00
Christopher Young eebb040e1e Remove GPS power save mode. 2017-05-13 12:15:42 -04:00
Christopher Young b423c4e48e Change pinout. Increase PWM frequency. Decrease min duty cycle.
#593.
2017-05-13 12:11:31 -04:00
Christopher Young 5a83452c64 Skip fancontrol build on CircleCI - no wiringPi equivalent on x86.
#593.
2017-05-13 11:01:52 -04:00
Christopher Young 200b3fcf57 Add wiringPi to CircleCI install.
#593.
2017-05-13 10:40:56 -04:00
Christopher Young c7f0ed1245 Re-add CircleCI hack.
#593.
2017-05-13 10:35:21 -04:00
Christopher Young 29c86d0343 Formatting.
#593.
2017-05-13 10:33:09 -04:00
Christopher Young 0264383389 Add new fancontrol install to .sh update packager and image maker script.
#593.
2017-05-13 10:24:12 -04:00
cyoung 5ae514e5ce Merge pull request #593 from lukepalmer/master
Rework fan PWM control
2017-05-13 10:15:27 -04:00
Eric Westphal 70236a95da Show --- on web UI when AHRS values invalid. 2017-05-13 08:40:19 -04:00
Eric Westphal 338f1cc934 AHRS settings in the UI 2017-05-12 20:40:53 -04:00
Luke Palmer 01cc01f8fa Rework fan PWM control 2017-05-11 00:32:45 -04:00
Christopher Young a6f9aaf9f5 TEMPORARY: get latest 'goflying' packages in Makefile. 2017-05-10 09:43:57 -04:00
Christopher Young d7ca5b0376 Undo merge typo. 2017-05-10 09:42:20 -04:00
Christopher Young 17b719f755 Merge remote-tracking branch 'origin/master' into ahrs_dev
# Conflicts:
#	main/gps.go
#	main/traffic.go
2017-05-10 09:27:22 -04:00
cyoung 7933b70821 Merge pull request #592 from westphae/master
WebUI and dependency changes.
2017-05-09 10:28:14 -04:00
Eric Westphal 449043bb4a Refactor rotation matrix creation function to westphae/goflying. 2017-05-08 21:21:37 -04:00
Eric Westphal 6127d4f70f Only report turn tate < 10 min/turn on web UI. 2017-04-22 18:37:03 -04:00
Eric Westphal f8187e1383 Report fixed digits for AHRS info on web UI. 2017-04-22 18:20:09 -04:00
Eric Westphal c113876821 Restore GPS uncertainties on web UI. 2017-04-22 18:08:52 -04:00
Christopher Young 7d7c2abe35 Gofmt. Typo fix. Comment change. 2017-04-21 14:16:21 -04:00
cyoung 1934d858de Merge pull request #586 from kjablonski/master
Enable Galileo and updates to stratux-help
2017-04-21 14:08:39 -04:00
kjablonski e3fcadb4ba Update gps.go
Fixed undeclared variable updatespeed
2017-04-21 06:57:18 -05:00
kjablonski a8bd9a28f9 Update gps.go
Added logic to only slow down to 2Hz for UBX8 using Galileo
2017-04-20 21:42:45 -05:00
Christopher Young 176cf42f2e Blink ACT LED ten times per second when there is a system error.
#567.
2017-04-19 17:04:12 -04:00
Christopher Young c0b6e9a93b Set "Maintenance Req'd" bit in GDL90 heartbeat when there exists a system error.
#567.
2017-04-19 16:49:35 -04:00
Christopher Young b431187d7a Use isGPSValid(). 2017-04-19 16:01:29 -04:00
Christopher Young fe7dc97c19 Clean up typos and formatting. 2017-04-19 15:57:25 -04:00
Christopher Young 2645f98293 Cleanup. 2017-04-19 15:51:49 -04:00
Eric Westphal 95ade5a64b Rename Reset AHRS Button for the last time. 2017-04-16 20:13:55 -05:00
Christopher Young 9e12f69318 Add comments on units and constants.
#580, #582.
2017-04-06 11:28:56 -04:00
Christopher Young f564f2bb6b Remove redundant distance calculation. 2017-04-06 11:27:03 -04:00
Christopher Young 93321a4f8f Reset Distance, Bearing, and BearingDist_valid if GPS data becomes invalid.
#580, #582.
2017-04-06 11:26:51 -04:00
Christopher Young 5d5f165218 Formatting.
Use gofmt after edits. #580, #582.
2017-04-06 11:24:46 -04:00
cyoung dfee391e66 Merge pull request #582 from ChiefPilot/master
Remove hardcoded alert flag on traffic report and replace with simple…
2017-04-06 11:24:01 -04:00
Eric Westphal fc438c0b30 mySituation AHRS and Baro variables now float32 for iOS. 2017-04-05 20:30:16 -04:00
Christopher Young 1fca793b2c Merge remote-tracking branch 'origin/master' into ahrs_dev
# Conflicts:
#	main/gen_gdl90.go
2017-04-04 20:55:57 -04:00
Christopher Young 744939d940 Add log comment on CPU profile option. 2017-04-04 20:55:03 -04:00
Christopher Young a6ded9a5c0 Add -cpuprofile command line option. 2017-04-04 20:52:22 -04:00
Christopher Young 171ab4a21e Merge fix. 2017-04-04 16:28:44 -04:00
Christopher Young 29b959afa9 Merge remote-tracking branch 'origin/master' into ahrs_dev
# Conflicts:
#	main/gen_gdl90.go
#	main/gps.go
#	main/managementinterface.go
#	main/network.go
#	web/js/main.js
#	web/plates/developer.html
#	web/plates/gps.html
#	web/plates/js/developer.js
#	web/plates/js/gps.js
#	web/plates/js/settings.js
#	web/plates/js/status.js
#	web/plates/status-help.html
#	web/plates/status.html
#	web/plates/traffic-help.html
2017-04-04 13:16:32 -04:00
Eric Westphal bc54533351 Ease up on the cpu. 2017-04-04 11:20:28 -04:00
kjablonski 64dca38480 Merge pull request #1 from cyoung/master
Merge Cyoung
2017-04-03 14:17:27 -05:00
kjablonski b8dd5d7b2c Update stxAliases.txt
Typo fixes
2017-04-03 14:12:18 -05:00
Brad Benson 24d20e7cdb Remove hardcoded alert flag on traffic report and replace with simple logic to set it only if a target is within 2nm. This addresses issue #580 . 2017-04-03 14:10:12 -05:00
Eric Westphal 23df9c9c2e Slip/skid indicates correctly in UDP; limit UI slip/skid to 10 deg max. 2017-04-02 10:26:23 -04:00
Eric Westphal ac6da35e3b Tidy up UI Status page, display CPU stats always. 2017-04-02 10:09:16 -04:00
Eric Westphal b9ebc3b39e Sensor values in arrays instead of scalars. 2017-04-01 19:21:12 -04:00
Eric Westphal 9b7212ed11 More robust acceleration detection for orientation. 2017-04-01 19:00:28 -04:00
Eric Westphal a2580d4593 AHRS auto-level working. 2017-04-01 14:02:12 -04:00
Eric Westphal 1961a3cc8c Remove some old comments. 2017-04-01 09:19:01 -04:00
Eric Westphal effa8da5a9 Decompose rotation matrix into x, y, z basis vectors. 2017-04-01 09:14:13 -04:00
Eric Westphal a998ede17b Merge branch 'ahrs_dev' 2017-04-01 08:35:34 -04:00
Eric Westphal 18af334813 Extract sensor rotation matrix creation into function. 2017-04-01 08:27:45 -04:00
Eric Westphal 6220a2dfe3 Change Situation field names to more explanatory scheme. 2017-03-30 19:20:49 -04:00
Eric Westphal c12aa3e728 Merge pull request #24 from cyoung/ahrs_dev
Fix nil pointer dereference crash.
2017-03-30 08:12:33 -04:00
Christopher Young bcd62e7c00 ssd1306 python driver - version change. 2017-03-28 17:18:53 -04:00
Christopher Young 7efcefcf3f Fix screen towers count - display only active. 2017-03-28 17:11:03 -04:00
Christopher Young f2c6c23c8e Remove auto-expand code. Increases microSD card failures. 2017-03-28 15:57:10 -04:00
Christopher Young a11b0b9be4 Formatting.
Run gofmt on modified files.
2017-03-28 11:57:32 -04:00
Christopher Young 89b848c3e5 Fix nil pointer dereference when sensor is not connected/initialized and webUI sensor option is disabled.
2017/03/28 13:43:00 wrote settings.
2017/03/28 13:43:01 http: panic serving 192.168.10.12:52012: runtime
error: invalid memory address or nil pointer dereference
goroutine 83 [running]:
net/http.(*conn).serve.func1(0x10ab6ae0, 0x73826140, 0x10d8c708)
	/root/go-1.5.1/src/net/http/server.go:1287 +0x9c
main.handleSettingsSetRequest(0x72ec00b0, 0x10d93580, 0x10db0620)
	/root/stratux-westphae/main/managementinterface.go:286 +0x1620
net/http.HandlerFunc.ServeHTTP(0x5d2ecc, 0x72ec00b0, 0x10d93580,
0x10db0620)
	/root/go-1.5.1/src/net/http/server.go:1422 +0x34
net/http.(*ServeMux).ServeHTTP(0x10960dc0, 0x72ec00b0, 0x10d93580,
0x10db0620)
	/root/go-1.5.1/src/net/http/server.go:1699 +0x164
net/http.serverHandler.ServeHTTP(0x109c4300, 0x72ec00b0, 0x10d93580,
0x10db0620)
	/root/go-1.5.1/src/net/http/server.go:1862 +0x190
net/http.(*conn).serve(0x10ab6ae0)
	/root/go-1.5.1/src/net/http/server.go:1361 +0xbfc
created by net/http.(*Server).Serve
	/root/go-1.5.1/src/net/http/server.go:1910 +0x360
2017/03/28 13:43:01 http: panic serving 192.168.10.12:52013: runtime
error: invalid memory address or nil pointer dereference
goroutine 58 [running]:
net/http.(*conn).serve.func1(0x1098b4a0, 0x73826140, 0x10de8228)
	/root/go-1.5.1/src/net/http/server.go:1287 +0x9c
main.handleSettingsSetRequest(0x72ec00b0, 0x10d93680, 0x10db0690)
	/root/stratux-westphae/main/managementinterface.go:286 +0x1620
net/http.HandlerFunc.ServeHTTP(0x5d2ecc, 0x72ec00b0, 0x10d93680,
0x10db0690)
	/root/go-1.5.1/src/net/http/server.go:1422 +0x34
net/http.(*ServeMux).ServeHTTP(0x10960dc0, 0x72ec00b0, 0x10d93680,
0x10db0690)
	/root/go-1.5.1/src/net/http/server.go:1699 +0x164
net/http.serverHandler.ServeHTTP(0x109c4300, 0x72ec00b0, 0x10d93680,
0x10db0690)
	/root/go-1.5.1/src/net/http/server.go:1862 +0x190
net/http.(*conn).serve(0x1098b4a0)
	/root/go-1.5.1/src/net/http/server.go:1361 +0xbfc
created by net/http.(*Server).Serve
	/root/go-1.5.1/src/net/http/server.go:1910 +0x360
2017-03-28 11:54:27 -04:00
cyoung 99e61dc343 Merge pull request #578 from westphae/master
Merge westphae/stratux:master into cyoung/stratux:ahrs_dev.
2017-03-28 11:41:59 -04:00
kjablonski 992367e50a Updates to gps.go
tweaks after testing on stratux
2017-03-27 21:49:01 -05:00
kjablonski aaf2025968 Update gps.go 2017-03-26 21:59:56 -05:00
kjablonski 1d33f79e04 More Galileo Updates
Updated sv numbers and added text to indicated Galileo in solution E#
2017-03-26 21:50:14 -05:00
Eric Westphal 9e101b4cf5 Minor ahrs.js name changes. 2017-03-26 20:44:42 -04:00
Eric Westphal 1904227438 Use websocket for gps/ahrs instead of GET polling. 2017-03-26 20:38:36 -04:00
kjablonski 0207ede47d Update gps.go
Added support for Galileo GNSS constellation
2017-03-26 19:15:31 -05:00
Eric Westphal bef3f475da Minor reformatting of gps.js. 2017-03-26 19:54:28 -04:00
Eric Westphal 7cca9a1bbc AHRS indicator lights red if stratux disconnects. 2017-03-26 19:42:15 -04:00
Eric Westphal a23a29fdfd Improved formatting of calibration warning message. 2017-03-25 22:55:19 -04:00
Eric Westphal ae92bae0d3 Resetting AHRS now turns of AI and displays calibration warning. 2017-03-25 18:24:51 -04:00
Christopher Young 7e0205be17 Limit main CPU to 900 MHz and set "sdram_freq" / "core_freq" as in pre-Jessie.
Issue #573.
2017-03-20 15:27:26 -04:00
Eric Westphal 63ce795340 web Makefile tried to copy nonexistent file. 2017-03-19 21:50:15 -05:00
Eric Westphal 551b2fc3e9 AI headings above 360 modded by 360. 2017-03-16 17:33:59 -04:00
Eric Westphal 2a40f80e5e Relabel cage button on AHRS UI page. 2017-03-14 19:33:21 -04:00
Eric Westphal adfa54813a Change Heading label to Track on AHRS UI. 2017-03-13 19:29:30 -04:00
Eric Westphal 9fefa4c3ff Create ai svg in javascript. 2017-03-12 22:27:24 -04:00
Eric Westphal ef8064c09f IMU->ATT and BMP->ALT on UI indicators. 2017-03-12 18:21:20 -04:00
Eric Westphal 571bec5a57 Make sure G Meter resets fully on power-up. 2017-03-11 19:39:49 -05:00
Eric Westphal d625f50446 Add arcs to g meter between max and min. 2017-03-11 09:20:26 -05:00
Eric Westphal f25df87825 Add G Meter to UI. 2017-03-10 22:03:35 -05:00
Eric Westphal 8ce402a33f Add AHRS status indicators to web UI. 2017-03-09 21:43:26 -05:00
Eric Westphal 5f8718c96a Reorder AHRS updates. 2017-03-09 21:41:45 -05:00
Eric Westphal cd314682eb Better orientation routine. 2017-03-09 21:40:21 -05:00
Eric Westphal 234dcb3726 Initial display of MagHeading, Slip/Skid, TurnRate, GLoad on web UI. 2017-03-08 18:11:05 -05:00
Eric Westphal d2526efc7c Slightly smarter sensor failure detection. 2017-03-08 18:10:13 -05:00
Eric Westphal 36595433be AHRSProvider calcs supplemental AHRS info instead of sensor. 2017-03-08 17:16:29 -05:00
Eric Westphal e78146ab99 Change "Calibration" to "Orientation" in UI. 2017-03-05 22:11:52 -05:00
Eric Westphal 3e43c1f69e AHRSLogger logs only if disk usage < 95%. 2017-03-05 19:07:01 -05:00
Eric Westphal 5667c1a871 All logs go to /root/ for FlightBox. 2017-03-05 18:56:11 -05:00
Eric Westphal f1ff15031f Add UI switch to record AHRS logs. 2017-03-05 18:34:25 -05:00
Eric Westphal 1344515c93 Separate UI switches for BMP and IMU connected. 2017-03-05 17:47:38 -05:00
Eric Westphal c34592e347 Refactor ahrs.InitializeSimple to separate logging from initialization. 2017-03-05 09:16:50 -05:00
Eric Westphal 043f334dc2 More robust initialization of baro ewma for ROC calc. 2017-03-05 09:13:18 -05:00
cyoung 0360e506ec Use netMutex to protect dhcpLeases, pingResponse, and outSockets. 2017-03-03 11:00:05 -05:00
cyoung 7631543b1a Merge pull request #566 from AvSquirrel/uat-traffic-improvements
UAT traffic decoding improvements
2017-03-03 09:56:58 -05:00
Eric Westphal 3d0ce092ab Re-run sensor calibration when caged. 2017-02-27 20:59:05 -05:00
Eric Westphal 787250b95f Slightly better location for stopping AHRS. 2017-02-27 20:58:45 -05:00
Eric Westphal cd6b708007 Better AHRS initialization behavior when sensors not yet calibrated. 2017-02-27 20:34:02 -05:00
Eric Westphal 4d31c3940c Initialize AHRSProvider using modified Reset interface. 2017-02-27 20:28:05 -05:00
Eric Westphal e397305fd0 MPU9250 correctly handles a zero calibration duration. 2017-02-27 19:57:01 -05:00
Eric Westphal 4bd6544cc0 AHRS_Provider gets a Reset method. 2017-02-27 18:07:14 -05:00
Eric Westphal 384cf16996 Move AHRS orientation explanation into help. 2017-02-23 14:41:39 -05:00
Eric Westphal b20302dff2 Cage button friendlier to data on web UI. 2017-02-23 14:41:03 -05:00
Eric Westphal 34396a36e5 Fix panic and lack of reconnect when Sensors switch toggled. 2017-02-22 16:54:13 -05:00
Eric Westphal f39c58ca3d netMutex becomes RWMutex, protects some additional reads. 2017-02-22 15:10:15 -05:00
cyoung acbe7742b2 Join DXF logo segments into polylines. 2017-02-17 12:57:04 -05:00
Eric Westphal 2ba3f136bb Change http status messages for go1.5.1 compatibility. 2017-02-17 11:11:27 -05:00
Eric Westphal f2cfe3344b Re-do sensor orientation setting method. 2017-02-16 16:57:30 -05:00
Eric Westphal e78afed4d4 Remove SensorLogger, some log messages. 2017-02-16 16:56:42 -05:00
Eric Westphal 2cf49218bd Increase GPS update cycle to 10Hz. 2017-02-15 16:10:52 -05:00
Eric Westphal 079dfc0e00 Increase AHRS calculation cycle to 20Hz for 10Hz GPS updates. 2017-02-15 16:09:09 -05:00
Christopher Young 4b63351c9c Disable hciuart. 2017-02-15 02:37:59 -05:00
Eric Westphal 9b180e2f25 AHRS tracks GPS time separately from sensor time. 2017-02-13 16:01:43 -05:00
Eric Westphal a5aa50f44f AHRS logging uses AHRSProvider built-in logging. 2017-02-13 15:15:45 -05:00
Eric Westphal 261dd637e0 Missing continue. 2017-02-13 14:26:29 -05:00
Keith Tschohl 71a9c06a29 Add parsing of UAT SIL, SDA, NACv, and In capability to verbose logs 2017-02-13 04:26:15 +00:00
Keith Tschohl 318e883db5 Add emergency status to traffic msgs; additional UAT statistics; cleanup 2017-02-13 03:37:51 +00:00
Eric Westphal 99cdda2219 ahrsweb Kalman Listener Send fails more nicely. 2017-02-12 17:06:36 -05:00
Eric Westphal 5ab394b31d Add Cage button to Attitude Indicator/AHRS. 2017-02-12 17:06:03 -05:00
Eric Westphal 59da452770 Add mutex to pingResponse map to prevent panics with Go>1.5. 2017-02-11 15:20:47 -05:00
Eric Westphal b3dd98cd76 AHRS attitude indicator displays tenth of degree changes. 2017-02-10 23:14:19 -05:00
Eric Westphal d17e218324 gdl90Report uses Gyro_heading. 2017-02-10 16:45:55 -05:00
Keith Tschohl 950c0594bf Disable sqlite logs when using UAT playback 2017-02-10 06:28:22 +00:00
Keith Tschohl f423f2c74e Determine UAT version. Proper decoding of callsign vs Mode 3/A code 2017-02-10 06:17:27 +00:00
Keith Tschohl dae0a29278 Add UAT traffic message decoder and v2 message documentation 2017-02-10 04:09:14 +00:00
Keith Tschohl 4201bb1ec3 Fix UAT track calculation when one velocity component = 0 2017-02-10 03:55:26 +00:00
Eric Westphal ba0440c49b Validate sensor calibration. 2017-02-07 21:35:59 -05:00
Eric Westphal ecd0ed5e2e bmp280 reads at the right frequency. 2017-02-07 21:35:21 -05:00
Christopher Young 239c473c9a Automatically expand root partition on first boot.
Compatible with .sh updates from previous versions via
`/etc/stratux.firstboot`.
2017-02-05 16:22:33 -05:00
cyoung 1ae6b5cb1f Merge pull request #514 from jamez70/developer_mode_add_loghandling
Added logfile truncation and download buttons to developer mdoe screen
2017-02-02 22:28:23 -05:00
cyoung a37d0f9ae3 Merge branch 'master' into developer_mode_add_loghandling 2017-02-02 22:28:16 -05:00
Christopher Young 6b10432240 dhcpcd disable. 2017-02-02 10:44:59 -05:00
Christopher Young d895772f6f Fix: systemd[1]: [/lib/systemd/system/stratux.service:8] Executable path is not absolute, ignoring: pkill dump1090 2017-02-02 10:07:56 -05:00
Christopher Young 6ec0b480bf Add hostapd_manager and stratux-wifi scripts to 'make install'. 2017-02-02 10:07:13 -05:00
cyoung dc074454c6 Merge pull request #555 from peepsnet/wifi-lag-fix
Wifi lag fix
2017-02-02 09:36:54 -05:00
cyoung 490e3d9900 Merge pull request #557 from AvSquirrel/10Hz-gps
GPS configuration and detection improvements
2017-01-30 00:27:24 -05:00
cyoung 9ee46170ff Merge pull request #556 from jonvadney/master
Add ability to set static ip from web ui when in dev mode
2017-01-29 20:32:17 -05:00
cyoung d8219c495d Merge pull request #559 from pmaag/traffic-help-additions
Added traffic type prefix definitions to traffic-help.html
2017-01-29 20:28:34 -05:00
Eric Westphal 5e0f586f8a Lighten logging, longer timeout for GPS. 2017-01-21 12:39:06 -05:00
Eric Westphal 0e14b82ddb Show CPU load on UI status page. 2017-01-16 22:25:26 -05:00
Eric Westphal b1351af740 A little more logging. 2017-01-16 18:25:53 -05:00
Eric Westphal 3c16945c92 Set orientation of AHRS sensor in UI. 2017-01-16 18:22:57 -05:00
Eric Westphal ed49f2c270 AHRS full-screen mode added. 2017-01-13 19:21:35 -05:00
Eric Westphal 541ce527a9 Add refresh UI function to developer mode. 2017-01-12 22:36:45 -05:00
Eric Westphal e0f794b907 AHRS calibration UI mostly done. 2017-01-08 23:04:16 -05:00
Eric Westphal 352c9eb79c sensorAttitudeSender is a little more robust. 2017-01-08 23:01:34 -05:00
Eric Westphal b6fef3ca9a sensors.go gets sensor orientation from globalSettings. 2017-01-08 12:11:51 -05:00
Eric Westphal af2ea7196b Make pressure reader work again. 2017-01-08 10:14:24 -05:00
Eric Westphal 816411b3ee Replace windoze CRLF with Linux LF in web files 2017-01-07 22:45:19 -05:00
Eric Westphal 22867df1f4 Improved GPS/AHRS UI layout 2017-01-07 08:29:33 -05:00
Eric Westphal a6642353d7 Add Enable_Sensors to settings UI 2017-01-07 08:05:37 -05:00
Eric Westphal 601efa9023 Start managementinterface earlier to avoid nil 2017-01-07 08:01:15 -05:00
Eric Westphal b615a0370b Move satelliteMutex into Situation alongside other Mutexes 2017-01-07 07:59:00 -05:00
pmaag f70a8c9525 Added traffic type prefix definitions to traffic-help.html
Added additional information to traffic-help.html to include the prefix
used when Show Traffic Source In Callsign is enabled within the
settings.

It was difficult to locate the definitions of each of the traffic type
prefixes, so I thought the help page would be a good location to define
these.

Additionally adjusted some spacing of the list elements to provide
easier readability on this help page.
2017-01-06 14:27:30 -08:00
Eric Westphal 9f9298734d Hack to avoid race condition, for now. 2017-01-05 23:01:00 -05:00
Eric Westphal 744c7bfe1c Replace paper airplane with attitude indicator in UI 2017-01-05 23:00:35 -05:00
Eric Westphal 84e81bbd3b Correct multiplier for climb rate 2016-12-29 15:12:19 -06:00
Eric Westphal c9c02e2e86 Change execution modes of non-executables 2016-12-29 06:43:00 -06:00
Eric Westphal 6c539a0f77 Merge branch 'dev' 2016-12-29 06:35:27 -06:00
Eric Westphal a3a811aa53 First working commit merging latest cyoung/master into westphae/dev 2016-12-29 06:33:11 -06:00
Keith Tschohl c7c6fb628b UI tweaks: Unbold 'Towers'. Suppress accuracy if disconnected / solution. Wordsmithing. 2016-12-26 21:25:56 +00:00
Keith Tschohl df22888465 Regression window tweaks 2016-12-26 15:54:05 +00:00
Keith Tschohl c67f4acb8c Update 'Status' help page. Make tabbing consistent. 2016-12-26 08:34:47 +00:00
Keith Tschohl 900ff0052e Status UI cleanup. Consolidate UAT stats, fix disappearing DIV for uptime / temp, add bytes free. 2016-12-26 08:07:52 +00:00
Keith Tschohl 7063c73ba7 Reset accuracy and NACp on GPS disconnect. Add sample rate to GPS UI page. 2016-12-26 07:30:46 +00:00
Keith Tschohl c84abec96f Report GPS position rate (Hz). Tweak gpsattitude filter. Cleanup. 2016-12-26 06:37:33 +00:00
Keith Tschohl c7ad7728d6 Add GPS hardware detection status to UI 2016-12-25 20:06:28 +00:00
Keith Tschohl 6544562913 Refined GPS detection. Updated gpsatttitude copyright notice 2016-12-25 19:00:01 +00:00
Keith Tschohl 529079368a 10 Hz default UBX config. Enable GLONASS multi-GNSS on UBX8 2016-12-25 08:36:40 +00:00
Jon Vadney 6198fc2ce3 add ability to set static ip from web ui when in dev mode 2016-12-25 07:03:56 +00:00
peepsnet 069db15e1e Update stratux-wifi.sh 2016-12-21 23:22:46 -05:00
peepsnet e5c694ac88 moved to function based
I moved all the code to functions and commented to reflect the file format
2016-12-21 22:46:55 -05:00
peepsnet 575d51c172 Removed encryption options
Since I am unable to get the encryption to work with the edimax I commented all the code out for now in hostapd_manager.sh
2016-12-21 22:45:23 -05:00
peepsnet 1b73935838 Added the hostpad.user creation code here 2016-12-21 12:17:21 -05:00
peepsnet 345350df82 Moving hostapd.user code 2016-12-21 12:10:24 -05:00
Jim Jacobsen 6de246d789 removed reopenLogFile it is unused 2016-12-20 22:57:09 -06:00
peepsnet b37a49948e Merge pull request #8 from cyoung/master
update master
2016-12-20 15:54:17 -05:00
cyoung 2b5037eb31 Merge pull request #553 from Helno/patch-1
Update fancontrol.py
2016-12-20 15:17:50 -05:00
Helno d4ed2d1b0c Update fancontrol.py
Update note on line 6 to reflect the currently used pin.
2016-12-20 11:58:59 -05:00
cyoung 5aeb10503e Merge pull request #550 from peepsnet/master
FIX Stratux so it works again!!! a.k.a. added stratux-wifi.sh to update scripts and correct pathing issue
2016-12-18 14:45:08 -05:00
peepsnet ac3a36251a Update interfaces 2016-12-18 11:53:27 -05:00
peepsnet ed1b908188 Cleaned up the comments
I cleaned up these comments and added the code that worked for me to get his running. I can now connect to my home wifi and cell phone hotspot with these settings.
2016-12-18 11:51:30 -05:00
peepsnet 806473455a simplify creating the tmp file 2016-12-18 11:12:19 -05:00
peepsnet eec6e2c7db nope 2016-12-18 09:53:55 -05:00
peepsnet 3b56dc7c3b added notes 2016-12-17 17:28:12 -05:00
peepsnet 6c927417c3 path typo
path typo for edimax driver
2016-12-17 15:40:43 -05:00
peepsnet 9957479024 Update makeupdate.sh 2016-12-17 15:31:17 -05:00
peepsnet e428800762 Update update_footer.sh 2016-12-17 15:30:06 -05:00
peepsnet cca83cd476 Merge pull request #7 from cyoung/master
update
2016-12-17 15:24:34 -05:00
Christopher Young 3e663c89c8 Limit number of traffic target reports sent in a single packet. 2016-12-14 20:52:16 -05:00
Eric Westphal cd2aadc0e3 Modifications for compatibility with simple AHRS 2016-12-12 18:12:40 -05:00
cyoung de93c79a07 Merge pull request #529 from peepsnet/master
Move user configurable options out of hostapd.conf and hostapd-edimax.conf to hostapd.user and build temp hoatapd.conf on the fly with stratux-wifi.sh
2016-12-12 14:39:33 -05:00
Christopher Young 720a7aad72 Clean up libimu ref. 2016-12-12 12:41:21 -05:00
cyoung 0107b59010 Merge pull request #544 from cyoung/gpsattitude
Promote gpsattitude to master.
2016-12-12 10:21:38 -05:00
Christopher Young ef56848715 Resolve conflicts. 2016-12-12 10:16:46 -05:00
Christopher Young 18de46745e Missing include. 2016-12-09 10:14:56 -05:00
Christopher Young 316cbf2329 Add DHCP lease directory write testing and webui error.
#500, #540.
2016-12-09 09:22:10 -05:00
cyoung beb3e04dd1 Merge pull request #542 from cyoung/use_modes
Use decoded ADS-B Out message from Ownship for Ownship 0x0A message d…
2016-12-09 08:58:29 -05:00
Christopher Young 9e8d20e3da Use decoded ADS-B Out message from Ownship for Ownship 0x0A message data, if available. 2016-12-02 10:57:40 -05:00
Christopher Young c19d32353f Typo. 2016-11-27 14:46:26 -05:00
peepsnet ed0cc5bd74 set a default passphrase if not choosen
Fixed the script to use a default passphrase("Squawk1200") if option -e used but no passphrase entered.
2016-11-24 12:00:24 -05:00
peepsnet a951410f3f Restart WiFi in script
This change now restarts the WiFI services in the script and no longer needs a restart!!
2016-11-24 11:48:14 -05:00
peepsnet 96a67ee5fc adding hostapd.user building code
Adding the code needed to update previous version of stratux with the new file structure needed while keeping custom user settings already used
2016-11-24 10:47:43 -05:00
peepsnet 469a413bb3 Change is logic placement
I removes all my code from this file and moved to stratux-pre-start.sh. This seems like a logical place to monkey around with stuff that must be ready for the start of stratux.
2016-11-24 10:41:50 -05:00
peepsnet 737df68e46 clean up 2016-11-24 00:00:52 -05:00
peepsnet 2ef42ea8d0 add sleep
add sleep to make sure the file write has time to finish before checking for the file
2016-11-23 23:51:18 -05:00
peepsnet 6c5352e3a1 clean up code 2016-11-23 23:35:14 -05:00
peepsnet 18b0bf53ef clean up 2016-11-23 23:31:03 -05:00
peepsnet 27db95f749 hopefully better speed 2016-11-23 22:09:35 -05:00
peepsnet e3e7fd7aab logic reorder 2016-11-23 21:20:42 -05:00
peepsnet 7b104be3dc formatting 2016-11-23 20:37:19 -05:00
peepsnet 94da60ed06 formatting 2016-11-23 19:35:36 -05:00
peepsnet 226b8442f7 Check for and handle hostapd.user
This script now not only starts hostapd using the proper driver(standard/edimax). 

It now checks for the existance of the hostapd.user file and if found uses it. if not found creates it with the values from the existing hostapd.conf

I choose to only carry over the values from the hostaod.conf and not the edimax because they should be the same. 

If there is no user configurable values in hostapd.conf and no hostapd.user file then a default hostapd.user file is created.
2016-11-23 19:22:18 -05:00
peepsnet 454da41fd2 Update stratux-wifi.sh 2016-11-23 17:25:21 -05:00
peepsnet d2c50f0921 Delete hostapd.user 2016-11-23 17:03:24 -05:00
peepsnet 31dc1a14fd user configurable hostapd values
this is where the user valies are stored and used to build /tmp/hostapd.conf
2016-11-23 17:01:28 -05:00
peepsnet 4a1ce917a3 update comments 2016-11-23 16:37:19 -05:00
peepsnet 3ad982e1c0 copy both hostapd.comf and hostapd-edimax.conf
this is now able because we moved the user configurable options away from the package files and build a temp hostapd.conf on the fly.
see https://github.com/cyoung/stratux/blob/master/image/stratux-wifi.sh
2016-11-23 16:13:35 -05:00
peepsnet d5afa25c69 Merge pull request #6 from cyoung/master
Standardize TODOs.
2016-11-23 16:10:36 -05:00
peepsnet c0a945bb88 edits hostapd.user
this file now edits hostapd.user to change user configurable values for hostapd
2016-11-23 15:54:49 -05:00
peepsnet 3cca4ba525 loading user config settings
update the file to create a tmp file that adds all the user config valuse to the hostapd.conf and uses the new /tmp/hostapd.conf to run the hostapd deamon
2016-11-23 15:52:44 -05:00
peepsnet 11f513c1da removed user configurable values 2016-11-23 15:50:55 -05:00
Christopher Young 5c70640eac Standardize TODOs. 2016-11-23 15:50:41 -05:00
peepsnet 9489933233 removed user configurable values
removed user configurable values to be placed in a global hosapd file
2016-11-23 15:50:32 -05:00
peepsnet a8b98677c3 Merge pull request #5 from cyoung/master
update
2016-11-23 15:49:12 -05:00
Eric Westphal d1607e0729 Support the BMP280 2016-11-23 10:34:41 -05:00
Christopher Young ff7a7a2781 Undo a few non-webui related changes. #531. 2016-11-22 23:33:39 -05:00
cyoung 8bf9347878 Merge pull request #531 from jamez70/move_timer_calls
Move timer calls to bottom of routines
2016-11-22 23:27:22 -05:00
Jim Jacobsen 1bf4de80a2 Move timer calls to bottom of routines, makes the web interface a lot more responsive 2016-11-23 03:14:45 +00:00
peepsnet d98d173e31 stop overwriting hostapd.conf on update
For some reason, this line was added and it caused the hostapd.conf(but not hostapd-edimax.conf) to be replaced at each update. This caused the users custom SSID and channel settings to be replaced!!
2016-11-19 11:03:37 -05:00
peepsnet 33c90e8da8 Merge pull request #4 from cyoung/master
update
2016-11-19 10:58:09 -05:00
Christopher Young ebfb671142 Rename ry835ai.go to gps.go. 2016-11-17 19:14:33 -05:00
Christopher Young 360845b454 Misc cleanup. 2016-11-17 19:10:59 -05:00
Christopher Young d7498169ed Misc cleanup. 2016-11-17 19:02:55 -05:00
Christopher Young 0ed4c0bfb7 Remove globalSettings.AHRS_Enabled. 2016-11-17 19:01:03 -05:00
Christopher Young d60248b660 Remove globalStatus.RY835AI_connected. 2016-11-17 18:56:15 -05:00
Christopher Young bc830b0a4e Remove mpu6050 references. 2016-11-17 18:49:18 -05:00
Christopher Young a47b1483c7 Remove linux-mpu9150 submodule. 2016-11-17 18:26:13 -05:00
Christopher Young eaea0178c2 Remove outdated FF compatibility warning. 2016-11-17 18:19:00 -05:00
Christopher Young 6c50a96347 Remove 'AHRS_GDL90_Enabled' option. 2016-11-17 18:18:16 -05:00
cyoung a473cca229 Merge pull request #527 from cyoung/master
Merge master.
2016-11-17 18:10:42 -05:00
Christopher Young 564bf93c63 Cleanup. #526. 2016-11-17 12:46:48 -05:00
Christopher Young 57e7c6d0a9 Formatting.
#526.
2016-11-17 12:43:47 -05:00
Christopher Young 83beb6dac1 Merge branch 'jamez70-gdl90-websocket-broadcaster' 2016-11-17 12:42:30 -05:00
Christopher Young 12df162b25 Manual merge. 2016-11-17 12:42:24 -05:00
cyoung 7d45737709 Merge pull request #516 from cyoung/stratux_websocket_support
Stratux websocket support. NEXRAD decoding added to uatparse.
2016-11-17 12:38:28 -05:00
Christopher Young b30f7094dc Formatting.
#525.
2016-11-17 10:54:30 -05:00
Christopher Young 2691fe714c Remove debug code.
#525.
2016-11-17 10:53:39 -05:00
cyoung 7b1dbf1975 Merge pull request #525 from jamez70/church-up-weather-status-page
Church up weather status page
2016-11-17 10:37:26 -05:00
Jim Jacobsen 7a801c6a06 oops again 2016-11-17 07:41:10 +00:00
Jim Jacobsen 2b3d06eafa Fixed JSON call 2016-11-17 07:25:36 +00:00
Jim Jacobsen 3a5a5e5048 GDL90 JSON interface stratux changes 2016-11-17 07:09:18 +00:00
Jim Jacobsen c5b18b79d9 More churching up, looks good 2016-11-17 06:58:36 +00:00
Jim Jacobsen e742ff0712 Add colors for wind, taf and pirep weather reports 2016-11-17 06:01:39 +00:00
Christopher Young 64836196cf Merge branch 'AvSquirrel-gpsattitude-june2016' into gpsattitude 2016-11-16 16:15:40 -05:00
Christopher Young a777e7d462 Manual merge. 2016-11-16 16:15:30 -05:00
cyoung 54204bab0d Merge pull request #524 from jamez70/gps_accuracy_meter_unit
Added 'm' specifier on unit for gps
2016-11-16 15:52:21 -05:00
Jim Jacobsen 9f195fa067 Was a bug, fixed now 2016-11-16 20:48:03 +00:00
Jim Jacobsen 71aea36e69 Added 'm' specifier on unit for gps 2016-11-16 20:42:09 +00:00
Christopher Young b67af3d191 Ping comments change. Added some data on recent tests. 2016-11-16 09:17:23 -05:00
cyoung 286fc27b84 Merge pull request #508 from uavionix/master
Add pingEFB text to README
2016-11-16 09:15:32 -05:00
Christopher Young 37e955474f Calculate data_item.time for report types other than WINDS. Don't calculate data age if greater than 2 days off.
#521.
2016-11-16 08:26:58 -05:00
Christopher Young 60b4b808ee Formatting.
#521.
2016-11-16 08:20:10 -05:00
cyoung 692157ecf5 Merge pull request #521 from jamez70/upper-winds-time-fix
Possible solution for upper level winds forecast time
2016-11-16 08:16:32 -05:00
cyoung b6fef657a2 Merge pull request #522 from jamez70/fix-font-weight
A font you can actually read on a tablet/phone
2016-11-15 09:55:22 -05:00
cyoung 6d9434d4b9 Merge pull request #519 from jamez70/fix_uat_status_layout
Updated UAT statistics
2016-11-15 09:37:32 -05:00
cyoung 49e252c270 Merge pull request #520 from jamez70/browser-cache-reload-possible-fix
Added seconds tag to stratux.appcache for page reloading if built cod…
2016-11-15 09:36:56 -05:00
Jim Jacobsen 7a980d7899 A font you can actually read on a tablet/phone 2016-11-14 05:55:30 +00:00
Jim Jacobsen b857c56a37 Possible solution for upper level winds forecast time 2016-11-14 05:07:16 +00:00
Jim Jacobsen 5058d0e4e1 Added seconds tag to stratux.appcache for page reloading if built code has changed 2016-11-14 05:00:38 +00:00
Jim Jacobsen d3a060a2de fixed incorrect color test html 2016-11-14 04:11:22 +00:00
Jim Jacobsen 380d13d383 Updated UAT statistics 2016-11-14 04:01:45 +00:00
Jim Jacobsen ff9c9966af Updated per suggestions and changes by ergonomicmike 2016-11-12 03:53:47 +00:00
peepsnet c77875493e Merge pull request #3 from cyoung/master
update
2016-10-27 08:34:13 -04:00
Christopher Young 33e9cb0b44 Change Intensity encoding. 2016-10-24 21:32:42 -04:00
Christopher Young 73d7cdbe1d weatherRawUpdate uibroadcast - send UATFrame as received. 2016-10-24 17:28:57 -04:00
Christopher Young 76e71bd6e5 Make NEXRADBlock fields exportable. 2016-10-24 17:14:06 -04:00
Christopher Young e0b123e426 Fixes. 2016-10-24 16:52:27 -04:00
Christopher Young b829e2228a Replaced NEXRAD processing. 2016-10-24 16:12:18 -04:00
Christopher Young 386be11b8c Subscribe /jsonio socket for situation updates. 2016-10-24 16:05:30 -04:00
Christopher Young f5ebf4c43d Use uibroadcast.SendJSON(). 2016-10-24 15:40:30 -04:00
Christopher Young a949bda34f Add mySituation uibroadcast. 2016-10-24 15:38:05 -04:00
Christopher Young 504d97ec7a Add SendJSON() to uibroadcaster. 2016-10-24 15:36:54 -04:00
Christopher Young 27206c0751 Formatting. 2016-10-24 15:28:44 -04:00
Christopher Young d433881b0b Formatting. 2016-10-24 15:27:48 -04:00
Christopher Young 04ee9d8b1b Formatting. 2016-10-24 15:22:57 -04:00
cyoung 5eb079dae6 Merge pull request #515 from jamez70/stratux_websocket_support
Initial support for NEXRAD data, added support for JSON types
2016-10-24 15:20:17 -04:00
Jim Jacobsen 7239e81418 Initial support for NEXRAD data, added support for JSON types 2016-10-23 23:38:13 -05:00
Jim Jacobsen 601e21c564 Added logfile truncation and download buttons to developer mdoe screen 2016-10-23 11:04:18 -05:00
cyoung 92e48862e2 Merge pull request #513 from jamez70/save_developermode
This saves developermode to settings when it is activated
2016-10-20 21:13:32 -04:00
Jim Jacobsen 1e9cff43c8 This saves developermode to settings when it is activated 2016-10-20 20:52:11 +00:00
cyoung b5ccfdc9ae Merge pull request #512 from jamez70/developer_mode_bugfix
Fixed typo with developer mode variable
2016-10-20 14:24:23 -04:00
Jim Jacobsen e4de2f5778 Fixed typo with developer mode variable 2016-10-20 18:17:31 +00:00
peepsnet af220df029 Merge pull request #2 from cyoung/master
update
2016-10-18 22:14:20 -04:00
Christopher Young 20ada0a9d7 Cleanup. 2016-10-18 20:29:31 -04:00
Christopher Young 32f0054f72 Formatting. 2016-10-18 20:27:14 -04:00
cyoung 2679c03472 Merge pull request #504 from jamez70/developer_mode_flag_handling
Developer mode flag handling
2016-10-18 20:19:04 -04:00
cyoung fc6e75adde Merge pull request #503 from peepsnet/master
Fixed the sleep function to lcase and a bit of look & feel
2016-10-18 20:18:33 -04:00
cyoung b9a9dd427d Merge pull request #510 from jamez70/fix_crash_in_issleeping
Fix crash in issleeping
2016-10-18 12:00:55 -04:00
Jim Jacobsen d1bb84327a reverted rules file 2016-10-17 22:34:32 -05:00
Jim Jacobsen 463ecafc38 Fixed bug with help of cyoung found with running on native linux, which may show itself on the RaspberryPi at some point 2016-10-17 22:30:43 -05:00
Jim Jacobsen 0f8e5810c6 Merge branch 'master' of github.com:cyoung/stratux 2016-10-14 21:11:30 -05:00
Jim Jacobsen 562529881d Merge branch 'master' of github.com:jamez70/stratux 2016-10-14 09:05:29 -05:00
Ryan C. Braun 5b1a9988f9 Add pingEFB text to README 2016-10-07 10:28:13 -05:00
peepsnet 883e8fd36c Merge pull request #1 from cyoung/master
Merge to update
2016-10-06 17:17:13 -04:00
cyoung 84a8d4a98a Merge pull request #506 from cyoung/traffic_counts
Add current UAT/ES tracked targets count in globalStatus.
2016-10-05 00:00:16 -04:00
Christopher Young ce5fe35bb7 Add current UAT/ES tracked targets count in globalStatus. 2016-10-04 23:50:44 -04:00
Jim Jacobsen bb00189e94 Added developer mode toggle by clicking on version 7 times within 3 seconds 2016-10-02 22:17:09 -05:00
peepsnet 0325a9ea39 Fixed the sleep function to lcase and a bit of look & feel 2016-10-02 11:54:31 -04:00
Jim Jacobsen 2a76788405 Added developer menu item in addition 2016-10-01 21:03:04 -05:00
Jim Jacobsen 9f1fd88485 Added developer mode handing from /etc/stratux.conf instead, then this allows options in the status and settings pages. Would like to add a menu option for this in the future though 2016-10-01 19:59:41 -05:00
Christopher Young 8929116f00 Formatting. 2016-10-01 11:48:27 -04:00
cyoung d67f2fe1db Merge pull request #492 from jamez70/allow_static_ip_hosts
Added ability to have static IP hosts
2016-10-01 11:47:04 -04:00
cyoung 3932153c3d Merge pull request #498 from peepsnet/patch-23
update for sdr-tool.sh. mkimg.sh addition.
2016-10-01 11:45:12 -04:00
cyoung 91ae3b7bfa Merge pull request #497 from peepsnet/patch-22
update for sdr-tool.sh script. Selfupdate addition.
2016-10-01 11:44:44 -04:00
cyoung 6f27e96233 Merge pull request #496 from peepsnet/patch-21
update for sdr-tool.sh script. Selfupdate addition.
2016-10-01 11:44:26 -04:00
cyoung 7865039dc2 Merge pull request #499 from peepsnet/patch-24
added sdr-tool.sh info
2016-10-01 11:43:57 -04:00
cyoung d9cb13d500 Merge pull request #495 from peepsnet/patch-20
Tool to "automate" setting SDR serials
2016-10-01 11:43:41 -04:00
peepsnet 06cbb8c508 uncommented a few need lines 2016-09-30 21:35:09 -04:00
peepsnet 0b71091b34 added sdr-tool.sh info 2016-09-30 21:24:38 -04:00
peepsnet c2b0e051ad update for sdr-tool.sh 2016-09-30 21:13:35 -04:00
peepsnet 066b61571c update for sdr-tool.sh script 2016-09-30 21:10:16 -04:00
peepsnet f8bb2c202f update for sdr-tool.sh script 2016-09-30 21:08:32 -04:00
peepsnet 37309af7bb Tool to "automate" setting SDR serials
The script walks users through setting serials for the SDRs and offers the "Fallback" option when setting the 1090 SDR.
2016-09-30 21:05:40 -04:00
Christopher Young 8f3ca19aca Add GPRMC date sanity checking. Add 'RealTime' monotonic ticker, set once by GPS time. 2016-09-29 18:30:26 -04:00
Jim Jacobsen bab827d492 Added ability to have static IP hosts 2016-09-27 23:56:17 -05:00
cyoung 2d03dde95a Merge pull request #471 from uavionix/master
Disable logging when Ping receives data
2016-09-27 17:21:04 -04:00
Christopher Young 8cef443497 Change green (ACT) LED default behavior on RPi - off = stratux not running, on = stratux running. 2016-09-26 14:34:41 -04:00
cyoung f711e61a1f Merge pull request #490 from jamez70/UAT_Statistics
Added UAT statistics to the status page
2016-09-25 20:44:26 -04:00
Jim Jacobsen f099336823 Fixed typo, and added TAF.AMD 2016-09-24 18:23:39 -05:00
Jim Jacobsen 2f2c3d27a3 Added UAT statistics to the status page 2016-09-24 12:17:46 -05:00
cyoung a951ea9afb Merge pull request #488 from AvSquirrel/ubx-zeroalt-fix
Workaround to allow negative GPS HAE on ublox-7. Fixes #487.
2016-09-21 09:04:25 -04:00
Christopher Young dc62a3abba Make HardwareBuild checking for updates case insensitive. 2016-09-19 18:27:19 -04:00
Christopher Young 31bbf1bc1b Don't display serialout settings unless a serialout device is present. 2016-09-19 12:25:23 -04:00
Christopher Young 30fe7295c4 Add automatic serialout when /dev/serialout0 is present.
/dev/serialout0 created by either inserting a CP2102-based
USB-to-Serial dongle or by symlink.
2016-09-19 12:21:39 -04:00
Keith Tschohl 9939ba986a Ignore PUBX,00 'HAE' field if it is equal to 0 2016-09-17 03:56:22 +00:00
Eric Westphal c3f002577f add ahrsweb kalman_listener for inflight monitoring of kalman filter 2016-09-16 13:36:45 -04:00
Eric Westphal 5acbcbfc32 improve ahrs kalman filter stability 2016-09-16 13:36:11 -04:00
Eric Westphal 91ed08583d Fix mapping of 9250 axes to ahrs kalman measurement 2016-09-16 13:34:44 -04:00
Christopher Young 85d73964c7 Typo. 2016-09-14 22:23:17 -04:00
Christopher Young 4659e03dbd Use Pin 12 (GPIO 18) for fancontrol. 2016-09-12 15:25:53 -04:00
Christopher Young 0d404a19bc Remove stratux-post-start.sh. 2016-09-12 14:44:28 -04:00
Christopher Young 95c1c3669e Remove stratux-post-start.sh. Start fancontrol and screen controller from rc.local. 2016-09-12 14:43:56 -04:00
Eric Westphal 6e622e3abb Integrate non-control Kalman approach 2016-09-11 20:33:26 -04:00
Eric Westphal cefbcc49da Measure magnetometer by default 2016-09-11 20:32:45 -04:00
Eric Westphal 9127c3a132 Round groundspeed 2016-09-11 20:32:10 -04:00
Christopher Young 89c82762b7 Change paths. 2016-09-11 18:49:01 -04:00
Christopher Young e4916a9de6 Add back DHCP default route.
Fixes some issues with Android. Cellular no longer usable on iPad when
connected.
2016-09-11 18:48:56 -04:00
Christopher Young 0588f8b0e7 Daemonize stratux-screen.py and fancontrol.py. 2016-09-11 17:24:01 -04:00
Christopher Young 333bb6c3ce Add "post start" script to start fan control and screen controllers. 2016-09-11 17:06:06 -04:00
Christopher Young 03f3957a0d Change paths for OLED screen addition. Add OLED script install into mkimg.sh. 2016-09-11 16:58:37 -04:00
Eric Westphal f6880436ba Merge remote-tracking branch 'origin/master' into dev 2016-09-11 06:37:44 -04:00
Eric Westphal ea353387d9 Fix FPS from FPM 2016-09-07 22:00:28 -04:00
Christopher Young e7636a0561 Add specific CP2102 rule for dedicated serialout device. 2016-09-06 16:16:02 -04:00
Christopher Young f477a8366e Traffic Javascript logic improvements and cleanup.
Fixes case where aircraft is first placed into “invalid position” table
and is never removed (even when position becomes valid).
2016-09-05 14:50:56 -04:00
Christopher Young 16c68b737d BMP logo initial commit. 2016-09-05 14:49:43 -04:00
Christopher Young 1159a37baf Add RPi3 FCC testing report for reference. 2016-08-26 23:09:47 -04:00
cyoung 5c322896e6 Merge pull request #478 from peepsnet/patch-19
Fixed typo
2016-08-24 17:48:16 -04:00
Christopher Young 0177402f00 Write only a single file for updates - fixes reboot loop issues.
Files with spaces and special characters were causing reboot loops.
2016-08-24 10:25:27 -04:00
cyoung 84e3497da5 Merge pull request #479 from tc0nn/master
Fixed typo in aliases for setSerial1
2016-08-20 23:00:51 -04:00
tconnolly@Tims-Home-iMac.local 45aac86b76 Fixed type in aliases for setSerial1 2016-08-20 20:07:25 -05:00
Ryan C. Braun e93b90197c Remove unused fmt from imports 2016-08-20 15:05:35 -05:00
peepsnet 574ff01d51 Fixed typo
this was preventing the stxAliases.txt from being copied over properly
2016-08-19 13:12:33 -04:00
Christopher Young e472329a32 Update issue template with checkboxes. 2016-08-16 16:07:03 -04:00
Christopher Young 6e6aa0b055 Clarify motd message about 'stratux-help' - command only applies to root user.
#473.
2016-08-16 16:04:25 -04:00
Jim Jacobsen 04e4454bb7 Added modification to udev rule to support replacement uAvionix device received 2016-08-11 21:12:38 -05:00
Ryan C. Braun 3cd58d20d8 Disable logging of Ping data reception 2016-08-09 14:36:01 -05:00
Ryan C. Braun 6daa3b7240 Merge remote-tracking branch 'upstream/master' 2016-08-09 14:10:55 -05:00
cyoung ff79aa5555 Merge pull request #463 from egid/egid-cleanup-426
Clean out clock UI
2016-08-05 17:07:02 -04:00
cyoung 973f576a54 Merge pull request #461 from egid/egid-gps-tweak
GPS accuracy on Status page
2016-08-05 17:05:59 -04:00
cyoung 1a7405ee32 Merge pull request #464 from AvSquirrel/boot-fixes
Update setup scripts to disable console on ttyAMA0
2016-08-05 17:04:42 -04:00
cyoung 5a13cc01ee Merge pull request #467 from peepsnet/patch-18
Added hostapd_manager.sh and raspi-config reminders
2016-08-05 12:07:12 -04:00
cyoung fb6c9ee119 Merge pull request #469 from cyoung/uavionix
PingEFB support - initial.
2016-08-05 12:05:02 -04:00
Christopher Young 8293c88936 Merge remote-tracking branch 'origin/master' into uavionix 2016-08-05 11:56:25 -04:00
Christopher Young 2569a146e9 Use apt-get to install python-pil. 2016-07-29 08:34:11 -04:00
Eric Gideon ee6ca139af add horizontal GPS precision to the "GPS solution" row on the status page 2016-07-23 13:16:20 -07:00
peepsnet afe73c38f1 Added hostapd_manager.sh and raspi-config reminders
Added hostapd_manager.sh and raspi-config reminders in the help
2016-07-22 20:35:56 -04:00
Eric Westphal 9faf95a90b Missed a few changes to pointers in ry83Xai 2016-07-21 21:57:51 -04:00
Eric Westphal 38cb2384d7 mpu.Calibrate takes a number of retries 2016-07-21 15:16:21 -04:00
Eric Westphal c27870d2a9 Make SituationData.GroundSpeed a float 2016-07-21 15:16:02 -04:00
Eric Westphal ef436544ac Use new channel interface for mpu9250.go 2016-07-19 07:49:41 -04:00
Eric Westphal 38b0105187 Merge branch 'gdl90report' into dev 2016-07-19 07:48:35 -04:00
Eric Westphal bf30fa147c Provide invalid GDL90Report values if AHRS invalid 2016-07-19 06:40:57 -04:00
Eric Westphal 832054bd35 Rate of Climb uses simpler ewma assuming steady data updates 2016-07-19 00:43:45 -04:00
Eric Westphal be30aefa79 Catch GDL90Report network error, useful for troubleshooting 2016-07-18 22:49:30 -04:00
Eric Westphal a7bb43d6ba Switch GDL90 report to version 1, include other goodies 2016-07-18 22:45:14 -04:00
Eric Westphal 9d133a5855 Calculate rate of climb from bmp altitude measurements 2016-07-18 22:43:44 -04:00
AvSquirrel f529ce3231 Remove references to /etc/inittab 2016-07-16 02:38:13 +00:00
Eric Westphal ad3798b5c8 Make Calibrate public for MPU's 2016-07-15 11:58:13 -04:00
AvSquirrel 56874e0886 Disable console on ttyAMA0 - shell updates 2016-07-15 15:50:30 +00:00
AvSquirrel fd6b8626e8 Disable console on ttyAMA0 - mkimg.sh 2016-07-15 15:49:51 +00:00
Eric Westphal 6b9b754257 MPU uses Calibrate rather than CalibrateGyro 2016-07-15 11:39:33 -04:00
Eric Westphal 3b21f9685a Some Kalman tuning 2016-07-15 11:39:10 -04:00
Eric Gideon 80b373a7a4 Remove clock / clock diff row from status template; also remove from js and go. 2016-07-15 01:28:30 -07:00
Eric Westphal 92001f1e35 First commit of AHRS Kalman Filter integration, untested 2016-07-15 01:31:45 -04:00
Eric Westphal bd2b303b59 Prepare for proper AHRS calculation 2016-07-15 01:31:03 -04:00
Eric Westphal 5382012417 mostly gofmt 2016-07-15 01:30:40 -04:00
Eric Westphal ee8c98eb50 Missing BMP won't shut down entire AHRS; make room for BMP280 2016-07-15 00:12:16 -04:00
Eric Westphal c201bdc4d8 Suggestion for network 2016-07-15 00:10:38 -04:00
Eric Westphal d91a2a10e7 Use RY835AI or RY836AI; add more fields to GDL90 report 2016-07-14 21:38:15 -04:00
Christopher Young e3d348a0fa Resolve conflicts. 2016-07-14 15:50:07 -04:00
Christopher Young 77ecb0d6ad Merge remote-tracking branch 'origin/master' into uavionix
# Conflicts:
#	Makefile
#	image/mkimg.sh
#	selfupdate/makeupdate.sh
2016-07-14 15:45:34 -04:00
Christopher Young eebf4be15c Update README. 2016-07-14 14:59:13 -04:00
Eric Westphal ddaf673006 Don't add one little change before pushing 2016-07-13 20:49:07 -04:00
Eric Westphal 7ee7a83a87 Change MPU to interface to allow RY835AI or RY836AI (or ....) 2016-07-13 18:42:25 -04:00
Eric Westphal c3c49b7c36 Prep for extracting interface for mpu6050 2016-07-13 16:36:33 -04:00
Christopher Young 945c8bf6bc Don't start ffMonitor() - no longer needed. 2016-07-13 15:53:02 -04:00
Christopher Young 04be847069 Add OLED screen display files. 2016-07-12 18:08:56 -04:00
Christopher Young 787887894d Switch last line of data every 5 seconds from CPU+Towers to GPS stats. 2016-07-12 01:15:31 -04:00
cyoung 3877461b6e Merge pull request #459 from peepsnet/patch-16
fix typo
2016-07-10 12:12:59 -04:00
cyoung 24e21bb640 Merge pull request #458 from peepsnet/patch-15
More info in the MOTD
2016-07-10 12:12:55 -04:00
cyoung 2f0f62c8b3 Merge pull request #452 from mhrivnak/patch-1
fixes a minor typo
2016-07-10 12:12:21 -04:00
peepsnet 622c9eb643 fix typo 2016-07-10 10:59:18 -04:00
peepsnet f77b21175b Update motd 2016-07-10 10:55:46 -04:00
peepsnet 2c0768c44c More info in the MOTD 2016-07-10 10:54:44 -04:00
Christopher Young 996deda432 Screen test script - initial commit. 2016-07-09 14:55:56 -04:00
Christopher Young e83bfb6319 Add python-dev for OLED screen. 2016-07-09 14:35:16 -04:00
Christopher Young 6d063cce42 OLED screen notes. 2016-07-09 14:25:06 -04:00
Christopher Young b31ed721c3 Fix more log errors. 2016-07-09 14:05:40 -04:00
Christopher Young f62d83f47f Typo. 2016-07-09 14:01:36 -04:00
Christopher Young f8fa9f5fb4 Fix some log(0) errors. 2016-07-09 13:59:41 -04:00
Christopher Young 3dfbcc6ad7 Add new kernel module name to blacklist for newer Linux distros. 2016-07-07 19:05:35 -04:00
Michael Hrivnak 76484b315e fixes a minor typo 2016-07-03 19:03:34 -04:00
Christopher Young f8269f5759 Make "GPS week out of scope" warning a debug message. 2016-06-30 11:51:56 -04:00
Christopher Young 917029b7ac Stratux logo vector format. 2016-06-28 14:10:42 -04:00
Christopher Young 31464f92ad Install fan control utility via update script. Move to /usr/bin/.
#444.
2016-06-27 09:28:56 -04:00
Christopher Young 9d3060af95 Use sh syntax since previous versions execute the update script using /bin/sh. 2016-06-24 17:15:43 -04:00
Christopher Young 629fa68a13 Use bash to execute update script. 2016-06-24 17:12:37 -04:00
Christopher Young 0f001da912 Remove init.d files from gen_gdl90 process. 2016-06-24 16:48:48 -04:00
Christopher Young f4a36b2df7 Throw webUI error prompting user to update image if /etc/debian_version <8.0.
#448.
2016-06-24 16:10:34 -04:00
Christopher Young b611615dce Don't delete init.d script in .sh update unless running Jessie.
#448.
2016-06-24 15:51:04 -04:00
Christopher Young d50748c23a Update README. 2016-06-23 17:53:09 -04:00
Christopher Young 18cbe9d784 Cleanup. Startup scripts installed by 'make install'. 2016-06-23 16:03:51 -04:00
Christopher Young 6ce1f48f63 Cleanup. Startup scripts installed by 'make install'. 2016-06-23 16:03:20 -04:00
Christopher Young 64710fe60d Typo. 2016-06-23 15:58:14 -04:00
Christopher Young 6e33ff07d6 Update Makefile, remove init.d file install, add new startup script file install. 2016-06-23 15:42:43 -04:00
Christopher Young 9f05b24536 Cleanup. 2016-06-23 15:34:00 -04:00
Christopher Young 3250158126 Clean up. Add systemd files install to mkimg.sh.
#445.
2016-06-21 22:58:30 -04:00
cyoung 5b998896cc Merge pull request #446 from kdknigga/master
convert from sysv init to systemd for the crash recovery benefits. Fixes #445.
2016-06-21 22:51:42 -04:00
Kris Knigga 29c6787f17 convert from sysv init to systemd for the crash recovery benefits 2016-06-21 19:30:29 -05:00
Christopher Young 6dd64321dd Type match. 2016-06-21 15:31:03 -04:00
Christopher Young 19742db6b8 Typo. 2016-06-21 15:27:06 -04:00
Christopher Young 953a211aa8 Ignore compiled test binaries. 2016-06-21 15:25:15 -04:00
Christopher Young 344f0ac2c4 Error checking in UAT parsing. Addresses #420. 2016-06-21 15:21:17 -04:00
Christopher Young ada5b4ae3f dest/src patch. 2016-06-21 15:05:28 -04:00
Christopher Young fc5641cb69 Integrate @toofishes improvement: Unroll loop in convert_to_phi.
“This yields a 10% CPU savings vs the original single value per loop
iteration implementation on a Raspberry Pi 2 Model B.”

https://github.com/mutability/dump978/commit/b0958f4305d2c7355d07fa9b938
8f6ad1b31b161
2016-06-21 14:54:59 -04:00
Christopher Young e180f79855 Start Canadian regs with "C-". Formatting.
#442.
2016-06-21 12:28:49 -04:00
cyoung ec3c5a6ab9 Merge pull request #442 from AvSquirrel/tail-number-decoding
Automatic translation of Mode S codes to US/CA tail numbers
2016-06-21 12:27:27 -04:00
cyoung edb9e8023c Merge pull request #444 from egid/master
GPIO fan control script
2016-06-21 12:25:27 -04:00
Eric Gideon 837c6ec476 adding fancontrol to the root user's dir; no automation at this time. 2016-06-21 09:11:54 -07:00
Eric Gideon 43c0da7e21 adding @helno's GPIO fan control script. 2016-06-21 09:06:30 -07:00
Eric Gideon 50027d416c Merge pull request #1 from cyoung/master
Update fork
2016-06-21 08:56:35 -07:00
AvSquirrel 6d19f57e0e Add decoding of Canadian tail numbers 2016-06-20 05:07:00 +00:00
AvSquirrel efaaa8777d Decode US civil Mode S codes to N numbers 2016-06-20 03:30:40 +00:00
AvSquirrel c5f2193b87 Change FF error message back per cyoung request 2016-06-19 03:12:43 +00:00
AvSquirrel 5dc2aec687 Merge remote-tracking branch 'upstream/master' into gpsattitude-june2016 2016-06-19 03:00:08 +00:00
Christopher Young a062241c7a Add metar-to-text functions. 2016-06-14 10:29:55 -04:00
Christopher Young 275d72befa Add Makefile. 2016-06-14 10:29:30 -04:00
Christopher Young de89ee301a Initial commit, metar parser.
https://sourceforge.net/p/mdsplib/code/HEAD/tree/
2016-06-14 10:28:31 -04:00
Christopher Young 9ae8ff93a2 Cleanup. 2016-06-13 16:25:21 -04:00
Christopher Young 5eadf628ee ASCII Stratux /etc/motd. Add note about clock. #426
http://patorjk.com/software/taag-v1/, “Univers” font.
2016-06-13 16:12:41 -04:00
Christopher Young 60ec38c5bb Change 'Data' in 'msg' struct from []byte to string for logging. 2016-06-10 15:12:32 -04:00
AvSquirrel 7b02ff0b70 Update settings.js for AHRS GDL90 toggle 2016-06-08 03:38:45 +00:00
AvSquirrel c34c107f23 Comment cleanup. Remove bloat from UI status page. 2016-06-08 03:20:43 +00:00
AvSquirrel fbc2ee16d3 Add toggle for GDL90 AHRS output. Use GDL90 AHRS toggle for FF compatibility instead of disabling AHRS hardware. 2016-06-08 02:52:00 +00:00
AvSquirrel 065836ef4c Tweak filter width. Comment out a couple of debug messages 2016-06-08 01:47:19 +00:00
cyoung 1b02ce3611 Merge pull request #438 from AvSquirrel/logging-fix-20160607
Bug fix for logging
2016-06-07 20:39:20 -04:00
AvSquirrel e5a6046660 Set logfiles for non-FlightBox installations 2016-06-08 00:20:10 +00:00
AvSquirrel 3d4dec80a4 Add GPS attitude logging to sqlite log 2016-06-08 00:10:17 +00:00
AvSquirrel cbd117d216 Initial implementation of GPS attitude on v0.9 codebase. Needs debug. 2016-06-07 13:03:25 +00:00
cyoung f40ae217bf Merge pull request #436 from tonymorris/master
fix typo in comment
2016-06-06 20:09:33 -04:00
Tony Morris b0e4ca1772 fix typo in comment 2016-06-02 20:41:25 +10:00
Ryan Braun c8244bf96f Merge pull request #1 from cyoung/uavionix
Merge master changes. Some minor Ping-related fixes.
2016-05-31 15:05:59 -05:00
Christopher Young 62bb61ac00 Include 99-uavionix.rules in .sh update. 2016-05-31 10:42:05 -04:00
cyoung 94d2467e22 Merge pull request #435 from AvSquirrel/ownship-testing
Intial prototype for ownship traffic suppression. Fixes #421.
2016-05-31 09:13:11 -04:00
Christopher Young 68e2d32f1d Move tower stats processing out of parseInput(). Remove unused ADSBTower.Messages_total. 2016-05-31 09:00:02 -04:00
Christopher Young 2132585f76 Remove products_last_minute comments. 2016-05-31 08:29:06 -04:00
cyoung 8f310d0afc Merge pull request #428 from AvSquirrel/uat-mutex
Additional UAT stability improvements (tower mutex, array bounds checks)
2016-05-31 08:26:50 -04:00
cyoung 1493526807 Merge pull request #430 from jpoirier/development
Add support for RPi0 board rev 1.3
2016-05-31 08:20:03 -04:00
Joseph Poirier 4431f3cda3 Add support for RPi0 board rev 1.3 2016-05-29 11:17:00 -05:00
Christopher Young 9e6ba2094e Allow user to set ppm to a blank string.
13c6fef514
2016-05-29 01:45:13 -04:00
Christopher Young 404a4c9c05 FlightBox additions: log to /root. 2016-05-27 16:27:22 -04:00
Christopher Young 4313e02fc7 Cleanup old logging code. Comments. 2016-05-27 16:20:20 -04:00
Christopher Young 89107818b8 decodeAirmet() not used in gen_gdl90 stats and still in development.
#420.
2016-05-27 11:51:11 -04:00
Christopher Young 438a947aa5 Remove extra log message. 2016-05-27 00:18:48 -04:00
Christopher Young e81c640baf Fix fatal error when can't listen on :50113 UDP. 2016-05-26 23:48:13 -04:00
Christopher Young 751d211b38 Use only /dev/ping. Formatting. 2016-05-26 23:31:06 -04:00
Christopher Young 5bafa0d8b0 Update udev rules from 'make install'. 2016-05-26 23:27:23 -04:00
Christopher Young 7e915cc116 Merge remote-tracking branch 'origin/master' into uavionix 2016-05-26 23:25:46 -04:00
Christopher Young 566295a227 Undo last change. 2016-05-26 23:20:40 -04:00
Christopher Young f417414fad Update udev rules with 'make install'. 2016-05-26 23:19:35 -04:00
cyoung 3843350432 Merge pull request #427 from uavionix/master
Initial
2016-05-26 23:15:41 -04:00
AvSquirrel 72aa6b5583 Bounds checking for uatparse.go arrays 2016-05-26 03:30:24 +00:00
AvSquirrel 5be9ec80ef Comment out 'products_last_minute' references 2016-05-24 19:48:31 +00:00
AvSquirrel f1521d6e25 Initial commit of ADSBTower mutex protection (needs testing) 2016-05-24 19:39:11 +00:00
cyoung 47271df764 Merge pull request #418 from AvSquirrel/udev-updates
Udev updates. Fixes #424.
2016-05-23 23:44:43 -04:00
Christopher Young 744240da50 Typo. 2016-05-23 11:27:50 -04:00
cyoung 5bd4c84e53 Merge pull request #405 from peepsnet/patch-14
include hostapd-edimax.conf along with hostapd.conf during updates
2016-05-23 11:14:53 -04:00
AvSquirrel 401c372ef4 Intial prototype for ownship traffic suppression 2016-05-20 03:28:41 +00:00
AvSquirrel d9c9b87f42 Add udev rules to Makefile 2016-05-19 04:03:34 +00:00
AvSquirrel 7940417f1c Add u-blox 8 to udev rules. Use generic descriptions for ublox 6/7. 2016-05-19 03:48:58 +00:00
Christopher Young aae8e925ef Fix 2016-05-17 19:19:32 -04:00
Christopher Young 7881d6c53a Move away from ttyUSB0 and use udev-specific rules.
#416.
2016-05-17 17:17:01 -04:00
Christopher Young 8b85b41342 Deploy stratux udev rules.
#416.
2016-05-17 17:13:30 -04:00
Christopher Young 4928f9526b Typo. 2016-05-17 15:26:11 -04:00
Christopher Young 1a50587cc9 Upload to temporary directory in .sh builds, then move.
#417.
2016-05-17 15:15:56 -04:00
Ryan C. Braun ae40a08d7e Fix udev typo 2016-05-16 18:07:46 -05:00
Ryan C. Braun c709088be2 Update udev rule to symlink 2016-05-16 18:07:04 -05:00
Christopher Young c1fa523aaf Initial commit - udev rules for GPS devices and serialout devices.
#416.
2016-05-16 18:39:42 -04:00
cyoung 29915cb62e Merge pull request #412 from AvSquirrel/gps-backend-working
GPS improvements: Satellite info; multi-GNSS support; UI updates
2016-05-16 17:58:01 -04:00
Christopher Young 13c6fef514 Allow user to set watch list to a blank string. 2016-05-16 17:51:38 -04:00
AvSquirrel a39a870378 Bug fix for GSA SBAS 'inSolution' marking. Update comments. 2016-05-16 02:17:01 +00:00
Christopher Young fba162a4e9 es_dump_csv initial commit. 2016-05-14 00:35:51 -04:00
Christopher Young b9951241a5 GetTunerGain to confirm tuner gain setting. 2016-05-13 23:58:08 -04:00
Christopher Young 7dca721b4c Add slackin badge. 2016-05-13 23:29:58 -04:00
Christopher Young 86859f32f5 Typo. 2016-05-13 22:57:33 -04:00
AvSquirrel fc1870af6a Length check for PUBX,03 messages. Add inSolution status to debug messages 2016-05-14 02:32:11 +00:00
AvSquirrel f02fdf102e Add mutex lock on handleSatellitesRequest 2016-05-14 01:44:13 +00:00
Christopher Young 2231ee4972 Remove null characters from serial string.
Fixes #413.
2016-05-13 21:42:05 -04:00
AvSquirrel 4fa44bb766 Clean up web UI formatting, update GPS help file 2016-05-08 21:55:48 +00:00
AvSquirrel c202e72c1d UBX config updates; comments; clean up debug messages 2016-05-08 20:41:49 +00:00
AvSquirrel 861debafbf Improve satellite counts for multiGNSS GSA messages 2016-05-08 16:36:05 +00:00
AvSquirrel 1d4de4571f Remove more debug mesages 2016-05-08 05:33:05 +00:00
AvSquirrel 65beb92208 Re-initialize on disconnect. Improvements for multi-GNSS 'in solution' counts. 2016-05-08 05:14:20 +00:00
AvSquirrel 653bb53cf6 Add UBX support. Enable GLONASS for M8N Neo. Reduce sampling to 5 Hz 2016-05-08 01:53:12 +00:00
AvSquirrel e71ede9007 Add GLONASS support to GSV parsing 2016-05-07 20:48:02 +00:00
AvSquirrel d692c4d732 Add satellite in solution indicator 2016-05-07 15:19:42 +00:00
AvSquirrel 06fc9a74b6 Suppress '-999' value for invalid elev/az in GPS UI 2016-05-07 06:44:18 +00:00
AvSquirrel a00e4d2afa Remove debug messages 2016-05-07 06:27:53 +00:00
AvSquirrel 34e4ff2dd0 Add satellite status to GPS UI page 2016-05-07 06:14:36 +00:00
AvSquirrel 34791c638a Create JSON interface for satellite constellation. 2016-05-07 05:18:10 +00:00
AvSquirrel df720ee23e Create and populate 'Satellites' structure 2016-05-06 05:50:45 +00:00
AvSquirrel a8f7728b11 Parse GPGSV fields into local variables 2016-05-05 05:16:16 +00:00
AvSquirrel 883509b076 Create Satellites data structure 2016-05-05 04:01:10 +00:00
AvSquirrel 26fce60fd4 Parse satellites tracked from GPGSV messages 2016-05-05 03:28:28 +00:00
Christopher Young 0a62fd2d9a Don't assign struct val directly. 2016-05-03 09:50:59 -04:00
Christopher Young 6db8ba6fc0 Type fix. 2016-05-03 09:39:16 -04:00
Christopher Young 64f1ae1154 Add MessageQueueLen (messageQueue length) to networkConnection struct.
Debugging for #409.
2016-05-03 09:31:57 -04:00
Christopher Young d01bdfee43 Typo. 2016-05-03 09:12:49 -04:00
Christopher Young 141045bb0e Add displayable error when SQLite logging is behind. 2016-05-03 09:05:54 -04:00
cyoung 8043ff79fd Merge pull request #410 from AvSquirrel/logging
Graceful shutdown of SQLite logs
2016-05-03 08:53:53 -04:00
cyoung 81b950c846 Merge pull request #408 from AvSquirrel/gps-backend
GPS backend improvements
2016-05-03 08:50:06 -04:00
AvSquirrel 29948156d6 Additional stability improvements 2016-05-03 04:59:13 +00:00
AvSquirrel 57197c55eb Split out traffic source from DEBUG. Fix panic closing closed channel. 2016-05-03 04:40:51 +00:00
AvSquirrel 5478cdaeb8 Add comments and clean up debug messages 2016-05-03 03:50:42 +00:00
AvSquirrel aaf03acd8c Close datalog.go channels on sqlite shutdown 2016-05-03 03:02:44 +00:00
AvSquirrel 24a6da3da9 Added graceful shutdown for SQLite logging 2016-05-02 05:03:21 +00:00
AvSquirrel 2dd8a14d62 Status and settings logged only when replay log enabled 2016-05-01 20:02:56 +00:00
AvSquirrel 837d98de25 Avoid false positive isGPSValid() check at startup 2016-04-29 08:54:04 -05:00
peepsnet 1555b2a5c8 hostapd-edimax.conf
I don't know if this was an oversight but I believe this should of been included
2016-04-29 09:22:25 -04:00
AvSquirrel 313f16e433 Improved isGPSValid(); reordered GPS port priority 2016-04-29 03:18:34 +00:00
Christopher Young feeeaea708 Remove wifi_watch.sh and associated rc.local entry. 2016-04-28 12:41:55 -04:00
cyoung bd2402f0fb Merge pull request #398 from AvSquirrel/traffic-ui-new
Traffic UI improvements
2016-04-24 12:32:43 -04:00
cyoung cfc54bba8b Merge pull request #399 from AvSquirrel/sirf-config-script
Shell script for offline SIRF-IV / BU-353-S4 configuration
2016-04-24 12:28:45 -04:00
AvSquirrel 054771e3f2 Add shell script for offline SIRF-IV / BU-353-S4 config 2016-04-24 15:53:11 +00:00
AvSquirrel 3769dfafbc TrafficUI helpfile update and minor UI fixes 2016-04-24 03:49:04 +00:00
AvSquirrel dc9292acbd Reformat non-position table for better reflow 2016-04-24 00:05:06 +00:00
AvSquirrel 749480f1c3 Zero-pad single-digit lat/lng in traffic UI 2016-04-23 23:34:50 +00:00
AvSquirrel 614cd875b2 Reformat ADS-B traffic table for better reflow 2016-04-23 23:10:53 +00:00
AvSquirrel 75923725ea Make mtk_config.sh executable 2016-04-23 04:33:34 +00:00
AvSquirrel 36d69c3fda Merge remote-tracking branch 'upstream/master' into traffic-ui-new 2016-04-23 04:32:13 +00:00
Christopher Young d8624016f6 Track startups in sqlite. 2016-04-22 16:10:56 -04:00
cyoung 6e5d449af0 Merge pull request #394 from AvSquirrel/gps-uart-fix
GPS UART fix for RPi 3. Fixes #393.
2016-04-22 07:22:11 -04:00
cyoung 14f35ba81e Merge pull request #396 from peepsnet/patch-13
Typo in stxAliases.txt
2016-04-22 07:20:35 -04:00
peepsnet f6f3431ab9 Typo 2016-04-20 15:28:22 -04:00
AvSquirrel f6d2ee1898 config.txt updates for RPi 3 2016-04-20 11:51:09 +00:00
AvSquirrel d83ec11ea9 Remove /dev/ttyS0 from GPS initialization 2016-04-20 03:45:24 +00:00
AvSquirrel 3d1af90d3d Add setup script for MTK3339 based receivers 2016-04-20 02:11:53 +00:00
Christopher Young da5f5d003d Remove unused code in comments. 2016-04-19 08:51:47 -04:00
Christopher Young a2ca212a52 Un-do dump1090 version change in #390. 2016-04-19 08:38:18 -04:00
Christopher Young 827bf13fde Comments update.
#390.
2016-04-19 08:37:22 -04:00
cyoung 6545c154c2 Merge pull request #390 from AvSquirrel/traffic-backend-working
Traffic backend updates
2016-04-19 08:28:36 -04:00
AvSquirrel d00ab538cd Traffic UI updates from gpsattitude branch 2016-04-17 12:17:11 +00:00
AvSquirrel 0292aeead3 Merge remote-tracking branch 'upstream/master' into traffic-ui-new 2016-04-17 12:11:57 +00:00
cyoung c327c0220b Merge pull request #391 from cyoung/reboot_repeat_fix
trigger reboot as a webservice and redirect webui to status page. Fixes #389.
2016-04-13 12:56:40 -04:00
bradanlane 70269dd442 trigger reboot as a webservice and redirect webui to wait on the status page for the reboot to complete 2016-04-13 12:38:37 -04:00
AvSquirrel 955fd13195 Separate ES:30006 logging into its own SQLite table 2016-04-13 05:21:05 +00:00
AvSquirrel 8b9c89542f Add distance / bearing calculation. Don't log stale traffic. 2016-04-13 04:04:28 +00:00
AvSquirrel d407c513c9 Reduce SQLite traffic to 1/sec. Backend improvements from gpsattitude branch 2016-04-13 03:41:08 +00:00
AvSquirrel c8ad41c8bc Update to AvSquirrel/dump1090@1ab6062 2016-04-13 02:52:55 +00:00
cyoung 43c5ff3b8c Merge pull request #387 from peepsnet/patch-12
typo
2016-04-12 11:46:45 -04:00
peepsnet f26ae164a7 typo 2016-04-12 11:36:20 -04:00
Christopher Young acee114964 Fixed race condition that caused CPUTemp = -99.00ºC. 2016-04-12 11:13:48 -04:00
Christopher Young 23619fad1b Add disk usage webUI warning. 2016-04-12 10:59:07 -04:00
Christopher Young e8f8a27bc3 Formatting (gofmt). 2016-04-12 10:38:04 -04:00
cyoung 20c09340d7 Merge pull request #376 from AvSquirrel/ownship-track
Improve ownship track accuracy. Add disk usage to logs.
2016-04-12 10:37:20 -04:00
cyoung 3f495ef0b5 Merge pull request #386 from AvSquirrel/sqlite-timestamp-slice
SQLite logging - Change dataLogTimestamps[] to slice
2016-04-12 10:30:10 -04:00
Christopher Young d9e556acba Add old Pi2 AMA0. 2016-04-11 22:52:07 -04:00
Christopher Young cc49ea9813 Fixes PR #382. 2016-04-11 17:25:09 -04:00
cyoung 36723d446f Merge pull request #385 from peepsnet/patch-11
Update update_footer.sh
2016-04-11 17:23:32 -04:00
cyoung 0e9adca4ab Merge pull request #383 from peepsnet/patch-9
Update mkimg.sh
2016-04-11 17:22:24 -04:00
cyoung ff3594b597 Merge pull request #382 from peepsnet/patch-8
adding .sxtAliases
2016-04-11 17:21:43 -04:00
cyoung 2cf27665cc Merge pull request #381 from peepsnet/patch-7
update for .stxAliases
2016-04-11 17:21:14 -04:00
cyoung 3ce1c5be3d Merge pull request #380 from peepsnet/patch-6
Add aliases and hostapd_manager.sh
2016-04-11 17:20:53 -04:00
cyoung 750cebe7a8 Merge pull request #379 from peepsnet/patch-5
Debugging aliases
2016-04-11 17:18:37 -04:00
cyoung 690a03f9d2 Merge pull request #375 from AvSquirrel/geometric-ownship-fix
Fix geometric ownship alt overflow
2016-04-11 17:15:11 -04:00
cyoung 3768370411 Merge pull request #367 from peepsnet/patch-4
keep an alias file after this file is modified and Stratux Specific Aliases
2016-04-11 17:14:03 -04:00
AvSquirrel 002105bb39 Change dataLogTimestamps from map to slice 2016-04-10 05:21:13 +00:00
Christopher Young fffe2b7505 Change hardware-specific /dev/ttyAMA0 to more general /dev/ttyS0. 2016-04-09 22:02:18 -04:00
peepsnet 781b0d64a3 Update update_footer.sh 2016-04-08 19:21:24 -04:00
peepsnet 4ca7fa94fc Update mkimg.sh 2016-04-08 19:17:54 -04:00
peepsnet 0f8c352ae6 adding .sxtAliases 2016-04-08 12:03:18 -04:00
peepsnet ad0f1a3c55 update for .stxAliases 2016-04-08 11:59:57 -04:00
peepsnet e8dff7d1cb Add aliases and hostapd_manager.sh
adding the lines to include stxAliases and hostapd_manager.sh to makefile
2016-04-08 11:56:38 -04:00
peepsnet 635d2fd106 filename 2016-04-08 11:53:31 -04:00
peepsnet 905b268893 Debugging aliases
Some shortcuts to help us get users to be able to debug stratux
2016-04-08 11:50:59 -04:00
peepsnet 78fcc855a9 typo 2016-04-08 10:59:32 -04:00
peepsnet 98b340e51a typo 2016-04-08 10:59:10 -04:00
peepsnet b0e58058a4 Stratux specific alias file 2016-04-08 10:56:33 -04:00
AvSquirrel 859e8da9c2 Additional mutex lock for insertData() 2016-04-07 22:34:01 +00:00
AvSquirrel 0de359ec0e Remove extraneous LF 2016-04-07 08:27:07 +00:00
AvSquirrel 21bc97e9b6 Add disk usage / free space to log 2016-04-07 08:21:15 +00:00
AvSquirrel 1be1c9fdcf Improved binning for ownship track message 2016-04-07 06:31:50 +00:00
AvSquirrel be3e487267 Use float for GPS track. Rebin ownship track. 2016-04-07 05:24:12 +00:00
AvSquirrel d1ebc2df1d Fix geometric ownship alt overflow 2016-04-07 04:18:57 +00:00
AvSquirrel 64b20d2bca Testing more mutex protection for checkTimestamp() 2016-04-06 09:41:23 -05:00
AvSquirrel 23e2721c90 Add datalog mutex for timestamp 2016-04-06 03:01:10 +00:00
peepsnet 77f9708d56 keep an alias file after this file is modified
Since I am tired of my aliases being over written I am adding this so I can make my own alias file and not have it overwritten!!!!!!!!!!!!!

create a file called .aliases in /root and they will be included
2016-04-04 12:20:34 -04:00
Christopher Young 22a019b9a7 Remove temporary files on update. 2016-04-03 14:41:06 -04:00
Christopher Young 5da86d919f Comment out debugging data. 2016-04-03 14:16:00 -04:00
Christopher Young 8545a9ba0d Fix bulkInsert query logic problem. Maximum rows based on column limitation (999). Issue warning if SQLite is taking too long. 2016-04-03 14:10:42 -04:00
cyoung a39bc203a2 Merge pull request #361 from peepsnet/patch-1
Update mkimg.sh for hostapd_manager.sh
2016-04-03 13:56:06 -04:00
Christopher Young 0b1ca4b2da Fix temporary fix for generic NMEA GPS - Satellites = SatellitesTracked = SatellitesSeen. 2016-04-03 13:42:38 -04:00
cyoung a37855225c Merge pull request #366 from peepsnet/patch-3
Correct typo and clarify instructions for hostapd_manager.sh
2016-04-03 11:00:33 -04:00
peepsnet 9cdd5e3af2 Correct typo and clarify instructions 2016-04-03 01:27:14 -04:00
cyoung 73236d73c8 Merge pull request #363 from cyoung/sqlite_logging
Sqlite logging.
2016-04-02 16:18:35 -04:00
Christopher Young feaffc07fc Compile with 4 cores. 2016-04-02 16:01:07 -04:00
Christopher Young 9607311dbe Increase batch size to 1,000 up to a maximum query size 750,000 bytes. 2016-04-02 15:57:05 -04:00
Christopher Young da4eb3dfc8 Type fix. 2016-04-02 15:40:25 -04:00
Christopher Young 1b093ef1bb INSERT speed fixes. 2016-04-02 15:33:19 -04:00
peepsnet 0b4df811ab Update mkimg.sh for hostapd_manager.sh
copy file to location and chmod
2016-04-01 19:42:54 -04:00
cyoung 2d10744cfe Merge pull request #360 from cyoung/sqlite_logging
Sqlite logging.
2016-04-01 18:44:11 -04:00
Christopher Young 980977146e Remove debugging code. 2016-04-01 18:42:28 -04:00
Christopher Young 8cc6534761 Remove debugging code. 2016-04-01 18:33:01 -04:00
Christopher Young 62dd58b07f Use batched inserts instead of prepared statements. 2016-04-01 18:25:53 -04:00
cyoung 8b56f1f6de Merge pull request #359 from peepsnet/patch-1
Bash script to modify hostapd.conf and hostapd-edimax.conf
2016-04-01 16:53:16 -04:00
Christopher Young f1f3977e5b Used prepared statements for SQLite inserts. 2016-04-01 15:42:46 -04:00
peepsnet 47bc631568 Completely rewritten for command line flags
Help documentation for go.sh.

Basic usage: hostapd_manager.sh -s ssid -c chan -e pass

Command line switches are optional. The following switches are recognized.
-s  --Sets the SSID to ssid. "-s stratux"
-c  --Sets the channel to chan. "-c 1"
-e  --Turns on encryption with passphrase pass. 8-13 Printable Characters. Cannot be used with -o. "-e password!"
-o  --Turns off encryption and sets network to open. Cannot be used with -e.
-h  --Displays this help message. No further functions are performed.

Example: hostapd_manager.sh -s stratux -c 1 -e N3558D
2016-04-01 15:00:51 -04:00
Christopher Young dbacc6b6e7 Move db writes to a separate goroutine. 2016-04-01 14:05:23 -04:00
peepsnet cb8a531710 Update hostapd_manager.sh
typo
2016-04-01 12:37:28 -04:00
Christopher Young 044a95d801 Stratux shutdown and archive log database when upgrading. 2016-04-01 12:00:21 -04:00
Christopher Young 268ea23ce5 Use tmp variable to assign. 2016-04-01 08:40:09 -04:00
Christopher Young 2bfb5d8c33 Typo. 2016-04-01 08:36:10 -04:00
Christopher Young fdbde39e96 Extrapolate GPS timestamps with stratuxClock. 2016-04-01 08:34:37 -04:00
Christopher Young b87aa52044 Batch data writes.
This will be done as part of a system where the database file is
compressed and moved periodically.
2016-04-01 08:26:37 -04:00
peepsnet 93841cc4f5 Update hostapd_manager.sh 2016-04-01 01:48:49 -04:00
peepsnet 267c906354 Update hostapd_manager.sh 2016-04-01 01:45:50 -04:00
peepsnet 6a8eb2b3c9 Update hostapd_manager.sh 2016-04-01 01:44:59 -04:00
peepsnet 5612e70e27 Update hostapd_manager.sh 2016-04-01 01:44:23 -04:00
peepsnet 039e0c231e Hostapd_manager.sh
File to modify:
/etc/hostapd/hostapd.conf
/etc/hostapd/hostapd-edimax.conf

This is a improvement on the script that was uploaded to reddit. 
https://www.reddit.com/r/stratux/comments/4c0ffw/change_ssid_bash_script/

usage:
hostapd_manager.sh ssid channel passphrase
2016-04-01 00:59:50 -04:00
Christopher Young 4e5513ce95 Send traffic update to logTraffic(). 2016-03-31 20:39:02 -04:00
Christopher Young 7ad31e9414 Temp. 2016-03-26 17:25:32 -04:00
Christopher Young ce1617af93 Remove further remnants of replay logging. 2016-03-26 17:24:08 -04:00
Christopher Young c6c8c22b63 Stratux plugin beginning. 2016-03-26 17:23:08 -04:00
Christopher Young 480426cdd1 Remove further remnants of replay logging. 2016-03-26 17:19:59 -04:00
Christopher Young e0f82b0a29 Data logging graceful shutdown. 2016-03-26 17:15:59 -04:00
Christopher Young 0199d49238 Move dump1090 terminal logging to datalog package. Remove remnants of replay logging. 2016-03-26 17:12:26 -04:00
Christopher Young fa28ac210c Remove UAT and ES replay logging. Add datalog functions for UAT and ES messages. 2016-03-26 16:49:57 -04:00
Christopher Young cb113cb804 Remove AHRS replay log. 2016-03-26 16:37:33 -04:00
Christopher Young aa2bd06fd0 Remove GPS replay log. 2016-03-26 16:34:02 -04:00
Christopher Young bcf20249e8 Don't log situation or traffic data unless globalSettings.ReplayLog is true. 2016-03-25 11:58:44 -04:00
Christopher Young 8de91a55f0 Remove extra help info.
PR #268.
2016-03-24 19:31:42 -04:00
Christopher Young 7c5da8ab55 Newline. 2016-03-24 18:08:42 -04:00
Christopher Young 32097e3b61 Debug output cleanup. 2016-03-24 17:28:00 -04:00
Christopher Young a86314e883 Cleanup. 2016-03-24 17:26:59 -04:00
Christopher Young ce566ae5d3 Use stratuxClock to check timestamp age. 2016-03-24 12:59:29 -04:00
Christopher Young d9bbe5881c Revert PR #352. 2016-03-24 12:39:26 -04:00
Christopher Young fbc7c6f168 Typo. 2016-03-24 12:13:08 -04:00
Christopher Young bd4f4c8743 Log status. 2016-03-24 10:51:12 -04:00
Christopher Young 5680908301 Track the last NMEA message in SituationData. 2016-03-24 10:37:24 -04:00
cyoung 5073fdadb6 Merge pull request #352 from jpoirier/go-checker
check for the go command not GOROOT
2016-03-24 10:34:44 -04:00
Christopher Young 937bbecd28 Refactoring and cleanup. 2016-03-24 10:23:29 -04:00
Joseph Poirier a1ee8dd5e1 check for the go command not GOROOT 2016-03-24 08:45:59 -05:00
Christopher Young 854b96f608 More data logger boilerplate. Add to Makefile and init in main(). 2016-03-24 09:33:11 -04:00
Christopher Young 67d62184d3 Save GPSTime in SituationData struct. 2016-03-24 08:59:34 -04:00
Christopher Young bcef2ba823 Improve main logger goroutine. 2016-03-24 01:14:48 -04:00
Christopher Young 275c1740f0 Export all possible status fields. 2016-03-24 00:29:08 -04:00
Christopher Young 0a26cfc240 Export all possible SituationData fields. 2016-03-24 00:26:56 -04:00
Christopher Young 934c24ee71 Generalized logData(), added test code. 2016-03-24 00:23:12 -04:00
Christopher Young 80f1007a6a Add struct .String() marshaling. Insert data function. 2016-03-23 23:08:00 -04:00
Christopher Young e12611e8d4 Initial commit: data logger functions. 2016-03-23 12:31:13 -04:00
cyoung 3272867964 Merge pull request #349 from jpoirier/circleci-prs
circleci: allows PRs to correctly build themselves when the PR happens
2016-03-23 11:08:42 -04:00
Joseph Poirier b63dfb198d circleci: allows PRs to correctly build themselves when the PR happens 2016-03-23 09:57:01 -05:00
cyoung fe8b440e9e Merge pull request #347 from jpoirier/development
image: add rpi0 and explicit edimax dongle check
2016-03-23 10:07:42 -04:00
Christopher Young 9754f19be2 Hide more debug printing. 2016-03-23 09:19:11 -04:00
Christopher Young f1ce8a75bc Hide more debug printing. 2016-03-23 09:18:28 -04:00
Joseph Poirier 7790f4e6ff image: add rpi0 and explicit edimax dongle check 2016-03-23 03:03:35 -05:00
Christopher Young b8c17e0460 Checking for specific hardware builds. 2016-03-22 11:43:00 -04:00
cyoung 9f40afdc21 Merge pull request #344 from egid/master
Tweak error messages to use FontAwesome icon and stock angular maui colors.
2016-03-22 10:39:43 -04:00
Eric Gideon 13ccff9842 Tweak error messages to use FontAwesome icon and stock angular maui colors. 2016-03-21 20:49:32 -07:00
Christopher Young 1a808ca591 Redefine "connected"/"recent" clients = recently pingable hosts. 2016-03-21 20:32:24 -04:00
Christopher Young 65537dbdc8 Issue a warning and disable features when FF broadcast messages are received.
Fixes #332.
2016-03-21 16:31:56 -04:00
Christopher Young a93501f8f4 Debug output. 2016-03-21 16:16:12 -04:00
Christopher Young 6afb4ec415 Cleanup. 2016-03-21 15:58:48 -04:00
Christopher Young f732eb2289 Add /etc/modules to mkimg and makeupdate. 2016-03-21 14:48:38 -04:00
Christopher Young db130aab76 Add /root/.bashrc to mkimg and makeupdate. 2016-03-21 13:42:10 -04:00
Christopher Young 6a9f1ff8e6 Add /etc/modprobe.d/rtl-sdr-blacklist.conf to mkimg and makeupdate. 2016-03-21 13:38:12 -04:00
Christopher Young 5c6e493fca Add /boot/config.txt to mkimg and makeupdate. 2016-03-21 13:05:42 -04:00
Christopher Young dfc6635f94 Cleanup. 2016-03-21 13:04:05 -04:00
Christopher Young b2eb382c1a Remove DHCP lease expiry code.
Fixes #325.
2016-03-20 00:56:21 -04:00
Christopher Young 1f9a5dde35 Update hostapd.conf with .sh update. 2016-03-18 15:59:53 -04:00
cyoung 2319b53ad1 Merge pull request #341 from jpoirier/hostapd_conf_fix
fix wmm parameter name
2016-03-18 15:58:19 -04:00
Joseph Poirier 279ab071ac fix wmm parameter name 2016-03-18 14:29:46 -05:00
Christopher Young 070626dc1f Temp. 2016-03-17 16:56:12 -04:00
Christopher Young 616a2b9fbd Add /boot/config.txt settings. 2016-03-17 16:55:03 -04:00
Christopher Young 2b1acf49a2 Remove wifi_watch.sh and rc.local start. 2016-03-17 16:54:45 -04:00
Christopher Young c3ecbf0b7c More setup changes. 2016-03-16 12:13:07 -04:00
Christopher Young a6b7ac17ab Update filename. 2016-03-16 11:55:47 -04:00
Christopher Young 6ced449faa Update script name. 2016-03-16 11:37:56 -04:00
Christopher Young b38045da03 Eliminate wifi_watch.sh by using post-up. 2016-03-16 11:32:58 -04:00
Christopher Young a6ffea0122 Eliminate hostapd startup scripts. Create stratux-wifi wifi start script. Use post-up for hostapd/dhcpd start. 2016-03-16 11:32:22 -04:00
Christopher Young 63491e525c Added two hostapd versions, two hostapd confs. 2016-03-16 10:37:19 -04:00
Christopher Young 84edd98b7e Initial commit - RPi2 (Edimax) and RPi3 confs, Edimax hostapd binary. 2016-03-16 09:44:37 -04:00
Christopher Young b160566288 Update test program. 2016-03-16 08:40:29 -04:00
cyoung bf86dc2ea3 Merge pull request #337 from jpoirier/development
fix cb funct type arg count, circleci branch specific builds, move cgo flag
2016-03-16 08:23:10 -04:00
cyoung 3ae0439429 Merge pull request #338 from jpoirier/godump978_init
auto init on package import
2016-03-16 08:20:39 -04:00
Joseph Poirier 799ee42bc1 fix circleci checkouts so PRs work 2016-03-16 07:14:07 -05:00
Joseph Poirier dbca0fb0b0 auto init on package import 2016-03-16 06:58:01 -05:00
Joseph Poirier 634c3abf3a fix cb function type arg count, circleci branch specific builds, move cgo flag 2016-03-16 06:41:19 -05:00
Christopher Young d3ee8dce97 Comment update. 2016-03-15 22:41:47 -04:00
cyoung 2224d131b6 Merge pull request #334 from jpoirier/xdump1090_fix
sdr: fix 1090 shutdown hang, add shutdown completed messages
2016-03-15 22:40:59 -04:00
Christopher Young c96ee7bce4 RPi3/RPi2 detect. 2016-03-15 00:27:47 -04:00
Christopher Young fae350408f Initial commit. 2016-03-14 23:29:41 -04:00
Christopher Young 4d475587a9 Initial commit. 2016-03-14 23:28:14 -04:00
Joseph Poirier 9d2d4850af sdr: fix type 2016-03-14 15:49:00 -05:00
Joseph Poirier c5aacf0fbd sdr: capture state locally prior to processing 2016-03-14 15:47:33 -05:00
Joseph Poirier 529b453ba2 sdr: replace Scan due to a report that it was still blocking, split stderr and stdout 2016-03-14 02:23:03 -05:00
Joseph Poirier 336d17d615 fix stray curley brace 2016-03-13 00:09:31 -06:00
Joseph Poirier 6f1625f1f7 Merge pull request #1 from zendor/dump1090_fix
updated shutdown to use a separate thread to kill dump1090
2016-03-12 20:54:34 -06:00
Allan Feldman 5939c0c368 fix a bad merge which deleted a brace 2016-03-12 18:19:07 -08:00
Allan Feldman cf94e0c79f updated shutdown to use a separate thread to kill dump1090 2016-03-12 18:13:03 -08:00
Joseph Poirier dea3374242 sdr: handle premature dump1090 process exit 2016-03-12 16:58:11 -06:00
Joseph Poirier 10c9f73e2a fix 1090 shutdown hang, add shutdown completed messages 2016-03-11 19:29:46 -06:00
Christopher Young 4e452956dc Typos. 2016-03-10 15:03:38 -05:00
Christopher Young 66c29aa9a6 RO Partition rebuild from WebUI. 2016-03-10 14:57:54 -05:00
Christopher Young e356194eb2 Add "System Errors" to main status page. 2016-03-10 14:41:30 -05:00
Christopher Young ac5a054e7d Logic error. 2016-03-10 13:29:07 -05:00
Christopher Young e5026f66c1 Add HardwareBuild to globalStatus - only used for FlightBox currently. 2016-03-10 13:09:25 -05:00
Christopher Young e6bb6ce477 Add system-wide errors concept for display in WebUI. 2016-03-10 13:06:14 -05:00
Christopher Young dbe8ed5c3a Change default settings: GPS enabled. 2016-03-10 12:34:06 -05:00
Christopher Young 2e621cb426 Cleanup. 2016-03-10 12:33:03 -05:00
Christopher Young f880d1e61a Add DroidEFB. 2016-03-10 10:33:43 -05:00
Christopher Young e4d74e221c Only show some debug output depending on globalSettings.DEBUG. 2016-03-10 10:20:46 -05:00
Christopher Young 009d7219f2 Sudo needed for CircleCI. 2016-03-09 09:01:55 -05:00
Christopher Young ee42e324f2 Remove sudo. 2016-03-09 08:54:13 -05:00
Christopher Young 796d0a2632 /view_logs page.
Fixes #232.
2016-03-07 23:51:53 -05:00
Christopher Young 3fa36963f0 Fix variable out of scope. 2016-03-07 21:36:30 -05:00
Christopher Young 1308e74587 Roll back webserver, use Go as webserver. 2016-03-07 21:33:28 -05:00
Christopher Young bcf7bbb053 Roll back webserver, use Go as webserver. 2016-03-07 21:29:35 -05:00
cyoung e98d55d8d7 Merge pull request #312 from jpoirier/development
sdr: comments and more idiomatic code
2016-03-07 21:22:47 -05:00
Joseph Poirier f0179b0c06 sdr: comments and more idiomatic code 2016-03-07 19:53:50 -06:00
Christopher Young d1d00d5bfb Cleanup. 2016-03-07 20:14:44 -05:00
Christopher Young bb6b2c5d70 Move /updateUpload URL to :8080 address. 2016-03-07 20:06:09 -05:00
Christopher Young 9bdef48b4b Cleanup. a+x /var/log/stratux default permissions. 2016-03-07 19:49:46 -05:00
cyoung e1a41f773f Merge pull request #266 from cyoung/separate_httpd
use standalone httpd service / move stratux services to port 8080
2016-03-07 19:20:28 -05:00
cyoung 2f9105bff9 Merge pull request #308 from jpoirier/development
minor tweaks
2016-03-07 19:16:47 -05:00
Joseph Poirier 13d8d7bbaf minor tweaks 2016-03-06 14:40:42 -06:00
cyoung 17ab2e5c41 Merge pull request #306 from bkwny/master
Update status.js to repair issue #299.
2016-03-04 20:30:33 -05:00
bkwny 3e17f9778d Merge pull request #1 from bkwny/bkwny-patch-1
Update status.js to repair issue #299.
2016-03-04 20:26:32 -05:00
bkwny d925990455 Update status.js
Add days to Uptime: value.  Express uptime in Mission Elapsed Time (MET) format.
2016-03-04 20:14:57 -05:00
Christopher Young afd57c8320 Remove duplicate iFly device. 2016-03-03 13:13:54 -05:00
Christopher Young f031ca3c04 Add iFly GPS 9.4+. 2016-03-03 13:11:57 -05:00
Christopher Young 4bf26079d1 Add AvPlan EFB. 2016-03-03 11:26:49 -05:00
cyoung bf0efb18de Merge pull request #303 from jpoirier/development
sdr: comment reflects behavior
2016-03-03 00:13:32 -05:00
Joseph Poirier 3640db4230 sdr: comment reflects behavior 2016-03-02 23:05:52 -06:00
cyoung 83eda624ce Merge pull request #302 from jpoirier/development
sdr: remove erroneous comment
2016-03-02 21:34:08 -05:00
Joseph Poirier 35f27f71ea sdr: remove erroneous comment 2016-03-02 20:27:12 -06:00
cyoung 4c144b07f9 Merge pull request #301 from jpoirier/development
sdr: some refactoring
2016-03-02 21:25:33 -05:00
Joseph Poirier 04fd251aca sdr: update comment 2016-03-02 20:22:50 -06:00
Joseph Poirier 1c08a12fff sdr: some refactoring 2016-03-02 20:02:33 -06:00
Christopher Young d714a5139e Issue template formatting. 2016-03-01 09:22:51 -05:00
Christopher Young 6af23ac54d Add issue template. 2016-03-01 09:17:56 -05:00
Christopher Young 0d67cb855b Display first 10 characters of Build hash next to version. 2016-02-28 22:53:59 -05:00
Christopher Young d2a3f9433a Add 'Build' to status struct. 2016-02-28 22:29:40 -05:00
Christopher Young 1c99b26ab4 Typo fix (again). 2016-02-28 22:23:27 -05:00
cyoung 2e80d63840 Merge pull request #296 from jpoirier/development
sdr: when cmd.Start fails use the proper shutdown procedure
2016-02-28 22:17:29 -05:00
Joseph Poirier f508d0331c Merge branch 'master' into development 2016-02-28 21:11:29 -06:00
Joseph Poirier 45b559e826 remove empty line 2016-02-28 21:04:40 -06:00
Christopher Young fa084c7a7a Change update file names. 2016-02-28 22:03:48 -05:00
Joseph Poirier 77ff0daee6 fix spelling 2016-02-28 20:57:36 -06:00
Joseph Poirier 3716f4e845 fix conflict 2016-02-28 20:54:48 -06:00
Joseph Poirier 5384d26f4d Merge branch 'development' of github.com:jpoirier/stratux into development 2016-02-28 20:51:06 -06:00
Joseph Poirier 493097c626 sdr: when cmdStart fails use the proper shutdown procedure 2016-02-28 20:50:40 -06:00
Joseph Poirier beeff7514b sdr: when cmd.Start fails use the proper shutdown propcedure 2016-02-28 20:46:13 -06:00
Christopher Young a5a02ff4d5 Typo fix. 2016-02-28 21:41:40 -05:00
cyoung f6dc54cde4 Merge pull request #292 from AvSquirrel/new_dump1090
Incorporate dump1090-mutability; improved signal strength reporting; bug fixes
2016-02-28 21:37:42 -05:00
cyoung 347ff4c362 Merge pull request #291 from jpoirier/development
when a dongle fails then close its process, ES read stdout/stderr simplified, update gitignore
2016-02-28 21:34:21 -05:00
Christopher Young 857b71b716 Added WiFi watcher script from @AvSquirrel.
Fixes #246.
2016-02-28 12:49:17 -05:00
Joseph Poirier 5483a4c095 Merge branch 'master' into development 2016-02-28 11:20:04 -06:00
Joseph Poirier 6aed4e1cb2 modify comment, update gitignore file 2016-02-28 11:18:21 -06:00
Christopher Young f034df937d Use CircleCI only as a signal for build process. 2016-02-28 12:03:28 -05:00
AvSquirrel 769169d722 Revise dump1090 for CA/CF reporting. Clean up demo traffic type identification. 2016-02-28 01:33:27 +00:00
AvSquirrel 1a5172e596 Tower signal strength, other bug fixes 2016-02-27 08:35:17 +00:00
Joseph Poirier 73dd2d7025 remove trailing whitespace 2016-02-27 02:25:34 -06:00
AvSquirrel 70abc35514 Merge remote-tracking branch 'upstream/master' into new_dump1090 2016-02-27 07:13:04 +00:00
AvSquirrel c3809c779e Add dump1090 heartbeat detection 2016-02-27 07:12:22 +00:00
Christopher Young 6762c01935 Add SSH key to CircleCI deployment. 2016-02-27 01:19:42 -05:00
Christopher Young d2f8a7d0de CircleCI package/upload to webserver. 2016-02-27 01:11:17 -05:00
Joseph Poirier 100afa42f2 comment update 2016-02-27 00:05:37 -06:00
AvSquirrel a9b631e732 Incorporate dump1090-mutability 2016-02-27 06:04:41 +00:00
Joseph Poirier d9a2667c18 add comment 2016-02-27 00:02:18 -06:00
Joseph Poirier 290ec802ad fix typo 2016-02-27 00:00:53 -06:00
Christopher Young 8f28239dd8 Typo fix. Addresses #267. 2016-02-27 00:55:14 -05:00
Joseph Poirier b9f18cdc2e comment update 2016-02-26 23:49:11 -06:00
Joseph Poirier e9271073e1 fix print statement 2016-02-26 23:46:39 -06:00
Christopher Young e97b7f5e4c Fixes #289. 2016-02-27 00:46:19 -05:00
Joseph Poirier 5f2a0e6509 fix copy/paste error 2016-02-26 23:40:08 -06:00
AvSquirrel 374ea26c5e Allow NIC=0 UAT traffic. Tweaks to demo traffic. 2016-02-27 05:36:33 +00:00
Joseph Poirier 143f395cb4 formatting 2016-02-26 23:27:36 -06:00
Joseph Poirier 34e079d047 close process when dongle fails, ES read stdout/stderr simplified, update gitignore 2016-02-26 23:22:40 -06:00
AvSquirrel e8ba0a30a5 Simplify UAT power calculation 2016-02-27 02:42:56 +00:00
Christopher Young 1ba74a9f1d Remove CircleCI hacks. 2016-02-26 21:19:14 -05:00
Christopher Young bc11d854e6 Typo fix. 2016-02-26 13:42:59 -05:00
Christopher Young f1f467249b Change some log prints to display only when globalSettings.DEBUG is true. 2016-02-26 13:37:45 -05:00
Christopher Young 6464d07b0b CircleCI hacks. 2016-02-26 13:03:31 -05:00
Christopher Young 63f0cb5daa CircleCI hacks. 2016-02-26 12:59:25 -05:00
Christopher Young 0f852bc3d1 Add AvSquirrel/dump1090. 2016-02-26 12:54:33 -05:00
Christopher Young 345bcc7e22 Add AvSquirrel/dump1090. 2016-02-26 12:51:31 -05:00
Christopher Young 7d199a946f Remove dump1090. 2016-02-26 12:50:49 -05:00
Christopher Young 38017426aa CircleCI update. 2016-02-26 12:38:35 -05:00
Christopher Young 6dd77c0bd2 Add AvSquirrel/dump1090 submodule. 2016-02-26 12:32:14 -05:00
Christopher Young b1cbc74b54 Remove dump1090 submodule. 2016-02-26 12:27:33 -05:00
Christopher Young 6a23888aa0 Use git:// instead of https:// 2016-02-26 12:20:44 -05:00
Christopher Young e3ab2af9ca Remove submodule directories before update. 2016-02-26 12:14:35 -05:00
Christopher Young 1cee936266 Formatting. 2016-02-26 12:08:01 -05:00
Christopher Young c85f3a0787 CircleCI remove cached files. 2016-02-26 12:07:33 -05:00
cyoung 7007d18606 Merge pull request #285 from AvSquirrel/new_dump1090
Dump1090 improvements. Overhauled traffic parsing. UAT groundspeed and air/ground status bug fixes.
2016-02-26 11:35:09 -05:00
cyoung 002a99f50e Merge pull request #279 from jpoirier/sdr_cleanup
better anonymous & tagged dongle handling, sdr file cleanup
2016-02-26 11:19:03 -05:00
cyoung a86b73b558 Merge pull request #280 from peepsnet/patch-1
Change to be more specific in choosing update file
2016-02-26 11:14:30 -05:00
Christopher Young 4aa70c0dea Add 'CACHE' section to appcache manifest. 2016-02-26 11:11:13 -05:00
Ryan C. Braun 6594cdf5f4 Enhance Ping support, add RSSI and RS bit errors 2016-02-26 11:18:22 +00:00
Ryan C. Braun 6ae392af6d Merge branch 'master' of https://github.com/cyoung/stratux
Conflicts:
	main/gen_gdl90.go
	web/plates/js/settings.js
2016-05-04 05:50:52 +00:00
Ryan C. Braun e1e02a4bc7 Change network reconnect behavior from ping to dump1090 2016-05-04 05:45:18 +00:00
Ryan C. Braun 3348cf81da Add uAvionix Ping udev rules 2016-04-20 09:36:45 +00:00
Ryan C. Braun 69a933efdd Merge branch 'master' of https://github.com/cyoung/stratux
Conflicts:
	Makefile
	main/traffic.go
2016-04-20 09:29:56 +00:00
Ryan C. Braun 91fd133271 First cut of uAvionix Ping changes 2016-04-20 08:59:55 +00:00
AvSquirrel 5d4284b902 Web UI formatting 2016-02-25 06:40:52 +00:00
AvSquirrel 5d082e3292 Incorporate dump1090-mutability. UI signal strength and traffic improvements. 2016-02-25 05:53:35 +00:00
Joseph Poirier fb61a9df63 Merge branch 'master' into sdr_cleanup 2016-02-24 08:25:04 -06:00
Joseph Poirier c640418e80 add map type 2016-02-24 08:23:21 -06:00
Joseph Poirier 5e2209e906 small optimization and error handling comment 2016-02-24 08:18:40 -06:00
AvSquirrel 27dc75ca0e Wrong order in UAT max signal strength 2016-02-24 02:20:38 +00:00
AvSquirrel a1a3dd5fbf Update dump1090 reference to AvSquirrel b360db7 2016-02-24 02:12:12 +00:00
AvSquirrel 08c04ad5f7 Merge remote-tracking branch 'upstream/master' into new_dump1090 2016-02-24 02:03:41 +00:00
AvSquirrel 404f2456e6 Exclude traffic signal from tower max signal calc 2016-02-24 02:01:35 +00:00
AvSquirrel bd36732e49 Enable UAT signal strength for traffic (downlink) messages 2016-02-23 07:00:16 +00:00
AvSquirrel 60c082b0a0 Cleanup. Comment out demo mode and most debug log message. 2016-02-23 06:41:52 +00:00
AvSquirrel 62fec20bee Dump traffic list to log each second 2016-02-23 05:51:52 +00:00
AvSquirrel 2360f90861 Overhaul of makeTrafficReportMsg and parseDownlinkReport. Needs testing. 2016-02-23 05:45:39 +00:00
Joseph Poirier 0d5807cb23 fix for dual assigned dongles, remove wall of text 2016-02-22 13:01:11 -06:00
peepsnet 4ae11c37ca Change to be more specific in choosing update file
This change might prevent another update*.sh script from being executed since it is just looking in the root directory. 

This would require naming the update the same update*stratux*v*.sh
i.e.: update-stratux-v0.7b4-f98a8d58c6.sh

Just a bit more safety...
2016-02-22 12:39:14 -05:00
Joseph Poirier bdd8025921 comment formatting, again 2016-02-22 11:14:30 -06:00
Joseph Poirier 3f0e5b6cb0 comment formatting 2016-02-22 11:12:01 -06:00
Joseph Poirier 41da5d9346 fix range value 2016-02-22 11:02:03 -06:00
Joseph Poirier 8f60404ede fix copy and paste 2016-02-22 10:36:41 -06:00
Joseph Poirier b91b1ce06c fixes to handle all dongle scenarios, uat config fix back to print name 2016-02-22 10:34:51 -06:00
Joseph Poirier 6c35cd164f fixes after review 2016-02-22 07:37:44 -06:00
AvSquirrel 93a6dc9b4b Add fields for NACp and signal strength; cleanup 2016-02-22 07:39:20 +00:00
Joseph Poirier 8579891b05 fix type error 2016-02-21 21:41:30 -06:00
Joseph Poirier bec0cef610 rework the dongle and settings handling code, fixes #239 2016-02-21 21:28:53 -06:00
Joseph Poirier 862151cea6 regex updates and device fix 2016-02-21 14:02:57 -06:00
cyoung f98a8d58c6 Merge pull request #273 from peepsnet/master
Second wifi dongle settings template for Dev work
2016-02-21 14:07:56 -05:00
cyoung 7082241f0d Merge pull request #268 from AvSquirrel/traffic-ui
Show traffic source (ADS-B vs TIS-B) in web UI
2016-02-21 14:06:39 -05:00
Joseph Poirier 0ff1b5c16f fix rES hasID typo 2016-02-21 11:00:12 -06:00
Joseph Poirier ff9a5bec02 final UAT and ES struct fixes 2016-02-21 10:57:16 -06:00
Joseph Poirier 483567f186 UAT and ES struct fixes 2016-02-21 10:55:16 -06:00
Joseph Poirier 8fc7b9f81b fix typo 2016-02-21 10:44:55 -06:00
Joseph Poirier e9221e5097 cleanup and idiomatic code in prep for #239 2016-02-21 10:40:14 -06:00
AvSquirrel 17454c4276 Mutex bug fix 2016-02-21 12:02:47 +00:00
AvSquirrel ac69e7825a Add 1090 emitter category 2016-02-21 09:44:26 +00:00
AvSquirrel abf5869a57 New dump1090 format on port 30006 2016-02-21 07:06:58 +00:00
peepsnet d83c8f6e14 More cleanup 2016-02-20 12:00:25 -05:00
peepsnet bea1bdfe45 Corrected typos 2016-02-20 11:59:31 -05:00
peepsnet b44a513615 Comments
Commented all lines and added a bit more instruction
2016-02-20 11:59:01 -05:00
cyoung cebb1ba103 Merge pull request #272 from bjax/bjax-patch-1
Fixed typo "delimeted" -> "delimited". Fixes #271.
2016-02-20 08:30:29 -05:00
Bruce Jackson 78f9082fe3 Fixed typo "delimeted" -> "delimited" 2016-02-20 08:09:14 -05:00
AvSquirrel 6492dc7788 Show traffic source in web UI 2016-02-19 06:09:34 +00:00
bradanlane 36393d859b use standalone httpd service / move stratux services to port 8080 2016-02-18 14:37:10 -05:00
cyoung 7a2e49867a Merge pull request #264 from AvSquirrel/traffic-ui
Bug fixes for traffic UI and setting GPS time
2016-02-18 14:02:22 -05:00
cyoung a9c7baae6d Merge pull request #265 from cyoung/traffic_time_units
added 's' units to the traffic page
2016-02-18 14:02:09 -05:00
bradanlane f28c7a74d1 added 's' units to the traffic page 2016-02-18 13:38:06 -05:00
AvSquirrel 25dc8e617d Bug fix for setting GPS time from RMC messages 2016-02-18 11:53:43 -06:00
cyoung 3a96f04394 Merge pull request #261 from yihchun/master
Fixed a bug from #248
2016-02-18 09:59:30 -05:00
Yih-Chun Hu 4fba4de5bd bugfix of error checking 2016-02-18 13:35:28 +00:00
AvSquirrel 9ad3a7e333 Decrease traffic UI timeout to 59 sec 2016-02-18 06:10:21 +00:00
Christopher Young 65559a38fd Remove irrelevant/old comments. 2016-02-18 00:34:21 -05:00
Christopher Young 44d4c826c2 Use .Since() instead of 'Now()'.Sub(). 2016-02-18 00:29:28 -05:00
cyoung 8ddeb1a7b0 Merge pull request #259 from AvSquirrel/traffic-ui
Traffic UI and other improvements
2016-02-18 00:25:32 -05:00
AvSquirrel 073f317909 Merge to upstream changes 2016-02-18 04:57:58 +00:00
AvSquirrel 8429eb5a53 Clean up comments 2016-02-18 04:50:27 +00:00
Christopher Young ca9bd3900b Typos. Fixes #258. 2016-02-17 23:42:58 -05:00
AvSquirrel 370725eb53 Implement improved traffic UI. Clean up status and traffic help pages. 2016-02-18 04:31:05 +00:00
AvSquirrel a900a8942d Update traffic UI to support ti.age 2016-02-18 02:12:50 +00:00
AvSquirrel a224db0ba4 Create and initialize ti.Age 2016-02-18 01:54:36 +00:00
AvSquirrel 3b510c146e Merge remote-tracking branch 'upstream/master' into traffic-ui 2016-02-18 00:48:25 +00:00
Christopher Young c165acd98e Add "Unix()" function to monotonic clock for "seconds-since-start".
#254.
2016-02-17 19:33:18 -05:00
cyoung cca7d15683 Merge pull request #257 from cyoung/webui_cleanup
some web ui cleanup
2016-02-17 18:19:13 -05:00
bradanlane 3da5c9becc added missing logs help, adjusted settings page layout, added basic filename checking for updates, cleaned up updates ui somewhat 2016-02-17 15:32:23 -05:00
AvSquirrel b49bb796ee Add Stratux time to traffic.js 2016-02-17 07:18:04 +00:00
AvSquirrel 367dedc5a6 Web UI clock data enhancements 2016-02-17 06:03:23 +00:00
cyoung 2e64c9ba37 Merge pull request #248 from yihchun/master
Fix for Issue #79
2016-02-17 00:05:24 -05:00
AvSquirrel 282f397368 Better GPS time resolution 2016-02-17 04:36:56 +00:00
AvSquirrel 48b5127af6 Improved demo traffic 2016-02-17 04:19:33 +00:00
AvSquirrel 878747e633 GPS improvements: clearer init messages, compatibility tweaks 2016-02-17 03:13:21 +00:00
root 9ff70d6633 Copy and paste error in the log message 2016-02-16 20:31:12 +00:00
root b356b64f15 Error checking and optimizations per jpoirier 2016-02-16 20:28:14 +00:00
peepsnet 8ea4089d99 Update interfaces 2016-02-16 14:20:00 -05:00
peepsnet 7918cbe629 Update interfaces 2016-02-16 13:50:49 -05:00
peepsnet aab98497dd Update interfaces 2016-02-16 12:43:27 -05:00
root 3cefce063b error on startup 2016-02-16 13:29:50 +00:00
root 9857f36023 Merge branch 'master' of https://github.com/cyoung/stratux 2016-02-16 13:19:47 +00:00
AvSquirrel 1695e97aa0 Restore UTC time for traffic age 2016-02-16 05:43:32 +00:00
AvSquirrel d57ed5f523 Blank out missing heading in traffic UI 2016-02-16 04:41:13 +00:00
Christopher Young d81051df00 Error checking. 2016-02-15 23:01:52 -05:00
Christopher Young 279a810db0 Skip expired leases. #230. 2016-02-15 22:21:15 -05:00
Christopher Young 02bf2251d8 Rough update process - startup script looks for update file, executes it, reboots. 2016-02-15 17:48:33 -05:00
Christopher Young f63f70d1d2 Remove "setNoCache()" from default web file get.
Cache manifest takes care of cache control now.
2016-02-15 17:13:22 -05:00
Christopher Young 3a01a4268d Scale back debug output. Use "log" instead of "fmt" for log printing. 2016-02-15 17:11:19 -05:00
Christopher Young 8931d7d55b Update uploader in "settings" on web interface.
#157.
2016-02-15 17:10:51 -05:00
Christopher Young deb39cb444 Force new link for startup script. 2016-02-15 16:22:37 -05:00
Christopher Young 57d9974152 Formatting. 2016-02-15 16:21:54 -05:00
root e101c10174 refactor, bug fix 2016-02-15 18:24:56 +00:00
root 2414087ede refactor 2016-02-15 18:21:43 +00:00
Christopher Young db727ba378 Make www fixes for selfupdate. 2016-02-15 13:09:40 -05:00
root 5201db4d07 Merge branch 'master' of https://github.com/cyoung/stratux 2016-02-15 18:04:40 +00:00
Christopher Young c2623d7f44 Formatting. 2016-02-15 12:58:06 -05:00
Christopher Young d25eb98272 Move www portion of Makefile to web/ dir. 2016-02-15 12:35:37 -05:00
Christopher Young f8b2ebd519 Initial commit - selfupdate scripts. 2016-02-15 12:27:27 -05:00
Christopher Young a4f5696a29 Clean up old startup scripts. 2016-02-15 11:48:10 -05:00
cyoung 0031ddc00c Merge pull request #249 from AvSquirrel/working
Networking improvements
2016-02-15 11:02:59 -05:00
AvSquirrel f2afc27d8f Improved message queue efficiency and status messaging 2016-02-15 05:04:38 +00:00
AvSquirrel e15c389975 Traffic message network optimization. Bug fix. 2016-02-15 01:27:02 +00:00
root 5d926a6274 Allows for per-SDR ppm information through RTL Serial numbers of
format stx:freq:ppm, such as stx:1090:20.
2016-02-13 20:30:33 +00:00
cyoung c7151b74c5 Merge pull request #244 from AvSquirrel/gps_memleak
Additional GPS compatibility improvements
2016-02-13 10:21:35 -05:00
cyoung f1195198b6 Merge pull request #243 from AvSquirrel/gps_memleak
GPS improvements: Support velocity / heading on older receivers; resolve stability issue related to disconnects
2016-02-11 23:12:20 -05:00
AvSquirrel 3aada2ee02 Additional gps bugfixes. Allow RMC to set quality status. 2016-02-12 04:07:30 +00:00
AvSquirrel 641068d80d Add track / speed support for RMC messages. Cleanup. 2016-02-12 03:20:35 +00:00
AvSquirrel b0621aae25 Clean up handlers for GPS track / speed 2016-02-12 02:00:57 +00:00
AvSquirrel a78b4d3e4d GPS - Parse NMEA v2.2 and earlier VTG messages 2016-02-11 03:03:53 +00:00
AvSquirrel 211d3a29ed Fix memory leak in serial GPS reader 2016-02-10 07:06:52 +00:00
Christopher Young fefe314848 Formatting. 2016-02-08 00:12:14 -05:00
cyoung 4812b9c852 Merge pull request #231 from iposva/master
Detect and setup GlobalSat BU-353
2016-02-08 00:09:00 -05:00
Christopher Young 8df47d80bb Add AerovieReports. 2016-02-08 00:06:28 -05:00
Christopher Young 1e8ae2e6f8 Add timestamps and metadata to output for signal performance work.
@Axtel4.
2016-02-07 22:52:33 -05:00
Ivan Posva 30a967b87e Avoid writing arrays of bytes and handle generation of NMEA check sum. 2016-02-05 07:41:09 +00:00
cyoung 41b091f78b Merge pull request #238 from AvSquirrel/gps_ui_fix
Detect disconnected GPS. Update web UI and attempt reconnect.
2016-02-04 21:42:44 -05:00
AvSquirrel 90605ef032 Detect disconnected GPS. Update web UI and attempt reconnect. 2016-02-05 01:08:12 +00:00
Ivan Posva eb1f8a2b3d Enable 5Hz Navigation.
Switch the serial port to 38400 baud before any configuration.
2016-02-04 10:05:05 +00:00
Ivan Posva 355e9681a4 Merge remote-tracking branch 'upstream/master' 2016-02-02 21:51:41 -08:00
Ivan Posva fb1775bdbf - Remove debugging prints. 2016-02-02 21:44:54 -08:00
Christopher Young bfeb190339 Move getairmet to test tools dir. 2016-02-02 11:30:26 -05:00
Christopher Young 5b04e94098 Move getairmet to test tools dir. 2016-02-02 11:28:13 -05:00
Ivan Posva 1c383bda23 - Discover GlobalSat BU-353-S4 USB GPS at /dev/ttyUSB0.
- Set appropriate baud rate.
- Enable VTG messages.
- Disable GSV messages.
2016-02-02 06:35:48 +00:00
Christopher Young 658f14bc79 Set RPi CPU governor to "powersave" mode.
Ref #222.
2016-01-29 15:42:59 -05:00
Christopher Young bbbcd3bbe1 Change terminology for status on weather/traffic/towers plates. Ref #210. 2016-01-29 14:41:30 -05:00
Christopher Young 442e882646 Cache manifest. Fixes #219. 2016-01-29 14:20:40 -05:00
Christopher Young 399a752025 Add signal strength and RS error to uatsummary output. 2016-01-29 10:30:26 -05:00
Christopher Young 0c614f6beb Debug output. 2016-01-29 10:22:23 -05:00
cyoung 9c1e679d16 Merge pull request #226 from cyoung/newprotocol
uatparse additions, AIRMET parsing.
2016-01-29 10:12:58 -05:00
cyoung 9ba317ab32 Merge pull request #224 from AvSquirrel/monotonic-fixes
Fix #223. Change ticker to 50 ms intervals for future improvements.
2016-01-27 07:56:35 -05:00
AvSquirrel 2f9ce16bfd Fix #223. Change ticker to 50 ms intervals for future improvements. 2016-01-26 23:27:09 -06:00
Christopher Young 1be927e672 Remove UAT SDR powersave. 2016-01-26 01:04:40 -05:00
Christopher Young 1f6c58350e PowerSave switch revert. 2016-01-26 01:03:26 -05:00
cyoung 30a14d0b2f Merge pull request #220 from jpoirier/development
dongle handling: remove misleading conflict msg, stricter string check
2016-01-26 01:00:44 -05:00
Christopher Young 2dfe38a927 Cleanup, max message rate. 2016-01-26 01:00:01 -05:00
Joseph Poirier e371039cd1 dongle handling: remove misleading conflict msg, stricter string check 2016-01-25 23:33:19 -06:00
Christopher Young 89dd33aba8 Remove UAT replay message re-logging. 2016-01-25 23:43:27 -05:00
Christopher Young a8708f15df Roll back to 1s traffic updates. 2016-01-25 23:16:31 -05:00
Christopher Young fd03b25d04 Disable X-Plane AHRS output port.
Not currently used by any app.
2016-01-24 22:19:34 -05:00
Christopher Young f5bed44086 Powersave switch. 2016-01-22 22:39:09 -05:00
cyoung 00024f1ca6 Merge pull request #213 from kdknigga/kdk_readme
Update the readme with a link to the FAQ and the official(?) website.
2016-01-20 14:18:14 -05:00
Christopher Young 5aca8adea2 CPU tweaks, networking tweaks. 2016-01-20 09:11:55 -05:00
Kris Knigga 5a989761f8 newline 2016-01-19 20:20:34 -06:00
Kris Knigga 9aeeb0abe7 Update the readme with a link to the FAQ and the official(?) website. 2016-01-19 20:05:34 -06:00
Christopher Young 57a9fbf393 Catch SIGINT and SIGTERM - shutdown SDR functions.
Fixes #204.
2016-01-19 10:40:40 -05:00
Christopher Young e0dde8d5de Add /getClients for debugging. 2016-01-19 09:50:02 -05:00
Christopher Young 3148ea6d8b Issue template. 2016-01-19 09:32:36 -05:00
Christopher Young 8f8bd363a2 Comments. 2016-01-19 08:39:46 -05:00
Christopher Young c832f6add7 linux-mpu9150 submodule update. 2016-01-11 11:19:40 -05:00
Christopher Young 1c69061c43 @AvSquirrel fixes.
Ref #190.
2016-01-11 11:16:25 -05:00
Christopher Young e00c7a82d1 Updated linux-mpu9150.
Fixes #190.
2016-01-10 16:03:54 -05:00
Christopher Young ae6ba61278 Cleanup.
Follow PR #195.
2016-01-10 15:56:57 -05:00
cyoung 92122743e5 Merge pull request #195 from jpoirier/development
only fetch serial id of unconfigured dongle
2016-01-10 15:55:53 -05:00
cyoung 57a9f49d0c Merge pull request #196 from cyoung/simplify_startstop
start/stop gen_gdl90 directly fron init.d-stratux
2016-01-10 15:53:46 -05:00
cyoung 812170d0ae Merge pull request #199 from braddward/updated-shutdown
Updated shutdown. Fixes #193.
2016-01-10 15:49:34 -05:00
Brad Ward 9897faea14 Added post reboot/shutdown messages 2016-01-09 15:00:19 -06:00
Brad Ward 53deb5f354 Changes to shutdown/reboot
Changed UI to provide better spacial separation of the shutdown and
reboot buttons.
Changed to call the shutdown and reboot methods via XHR POST.
2016-01-09 14:23:25 -06:00
Brad Ward 48eb3f7c65 Added methods for doing async posts for shutdown and reboot 2016-01-09 14:14:54 -06:00
cyoung 1420ad16e0 Merge pull request #198 from AvSquirrel/timezone-fix
GPS time zone fix. Don't assume Pi is set to UTC.
2016-01-09 13:25:57 -05:00
AvSquirrel e9e8c5c098 GPS time zone fix. Don't assume Pi is set to UTC. 2016-01-09 12:15:21 -06:00
bradanlane 4d85491f67 start/stop gen_gdl90 directly fron init.d-stratux 2016-01-08 16:02:57 -05:00
Joseph Poirier 40ce5dcde7 add serial to ES object 2016-01-08 09:35:26 -06:00
Joseph Poirier 4cbe3713a7 only fetch serial id of unconfigured dongle 2016-01-08 09:33:58 -06:00
cyoung 3c7d700cff Merge pull request #191 from AvSquirrel/GPS-20160105
GPS compatibility improvements: Parse lat-lng of arbitrary precision
2016-01-07 12:21:27 -05:00
Christopher Young 0f4fa6db22 Error. 2016-01-07 12:13:51 -05:00
Christopher Young cfd1541708 Use monotonic clock for status print.
#174.
2016-01-07 11:54:38 -05:00
Christopher Young f4c9af112a Use monotonic clock for RY835AI/GPS data check functions.
#174.
2016-01-07 11:47:01 -05:00
Christopher Young 363f411b45 Typo fix. 2016-01-07 11:42:37 -05:00
Christopher Young 24142bef73 Use monotonic clock for traffic tracking.
#174.
2016-01-07 11:42:30 -05:00
Christopher Young dcf50409e9 Use monotonic clock for message tracking.
#174.
2016-01-07 11:37:57 -05:00
Christopher Young 1382060024 Use monotonic clock for network/sleep functions.
#174.
2016-01-07 11:34:37 -05:00
Christopher Young ce5f185c0f Use monotonic clock for SDR/network timing.
#174.
2016-01-07 11:29:55 -05:00
Christopher Young f1a0355231 Add Since() function to monotonic clock. 2016-01-07 11:20:06 -05:00
Christopher Young 55983489a2 Add monotonic.go to Makefile. 2016-01-07 11:10:27 -05:00
Christopher Young 6303b0c536 Use monotonic timer for uptime.
Fixes #69.
2016-01-07 11:08:54 -05:00
Christopher Young 43ac4e8236 Disable ntpd on release image. 2016-01-07 10:28:24 -05:00
AvSquirrel 1971700f02 Add UBX-CFG files for u-center 2016-01-06 06:07:38 +00:00
AvSquirrel ee241c71fb Parse lat-lng of arbitrary precision 2016-01-06 03:09:42 +00:00
Christopher Young cf0296d77f Cleanup. 2016-01-05 11:09:06 -05:00
Christopher Young b0d1299fce Cleanup. 2016-01-05 11:08:16 -05:00
cyoung cc41a25900 Merge pull request #184 from braddward/updated-shutdown
Updated shutdown
2016-01-05 11:01:44 -05:00
cyoung 11907e84ff Merge pull request #186 from AvSquirrel/ahrsFusion
AHRS heading improvements. "Fallback" GPS message parsing
2016-01-04 11:42:31 -05:00
cyoung 951c750c59 Merge pull request #188 from cyoung/origin_src_fix_20160104
Fix transposed S/T in base40 decoding
2016-01-04 11:38:42 -05:00
bradanlane 21956790ba Fix transposed S/T in base40 decoding
the code at mutability/dump978 posted a fix for a typo in the base 40 decode. the 'S' and 'T' letters were transposed in the reference string.

reference: 564902f53b
2016-01-04 09:05:00 -05:00
Christopher Young 7d6f4eb7af Trigger traffic report on change. 2016-01-03 22:54:21 -05:00
AvSquirrel cdcfa1c8d7 Formatting 2016-01-04 00:14:29 +00:00
AvSquirrel 3bc45ac5be Remove debug log message 2016-01-04 00:12:10 +00:00
AvSquirrel c95ac50763 Merge remote-tracking branch 'upstream/master' into ahrsFusion 2016-01-04 00:10:32 +00:00
AvSquirrel caf155ca65 Improved GPS fallback code - added GSA parsing 2016-01-03 23:54:42 +00:00
Brad Ward 95364bab22 Merge branch 'updated-shutdown' of https://github.com/braddward/stratux into updated-shutdown 2016-01-03 13:34:05 -06:00
Brad Ward e07390feb1 Moved reboot and shutdown to settings panel. Added modal confirmation dialogs. 2016-01-03 13:21:41 -06:00
Brad Ward 738f062e7e Added help text for reboot and shutdown options 2016-01-03 13:21:15 -06:00
Brad Ward 1488e7d494 added ui-yeld-to=modals directive 2016-01-03 12:57:29 -06:00
Christopher Young bba257db6d Add SBS1 message type 5 "Surveillance alt message". 2016-01-03 13:52:33 -05:00
Christopher Young 65e82714b4 Add SBS1 message type comments. 2016-01-03 13:46:26 -05:00
Brad Ward fd9cde57ae Removed shutdown reboot buttons from status screen 2016-01-03 10:21:41 -06:00
Brad Ward 71d67cb3dc CSS for modal confirmation dialogs 2016-01-03 10:14:58 -06:00
Brad Ward fd39651fd7 additional css for modal dialogs 2016-01-03 09:47:27 -06:00
Brad Ward a79819a7db Merge remote-tracking branch 'cyoung/master' 2016-01-03 09:41:27 -06:00
Christopher Young f3a90a3d61 Remove dump978 binary copy from build process. 2016-01-02 22:33:06 -05:00
AvSquirrel 0c5aad28bf AHRS heading fixes 2016-01-02 00:40:17 +00:00
cyoung d682bb5cf0 Merge pull request #178 from AvSquirrel/ahrsFusion
Check for valid GPS date. Fix time string formatting.
2016-01-01 13:32:55 -05:00
AvSquirrel 0f611560d4 Check for valid GPS date. Fix time string formatting. 2016-01-01 05:46:25 +00:00
Christopher Young bb23bd507f Fix CPU status byte bug. Change link to spec. 2015-12-31 23:44:51 -05:00
Christopher Young 43b6bf7fc8 Change compiler flags dump978. 2015-12-31 23:44:51 -05:00
cyoung a99173a472 Merge pull request #175 from AvSquirrel/ahrsFusion
AHRS: Correct pitch/roll direction. New heading filter.
2015-12-31 12:05:12 -05:00
cyoung 482e87d8f5 Merge pull request #173 from AvSquirrel/trafficUI
Fix webUI zero GS bug
2015-12-31 11:04:08 -05:00
AvSquirrel 2d7e213af2 Reverse UI pitch animation direction 2015-12-31 07:32:31 +00:00
AvSquirrel 8410819ae2 AHRS roll direction fix. Experimental heading filter. 2015-12-31 07:10:10 +00:00
AvSquirrel 8a8b1e8674 Fix webUI zero GS bug 2015-12-31 01:01:36 +00:00
braddward 387232ee00 Merge pull request #1 from cyoung/master
Updating my fork
2015-12-29 19:20:20 -06:00
Christopher Young 09c738f4e9 Build process updates. 2015-12-29 19:51:53 -05:00
Christopher Young 17c43dbb3a Update build process to use new dump1090.
Fixes #171.
2015-12-29 19:50:33 -05:00
Christopher Young f21070414d Add dump1090 MalcolmRobb fork as submodule. 2015-12-29 19:40:41 -05:00
Christopher Young c2857c1e84 Remove dump1090. 2015-12-29 19:39:30 -05:00
Christopher Young 7c77a563a5 Formatting. 2015-12-29 17:52:10 -05:00
cyoung 1960167909 Merge pull request #170 from AvSquirrel/gps-fixes
Delay start of UART reads. Link dev logs to web UI.
2015-12-29 17:51:44 -05:00
Christopher Young 71d604f07e Manual fix for Pull Request #170. 2015-12-29 17:51:31 -05:00
Christopher Young 53db559c15 Manual fix for Pull Request #170. 2015-12-29 17:48:01 -05:00
Christopher Young dab97a2328 Set heading from GPS with sustained >=10kts.
Apply same to new source.
2015-12-29 17:14:03 -05:00
Christopher Young 32383c12c2 Set heading from GPS with sustained >=10kts.
Restore overwritten change.
2015-12-29 17:02:18 -05:00
Christopher Young 60e143bd36 Formatting. 2015-12-29 17:00:59 -05:00
AvSquirrel 5275f27a00 Link developer logs on 'Logs' page 2015-12-29 15:42:53 +00:00
AvSquirrel 48f3170df9 Add 250 ms delay before opening UART port at 38.4k 2015-12-29 02:55:37 +00:00
Christopher Young 052b4e2855 Add mySituation.SatellitesSeen to stratux.log status message. 2015-12-28 02:19:02 -05:00
Christopher Young d94e049ba2 Update GPS satellite variables even if isGPSValid() is false.
isGPSValid() only when “acceptable” solution is found, updating
variables shows progress.
2015-12-28 01:56:33 -05:00
Christopher Young 446112aced Formatting. 2015-12-28 01:54:04 -05:00
cyoung 502084c20f Merge pull request #169 from AvSquirrel/GPS-UBX2
Updated GPS initialization and parsing
2015-12-28 01:38:15 -05:00
AvSquirrel 799a247c6c Add geoid separation offset and satellites seen. 2015-12-28 05:57:31 +00:00
Christopher Young 3988257a6f Add FltPlan Go to official support list. 2015-12-27 22:27:06 -05:00
Christopher Young 720f964b05 git clone --recursive 2015-12-27 18:58:14 -05:00
Christopher Young 00f2a2491d Update Makefile to get submodules. 2015-12-27 18:42:24 -05:00
Christopher Young 59156e288d Update build to copy libimu.so. 2015-12-27 18:41:20 -05:00
cyoung 680284ee1e Merge pull request #167 from cyoung/ahrs
Integrate linux-mpu9150 for AHRS.
2015-12-27 18:38:26 -05:00
Christopher Young c45bcc7e74 Fix track correction. 2015-12-27 18:19:39 -05:00
Christopher Young c1859fb0be Set heading from GPS with sustained >=10kts. 2015-12-27 17:50:10 -05:00
Christopher Young 0088515be7 Change sensortest for new MPU6050 module. 2015-12-27 16:26:14 -05:00
Christopher Young b06262bd32 Fix CircleCI for submodule. 2015-12-27 16:16:34 -05:00
Christopher Young a35e3cb76f Use linux-mpu9150 DMP functions to retrieve position data. Remove old POC code. 2015-12-27 16:11:21 -05:00
Christopher Young 9f66732bfb Go get for all relevant directories. 2015-12-27 13:48:56 -05:00
Christopher Young 75f49f2951 Update Makefile for linux-mpu9150. 2015-12-27 13:33:04 -05:00
Christopher Young fe1b6ed9ef Add linux-mpu9150 external. 2015-12-27 13:21:15 -05:00
Christopher Young 1c231dd301 Fix websocket reconnect bug.
Fixes #164.
2015-12-27 13:11:55 -05:00
Christopher Young 4f56a4c7b3 Set "no cache" on all served pages.
Fixes #164.
2015-12-27 13:11:55 -05:00
cyoung 7f392a7d41 Merge pull request #166 from cyoung/powersave
Turn down UAT capture to 10% duty cylce when message rate is 0.
2015-12-27 10:30:43 -05:00
AvSquirrel 681e05f3a3 Add new GPS status messages 2015-12-27 08:47:37 +00:00
AvSquirrel 555f9ccb8c Clean branch for UBX NMEA configuration 2015-12-27 03:19:35 +00:00
AvSquirrel 1549d3b4c5 Merge branch 'master' of https://github.com/AvSquirrel/stratux 2015-12-27 03:00:25 +00:00
Christopher Young 24b28f225f Merge remote-tracking branch 'origin/master' into powersave 2015-12-26 17:47:33 -05:00
Christopher Young e23ce3f25d Update comment. 2015-12-26 17:47:29 -05:00
Christopher Young f51bd61b3b Typo. 2015-12-26 17:34:35 -05:00
Christopher Young cc418aa797 Merge fix. 2015-12-26 17:27:32 -05:00
Christopher Young 0215bc8fa4 Merge remote-tracking branch 'origin/master' into powersave 2015-12-26 17:23:34 -05:00
Christopher Young c88d15929c Reused var. 2015-12-26 17:23:25 -05:00
Christopher Young 268bc227c9 Merge remote-tracking branch 'origin/master' into powersave
# Conflicts:
#	main/network.go
2015-12-26 17:18:57 -05:00
Christopher Young ccd023f50c Version number for status message. 2015-12-26 17:17:53 -05:00
Christopher Young 7fb784dd0b GPS/AHRS on/off settings portion of status message. 2015-12-26 16:52:32 -05:00
Christopher Young 364f45603b Moved WingX to "official support". 2015-12-26 16:51:19 -05:00
AvSquirrel 42dbdf916b Merge pull request #13 from cyoung/master
Merge from cyoung master branch; post-0.5b2 fixes
2015-12-22 22:19:31 -06:00
Christopher Young 54231905c5 Use build string as a hex value instead of characters. 2015-12-22 17:37:39 -05:00
Christopher Young 01919b3ab9 Connected RY835AI y/n. 2015-12-22 17:18:14 -05:00
Christopher Young e3afdc0485 Logic error. 2015-12-22 17:17:02 -05:00
Christopher Young 1c10034411 Add docs on /traffic websocket. 2015-12-22 16:33:55 -05:00
Christopher Young b0b36e80a0 Change CPU temp calculation formula for status message. 2015-12-22 15:40:56 -05:00
Christopher Young 4f9b57007c New Makefile broke build process - fixed. 2015-12-21 14:41:53 -05:00
AvSquirrel a99a1a2316 Merge pull request #10 from cyoung/master
Update from cyoung master. Traffic altitude correction; queuing.
2015-12-20 23:44:13 -06:00
Christopher Young e6ad9aa830 Save some cycles when message queues aren't that large. 2015-12-21 00:05:47 -05:00
Christopher Young 72d989ed3b Save some cycles when message queues aren't that large. 2015-12-20 23:59:39 -05:00
Christopher Young 8d573788b1 Wait for UAT read goroutine to quit before calling .Close() on device. 2015-12-20 23:38:45 -05:00
cyoung 71b4f3c2c0 Merge pull request #154 from jpoirier/fix_alt
fixed altitude calculation as per GDL 90 data interface spec
2015-12-20 23:31:11 -05:00
Christopher Young c935cab08f Enable both UAT and 1090ES by default.
UAT takes priority if only one RTL-SDR device connected.
2015-12-20 21:56:53 -05:00
Joseph Poirier b765d55f7c updated example link 2015-12-20 18:20:38 -06:00
Joseph Poirier 227f4f5571 use smallest possible var size 2015-12-20 16:16:52 -06:00
Joseph Poirier 373c0fa956 fixed altitude calculation as per GDL 90 data interface spec 2015-12-20 15:34:36 -06:00
AvSquirrel 7968831370 Merge pull request #8 from cyoung/master
Updates from cyoung master. Stratux heartbeat, soft shutdown
2015-12-20 14:09:01 -06:00
Christopher Young b542ddc7ca Switch ordering in WingX heartbeat. 2015-12-19 23:35:46 -05:00
cyoung 2674b1076d Merge pull request #152 from braddward/shutdown
Shutdown and Reboot functions
2015-12-19 20:08:58 -05:00
Brad Ward 1c9a3a2ce2 Removed local constants in favor of using syscalls already defined exported constants 2015-12-20 00:56:36 +00:00
Brad Ward ee7804d124 Added shutdown/reboot feature
Added shutdown and reboot buttons to the status screen.
2015-12-19 15:21:19 -06:00
Brad Ward 3089cd5a3f Shutdown/Reboot
Added methods to shutdown and reboot the pi via syscalls
2015-12-19 15:18:00 -06:00
AvSquirrel 1e9d3ae747 Merge pull request #6 from cyoung/master
Pull latest cyoung commits including SX heartbeat
2015-12-19 13:05:20 -06:00
Christopher Young c01b72cbd0 Syntax highlighting. 2015-12-18 18:54:26 -05:00
Christopher Young a9be27f618 Formatting. 2015-12-18 18:53:36 -05:00
Christopher Young 117fa8711d Formatting. 2015-12-18 18:51:26 -05:00
Christopher Young b33b1ed098 Ref new status message. Web interface examples. 2015-12-18 18:50:39 -05:00
Christopher Young e7a19f2296 Invalid values - 0xFF.
Addresses #150.
2015-12-18 14:35:42 -05:00
Christopher Young 71400227dc WingX heartbeat.
Addresses #150.
2015-12-18 12:28:37 -05:00
Christopher Young d830548700 Don't log replayed data. 2015-12-17 16:35:42 -05:00
Christopher Young cc2ebfdb93 Use log for errors/debug output. 2015-12-17 16:22:05 -05:00
Christopher Young 495fb46fee Cleanup. 2015-12-17 16:11:17 -05:00
cyoung 6b9a750ddc Merge pull request #144 from jamez70/replay_integration_uncompressed_logs
Switched logs back to uncompressed. Replay now supported with command…
2015-12-17 14:53:42 -05:00
Christopher Young 3b5fe624dc Parse Overlay Geometry "8" (6.8.7).
Extended Range Circular Prism (AGL).
2015-12-15 18:16:42 -05:00
Christopher Young d6153029ab 0.2nm resolution on radii. 2015-12-15 18:02:35 -05:00
Christopher Young 32e0e4b8ae Parse Overlay Geometry "7" (6.18.7).
Extended Range Circular Prism (MSL).
2015-12-15 17:58:22 -05:00
Christopher Young 4eae84226a Parse Overlay Geometry "9" (6.18.8). 2015-12-15 16:36:51 -05:00
Christopher Young 2e5aa451a9 GDL90 docs. 2015-12-15 15:00:55 -05:00
Christopher Young ec4c652758 Group points in output with geohash. 2015-12-15 11:37:16 -05:00
Christopher Young 936b148026 Parse all date_time_format and record_applicability_options. 2015-12-15 11:13:46 -05:00
Christopher Young 2b05579b92 Format DLAC newlines. 2015-12-15 10:29:54 -05:00
Christopher Young b15bcf4f5d Some JSON output. 2015-12-14 22:41:47 -05:00
Christopher Young d94cc20ce3 Typo fix. 2015-12-14 02:46:21 -05:00
Christopher Young 0d759e91a0 Test program. Parsing some polygons. 2015-12-14 02:40:46 -05:00
AvSquirrel 2d2d64a038 Merge pull request #4 from cyoung/master
Merge updates from cyoung master
2015-12-13 23:29:53 -06:00
Christopher Young ecb7648999 Decode Product ID 8-13, DLAC text. 2015-12-13 21:54:50 -05:00
Christopher Young b337558f60 FIS-B information. 2015-12-13 21:54:31 -05:00
Christopher Young cdbf4e5cb3 ProductID 8-13 format info. 2015-12-13 20:35:08 -05:00
Christopher Young c75aababac UAT docs. 2015-12-13 20:05:14 -05:00
Jim Jacobsen bb8f0254e1 Added developer mode command line switch which allows uncompressed log files 2015-12-14 01:04:40 +00:00
Christopher Young 428345735a Decode all time formats. 2015-12-13 19:52:59 -05:00
Christopher Young afe4d08ddf Beginning. 2015-12-13 18:43:23 -05:00
Christopher Young a71c49951a Revert "Beginning."
This reverts commit 69281675b7.
2015-12-13 18:39:50 -05:00
Christopher Young 69281675b7 Beginning. 2015-12-13 18:23:57 -05:00
Christopher Young 6c20883e4e Revert "Beginning."
This reverts commit 1fc4e70152.
2015-12-13 18:23:12 -05:00
Christopher Young 1fc4e70152 Beginning. 2015-12-13 18:22:35 -05:00
cyoung 34eec10b5a Merge pull request #145 from cyoung/Bagarre
Add /situation WS with 100ms update.
2015-12-13 18:05:43 -05:00
cyoung 9df3822096 Merge pull request #143 from jamez70/bmp180_test
bmp180_read will do continuous reads on the bmp180 pressure sensor fo…
2015-12-13 17:39:33 -05:00
Jim Jacobsen 191752b3e8 Switched logs back to uncompressed. Replay now supported with command line arguments. specify -h for help with arguments 2015-12-13 20:19:15 +00:00
Jim Jacobsen 0ab0541986 bmp180_read will do continuous reads on the bmp180 pressure sensor for testing 2015-12-13 19:02:24 +00:00
cyoung de3f48b013 Merge pull request #135 from jamez70/makefile-build-test
Makefile build test
2015-12-13 12:04:49 -05:00
cyoung c287a7b70f Merge pull request #137 from jamez70/log-file-splitting
Added indexed logs instead of everything ending up in one file
2015-12-13 12:03:40 -05:00
Jim Jacobsen c81acbeab2 Added indexed logs instead of everything ending up in one file 2015-12-08 22:58:42 -06:00
Jim Jacobsen 5886a411ee Had to remove leading tab, was causing build issues 2015-12-06 19:01:47 +00:00
Jim Jacobsen 73cec0a220 Remove spaces from environment test 2015-12-06 18:39:07 +00:00
Jim Jacobsen 33332a9feb Updated for circleci 2015-12-06 18:35:32 +00:00
Jim Jacobsen b58f1993fd Update makefiles to build test apps 2015-12-06 18:01:21 +00:00
Christopher Young 0be0dce9d5 SDR device rec update. 2015-12-05 17:24:55 -05:00
Christopher Young 6a6b31b85c Use github.com/jpoirier/librtlsdr for image builds. 2015-12-03 16:24:30 -05:00
Christopher Young 0db686a14b gzip stream replay logs.
Addresses (partially) replay log file size mentioned in #131.
CPU impact is minimal, can still process 45,000+ UAT messages per min.
2015-12-02 12:18:52 -05:00
AvSquirrel e6b11f7d8f Merge pull request #1 from cyoung/master
Merge from cyoung master branch 2015-12-01
2015-12-01 19:38:17 -06:00
Christopher Young f315ca5799 Remove TP-LINK from supported adapters. Close #119. 2015-12-01 20:13:18 -05:00
Christopher Young a8dd42ef06 Fixes #124. 2015-12-01 20:11:33 -05:00
Christopher Young 306ee8fa57 Comment. 2015-12-01 19:32:20 -05:00
cyoung 3fc1f2de16 Merge pull request #127 from AvSquirrel/working
Add WAAS status to webUI. Correct unit casting error on ownship alt.
2015-12-01 19:29:36 -05:00
Christopher Young 9f5cf89705 Add /situation WS with 100ms update. 2015-12-01 19:23:35 -05:00
AvSquirrel 6184b7bc97 Add WAAS status to webUI. Correct unit casting error on ownship alt. 2015-11-25 03:43:07 +00:00
Christopher Young 25b8bf0402 Close() UAT device when not receiving messages.
Check for 10 seconds once every 60 seconds to see if we’re in range.
2015-11-21 17:54:37 -05:00
Christopher Young ab889fb116 Merge branch 'master' of https://www.github.com/cyoung/stratux 2015-11-17 18:12:02 -05:00
Christopher Young 335a21e3b3 Update Naviator. 2015-11-17 18:11:50 -05:00
Christopher Young ec88895038 Logic error. 2015-11-17 16:12:41 -05:00
Christopher Young 64277ef6ef Type fix. 2015-11-17 15:59:41 -05:00
Christopher Young 3d44242d50 Type fix. 2015-11-17 14:32:49 -05:00
Christopher Young 2633f0056a Pause UAT reading 75% of the time when no UAT messages are being received. 2015-11-17 14:31:21 -05:00
Christopher Young c4c427ddb2 Save some cycles when message queues aren't that large. 2015-11-17 14:21:05 -05:00
cyoung 94bfd8304e Merge pull request #118 from jpoirier/development
unquote ldflags command in build flag
2015-11-13 22:46:02 -05:00
Joseph Poirier abd4a50386 unquote ldflags command in build flag 2015-11-13 19:31:21 -06:00
cyoung 519b00088d Merge pull request #116 from jpoirier/development
add version/build/license badges/shields
2015-11-12 22:51:47 -05:00
Joseph Poirier 18c3693485 fix copy/paste error 2015-11-12 21:50:26 -06:00
Joseph Poirier ecccac6a64 add version/build/license badges/shields 2015-11-12 21:48:20 -06:00
cyoung b9934a8280 Merge pull request #112 from jpoirier/development
godump978 use system lib path, copy dump978 so before it's needed, fi…
2015-11-12 22:16:13 -05:00
Joseph Poirier c0e491f9d8 Merge master fix conflict 2015-11-12 20:23:53 -06:00
Joseph Poirier 8955599246 Revert "pipe dump1090's out to the logger"
This reverts commit d66047c4ea.
2015-11-12 20:15:01 -06:00
Christopher Young 252d68fe29 Change FF version rec. 2015-11-12 20:28:57 -05:00
Joseph Poirier d66047c4ea pipe dump1090's out to the logger 2015-11-12 14:19:12 -06:00
Christopher Young 724a87de48 Fixes #115. 2015-11-12 14:53:07 -05:00
Christopher Young 9dda52d200 Fixes #114. 2015-11-12 14:34:04 -05:00
Christopher Young 2c973ece39 Merge branch 'master' of https://www.github.com/cyoung/stratux 2015-11-12 14:26:57 -05:00
Christopher Young 7f50242867 Fixes #102.
START,Thu Nov 12 19:25:38 +0000 UTC 2015,Thu Nov 12 19:25:38 +0000
UTC 2015
     UNPAUSE,71289772
     2739899291,Found 2 device(s):
     2740283977,0: Realtek, RTL2838UHIDIR, SN: stratux:978
     2740438248,1: Realtek, RTL2838UHIDIR, SN: 00000001 (currently
selected)
     2740605904,Found Rafael Micro R820T tuner
     2740683299,Max available gain is: 49.60
     2740807935,Setting gain to: 49.60
     2740880330,Exact sample rate is: 2000000.052982 Hz
     2740943976,Gain reported by device: 49.60
2015-11-12 14:26:43 -05:00
Joseph Poirier 7850ca3634 godump978 use system lib path, copy dump978 so before it's needed, fixes for circleci builder 2015-11-11 19:07:34 -06:00
cyoung 3e623cc115 Merge pull request #110 from jpoirier/development
add freq mode specific writeID mehtods
2015-11-11 14:08:43 -05:00
Joseph Poirier cb01bcc731 cricl.yml cache the previously built go compiler folder 2015-11-11 13:04:58 -06:00
Joseph Poirier 6d46a66933 add freq mode specific writeID mehtods 2015-11-11 12:54:42 -06:00
bradanlane 9fb3a19ad1 fixed NaN for TAF weather reports 2015-11-11 12:37:15 -05:00
cyoung 3f2ad2d71e Merge pull request #109 from jpoirier/development
commnet out device count logging
2015-11-11 12:25:46 -05:00
Joseph Poirier ca6a77d19a commnet out device count logging 2015-11-11 11:18:02 -06:00
Christopher Young 3745a805b7 Fixed zombie process issue. 2015-11-10 20:02:37 -05:00
cyoung 01058ab4f1 Merge pull request #104 from jpoirier/development
s/return/break and comment out noisey log message
2015-11-10 19:33:01 -05:00
Joseph Poirier bfd72f877c s/break/return and comment out noisey log message 2015-11-10 18:14:29 -06:00
Christopher Young a5072f034d Ref #103.
Fixes log issue.
2015-11-10 18:52:54 -05:00
Christopher Young 91f9242c1a Fixes #85.
Everything was showing a day older since “date” starts at 1.

Changed the display format of age, not the prettiest but should be
something that is obvious whose units are which especially since its
format will vary often.
2015-11-10 18:45:18 -05:00
Christopher Young 5ddd7d1b65 Formatting. 2015-11-10 18:44:00 -05:00
Christopher Young c3d6ebaa2e Typo. 2015-11-10 17:49:44 -05:00
Christopher Young 9691d47a75 Mutex for uibroadcaster.sockets. 2015-11-10 17:27:06 -05:00
Christopher Young 3777d5a7c0 Merge branch 'master' of https://www.github.com/cyoung/stratux 2015-11-10 17:23:56 -05:00
Christopher Young 0cc762fdc2 Don't start dump1090 on boot - let gen_gdl90 start it. 2015-11-10 17:23:23 -05:00
cyoung 491028c15b Merge pull request #101 from cyoung/jdp_dev
Jdp dev
2015-11-09 20:50:37 -05:00
Joseph Poirier f7e9991db4 consistent error handling for GetFreqCorrection 2015-11-09 09:14:08 -06:00
Joseph Poirier cb2b1acccc remove small hack for freq correction; gortlsdr has been modified to handle -2 error from librtlsdr when requested ppm is the same as current ppm" 2015-11-09 09:10:55 -06:00
bradanlane e9a2d73cd3 compute age of weather reports relative to mobile device time; also fixed typos in tower-help 2015-11-07 10:25:39 -05:00
Joseph Poirier 76408d5828 comment out debug prints 2015-11-07 00:24:56 -06:00
Joseph Poirier f357d224c6 debug print cleanup 2015-11-06 23:48:44 -06:00
Joseph Poirier 07a9349ddf add missing curley brace 2015-11-06 23:37:15 -06:00
Joseph Poirier c5cf3898d3 better/fixed error GetFreqCorrection handling 2015-11-06 23:35:39 -06:00
Joseph Poirier 2dab583e8e handle librtlsdr returned error code inconsistencies where dev->corr == PPM when calling SetFreqCorrection 2015-11-06 23:18:15 -06:00
Joseph Poirier 18da53d028 debug prints for testing 2015-11-06 22:50:40 -06:00
Joseph Poirier c1932b26cc log prints for testing 2015-11-06 22:32:05 -06:00
Joseph Poirier 88ec861fb7 put back Devices assignment, change type for atomic store 2015-11-06 21:57:59 -06:00
Joseph Poirier cb1dbcf92f Merge branch 'master' into jdp_dev 2015-11-06 18:58:56 -06:00
bradanlane d6da11c29c revert weather 'age' back to the short datetime reported with the message. we can revisite using 'age' once we have a valid system time for the raspberry pi to compute against 2015-11-06 10:53:53 -05:00
bradanlane 98795f3da1 fix from unexpected case wehre device stores CPU temp as simple integer (eg 53 vs 53000 for 50.0C 2015-11-06 09:47:25 -05:00
bradanlane 1465ba1a37 enable tower page and added tower help 2015-11-06 09:44:46 -05:00
Joseph Poirier afe13d1587 Merge branch 'master' into jdp_dev 2015-11-05 22:17:22 -06:00
Joseph Poirier 627353de48 minorcode changes 2015-11-05 21:54:39 -06:00
Christopher Young 3289772485 Set "airborne" flag correctly on TIS-B traffic.
Shows traffic in different color in FF when on ground.
2015-11-05 22:02:58 -05:00
Joseph Poirier 926fa06886 Merge branch 'master' into jdp_dev 2015-11-05 20:56:53 -06:00
Christopher Young bb5663bde0 Unit typo. 2015-11-05 20:17:45 -05:00
cyoung d0d466896e Merge pull request #96 from cyoung/uat_towers_status
created new towers details page and towers status on main page
2015-10-30 11:56:54 -04:00
bradanlane 0324cc4b1f created new towers details page but its commented out of the WebUI; simple active tower count is added to primary status page; created status web servcie for cases wehre a single instance is needed 2015-10-27 10:55:18 -04:00
Joseph Poirier 595f50cc2f UAT and ES mode/hardware handling 2015-10-25 22:16:19 -05:00
Christopher Young 7bfb0067b4 Fixed outdated comment - ReplayLog can be changed during runtime now. 2015-10-25 20:58:21 -04:00
Christopher Young e2ef3ae054 Don't set default route at all.
Works with iOS and Android per #51.
2015-10-25 20:30:43 -04:00
Christopher Young 293d0e74a8 Merge branch 'master' of https://www.github.com/cyoung/stratux 2015-10-21 15:27:44 -04:00
Christopher Young 3e042a82ed Revert SDR code changes. 2015-10-21 15:25:22 -04:00
bradanlane 865ba680c8 replace map on GPS page to be more accurate. 2015-10-20 15:14:25 -04:00
bradanlane 63922bccdd Merge branch 'master' of https://github.com/cyoung/stratux 2015-10-20 15:13:13 -04:00
bradanlane 3293811588 replace map on GPS page to be more accurate. 2015-10-20 15:12:10 -04:00
Christopher Young 6f5f69b322 Detect 'stratux:978' in serial string to keep static 978 tuner dev. 2015-10-20 10:50:09 -04:00
Christopher Young 4761947799 Leveling. Roll sign was backwards. 2015-10-19 18:21:57 -04:00
Christopher Young 6de0a8602a Set time according to NEO-M8N, even if no GPS lock. Index fix. 2015-10-19 13:18:48 -04:00
Christopher Young 663fe90ae8 Speed option for AHRS replay. 2015-10-19 13:08:27 -04:00
Christopher Young fbcfddc006 Isolate CPU temperature monitor to its own goroutine.
Addresses #63.
2015-10-19 08:17:02 -04:00
Christopher Young 941bd3f70c Missing import. 2015-10-18 22:07:37 -04:00
Christopher Young 5f58d4bb5f Set write deadline on UI broadcast writes. 2015-10-18 22:06:33 -04:00
Christopher Young 2aa4378157 Fixed potential race condition. 2015-10-18 21:59:23 -04:00
Christopher Young 2498e15696 Fixed potential mutex issue. 2015-10-18 20:27:49 -04:00
Christopher Young dc50cb9b0f circleci changes 2015-10-18 12:57:31 -04:00
Christopher Young 04e0ac7436 cirleci changes. 2015-10-18 11:34:05 -04:00
Christopher Young c39cee250e circleci changes 2015-10-18 11:18:54 -04:00
Christopher Young ca6e6f7963 circleci changes 2015-10-18 11:17:25 -04:00
Christopher Young ba80ae737b circleci changes 2015-10-18 11:13:19 -04:00
Christopher Young d88722ee88 circleci changes 2015-10-18 11:10:02 -04:00
Christopher Young 487b448ecb circleci changes 2015-10-18 11:05:45 -04:00
Christopher Young a3183431a9 circleci changes 2015-10-18 11:04:01 -04:00
Christopher Young a36b4bcea4 circleci changes 2015-10-18 10:54:21 -04:00
Christopher Young 9bd2d6a927 circleci changes 2015-10-18 10:52:07 -04:00
Christopher Young 38b16796c2 circleci changes 2015-10-18 10:50:24 -04:00
cyoung eae150ee1c Merge pull request #81 from cyoung/ui_gps-ahrs
new gps / ahrs page
2015-10-18 10:45:20 -04:00
Christopher Young cd2ad87c44 cgo lib path 2015-10-18 01:08:54 -04:00
Christopher Young a8c02f2f01 libusb-1.0-0-dev (circleci). 2015-10-18 01:02:39 -04:00
Christopher Young e56ecbdbab libusb (circleci). 2015-10-18 01:00:40 -04:00
Christopher Young 78bc7e6a67 rtl-sdr install (circleci). 2015-10-18 00:59:06 -04:00
Christopher Young 78a39673f5 apt-get update (circleci). 2015-10-18 00:55:59 -04:00
Christopher Young 867b08eba4 Install rtl-sdr (circleci). 2015-10-18 00:54:38 -04:00
Christopher Young 6dac3b6c6f Don't cross compile by default. 2015-10-18 00:51:08 -04:00
bradanlane a16158e4ad improve gps/ahrs page to use same colors for map and airplane as rest of WebUI 2015-10-15 10:21:35 -04:00
bradanlane 6e84557616 new gps / ahrs page with both data details and graphical representation using image for gps location and webgl for ahrs 2015-10-14 17:35:41 -04:00
Christopher Young 85ce802dd6 App integration "guide". 2015-10-12 10:37:16 -04:00
Christopher Young 3916dd8a83 App support update. 2015-10-12 09:39:35 -04:00
Christopher Young 8769ced73e Error checking on OwnshipModeS. 2015-10-10 16:02:12 -04:00
cyoung a6f302dc13 Merge pull request #80 from cyoung/ui_coloring
color coded METARs; time 'old' for weather; and message volume bar graph
2015-10-10 15:10:55 -04:00
bradanlane caba8bab78 color coded METARs; time 'old' for weather; and message volume bar graph 2015-10-10 15:00:38 -04:00
Christopher Young 451fec9bbb clean: rm -f libdump978.so 2015-10-09 20:08:46 -04:00
Christopher Young 0d0e3b8216 Default value - OwnshipModeS as string. 2015-10-09 20:07:28 -04:00
cyoung a58fc63efb Merge pull request #73 from cyoung/ownship
add OwnshipModeS to UI; tweaked Settings field validation
2015-10-09 12:13:32 -04:00
Christopher Young fa4718c212 Default ModeS code - not zero. 2015-10-08 07:25:43 -04:00
Christopher Young a2a7b11494 Redo weather/traffic websocket updates (#74). 2015-10-07 20:24:56 -04:00
Christopher Young e41b040cd4 Replay speed on command line. 2015-10-07 19:25:29 -04:00
Christopher Young 202e36c3a4 Disable port 43211 output by default. 2015-10-07 19:04:06 -04:00
Christopher Young 3f6d9a07a9 Don't print GPS status in log unless enabled. 2015-10-07 19:03:24 -04:00
bradanlane 30abcb82ee add OwnshipModeS to UI and maintain consistent format for storage; also tweaked 'settings' page field validation 2015-10-06 18:31:20 -04:00
Christopher Young 34f55beb04 libdump978 entries in Makefile. 2015-10-05 10:19:24 -04:00
Christopher Young bdb680eaaa Replay log on/off while running. 2015-10-04 18:50:21 -04:00
Christopher Young 2e0171aff8 "make www" 2015-10-04 18:34:52 -04:00
Christopher Young 891af1ff11 Formatting. 2015-10-04 18:33:44 -04:00
Christopher Young 5e91ca6500 Merge branch 'webui_traffic_weather' 2015-10-04 18:28:47 -04:00
Christopher Young 5916f00960 Merge. 2015-10-04 18:28:37 -04:00
bradanlane 3860a8b9ea twek one CSS element on 'settings' page 2015-10-04 14:30:07 -04:00
bradanlane a1502307aa new 'weather' page which uses new 'WatchList' setting 2015-10-04 13:50:51 -04:00
bradanlane 45215e258b traffic page complete; includes context sensitive help; does not include trafic fource indication 2015-10-01 17:19:28 -04:00
Christopher Young 6ba4009f1b Rename /control to /status (JS). 2015-10-01 16:21:41 -04:00
Christopher Young c842cbe595 Traffic source tracking. 2015-10-01 16:10:35 -04:00
Christopher Young baae410a3f Stratux heartbeat. 2015-09-30 21:06:38 -04:00
Christopher Young 2661c86560 Skip traffic targets on websocket with no valid position. 2015-09-30 18:52:52 -04:00
Christopher Young aafcd4892c NIC & NACp from @AvSquirrel. 2015-09-30 13:36:31 -04:00
Christopher Young 94876edd40 /traffic websocket - stream traffic updates (1090ES and UAT) as received. 2015-09-30 13:14:48 -04:00
Christopher Young 2bf466a1c8 /weather websocket - stream UAT text updates as received. 2015-09-30 12:50:23 -04:00
Christopher Young 8f5c33f6b1 Rename /control to /status (websocket system status stream). 2015-09-30 12:39:45 -04:00
Christopher Young 4551cadaef Update FF rec. 2015-09-30 12:15:20 -04:00
Christopher Young ae37369b28 Implement ModeS for ownship. 2015-09-30 11:52:13 -04:00
Christopher Young dd92da4dc3 Remove some debug prints. 2015-09-30 11:10:11 -04:00
Christopher Young 205984ce09 Consolidating websocket functions. 2015-09-30 10:51:41 -04:00
Christopher Young c9f9851d26 UAT products non-exportable: not used by interface currently. 2015-09-30 10:37:49 -04:00
Christopher Young ee88b93393 Cleanup. 2015-09-30 10:30:28 -04:00
Christopher Young 797f71a4da gofmt 2015-09-30 10:22:27 -04:00
cyoung 2d770d5b2e Merge pull request #67 from cyoung/webui_20_initial
WebUI 2.0 initial
2015-09-30 10:21:53 -04:00
cyoung 3c0af57539 Merge pull request #65 from cyoung/new_rest_services
New REST services with getter/setter for settings
2015-09-30 10:21:00 -04:00
bradanlane 4274469f15 completed STATUS and SETTINGS pages with context sensitive HELP (without debug) 2015-09-29 18:27:52 -04:00
bradanlane 125c052385 completed STATUS and SETTINGS pages with context sensitive HELP 2015-09-29 18:05:50 -04:00
bradanlane da40576459 new WebUI is feature parity with old WebUI plus PPM setting 2015-09-28 15:20:43 -04:00
bradanlane 3606432f30 REST services getter/setter for settings completed without debug output 2015-09-28 14:15:41 -04:00
bradanlane 9339fb21ed REST services getter/setter for settings completed without debug output 2015-09-28 14:14:32 -04:00
bradanlane ef2b67a891 REST services getter/setter for settings completed 2015-09-28 14:08:05 -04:00
bradanlane e3477e8669 added AJAX getSettings and stub for setSettings 2015-09-26 17:16:40 -04:00
cyoung a90a51e343 Merge pull request #62 from jpoirier/development
Development
2015-09-26 08:59:22 -04:00
Joseph Poirier 947a9217ca reorder defer calls 2015-09-26 02:20:16 -05:00
Joseph Poirier 4f305f5215 format the humanize import so goimports doesn't remove it 2015-09-26 02:09:49 -05:00
Joseph Poirier a56a2589a3 some low-hanging fruit, note that strings.Split never returns an empty list and at miniumum it'll contain one zero length string element 2015-09-26 02:04:39 -05:00
Christopher Young 968062f49a Data collection. 2015-09-25 15:41:09 -04:00
Christopher Young d03ac5abed AHRS replay tool. 2015-09-25 15:40:52 -04:00
Christopher Young cb4592bbbe Stop saving pitch/roll history after calibration.
Fixes #48. Fixes #60.
2015-09-24 23:50:56 -04:00
Christopher Young 2324bbe6f0 Parse UAT message product ID from all frames - display.
http://i.imgur.com/B3u3bzw.png
2015-09-24 17:28:08 -04:00
Christopher Young 0dc32f23e1 /getTowers.
#59
2015-09-24 17:18:21 -04:00
Christopher Young 3e972b3753 Reorg. 2015-09-24 16:31:06 -04:00
Christopher Young 63173fc88d /getTraffic and /getSituation. 2015-09-24 16:26:51 -04:00
Christopher Young 5938f28a02 AHRS replay logs - test data. 2015-09-24 07:57:50 -04:00
Christopher Young 3c50cd59cd Use GPS altitude in Ownship when pressure altitude not available.
Temporary.
2015-09-24 07:46:40 -04:00
cyoung 84fb44f6b2 Merge pull request #58 from jpoirier/development
shift direction fix
2015-09-24 00:53:08 -04:00
Joseph Poirier e81e37ca65 shift direction fix 2015-09-23 23:28:16 -05:00
Christopher Young 75f60562af Pressure alt fix from @AvSquirrel. 2015-09-23 23:12:48 -04:00
Christopher Young 324bef7701 AHRS replay log. 2015-09-23 16:21:32 -04:00
Christopher Young c80de8856f Merge branch 'master' of https://www.github.com/cyoung/stratux 2015-09-22 23:52:52 -04:00
Christopher Young edcccbda13 Fixes #33.
Set system time from RMC sentence.
2015-09-22 23:51:56 -04:00
Christopher Young b97eb52988 Cleanup. 2015-09-22 23:28:06 -04:00
Christopher Young 8b73e64645 Search for precip in local area, translate in to text warning.
$ ./nexrad_annunciator ../test-data/example.radar 38.32 -88.86 47
moderate precip 1 o'clock, 5.2 nm.
$ ./nexrad_annunciator ../test-data/example.radar 38.38 -88.41 140
heavy precip 2 o'clock, 8.9 nm.
$ ./nexrad_annunciator ../test-data/example.radar 38.22 -88.25 140
very heavy precip 11 o'clock, 6.7 nm.
2015-09-22 23:14:59 -04:00
Christopher Young 4156940348 NEXRAD decoding test frames. 2015-09-22 20:12:40 -04:00
Christopher Young 59f03c5141 Initialize seenTraffic. 2015-09-22 19:51:37 -04:00
Christopher Young f1ea6bd1a6 Working NEXRAD decode. 2015-09-22 19:40:29 -04:00
Christopher Young 0db905904f Print stats in main log.
2015/09/22 13:52:11 stats [uptime 1 minute ago]
2015/09/22 13:52:11  - CPUTemp=49.23 deg C, MemStats.Alloc=101MB,
MemStats.Sys=126MB, totalNetworkMessagesSent=0
2015/09/22 13:52:11  - UAT/min 103,226/103,226 [maxSS=55.30%], ES/min
0/0
2015/09/22 13:52:11  - Total traffic targets tracked=0, last GPS fix: a
long while ago
2015-09-22 09:52:49 -04:00
Christopher Young 476ebed93d Fixes #48.
On every sequential (client  asleep) queue overflow, progressively
remove more from the queue. Better memory management, especially for
clients that are constantly in sleep more or asleep for a very long
time.
2015-09-22 08:55:51 -04:00
Christopher Young e43c509aa1 Fixes #52 (mostly).
go doesn’t run under qemu, so you’ll need to get the go imports on
there somehow.
2015-09-22 01:28:28 -04:00
Christopher Young 5f307d7862 Upgrade to qemu 2.4.0 - command line flags change. 2015-09-22 01:06:55 -04:00
Christopher Young 6165d327a1 Log signal strength in UAT log. 2015-09-22 00:04:59 -04:00
Christopher Young 34bc4ab051 Prototype changes. 2015-09-21 21:08:08 -04:00
Christopher Young 0c2ab9c5c2 Formatting. 2015-09-21 21:08:03 -04:00
Christopher Young bc5342935b Formatting. 2015-09-21 21:04:27 -04:00
Christopher Young 4acff06355 Signal strength from 978 demod passed to lib. 2015-09-21 21:03:32 -04:00
Christopher Young e434c50e86 Signal power level.
From @tomcourt
2015-09-21 15:44:08 -04:00
Christopher Young 9e78dddab7 GPS message replay log. 2015-09-21 14:20:12 -04:00
Christopher Young 3c30d78368 Replace problematic iana package constants with actual values.
Fixes Makefile issue.
2015-09-21 14:01:01 -04:00
Christopher Young a8e8562e5f Formatting. 2015-09-21 13:01:18 -04:00
Christopher Young 229df30ff4 Fixes #45. 2015-09-20 09:44:02 -04:00
Christopher Young 0609d0c3e4 FF vers. 2015-09-20 09:22:25 -04:00
Christopher Young 1f46ccda01 PPM uint16 -> int. 2015-09-19 14:19:57 -04:00
Christopher Young c3e6d41ebe Always use tag for version. 2015-09-19 12:37:52 -04:00
Christopher Young f3a52e9ab5 Version printing for logs. 2015-09-18 23:00:05 -04:00
Christopher Young 10f21a651b RY835AI auto config.
10HZ update.
115200 baud.
Dynamic Platform Model: “Airborne <2g”
2015-09-18 15:18:58 -04:00
Christopher Young f3b95de7e8 Libtool. 2015-09-18 10:50:19 -04:00
Christopher Young 68d999f5e7 GPS only RY835AI support. 2015-09-18 08:12:02 -04:00
193 zmienionych plików z 100861 dodań i 6544 usunięć

33
.gitignore vendored
Wyświetl plik

@ -1,8 +1,12 @@
.idea/
.vscode/
dump978/extract_nexrad
dump978/uat2esnt
dump978/uat2json
dump978/uat2text
gen_gdl90
libdump978.so
fancontrol
*.mp4
@ -10,4 +14,31 @@ gen_gdl90
*.zip
*.log
test/bmp180_read
test/es_dump_csv
test/extract_latlng
test/extract_metar
test/getairmet
test/icao2reg
test/maxgap
test/nexrad_annunciator
test/packetrate
test/replay
test/sensortest
test/uat_read
test/uatsummary
.DS_Store

6
.gitmodules vendored
Wyświetl plik

@ -0,0 +1,6 @@
[submodule "dump1090"]
path = dump1090
url = https://github.com/stratux/dump1090
[submodule "goflying"]
path = goflying
url = https://github.com/cyoung/goflying

3
CONTRIBUTING.md 100644
Wyświetl plik

@ -0,0 +1,3 @@
## Issues
Please use the [issue template](https://github.com/cyoung/stratux/issues/new?title=description+of+issue&body=1.%20Stratux%20version%3A%0A2.%20Stratux%20config%3A%20single%2Fdual%20SDR%2C%20GPS%20yes%2Fno%20(type%3F)%2C%20AHRS%20yes%2Fno%2C%20battery%2C%20battery%20cable.%0A3.%20EFB%20app%20and%20version%20(e.g.%2C%20WingX%20Pro7%208.6.2).%20EFB%20platform%20(e.g.%2C%20iOS%209.2).%20EFB%20hardware%20(e.g.%2C%20iPad%20Mini%202).%0A4.%20Description%20of%20your%20issue.%20If%20possible%2C%20enable%20%22Replay%20Logs%22%2C%20reproduce%20the%20problem%2C%20and%20provide%20a%20copy%20of%20the%20logs%20in%20http%3A%2F%2F192.168.10.1%2Flogs%2Fstratux%2F%20and%20http%3A%2F%2F192.168.10.1%2Flogs%2Fstratux.log.) to report an issue.

29
ISSUE_TEMPLATE.md 100644
Wyświetl plik

@ -0,0 +1,29 @@
1. Stratux version:
2. Stratux config:
SDR
- [ ] single
- [ ] dual
GPS
- [ ] yes
- [ ] no
type:
AHRS
- [ ] yes
- [ ] no
power source:
usb cable:
3. EFB app and version: (e.g., WingX Pro7 8.6.2)
EFB platform: (e.g., iOS 9.2)
EFB hardware: (e.g., iPad Mini 2)
4. Description of your issue:
If possible, enable "Replay Logs", reproduce the problem, and provide a copy of the logs in http://192.168.10.1/logs/stratux/ and http://192.168.10.1/logs/stratux.log.

Wyświetl plik

@ -1,4 +1,4 @@
Copyright (c) 2015 Christopher Young.
Copyright (c) 2015-2016 Christopher Young ("Copyright Holder").
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -9,7 +9,7 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Christopher Young nor the
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

Wyświetl plik

@ -1,16 +1,63 @@
GOOS ?= linux
GOARCH ?= arm
GOARM ?= 7
ifeq "$(CIRCLECI)" "true"
BUILDINFO=
PLATFORMDEPENDENT=
else
LDFLAGS_VERSION=-X main.stratuxVersion=`git describe --tags --abbrev=0` -X main.stratuxBuild=`git log -n 1 --pretty=%H`
BUILDINFO=-ldflags "$(LDFLAGS_VERSION)"
BUILDINFO_STATIC=-ldflags "-extldflags -static $(LDFLAGS_VERSION)"
$(if $(GOROOT),,$(error GOROOT is not set!))
PLATFORMDEPENDENT=fancontrol
endif
all:
# GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) go get -t -d -v ./...
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) go build main/gen_gdl90.go main/traffic.go main/ry835ai.go main/network.go main/managementinterface.go main/sdr.go
make xdump978 xdump1090 xgen_gdl90 $(PLATFORMDEPENDENT)
xgen_gdl90:
go get -t -d -v ./main ./godump978 ./uatparse ./sensors
go build $(BUILDINFO) -p 4 main/gen_gdl90.go main/traffic.go main/gps.go main/network.go main/managementinterface.go main/sdr.go main/ping.go main/uibroadcast.go main/monotonic.go main/datalog.go main/equations.go main/sensors.go main/cputemp.go main/lowpower_uat.go
fancontrol:
go get -t -d -v ./main
go build $(BUILDINFO_STATIC) -p 4 main/fancontrol.go main/equations.go main/cputemp.go
xdump1090:
git submodule update --init
cd dump1090 && make
xdump978:
cd dump978 && make lib
sudo cp -f ./libdump978.so /usr/lib/libdump978.so
.PHONY: test
test:
sh -c true
make -C test
www:
cd web && make
install:
cp -f gen_gdl90 /usr/bin/gen_gdl90
chmod 755 /usr/bin/gen_gdl90
cp -f fancontrol /usr/bin/fancontrol
chmod 755 /usr/bin/fancontrol
-/usr/bin/fancontrol remove
/usr/bin/fancontrol install
cp image/10-stratux.rules /etc/udev/rules.d/10-stratux.rules
cp image/99-uavionix.rules /etc/udev/rules.d/99-uavionix.rules
rm -f /etc/init.d/stratux
cp __lib__systemd__system__stratux.service /lib/systemd/system/stratux.service
cp __root__stratux-pre-start.sh /root/stratux-pre-start.sh
chmod 644 /lib/systemd/system/stratux.service
chmod 744 /root/stratux-pre-start.sh
ln -fs /lib/systemd/system/stratux.service /etc/systemd/system/multi-user.target.wants/stratux.service
make www
cp -f libdump978.so /usr/lib/libdump978.so
cp -f dump1090/dump1090 /usr/bin/
cp -f image/hostapd_manager.sh /usr/sbin/
cp -f image/stratux-wifi.sh /usr/sbin/
clean:
rm -f gen_gdl90
rm -f gen_gdl90 libdump978.so fancontrol ahrs_approx
cd dump1090 && make clean
cd dump978 && make clean

Wyświetl plik

@ -1,24 +1,63 @@
# stratux
[![stratux version](https://img.shields.io/github/tag/cyoung/stratux.svg?style=flat&label=stratux)](https://github.com/b3nn0/stratux/releases)
[![BSD3 License](http://img.shields.io/badge/license-BSD3-brightgreen.svg)](https://tldrlegal.com/license/bsd-3-clause-license-%28revised%29)
[![](https://dcbadge.limes.pink/api/server/https://discord.gg/D9NQ6xe4nF)](https://discord.gg/D9NQ6xe4nF)
# Stratux - deprecated branch (as of 2020)
This branch is no longer maintained. Do not report issues here! Active development is taking place on the [@b3nn0 branch](https://github.com/b3nn0/stratux).
**[Current branch](https://github.com/b3nn0/stratux)**
[Current release](https://github.com/b3nn0/stratux/releases)
[Stratux developer Discord](https://discord.gg/D9NQ6xe4nF)
## History
Stratux was founded in 2015 by [@cyoung](https://github.com/cyoung) and other developers with the mission of creating an open-source, modular, ADS-B solution using affordable microchips and a Raspberry Pi board. After building the project to include a dual band receiver, GPS, and AHRS [@cyoung](https://github.com/cyoung) moved on to other projects in 2020. [@b3nn0](https://github.com/b3nn0) took the reins as the main developer building out many features for the OpenGliderNetwork (OGN) and other Europe specific enhancements while maintaining the Stratux code base for users around the world.
Stratux is still under active development with hardward upgrades, new features, [Reddit](https://www.reddit.com/r/stratux) and [Discord](https://discord.gg/D9NQ6xe4nF) communities. You can find parts, pre-built units, and build guides on the [Stratux website](http://stratux.me). You can also [support the developers](https://www.paypal.com/paypalme/stratuxeu) or reach out to the community with new ideas.
## Old readme
RTL-SDR UAT tools
Use with Raspberry Pi 3B. The 3B+ and Pi 4B will work but use a lot more power.
Use Pi 2 and ForeFlight 7.3 (Sep 14, 2015).
Tested and works well with most common R820T and R820T2 RTL-SDR devices.
Supported WiFi adapters:
* Edimax EW-7811Un
* TP-LINK TL-WN725N
Tested RTL-SDR:
* NooElec NESDR Mini 2
* Generic R820T (degraded performance)
Apps with stratux recognition/support:
* ForeFlight 10+ - weather, traffic, AHRS.
* Seattle Avionics FlyQ EFB 2.1.1+.
* AvNav EFB 2.0.0+.
* Naviator.
* WingX Pro7 8.6.2+
* FltPlan Go.
* AerovieReports.
* AvPlan EFB.
* iFly GPS 9.4+.
* DroidEFB 2.1.1+.
* kwikEFIS
* Pilots Atlas
Tested weather/traffic displays:
* ForeFlight 7.2 (Jul 13, 2015) - weather, traffic, AHRS.
* Naviator - weather, traffic, AHRS.
* WingX - weather & traffic.
* Avare
* iFly 740 - weather & traffic.
Other EFBs? See the [app vendor integration guide](https://github.com/cyoung/stratux/blob/master/notes/app-vendor-integration.md).
https://www.reddit.com/r/stratux
Questions? [See the FAQ](https://github.com/cyoung/stratux/wiki/FAQ)
http://stratux.me/
http://slack.stratux.me/
https://www.reddit.com/r/stratux
Jet tests (high gain antennas):
* Dassault Falcon 20
* Embraer ERJ 145
* Cessna Citation 501
* Citation Sovereign+
* Lear 35
* Rockwell B-1b
* Boeing C-17
* Gulfstream G450

Wyświetl plik

@ -0,0 +1,16 @@
[Unit]
Description=Stratux
After=network.target
[Service]
ExecStartPre=/root/stratux-pre-start.sh
ExecStart=/usr/bin/gen_gdl90
ExecStop=/usr/bin/pkill dump1090
KillMode=process
Restart=always
RestartSec=5
LimitCORE=1073741824
[Install]
WantedBy=multi-user.target

Wyświetl plik

@ -0,0 +1,41 @@
#!/bin/bash
echo powersave >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
#Logging Function
SCRIPT=`basename ${BASH_SOURCE[0]}`
STX_LOG="/var/log/stratux.log"
function wLog () {
echo "$(date +"%Y/%m/%d %H:%m:%S") - $SCRIPT - $1" >> ${STX_LOG}
}
wLog "Running Stratux Updater Script."
SCRIPT_MASK="update*stratux*v*.sh"
TEMP_LOCATION="/boot/StratuxUpdates/$SCRIPT_MASK"
UPDATE_LOCATION="/root/$SCRIPT_MASK"
if [ -e ${TEMP_LOCATION} ]; then
wLog "Found Update Script in $TEMP_LOCATION$SCRIPT_MASK"
TEMP_SCRIPT=`ls -1t ${TEMP_LOCATION} | head -1`
wLog "Moving Script $TEMP_SCRIPT"
cp -r ${TEMP_SCRIPT} /root/
wLog "Changing permissions to chmod a+x $UPDATE_LOCATION"
chmod a+x ${UPDATE_LOCATION}
wLog "Removing Update file from $TEMP_LOCATION"
rm -rf ${TEMP_SCRIPT}
fi
# Check if we need to run an update.
if [ -e ${UPDATE_LOCATION} ]; then
UPDATE_SCRIPT=`ls -1t ${UPDATE_LOCATION} | head -1`
if [ -n ${UPDATE_SCRIPT} ] ; then
# Execute the script, remove it, then reboot.
wLog "Running update script ${UPDATE_SCRIPT}..."
bash ${UPDATE_SCRIPT}
wLog "Removing Update SH"
rm -f ${UPDATE_SCRIPT}
wLog "Finished... Rebooting... Bye"
reboot
fi
fi
wLog "Exited without updating anything..."

Wyświetl plik

@ -1,6 +1,20 @@
machine:
environment:
PATH: $HOME/go/bin:$HOME/gopath/bin:$PATH
GOPATH: $HOME/gopath
dependencies:
pre:
- sudo apt-get update; sudo apt-get install libusb-1.0-0-dev mercurial; cd ~/; git clone https://github.com/jpoirier/librtlsdr; cd librtlsdr; mkdir build; cd build; cmake ../; make; sudo make install; sudo ldconfig; cd ~/; rm -rf gopath; mkdir gopath; wget https://dl.google.com/go/go1.9.2.linux-amd64.tar.gz; tar -zxvf go1.9.2.linux-amd64.tar.gz; go version; env
override:
- make
- cd .. ; rm -rf stratux ; git clone --recursive https://github.com/cyoung/stratux ; cd stratux ; git config --add remote.origin.fetch "+refs/pull/*/head:refs/remotes/origin/pr/*" ; git fetch origin ; BRANCH=`echo "$CIRCLE_BRANCH" | sed 's/pull\//pr\//g'` ; git checkout $BRANCH ; make
test:
override:
- make test
- make
deployment:
production:
branch: master
commands:
- yes | ssh -i ~/.ssh/id_updates.stratux.me stratux-updates@updates.stratux.me "touch queue/`git log -n 1 --pretty=%H`"

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,76 @@
MON-VER - 0A 04 BE 00 32 2E 30 31 20 28 37 35 33 35 30 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 30 30 38 30 30 30 30 00 00 32 2E 30 31 20 28 37 35 33 33 31 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50 52 4F 54 56 45 52 20 31 35 2E 30 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 46 49 53 20 30 78 45 46 34 30 31 35 20 28 37 39 31 38 39 29 00 00 00 00 00 00 00 00 00 00 4D 4F 44 20 4E 45 4F 2D 4D 38 4E 2D 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 50 53 3B 53 42 41 53 3B 47 4C 4F 3B 42 44 53 3B 51 5A 53 53 00 00 00 00 00 00 00 00 00
CFG-ANT - 06 13 04 00 1B 00 F0 FD
CFG-DAT - 06 06 02 00 00 00
CFG-GNSS - 06 3E 2C 00 00 20 20 05 00 08 10 00 01 00 01 01 01 01 03 00 01 00 01 01 03 00 10 00 00 00 01 01 05 00 03 00 00 00 01 01 06 04 0E 00 00 00 01 01
CFG-INF - 06 02 0A 00 00 00 00 00 00 00 00 00 00 00
CFG-INF - 06 02 0A 00 01 00 00 00 87 87 87 87 87 87
CFG-INF - 06 02 0A 00 03 00 00 00 00 00 00 00 00 00
CFG-ITFM - 06 39 08 00 F3 AC 62 2D 1E 03 00 00
CFG-LOGFILTER - 06 47 0C 00 01 00 00 00 00 00 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0B 30 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0B 33 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0B 31 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0B 01 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 21 08 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 0B 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 09 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 02 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 06 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 07 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 21 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 08 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 60 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 22 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 31 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 04 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 09 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 34 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 01 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 02 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 07 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 35 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 32 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 06 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 03 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 30 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 20 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 21 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 11 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 12 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 02 20 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0D 03 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0D 01 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 00 01 01 01 01 01 01
CFG-MSG - 06 01 08 00 F0 01 00 00 00 00 00 01
CFG-MSG - 06 01 08 00 F0 02 01 01 01 01 01 01
CFG-MSG - 06 01 08 00 F0 03 05 05 05 05 05 01
CFG-MSG - 06 01 08 00 F0 01 01 01 01 01 01 01
CFG-MSG - 06 01 08 00 F0 05 01 01 01 01 01 01
CFG-MSG - 06 01 08 00 F0 06 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 07 05 05 05 05 05 00
CFG-MSG - 06 01 08 00 F0 08 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 09 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 0A 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 0D 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 0E 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 0F 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F1 00 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F1 03 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F1 04 00 00 00 00 00 00
CFG-NAV5 - 06 24 24 00 FF FF 07 03 00 00 00 00 10 27 00 00 05 00 FA 00 FA 00 64 00 2C 01 00 00 00 00 00 00 C8 00 00 00 00 00 00 00
CFG-NAVX5 - 06 23 28 00 00 00 FF FF 1F 00 00 00 03 02 03 14 06 00 00 01 00 00 DC 06 00 00 00 00 01 01 00 00 00 64 64 00 00 01 10 00 00 00 00 00
CFG-NMEA - 06 17 14 00 00 40 00 02 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00
CFG-ODO - 06 1E 14 00 00 00 00 00 00 00 00 00 19 46 19 66 0A 32 00 00 99 4C 00 00
CFG-PM2 - 06 3B 2C 00 01 06 00 00 00 90 02 00 E8 03 00 00 10 27 00 00 00 00 00 00 00 00 00 00 2C 01 00 00 4F C1 03 00 86 02 00 00 FE 00 00 00 64 40 01 00
CFG-PRT - 06 00 14 00 00 00 00 00 84 00 00 00 00 00 00 00 07 00 03 00 00 00 00 00
CFG-PRT - 06 00 14 00 01 00 00 00 C0 08 00 00 80 25 00 00 03 00 02 00 00 00 00 00
CFG-PRT - 06 00 14 00 02 00 00 00 C0 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CFG-PRT - 06 00 14 00 03 00 00 00 00 00 00 00 00 00 00 00 07 00 03 00 00 00 00 00
CFG-PRT - 06 00 14 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CFG-RATE - 06 08 06 00 E8 03 01 00 01 00
CFG-RINV - 06 34 18 00 00 4E 6F 74 69 63 65 3A 20 6E 6F 20 64 61 74 61 20 73 61 76 65 64 21 00
CFG-RXM - 06 11 02 00 08 00
CFG-SBAS - 06 16 08 00 01 07 03 00 00 00 00 00
CFG-TP5 - 06 31 20 00 00 ED 02 00 32 00 00 00 40 42 0F 00 40 42 0F 00 00 00 00 00 A0 86 01 00 00 00 00 00 77 00 00 00
CFG-TP5 - 06 31 20 00 01 ED 02 00 32 00 00 00 04 00 00 00 01 00 00 00 48 E8 01 00 A0 86 01 00 00 00 00 00 7E 00 00 00
CFG-USB - 06 1B 6C 00 46 15 A8 01 00 00 00 00 64 00 22 00 75 2D 62 6C 6F 78 20 41 47 20 2D 20 77 77 77 2E 75 2D 62 6C 6F 78 2E 63 6F 6D 00 00 00 00 00 00 75 2D 62 6C 6F 78 20 47 4E 53 53 20 72 65 63 65 69 76 65 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Wyświetl plik

@ -0,0 +1,76 @@
MON-VER - 0A 04 BE 00 32 2E 30 31 20 28 37 35 33 35 30 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 30 30 38 30 30 30 30 00 00 32 2E 30 31 20 28 37 35 33 33 31 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50 52 4F 54 56 45 52 20 31 35 2E 30 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 46 49 53 20 30 78 45 46 34 30 31 35 20 28 37 39 31 38 39 29 00 00 00 00 00 00 00 00 00 00 4D 4F 44 20 4E 45 4F 2D 4D 38 4E 2D 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 50 53 3B 53 42 41 53 3B 47 4C 4F 3B 42 44 53 3B 51 5A 53 53 00 00 00 00 00 00 00 00 00
CFG-ANT - 06 13 04 00 1B 00 F0 FD
CFG-DAT - 06 06 02 00 00 00
CFG-GNSS - 06 3E 2C 00 00 20 20 05 00 08 10 00 01 00 01 01 01 01 03 00 01 00 01 01 03 00 10 00 00 00 01 01 05 00 03 00 00 00 01 01 06 04 0E 00 00 00 01 01
CFG-INF - 06 02 0A 00 00 00 00 00 00 00 00 00 00 00
CFG-INF - 06 02 0A 00 01 00 00 00 87 87 87 87 87 87
CFG-INF - 06 02 0A 00 03 00 00 00 00 00 00 00 00 00
CFG-ITFM - 06 39 08 00 F3 AC 62 2D 1E 03 00 00
CFG-LOGFILTER - 06 47 0C 00 01 00 00 00 00 00 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0B 30 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0B 33 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0B 31 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0B 01 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 21 08 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 0B 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 09 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 02 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 06 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 07 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 21 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0A 08 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 60 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 22 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 31 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 04 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 09 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 34 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 01 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 02 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 07 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 35 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 32 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 06 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 03 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 30 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 20 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 21 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 11 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 01 12 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 02 20 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0D 03 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 0D 01 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 00 00 0A 00 0A 00 01
CFG-MSG - 06 01 08 00 F0 01 00 00 00 00 00 01
CFG-MSG - 06 01 08 00 F0 02 00 00 00 00 00 01
CFG-MSG - 06 01 08 00 F0 03 00 00 00 00 00 01
CFG-MSG - 06 01 08 00 F0 04 00 00 00 00 00 01
CFG-MSG - 06 01 08 00 F0 05 00 00 00 00 00 01
CFG-MSG - 06 01 08 00 F0 06 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 07 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 08 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 09 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 0A 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 0D 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 0E 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F0 0F 00 00 00 00 00 00
CFG-MSG - 06 01 08 00 F1 00 01 01 01 01 01 00
CFG-MSG - 06 01 08 00 F1 03 0A 0A 0A 0A 0A 00
CFG-MSG - 06 01 08 00 F1 04 0A 0A 0A 0A 0A 00
CFG-NAV5 - 06 24 24 00 FF FF 07 03 00 00 00 00 10 27 00 00 05 00 FA 00 FA 00 64 00 2C 01 00 00 00 00 00 00 C8 00 00 00 00 00 00 00
CFG-NAVX5 - 06 23 28 00 00 00 FF FF 1F 00 00 00 03 02 03 14 06 00 00 01 00 00 DC 06 00 00 00 00 01 01 00 00 00 64 64 00 00 01 10 00 00 00 00 00
CFG-NMEA - 06 17 14 00 00 40 00 02 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00
CFG-ODO - 06 1E 14 00 00 00 00 00 00 00 00 00 19 46 19 66 0A 32 00 00 99 4C 00 00
CFG-PM2 - 06 3B 2C 00 01 06 00 00 00 90 02 00 E8 03 00 00 10 27 00 00 00 00 00 00 00 00 00 00 2C 01 00 00 4F C1 03 00 86 02 00 00 FE 00 00 00 64 40 01 00
CFG-PRT - 06 00 14 00 00 00 00 00 84 00 00 00 00 00 00 00 07 00 03 00 00 00 00 00
CFG-PRT - 06 00 14 00 01 00 00 00 C0 08 00 00 00 96 00 00 03 00 02 00 00 00 00 00
CFG-PRT - 06 00 14 00 02 00 00 00 C0 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CFG-PRT - 06 00 14 00 03 00 00 00 00 00 00 00 00 00 00 00 07 00 03 00 00 00 00 00
CFG-PRT - 06 00 14 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CFG-RATE - 06 08 06 00 64 00 01 00 01 00
CFG-RINV - 06 34 18 00 00 4E 6F 74 69 63 65 3A 20 6E 6F 20 64 61 74 61 20 73 61 76 65 64 21 00
CFG-RXM - 06 11 02 00 08 00
CFG-SBAS - 06 16 08 00 01 07 03 00 00 00 00 00
CFG-TP5 - 06 31 20 00 00 ED 02 00 32 00 00 00 40 42 0F 00 40 42 0F 00 00 00 00 00 A0 86 01 00 00 00 00 00 77 00 00 00
CFG-TP5 - 06 31 20 00 01 ED 02 00 32 00 00 00 04 00 00 00 01 00 00 00 48 E8 01 00 A0 86 01 00 00 00 00 00 7E 00 00 00
CFG-USB - 06 1B 6C 00 46 15 A8 01 00 00 00 00 64 00 22 00 75 2D 62 6C 6F 78 20 41 47 20 2D 20 77 77 77 2E 75 2D 62 6C 6F 78 2E 63 6F 6D 00 00 00 00 00 00 75 2D 62 6C 6F 78 20 47 4E 53 53 20 72 65 63 65 69 76 65 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

1
dump1090 160000

@ -0,0 +1 @@
Subproject commit 9a4fb850937565cfeadd1e5889cddbf93f45faf5

Wyświetl plik

@ -1,15 +0,0 @@
CFLAGS?=-O2 -g -Wall -W $(shell pkg-config --cflags librtlsdr)
LDLIBS+=$(shell pkg-config --libs librtlsdr) -lpthread -lm
CC?=gcc
PROGNAME=dump1090
all: dump1090
%.o: %.c
$(CC) $(CFLAGS) -c $<
dump1090: dump1090.o anet.o
$(CC) -g -o dump1090 dump1090.o anet.o $(LDFLAGS) $(LDLIBS)
clean:
rm -f *.o dump1090

Wyświetl plik

@ -1,284 +0,0 @@
Dump1090 README
===
Dump 1090 is a Mode S decoder specifically designed for RTLSDR devices.
The main features are:
* Robust decoding of weak messages, with mode1090 many users observed
improved range compared to other popular decoders.
* Network support: TCP30003 stream (MSG5...), Raw packets, HTTP.
* Embedded HTTP server that displays the currently detected aircrafts on
Google Map.
* Single bit errors correction using the 24 bit CRC.
* Ability to decode DF11, DF17 messages.
* Ability to decode DF formats like DF0, DF4, DF5, DF16, DF20 and DF21
where the checksum is xored with the ICAO address by brute forcing the
checksum field using recently seen ICAO addresses.
* Decode raw IQ samples from file (using --ifile command line switch).
* Interactive command-line-interfae mode where aircrafts currently detected
are shown as a list refreshing as more data arrives.
* CPR coordinates decoding and track calculation from velocity.
* TCP server streaming and receiving raw data to/from connected clients
(using --net).
While from time to time I still add / fix stuff in my fork, I target
minimalism of the implementation. However there is a
[much more feature complete fork](https://github.com/MalcolmRobb/dump1090)
available, developed by MalcolmRobb.
Installation
---
Type "make".
Normal usage
---
To capture traffic directly from your RTL device and show the captured traffic
on standard output, just run the program without options at all:
./dump1090
To just output hexadecimal messages:
./dump1090 --raw
To run the program in interactive mode:
./dump1090 --interactive
To run the program in interactive mode, with networking support, and connect
with your browser to http://localhost:8080 to see live traffic:
./dump1090 --interactive --net
In iteractive mode it is possible to have a less information dense but more
"arcade style" output, where the screen is refreshed every second displaying
all the recently seen aircrafts with some additional information such as
altitude and flight number, extracted from the received Mode S packets.
Using files as source of data
---
To decode data from file, use:
./dump1090 --ifile /path/to/binfile
The binary file should be created using `rtl_sdr` like this (or with any other
program that is able to output 8-bit unsigned IQ samples at 2Mhz sample rate).
rtl_sdr -f 1090000000 -s 2000000 -g 50 output.bin
In the example `rtl_sdr` a gain of 50 is used, simply you should use the highest
gain availabe for your tuner. This is not needed when calling Dump1090 itself
as it is able to select the highest gain supported automatically.
It is possible to feed the program with data via standard input using
the --ifile option with "-" as argument.
Additional options
---
Dump1090 can be called with other command line options to set a different
gain, frequency, and so forth. For a list of options use:
./dump1090 --help
Everything is not documented here should be obvious, and for most users calling
it without arguments at all is the best thing to do.
Reliability
---
By default Dump1090 tries to fix single bit errors using the checksum.
Basically the program will try to flip every bit of the message and check if
the checksum of the resulting message matches.
This is indeed able to fix errors and works reliably in my experience,
however if you are interested in very reliable data I suggest to use
the --no-fix command line switch in order to disable error fixing.
Performances and sensibility of detection
---
In my limited experience Dump1090 was able to decode a big number of messages
even in conditions where I encountered problems using other programs, however
no formal test was performed so I can't really claim that this program is
better or worse compared to other similar programs.
If you can capture traffic that Dump1090 is not able to decode properly, drop
me an email with a download link. I may try to improve the detection during
my free time (this is just an hobby project).
Network server features
---
By enabling the networking support with --net Dump1090 starts listening
for clients connections on port 30002 and 30001 (you can change both the
ports if you want, see --help output).
Port 30002
---
Connected clients are served with data ASAP as they arrive from the device
(or from file if --ifile is used) in the raw format similar to the following:
*8D451E8B99019699C00B0A81F36E;
Every entry is separated by a simple newline (LF character, hex 0x0A).
Port 30001
---
Port 30001 is the raw input port, and can be used to feed Dump1090 with
data in the same format as specified above, with hex messages starting with
a `*` and ending with a `;` character.
So for instance if there is another remote Dump1090 instance collecting data
it is possible to sum the output to a local Dump1090 instance doing something
like this:
nc remote-dump1090.example.net 30002 | nc localhost 30001
It is important to note that what is received via port 30001 is also
broadcasted to clients listening to port 30002.
In general everything received from port 30001 is handled exactly like the
normal traffic from RTL devices or from file when --ifile is used.
It is possible to use Dump1090 just as an hub using --ifile with /dev/zero
as argument as in the following example:
./dump1090 --net-only
Or alternatively to see what's happening on the screen:
./dump1090 --net-only --interactive
Then you can feed it from different data sources from the internet.
Port 30003
---
Connected clients are served with messages in SBS1 (BaseStation) format,
similar to:
MSG,4,,,738065,,,,,,,,420,179,,,0,,0,0,0,0
MSG,3,,,738065,,,,,,,35000,,,34.81609,34.07810,,,0,0,0,0
This can be used to feed data to various sharing sites without the need to use another decoder.
Antenna
---
Mode S messages are transmitted in the 1090 Mhz frequency. If you have a decent
antenna you'll be able to pick up signals from aircrafts pretty far from your
position, especially if you are outdoor and in a position with a good sky view.
You can easily build a very cheap antenna following the istructions at:
http://antirez.com/news/46
With this trivial antenna I was able to pick up signals of aircrafts 200+ Km
away from me.
If you are interested in a more serious antenna check the following
resources:
* http://gnuradio.org/redmine/attachments/download/246/06-foster-adsb.pdf
* http://www.lll.lu/~edward/edward/adsb/antenna/ADSBantenna.html
* http://modesbeast.com/pix/adsb-ant-drawing.gif
Aggressive mode
---
With --aggressive it is possible to activate the *aggressive mode* that is a
modified version of the Mode S packet detection and decoding.
THe aggresive mode uses more CPU usually (especially if there are many planes
sending DF17 packets), but can detect a few more messages.
The algorithm in aggressive mode is modified in the following ways:
* Up to two demodulation errors are tolerated (adjacent entires in the magnitude
vector with the same eight). Normally only messages without errors are
checked.
* It tries to fix DF17 messages trying every two bits combination.
The use of aggressive mdoe is only advised in places where there is low traffic
in order to have a chance to capture some more messages.
Debug mode
---
The Debug mode is a visual help to improve the detection algorithm or to
understand why the program is not working for a given input.
In this mode messages are displayed in an ASCII-art style graphical
representation, where the individial magnitude bars sampled at 2Mhz are
displayed.
An index shows the sample number, where 0 is the sample where the first
Mode S peak was found. Some additional background noise is also added
before the first peak to provide some context.
To enable debug mode and check what combinations of packets you can
log, use `mode1090 --help` to obtain a list of available debug flags.
Debug mode includes an optional javascript output that is used to visualize
packets using a web browser, you can use the file debug.html under the
'tools' directory to load the generated frames.js file.
How this program works?
---
The code is very documented and written in order to be easy to understand.
For the diligent programmer with a Mode S specification on his hands it
should be trivial to understand how it works.
The algorithms I used were obtained basically looking at many messages
as displayed using a trow-away SDL program, and trying to model the algorithm
based on how the messages look graphically.
How to test the program?
---
If you have an RTLSDR device and you happen to be in an area where there
are aircrafts flying over your head, just run the program and check for signals.
However if you don't have an RTLSDR device, or if in your area the presence
of aircrafts is very limited, you may want to try the sample file distributed
with the Dump1090 distribution under the "testfiles" directory.
Just run it like this:
./dump1090 --ifile testfiles/modes1.bin
What is --strip mode?
---
It is just a simple filter that will get raw IQ 8 bit samples in input
and will output a file missing all the parts of the file where I and Q
are lower than the specified <level> for more than 32 samples.
Use it like this:
cat big.bin | ./dump1090 --snip 25 > small.bin
I used it in order to create a small test file to include inside this
program source code distribution.
Contributing
---
Dump1090 was written during some free time during xmas 2012, it is an hobby
project so I'll be able to address issues and improve it only during
free time, however you are incouraged to send pull requests in order to
improve the program. A good starting point can be the TODO list included in
the source distribution.
Credits
---
Dump1090 was written by Salvatore Sanfilippo <antirez@gmail.com> and is
released under the BSD three clause license.

Wyświetl plik

@ -1,5 +0,0 @@
TODO
* Extract more information from captured Mode S messages.
* Improve the web interface gmap.html.
* Enhance the algorithm to reliably decode more messages.

Wyświetl plik

@ -1,382 +0,0 @@
/* anet.c -- Basic TCP socket stuff made a bit less boring
*
* Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include "anet.h"
static void anetSetError(char *err, const char *fmt, ...)
{
va_list ap;
if (!err) return;
va_start(ap, fmt);
vsnprintf(err, ANET_ERR_LEN, fmt, ap);
va_end(ap);
}
int anetNonBlock(char *err, int fd)
{
int flags;
/* Set the socket nonblocking.
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
* interrupted by a signal. */
if ((flags = fcntl(fd, F_GETFL)) == -1) {
anetSetError(err, "fcntl(F_GETFL): %s", strerror(errno));
return ANET_ERR;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno));
return ANET_ERR;
}
return ANET_OK;
}
int anetTcpNoDelay(char *err, int fd)
{
int yes = 1;
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1)
{
anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno));
return ANET_ERR;
}
return ANET_OK;
}
int anetSetSendBuffer(char *err, int fd, int buffsize)
{
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1)
{
anetSetError(err, "setsockopt SO_SNDBUF: %s", strerror(errno));
return ANET_ERR;
}
return ANET_OK;
}
int anetTcpKeepAlive(char *err, int fd)
{
int yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) {
anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno));
return ANET_ERR;
}
return ANET_OK;
}
int anetResolve(char *err, char *host, char *ipbuf)
{
struct sockaddr_in sa;
sa.sin_family = AF_INET;
if (inet_aton(host, &sa.sin_addr) == 0) {
struct hostent *he;
he = gethostbyname(host);
if (he == NULL) {
anetSetError(err, "can't resolve: %s", host);
return ANET_ERR;
}
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
}
strcpy(ipbuf,inet_ntoa(sa.sin_addr));
return ANET_OK;
}
static int anetCreateSocket(char *err, int domain) {
int s, on = 1;
if ((s = socket(domain, SOCK_STREAM, 0)) == -1) {
anetSetError(err, "creating socket: %s", strerror(errno));
return ANET_ERR;
}
/* Make sure connection-intensive things like the redis benckmark
* will be able to close/open sockets a zillion of times */
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno));
return ANET_ERR;
}
return s;
}
#define ANET_CONNECT_NONE 0
#define ANET_CONNECT_NONBLOCK 1
static int anetTcpGenericConnect(char *err, char *addr, int port, int flags)
{
int s;
struct sockaddr_in sa;
if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR)
return ANET_ERR;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
if (inet_aton(addr, &sa.sin_addr) == 0) {
struct hostent *he;
he = gethostbyname(addr);
if (he == NULL) {
anetSetError(err, "can't resolve: %s", addr);
close(s);
return ANET_ERR;
}
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
}
if (flags & ANET_CONNECT_NONBLOCK) {
if (anetNonBlock(err,s) != ANET_OK)
return ANET_ERR;
}
if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
if (errno == EINPROGRESS &&
flags & ANET_CONNECT_NONBLOCK)
return s;
anetSetError(err, "connect: %s", strerror(errno));
close(s);
return ANET_ERR;
}
return s;
}
int anetTcpConnect(char *err, char *addr, int port)
{
return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONE);
}
int anetTcpNonBlockConnect(char *err, char *addr, int port)
{
return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONBLOCK);
}
int anetUnixGenericConnect(char *err, char *path, int flags)
{
int s;
struct sockaddr_un sa;
if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR)
return ANET_ERR;
sa.sun_family = AF_LOCAL;
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
if (flags & ANET_CONNECT_NONBLOCK) {
if (anetNonBlock(err,s) != ANET_OK)
return ANET_ERR;
}
if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) == -1) {
if (errno == EINPROGRESS &&
flags & ANET_CONNECT_NONBLOCK)
return s;
anetSetError(err, "connect: %s", strerror(errno));
close(s);
return ANET_ERR;
}
return s;
}
int anetUnixConnect(char *err, char *path)
{
return anetUnixGenericConnect(err,path,ANET_CONNECT_NONE);
}
int anetUnixNonBlockConnect(char *err, char *path)
{
return anetUnixGenericConnect(err,path,ANET_CONNECT_NONBLOCK);
}
/* Like read(2) but make sure 'count' is read before to return
* (unless error or EOF condition is encountered) */
int anetRead(int fd, char *buf, int count)
{
int nread, totlen = 0;
while(totlen != count) {
nread = read(fd,buf,count-totlen);
if (nread == 0) return totlen;
if (nread == -1) return -1;
totlen += nread;
buf += nread;
}
return totlen;
}
/* Like write(2) but make sure 'count' is read before to return
* (unless error is encountered) */
int anetWrite(int fd, char *buf, int count)
{
int nwritten, totlen = 0;
while(totlen != count) {
nwritten = write(fd,buf,count-totlen);
if (nwritten == 0) return totlen;
if (nwritten == -1) return -1;
totlen += nwritten;
buf += nwritten;
}
return totlen;
}
static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) {
if (bind(s,sa,len) == -1) {
anetSetError(err, "bind: %s", strerror(errno));
close(s);
return ANET_ERR;
}
/* Use a backlog of 512 entries. We pass 511 to the listen() call because
* the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1);
* which will thus give us a backlog of 512 entries */
if (listen(s, 511) == -1) {
anetSetError(err, "listen: %s", strerror(errno));
close(s);
return ANET_ERR;
}
return ANET_OK;
}
int anetTcpServer(char *err, int port, char *bindaddr)
{
int s;
struct sockaddr_in sa;
if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR)
return ANET_ERR;
memset(&sa,0,sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
if (bindaddr && inet_aton(bindaddr, &sa.sin_addr) == 0) {
anetSetError(err, "invalid bind address");
close(s);
return ANET_ERR;
}
if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa)) == ANET_ERR)
return ANET_ERR;
return s;
}
int anetUnixServer(char *err, char *path, mode_t perm)
{
int s;
struct sockaddr_un sa;
if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR)
return ANET_ERR;
memset(&sa,0,sizeof(sa));
sa.sun_family = AF_LOCAL;
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa)) == ANET_ERR)
return ANET_ERR;
if (perm)
chmod(sa.sun_path, perm);
return s;
}
static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) {
int fd;
while(1) {
fd = accept(s,sa,len);
if (fd == -1) {
if (errno == EINTR)
continue;
else {
anetSetError(err, "accept: %s", strerror(errno));
return ANET_ERR;
}
}
break;
}
return fd;
}
int anetTcpAccept(char *err, int s, char *ip, int *port) {
int fd;
struct sockaddr_in sa;
socklen_t salen = sizeof(sa);
if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == ANET_ERR)
return ANET_ERR;
if (ip) strcpy(ip,inet_ntoa(sa.sin_addr));
if (port) *port = ntohs(sa.sin_port);
return fd;
}
int anetUnixAccept(char *err, int s) {
int fd;
struct sockaddr_un sa;
socklen_t salen = sizeof(sa);
if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == ANET_ERR)
return ANET_ERR;
return fd;
}
int anetPeerToString(int fd, char *ip, int *port) {
struct sockaddr_in sa;
socklen_t salen = sizeof(sa);
if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) {
*port = 0;
ip[0] = '?';
ip[1] = '\0';
return -1;
}
if (ip) strcpy(ip,inet_ntoa(sa.sin_addr));
if (port) *port = ntohs(sa.sin_port);
return 0;
}
int anetSockName(int fd, char *ip, int *port) {
struct sockaddr_in sa;
socklen_t salen = sizeof(sa);
if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) {
*port = 0;
ip[0] = '?';
ip[1] = '\0';
return -1;
}
if (ip) strcpy(ip,inet_ntoa(sa.sin_addr));
if (port) *port = ntohs(sa.sin_port);
return 0;
}

Wyświetl plik

@ -1,59 +0,0 @@
/* anet.c -- Basic TCP socket stuff made a bit less boring
*
* Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ANET_H
#define ANET_H
#define ANET_OK 0
#define ANET_ERR -1
#define ANET_ERR_LEN 256
#if defined(__sun)
#define AF_LOCAL AF_UNIX
#endif
int anetTcpConnect(char *err, char *addr, int port);
int anetTcpNonBlockConnect(char *err, char *addr, int port);
int anetUnixConnect(char *err, char *path);
int anetUnixNonBlockConnect(char *err, char *path);
int anetRead(int fd, char *buf, int count);
int anetResolve(char *err, char *host, char *ipbuf);
int anetTcpServer(char *err, int port, char *bindaddr);
int anetUnixServer(char *err, char *path, mode_t perm);
int anetTcpAccept(char *err, int serversock, char *ip, int *port);
int anetUnixAccept(char *err, int serversock);
int anetWrite(int fd, char *buf, int count);
int anetNonBlock(char *err, int fd);
int anetTcpNoDelay(char *err, int fd);
int anetTcpKeepAlive(char *err, int fd);
int anetPeerToString(int fd, char *ip, int *port);
int anetSetSendBuffer(char *err, int fd, int buffsize);
#endif

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1,180 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map_canvas { height: 100% }
#info {
position: absolute;
width:20%;
height:100%;
bottom:0px;
right:0px;
top:0px;
background-color: white;
border-left:1px #666 solid;
font-family:Helvetica;
}
#info div {
padding:0px;
padding-left:10px;
margin:0px;
}
#info div h1 {
margin-top:10px;
font-size:16px;
}
#info div p {
font-size:14px;
color:#333;
}
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">
</script>
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?sensor=true">
</script>
<script type="text/javascript">
Map=null;
CenterLat=45.0;
CenterLon=9.0;
Planes={};
NumPlanes = 0;
Selected=null
function getIconForPlane(plane) {
var r = 255, g = 255, b = 0;
var maxalt = 40000; /* Max altitude in the average case */
var invalt = maxalt-plane.altitude;
var selected = (Selected == plane.hex);
if (invalt < 0) invalt = 0;
b = parseInt(255/maxalt*invalt);
return {
strokeWeight: (selected ? 2 : 1),
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
scale: 5,
fillColor: 'rgb('+r+','+g+','+b+')',
fillOpacity: 0.9,
rotation: plane.track
};
}
function selectPlane() {
if (!Planes[this.planehex]) return;
var old = Selected;
Selected = this.planehex;
if (Planes[old]) {
/* Remove the highlight in the previously selected plane. */
Planes[old].marker.setIcon(getIconForPlane(Planes[old]));
}
Planes[Selected].marker.setIcon(getIconForPlane(Planes[Selected]));
refreshSelectedInfo();
}
function refreshGeneralInfo() {
var i = document.getElementById('geninfo');
i.innerHTML = NumPlanes+' planes on screen.';
}
function refreshSelectedInfo() {
var i = document.getElementById('selinfo');
var p = Planes[Selected];
if (!p) return;
var html = 'ICAO: '+p.hex+'<br>';
if (p.flight.length) {
html += '<b>'+p.flight+'</b><br>';
}
html += 'Altitude: '+p.altitude+' feet<br>';
html += 'Speed: '+p.speed+' knots<br>';
html += 'Coordinates: '+p.lat+', '+p.lon+'<br>';
i.innerHTML = html;
}
function fetchData() {
$.getJSON('/data.json', function(data) {
var stillhere = {}
for (var j=0; j < data.length; j++) {
var plane = data[j];
var marker = null;
stillhere[plane.hex] = true;
plane.flight = $.trim(plane.flight);
if (Planes[plane.hex]) {
var myplane = Planes[plane.hex];
marker = myplane.marker;
var icon = marker.getIcon();
var newpos = new google.maps.LatLng(plane.lat, plane.lon);
marker.setPosition(newpos);
marker.setIcon(getIconForPlane(plane));
myplane.altitude = plane.altitude;
myplane.speed = plane.speed;
myplane.lat = plane.lat;
myplane.lon = plane.lon;
myplane.track = plane.track;
myplane.flight = plane.flight;
if (myplane.hex == Selected)
refreshSelectedInfo();
} else {
marker = new google.maps.Marker({
position: new google.maps.LatLng(plane.lat, plane.lon),
map: Map,
icon: getIconForPlane(plane)
});
plane.marker = marker;
marker.planehex = plane.hex;
Planes[plane.hex] = plane;
/* Trap clicks for this marker. */
google.maps.event.addListener(marker, 'click', selectPlane);
}
if (plane.flight.length == 0)
marker.setTitle(plane.hex)
else
marker.setTitle(plane.flight+' ('+plane.hex+')')
}
NumPlanes = data.length;
/* Remove idle planes. */
for (var p in Planes) {
if (!stillhere[p]) {
Planes[p].marker.setMap(null);
delete Planes[p];
}
}
});
}
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(CenterLat, CenterLon),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
Map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
/* Setup our timer to poll from the server. */
window.setInterval(function() {
fetchData();
refreshGeneralInfo();
}, 1000);
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:80%; height:100%"></div>
<div id="info">
<div>
<h1>Dump1090</h1>
<p id="geninfo"></p>
<p id="selinfo">Click on a plane for info.</p>
</div>
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -1,193 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<head>
<script>
var frames = [];
var currentFrame = 0;
var modes_checksum_table = [
0x3935ea, 0x1c9af5, 0xf1b77e, 0x78dbbf, 0xc397db, 0x9e31e9, 0xb0e2f0, 0x587178,
0x2c38bc, 0x161c5e, 0x0b0e2f, 0xfa7d13, 0x82c48d, 0xbe9842, 0x5f4c21, 0xd05c14,
0x682e0a, 0x341705, 0xe5f186, 0x72f8c3, 0xc68665, 0x9cb936, 0x4e5c9b, 0xd8d449,
0x939020, 0x49c810, 0x24e408, 0x127204, 0x093902, 0x049c81, 0xfdb444, 0x7eda22,
0x3f6d11, 0xe04c8c, 0x702646, 0x381323, 0xe3f395, 0x8e03ce, 0x4701e7, 0xdc7af7,
0x91c77f, 0xb719bb, 0xa476d9, 0xadc168, 0x56e0b4, 0x2b705a, 0x15b82d, 0xf52612,
0x7a9309, 0xc2b380, 0x6159c0, 0x30ace0, 0x185670, 0x0c2b38, 0x06159c, 0x030ace,
0x018567, 0xff38b7, 0x80665f, 0xbfc92b, 0xa01e91, 0xaff54c, 0x57faa6, 0x2bfd53,
0xea04ad, 0x8af852, 0x457c29, 0xdd4410, 0x6ea208, 0x375104, 0x1ba882, 0x0dd441,
0xf91024, 0x7c8812, 0x3e4409, 0xe0d800, 0x706c00, 0x383600, 0x1c1b00, 0x0e0d80,
0x0706c0, 0x038360, 0x01c1b0, 0x00e0d8, 0x00706c, 0x003836, 0x001c1b, 0xfff409,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
];
function modesChecksum(frame) {
var crc = 0;
var bits = frame.bits;
var offset = (bits == 112) ? 0 : (112-56);
for(var j = 0; j < bits; j++) {
var byte = j/8;
var bit = j%8;
var bitmask = 1 << (7-bit);
/* If bit is set, xor with corresponding table entry. */
if (frame.hex.charCodeAt(byte) & bitmask)
crc ^= modes_checksum_table[j+offset];
}
return crc; /* 24 bit checksum. */
}
function getFrameChecksum(frame) {
var res = "";
for (j = 0; j < frame.hex.length; j++) {
var val = frame.hex.charCodeAt(j);
var h = val.toString(16);
if (h.length == 1) h = "0"+h;
res += h;
}
return res;
}
function displayFrame(i) {
var div = document.getElementById("frame");
var msgbits = 8+112;
var frame = frames[i];
var padding = frame.mag.length - msgbits*2;
/* Remove the old representation. */
var nodes = div.childNodes.length;
for(var j = 0; j < nodes; j++) {
div.removeChild(div.firstChild);
}
/* Display the new one. */
for (var j = -padding; j < msgbits*2+padding; j++) {
var m = frame.mag[j+padding];
var type;
if (j < 0) type = "noise";
if (j >= 0 && j < 16) type = "pre";
if (j >= 16) {
if (!(j % 2)) {
var next = frame.mag[j+padding+1];
if (m > next)
type = "one";
else
type = "zero";
}
var bit = (j-16)/2;
if (bit == frame.fix1 ||
bit == frame.fix2)
type = "err";
}
var sample = document.createElement("div");
sample.setAttribute("class","sample "+type);
sample.setAttribute("title","sample "+j+" ("+m+")");
sample.style.left = ""+((j+padding)*4)+"px";
sample.style.height = ""+(m/256)+"px";
div.appendChild(sample);
}
document.getElementById("info").innerHTML =
"#"+currentFrame+" "+frame.descr+"<br>"+
"Bits:"+frame.bits+"<br>"+
"DF : "+(frame.hex.charCodeAt(0) >> 3)+"<br>"+
"fix1: "+frame.fix1+"<br>"+
"fix2: "+frame.fix2+"<br>"+
"hex : "+getFrameChecksum(frame)+"<br>"+
"crc (computed): "+modesChecksum(frame).toString(16)+"<br>";
}
function recomputeHex(frame) {
var padding = frame.mag.length - (112+8)*2;
var b = [];
var hex = "";
/* Get bits */
for (var j = 0; j < frame.bits*2; j += 2) {
var bit;
var l = frame.mag[padding+j+16];
var r = frame.mag[padding+j+1+16];
if (l > r)
bit = 1;
else
bit = 0;
b.push(bit);
}
/* Pack into bytes */
for (j = 0; j < frame.bits; j+= 8) {
hex += String.fromCharCode(
b[j]<<7 |
b[j+1]<<6 |
b[j+2]<<5 |
b[j+3]<<4 |
b[j+4]<<3 |
b[j+5]<<2 |
b[j+6]<<1 |
b[j+7]);
}
frame.hex = hex;
}
window.onload = function() {
document.getElementById("next").onclick = function() {
if (currentFrame != frames.length-1) currentFrame++;
displayFrame(currentFrame);
}
document.getElementById("prev").onclick = function() {
if (currentFrame != 0) currentFrame--;
displayFrame(currentFrame);
}
document.getElementById("re").onclick = function() {
recomputeHex(frames[currentFrame]);
displayFrame(currentFrame);
}
displayFrame(currentFrame);
}
</script>
<script src="frames.js"></script>
<style>
#frame {
width: 1024px;
height: 255px;
border: 1px #aaa solid;
position: relative;
}
.sample {
position: absolute;
bottom: 0px;
}
.pre {
width:4px;
background-color: orange;
}
.one {
width:4px;
background-color: #0000cc;
}
.zero {
width:4px;
background-color: #aaaaaa;
}
.err {
width:4px;
background-color: #cc6666;
}
.noise {
width:2px;
background-color: #ffffff;
border: 1px #aaa dotted;
}
</style>
</head>
<div id="frame">
</div>
<pre id="info">
</pre>
<input type="button" id="prev" value="Prev frame">
<input type="button" id="next" value="Next frame">
<input type="button" id="re" value="Recompute Hex">
</body>
</html>

Wyświetl plik

@ -1,4 +1,4 @@
CFLAGS+=-O2 -g -Wall -Werror -Ifec
CFLAGS+=-O2 -Wall -Werror -Ifec
LDFLAGS=
LIBS=-lm
CC=gcc

Wyświetl plik

@ -33,227 +33,259 @@ static void make_atan2_table(void);
#ifndef BUILD_LIB
static void read_from_stdin(void);
#endif
static int process_buffer(uint16_t *phi, int len, uint64_t offset);
static int process_buffer(uint16_t *phi, uint16_t *raw, int len,
uint64_t offset);
static int demod_adsb_frame(uint16_t *phi, uint8_t *to, int *rs_errors);
static int demod_uplink_frame(uint16_t *phi, uint8_t *to, int *rs_errors);
static void demod_frame(uint16_t *phi, uint8_t *frame, int bytes, int16_t center_dphi);
static void demod_frame(uint16_t *phi, uint8_t *frame, int bytes,
int16_t center_dphi);
static void handle_adsb_frame(uint64_t timestamp, uint8_t *frame, int rs);
static void handle_uplink_frame(uint64_t timestamp, uint8_t *frame, int rs);
#define SYNC_BITS (36)
#define ADSB_SYNC_WORD 0xEACDDA4E2UL
#define ADSB_SYNC_WORD 0xEACDDA4E2UL
#define UPLINK_SYNC_WORD 0x153225B1DUL
// relying on signed overflow is theoretically bad. Let's do it properly.
#ifdef USE_SIGNED_OVERFLOW
#define phi_difference(from,to) ((int16_t)((to) - (from)))
#define phi_difference(from, to) ((int16_t)((to) - (from)))
#else
inline int16_t phi_difference(uint16_t from, uint16_t to)
{
int32_t difference = to - from; // lies in the range -65535 .. +65535
if (difference >= 32768) // +32768..+65535
return difference - 65536; // -> -32768..-1: always in range
else if (difference < -32768) // -65535..-32769
return difference + 65536; // -> +1..32767: always in range
else
return difference;
inline int16_t phi_difference(uint16_t from, uint16_t to) {
int32_t difference = to - from; // lies in the range -65535 .. +65535
if (difference >= 32768) // +32768..+65535
return difference - 65536; // -> -32768..-1: always in range
else if (difference < -32768) // -65535..-32769
return difference + 65536; // -> +1..32767: always in range
else
return difference;
}
#endif
#ifndef BUILD_LIB
int main(int argc, char **argv)
{
make_atan2_table();
init_fec();
read_from_stdin();
return 0;
int main(int argc, char **argv) {
make_atan2_table();
init_fec();
read_from_stdin();
return 0;
}
#else
static CallBack userCB = NULL;
void Dump978Init(CallBack cb)
{
make_atan2_table();
init_fec();
userCB = cb;
void Dump978Init(CallBack cb) {
make_atan2_table();
init_fec();
userCB = cb;
}
#endif
static void dump_raw_message(char updown, uint8_t *data, int len, int rs_errors)
{
static int signal_strength = 0;
static void dump_raw_message(char updown, uint8_t *data, int len,
int rs_errors) {
#ifndef BUILD_LIB
int i;
int i;
fprintf(stdout, "%c", updown);
for (i = 0; i < len; ++i) {
fprintf(stdout, "%02x", data[i]);
}
fprintf(stdout, "%c", updown);
for (i = 0; i < len; ++i) {
fprintf(stdout, "%02x", data[i]);
}
if (rs_errors)
fprintf(stdout, ";rs=%d", rs_errors);
fprintf(stdout, ";\n");
if (rs_errors)
fprintf(stdout, ";rs=%d", rs_errors);
fprintf(stdout, ";ss=%d", signal_strength);
fprintf(stdout, ";\n");
#else
userCB(updown, data, len);
userCB(updown, data, len, rs_errors, signal_strength);
#endif
}
static void handle_adsb_frame(uint64_t timestamp, uint8_t *frame, int rs)
{
dump_raw_message('-', frame, (frame[0]>>3) == 0 ? SHORT_FRAME_DATA_BYTES : LONG_FRAME_DATA_BYTES, rs);
fflush(stdout);
static void handle_adsb_frame(uint64_t timestamp, uint8_t *frame, int rs) {
dump_raw_message('-', frame, (frame[0] >> 3) == 0 ? SHORT_FRAME_DATA_BYTES
: LONG_FRAME_DATA_BYTES,
rs);
fflush(stdout);
}
static void handle_uplink_frame(uint64_t timestamp, uint8_t *frame, int rs)
{
dump_raw_message('+', frame, UPLINK_FRAME_DATA_BYTES, rs);
fflush(stdout);
static void handle_uplink_frame(uint64_t timestamp, uint8_t *frame, int rs) {
dump_raw_message('+', frame, UPLINK_FRAME_DATA_BYTES, rs);
fflush(stdout);
}
uint16_t iqphase[65536]; // contains value [0..65536) -> [0, 2*pi)
void make_atan2_table(void)
{
unsigned i,q;
union {
uint8_t iq[2];
uint16_t iq16;
} u;
uint16_t iqamplitude[65536]; // contains value [0..65536) -> [0, 1000*sqrt(2))
for (i = 0; i < 256; ++i) {
for (q = 0; q < 256; ++q) {
double d_i = (i - 127.5);
double d_q = (q - 127.5);
double ang = atan2(d_q, d_i) + M_PI; // atan2 returns [-pi..pi], normalize to [0..2*pi]
double scaled_ang = round(32768 * ang / M_PI);
void make_atan2_table(void) {
unsigned i, q;
union {
uint8_t iq[2];
uint16_t iq16;
} u;
u.iq[0] = i;
u.iq[1] = q;
iqphase[u.iq16] = (scaled_ang < 0 ? 0 : scaled_ang > 65535 ? 65535 : (uint16_t)scaled_ang);
}
for (i = 0; i < 256; ++i) {
for (q = 0; q < 256; ++q) {
double d_i = (i - 127.5);
double d_q = (q - 127.5);
double ang = atan2(d_q, d_i) +
M_PI; // atan2 returns [-pi..pi], normalize to [0..2*pi]
double scaled_ang = round(32768 * ang / M_PI);
double amp = sqrt(d_i * d_i + d_q * d_q);
uint16_t scaled_amp = amp * 1000.0 / 127.5;
u.iq[0] = i;
u.iq[1] = q;
iqphase[u.iq16] =
(scaled_ang < 0 ? 0 : scaled_ang > 65535 ? 65535
: (uint16_t)scaled_ang);
iqamplitude[u.iq16] = scaled_amp;
}
}
}
static void convert_to_phi(uint16_t *buffer, int n)
{
static void convert_to_phi(uint16_t *dest, uint16_t *src, int n) {
int i;
for (i = 0; i < n; ++i)
buffer[i] = iqphase[buffer[i]];
// unroll the loop. n is always > 2048, usually 36864
for (i = 0; i+8 <= n; i += 8) {
dest[i] = iqphase[src[i]];
dest[i+1] = iqphase[src[i+1]];
dest[i+2] = iqphase[src[i+2]];
dest[i+3] = iqphase[src[i+3]];
dest[i+4] = iqphase[src[i+4]];
dest[i+5] = iqphase[src[i+5]];
dest[i+6] = iqphase[src[i+6]];
dest[i+7] = iqphase[src[i+7]];
}
for (; i < n; ++i)
dest[i] = iqphase[src[i]];
}
static void calc_power(uint16_t *samples, int len) { // sets signal_strength to scaled amplitude. 0 = no signal, 1000 = saturated receiver on all samples in measurement.
long avg = 0;
int n = len;
while (n--) {
avg += iqamplitude[*samples++];
}
signal_strength = avg / len;
}
#ifndef BUILD_LIB
void read_from_stdin(void)
{
char buffer[65536*2];
int n;
int used = 0;
uint64_t offset = 0;
void read_from_stdin(void) {
char buffer[65536 * 2];
uint16_t phi[65536];
while ( (n = read(0, buffer+used, sizeof(buffer)-used)) > 0 ) {
int processed;
int n;
int used = 0;
uint64_t offset = 0;
convert_to_phi((uint16_t*) (buffer+(used&~1)), ((used&1)+n)/2);
while ((n = read(0, buffer + used, sizeof(buffer) - used)) > 0) {
int processed;
used += n;
processed = process_buffer((uint16_t*) buffer, used/2, offset);
used -= processed * 2;
offset += processed;
if (used > 0) {
memmove(buffer, buffer+processed*2, used);
}
convert_to_phi(phi + used / 2, (uint16_t *)(buffer + (used & ~1)),
((used & 1) + n) / 2);
used += n;
processed = process_buffer(phi, (uint16_t *)buffer, used / 2, offset);
used -= processed * 2;
offset += processed;
if (used > 0) {
memmove(buffer, buffer + processed * 2, used);
memmove(phi, phi + processed, used);
}
}
}
#else
// #define DEFAULT_SAMPLE_RATE 2048000
// #define DEFAULT_BUF_LENGTH (262144) 16*16384
static char buffer[65536*2]; // 131072, max received should be 113120
int process_data(char *data, int dlen)
{
int n;
int processed;
int doffset = 0;
static int used = 0;
static uint64_t offset = 0;
static char buffer[65536 * 2]; // 131072, max received should be 113120
static uint16_t phi[65536];
int process_data(char *data, int dlen) {
int n;
int processed;
int doffset = 0;
static int used = 0;
static uint64_t offset = 0;
while (dlen > 0) {
n = (sizeof(buffer)-used) >= dlen ? dlen : (sizeof(buffer)-used);
memcpy(buffer+used, data+doffset, n);
while (dlen > 0) {
n = (sizeof(buffer) - used) >= dlen ? dlen : (sizeof(buffer) - used);
memcpy(buffer + used, data + doffset, n);
convert_to_phi((uint16_t*) (buffer+(used&~1)), ((used&1)+n)/2);
convert_to_phi(phi + used / 2, (uint16_t *)(buffer + (used & ~1)),
((used & 1) + n) / 2);
used += n;
processed = process_buffer((uint16_t*)buffer, used/2, offset);
used -= processed * 2;
offset += processed;
if (used > 0) {
memmove(buffer, buffer+processed*2, used);
}
doffset += n;
dlen -= n;
used += n;
processed = process_buffer(phi, (uint16_t *)buffer, used / 2, offset);
used -= processed * 2;
offset += processed;
if (used > 0) {
memmove(buffer, buffer + processed * 2, used);
memmove(phi, phi + processed, used);
}
return dlen;
doffset += n;
dlen -= n;
}
return dlen;
}
#endif
// Return 1 if word is "equal enough" to expected
static inline int sync_word_fuzzy_compare(uint64_t word, uint64_t expected)
{
uint64_t diff;
static inline int sync_word_fuzzy_compare(uint64_t word, uint64_t expected) {
uint64_t diff;
if (word == expected)
return 1;
if (word == expected)
return 1;
diff = word ^ expected; // guaranteed nonzero
diff = word ^ expected; // guaranteed nonzero
// This is a bit-twiddling popcount
// hack, tweaked as we only care about
// "<N" or ">=N" set bits for fixed N -
// so we can bail out early after seeing N
// set bits.
//
// It relies on starting with a nonzero value
// with zero or more trailing clear bits
// after the last set bit:
//
// 010101010101010000
// ^
// Subtracting one, will flip the
// bits starting at the last set bit:
//
// 010101010101001111
// ^
// then we can use that as a bitwise-and
// mask to clear the lowest set bit:
//
// 010101010101000000
// ^
// And repeat until the value is zero
// or we have seen too many set bits.
// This is a bit-twiddling popcount
// hack, tweaked as we only care about
// "<N" or ">=N" set bits for fixed N -
// so we can bail out early after seeing N
// set bits.
//
// It relies on starting with a nonzero value
// with zero or more trailing clear bits
// after the last set bit:
//
// 010101010101010000
// ^
// Subtracting one, will flip the
// bits starting at the last set bit:
//
// 010101010101001111
// ^
// then we can use that as a bitwise-and
// mask to clear the lowest set bit:
//
// 010101010101000000
// ^
// And repeat until the value is zero
// or we have seen too many set bits.
// >= 1 bit
diff &= (diff-1); // clear lowest set bit
if (!diff)
return 1; // 1 bit error
// >= 1 bit
diff &= (diff - 1); // clear lowest set bit
if (!diff)
return 1; // 1 bit error
// >= 2 bits
diff &= (diff-1); // clear lowest set bit
if (!diff)
return 1; // 2 bits error
// >= 2 bits
diff &= (diff - 1); // clear lowest set bit
if (!diff)
return 1; // 2 bits error
// >= 3 bits
diff &= (diff-1); // clear lowest set bit
if (!diff)
return 1; // 3 bits error
// >= 3 bits
diff &= (diff - 1); // clear lowest set bit
if (!diff)
return 1; // 3 bits error
// >= 4 bits
diff &= (diff-1); // clear lowest set bit
if (!diff)
return 1; // 4 bits error
// >= 4 bits
diff &= (diff - 1); // clear lowest set bit
if (!diff)
return 1; // 4 bits error
// > 4 bits in error, give up
return 0;
// > 4 bits in error, give up
return 0;
}
#define MAX_SYNC_ERRORS 4
@ -262,172 +294,185 @@ static inline int sync_word_fuzzy_compare(uint64_t word, uint64_t expected)
// that matches the sync word 'pattern'. Place the dphi
// threshold to use for bit slicing in '*center'. Return 1
// if the sync word is OK, 0 on failure
int check_sync_word(uint16_t *phi, uint64_t pattern, int16_t *center)
{
int i;
int32_t dphi_zero_total = 0;
int zero_bits = 0;
int32_t dphi_one_total = 0;
int one_bits = 0;
int error_bits;
int check_sync_word(uint16_t *phi, uint64_t pattern, int16_t *center) {
int i;
int32_t dphi_zero_total = 0;
int zero_bits = 0;
int32_t dphi_one_total = 0;
int one_bits = 0;
int error_bits;
// find mean dphi for zero and one bits;
// take the mean of the two as our central value
// find mean dphi for zero and one bits;
// take the mean of the two as our central value
for (i = 0; i < SYNC_BITS; ++i) {
int16_t dphi = phi_difference(phi[i*2], phi[i*2+1]);
for (i = 0; i < SYNC_BITS; ++i) {
int16_t dphi = phi_difference(phi[i * 2], phi[i * 2 + 1]);
if (pattern & (1UL << (35-i))) {
++one_bits;
dphi_one_total += dphi;
} else {
++zero_bits;
dphi_zero_total += dphi;
}
if (pattern & (1UL << (35 - i))) {
++one_bits;
dphi_one_total += dphi;
} else {
++zero_bits;
dphi_zero_total += dphi;
}
}
dphi_zero_total /= zero_bits;
dphi_one_total /= one_bits;
dphi_zero_total /= zero_bits;
dphi_one_total /= one_bits;
*center = (dphi_one_total + dphi_zero_total) / 2;
*center = (dphi_one_total + dphi_zero_total) / 2;
// recheck sync word using our center value
error_bits = 0;
for (i = 0; i < SYNC_BITS; ++i) {
int16_t dphi = phi_difference(phi[i*2], phi[i*2+1]);
// recheck sync word using our center value
error_bits = 0;
for (i = 0; i < SYNC_BITS; ++i) {
int16_t dphi = phi_difference(phi[i * 2], phi[i * 2 + 1]);
if (pattern & (1UL << (35-i))) {
if (dphi < *center)
++error_bits;
} else {
if (dphi >= *center)
++error_bits;
}
if (pattern & (1UL << (35 - i))) {
if (dphi < *center)
++error_bits;
} else {
if (dphi >= *center)
++error_bits;
}
}
//fprintf(stdout, "check_sync_word: center=%.0fkHz, errors=%d\n", *center * 2083334.0 / 65536 / 1000, error_bits);
// fprintf(stdout, "check_sync_word: center=%.0fkHz, errors=%d\n", *center *
// 2083334.0 / 65536 / 1000, error_bits);
return (error_bits <= MAX_SYNC_ERRORS);
return (error_bits <= MAX_SYNC_ERRORS);
}
#define SYNC_MASK ((((uint64_t)1)<<SYNC_BITS)-1)
#define SYNC_MASK ((((uint64_t)1) << SYNC_BITS) - 1)
int process_buffer(uint16_t *phi, int len, uint64_t offset)
{
uint64_t sync0 = 0, sync1 = 0;
int lenbits;
int bit;
int process_buffer(uint16_t *phi, uint16_t *raw, int len, uint64_t offset) {
uint64_t sync0 = 0, sync1 = 0;
int lenbits;
int bit;
uint8_t demod_buf_a[UPLINK_FRAME_BYTES];
uint8_t demod_buf_b[UPLINK_FRAME_BYTES];
uint8_t demod_buf_a[UPLINK_FRAME_BYTES];
uint8_t demod_buf_b[UPLINK_FRAME_BYTES];
// We expect samples at twice the UAT bitrate.
// We look at phase difference between pairs of adjacent samples, i.e.
// sample 1 - sample 0 -> sync0
// sample 2 - sample 1 -> sync1
// sample 3 - sample 2 -> sync0
// sample 4 - sample 3 -> sync1
// ...
//
// We accumulate bits into two buffers, sync0 and sync1.
// Then we compare those buffers to the expected 36-bit sync word that
// should be at the start of each UAT frame. When (if) we find it,
// that tells us which sample to start decoding from.
// We expect samples at twice the UAT bitrate.
// We look at phase difference between pairs of adjacent samples, i.e.
// sample 1 - sample 0 -> sync0
// sample 2 - sample 1 -> sync1
// sample 3 - sample 2 -> sync0
// sample 4 - sample 3 -> sync1
// ...
//
// We accumulate bits into two buffers, sync0 and sync1.
// Then we compare those buffers to the expected 36-bit sync word that
// should be at the start of each UAT frame. When (if) we find it,
// that tells us which sample to start decoding from.
// Stop when we run out of remaining samples for a max-sized frame.
// Arrange for our caller to pass the trailing data back to us next time;
// ensure we don't consume any partial sync word we might be part-way
// through. This means we don't need to maintain state between calls.
// Stop when we run out of remaining samples for a max-sized frame.
// Arrange for our caller to pass the trailing data back to us next time;
// ensure we don't consume any partial sync word we might be part-way
// through. This means we don't need to maintain state between calls.
lenbits = len/2 - (SYNC_BITS + UPLINK_FRAME_BITS);
for (bit = 0; bit < lenbits; ++bit) {
int16_t dphi0 = phi_difference(phi[bit*2], phi[bit*2+1]);
int16_t dphi1 = phi_difference(phi[bit*2+1], phi[bit*2+2]);
lenbits = len / 2 - (SYNC_BITS + UPLINK_FRAME_BITS);
for (bit = 0; bit < lenbits; ++bit) {
int16_t dphi0 = phi_difference(phi[bit * 2], phi[bit * 2 + 1]);
int16_t dphi1 = phi_difference(phi[bit * 2 + 1], phi[bit * 2 + 2]);
sync0 = ((sync0 << 1) | (dphi0 > 0 ? 1 : 0)) & SYNC_MASK;
sync1 = ((sync1 << 1) | (dphi1 > 0 ? 1 : 0)) & SYNC_MASK;
sync0 = ((sync0 << 1) | (dphi0 > 0 ? 1 : 0)) & SYNC_MASK;
sync1 = ((sync1 << 1) | (dphi1 > 0 ? 1 : 0)) & SYNC_MASK;
if (bit < SYNC_BITS)
continue; // haven't fully populated sync0/1 yet
if (bit < SYNC_BITS)
continue; // haven't fully populated sync0/1 yet
// see if we have (the start of) a valid sync word
// It would be nice to look at popcount(expected ^ sync)
// so we can tolerate some errors, but that turns out
// to be very expensive to do on every sample
// see if we have (the start of) a valid sync word
// It would be nice to look at popcount(expected ^ sync)
// so we can tolerate some errors, but that turns out
// to be very expensive to do on every sample
// when we find a match, try to demodulate both with that match
// and with the next position, and pick the one with fewer
// errors.
// when we find a match, try to demodulate both with that match
// and with the next position, and pick the one with fewer
// errors.
// check for downlink frames:
if (sync_word_fuzzy_compare(sync0, ADSB_SYNC_WORD) || sync_word_fuzzy_compare(sync1, ADSB_SYNC_WORD)) {
int startbit = (bit-SYNC_BITS+1);
int shift = (sync_word_fuzzy_compare(sync0, ADSB_SYNC_WORD) ? 0 : 1);
int index = startbit*2+shift;
// check for downlink frames:
if (sync_word_fuzzy_compare(sync0, ADSB_SYNC_WORD) ||
sync_word_fuzzy_compare(sync1, ADSB_SYNC_WORD)) {
int startbit = (bit - SYNC_BITS + 1);
int shift = (sync_word_fuzzy_compare(sync0, ADSB_SYNC_WORD) ? 0 : 1);
int index = startbit * 2 + shift;
int skip_0, skip_1;
int rs_0 = -1, rs_1 = -1;
int skip_0, skip_1;
int rs_0 = -1, rs_1 = -1;
skip_0 = demod_adsb_frame(phi+index, demod_buf_a, &rs_0);
skip_1 = demod_adsb_frame(phi+index+1, demod_buf_b, &rs_1);
if (skip_0 && rs_0 <= rs_1) {
handle_adsb_frame(offset+index, demod_buf_a, rs_0);
bit = startbit + skip_0;
continue;
} else if (skip_1 && rs_1 <= rs_0) {
handle_adsb_frame(offset+index+1, demod_buf_b, rs_1);
bit = startbit + skip_1;
continue;
} else {
// demod failed
}
}
// check for uplink frames:
else if (sync_word_fuzzy_compare(sync0, UPLINK_SYNC_WORD) || sync_word_fuzzy_compare(sync1, UPLINK_SYNC_WORD)) {
int startbit = (bit-SYNC_BITS+1);
int shift = (sync_word_fuzzy_compare(sync0, UPLINK_SYNC_WORD) ? 0 : 1);
int index = startbit*2+shift;
int skip_0, skip_1;
int rs_0 = -1, rs_1 = -1;
skip_0 = demod_uplink_frame(phi+index, demod_buf_a, &rs_0);
skip_1 = demod_uplink_frame(phi+index+1, demod_buf_b, &rs_1);
if (skip_0 && rs_0 <= rs_1) {
handle_uplink_frame(offset+index, demod_buf_a, rs_0);
bit = startbit + skip_0;
continue;
} else if (skip_1 && rs_1 <= rs_0) {
handle_uplink_frame(offset+index+1, demod_buf_b, rs_1);
bit = startbit + skip_1;
continue;
} else {
// demod failed
}
}
skip_0 = demod_adsb_frame(phi + index, demod_buf_a, &rs_0);
skip_1 = demod_adsb_frame(phi + index + 1, demod_buf_b, &rs_1);
if (skip_0 && rs_0 <= rs_1) {
calc_power(raw + index, skip_0 * 2);
handle_adsb_frame(offset + index, demod_buf_a, rs_0);
bit = startbit + skip_0;
continue;
} else if (skip_1 && rs_1 <= rs_0) {
calc_power(raw + index + 1, skip_1 * 2);
handle_adsb_frame(offset + index + 1, demod_buf_b, rs_1);
bit = startbit + skip_1;
continue;
} else {
// demod failed
}
}
return (bit - SYNC_BITS)*2;
// check for uplink frames:
else if (sync_word_fuzzy_compare(sync0, UPLINK_SYNC_WORD) ||
sync_word_fuzzy_compare(sync1, UPLINK_SYNC_WORD)) {
int startbit = (bit - SYNC_BITS + 1);
int shift = (sync_word_fuzzy_compare(sync0, UPLINK_SYNC_WORD) ? 0 : 1);
int index = startbit * 2 + shift;
int skip_0, skip_1;
int rs_0 = -1, rs_1 = -1;
skip_0 = demod_uplink_frame(phi + index, demod_buf_a, &rs_0);
skip_1 = demod_uplink_frame(phi + index + 1, demod_buf_b, &rs_1);
if (skip_0 && rs_0 <= rs_1) {
calc_power(raw + index, skip_0 * 2);
handle_uplink_frame(offset + index, demod_buf_a, rs_0);
bit = startbit + skip_0;
continue;
} else if (skip_1 && rs_1 <= rs_0) {
calc_power(raw + index, skip_1 * 2);
handle_uplink_frame(offset + index + 1, demod_buf_b, rs_1);
bit = startbit + skip_1;
continue;
} else {
// demod failed
}
}
}
return (bit - SYNC_BITS) * 2;
}
// demodulate 'bytes' bytes from samples at 'phi' into 'frame',
// using 'center_dphi' as the bit slicing threshold
static void demod_frame(uint16_t *phi, uint8_t *frame, int bytes, int16_t center_dphi)
{
while (--bytes >= 0) {
uint8_t b = 0;
if (phi_difference(phi[0], phi[1]) > center_dphi) b |= 0x80;
if (phi_difference(phi[2], phi[3]) > center_dphi) b |= 0x40;
if (phi_difference(phi[4], phi[5]) > center_dphi) b |= 0x20;
if (phi_difference(phi[6], phi[7]) > center_dphi) b |= 0x10;
if (phi_difference(phi[8], phi[9]) > center_dphi) b |= 0x08;
if (phi_difference(phi[10], phi[11]) > center_dphi) b |= 0x04;
if (phi_difference(phi[12], phi[13]) > center_dphi) b |= 0x02;
if (phi_difference(phi[14], phi[15]) > center_dphi) b |= 0x01;
*frame++ = b;
phi += 16;
}
static void demod_frame(uint16_t *phi, uint8_t *frame, int bytes,
int16_t center_dphi) {
while (--bytes >= 0) {
uint8_t b = 0;
if (phi_difference(phi[0], phi[1]) > center_dphi)
b |= 0x80;
if (phi_difference(phi[2], phi[3]) > center_dphi)
b |= 0x40;
if (phi_difference(phi[4], phi[5]) > center_dphi)
b |= 0x20;
if (phi_difference(phi[6], phi[7]) > center_dphi)
b |= 0x10;
if (phi_difference(phi[8], phi[9]) > center_dphi)
b |= 0x08;
if (phi_difference(phi[10], phi[11]) > center_dphi)
b |= 0x04;
if (phi_difference(phi[12], phi[13]) > center_dphi)
b |= 0x02;
if (phi_difference(phi[14], phi[15]) > center_dphi)
b |= 0x01;
*frame++ = b;
phi += 16;
}
}
// Demodulate an ADSB (Long UAT or Basic UAT) downlink frame
@ -436,24 +481,23 @@ static void demod_frame(uint16_t *phi, uint8_t *frame, int bytes, int16_t center
// number of corrected errors, or 9999 if demodulation failed.
// Return 0 if demodulation failed, or the number of bits (not
// samples) consumed if demodulation was OK.
static int demod_adsb_frame(uint16_t *phi, uint8_t *to, int *rs_errors)
{
int16_t center_dphi;
int frametype;
static int demod_adsb_frame(uint16_t *phi, uint8_t *to, int *rs_errors) {
int16_t center_dphi;
int frametype;
if (!check_sync_word(phi, ADSB_SYNC_WORD, &center_dphi)) {
*rs_errors = 9999;
return 0;
}
if (!check_sync_word(phi, ADSB_SYNC_WORD, &center_dphi)) {
*rs_errors = 9999;
return 0;
}
demod_frame(phi + SYNC_BITS*2, to, LONG_FRAME_BYTES, center_dphi);
frametype = correct_adsb_frame(to, rs_errors);
if (frametype == 1)
return (SYNC_BITS + SHORT_FRAME_BITS);
else if (frametype == 2)
return (SYNC_BITS + LONG_FRAME_BITS);
else
return 0;
demod_frame(phi + SYNC_BITS * 2, to, LONG_FRAME_BYTES, center_dphi);
frametype = correct_adsb_frame(to, rs_errors);
if (frametype == 1)
return (SYNC_BITS + SHORT_FRAME_BITS);
else if (frametype == 2)
return (SYNC_BITS + LONG_FRAME_BITS);
else
return 0;
}
// Demodulate an uplink frame
@ -462,21 +506,21 @@ static int demod_adsb_frame(uint16_t *phi, uint8_t *to, int *rs_errors)
// number of corrected errors, or 9999 if demodulation failed.
// Return 0 if demodulation failed, or the number of bits (not
// samples) consumed if demodulation was OK.
static int demod_uplink_frame(uint16_t *phi, uint8_t *to, int *rs_errors)
{
int16_t center_dphi;
uint8_t interleaved[UPLINK_FRAME_BYTES];
static int demod_uplink_frame(uint16_t *phi, uint8_t *to, int *rs_errors) {
int16_t center_dphi;
uint8_t interleaved[UPLINK_FRAME_BYTES];
if (!check_sync_word(phi, UPLINK_SYNC_WORD, &center_dphi)) {
*rs_errors = 9999;
return 0;
}
if (!check_sync_word(phi, UPLINK_SYNC_WORD, &center_dphi)) {
*rs_errors = 9999;
return 0;
}
demod_frame(phi + SYNC_BITS*2, interleaved, UPLINK_FRAME_BYTES, center_dphi);
demod_frame(phi + SYNC_BITS * 2, interleaved, UPLINK_FRAME_BYTES,
center_dphi);
// deinterleave and correct
if (correct_uplink_frame(interleaved, to, rs_errors) == 1)
return (UPLINK_FRAME_BITS+SYNC_BITS);
else
return 0;
}
// deinterleave and correct
if (correct_uplink_frame(interleaved, to, rs_errors) == 1)
return (UPLINK_FRAME_BITS + SYNC_BITS);
else
return 0;
}

Wyświetl plik

@ -4,7 +4,7 @@
// $ gcc -c -O2 -g -Wall -Werror -Ifec -fpic -DBUILD_LIB=1 dump978.c fec.c fec/decode_rs_char.c fec/init_rs_char.c
// $ gcc -shared -lm -o ../libdump978.so dump978.o fec.o decode_rs_char.o init_rs_char.o
typedef void (*CallBack)(char updown, uint8_t *data, int len);
typedef void (*CallBack)(char updown, uint8_t *data, int len, int rs_errors, int signal_strength);
extern void Dump978Init(CallBack cb);
extern int process_data(char *data, int dlen);

Wyświetl plik

@ -267,7 +267,8 @@ static void uat_display_sv(const struct uat_adsb_mdb *mdb, FILE *to)
mdb->tisb_site_id);
}
static char base40_alphabet[40] = "0123456789ABCDEFGHIJKLMNOPQRTSUVWXYZ ..";
static char base40_alphabet[40] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ..";
static void uat_decode_ms(uint8_t *frame, struct uat_adsb_mdb *mdb)
{
uint16_t v;

Wyświetl plik

@ -19,16 +19,16 @@
package godump978
/*
#cgo linux LDFLAGS: -L. -ldump978
#cgo darwin LDFLAGS: -L. -ldump978
#cgo linux LDFLAGS: -ldump978 -lm
#cgo darwin LDFLAGS: -ldump978 -lm
#cgo windows CFLAGS: -IC:/WINDOWS/system32
#cgo windows LDFLAGS: -L. -lrtlsdr -LC:/WINDOWS/system32
#cgo windows LDFLAGS: -L. -ldump978 -LC:/WINDOWS/system32
#include <stdlib.h>
#include <stdint.h>
#include "../dump978/dump978.h"
extern void dump978Cb(char updown, uint8_t *data, int len);
extern void dump978Cb(char updown, uint8_t *data, int len, int rs_errors, int signal_strength);
static inline CallBack GetGoCb() {
return (CallBack)dump978Cb;
}
@ -42,10 +42,9 @@ var PackageVersion = "v0.1"
// InChan is a buffered input channel for raw data.
var InChan = make(chan []byte, 100)
type UserCbT func(C.char, *C.uint8_t, C.int)
type UserCbT func(C.char, *C.uint8_t, C.int, C.int, C.int)
// Dump978Init must be the first function called in this package.
func Dump978Init() {
func init() {
C.Dump978Init((C.CallBack)(C.GetGoCb()))
}

Wyświetl plik

@ -10,9 +10,12 @@ import (
"fmt"
"reflect"
"unsafe"
"strconv"
)
/*
#cgo CFLAGS: -L../
#include <stdint.h>
#include "../dump978/dump978.h"
*/
@ -22,7 +25,7 @@ import "C"
var OutChan = make(chan string, 100)
//export dump978Cb
func dump978Cb(updown C.char, data *C.uint8_t, length C.int) {
func dump978Cb(updown C.char, data *C.uint8_t, length C.int, rs_errors C.int, signal_strength C.int) {
// c buffer to go slice without copying
var buf []byte
@ -37,5 +40,7 @@ func dump978Cb(updown C.char, data *C.uint8_t, length C.int) {
outData += fmt.Sprintf("%02x", buf[i])
}
outData += ";rs=" + strconv.Itoa(int(rs_errors)) + ";ss=" + strconv.Itoa(int(signal_strength)) + ";"
OutChan <- outData
}

1
goflying 160000

@ -0,0 +1 @@
Subproject commit 1da95360a858bfdc5af2b4e7d5caa66542f164e1

Wyświetl plik

@ -0,0 +1,48 @@
# To be placed in /etc/udev/rules.d.
# Auto-detect common USB stratux peripherals.
# u-blox devices. Known devices include
# ublox9: experimental boards
# ublox8: RY835AI, RY836AI, GPYes 2.0
# ublox7: VK-172, RY725AI, GPYes
# ublox6: VK-162
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a9", SYMLINK+="ublox9"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a8", SYMLINK+="ublox8"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a7", SYMLINK+="ublox7"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a6", SYMLINK+="ublox6"
#SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a7", SYMLINK+="vk172"
#SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a6", SYMLINK+="vk162"
# Stratux uatradio.
# 0403:7028 (Stratux UATRadio)
ATTRS{idProduct}=="7028", ATTRS{idVendor}=="0403", RUN+="/sbin/modprobe -q ftdi_sio" RUN+="/bin/sh -c 'echo 0403 7028 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'", OWNER="root", MODE="0666", SYMLINK+="uatradio"
# pl2303 devices are indistinguishable using idVendor and idProduct.
# Currently the BU-353-S4 and the TU-S9 (serialout) use the pl2303.
SUBSYSTEMS=="usb", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", SYMLINK+="prolific%n"
#SUBSYSTEMS=="usb", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", SYMLINK+="bu353s4"
#SUBSYSTEMS=="usb", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", SYMLINK+="tu-s9"
# CP2102-based serial adapters. Assume that all devices plugged in with this idVendor and idProduct are for serialout.
#cp210x-program --write-cp210x -m 10C4:EA60 \
# --set-product-string="Stratux Serialout" \
# --set-max-power=100 \
# --set-bus-powered=no
SUBSYSTEMS=="usb", ATTRS{interface}=="Stratux Serialout", SYMLINK+="serialout%n"
# SoftRF.
# SoftRF Standalone (NodeMCU or DoIt ESP32 devkit with CP2102 chip)
SUBSYSTEMS=="usb", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{product}=="DIY SoftRF", SYMLINK+="softrf"
# TTGO T-Beam (ESP32 with OTP CP2104 chip)
SUBSYSTEMS=="usb", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{product}=="CP2104 USB to UART Bridge Controller", SYMLINK+="softrf"
# Dongle Edition (LilyGO & SoftRF T-Motion. USB CDC ACM output)
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", SYMLINK+="softrf"
# end of SoftRF section

Wyświetl plik

@ -0,0 +1,6 @@
# uAvionix Ping Mavlink
ATTRS{idProduct}=="74f0", ATTRS{idVendor}=="0403", RUN+="/sbin/modprobe -q ftdi_sio" RUN+="/bin/sh -c 'echo 0403 74f0 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'", OWNER="root", MODE="0666", SYMLINK+="ping"
# uAvionix Ping Raw
ATTRS{idProduct}=="74f1", ATTRS{idVendor}=="0403", RUN+="/sbin/modprobe -q ftdi_sio" RUN+="/bin/sh -c 'echo 0403 74f1 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'", OWNER="root", MODE="0666", SYMLINK+="ping"

31
image/bashrc.txt 100644
Wyświetl plik

@ -0,0 +1,31 @@
# ~/.bashrc: executed by bash(1) for non-login shells.
# Note: PS1 and umask are already set in /etc/profile. You should not
# need this unless you want different defaults for root.
# PS1='${debian_chroot:+($debian_chroot)}\h:\w\$ '
# umask 022
# You may uncomment the following lines if you want `ls' to be colorized:
# export LS_OPTIONS='--color=auto'
# eval "`dircolors`"
# alias ls='ls $LS_OPTIONS'
# alias ll='ls $LS_OPTIONS -l'
# alias l='ls $LS_OPTIONS -lA'
#
# Some more alias to avoid making mistakes:
# alias rm='rm -i'
# alias cp='cp -i'
# alias mv='mv -i'
export PATH=/root/go/bin:${PATH}
export GOROOT=/root/go
export GOPATH=/root/go_path
# This will allow users to keep an alias file after this file is added
if [ -f /root/.aliases ]; then
. /root/.aliases
fi
# Useful aliases for stratux debugging
if [ -f /root/.stxAliases ]; then
. /root/.stxAliases
fi

20
image/config.txt 100644
Wyświetl plik

@ -0,0 +1,20 @@
# RPi /boot/config.txt
dtparam=audio=on
max_usb_current=1
dtparam=i2c_arm=on
dtparam=i2c1=on
dtparam=i2c1_baudrate=400000
dtparam=i2c_arm_baudrate=400000
# move RPi3 Bluetooth off of hardware UART to free up connection for GPS
dtoverlay=pi3-miniuart-bt
# disable default (mmc0) behavior on the ACT LED.
dtparam=act_led_trigger=none
dtparam=act_led_activelow=off
# The below has been added as a proposed EMI reduction measure. Issue #573.
sdram_freq=450
core_freq=450
arm_freq=900

Wyświetl plik

@ -0,0 +1,14 @@
ddns-update-style none;
default-lease-time 86400; # 24 hours
max-lease-time 172800; # 48 hours
authoritative;
log-facility local7;
subnet 192.168.10.0 netmask 255.255.255.0 {
range 192.168.10.10 192.168.10.50;
option broadcast-address 192.168.10.255;
option routers 192.168.10.1;
default-lease-time 12000;
max-lease-time 12000;
option domain-name "stratux.local";
option domain-name-servers 4.2.2.2;
}

Wyświetl plik

@ -0,0 +1,13 @@
ddns-update-style none;
default-lease-time 86400; # 24 hours
max-lease-time 172800; # 48 hours
authoritative;
log-facility local7;
subnet 192.168.10.0 netmask 255.255.255.0 {
range 192.168.10.10 192.168.10.50;
option broadcast-address 192.168.10.255;
default-lease-time 12000;
max-lease-time 12000;
option domain-name "stratux.local";
option domain-name-servers 4.2.2.2;
}

Wyświetl plik

@ -1,118 +0,0 @@
#
# Sample configuration file for ISC dhcpd for Debian
#
#
# The ddns-updates-style parameter controls whether or not the server will
# attempt to do a DNS update when a lease is confirmed. We default to the
# behavior of the version 2 packages ('none', since DHCP v2 didn't
# have support for DDNS.)
ddns-update-style none;
# option definitions common to all supported networks...
#option domain-name "stratux.local";
#option domain-name-servers ns1.example.org, ns2.example.org;
default-lease-time 86400; # 24 hours
max-lease-time 172800; # 48 hours
# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;
# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;
# No service will be given on this subnet, but declaring it helps the
# DHCP server to understand the network topology.
#subnet 10.152.187.0 netmask 255.255.255.0 {
#}
# This is a very basic subnet declaration.
#subnet 10.254.239.0 netmask 255.255.255.224 {
# range 10.254.239.10 10.254.239.20;
# option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
#}
# This declaration allows BOOTP clients to get dynamic addresses,
# which we don't really recommend.
#subnet 10.254.239.32 netmask 255.255.255.224 {
# range dynamic-bootp 10.254.239.40 10.254.239.60;
# option broadcast-address 10.254.239.31;
# option routers rtr-239-32-1.example.org;
#}
# A slightly different configuration for an internal subnet.
#subnet 10.5.5.0 netmask 255.255.255.224 {
# range 10.5.5.26 10.5.5.30;
# option domain-name-servers ns1.internal.example.org;
# option domain-name "internal.example.org";
# option routers 10.5.5.1;
# option broadcast-address 10.5.5.31;
# default-lease-time 600;
# max-lease-time 7200;
#}
# Hosts which require special configuration options can be listed in
# host statements. If no address is specified, the address will be
# allocated dynamically (if possible), but the host-specific information
# will still come from the host declaration.
#host passacaglia {
# hardware ethernet 0:0:c0:5d:bd:95;
# filename "vmunix.passacaglia";
# server-name "toccata.fugue.com";
#}
# Fixed IP addresses can also be specified for hosts. These addresses
# should not also be listed as being available for dynamic assignment.
# Hosts for which fixed IP addresses have been specified can boot using
# BOOTP or DHCP. Hosts for which no fixed address is specified can only
# be booted with DHCP, unless there is an address range on the subnet
# to which a BOOTP client is connected which has the dynamic-bootp flag
# set.
#host fantasia {
# hardware ethernet 08:00:07:26:c0:a5;
# fixed-address fantasia.fugue.com;
#}
# You can declare a class of clients and then do address allocation
# based on that. The example below shows a case where all clients
# in a certain class get addresses on the 10.17.224/24 subnet, and all
# other clients get addresses on the 10.0.29/24 subnet.
#class "foo" {
# match if substring (option vendor-class-identifier, 0, 4) = "SUNW";
#}
#shared-network 224-29 {
# subnet 10.17.224.0 netmask 255.255.255.0 {
# option routers rtr-224.example.org;
# }
# subnet 10.0.29.0 netmask 255.255.255.0 {
# option routers rtr-29.example.org;
# }
# pool {
# allow members of "foo";
# range 10.17.224.10 10.17.224.250;
# }
# pool {
# deny members of "foo";
# range 10.0.29.10 10.0.29.230;
# }
#}
subnet 192.168.10.0 netmask 255.255.255.0 {
range 192.168.10.10 192.168.10.50;
option broadcast-address 192.168.10.255;
option routers 0.0.0.0;
default-lease-time 12000;
max-lease-time 12000;
option domain-name "stratux.local";
option domain-name-servers 4.2.2.2;
}

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,6 @@
interface=wlan0
driver=rtl871xdrv
hw_mode=g
wme_enabled=1
ieee80211n=1
ignore_broadcast_ssid=0

Wyświetl plik

@ -1,8 +1,5 @@
interface=wlan0
driver=rtl871xdrv
ssid=stratux
hw_mode=g
channel=1
wme_enabled=1
wmm_enabled=1
ieee80211n=1
ignore_broadcast_ssid=0

Wyświetl plik

@ -0,0 +1,319 @@
#!/bin/bash
######################################################################
# STRATUX HOSTAPD MANAGER #
######################################################################
#Logging Function
SCRIPT=`basename ${BASH_SOURCE[0]}`
STX_LOG="/var/log/stratux.log"
function wLog () {
echo "$(date +"%Y/%m/%d %H:%m:%S") - $SCRIPT - $1" >> $STX_LOG
}
wLog "Running Hostapd Manager Script."
# files to edit
HOSTAPD=('/etc/hostapd/hostapd.user')
# values to be added to hostapd.user for security.
HOSTAPD_SECURE_VALUES_DELETE=('auth_algs=1' 'wpa=3' 'wpa_passphrase=' 'wpa_key_mgmt=WPA-PSK' 'wpa_pairwise=TKIP' 'rsn_pairwise=CCMP')
# 'wpa_passphrase=' was left out of this to set it with the $wifiPass. I assume you can not evaluate a variable from within an array variable
HOSTAPD_SECURE_VALUES_WRITE=('auth_algs=1' 'wpa=3' 'wpa_key_mgmt=WPA-PSK' 'wpa_pairwise=TKIP' 'rsn_pairwise=CCMP')
#Initialize variables to default values.
OPT_S=false
OPT_C=false
OPT_E=false
OPT_O=false
OPT_P=false
wifiPass="SquawkDirtyToMe!"
parm="*"
err="####"
att="+++"
#Set fonts for Help.
BOLD=$(tput bold)
STOT=$(tput smso)
UNDR=$(tput smul)
REV=$(tput rev)
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
MAGENTA=$(tput setaf 5)
WHITE=$(tput setaf 7)
NORM=$(tput sgr0)
NORMAL=$(tput sgr0)
#Help function
function HELP {
echo -e \\n"Help documentation for ${BOLD}${SCRIPT}.${NORM}"\\n
echo -e "${REV}Basic usage:${NORM} ${BOLD}$SCRIPT -s ssid -c chan -p pass ${NORM}"\\n
echo "The following command line switches are recognized."
echo "${REV}-s${NORM} --Sets the SSID to ${BOLD}ssid${NORM}. \"-s stratux\""
echo "${REV}-c${NORM} --Sets the channel to ${BOLD}chan${NORM}. \"-c 1\""
echo "${REV}-o${NORM} --Turns off encryption and sets network to open. Cannot be used with -e or -p."
echo "${REV}-e${NORM} --Turns on encryption with passphrase ${BOLD}$wifiPass${NORM}. Cannot be used with -o or -p"
echo "${REV}-p${NORM} --Turns on encryption with your chosen passphrase ${BOLD}pass${NORM}. 8-63 Printable Characters(ascii 32-126). Cannot be used with -o or -e. \"-p password!\""
echo -e "${REV}-h${NORM} --Displays this help message. No further functions are performed."\\n
echo -e "Example: ${BOLD}$SCRIPT -s Stratux-N3558D -c 5 -p SquawkDirty!${NORM}"\\n
exit 1
}
function confirm() {
# call with a prompt string or use a default
read -r -p "$1 " response
case "$response" in
[yY][eE][sS]|[yY])
true
;;
*)
exit 1
;;
esac
}
function cleanhostapd () {
wLog "Cleaning hostapd config at $1"
for j in "${HOSTAPD_SECURE_VALUES_DELETE[@]}"
do
sed -i "/$j/ d" ${1}
done
sed -i '/^\s*$/d' ${1}
}
function writehostapd () {
wLog "Writing hostapd config at $1"
sed -i '/^\s*$/d' ${1}
echo "" >> ${1}
for j in "${HOSTAPD_SECURE_VALUES_WRITE[@]}"
do
echo "${j}" >> ${1}
done
echo "wpa_passphrase=$wifiPass" >> ${1}
}
#apply settings and restart all processes
function APPLYSETTINGS {
wLog "Restarting all wifi settings."
echo "${RED}${BOLD} $att At this time the script will restart your WiFi services.${WHITE}${NORMAL}"
echo "If you are connected to Stratux through the ${BOLD}192.168.10.1${NORMAL} interface then you will be disconnected"
echo "Please wait up to 1 min and look for the new SSID on your wireless device."
sleep 3
echo "${YELLOW}$att Restarting Stratux WiFi Services... $att ${WHITE}"
echo "${YELLOW}$att SSH will now disconnect if connected to http://192.168.10.1 ... $att ${WHITE}"
echo "ifdown wlan0..."
ifdown wlan0
sleep 0.5
echo "ifup wlan0..."
echo "Calling Stratux WiFI Start Script(stratux-wifi.sh) via ifup wlan0..."
ifup wlan0
sleep 0.5
echo ""
echo ""
echo "All systems should be up and running and you should see your new SSID!"
}
clear
echo ""
echo "#### Stratux HOSTAPD Settings ####"
echo ""
if [ $(whoami) != 'root' ]; then
echo "${BOLD}${RED}This script must be executed as root, exiting...${WHITE}${NORMAL}"
echo "${BOLD}${RED}USAGE${WHITE}${NORMAL}"
exit 1
fi
#Check the number of arguments. If none are passed, print help and exit.
NUMARGS=$#
if [ $NUMARGS -eq 0 ]; then
HELP
fi
### Start getopts code ###
#Parse command line flags
#If an option should be followed by an argument, it should be followed by a ":".
#Notice there is no ":" after "eoqh". The leading ":" suppresses error messages from
#getopts. This is required to get my unrecognized option code to work.
options=':s:c:p:eoh'
#options=':s:c:h'
while getopts $options option; do
case $option in
s) #set option "s"
if [[ -z "${OPTARG}" || "${OPTARG}" == *[[:space:]]* || "${OPTARG}" == -* ]]; then
echo "${BOLD}${RED}$err No SSID for -s, exiting...${WHITE}${NORMAL}"
wLog "No SSID for -s, exiting..."
exit 1
else
OPT_S=$OPTARG
echo "$parm SSID Option -s used: $OPT_S"
echo "${GREEN} SSID will now be ${BOLD}${UNDR}$OPT_S${NORMAL}.${WHITE}"
fi
;;
c) #set option "c"
if [[ -z "${OPTARG}" || "${OPTARG}" == *[[:space:]]* || "${OPTARG}" == -* ]]; then
echo "${BOLD}${RED}$err Channel option(-c) used without value, exiting... ${WHITE}${NORMAL}"
wLog "Channel option(-c) used without value, exiting..."
exit 1
else
OPT_C=$OPTARG
echo "$parm Channel option -c used: $OPT_C"
if [[ "$OPT_C" =~ ^[0-9]+$ ]] && [ "$OPT_C" -ge 1 -a "$OPT_C" -le 13 ]; then
echo "${GREEN} Channel will now be set to ${BOLD}${UNDR}$OPT_C${WHITE}${NORMAL}."
else
echo "${BOLD}${RED}$err Channel is not within acceptable values, exiting...${WHITE}${NORMAL}"
wLog "Channel is not within acceptable values, exiting..."
exit 1
fi
fi
;;
e) #set option "e" with default passphrase
if [[ -z "${OPTARG}" || "${OPTARG}" == *[[:space:]]* || "${OPTARG}" == -* ]]; then
echo "$parm Encrypted WiFI Option -e used."
OPT_E=$wifiPass
echo "${GREEN} WiFi will be encrypted using ${BOLD}${UNDR}$OPT_E${NORMAL}${GREEN} as the passphrase!${WHITE}${NORMAL}"
else
echo "${BOLD}${RED}$err Option -e does not require argument. exiting...${WHITE}${NORMAL}"
wLog "Option -e does not require argument."
exit 1
fi
;;
p) #set encryption with user specified passphrase
if [[ -z "${OPTARG}" || "${OPTARG}" =~ ^[[:space:]]*$ || "${OPTARG}" == -* ]]; then
echo "${BOLD}${RED}$err Encryption option(-p) used without passphrase!${WHITE}${NORMAL}"
echo "${BOLD}${RED}$err Encryption option(-p) required an argument \"-p passphrase\". exiting...${WHITE}${NORMAL}"
wLog "Encryption option(-p) used without passphrase!"
else
OPT_P=$OPTARG
wifiPass=$OPTARG
fi
echo "$parm Encryption option -p used:"
if [ -z `echo $OPT_P | tr -d "[:print:]"` ] && [ ${#OPT_P} -ge 8 ] && [ ${#OPT_P} -le 63 ]; then
echo "${GREEN} WiFi will be encrypted using ${BOLD}${UNDR}$OPT_P${NORMAL}${GREEN} as the passphrase!${WHITE}${NORMAL}"
else
echo "${BOLD}${RED}$err Invalid PASSWORD: 8 - 63 printable characters, exiting...${WHITE}${NORMAL}"
wLog "Invalid PASSWORD: 8 - 63 printable characters, exiting..."
exit 1
fi
;;
o) #set option "o"
if [[ -z "${OPTARG}" || "${OPTARG}" == *[[:space:]]* || "${OPTARG}" == -* ]]; then
echo "$parm Open WiFI Option -o used."
echo "${GREEN} WiFi will be set to ${BOLD}${UNDR}OPEN${NORMAL}${GREEN} or ${BOLD}${UNDR}UNSECURE${WHITE}${NORMAL}"
OPT_O=true
else
echo "${BOLD}${RED}$err Option -o does not require argument. exiting...${WHITE}${NORMAL}"
wLog "Option -o does not require argument. exiting..."
exit 1
fi
;;
h) #show help
HELP
;;
\?) # invalid option
echo "${BOLD}${RED}$err Invalid option -$OPTARG ${WHITE}${NORMAL}" >&2
HELP
exit 1
;;
:) # Missing Arg
echo "${BOLD}${RED}$err Missing option for argument -$OPTARG ${WHITE}${NORMAL}" >&2
HELP
exit 1
;;
*) # Invalid
echo "${BOLD}${RED}$err Unimplemented option -$OPTARG ${WHITE}${NORMAL}" >&2
HELP
exit 1
;;
esac
done
shift $((OPTIND-1)) #This tells getopts to move on to the next argument.
### End getopts code ###
### Main loop to process files ###
#This is where your main file processing will take place. This example is just
#printing the files and extensions to the terminal. You should place any other
#file processing tasks within the while-do loop.
if [[ $OPT_O == true && ( $OPT_E != false || $OPT_P != false ) ]]; then
echo "${BOLD}${RED}$err Option -e , -p and -o cannot be used simultaneously. Exiting... ${WHITE}${NORMAL}"
wLog "Option -e , -p and -o cannot be used simultaneously."
exit 1
fi
if [ $OPT_P != false ] && [ $OPT_E != false ]; then
echo "${BOLD}${RED}$err Option -e and -p cannot be used simultaneously. Exiting... ${WHITE}${NORMAL}"
wLog "Option -e and -p cannot be used simultaneously."
exit 1
fi
echo ""
echo "${BOLD}No errors found. Continuing...${NORMAL}"
echo ""
confirm "Are you ready to apply these settings? [y/n]"
####
#### File modification loop
####
for i in "${HOSTAPD[@]}"
do
if [ -f ${i} ]; then
echo "Working on $i..."
wLog "Working on $i..."
if [ $OPT_S != false ]; then
wLog "Writing SSID $OPT_S to file $i"
echo "${MAGENTA}Setting ${YELLOW}SSID${MAGENTA} to ${YELLOW}$OPT_S ${MAGENTA}in $i...${WHITE}"
if grep -q "^ssid=" ${HOSTAPD[$x]}; then
sed -i "s/^ssid=.*/ssid=${OPT_S}/" ${i}
else
echo ${OPT_S} >> ${i}
fi
fi
if [ $OPT_C != false ]; then
wLog "Writing channel $OPT_C to file $i"
echo "${MAGENTA}Setting ${YELLOW}Channel${MAGENTA} to ${YELLOW}$OPT_C ${MAGENTA}in $i...${WHITE}"
if grep -q "^channel=" ${i}; then
sed -i "s/^channel=.*/channel=${OPT_C}/" ${i}
else
echo ${OPT_C} >> ${i}
fi
fi
if [ $OPT_E != false ] || [ $OPT_P != false ]; then
wLog "Writing security and setting passphrase to $wifiPass to file $i"
echo "${MAGENTA}Adding WPA encryption with passphrase: ${YELLOW}$wifiPass ${MAGENTA}to $i...${WHITE}"
cleanhostapd $i
writehostapd $i
fi
if [ $OPT_O != false ]; then
wLog "Removing WiFi security in file $i"
echo "${MAGENTA}Removing WPA encryption in $i...${WHITE}"
cleanhostapd $i
fi
echo "${GREEN}Modified ${i}...done${WHITE}"
echo ""
else
echo "${MAGENTA}No ${i} file found...${WHITE}${NORMAL}"
echo ""
fi
done
### End main loop ###
### Apply Settings and restart all services
APPLYSETTINGS
exit 0

Wyświetl plik

@ -1,14 +1,59 @@
auto lo
iface lo inet loopback
allow-hotplug eth0
iface eth0 inet dhcp
allow-hotplug wlan0
#iface wlan0 inet manual
#wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
#iface default inet dhcp
iface wlan0 inet static
address 192.168.10.1
netmask 255.255.255.0
post-up /usr/sbin/stratux-wifi.sh
wireless-power off
#####################################################################
## Custom settings not for novice users!!!!!!
## Modify at your own risk!!!!!!!!!!!!!!!!!!!
##
## Second Wifi Dongle for local work and internet access
## This template is for adding a second wifi dongle to your PI for internet access while debugging
## Modify /etc/wpa_supplicant/wpa_supplicant.conf with your settings also( see below )
##
## Uncomment the following lines as needed.
# allow-hotplug wlan1
# iface wlan1 inet manual
# wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
# iface name_of_WPA_Config inet dhcp
# iface name_of_other_WPA_Config inet dhcp
## End of interfaces
#contents of wpa_supplicant.conf
#############################################################
# ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
# update_config=1
# network={
# ssid="SSID_1"
# id_str="name_of_WPA_Config"
# scan_ssid=1
# key_mgmt=WPA-PSK
# psk="mypassword"
# priority=1
# }
# network={
# ssid="SSID_2"
# id_str="name_of_other_WPA_Config"
# scan_ssid=1
# key_mgmt=WPA-PSK
# psk="mypassword"
# priority=3
# }
#############################################################

Wyświetl plik

@ -0,0 +1,32 @@
# see "man logrotate" for details
# rotate log files weekly
daily
# keep 2 days worth of backlogs
rotate 2
# create new (empty) log files after rotating old ones
create
# uncomment this if you want your log files compressed
compress
# packages drop log rotation information into this directory
include /etc/logrotate.d
# no packages own wtmp, or btmp -- we'll rotate them here
/var/log/wtmp {
missingok
monthly
create 0664 root utmp
rotate 1
}
/var/log/btmp {
missingok
monthly
create 0660 root utmp
rotate 1
}
# system-specific logs may be configured here

Wyświetl plik

@ -0,0 +1,12 @@
# Keep 10 days of stratux logfiles.
/var/log/stratux.log
{
rotate 10
daily
missingok
notifempty
compress
postrotate
/usr/bin/killall -HUP gen_gdl90
endscript
}

172
image/mkimg.sh 100755
Wyświetl plik

@ -0,0 +1,172 @@
#!/bin/bash
#kpartx -a asdfsadf.img
##dd if=/dev/zero bs=1M count=200 >>2016-02-26-raspbian-jessie-lite.img
#mount root partition
##mount -o loop,offset=67108864 2016-02-26-raspbian-jessie-lite.img mnt/
##resize2fs /dev/loop0
#mount boot partition
##mount -o loop,offset=4194304 2016-02-26-raspbian-jessie-lite.img mnt/boot/
chroot mnt/ apt-get update
#update firmware
chroot mnt/ apt-get -y install rpi-update
chroot mnt/ rpi-update
#wifi
chroot mnt/ apt-get install -y hostapd isc-dhcp-server
#troubleshooting
chroot mnt/ apt-get install -y tcpdump
#wifi startup
chroot mnt/ systemctl enable isc-dhcp-server
#ssh startup
chroot mnt/ systemctl enable ssh
#disable ntpd autostart
chroot mnt/ systemctl disable ntp
#root key
mkdir -p mnt/etc/ssh/authorized_keys
cp -f root mnt/etc/ssh/authorized_keys/root
chown root.root mnt/etc/ssh/authorized_keys/root
chmod 644 mnt/etc/ssh/authorized_keys/root
#motd
cp -f motd mnt/etc/motd
#dhcpd config
cp -f dhcpd.conf mnt/etc/dhcp/dhcpd.conf
#hostapd config
cp -f hostapd.conf mnt/etc/hostapd/hostapd.conf
cp -f hostapd-edimax.conf mnt/etc/hostapd/hostapd-edimax.conf
#hostapd manager script
cp -f hostapd_manager.sh mnt/usr/sbin/hostapd_manager.sh
chmod 755 mnt/usr/sbin/hostapd_manager.sh
#hostapd
cp -f hostapd-edimax mnt/usr/sbin/hostapd-edimax
chmod 755 mnt/usr/sbin/hostapd-edimax
#remove hostapd startup scripts
rm -f mnt/etc/rc*.d/*hostapd mnt/etc/network/if-pre-up.d/hostapd mnt/etc/network/if-post-down.d/hostapd mnt/etc/init.d/hostapd mnt/etc/default/hostapd
#interface config
cp -f interfaces mnt/etc/network/interfaces
#custom hostapd start script
cp stratux-wifi.sh mnt/usr/sbin/
chmod 755 mnt/usr/sbin/stratux-wifi.sh
#SDR Serial Script
cp -f sdr-tool.sh mnt/usr/sbin/sdr-tool.sh
chmod 755 mnt/usr/sbin/sdr-tool.sh
#ping udev
cp -f 99-uavionix.rules mnt/etc/udev/rules.d
#logrotate conf
cp -f logrotate.conf mnt/etc/logrotate.conf
#fan/temp control script
#remove old script
rm -rf mnt/usr/bin/fancontrol.py
#install new program
cp ../fancontrol mnt/usr/bin
chmod 755 mnt/usr/bin/fancontrol
chroot mnt/ /usr/bin/fancontrol remove
chroot mnt/ /usr/bin/fancontrol install
#isc-dhcp-server config
cp -f isc-dhcp-server mnt/etc/default/isc-dhcp-server
#sshd config
cp -f sshd_config mnt/etc/ssh/sshd_config
#udev config
cp -f 10-stratux.rules mnt/etc/udev/rules.d
#stratux files
cp -f ../libdump978.so mnt/usr/lib/libdump978.so
#go1.5.1 setup
cp -rf /root/go mnt/root/
cp -f bashrc.txt mnt/root/.bashrc
#debug aliases
cp -f stxAliases.txt mnt/root/.stxAliases
#rtl-sdr setup
cp -f rtl-sdr-blacklist.conf mnt/etc/modprobe.d/
chroot mnt/ apt-get install -y git cmake libusb-1.0-0.dev build-essential
rm -rf mnt/root/librtlsdr
git clone https://github.com/jpoirier/librtlsdr mnt/root/librtlsdr
mkdir -p mnt/root/librtlsdr/build
#FIXME
chroot mnt/ 'cd /root/librtlsdr/build && cmake ../ && make && make install && ldconfig'
#stratux setup
cd /root
apt-get install -y mercurial
apt-get install -y build-essential
rm -rf stratux
git clone https://github.com/cyoung/stratux --recursive
cd stratux
make
make install
#system tweaks
cp -f modules.txt mnt/etc/modules
#kalibrate-rtl
cd /root
rm -rf kalibrate-rtl
git clone https://github.com/steve-m/kalibrate-rtl
cd kalibrate-rtl
apt-get install -y autoconf fftw3 fftw3-dev libtool
./bootstrap
./configure
make
make install
#disable serial console
sed -i mnt/boot/cmdline.txt -e "s/console=ttyAMA0,[0-9]\+ //"
#Set the keyboard layout to US.
sed -i mnt/etc/default/keyboard -e "/^XKBLAYOUT/s/\".*\"/\"us\"/"
#boot settings
cp -f config.txt mnt/boot/
#external OLED screen
apt-get install -y libjpeg-dev i2c-tools python-smbus python-pip python-dev python-pil python-daemon screen
#for fancontrol.py:
pip install wiringpi
cd /root
git clone https://github.com/rm-hull/ssd1306
cd ssd1306
# Force an older version of ssd1306, since recent changes have caused a lot of compatibility issues.
git reset --hard 232fc801b0b8bd551290e26a13122c42d628fd39
python setup.py install
cp /root/stratux/test/screen/screen.py /usr/bin/stratux-screen.py
mkdir -p /etc/stratux-screen/
cp -f /root/stratux/test/screen/stratux-logo-64x64.bmp /etc/stratux-screen/stratux-logo-64x64.bmp
cp -f /root/stratux/test/screen/CnC_Red_Alert.ttf /etc/stratux-screen/CnC_Red_Alert.ttf
#startup scripts
cp -f ../__lib__systemd__system__stratux.service mnt/lib/systemd/system/stratux.service
cp -f ../__root__stratux-pre-start.sh mnt/root/stratux-pre-start.sh
cp -f rc.local mnt/etc/rc.local
#dhcpcd causes first boot hanging.
chroot mnt/ systemctl disable dhcpcd
#disable hciuart - interferes with ttyAMA0 as a serial port.
chroot mnt/ systemctl disable hciuart
#clean up for release images.
rm -rf mnt/root/stratux mnt/root/go

Wyświetl plik

@ -0,0 +1,7 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
i2c-bcm2708
i2c-dev

20
image/motd 100644
Wyświetl plik

@ -0,0 +1,20 @@
ad88888ba 888888888888 88888888ba db 888888888888 88 88 8b d8
d8" "8b 88 88 "8b d88b 88 88 88 Y8, ,8P
Y8, 88 88 ,8P d8'`8b 88 88 88 `8b d8'
`Y8aaaaa, 88 88aaaaaa8P' d8' `8b 88 88 88 Y88P
`"""""8b, 88 88""""88' d8YaaaaY8b 88 88 88 d88b
`8b 88 88 `8b d8""""""""8b 88 88 88 ,8P Y8,
Y8a a8P 88 88 `8b d8' `8b 88 Y8a. .a8P d8' `8b
"Y88888P" 88 88 `8b d8' `8b 88 `"Y8888Y"' 8P Y8
NOTE TO DEVELOPERS: Make sure that your system has an acceptable clock source, i.e., a GPS
with sufficient signal or enable ntpd (internet connection required).
Everything here comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Type 'stratux-help' (as root) for a few debugging commands.

29
image/rc.local 100755
Wyświetl plik

@ -0,0 +1,29 @@
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
#
# Rotate logs on boot.
#
/usr/sbin/logrotate /etc/logrotate.conf
/usr/bin/stratux-screen.py start
exit 0

Wyświetl plik

@ -0,0 +1,2 @@
# Ignore gen_gdl90. stratux.log is written directly from the process.
if $programname == 'gen_gdl90' then ~

Wyświetl plik

@ -0,0 +1,4 @@
blacklist dvb_usb_rtl28xxu
blacklist e4000
blacklist rtl2832
blacklist dvb_usb_rtl2832u

317
image/sdr-tool.sh 100644
Wyświetl plik

@ -0,0 +1,317 @@
#!/bin/bash
######################################################################
# STRATUX SDR MANAGER #
######################################################################
#Set Script Name variable
SCRIPT=`basename ${BASH_SOURCE[0]}`
# rtl_eeprom -d 0 -s <String>:<Freq>:<PPM>
#Initialize variables to default values.
SERVICE=stratux.service
WhichSDR=1090
FallBack=true
PPMValue=0
parm="*"
err="####"
att="+++"
#Set fonts for Help.
BOLD=$(tput bold)
STOT=$(tput smso)
DIM=$(tput dim)
UNDR=$(tput smul)
REV=$(tput rev)
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
MAGENTA=$(tput setaf 5)
WHITE=$(tput setaf 7)
NORM=$(tput sgr0)
NORMAL=$(tput sgr0)
#This is the Title
function HEAD {
clear
echo "######################################################################"
echo "# STRATUX SDR SERIAL TOOL #"
echo "######################################################################"
echo " "
}
function STOPSTRATUX {
HEAD
echo "Give me a few seconds to check if STRATUX is running..."
# The service we want to check (according to systemctl)
if [ "`systemctl is-active $SERVICE`" = "active" ]
then
echo "$SERVICE is currently running"
echo "Stopping..."
SDRs=`systemctl stop stratux.service`
fi
sleep 3
}
function STARTSTRATUX {
HEAD
echo "Give me a few seconds to get STRATUX running again..."
SDRs=`systemctl start stratux.service`
sleep 3
if [ "`systemctl is-active $SERVICE`" = "active" ]
then
echo "$SERVICE is now running"
else
echo "$SERVICE did not restart. Try 'reboot' to restart your RaspberryPI"
fi
}
#Function to set the serial function
function SETSDRSERIAL {
HEAD
echo "# Setting ${WhichSDR}mhz SDR Serial Data #"
#Build this string
# rtl_eeprom -d 0 -s <String>:<Freq>:<PPM>
echo " SETTING SERIAL: "
echo " rtl_eeprom -d 0 -s stx:${WhichSDR}:${PPMValue} "
echo " "
echo "${REV}Answer 'y' to the qustion: 'Write new configuration to device [y/n]?'${NORM}"
echo " "
SDRs=`rtl_eeprom -d 0 -s stx:${WhichSDR}:${PPMValue}`
sleep 2
echo " "
echo "Do you have another SDR to program?"
echo " 'Yes' will shutdown your STRATUX and allow you to swap SDRs."
echo " 'No' will reboot your STRATUX and return your STRATUX to normal operation."
echo " 'exit' will exit the script and return you to your shell prompt"
choices=( 'Yes' 'No' 'exit' )
# Present the choices.
# The user chooses by entering the *number* before the desired choice.
select choice in "${choices[@]}"; do
# If an invalid number was chosen, $choice will be empty.
# Report an error and prompt again.
[[ -n $choice ]] || { echo "Invalid choice." >&2; continue; }
case $choice in
'Yes')
echo "Shutting down..."
SDRs=`shutdown -h now`
;;
'No')
echo "Rebooting..."
SDRs=`reboot`
;;
exit)
STARTSTRATUX
echo "Exiting. "
exit 0
esac
break
done
}
function SDRInfo {
HEAD
echo "# Building ${WhichSDR}mhz SDR Serial #"
echo " "
echo "Do you have a PPM value to enter?"
echo "If not, its ok... Just choose 'No'"
choices=( 'Yes' 'No' 'exit' )
# Present the choices.
# The user chooses by entering the *number* before the desired choice.
select choice in "${choices[@]}"; do
# If an invalid number was chosen, $choice will be empty.
# Report an error and prompt again.
[[ -n $choice ]] || { echo "Invalid choice." >&2; continue; }
case $choice in
'Yes')
echo "Please enter your PPM value for your 978mhz SDR:"
read PPMValue
;;
'No')
echo " "
;;
exit)
STARTSTRATUX
echo "Exiting. "
exit 0
esac
break
done
SETSDRSERIAL
}
function PICKFALLBACK {
HEAD
echo "# Gathering ${WhichSDR}mhz SDR Serial #"
echo " "
echo "${RED}${BOLD}IMPORTANT INFORMATION: READ CAREFULLY${NORM}"
echo "${BOLD}DO you want to set the 1090mhz SDR to Fall Back to 978mhz in the event of the 978mhx SDR failing inflight?${NORM}"
echo "If no serials are set on any of the attached SDRs then STRATUX will assign 978mhz to the first SDR found and 1090mhz to the remaining SDR. This is a safety featre of STRATUX to always allow users to always have access to WEATHER and METAR data in the event of one SDR failing in flight. "
echo " "
echo "When a user assigns a frequency to an SDR, via setting serials, STRATUX will always assign that frequency. NO MATTER WHAT."
echo "This could cause issues if an SDR fails in flight. If the 978mhz SDR fails in flight and the other SDR is assigned the 1090 serial this SDR will never be set to 978mhz and the user will not have access to WEATHER and METAR data"
echo " "
echo "Choosing the Fall Back mode will allow the remaining SDR to be assigned to 978mhz while keeping the PPM value, allowing the user to continue to receive WEATHER and METAR data."
echo "Fall Back mode is reccomended!"
choices=( 'FallBack' '1090mhz' 'exit' )
# Present the choices.
# The user chooses by entering the *number* before the desired choice.
select choice in "${choices[@]}"; do
# If an invalid number was chosen, $choice will be empty.
# Report an error and prompt again.
[[ -n $choice ]] || { echo "Invalid choice." >&2; continue; }
case $choice in
'FallBack')
WhichSDR=0
;;
'1090mhz')
echo " "
;;
exit)
STARTSTRATUX
echo "Exiting. "
exit 0
esac
break
done
}
function PICKFREQ {
HEAD
echo "# Selecting Radio to set Serial #"
echo " "
echo "${BOLD}Which SDR are you setting up?${NORM}"
echo "${DIM}If you have tuned antennas make sure you have the correct SDR and antenna combination hooked up at this time and remember which antenna connection is for which antenna.${NORM}"
choices=( '978mhz' '1090mhz' 'exit' )
# Present the choices.
# The user chooses by entering the *number* before the desired choice.
select choice in "${choices[@]}"; do
# If an invalid number was chosen, $choice will be empty.
# Report an error and prompt again.
[[ -n $choice ]] || { echo "Invalid choice." >&2; continue; }
case $choice in
'978mhz')
WhichSDR=978
SDRInfo
;;
'1090mhz')
PICKFALLBACK
SDRInfo
;;
exit)
STARTSTRATUX
echo "Exiting. "
exit 0
esac
break
done
}
function MAINMENU {
HEAD
echo "Loading SDR info..."
sleep 2
HEAD
echo "# CONFIRM ONLY ONE SDR INSTALLED #"
echo "----------------------------------------------------------------------"
SDRs=`rtl_eeprom`
echo "----------------------------------------------------------------------"
echo " "
echo "${BOLD}${RED}Read the lines above.${NORM}"
echo "${BOLD}How many SDRs were found?${NORM}"
# Define the choices to present to the user, which will be
# presented line by line, prefixed by a sequential number
# (E.g., '1) copy', ...)
choices=( 'Only 1' '2 or more' 'exit' )
# Present the choices.
# The user chooses by entering the *number* before the desired choice.
select choice in "${choices[@]}"; do
# If an invalid number was chosen, $choice will be empty.
# Report an error and prompt again.
[[ -n $choice ]] || { echo "Invalid choice." >&2; continue; }
case $choice in
'Only 1')
PICKFREQ
;;
'2 or more')
echo "#####################################################################################"
echo "# ${RED}Too Many SDRs Plugged in. Unplug all SDRs except one and try again!!${NORM} #"
echo "#####################################################################################"
STARTSTRATUX
echo "Exiting. "
exit 0
;;
exit)
STARTSTRATUX
echo "Exiting... "
exit 0
esac
# Getting here means that a valid choice was made,
# so break out of the select statement and continue below,
# if desired.
# Note that without an explicit break (or exit) statement,
# bash will continue to prompt.
break
done
}
function START {
echo "Help documentation for ${BOLD}${SCRIPT}.${NORM}"
echo " "
echo "This script will help you in setting your SDR serials. Please read carefully before continuing. There are many options in settings the SDR serials. Programming the SDR serials does 2 things. "
echo " "
echo "${BOLD}First:${NORM}"
echo "Setting the serials will tell your STRATUX which SDR is attached to which tuned antenna."
echo " "
echo "${BOLD}Second:${NORM}"
echo "Setting the PPM value will enhance the reception of your SDR by correcting the Frequency Error in each SDR. Each PPM value is unique to each SDR. For more info on this please refer to the Settings page in the WebUI and click on the Help in the top right."
echo " "
echo "Steps we will take:"
echo "1) Make sure you have ${BOLD}${REV}ONLY ONE${NORM} SDR plugged in at a time. Plugging in one SDR at a time will ensure they are not mixed up."
echo "2) Select which SDR we are setting the serial for."
echo "3) Add a PPM value. If you do not know or do not want to set this value this will be set to 0. "
echo "4) Write the serial to the SDR."
echo " "
echo "If you are ready to begin choose ${BOLD}Continue${NORM} to begin."
echo " Continuing will stop the STRATUX service to release the SDRs for setting the serials"
choices=( 'Continue' 'Exit' )
# Present the choices.
# The user chooses by entering the *number* before the desired choice.
select choice in "${choices[@]}"; do
# If an invalid number was chosen, $choice will be empty.
# Report an error and prompt again.
[[ -n $choice ]] || { echo "Invalid choice." >&2; continue; }
case $choice in
'Continue')
STOPSTRATUX
MAINMENU
;;
exit)
STARTSTRATUX
echo "Exiting. "
exit 0
esac
break
done
}
HEAD
START

Wyświetl plik

@ -10,7 +10,7 @@ set -e
run_qemu() {
rm fifo.out fifo.in || true
mkfifo fifo.out fifo.in
qemu-system-arm -M versatilepb -cpu arm1136-r2 -m 256 -nographic -no-reboot \
qemu-system-arm -M versatilepb -cpu arm1136-r2 -m 256 -display none -no-reboot \
-kernel zImage -hda qemu_rootfs.sqf -drive file=$1,index=1,media=disk,cache=unsafe \
-drive file=wheezy_apt_cache.$IMGFORMAT,index=2,media=disk,cache=unsafe \
-append "root=/dev/sda rw init=/sbin/init.sh panic=1 PATH=/bin:/sbin console=ttyAMA0 HOST=armv6l"\

Wyświetl plik

@ -20,6 +20,13 @@ setup_stratux_bootconfig() {
echo "max_usb_current=1" >>boot/config.txt
#i2c
echo "dtparam=i2c1=on" >>boot/config.txt
echo "dtparam=i2c1_baudrate=400000" >>boot/config.txt
echo "dtparam=i2c_arm_baudrate=400000" >>boot/config.txt
#fixed arm/sdram/core freq.
echo "arm_freq=900" >>boot/config.txt
echo "sdram_freq=450" >>boot/config.txt
echo "core_freq=450" >>boot/config.txt
#disable serial console
sed -i boot/cmdline.txt -e "s/console=ttyAMA0,[0-9]\+ //"
}
@ -30,8 +37,7 @@ setup_stratux() {
echo "**** STRATUX SETUP *****"
ssh_in_to_qemu chroot /mnt sh -l -ex - <<\EOF
#general
apt-get install -y screen
#wifi
apt-get install -y hostapd isc-dhcp-server
#troubleshooting
@ -39,6 +45,8 @@ apt-get install -y tcpdump
#wifi startup
update-rc.d hostapd enable
update-rc.d isc-dhcp-server enable
#disable ntpd autostart
update-rc.d ntp disable
EOF
scp_in_to_qemu /root/spindle/hostapd-edimax /tmp/hostapd.in
@ -49,9 +57,13 @@ scp_in_to_qemu /root/spindle/hostapd.conf /tmp/hostapd.conf.in
scp_in_to_qemu /root/spindle/isc-dhcp-server /tmp/isc-dhcp-server.in
scp_in_to_qemu /root/spindle/sshd_config /tmp/sshd_config.in
scp_in_to_qemu /root/spindle/libdump978.so /tmp/libdump978.so.in
scp_in_to_qemu /root/spindle/libimu.so /tmp/libimu.so.in
scp_in_to_qemu /root/spindle/go.tgz /mnt/root/go.tgz
ssh_in_to_qemu chroot /mnt sh -l -ex - <<\EOF
mv /tmp/libdump978.so.in /usr/lib/libdump978.so
mv /tmp/libimu.so.in /usr/lib/libimu.so
mv -f /tmp/hostapd.in /usr/sbin/hostapd
chown root.root /usr/sbin/hostapd
chmod 755 /usr/sbin/hostapd
@ -78,6 +90,20 @@ echo blacklist rtl2832 >>/etc/modprobe.d/rtl-sdr-blacklist.conf
echo "# prevent power down of wireless when idle" >>/etc/modprobe.d/8192cu.conf
echo "options 8192cu rtw_power_mgnt=0 rtw_enusbss=0" >>/etc/modprobe.d/8192cu.conf
#Set up Go1.5.1.
echo export PATH=/root/go/bin:\$\{PATH\} >>/root/.bashrc
echo export GOROOT=/root/go >>/root/.bashrc
echo export GOPATH=/root/go_path >>/root/.bashrc
cd /root
tar -zxvf go.tgz
rm -f go.tgz
#ifndef DEBUG
#rm -rf go
#endif
EOF
echo "*** STRATUX COMPILE/PACKAGE INSTALL ***"
@ -88,9 +114,9 @@ apt-get install -y git cmake libusb-1.0-0.dev build-essential
cd /root
rm -rf rtl-sdr
git clone git://git.osmocom.org/rtl-sdr.git
cd rtl-sdr
rm -rf librtlsdr
git clone https://github.com/jpoirier/librtlsdr
cd librtlsdr
mkdir build
cd build
cmake ../
@ -99,58 +125,64 @@ make install
ldconfig
EOF
echo " - dump1090"
ssh_in_to_qemu chroot /mnt sh -l -ex - <<\EOF
cd /root
rm -rf dump1090
git clone https://github.com/antirez/dump1090
cd dump1090
make
cp dump1090 /usr/bin/
EOF
echo " - Stratux"
scp_in_to_qemu /root/spindle/gen_gdl90 /tmp/gen_gdl90
ssh_in_to_qemu chroot /mnt sh -l -ex - <<\EOF
ssh_in_to_qemu chroot /mnt bash -l -ex - <<\EOF
source /root/.bashrc
cd /root
apt-get install -y mercurial
rm -rf stratux
git clone https://github.com/cyoung/stratux
git clone https://github.com/cyoung/stratux --recursive
cd stratux
mkdir -p /var/www
cp -r web/* /var/www/
cd dump978
make
cp dump978 /usr/bin/
cd ..
make www
make xdump978
make xdump1090
cp -f dump1090/dump1090 /usr/bin/
mv /tmp/gen_gdl90 /usr/bin/gen_gdl90
chmod +x /usr/bin/gen_gdl90
cp start_uat.sh /usr/bin/start_uat
#Startup script.
cp init.d-stratux /etc/init.d/stratux
cp start_stratux.sh /usr/sbin/stratux
chmod 755 /usr/bin/start_uat
chmod 755 /usr/sbin/stratux
chmod 755 /etc/init.d/stratux
ln -s /etc/init.d/stratux /etc/rc2.d/S01stratux
ln -s /etc/init.d/stratux /etc/rc6.d/K01stratux
update-rc.d stratux enable
mkdir -p /root/go_path
#FIXME
#export PATH=/root/go/bin:${PATH}
#export GOROOT=/root/go
#export GOPATH=/root/go_path
#make
EOF
ssh_in_to_qemu chroot /mnt sh -l -ex - <<\EOF
#i2c
echo "i2c-bcm2708" >>/etc/modules
echo "i2c-dev" >>/etc/modules
#sysctl tweaks
echo "net.core.rmem_max = 167772160" >>/etc/sysctl.conf
echo "net.core.rmem_default = 167772160" >>/etc/sysctl.conf
echo "net.core.wmem_max = 167772160" >>/etc/sysctl.conf
echo "net.core.wmem_default = 167772160" >>/etc/sysctl.conf
#kalibrate-rl
cd /root
git clone https://github.com/steve-m/kalibrate-rtl
cd kalibrate-rtl
apt-get install -y autoconf fftw3 fftw3-dev
apt-get install -y libtool
./bootstrap
./configure
@ -160,6 +192,13 @@ make install
#disable serial console
sed -i /etc/inittab -e "s|^.*:.*:respawn:.*ttyAMA0|#&|"
#Set the keyboard layout to US.
sed -i /etc/default/keyboard -e "/^XKBLAYOUT/s/\".*\"/\"us\"/"
EOF
echo "**** END STRATUX SETUP *****"

Wyświetl plik

@ -0,0 +1,106 @@
#!/bin/bash
#####
##### Wifi/AP control file
#####
##### Description: All the scripting related to the AP and wireless functions for Stratux should be placed in this file
##### This file is called when wlan0 is started i.e. "ifup wlan0"
##### This script is called from /etc/network/interfaces by the line "post-up /usr/sbin/stratux-wifi.sh" under the wlan0 configuration
#####
# common variables
DAEMON_USER_PREF=/etc/hostapd/hostapd.user
#Logging Function
SCRIPT=`basename ${BASH_SOURCE[0]}`
STX_LOG="/var/log/stratux.log"
function wLog () {
echo "$(date +"%Y/%m/%d %H:%m:%S") - $SCRIPT - $1" >> ${STX_LOG}
}
wLog "Running Stratux WiFI Script."
##### Function for setting up new file structure for hostapd settings
##### Look for hostapd.user and if found do nothing.
##### If not assume because of previous version and convert to new file structure
function hostapd-upgrade {
DAEMON_CONF=/etc/hostapd/hostapd.conf
DAEMON_CONF_EDIMAX=/etc/hostapd/hostapd-edimax.conf
HOSTAPD_VALUES=('ssid=' 'channel=' 'auth_algs=' 'wpa=' 'wpa_passphrase=' 'wpa_key_mgmt=' 'wpa_pairwise=' 'rsn_pairwise=')
wLog "Moving existing values from $DAEMON_CONF to $DAEMON_USER_PREF if found"
for i in "${HOSTAPD_VALUES[@]}"
do
if grep -q "^$i" $DAEMON_CONF
then
grep "^$i" $DAEMON_CONF >> $DAEMON_USER_PREF
sed -i '/^'"$i"'/d' $DAEMON_CONF
sed -i '/^'"$i"'/d' $DAEMON_CONF_EDIMAX
fi
done
sleep 1 #make sure there is time to get the file written before checking for it again
# If once the code above runs and there is still no hostapd.user file then something is wrong and we will just create the file with basic settings.
# Any more then this they somebody was messing with things and its not our fault things are this bad
wLog "Rechecking if $DAEMON_USER_PREF exists after moving files."
if [ ! -f $DAEMON_USER_PREF ]; then
wLog "File not found. Creating default file. "
echo "ssid=stratux" > $DAEMON_USER_PREF
echo "channel=1" >> $DAEMON_USER_PREF
fi
}
##### End hostapd settings structure function
##### Hostapd Driver check function #####
function ap-start {
# Preliminaries. Kill off old services.
wLog "Killing Hostapd services "
/usr/bin/killall -9 hostapd hostapd-edimax
wLog "Stopping DHCP services "
/usr/sbin/service isc-dhcp-server stop
#EDIMAX Mac Addresses from http://www.adminsub.net/mac-address-finder/edimax
#for logic check all addresses must be lowercase
# 74:da:38 is my MAC on my NANO
edimaxMac=(80:1f:02 74:da:38 00:50:fc 00:1f:1f 00:0e:2e 00:00:b4)
#Assume PI3 settings
DAEMON_CONF=/etc/hostapd/hostapd.conf
DAEMON_SBIN=/usr/sbin/hostapd
# Location of temporary hostapd.conf built by combining
# non-editable /etc/hostapd/hostapd.conf or hostapd-edimax.conf
# and the user configurable /etc/hostapd/hostapd.conf
DAEMON_TMP=/tmp/hostapd.conf
#get the first 3 octets of the MAC(XX:XX:XX) at wlan0
wlan0mac=$(head -c 8 /sys/class/net/wlan0/address)
# Is there an Edimax Mac Address at wlan0
if [[ ${edimaxMac[*]} =~ "$wlan0mac" ]]; then
DAEMON_CONF=/etc/hostapd/hostapd-edimax.conf
DAEMON_SBIN=/usr/sbin/hostapd-edimax
wLog "Edimax Dongle found at WLAN0. Using Edimad conf files $DAEMON_SBIN : $DAEMON_CONF"
fi
#Make a new hostapd or hostapd-edimax conf file based on logic above
cat ${DAEMON_USER_PREF} <(echo) ${DAEMON_CONF} > ${DAEMON_TMP}
${DAEMON_SBIN} -B ${DAEMON_TMP}
sleep 2
wLog "Restarting DHCP services"
/usr/sbin/service isc-dhcp-server start
}
##### End Hostapd driver check function #####
#Do we need to upgrade the hostapd configuration files
wLog "Checking if $DAEMON_USER_PREF file exists"
if [ ! -f $DAEMON_USER_PREF ]; then
wLog "File not found. Upgrading to new file structure."
hostapd-upgrade
fi
# function to build /tmp/hostapd.conf and start AP
ap-start

Wyświetl plik

@ -0,0 +1,71 @@
alias stratux-off='shutdown -P now'
alias eeprom='rtl_eeprom'
alias sa='service --status-all'
alias stxrestart='service stratux restart'
alias stxstop='service stratux stop'
alias stxstart='service stratux start'
alias sdr0='rtl_eeprom -d 0'
alias sdr1='rtl_eeprom -d 1'
alias sdrs='sdr0 || sdr1'
alias d90='dump1090'
alias d900='dump1090 --device-index 0 --interactive'
alias d901='dump1090 --device-index 1 --interactive'
alias kal0='kal -d 0 -s GSM850 -g 47'
alias kal1='kal -d 1 -s GSM850 -g 47'
alias kalChan0='function _kalChan0 () { kal -d 0 -g 47 -c $1; unset -f _kalChan0; }; _kalChan0'
alias kalChan1='function _kalChan1 () { kal -d 1 -g 47 -c $1; unset -f _kalChan1; }; _kalChan1'
alias setSerial0='function _setSerial0 () { rtl_eeprom -d 0 -s stx:0:$1; unset -f _setSerial0; }; _setSerial0'
alias setSerial1='function _setSerial1 () { rtl_eeprom -d 1 -s stx:0:$1; unset -f _setSerial1; }; _setSerial1'
alias secure='hostapd_manager.sh -e'
alias open='hostapd_manager.sh -o'
alias stratux-help='_stxhelp'
function _stxhelp() {
clear
echo ""
echo "########################################################"
echo ""
echo "These are commands avalible to you. Use at your own Risk"
echo ""
echo "########################################################"
echo ""
echo " Common tools "
echo "########################################################"
echo ""
echo "secure Turns on WiFi Security"
echo "open Turns off WiFi Security"
echo "stratux-off Shutdown Stratux"
echo "hostapd_manager.sh Sets the Change SSID, Channel, or Encryption for your Stratux"
echo "sdr-tool.sh Tool to walk you though setting your SDRs Serials"
echo ""
echo " Developer Tools "
echo "########################################################"
echo ""
echo "sa List all services running"
echo "stxrestart Restart Startux service only"
echo "stxstop Stop Stratux Service."
echo "stxstart Start Stratux Service."
echo "sdr0 Test to see if sdr0 is in use by Stratux."
echo "sdr1 Test to see if sdr1 is in use by Startux."
echo "sdrs Test to see if both SDRs are in use by Stratux."
echo "d90 Run dump1090 on SDR0"
echo "d900 Run dump1090 on SDR0 in interactive mode."
echo "d901 Run dump1090 on SDR1 in interactive mode."
echo "kal0 Find Channels for calibrating PPM of SDR0."
echo "kal1 Find Channels for calibrating PPM of SDR1."
echo "kalChan0 Use the Chan from above to get ppm pf SDR0. Example: kalChan0 151"
echo "kalChan1 Use the Chan from above to get ppm pf SDR1. Example: kalChan1 151"
echo "setSerial0 Set the PPM error to SDR0. Value from kalChan0. Example: setSerial0 -45"
echo "setSerial1 Set the PPM error to SDR1. Value from kalChan1. Example: setSerial1 23"
echo "raspi-config Open Raspberry Pi settings to expand filesystem"
}

Wyświetl plik

@ -1,64 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: stratux
# Required-Start: $network
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: 2
# Default-Stop: 6
# Short-Description: Stratux ADS-B Receiver
# Description: RTL-SDR ADS-B receiver
### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON_SBIN=/usr/sbin/stratux
DAEMON_DEFS=
DAEMON_CONF=
NAME=stratux
DESC="Stratux ADS-B Receiver"
PIDFILE=/var/run/stratux.pid
[ -x "$DAEMON_SBIN" ] || exit 0
DAEMON_OPTS="-B -P $PIDFILE $DAEMON_OPTS $DAEMON_CONF"
. /lib/lsb/init-functions
case "$1" in
start)
log_daemon_msg "Starting $DESC" "$NAME"
start-stop-daemon --start --oknodo --quiet --exec "$DAEMON_SBIN" \
--pidfile "$PIDFILE" --make-pidfile -- $DAEMON_OPTS >/dev/null
log_end_msg "$?"
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
start-stop-daemon --stop --oknodo --quiet --exec "$DAEMON_SBIN" \
--pidfile "$PIDFILE"
log_end_msg "$?"
;;
reload)
log_daemon_msg "Reloading $DESC" "$NAME"
start-stop-daemon --stop --signal HUP --exec "$DAEMON_SBIN" \
--pidfile "$PIDFILE"
log_end_msg "$?"
;;
restart|force-reload)
$0 stop
sleep 8
$0 start
;;
status)
status_of_proc "$DAEMON_SBIN" "$NAME"
exit $?
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload|reload|status}" >&2
exit 1
;;
esac
exit 0

46
main/cputemp.go 100644
Wyświetl plik

@ -0,0 +1,46 @@
package main
import (
"io/ioutil"
"strconv"
"strings"
"time"
)
const invalidCpuTemp = float32(-99.0)
type CpuTempUpdateFunc func(cpuTemp float32)
/* cpuTempMonitor() reads the RPi board temperature every second and
calls a callback. This is broken out into its own function (run as
its own goroutine) because the RPi temperature monitor code is buggy,
and often times reading this file hangs quite some time. */
func cpuTempMonitor(updater CpuTempUpdateFunc) {
timer := time.NewTicker(1 * time.Second)
for {
// Update CPUTemp.
temp, err := ioutil.ReadFile("/sys/class/thermal/thermal_zone0/temp")
tempStr := strings.Trim(string(temp), "\n")
t := invalidCpuTemp
if err == nil {
tInt, err := strconv.Atoi(tempStr)
if err == nil {
if tInt > 1000 {
t = float32(tInt) / float32(1000.0)
} else {
t = float32(tInt) // case where Temp is returned as simple integer
}
}
}
if t >= invalidCpuTemp { // Only update if valid value was obtained.
updater(t)
}
<-timer.C
}
}
// Check if CPU temperature is valid. Assume <= 0 is invalid.
func isCPUTempValid(cpuTemp float32) bool {
return cpuTemp > 0
}

642
main/datalog.go 100644
Wyświetl plik

@ -0,0 +1,642 @@
/*
Copyright (c) 2015-2016 Christopher Young
Distributable under the terms of The "BSD New" License
that can be found in the LICENSE file, herein included
as part of this header.
datalog.go: Log stratux data as it is received. Bucket data into timestamp time slots.
*/
package main
import (
"database/sql"
"errors"
"fmt"
_ "github.com/mattn/go-sqlite3"
"log"
"os"
"reflect"
"strconv"
"strings"
"time"
)
const (
LOG_TIMESTAMP_RESOLUTION = 250 * time.Millisecond
)
type StratuxTimestamp struct {
id int64
Time_type_preference int // 0 = stratuxClock, 1 = gpsClock, 2 = gpsClock extrapolated via stratuxClock.
StratuxClock_value time.Time
GPSClock_value time.Time // The value of this is either from the GPS or extrapolated from the GPS via stratuxClock if pref is 1 or 2. It is time.Time{} if 0.
PreferredTime_value time.Time
StartupID int64
}
// 'startup' table creates a new entry each time the daemon is started. This keeps track of sequential starts, even if the
// timestamp is ambiguous (units with no GPS). This struct is just a placeholder for an empty table (other than primary key).
type StratuxStartup struct {
id int64
Fill string
}
var dataLogStarted bool
var dataLogReadyToWrite bool
var stratuxStartupID int64
var dataLogTimestamps []StratuxTimestamp
var dataLogCurTimestamp int64 // Current timestamp bucket. This is an index on dataLogTimestamps which is not necessarily the db id.
/*
checkTimestamp().
Verify that our current timestamp is within the LOG_TIMESTAMP_RESOLUTION bucket.
Returns false if the timestamp was changed, true if it is still valid.
This is where GPS timestamps are extrapolated, if the GPS data is currently valid.
*/
func checkTimestamp() bool {
thisCurTimestamp := dataLogCurTimestamp
if stratuxClock.Since(dataLogTimestamps[thisCurTimestamp].StratuxClock_value) >= LOG_TIMESTAMP_RESOLUTION {
var ts StratuxTimestamp
ts.id = 0
ts.Time_type_preference = 0 // stratuxClock.
ts.StratuxClock_value = stratuxClock.Time
ts.GPSClock_value = time.Time{}
ts.PreferredTime_value = stratuxClock.Time
// Extrapolate from GPS timestamp, if possible.
if isGPSClockValid() && thisCurTimestamp > 0 {
// Was the last timestamp either extrapolated or GPS time?
last_ts := dataLogTimestamps[thisCurTimestamp]
if last_ts.Time_type_preference == 1 || last_ts.Time_type_preference == 2 {
// Extrapolate via stratuxClock.
timeSinceLastTS := ts.StratuxClock_value.Sub(last_ts.StratuxClock_value) // stratuxClock ticks since last timestamp.
extrapolatedGPSTimestamp := last_ts.PreferredTime_value.Add(timeSinceLastTS)
// Re-set the preferred timestamp type to '2' (extrapolated time).
ts.Time_type_preference = 2
ts.PreferredTime_value = extrapolatedGPSTimestamp
ts.GPSClock_value = extrapolatedGPSTimestamp
}
}
dataLogTimestamps = append(dataLogTimestamps, ts)
dataLogCurTimestamp = int64(len(dataLogTimestamps) - 1)
return false
}
return true
}
type SQLiteMarshal struct {
FieldType string
Marshal func(v reflect.Value) string
}
func boolMarshal(v reflect.Value) string {
b := v.Bool()
if b {
return "1"
}
return "0"
}
func intMarshal(v reflect.Value) string {
return strconv.FormatInt(v.Int(), 10)
}
func uintMarshal(v reflect.Value) string {
return strconv.FormatUint(v.Uint(), 10)
}
func floatMarshal(v reflect.Value) string {
return strconv.FormatFloat(v.Float(), 'f', 10, 64)
}
func stringMarshal(v reflect.Value) string {
return v.String()
}
func notsupportedMarshal(v reflect.Value) string {
return ""
}
func structCanBeMarshalled(v reflect.Value) bool {
m := v.MethodByName("String")
if m.IsValid() && !m.IsNil() {
return true
}
return false
}
func structMarshal(v reflect.Value) string {
if structCanBeMarshalled(v) {
m := v.MethodByName("String")
in := make([]reflect.Value, 0)
ret := m.Call(in)
if len(ret) > 0 {
return ret[0].String()
}
}
return ""
}
var sqliteMarshalFunctions = map[string]SQLiteMarshal{
"bool": {FieldType: "INTEGER", Marshal: boolMarshal},
"int": {FieldType: "INTEGER", Marshal: intMarshal},
"uint": {FieldType: "INTEGER", Marshal: uintMarshal},
"float": {FieldType: "REAL", Marshal: floatMarshal},
"string": {FieldType: "TEXT", Marshal: stringMarshal},
"struct": {FieldType: "STRING", Marshal: structMarshal},
"notsupported": {FieldType: "notsupported", Marshal: notsupportedMarshal},
}
var sqlTypeMap = map[reflect.Kind]string{
reflect.Bool: "bool",
reflect.Int: "int",
reflect.Int8: "int",
reflect.Int16: "int",
reflect.Int32: "int",
reflect.Int64: "int",
reflect.Uint: "uint",
reflect.Uint8: "uint",
reflect.Uint16: "uint",
reflect.Uint32: "uint",
reflect.Uint64: "uint",
reflect.Uintptr: "notsupported",
reflect.Float32: "float",
reflect.Float64: "float",
reflect.Complex64: "notsupported",
reflect.Complex128: "notsupported",
reflect.Array: "notsupported",
reflect.Chan: "notsupported",
reflect.Func: "notsupported",
reflect.Interface: "notsupported",
reflect.Map: "notsupported",
reflect.Ptr: "notsupported",
reflect.Slice: "notsupported",
reflect.String: "string",
reflect.Struct: "struct",
reflect.UnsafePointer: "notsupported",
}
func makeTable(i interface{}, tbl string, db *sql.DB) {
val := reflect.ValueOf(i)
fields := make([]string, 0)
for i := 0; i < val.NumField(); i++ {
kind := val.Field(i).Kind()
fieldName := val.Type().Field(i).Name
sqlTypeAlias := sqlTypeMap[kind]
// Check that if the field is a struct that it can be marshalled.
if sqlTypeAlias == "struct" && !structCanBeMarshalled(val.Field(i)) {
continue
}
if sqlTypeAlias == "notsupported" || fieldName == "id" {
continue
}
sqlType := sqliteMarshalFunctions[sqlTypeAlias].FieldType
s := fieldName + " " + sqlType
fields = append(fields, s)
}
// Add the timestamp_id field to link up with the timestamp table.
if tbl != "timestamp" && tbl != "startup" {
fields = append(fields, "timestamp_id INTEGER")
}
tblCreate := fmt.Sprintf("CREATE TABLE %s (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, %s)", tbl, strings.Join(fields, ", "))
_, err := db.Exec(tblCreate)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
}
}
/*
bulkInsert().
Reads insertBatch and insertBatchIfs. This is called after a group of insertData() calls.
*/
func bulkInsert(tbl string, db *sql.DB) (res sql.Result, err error) {
if _, ok := insertString[tbl]; !ok {
return nil, errors.New("no insert statement")
}
batchVals := insertBatchIfs[tbl]
numColsPerRow := len(batchVals[0])
maxRowBatch := int(999 / numColsPerRow) // SQLITE_MAX_VARIABLE_NUMBER = 999.
// log.Printf("table %s. %d cols per row. max batch %d\n", tbl, numColsPerRow, maxRowBatch)
for len(batchVals) > 0 {
// timeInit := time.Now()
i := int(0) // Variable number of rows per INSERT statement.
stmt := ""
vals := make([]interface{}, 0)
querySize := uint64(0) // Size of the query in bytes.
for len(batchVals) > 0 && i < maxRowBatch && querySize < 750000 { // Maximum of 1,000,000 bytes per query.
if len(stmt) == 0 { // The first set will be covered by insertString.
stmt = insertString[tbl]
querySize += uint64(len(insertString[tbl]))
} else {
addStr := ", (" + strings.Join(strings.Split(strings.Repeat("?", len(batchVals[0])), ""), ",") + ")"
stmt += addStr
querySize += uint64(len(addStr))
}
for _, val := range batchVals[0] {
querySize += uint64(len(val.(string)))
}
vals = append(vals, batchVals[0]...)
batchVals = batchVals[1:]
i++
}
// log.Printf("inserting %d rows to %s. querySize=%d\n", i, tbl, querySize)
res, err = db.Exec(stmt, vals...)
// timeBatch := time.Since(timeInit) // debug
// log.Printf("SQLite: bulkInserted %d rows to %s. Took %f msec to build and insert query. querySize=%d\n", i, tbl, 1000*timeBatch.Seconds(), querySize) // debug
if err != nil {
log.Printf("sqlite INSERT error: '%s'\n", err.Error())
return
}
}
// Clear the buffers.
delete(insertString, tbl)
delete(insertBatchIfs, tbl)
return
}
/*
insertData().
Inserts an arbitrary struct into an SQLite table.
Inserts the timestamp first, if its 'id' is 0.
*/
// Cached 'VALUES' statements. Indexed by table name.
var insertString map[string]string // INSERT INTO tbl (col1, col2, ...) VALUES(?, ?, ...). Only for one value.
var insertBatchIfs map[string][][]interface{}
func insertData(i interface{}, tbl string, db *sql.DB, ts_num int64) int64 {
val := reflect.ValueOf(i)
keys := make([]string, 0)
values := make([]string, 0)
for i := 0; i < val.NumField(); i++ {
kind := val.Field(i).Kind()
fieldName := val.Type().Field(i).Name
sqlTypeAlias := sqlTypeMap[kind]
if sqlTypeAlias == "notsupported" || fieldName == "id" {
continue
}
v := sqliteMarshalFunctions[sqlTypeAlias].Marshal(val.Field(i))
keys = append(keys, fieldName)
values = append(values, v)
}
// Add the timestamp_id field to link up with the timestamp table.
if tbl != "timestamp" && tbl != "startup" {
keys = append(keys, "timestamp_id")
if dataLogTimestamps[ts_num].id == 0 {
//FIXME: This is somewhat convoluted. When insertData() is called for a ts_num that corresponds to a timestamp with no database id,
// then it inserts that timestamp via the same interface and the id is updated in the structure via the below lines
// (dataLogTimestamps[ts_num].id = id).
dataLogTimestamps[ts_num].StartupID = stratuxStartupID
insertData(dataLogTimestamps[ts_num], "timestamp", db, ts_num) // Updates dataLogTimestamps[ts_num].id.
}
values = append(values, strconv.FormatInt(dataLogTimestamps[ts_num].id, 10))
}
if _, ok := insertString[tbl]; !ok {
// Prepare the statement.
tblInsert := fmt.Sprintf("INSERT INTO %s (%s) VALUES(%s)", tbl, strings.Join(keys, ","),
strings.Join(strings.Split(strings.Repeat("?", len(keys)), ""), ","))
insertString[tbl] = tblInsert
}
// Make the values slice into a slice of interface{}.
ifs := make([]interface{}, len(values))
for i := 0; i < len(values); i++ {
ifs[i] = values[i]
}
insertBatchIfs[tbl] = append(insertBatchIfs[tbl], ifs)
if tbl == "timestamp" || tbl == "startup" { // Immediate insert always for "timestamp" and "startup" table.
res, err := bulkInsert(tbl, db) // Bulk insert of 1, always.
if err == nil {
id, err := res.LastInsertId()
if err == nil && tbl == "timestamp" { // Special handling for timestamps. Update the timestamp ID.
ts := dataLogTimestamps[ts_num]
ts.id = id
dataLogTimestamps[ts_num] = ts
}
return id
}
}
return 0
}
type DataLogRow struct {
tbl string
data interface{}
ts_num int64
}
var dataLogChan chan DataLogRow
var shutdownDataLog chan bool
var shutdownDataLogWriter chan bool
var dataLogWriteChan chan DataLogRow
func dataLogWriter(db *sql.DB) {
dataLogWriteChan = make(chan DataLogRow, 10240)
shutdownDataLogWriter = make(chan bool)
// The write queue. As data comes in via dataLogChan, it is timestamped and stored.
// When writeTicker comes up, the queue is emptied.
writeTicker := time.NewTicker(10 * time.Second)
rowsQueuedForWrite := make([]DataLogRow, 0)
for {
select {
case r := <-dataLogWriteChan:
// Accept timestamped row.
rowsQueuedForWrite = append(rowsQueuedForWrite, r)
case <-writeTicker.C:
// for i := 0; i < 1000; i++ {
// logSituation()
// }
timeStart := stratuxClock.Time
nRows := len(rowsQueuedForWrite)
if globalSettings.DEBUG {
log.Printf("Writing %d rows\n", nRows)
}
// Write the buffered rows. This will block while it is writing.
// Save the names of the tables affected so that we can run bulkInsert() on after the insertData() calls.
tblsAffected := make(map[string]bool)
// Start transaction.
tx, err := db.Begin()
if err != nil {
log.Printf("db.Begin() error: %s\n", err.Error())
break // from select {}
}
for _, r := range rowsQueuedForWrite {
tblsAffected[r.tbl] = true
insertData(r.data, r.tbl, db, r.ts_num)
}
// Do the bulk inserts.
for tbl, _ := range tblsAffected {
bulkInsert(tbl, db)
}
// Close the transaction.
tx.Commit()
rowsQueuedForWrite = make([]DataLogRow, 0) // Zero the queue.
timeElapsed := stratuxClock.Since(timeStart)
if globalSettings.DEBUG {
rowsPerSecond := float64(nRows) / float64(timeElapsed.Seconds())
log.Printf("Writing finished. %d rows in %.2f seconds (%.1f rows per second).\n", nRows, float64(timeElapsed.Seconds()), rowsPerSecond)
}
if timeElapsed.Seconds() > 10.0 {
log.Printf("WARNING! SQLite logging is behind. Last write took %.1f seconds.\n", float64(timeElapsed.Seconds()))
dataLogCriticalErr := fmt.Errorf("WARNING! SQLite logging is behind. Last write took %.1f seconds.\n", float64(timeElapsed.Seconds()))
addSystemError(dataLogCriticalErr)
}
case <-shutdownDataLogWriter: // Received a message on the channel to initiate a graceful shutdown, and to command dataLog() to shut down
log.Printf("datalog.go: dataLogWriter() received shutdown message with rowsQueuedForWrite = %d\n", len(rowsQueuedForWrite))
shutdownDataLog <- true
return
}
}
log.Printf("datalog.go: dataLogWriter() shutting down\n")
}
func dataLog() {
dataLogStarted = true
log.Printf("datalog.go: dataLog() started\n")
dataLogChan = make(chan DataLogRow, 10240)
shutdownDataLog = make(chan bool)
dataLogTimestamps = make([]StratuxTimestamp, 0)
var ts StratuxTimestamp
ts.id = 0
ts.Time_type_preference = 0 // stratuxClock.
ts.StratuxClock_value = stratuxClock.Time
ts.GPSClock_value = time.Time{}
ts.PreferredTime_value = stratuxClock.Time
dataLogTimestamps = append(dataLogTimestamps, ts)
dataLogCurTimestamp = 0
// Check if we need to create a new database.
createDatabase := false
if _, err := os.Stat(dataLogFilef); os.IsNotExist(err) {
createDatabase = true
log.Printf("creating new database '%s'.\n", dataLogFilef)
}
db, err := sql.Open("sqlite3", dataLogFilef)
if err != nil {
log.Printf("sql.Open(): %s\n", err.Error())
}
defer func() {
db.Close()
dataLogStarted = false
//close(dataLogChan)
log.Printf("datalog.go: dataLog() has closed DB in %s\n", dataLogFilef)
}()
_, err = db.Exec("PRAGMA journal_mode=WAL")
if err != nil {
log.Printf("db.Exec('PRAGMA journal_mode=WAL') err: %s\n", err.Error())
}
_, err = db.Exec("PRAGMA synchronous=OFF")
if err != nil {
log.Printf("db.Exec('PRAGMA journal_mode=WAL') err: %s\n", err.Error())
}
//log.Printf("Starting dataLogWriter\n") // REMOVE -- DEBUG
go dataLogWriter(db)
// Do we need to create the database?
if createDatabase {
makeTable(StratuxTimestamp{}, "timestamp", db)
makeTable(mySituation, "mySituation", db)
makeTable(globalStatus, "status", db)
makeTable(globalSettings, "settings", db)
makeTable(TrafficInfo{}, "traffic", db)
makeTable(msg{}, "messages", db)
makeTable(esmsg{}, "es_messages", db)
makeTable(Dump1090TermMessage{}, "dump1090_terminal", db)
makeTable(gpsPerfStats{}, "gps_attitude", db)
makeTable(StratuxStartup{}, "startup", db)
}
// The first entry to be created is the "startup" entry.
stratuxStartupID = insertData(StratuxStartup{}, "startup", db, 0)
dataLogReadyToWrite = true
//log.Printf("Entering dataLog read loop\n") //REMOVE -- DEBUG
for {
select {
case r := <-dataLogChan:
// When data is input, the first step is to timestamp it.
// Check if our time bucket has expired or has never been entered.
checkTimestamp()
// Mark the row with the current timestamp ID, in case it gets entered later.
r.ts_num = dataLogCurTimestamp
// Queue it for the scheduled write.
dataLogWriteChan <- r
case <-shutdownDataLog: // Received a message on the channel to complete a graceful shutdown (see the 'defer func()...' statement above).
log.Printf("datalog.go: dataLog() received shutdown message\n")
return
}
}
log.Printf("datalog.go: dataLog() shutting down\n")
close(shutdownDataLog)
}
/*
setDataLogTimeWithGPS().
Create a timestamp entry using GPS time.
*/
func setDataLogTimeWithGPS(sit SituationData) {
if isGPSClockValid() {
var ts StratuxTimestamp
// Piggyback a GPS time update from this update.
ts.id = 0
ts.Time_type_preference = 1 // gpsClock.
ts.StratuxClock_value = stratuxClock.Time
ts.GPSClock_value = sit.GPSTime
ts.PreferredTime_value = sit.GPSTime
dataLogTimestamps = append(dataLogTimestamps, ts)
dataLogCurTimestamp = int64(len(dataLogTimestamps) - 1)
}
}
/*
logSituation(), logStatus(), ... pass messages from other functions to the logging
engine. These are only read into `dataLogChan` if the Replay Log is toggled on,
and if the log system is ready to accept writes.
*/
func isDataLogReady() bool {
return dataLogReadyToWrite
}
func logSituation() {
if globalSettings.ReplayLog && isDataLogReady() {
dataLogChan <- DataLogRow{tbl: "mySituation", data: mySituation}
}
}
func logStatus() {
if globalSettings.ReplayLog && isDataLogReady() {
dataLogChan <- DataLogRow{tbl: "status", data: globalStatus}
}
}
func logSettings() {
if globalSettings.ReplayLog && isDataLogReady() {
dataLogChan <- DataLogRow{tbl: "settings", data: globalSettings}
}
}
func logTraffic(ti TrafficInfo) {
if globalSettings.ReplayLog && isDataLogReady() {
dataLogChan <- DataLogRow{tbl: "traffic", data: ti}
}
}
func logMsg(m msg) {
if globalSettings.ReplayLog && isDataLogReady() {
dataLogChan <- DataLogRow{tbl: "messages", data: m}
}
}
func logESMsg(m esmsg) {
if globalSettings.ReplayLog && isDataLogReady() {
dataLogChan <- DataLogRow{tbl: "es_messages", data: m}
}
}
func logGPSAttitude(gpsPerf gpsPerfStats) {
if globalSettings.ReplayLog && isDataLogReady() {
dataLogChan <- DataLogRow{tbl: "gps_attitude", data: gpsPerf}
}
}
func logDump1090TermMessage(m Dump1090TermMessage) {
if globalSettings.DEBUG && globalSettings.ReplayLog && isDataLogReady() {
dataLogChan <- DataLogRow{tbl: "dump1090_terminal", data: m}
}
}
func initDataLog() {
//log.Printf("dataLogStarted = %t. dataLogReadyToWrite = %t\n", dataLogStarted, dataLogReadyToWrite) //REMOVE -- DEBUG
insertString = make(map[string]string)
insertBatchIfs = make(map[string][][]interface{})
go dataLogWatchdog()
//log.Printf("datalog.go: initDataLog() complete.\n") //REMOVE -- DEBUG
}
/*
dataLogWatchdog(): Watchdog function to control startup / shutdown of data logging subsystem.
Called by initDataLog as a goroutine. It iterates once per second to determine if
globalSettings.ReplayLog has toggled. If logging was switched from off to on, it starts
datalog() as a goroutine. If the log is running and we want it to stop, it calls
closeDataLog() to turn off the input channels, close the log, and tear down the dataLog
and dataLogWriter goroutines.
*/
func dataLogWatchdog() {
for {
if !dataLogStarted && globalSettings.ReplayLog { // case 1: sqlite logging isn't running, and we want to start it
log.Printf("datalog.go: Watchdog wants to START logging.\n")
go dataLog()
} else if dataLogStarted && !globalSettings.ReplayLog { // case 2: sqlite logging is running, and we want to shut it down
log.Printf("datalog.go: Watchdog wants to STOP logging.\n")
closeDataLog()
}
//log.Printf("Watchdog iterated.\n") //REMOVE -- DEBUG
time.Sleep(1 * time.Second)
//log.Printf("Watchdog sleep over.\n") //REMOVE -- DEBUG
}
}
/*
closeDataLog(): Handler for graceful shutdown of data logging goroutines. It is called by
by dataLogWatchdog(), gracefulShutdown(), and by any other function (disk space monitor?)
that needs to be able to shut down sqlite logging without corrupting data or blocking
execution.
This function turns off log message reads into the dataLogChan receiver, and sends a
message to a quit channel ('shutdownDataLogWriter`) in dataLogWriter(). dataLogWriter()
then sends a message to a quit channel to 'shutdownDataLog` in dataLog() to close *that*
goroutine. That function sets dataLogStarted=false once the logfile is closed. By waiting
for that signal, closeDataLog() won't exit until the log is safely written. This prevents
data loss on shutdown.
*/
func closeDataLog() {
//log.Printf("closeDataLog(): dataLogStarted = %t\n", dataLogStarted) //REMOVE -- DEBUG
dataLogReadyToWrite = false // prevent any new messages from being sent down the channels
log.Printf("datalog.go: Starting data log shutdown\n")
shutdownDataLogWriter <- true //
defer close(shutdownDataLogWriter) // ... and close the channel so subsequent accidental writes don't stall execution
log.Printf("datalog.go: Waiting for shutdown signal from dataLog()")
for dataLogStarted {
//log.Printf("closeDataLog(): dataLogStarted = %t\n", dataLogStarted) //REMOVE -- DEBUG
time.Sleep(50 * time.Millisecond)
}
log.Printf("datalog.go: Data log shutdown successful.\n")
}

355
main/equations.go 100644
Wyświetl plik

@ -0,0 +1,355 @@
/*
Copyright (c) 2016 AvSquirrel (https://github.com/AvSquirrel)
Distributable under the terms of the "BSD New" License
that can be found in the LICENSE file, herein included
as part of this header.
equations.go: Math and statistics library used to support AHRS
and other fuctions of Stratux package
*/
package main
import (
"fmt"
"math"
)
// linReg calculates slope and intercept for a least squares linear regression of y[] vs x[]
// Returns error if fewer than two data points in each series, or if series lengths are different
func linReg(x, y []float64) (slope, intercept float64, valid bool) {
n := len(x)
nf := float64(n)
if n != len(y) {
fmt.Printf("linReg: Lengths not equal\n")
return math.NaN(), math.NaN(), false
}
if n < 2 {
fmt.Printf("linReg: Lengths too short\n")
return math.NaN(), math.NaN(), false
}
var Sx, Sy, Sxx, Sxy, Syy float64
for i := range x {
Sx += x[i]
Sy += y[i]
Sxx += x[i] * x[i]
Sxy += x[i] * y[i]
Syy += y[i] * y[i]
}
if nf*Sxx == Sx*Sx {
fmt.Printf("linReg: Infinite slope\n")
return math.NaN(), math.NaN(), false
}
// Calculate slope and intercept
slope = (nf*Sxy - Sx*Sy) / (nf*Sxx - Sx*Sx)
intercept = Sy/nf - slope*Sx/nf
valid = true
return
}
// linRegWeighted calculates slope and intercept for a weighted least squares
// linear regression of y[] vs x[], given weights w[] for each point.
// Returns error if fewer than two data points in each series, if series lengths are different,
// if weights sum to zero, or if slope is infinite
func linRegWeighted(x, y, w []float64) (slope, intercept float64, valid bool) {
n := len(x)
if n != len(y) || n != len(w) {
fmt.Printf("linRegWeighted: Lengths not equal\n")
return math.NaN(), math.NaN(), false
}
if n < 2 {
fmt.Printf("linRegWeighted: Lengths too short\n")
return math.NaN(), math.NaN(), false
}
//var Sx, Sy, Sxx, Sxy, Syy float64
var Sw, Swx, Swy, Swxx, Swxy, Swyy float64
for i := range x {
Sw += w[i]
Swxy += w[i] * x[i] * y[i]
Swx += w[i] * x[i]
Swy += w[i] * y[i]
Swxx += w[i] * x[i] * x[i]
Swyy += w[i] * y[i] * y[i]
/*
Sx += x[i]
Sy += y[i]
Sxx += x[i]*x[i]
Sxy += x[i]*y[i]
Syy += y[i]*y[i]
*/
}
if Sw == 0 {
fmt.Printf("linRegWeighted: Sum of weights is zero\n")
return math.NaN(), math.NaN(), false
}
if Sw*Swxx == Swx*Swx {
fmt.Printf("linRegWeighted: Infinite slope\n")
return math.NaN(), math.NaN(), false
}
// Calculate slope and intercept
slope = (Sw*Swxy - Swx*Swy) / (Sw*Swxx - Swx*Swx)
intercept = Swy/Sw - slope*Swx/Sw
valid = true
return
}
// triCubeWeight returns the value of the tricube weight function
// at point x, for the given center and halfwidth.
func triCubeWeight(center, halfwidth, x float64) float64 {
var weight, x_t float64
x_t = math.Abs((x - center) / halfwidth)
if x_t < 1 {
weight = math.Pow((1 - math.Pow(x_t, 3)), 3)
} else {
weight = 0
}
return weight
}
// arrayMin calculates the minimum value in array x
func arrayMin(x []float64) (float64, bool) {
if len(x) < 1 {
fmt.Printf("arrayMin: Length too short\n")
return math.NaN(), false
}
min := x[0]
for i := range x {
if x[i] < min {
min = x[i]
}
}
return min, true
}
// arrayMax calculates the maximum value in array x
func arrayMax(x []float64) (float64, bool) {
if len(x) < 1 {
fmt.Printf("arrayMax: Length too short\n")
return math.NaN(), false
}
max := x[0]
for i := range x {
if x[i] > max {
max = x[i]
}
}
return max, true
}
// arrayRange calculates the range of values in array x
func arrayRange(x []float64) (float64, bool) {
max, err1 := arrayMax(x)
min, err2 := arrayMin(x)
if !err1 || !err2 {
fmt.Printf("Error calculating range\n")
return math.NaN(), false
}
return (max - min), true
}
// mean returns the arithmetic mean of array x
func mean(x []float64) (float64, bool) {
if len(x) < 1 {
fmt.Printf("mean: Length too short\n")
return math.NaN(), false
}
sum := 0.0
nf := float64(len(x))
for i := range x {
sum += x[i]
}
return sum / nf, true
}
// stdev estimates the sample standard deviation of array x
func stdev(x []float64) (float64, bool) {
if len(x) < 2 {
fmt.Printf("stdev: Length too short\n")
return math.NaN(), false
}
nf := float64(len(x))
xbar, xbarValid := mean(x)
if !xbarValid {
fmt.Printf("stdev: Error calculating xbar\n")
return math.NaN(), false
}
sumsq := 0.0
for i := range x {
sumsq += (x[i] - xbar) * (x[i] - xbar)
}
return math.Pow(sumsq/(nf-1), 0.5), true
}
// radians converts angle from degrees, and returns its value in radians
func radians(angle float64) float64 {
return angle * math.Pi / 180.0
}
// degrees converts angle from radians, and returns its value in degrees
func degrees(angle float64) float64 {
return angle * 180.0 / math.Pi
}
// radiansRel converts angle from degrees, and returns its value in radians in the range -Pi to + Pi
func radiansRel(angle float64) float64 {
for angle > 180 {
angle -= 360
}
for angle < -180 {
angle += 360
}
return angle * math.Pi / 180.0
}
// degreesRel converts angle from radians, and returns its value in the range of -180 to +180 degrees
func degreesRel(angle float64) float64 {
for angle > math.Pi {
angle -= 2 * math.Pi
}
for angle < -math.Pi {
angle += 2 * math.Pi
}
return angle * 180.0 / math.Pi
}
// degreesHdg converts angle from radians, and returns its value in the range of 0+ to 360 degrees
func degreesHdg(angle float64) float64 {
for angle < 0 {
angle += 2 * math.Pi
}
return angle * 180.0 / math.Pi
}
// roundToInt16 cheaply rounds a float64 to an int16, rather than truncating
func roundToInt16(in float64) (out int16) {
if in >= 0 {
out = int16(in + 0.5)
} else {
out = int16(in - 0.5)
}
return
}
/*
Distance functions based on rectangular coordinate systems
Simple calculations and "good enough" on small scale (± 1° of lat / lon)
suitable for relative distance to nearby traffic
*/
// distRect returns distance and bearing to target #2 (e.g. traffic) from target #1 (e.g. ownship)
// Inputs are lat / lon of both points in decimal degrees
// Outputs are distance in meters and bearing in degrees (0° = north, 90° = east)
// Secondary outputs are north and east components of distance in meters (north, east positive)
func distRect(lat1, lon1, lat2, lon2 float64) (dist, bearing, distN, distE float64) {
radius_earth := 6371008.8 // meters; mean radius
dLat := radiansRel(lat2 - lat1)
avgLat := radiansRel((lat2 + lat1) / 2)
dLon := radiansRel(lon2 - lon1)
distN = dLat * radius_earth
distE = dLon * radius_earth * math.Abs(math.Cos(avgLat))
dist = math.Pow(distN*distN+distE*distE, 0.5)
bearing = math.Atan2(distE, distN)
bearing = degreesHdg(bearing)
return
}
// distRectNorth returns north-south distance from point 1 to point 2.
// Inputs are lat in decimal degrees. Output is distance in meters (east positive)
func distRectNorth(lat1, lat2 float64) float64 {
var dist float64
radius_earth := 6371008.8 // meters; mean radius
dLat := radiansRel(lat2 - lat1)
dist = dLat * radius_earth
return dist
}
// distRectEast returns east-west distance from point 1 to point 2.
// Inputs are lat/lon in decimal degrees. Output is distance in meters (north positive)
func distRectEast(lat1, lon1, lat2, lon2 float64) float64 {
var dist float64
radius_earth := 6371008.8 // meters; mean radius
//dLat := radiansRel(lat2 - lat1) // unused
avgLat := radiansRel((lat2 + lat1) / 2)
dLon := radiansRel(lon2 - lon1)
dist = dLon * radius_earth * math.Abs(math.Cos(avgLat))
return dist
}
/*
Distance functions: Polar coordinate systems
More accurate over longer distances
*/
// distance calculates distance between two points using the law of cosines.
// Inputs are lat / lon of both points in decimal degrees
// Outputs are distance in meters and bearing to the target from origin in degrees (0° = north, 90° = east)
func distance(lat1, lon1, lat2, lon2 float64) (dist, bearing float64) {
radius_earth := 6371008.8 // meters; mean radius
lat1 = radians(lat1)
lon1 = radians(lon1)
lat2 = radians(lat2)
lon2 = radians(lon2)
dist = math.Acos(math.Sin(lat1)*math.Sin(lat2)+math.Cos(lat1)*math.Cos(lat2)*math.Cos(lon2-lon1)) * radius_earth
var x, y float64
x = math.Cos(lat1)*math.Sin(lat2) - math.Sin(lat1)*math.Cos(lat2)*math.Cos(lon2-lon1)
y = math.Sin(lon2-lon1) * math.Cos(lat2)
bearing = degreesHdg(math.Atan2(y, x))
return
}
// CalcAltitude determines the pressure altitude (feet) from the atmospheric pressure (hPa)
func CalcAltitude(press float64) (altitude float64) {
altitude = 145366.45 * (1.0 - math.Pow(press/1013.25, 0.190284))
return
}
// golang only defines min/max for float64. Really.
func iMin(x, y int) int {
if x < y {
return x
}
return y
}
func iMax(x, y int) int {
if x > y {
return x
}
return y
}

241
main/fancontrol.go 100644
Wyświetl plik

@ -0,0 +1,241 @@
package main
import (
"encoding/json"
"flag"
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/takama/daemon"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
// #include <wiringPi.h>
// #cgo LDFLAGS: -lwiringPi
import "C"
// Initialize Prometheus metrics.
var (
currentTemp = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "current_temp",
Help: "Current CPU temp.",
})
totalFanOnTime = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "total_fan_on_time",
Help: "Total fan run time.",
},
[]string{"all"},
)
totalUptime = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "total_uptime",
Help: "Total uptime.",
},
[]string{"all"},
)
)
const (
// CPU temperature target, degrees C
defaultTempTarget = 50.
hysteresis = float32(1.)
pwmClockDivisor = 100
/* Minimum duty cycle is the point below which the fan does
/* not spin. This depends on both your fan and the switching
/* transistor used. */
defaultPwmDutyMin = 1
pwmDutyMax = 10
// Temperature at which we give up attempting active fan speed control and set it to full speed.
failsafeTemp = 65
// how often to update
delaySeconds = 30
// GPIO-1/BCM "18"/Pin 12 on a Raspberry Pi 3
defaultPin = 1
// name of the service
name = "fancontrol"
description = "cooling fan speed control based on CPU temperature"
// Address on which daemon should be listen.
addr = ":9977"
)
type FanControl struct {
TempTarget float32
TempCurrent float32
PWMDutyMin int
PWMDutyMax int
PWMDutyCurrent int
PWMPin int
}
var myFanControl FanControl
var stdlog, errlog *log.Logger
func updateStats() {
updateTicker := time.NewTicker(1 * time.Second)
for {
<-updateTicker.C
totalUptime.With(prometheus.Labels{"all": "all"}).Inc()
currentTemp.Set(float64(myFanControl.TempCurrent))
if myFanControl.PWMDutyCurrent > 0 {
totalFanOnTime.With(prometheus.Labels{"all": "all"}).Inc()
}
}
}
func fanControl() {
prometheus.MustRegister(currentTemp)
prometheus.MustRegister(totalFanOnTime)
prometheus.MustRegister(totalUptime)
go updateStats()
cPin := C.int(myFanControl.PWMPin)
C.wiringPiSetup()
// Power on "test". Allows the user to verify that their fan is working.
C.pinMode(cPin, C.OUTPUT)
C.digitalWrite(cPin, C.HIGH)
time.Sleep(5 * time.Second)
C.digitalWrite(cPin, C.LOW)
C.pwmSetMode(C.PWM_MODE_MS)
C.pinMode(cPin, C.PWM_OUTPUT)
C.pwmSetRange(C.uint(myFanControl.PWMDutyMax))
C.pwmSetClock(pwmClockDivisor)
C.pwmWrite(cPin, C.int(myFanControl.PWMDutyMin))
myFanControl.TempCurrent = 0
go cpuTempMonitor(func(cpuTemp float32) {
if isCPUTempValid(cpuTemp) {
myFanControl.TempCurrent = cpuTemp
}
})
myFanControl.PWMDutyCurrent = 0
delay := time.NewTicker(delaySeconds * time.Second)
for {
if myFanControl.TempCurrent > (myFanControl.TempTarget + hysteresis) {
myFanControl.PWMDutyCurrent = iMax(iMin(myFanControl.PWMDutyMax, myFanControl.PWMDutyCurrent+1), myFanControl.PWMDutyMin)
} else if myFanControl.TempCurrent < (myFanControl.TempTarget - hysteresis) {
myFanControl.PWMDutyCurrent = iMax(myFanControl.PWMDutyCurrent-1, 0)
if myFanControl.PWMDutyCurrent < myFanControl.PWMDutyMin {
myFanControl.PWMDutyCurrent = 0
}
}
//log.Println(myFanControl.TempCurrent, " ", myFanControl.PWMDutyCurrent)
C.pwmWrite(cPin, C.int(myFanControl.PWMDutyCurrent))
<-delay.C
if myFanControl.PWMDutyCurrent == myFanControl.PWMDutyMax && myFanControl.TempCurrent >= failsafeTemp {
// Reached the maximum temperature. We stop using PWM control and set the fan to "on" permanently.
break
}
}
// Default to "ON".
C.pinMode(cPin, C.OUTPUT)
C.digitalWrite(cPin, C.HIGH)
}
// Service has embedded daemon
type Service struct {
daemon.Daemon
}
// Manage by daemon commands or run the daemon
func (service *Service) Manage() (string, error) {
tempTarget := flag.Float64("temp", defaultTempTarget, "Target CPU Temperature, degrees C")
pwmDutyMin := flag.Int("minduty", defaultPwmDutyMin, "Minimum PWM duty cycle")
pin := flag.Int("pin", defaultPin, "PWM pin (wiringPi numbering)")
flag.Parse()
usage := "Usage: " + name + " install | remove | start | stop | status"
// if received any kind of command, do it
if flag.NArg() > 0 {
command := os.Args[flag.NFlag()+1]
switch command {
case "install":
return service.Install()
case "remove":
return service.Remove()
case "start":
return service.Start()
case "stop":
return service.Stop()
case "status":
return service.Status()
default:
return usage, nil
}
}
myFanControl.TempTarget = float32(*tempTarget)
myFanControl.PWMDutyMin = *pwmDutyMin
myFanControl.PWMDutyMax = pwmDutyMax
myFanControl.PWMPin = *pin
go fanControl()
// Set up channel on which to send signal notifications.
// We must use a buffered channel or risk missing the signal
// if we're not ready to receive when the signal is sent.
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)
http.HandleFunc("/", handleStatusRequest)
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(addr, nil)
// interrupt by system signal
for {
killSignal := <-interrupt
stdlog.Println("Got signal:", killSignal)
if killSignal == os.Interrupt {
return "Daemon was interrupted by system signal", nil
}
return "Daemon was killed", nil
}
}
func handleStatusRequest(w http.ResponseWriter, r *http.Request) {
statusJSON, _ := json.Marshal(&myFanControl)
w.Write(statusJSON)
}
func init() {
stdlog = log.New(os.Stdout, "", 0)
errlog = log.New(os.Stderr, "", 0)
}
func main() {
srv, err := daemon.New(name, description, []string{}...)
if err != nil {
errlog.Println("Error: ", err)
os.Exit(1)
}
service := &Service{srv}
status, err := service.Manage()
if err != nil {
errlog.Println(status, "\nError: ", err)
os.Exit(1)
}
fmt.Println(status)
}

Plik diff jest za duży Load Diff

2140
main/gps.go 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,155 @@
package main
import (
"encoding/hex"
"fmt"
"github.com/stratux/serial"
"log"
"os"
"time"
"unsafe"
)
/*
#cgo LDFLAGS: -ldump978 -lm
#include <stdint.h>
#include "../dump978/fec.h"
*/
import "C"
var radioSerialConfig *serial.Config
var radioSerialPort *serial.Port
func initUATRadioSerial() error {
// Init for FEC routines.
C.init_fec()
go func() {
watchTicker := time.NewTicker(1 * time.Second)
for {
<-watchTicker.C
// Watch for the radio or change in settings.
if !globalSettings.UAT_Enabled || globalStatus.UATRadio_connected {
// UAT not enabled or radio already set up. Continue.
continue
}
if _, err := os.Stat("/dev/uatradio"); err != nil {
// Device not connected.
continue
}
log.Printf("===== UAT Device Name : UATRadio v1.0 =====\n")
// Initialize port at 2Mbaud.
radioSerialConfig = &serial.Config{Name: "/dev/uatradio", Baud: 2000000}
p, err := serial.OpenPort(radioSerialConfig)
if err != nil {
log.Printf("\tUAT Open Failed: %s\n", err.Error())
continue
}
log.Printf("\tUATRadio init success.\n")
radioSerialPort = p
globalStatus.UATRadio_connected = true
// Start a goroutine to watch the serial port.
go radioSerialPortReader(radioSerialPort)
}
}()
return nil
}
/*
radioSerialPortReader().
Loop to read data from the radio serial port.
*/
var radioMagic = []byte{0x0a, 0xb0, 0xcd, 0xe0}
func radioSerialPortReader(serialPort *serial.Port) {
defer func() {
globalStatus.UATRadio_connected = false
serialPort.Close()
}()
tmpBuf := make([]byte, 1024) // Read buffer.
var buf []byte // Message buffer.
for {
n, err := serialPort.Read(tmpBuf)
if err != nil {
log.Printf("serial port err, shutting down radio: %s\n", err.Error())
return
}
buf = append(buf, tmpBuf[:n]...)
bufLen := len(buf)
var finBuf []byte // Truncated buffer, with processed messages extracted.
var numMessages int // Number of messages extracted.
// Search for a suitable message to extract.
for i := 0; i < bufLen-6; i++ {
if (buf[i] == radioMagic[0]) && (buf[i+1] == radioMagic[1]) && (buf[i+2] == radioMagic[2]) && (buf[i+3] == radioMagic[3]) {
// Found the magic sequence. Get the length.
msgLen := int(uint16(buf[i+4])+(uint16(buf[i+5])<<8)) + 5 // 5 bytes for RSSI and TS.
// Check if we've read enough to finish this message.
if bufLen < i+6+msgLen {
break // Wait for more of the message to come in.
}
// Message is long enough.
processRadioMessage(buf[i+6 : i+6+msgLen])
// Remove everything in the buffer before this message.
finBuf = buf[i+6+msgLen:]
numMessages++
}
}
if numMessages > 0 {
buf = finBuf
}
}
}
/*
processRadioMessage().
Processes a single message from the radio. De-interleaves (when necessary), checks Reed-Solomon, passes to main process.
*/
func processRadioMessage(msg []byte) {
// RSSI and message timestamp are prepended to the actual packet.
// RSSI
rssiRaw := int8(msg[0])
//rssiAdjusted := int16(rssiRaw) - 132 // -132 dBm, calculated minimum RSSI.
//rssiDump978 := int16(1000 * (10 ^ (float64(rssiAdjusted) / 20)))
rssiDump978 := rssiRaw
//_ := uint32(msg[1]) + (uint32(msg[2]) << 8) + (uint32(msg[3]) << 16) + (uint32(msg[4]) << 24) // Timestamp. Currently unused.
msg = msg[5:]
var toRelay string
var rs_errors int
switch len(msg) {
case 552:
to := make([]byte, 552)
C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))
toRelay = fmt.Sprintf("+%s;ss=%d;", hex.EncodeToString(to[:432]), rssiDump978)
case 48:
to := make([]byte, 48)
copy(to, msg)
i := int(C.correct_adsb_frame((*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors))))
if i == 1 {
// Short ADS-B frame.
toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:18]), rssiDump978)
} else if i == 2 {
// Long ADS-B frame.
toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:34]), rssiDump978)
}
default:
log.Printf("processRadioMessage(): unhandled message size %d\n", len(msg))
}
if len(toRelay) > 0 && rs_errors != 9999 {
o, msgtype := parseInput(toRelay)
if o != nil && msgtype != 0 {
relayMessage(msgtype, o)
}
}
}

Wyświetl plik

@ -1,11 +1,32 @@
/*
Copyright (c) 2015-2016 Christopher Young
Distributable under the terms of The "BSD New" License
that can be found in the LICENSE file, herein included
as part of this header.
managementinterface.go: Web interfaces (JSON and websocket), web server for web interface HTML.
*/
package main
import (
"archive/zip"
"encoding/hex"
"encoding/json"
"fmt"
humanize "github.com/dustin/go-humanize"
"golang.org/x/net/websocket"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"syscall"
"text/template"
"time"
)
@ -14,68 +35,832 @@ type SettingMessage struct {
Value bool `json:"state"`
}
type InfoMessage struct {
*status
*settings
// Weather updates channel.
var weatherUpdate *uibroadcaster
var trafficUpdate *uibroadcaster
var gdl90Update *uibroadcaster
func handleGDL90WS(conn *websocket.Conn) {
// Subscribe the socket to receive updates.
gdl90Update.AddSocket(conn)
// Connection closes when function returns. Since uibroadcast is writing and we don't need to read anything (for now), just keep it busy.
for {
buf := make([]byte, 1024)
_, err := conn.Read(buf)
if err != nil {
break
}
if buf[0] != 0 { // Dummy.
continue
}
time.Sleep(1 * time.Second)
}
}
func statusSender(conn *websocket.Conn) {
// Situation updates channel.
var situationUpdate *uibroadcaster
// Raw weather (UATFrame packet stream) update channel.
var weatherRawUpdate *uibroadcaster
/*
The /weather websocket starts off by sending the current buffer of weather messages, then sends updates as they are received.
*/
func handleWeatherWS(conn *websocket.Conn) {
// Subscribe the socket to receive updates.
weatherUpdate.AddSocket(conn)
// Connection closes when function returns. Since uibroadcast is writing and we don't need to read anything (for now), just keep it busy.
for {
buf := make([]byte, 1024)
_, err := conn.Read(buf)
if err != nil {
break
}
if buf[0] != 0 { // Dummy.
continue
}
time.Sleep(1 * time.Second)
}
}
func handleJsonIo(conn *websocket.Conn) {
trafficMutex.Lock()
for _, traf := range traffic {
if !traf.Position_valid { // Don't send unless a valid position exists.
continue
}
trafficJSON, _ := json.Marshal(&traf)
conn.Write(trafficJSON)
}
// Subscribe the socket to receive updates.
trafficUpdate.AddSocket(conn)
weatherRawUpdate.AddSocket(conn)
situationUpdate.AddSocket(conn)
trafficMutex.Unlock()
// Connection closes when function returns. Since uibroadcast is writing and we don't need to read anything (for now), just keep it busy.
for {
buf := make([]byte, 1024)
_, err := conn.Read(buf)
if err != nil {
break
}
if buf[0] != 0 { // Dummy.
continue
}
time.Sleep(1 * time.Second)
}
}
// Works just as weather updates do.
func handleTrafficWS(conn *websocket.Conn) {
trafficMutex.Lock()
for _, traf := range traffic {
if !traf.Position_valid { // Don't send unless a valid position exists.
continue
}
trafficJSON, _ := json.Marshal(&traf)
conn.Write(trafficJSON)
}
// Subscribe the socket to receive updates.
trafficUpdate.AddSocket(conn)
trafficMutex.Unlock()
// Connection closes when function returns. Since uibroadcast is writing and we don't need to read anything (for now), just keep it busy.
for {
buf := make([]byte, 1024)
_, err := conn.Read(buf)
if err != nil {
break
}
if buf[0] != 0 { // Dummy.
continue
}
time.Sleep(1 * time.Second)
}
}
func handleStatusWS(conn *websocket.Conn) {
// log.Printf("Web client connected.\n")
timer := time.NewTicker(1 * time.Second)
for {
<-timer.C
// The below is not used, but should be if something needs to be streamed from the web client ever in the future.
/* var msg SettingMessage
err := websocket.JSON.Receive(conn, &msg)
if err == io.EOF {
break
} else if err != nil {
log.Printf("handleStatusWS: %s\n", err.Error())
} else {
// Use 'msg'.
}
*/
update, _ := json.Marshal(InfoMessage{status:&globalStatus, settings:&globalSettings})
// Send status.
update, _ := json.Marshal(&globalStatus)
_, err := conn.Write(update)
if err != nil {
// log.Printf("Web client disconnected.\n")
// log.Printf("Web client disconnected.\n")
break
}
<-timer.C
}
}
func handleSituationWS(conn *websocket.Conn) {
timer := time.NewTicker(100 * time.Millisecond)
for {
situationJSON, _ := json.Marshal(&mySituation)
_, err := conn.Write(situationJSON)
if err != nil {
break
}
<-timer.C
}
}
// AJAX call - /getStatus. Responds with current global status
// a webservice call for the same data available on the websocket but when only a single update is needed
func handleStatusRequest(w http.ResponseWriter, r *http.Request) {
setNoCache(w)
setJSONHeaders(w)
statusJSON, _ := json.Marshal(&globalStatus)
fmt.Fprintf(w, "%s\n", statusJSON)
}
// AJAX call - /getSituation. Responds with current situation (lat/lon/gdspeed/track/pitch/roll/heading/etc.)
func handleSituationRequest(w http.ResponseWriter, r *http.Request) {
setNoCache(w)
setJSONHeaders(w)
situationJSON, _ := json.Marshal(&mySituation)
fmt.Fprintf(w, "%s\n", situationJSON)
}
// AJAX call - /getTowers. Responds with all ADS-B ground towers that have sent messages that we were able to parse, along with its stats.
func handleTowersRequest(w http.ResponseWriter, r *http.Request) {
setNoCache(w)
setJSONHeaders(w)
ADSBTowerMutex.Lock()
towersJSON, err := json.Marshal(&ADSBTowers)
if err != nil {
log.Printf("Error sending tower JSON data: %s\n", err.Error())
}
// for testing purposes, we can return a fixed reply
// towersJSON = []byte(`{"(38.490880,-76.135554)":{"Lat":38.49087953567505,"Lng":-76.13555431365967,"Signal_strength_last_minute":100,"Signal_strength_max":67,"Messages_last_minute":1,"Messages_total":1059},"(38.978698,-76.309276)":{"Lat":38.97869825363159,"Lng":-76.30927562713623,"Signal_strength_last_minute":495,"Signal_strength_max":32,"Messages_last_minute":45,"Messages_total":83},"(39.179285,-76.668413)":{"Lat":39.17928457260132,"Lng":-76.66841268539429,"Signal_strength_last_minute":50,"Signal_strength_max":24,"Messages_last_minute":1,"Messages_total":16},"(39.666309,-74.315300)":{"Lat":39.66630935668945,"Lng":-74.31529998779297,"Signal_strength_last_minute":9884,"Signal_strength_max":35,"Messages_last_minute":4,"Messages_total":134}}`)
fmt.Fprintf(w, "%s\n", towersJSON)
ADSBTowerMutex.Unlock()
}
// AJAX call - /getSatellites. Responds with all GNSS satellites that are being tracked, along with status information.
func handleSatellitesRequest(w http.ResponseWriter, r *http.Request) {
setNoCache(w)
setJSONHeaders(w)
mySituation.muSatellite.Lock()
satellitesJSON, err := json.Marshal(&Satellites)
if err != nil {
log.Printf("Error sending GNSS satellite JSON data: %s\n", err.Error())
}
fmt.Fprintf(w, "%s\n", satellitesJSON)
mySituation.muSatellite.Unlock()
}
// AJAX call - /getSettings. Responds with all stratux.conf data.
func handleSettingsGetRequest(w http.ResponseWriter, r *http.Request) {
setNoCache(w)
setJSONHeaders(w)
readWiFiUserSettings()
settingsJSON, _ := json.Marshal(&globalSettings)
fmt.Fprintf(w, "%s\n", settingsJSON)
}
// AJAX call - /setSettings. receives via POST command, any/all stratux.conf data.
func handleSettingsSetRequest(w http.ResponseWriter, r *http.Request) {
// define header in support of cross-domain AJAX
setNoCache(w)
setJSONHeaders(w)
w.Header().Set("Access-Control-Allow-Method", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
// for an OPTION method request, we return header without processing.
// this insures we are recognized as supporting cross-domain AJAX REST calls
if r.Method == "POST" {
// raw, _ := httputil.DumpRequest(r, true)
// log.Printf("handleSettingsSetRequest:raw: %s\n", raw)
var resetWiFi bool
decoder := json.NewDecoder(r.Body)
for {
var msg map[string]interface{} // support arbitrary JSON
err := decoder.Decode(&msg)
if err == io.EOF {
break
} else if err != nil {
log.Printf("handleSettingsSetRequest:error: %s\n", err.Error())
} else {
for key, val := range msg {
// log.Printf("handleSettingsSetRequest:json: testing for key:%s of type %s\n", key, reflect.TypeOf(val))
switch key {
case "DarkMode":
globalSettings.DarkMode = val.(bool)
case "UAT_Enabled":
globalSettings.UAT_Enabled = val.(bool)
case "ES_Enabled":
globalSettings.ES_Enabled = val.(bool)
case "Ping_Enabled":
globalSettings.Ping_Enabled = val.(bool)
case "GPS_Enabled":
globalSettings.GPS_Enabled = val.(bool)
case "IMU_Sensor_Enabled":
globalSettings.IMU_Sensor_Enabled = val.(bool)
if !globalSettings.IMU_Sensor_Enabled && globalStatus.IMUConnected {
myIMUReader.Close()
globalStatus.IMUConnected = false
}
case "BMP_Sensor_Enabled":
globalSettings.BMP_Sensor_Enabled = val.(bool)
if !globalSettings.BMP_Sensor_Enabled && globalStatus.BMPConnected {
myPressureReader.Close()
globalStatus.BMPConnected = false
}
case "DEBUG":
globalSettings.DEBUG = val.(bool)
case "DisplayTrafficSource":
globalSettings.DisplayTrafficSource = val.(bool)
case "ReplayLog":
v := val.(bool)
if v != globalSettings.ReplayLog { // Don't mark the files unless there is a change.
globalSettings.ReplayLog = v
}
case "AHRSLog":
globalSettings.AHRSLog = val.(bool)
case "IMUMapping":
if globalSettings.IMUMapping != val.([2]int) {
globalSettings.IMUMapping = val.([2]int)
myIMUReader.Close()
globalStatus.IMUConnected = false // Force a restart of the IMU reader
}
case "PPM":
globalSettings.PPM = int(val.(float64))
case "Baud":
if serialOut, ok := globalSettings.SerialOutputs["/dev/serialout0"]; ok { //FIXME: Only one device for now.
newBaud := int(val.(float64))
if newBaud == serialOut.Baud { // Same baud rate. No change.
continue
}
log.Printf("changing /dev/serialout0 baud rate from %d to %d.\n", serialOut.Baud, newBaud)
serialOut.Baud = newBaud
// Close the port if it is open.
if serialOut.serialPort != nil {
log.Printf("closing /dev/serialout0 for baud rate change.\n")
serialOut.serialPort.Close()
serialOut.serialPort = nil
}
globalSettings.SerialOutputs["/dev/serialout0"] = serialOut
}
case "WatchList":
globalSettings.WatchList = val.(string)
case "GLimits":
globalSettings.GLimits = val.(string)
case "OwnshipModeS":
// Expecting a hex string less than 6 characters (24 bits) long.
if len(val.(string)) > 6 { // Too long.
continue
}
// Pad string, must be 6 characters long.
vals := strings.ToUpper(val.(string))
for len(vals) < 6 {
vals = "0" + vals
}
hexn, err := hex.DecodeString(vals)
if err != nil { // Number not valid.
log.Printf("handleSettingsSetRequest:OwnshipModeS: %s\n", err.Error())
continue
}
globalSettings.OwnshipModeS = fmt.Sprintf("%02X%02X%02X", hexn[0], hexn[1], hexn[2])
case "StaticIps":
ipsStr := val.(string)
ips := strings.Split(ipsStr, " ")
if ipsStr == "" {
ips = make([]string, 0)
}
re, _ := regexp.Compile(`^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`)
err := ""
for _, ip := range ips {
// Verify IP format
if !re.MatchString(ip) {
err = err + "Invalid IP: " + ip + ". "
}
}
if err != "" {
log.Printf("handleSettingsSetRequest:StaticIps: %s\n", err)
continue
}
globalSettings.StaticIps = ips
case "WiFiSSID":
globalSettings.WiFiSSID = val.(string)
resetWiFi = true
case "WiFiChannel":
globalSettings.WiFiChannel = int(val.(float64))
resetWiFi = true
case "WiFiSecurityEnabled":
globalSettings.WiFiSecurityEnabled = val.(bool)
resetWiFi = true
case "WiFiPassphrase":
globalSettings.WiFiPassphrase = val.(string)
resetWiFi = true
case "WiFiSmartEnabled":
globalSettings.WiFiSmartEnabled = val.(bool)
resetWiFi = true
default:
log.Printf("handleSettingsSetRequest:json: unrecognized key:%s\n", key)
}
}
saveSettings()
if resetWiFi {
saveWiFiUserSettings()
go func() {
time.Sleep(time.Second)
cmd := exec.Command("ifdown", "wlan0")
if err := cmd.Start(); err != nil {
log.Printf("Error shutting down WiFi: %s\n", err.Error())
}
if err = cmd.Wait(); err != nil {
log.Printf("Error shutting down WiFi: %s\n", err.Error())
}
cmd = exec.Command("ifup", "wlan0")
if err := cmd.Start(); err != nil {
log.Printf("Error starting WiFi: %s\n", err.Error())
}
if err = cmd.Wait(); err != nil {
log.Printf("Error starting WiFi: %s\n", err.Error())
}
}()
}
}
}
// while it may be redundant, we return the latest settings
settingsJSON, _ := json.Marshal(&globalSettings)
fmt.Fprintf(w, "%s\n", settingsJSON)
}
}
func handleShutdownRequest(w http.ResponseWriter, r *http.Request) {
syscall.Sync()
gracefulShutdown()
syscall.Reboot(syscall.LINUX_REBOOT_CMD_POWER_OFF)
}
func doReboot() {
syscall.Sync()
gracefulShutdown()
syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART)
}
func handleDeleteLogFile(w http.ResponseWriter, r *http.Request) {
log.Println("handleDeleteLogFile called!!!")
clearDebugLogFile()
}
func handleDeleteAHRSLogFiles(w http.ResponseWriter, r *http.Request) {
files, err := ioutil.ReadDir("/var/log")
if err != nil {
http.Error(w, fmt.Sprintf("error deleting AHRS logs: %s", err), http.StatusNotFound)
return
}
var fn string
for _, f := range files {
fn = f.Name()
if v, _ := filepath.Match("sensors_*.csv", fn); v {
os.Remove("/var/log/" + fn)
log.Printf("Deleting AHRS log file %s\n", fn)
}
analysisLogger = nil
}
}
func handleDevelModeToggle(w http.ResponseWriter, r *http.Request) {
log.Printf("handleDevelModeToggle called!!!\n")
globalSettings.DeveloperMode = true
saveSettings()
}
func handleRestartRequest(w http.ResponseWriter, r *http.Request) {
log.Printf("handleRestartRequest called\n")
go doRestartApp()
}
func handleRebootRequest(w http.ResponseWriter, r *http.Request) {
setNoCache(w)
setJSONHeaders(w)
w.Header().Set("Access-Control-Allow-Method", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
go delayReboot()
}
func handleOrientAHRS(w http.ResponseWriter, r *http.Request) {
// define header in support of cross-domain AJAX
setNoCache(w)
w.Header().Set("Content-Type", "text/plain")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Method", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
// For an OPTION method request, we return header without processing.
// This ensures we are recognized as supporting cross-domain AJAX REST calls.
if r.Method == "POST" {
var (
action []byte = make([]byte, 1)
err error
)
if _, err = r.Body.Read(action); err != nil {
log.Println("AHRS Error: handleOrientAHRS received invalid request")
http.Error(w, "orientation received invalid request", http.StatusBadRequest)
}
switch action[0] {
case 'f': // Set sensor "forward" direction (toward nose of airplane).
f, err := getMinAccelDirection()
if err != nil {
log.Printf("AHRS Error: sensor orientation: couldn't read accelerometer: %s\n", err)
http.Error(w, fmt.Sprintf("couldn't read accelerometer: %s\n", err), http.StatusBadRequest)
return
}
log.Printf("AHRS Info: sensor orientation success! forward axis is %d\n", f)
globalSettings.IMUMapping = [2]int{f, 0}
case 'd': // Set sensor "up" direction (toward top of airplane).
globalSettings.SensorQuaternion = [4]float64{0, 0, 0, 0}
saveSettings()
myIMUReader.Close()
globalStatus.IMUConnected = false // restart the processes depending on the orientation
ResetAHRSGLoad()
time.Sleep(2000 * time.Millisecond)
}
}
}
func handleManagementConnection(conn *websocket.Conn) {
// log.Printf("Web client connected.\n")
go statusSender(conn)
func handleCageAHRS(w http.ResponseWriter, r *http.Request) {
// define header in support of cross-domain AJAX
setNoCache(w)
w.Header().Set("Content-Type", "text/plain")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Method", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
for {
var msg SettingMessage
err := websocket.JSON.Receive(conn, &msg)
if err == io.EOF {
break
} else if err != nil {
log.Printf("handleManagementConnection: %s\n", err.Error())
} else {
if msg.Setting == "UAT_Enabled" {
globalSettings.UAT_Enabled = msg.Value
}
if msg.Setting == "ES_Enabled" {
globalSettings.ES_Enabled = msg.Value
}
if msg.Setting == "GPS_Enabled" {
globalSettings.GPS_Enabled = msg.Value
}
if msg.Setting == "AHRS_Enabled" {
globalSettings.AHRS_Enabled = msg.Value
}
if msg.Setting == "DEBUG" {
globalSettings.DEBUG = msg.Value
}
// For an OPTION method request, we return header without processing.
// This ensures we are recognized as supporting cross-domain AJAX REST calls.
if r.Method == "POST" {
CageAHRS()
}
}
saveSettings()
func handleCalibrateAHRS(w http.ResponseWriter, r *http.Request) {
// define header in support of cross-domain AJAX
setNoCache(w)
w.Header().Set("Content-Type", "text/plain")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Method", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
// For an OPTION method request, we return header without processing.
// This ensures we are recognized as supporting cross-domain AJAX REST calls.
if r.Method == "POST" {
CalibrateAHRS()
}
}
func handleResetGMeter(w http.ResponseWriter, r *http.Request) {
// define header in support of cross-domain AJAX
setNoCache(w)
w.Header().Set("Content-Type", "text/plain")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Method", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
// For an OPTION method request, we return header without processing.
// This ensures we are recognized as supporting cross-domain AJAX REST calls.
if r.Method == "POST" {
ResetAHRSGLoad()
}
}
func doRestartApp() {
time.Sleep(1)
syscall.Sync()
out, err := exec.Command("/bin/systemctl", "restart", "stratux").Output()
if err != nil {
log.Printf("restart error: %s\n%s", err.Error(), out)
} else {
log.Printf("restart: %s\n", out)
}
}
// AJAX call - /getClients. Responds with all connected clients.
func handleClientsGetRequest(w http.ResponseWriter, r *http.Request) {
setNoCache(w)
setJSONHeaders(w)
netMutex.Lock()
clientsJSON, _ := json.Marshal(&outSockets)
netMutex.Unlock()
fmt.Fprintf(w, "%s\n", clientsJSON)
}
func delayReboot() {
time.Sleep(1 * time.Second)
doReboot()
}
func handleDownloadLogRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", "attachment; filename='stratux.log'")
http.ServeFile(w, r, "/var/log/stratux.log")
}
func handleDownloadAHRSLogsRequest(w http.ResponseWriter, r *http.Request) {
// Common error handler
httpErr := func(w http.ResponseWriter, e error) {
http.Error(w, fmt.Sprintf("error zipping AHRS logs: %s", e), http.StatusNotFound)
}
files, err := ioutil.ReadDir("/var/log")
if err != nil {
httpErr(w, err)
return
}
z := zip.NewWriter(w)
defer z.Close()
for _, f := range files {
fn := f.Name()
v1, _ := filepath.Match("sensors_*.csv", fn)
v2, _ := filepath.Match("stratux.log", fn)
if !(v1 || v2) {
continue
}
unzippedFile, err := os.Open("/var/log/" + fn)
if err != nil {
httpErr(w, err)
return
}
fh, err := zip.FileInfoHeader(f)
if err != nil {
httpErr(w, err)
return
}
zippedFile, err := z.CreateHeader(fh)
if err != nil {
httpErr(w, err)
return
}
_, err = io.Copy(zippedFile, unzippedFile)
if err != nil {
httpErr(w, err)
return
}
}
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", "attachment; filename=\"ahrs_logs.zip\"")
}
func handleDownloadDBRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", "attachment; filename='stratux.sqlite'")
http.ServeFile(w, r, "/var/log/stratux.sqlite")
}
// Upload an update file.
func handleUpdatePostRequest(w http.ResponseWriter, r *http.Request) {
setNoCache(w)
setJSONHeaders(w)
r.ParseMultipartForm(1024 * 1024 * 32) // ~32MB update.
file, handler, err := r.FormFile("update_file")
if err != nil {
log.Printf("Update failed from %s (%s).\n", r.RemoteAddr, err.Error())
return
}
defer file.Close()
// Special hardware builds. Don't allow an update unless the filename contains the hardware build name.
if (len(globalStatus.HardwareBuild) > 0) && !strings.Contains(strings.ToLower(handler.Filename), strings.ToLower(globalStatus.HardwareBuild)) {
w.WriteHeader(404)
return
}
updateFile := fmt.Sprintf("/root/update-stratux-v.sh")
f, err := os.OpenFile(updateFile, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Printf("Update failed from %s (%s).\n", r.RemoteAddr, err.Error())
return
}
defer f.Close()
io.Copy(f, file)
log.Printf("%s uploaded %s for update.\n", r.RemoteAddr, updateFile)
// Successful update upload. Now reboot.
go delayReboot()
}
func setNoCache(w http.ResponseWriter) {
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "0")
}
func setJSONHeaders(w http.ResponseWriter) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json")
}
func defaultServer(w http.ResponseWriter, r *http.Request) {
// setNoCache(w)
http.FileServer(http.Dir("/var/www")).ServeHTTP(w, r)
}
func handleroPartitionRebuild(w http.ResponseWriter, r *http.Request) {
out, err := exec.Command("/usr/sbin/rebuild_ro_part.sh").Output()
if err != nil {
addSingleSystemErrorf("partition-rebuild", "Rebuild RO Partition error: %s", err.Error())
} else {
addSingleSystemErrorf("partition-rebuild", "Rebuild RO Partition success: %s", out)
}
}
// https://gist.github.com/alexisrobert/982674.
// Copyright (c) 2010-2014 Alexis ROBERT <alexis.robert@gmail.com>.
const dirlisting_tpl = `<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<!-- Modified from lighttpd directory listing -->
<head>
<title>Index of {{.Name}}</title>
<style type="text/css">
a, a:active {text-decoration: none; color: blue;}
a:visited {color: #48468F;}
a:hover, a:focus {text-decoration: underline; color: red;}
body {background-color: #F5F5F5;}
h2 {margin-bottom: 12px;}
table {margin-left: 12px;}
th, td { font: 90% monospace; text-align: left;}
th { font-weight: bold; padding-right: 14px; padding-bottom: 3px;}
td {padding-right: 14px;}
td.s, th.s {text-align: right;}
div.list { background-color: white; border-top: 1px solid #646464; border-bottom: 1px solid #646464; padding-top: 10px; padding-bottom: 14px;}
div.foot { font: 90% monospace; color: #787878; padding-top: 4px;}
</style>
</head>
<body>
<h2>Index of {{.Name}}</h2>
<div class="list">
<table summary="Directory Listing" cellpadding="0" cellspacing="0">
<thead><tr><th class="n">Name</th><th>Last Modified</th><th>Size (bytes)</th><th class="dl">Options</th></tr></thead>
<tbody>
{{range .Children_files}}
<tr><td class="n"><a href="/logs/stratux/{{.Name}}">{{.Name}}</a></td><td>{{.Mtime}}</td><td>{{.Size}}</td><td class="dl"><a href="/logs/stratux/{{.Name}}">Download</a></td></tr>
{{end}}
</tbody>
</table>
</div>
<div class="foot">{{.ServerUA}}</div>
</body>
</html>`
type fileInfo struct {
Name string
Mtime string
Size string
}
// Manages directory listings
type dirlisting struct {
Name string
Children_files []fileInfo
ServerUA string
}
//FIXME: This needs to be switched to show a "sessions log" from the sqlite database.
func viewLogs(w http.ResponseWriter, r *http.Request) {
names, err := ioutil.ReadDir("/var/log/stratux/")
if err != nil {
return
}
fi := make([]fileInfo, 0)
for _, val := range names {
if val.Name()[0] == '.' {
continue
} // Remove hidden files from listing
if !val.IsDir() {
mtime := val.ModTime().Format("2006-Jan-02 15:04:05")
sz := humanize.Comma(val.Size())
fi = append(fi, fileInfo{Name: val.Name(), Mtime: mtime, Size: sz})
}
}
tpl, err := template.New("tpl").Parse(dirlisting_tpl)
if err != nil {
return
}
data := dirlisting{Name: r.URL.Path, ServerUA: "Stratux " + stratuxVersion + "/" + stratuxBuild,
Children_files: fi}
err = tpl.Execute(w, data)
if err != nil {
log.Printf("viewLogs() error: %s\n", err.Error())
}
}
func managementInterface() {
http.Handle("/", http.FileServer(http.Dir("/var/www")))
weatherUpdate = NewUIBroadcaster()
trafficUpdate = NewUIBroadcaster()
situationUpdate = NewUIBroadcaster()
weatherRawUpdate = NewUIBroadcaster()
gdl90Update = NewUIBroadcaster()
http.HandleFunc("/", defaultServer)
http.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log"))))
http.HandleFunc("/control",
http.HandleFunc("/view_logs/", viewLogs)
http.HandleFunc("/gdl90",
func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{
Handler: websocket.Handler(handleManagementConnection)}
Handler: websocket.Handler(handleGDL90WS)}
s.ServeHTTP(w, req)
})
http.HandleFunc("/status",
func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{
Handler: websocket.Handler(handleStatusWS)}
s.ServeHTTP(w, req)
})
http.HandleFunc("/situation",
func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{
Handler: websocket.Handler(handleSituationWS)}
s.ServeHTTP(w, req)
})
http.HandleFunc("/weather",
func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{
Handler: websocket.Handler(handleWeatherWS)}
s.ServeHTTP(w, req)
})
http.HandleFunc("/traffic",
func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{
Handler: websocket.Handler(handleTrafficWS)}
s.ServeHTTP(w, req)
})
http.HandleFunc("/jsonio",
func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{
Handler: websocket.Handler(handleJsonIo)}
s.ServeHTTP(w, req)
})
http.HandleFunc("/getStatus", handleStatusRequest)
http.HandleFunc("/getSituation", handleSituationRequest)
http.HandleFunc("/getTowers", handleTowersRequest)
http.HandleFunc("/getSatellites", handleSatellitesRequest)
http.HandleFunc("/getSettings", handleSettingsGetRequest)
http.HandleFunc("/setSettings", handleSettingsSetRequest)
http.HandleFunc("/restart", handleRestartRequest)
http.HandleFunc("/shutdown", handleShutdownRequest)
http.HandleFunc("/reboot", handleRebootRequest)
http.HandleFunc("/getClients", handleClientsGetRequest)
http.HandleFunc("/updateUpload", handleUpdatePostRequest)
http.HandleFunc("/roPartitionRebuild", handleroPartitionRebuild)
http.HandleFunc("/develmodetoggle", handleDevelModeToggle)
http.HandleFunc("/orientAHRS", handleOrientAHRS)
http.HandleFunc("/calibrateAHRS", handleCalibrateAHRS)
http.HandleFunc("/cageAHRS", handleCageAHRS)
http.HandleFunc("/resetGMeter", handleResetGMeter)
http.HandleFunc("/deletelogfile", handleDeleteLogFile)
http.HandleFunc("/downloadlog", handleDownloadLogRequest)
http.HandleFunc("/deleteahrslogfiles", handleDeleteAHRSLogFiles)
http.HandleFunc("/downloadahrslogs", handleDownloadAHRSLogsRequest)
http.HandleFunc("/downloaddb", handleDownloadDBRequest)
err := http.ListenAndServe(managementAddr, nil)

66
main/monotonic.go 100644
Wyświetl plik

@ -0,0 +1,66 @@
/*
Copyright (c) 2015-2016 Christopher Young
Distributable under the terms of The "BSD New" License
that can be found in the LICENSE file, herein included
as part of this header.
Modifications (c) 2016 AvSquirrel (https://github.com/AvSquirrel)
monotonic.go: Create monotonic clock using time.Timer - necessary because of real time clock changes on RPi.
*/
package main
import (
humanize "github.com/dustin/go-humanize"
"time"
)
// Timer (since start).
type monotonic struct {
Milliseconds uint64
Time time.Time
ticker *time.Ticker
realTimeSet bool
RealTime time.Time
}
func (m *monotonic) Watcher() {
for {
<-m.ticker.C
m.Milliseconds += 10
m.Time = m.Time.Add(10 * time.Millisecond)
if m.realTimeSet {
m.RealTime = m.RealTime.Add(10 * time.Millisecond)
}
}
}
func (m *monotonic) Since(t time.Time) time.Duration {
return m.Time.Sub(t)
}
func (m *monotonic) HumanizeTime(t time.Time) string {
return humanize.RelTime(t, m.Time, "ago", "from now")
}
func (m *monotonic) Unix() int64 {
return int64(m.Since(time.Time{}).Seconds())
}
func (m *monotonic) HasRealTimeReference() bool {
return m.realTimeSet
}
func (m *monotonic) SetRealTimeReference(t time.Time) {
if !m.realTimeSet { // Only allow the real clock to be set once.
m.RealTime = t
m.realTimeSet = true
}
}
func NewMonotonic() *monotonic {
t := &monotonic{Milliseconds: 0, Time: time.Time{}, ticker: time.NewTicker(10 * time.Millisecond)}
go t.Watcher()
return t
}

Wyświetl plik

@ -1,11 +1,21 @@
/*
Copyright (c) 2015-2016 Christopher Young
Distributable under the terms of The "BSD New" License
that can be found in the LICENSE file, herein included
as part of this header.
network.go: Client networking routines, DHCP lease monitoring, queue management, ICMP monitoring.
*/
package main
import (
"github.com/tarm/serial"
"golang.org/x/net/icmp"
"golang.org/x/net/internal/iana"
"golang.org/x/net/ipv4"
"io/ioutil"
"log"
"math"
"math/rand"
"net"
"os"
@ -23,35 +33,60 @@ type networkMessage struct {
}
type networkConnection struct {
Conn *net.UDPConn
Ip string
Port uint32
Capability uint8
messageQueue [][]byte // Device message queue.
Conn *net.UDPConn
Ip string
Port uint32
Capability uint8
messageQueue [][]byte // Device message queue.
MessageQueueLen int // Length of the message queue. For debugging.
/*
Sleep mode/throttle variables. "sleep mode" is actually now just a very reduced packet rate, since we don't know positively
when a client is ready to accept packets - we just assume so if we don't receive ICMP Unreachable packets in 5 secs.
*/
lastUnreachable time.Time // Last time the device sent an ICMP Unreachable packet.
LastUnreachable time.Time // Last time the device sent an ICMP Unreachable packet.
nextMessageTime time.Time // The next time that the device is "able" to receive a message.
numOverflows uint32 // Number of times the queue has overflowed - for calculating the amount to chop off from the queue.
SleepFlag bool // Whether or not this client has been marked as sleeping - only used for debugging (relies on messages being sent to update this flag in sendToAllConnectedClients()).
FFCrippled bool
}
type serialConnection struct {
DeviceString string
Baud int
serialPort *serial.Port
}
var messageQueue chan networkMessage
var outSockets map[string]networkConnection
var dhcpLeases map[string]string
var netMutex *sync.Mutex
var pingResponse map[string]time.Time // Last time an IP responded to an "echo" response.
var netMutex *sync.Mutex // netMutex needs to be locked before accessing dhcpLeases, pingResponse, and outSockets and calling isSleeping() and isThrottled().
var totalNetworkMessagesSent uint32
const (
NETWORK_GDL90_STANDARD = 1
NETWORK_AHRS_FFSIM = 2
NETWORK_AHRS_GDL90 = 4
dhcp_lease_file = "/var/lib/dhcp/dhcpd.leases"
dhcp_lease_dir = "/var/lib/dhcp"
extra_hosts_file = "/etc/stratux-static-hosts.conf"
)
var dhcpLeaseDirectoryLastTest time.Time // Last time fsWriteTest() was run on the DHCP lease directory.
// Read the "dhcpd.leases" file and parse out IP/hostname.
func getDHCPLeases() (map[string]string, error) {
// Do a write test. Even if we are able to read the file, it may be out of date because there's a fs write issue.
// Only perform the test once every 5 minutes to minimize writes.
if stratuxClock.Since(dhcpLeaseDirectoryLastTest) >= 5*time.Minute {
err := fsWriteTest(dhcp_lease_dir)
if err != nil {
addSingleSystemErrorf("fs-write", "Write error on '%s', your EFB may have issues receiving weather and traffic.", dhcp_lease_dir)
}
dhcpLeaseDirectoryLastTest = stratuxClock.Time
}
dat, err := ioutil.ReadFile(dhcp_lease_file)
ret := make(map[string]string)
if err != nil {
@ -74,58 +109,218 @@ func getDHCPLeases() (map[string]string, error) {
ret[block_ip] = ""
}
}
// Add IP's set through the settings page
if globalSettings.StaticIps != nil {
for _, ip := range globalSettings.StaticIps {
ret[ip] = ""
}
}
// Added the ability to have static IP hosts stored in /etc/stratux-static-hosts.conf
dat2, err := ioutil.ReadFile(extra_hosts_file)
if err != nil {
return ret, nil
}
iplines := strings.Split(string(dat2), "\n")
block_ip2 := ""
for _, ipline := range iplines {
spacedip := strings.Split(ipline, " ")
if len(spacedip) == 2 {
// The ip is in block_ip2
block_ip2 = spacedip[0]
// the hostname is here
ret[block_ip2] = spacedip[1]
}
}
return ret, nil
}
/*
isSleeping().
Check if a client identifier 'ip:port' is in either a sleep or active state.
***WARNING***: netMutex must be locked before calling this function.
*/
func isSleeping(k string) bool {
if globalSettings.NoSleep == true {
return false
}
ipAndPort := strings.Split(k, ":")
lastPing, ok := pingResponse[ipAndPort[0]]
// No ping response. Assume disconnected/sleeping device.
if !ok || time.Since(lastPing) > (10*time.Second) {
if lastPing, ok := pingResponse[ipAndPort[0]]; !ok || stratuxClock.Since(lastPing) > (10*time.Second) {
return true
}
if time.Since(outSockets[k].lastUnreachable) < (5 * time.Second) {
if stratuxClock.Since(outSockets[k].LastUnreachable) < (5 * time.Second) {
return true
}
return false
}
// Throttle mode for testing port open and giving some start-up time to the app.
// Throttling is 0.1% data rate for first 15 seconds.
/*
isThrottled().
Checks if a client identifier 'ip:port' is throttled.
Throttle mode is for testing port open and giving some start-up time to the app.
Throttling is 0.1% data rate for first 15 seconds.
***WARNING***: netMutex must be locked before calling this function.
*/
func isThrottled(k string) bool {
return (rand.Int()%1000 != 0) && time.Since(outSockets[k].lastUnreachable) < (15*time.Second)
return (rand.Int()%1000 != 0) && stratuxClock.Since(outSockets[k].LastUnreachable) < (15*time.Second)
}
func sendToAllConnectedClients(msg networkMessage) {
if (msg.msgType & NETWORK_GDL90_STANDARD) != 0 {
// It's a GDL90 message. Send to serial output channel (which may or may not cause something to happen).
serialOutputChan <- msg.msg
networkGDL90Chan <- msg.msg
}
netMutex.Lock()
defer netMutex.Unlock()
for k, netconn := range outSockets {
sleepFlag := isSleeping(k)
netconn.SleepFlag = sleepFlag
outSockets[k] = netconn
// Check if this port is able to accept the type of message we're sending.
if (netconn.Capability & msg.msgType) == 0 {
continue
}
// Send non-queueable messages immediately, or discard if the client is in sleep mode.
if !sleepFlag {
netconn.numOverflows = 0 // Reset the overflow counter whenever the client is not sleeping so that we're not penalizing future sleepmodes.
}
if !msg.queueable {
if !isSleeping(k) {
netconn.Conn.Write(msg.msg) // Write immediately.
if sleepFlag {
continue
}
netconn.Conn.Write(msg.msg) // Write immediately.
totalNetworkMessagesSent++
globalStatus.NetworkDataMessagesSent++
globalStatus.NetworkDataMessagesSentNonqueueable++
globalStatus.NetworkDataBytesSent += uint64(len(msg.msg))
globalStatus.NetworkDataBytesSentNonqueueable += uint64(len(msg.msg))
} else {
// Queue the message if the message is "queueable".
if len(netconn.messageQueue) >= maxUserMsgQueueSize { // Too many messages queued? Drop the oldest.
log.Printf("%s:%d - message queue overflow.\n", netconn.Ip, netconn.Port)
netconn.messageQueue = netconn.messageQueue[1 : maxUserMsgQueueSize-1]
netconn.numOverflows++
s := 2 * netconn.numOverflows // Double the amount we chop off on each overflow.
if int(s) >= len(netconn.messageQueue) {
netconn.messageQueue = make([][]byte, 0)
} else {
netconn.messageQueue = netconn.messageQueue[s:]
}
}
netconn.messageQueue = append(netconn.messageQueue, msg.msg)
netconn.messageQueue = append(netconn.messageQueue, msg.msg) // each netconn.messageQueue is therefore an array (well, a slice) of formatted GDL90 messages
outSockets[k] = netconn
}
}
}
// Just returns the number of DHCP leases for now.
func getNetworkStats() uint {
ret := uint(len(dhcpLeases))
globalStatus.Connected_Users = ret
return ret
var serialOutputChan chan []byte
var networkGDL90Chan chan []byte
func networkOutWatcher() {
for {
ch := <-networkGDL90Chan
gdl90Update.SendJSON(ch)
}
}
// Monitor serial output channel, send to serial port.
func serialOutWatcher() {
// Check every 30 seconds for a serial output device.
serialTicker := time.NewTicker(30 * time.Second)
serialDev := "/dev/serialout0" //FIXME: This is temporary. Only one serial output device for now.
for {
select {
case <-serialTicker.C:
if _, err := os.Stat(serialDev); !os.IsNotExist(err) { // Check if the device file exists.
var thisSerialConn serialConnection
// Check if we need to start handling a new device.
if val, ok := globalSettings.SerialOutputs[serialDev]; !ok {
newSerialOut := serialConnection{DeviceString: serialDev, Baud: 38400}
log.Printf("detected new serial output, setting up now: %s. Default baudrate 38400.\n", serialDev)
if globalSettings.SerialOutputs == nil {
globalSettings.SerialOutputs = make(map[string]serialConnection)
}
globalSettings.SerialOutputs[serialDev] = newSerialOut
saveSettings()
thisSerialConn = newSerialOut
} else {
thisSerialConn = val
}
// Check if we need to open the connection now.
if thisSerialConn.serialPort == nil {
cfg := &serial.Config{Name: thisSerialConn.DeviceString, Baud: thisSerialConn.Baud}
p, err := serial.OpenPort(cfg)
if err != nil {
log.Printf("serialout port (%s) err: %s\n", thisSerialConn.DeviceString, err.Error())
break // We'll attempt again in 30 seconds.
} else {
log.Printf("opened serialout: Name: %s, Baud: %d\n", thisSerialConn.DeviceString, thisSerialConn.Baud)
}
// Save the serial port connection.
thisSerialConn.serialPort = p
globalSettings.SerialOutputs[serialDev] = thisSerialConn
}
}
case b := <-serialOutputChan:
if val, ok := globalSettings.SerialOutputs[serialDev]; ok {
if val.serialPort != nil {
_, err := val.serialPort.Write(b)
if err != nil { // Encountered an error in writing to the serial port. Close it and set Serial_out_enabled.
log.Printf("serialout (%s) port err: %s. Closing port.\n", val.DeviceString, err.Error())
val.serialPort.Close()
val.serialPort = nil
globalSettings.SerialOutputs[serialDev] = val
}
}
}
}
}
}
// Returns the number of DHCP leases and prints queue lengths.
func getNetworkStats() {
netMutex.Lock()
defer netMutex.Unlock()
var numNonSleepingClients uint
for k, netconn := range outSockets {
queueBytes := 0
for _, msg := range netconn.messageQueue {
queueBytes += len(msg)
}
if globalSettings.DEBUG {
log.Printf("On %s:%d, Queue length = %d messages / %d bytes\n", netconn.Ip, netconn.Port, len(netconn.messageQueue), queueBytes)
}
ipAndPort := strings.Split(k, ":")
if len(ipAndPort) != 2 {
continue
}
ip := ipAndPort[0]
if pingRespTime, ok := pingResponse[ip]; ok {
// Don't count the ping time if it is the same as stratuxClock epoch.
// If the client has responded to a ping in the last 15 minutes, count it as "connected" or "recent".
if !pingRespTime.Equal(time.Time{}) && stratuxClock.Since(pingRespTime) < 15*time.Minute {
numNonSleepingClients++
}
}
}
globalStatus.Connected_Users = numNonSleepingClients
}
// See who has a DHCP lease and make a UDP connection to each of them.
@ -172,21 +367,86 @@ func refreshConnectedClients() {
}
func messageQueueSender() {
secondTimer := time.NewTicker(5 * time.Second)
queueTimer := time.NewTicker(400 * time.Microsecond) // 2500 msg/sec
secondTimer := time.NewTicker(15 * time.Second) // getNetworkStats().
queueTimer := time.NewTicker(100 * time.Millisecond)
var lastQueueTimeChange time.Time // Reevaluate send frequency every 5 seconds.
for {
select {
case msg := <-messageQueue:
sendToAllConnectedClients(msg)
case <-queueTimer.C:
netMutex.Lock()
averageSendableQueueSize := float64(0.0)
for k, netconn := range outSockets {
if len(netconn.messageQueue) > 0 && !isSleeping(k) && !isThrottled(k) {
tmpConn := netconn
tmpConn.Conn.Write(tmpConn.messageQueue[0])
tmpConn.messageQueue = tmpConn.messageQueue[1:]
outSockets[k] = tmpConn
averageSendableQueueSize += float64(len(netconn.messageQueue)) // Add num sendable messages.
var queuedMsg []byte
// Combine the first 256 entries in netconn.messageQueue to avoid flooding wlan0 with too many IOPS.
// Need to play nice with non-queued messages, so this limits the number of entries to combine.
// UAT uplink block is 432 bytes, so transmit block size shouldn't be larger than 108 KiB. 10 Mbps per device would therefore be needed to send within a 100 ms window.
mqDepth := len(netconn.messageQueue)
if mqDepth > 256 {
mqDepth = 256
}
for j := 0; j < mqDepth; j++ {
queuedMsg = append(queuedMsg, netconn.messageQueue[j]...)
}
/*
for j, _ := range netconn.messageQueue {
queuedMsg = append(queuedMsg, netconn.messageQueue[j]...)
}
*/
netconn.Conn.Write(queuedMsg)
totalNetworkMessagesSent++
globalStatus.NetworkDataMessagesSent++
globalStatus.NetworkDataBytesSent += uint64(len(queuedMsg))
//netconn.messageQueue = [][]byte{}
if mqDepth < len(netconn.messageQueue) {
netconn.messageQueue = netconn.messageQueue[mqDepth:]
} else {
netconn.messageQueue = [][]byte{}
}
outSockets[k] = netconn
/*
tmpConn := netconn
tmpConn.Conn.Write(tmpConn.messageQueue[0])
totalNetworkMessagesSent++
globalStatus.NetworkDataMessagesSent++
globalStatus.NetworkDataBytesSent += uint64(len(tmpConn.messageQueue[0]))
tmpConn.messageQueue = tmpConn.messageQueue[1:]
outSockets[k] = tmpConn
*/
}
netconn.MessageQueueLen = len(netconn.messageQueue)
outSockets[k] = netconn
}
if stratuxClock.Since(lastQueueTimeChange) >= 5*time.Second {
var pd float64
if averageSendableQueueSize > 0.0 && len(outSockets) > 0 {
averageSendableQueueSize = averageSendableQueueSize / float64(len(outSockets)) // It's a total, not an average, up until this point.
pd = math.Max(float64(1.0/750.0), float64(1.0/(4.0*averageSendableQueueSize))) // Say 250ms is enough to get through the whole queue.
} else {
pd = float64(0.1) // 100ms.
}
if globalSettings.DEBUG {
log.Printf("Average sendable queue is %v messages. Changing queue timer to %f seconds\n", averageSendableQueueSize, pd)
}
queueTimer.Stop()
queueTimer = time.NewTicker(time.Duration(pd*1000000000.0) * time.Nanosecond)
lastQueueTimeChange = stratuxClock.Time
}
netMutex.Unlock()
case <-secondTimer.C:
@ -196,7 +456,7 @@ func messageQueueSender() {
}
func sendMsg(msg []byte, msgType uint8, queueable bool) {
messageQueue <- networkMessage{msg: msg, msgType: msgType, queueable: queueable, ts: time.Now()}
messageQueue <- networkMessage{msg: msg, msgType: msgType, queueable: queueable, ts: stratuxClock.Time}
}
func sendGDL90(msg []byte, queueable bool) {
@ -204,7 +464,6 @@ func sendGDL90(msg []byte, queueable bool) {
}
func monitorDHCPLeases() {
//TODO: inotify or dhcp event hook.
timer := time.NewTicker(30 * time.Second)
for {
select {
@ -218,6 +477,7 @@ func icmpEchoSender(c *icmp.PacketConn) {
timer := time.NewTicker(5 * time.Second)
for {
<-timer.C
netMutex.Lock()
// Collect IPs.
ips := make(map[string]bool)
for k, _ := range outSockets {
@ -242,7 +502,9 @@ func icmpEchoSender(c *icmp.PacketConn) {
log.Printf("couldn't send ICMP Echo: %s\n", err.Error())
continue
}
totalNetworkMessagesSent++
}
netMutex.Unlock()
}
}
@ -262,7 +524,7 @@ func sleepMonitor() {
log.Printf("%s\n", err.Error())
continue
}
msg, err := icmp.ParseMessage(iana.ProtocolICMP, buf[:n])
msg, err := icmp.ParseMessage(1, buf[:n])
if err != nil {
continue
}
@ -271,7 +533,9 @@ func sleepMonitor() {
// Look for echo replies, mark it as received.
if msg.Type == ipv4.ICMPTypeEchoReply {
pingResponse[ip] = time.Now()
netMutex.Lock()
pingResponse[ip] = stratuxClock.Time
netMutex.Unlock()
continue // No further processing needed.
}
@ -280,7 +544,7 @@ func sleepMonitor() {
continue
}
// Packet parsing.
mb, err := msg.Body.Marshal(iana.ProtocolICMP)
mb, err := msg.Body.Marshal(1)
if err != nil {
continue
}
@ -299,14 +563,87 @@ func sleepMonitor() {
netMutex.Unlock()
continue
}
p.lastUnreachable = time.Now()
p.LastUnreachable = stratuxClock.Time
outSockets[ipAndPort] = p
netMutex.Unlock()
}
}
func networkStatsCounter() {
timer := time.NewTicker(1 * time.Second)
var previousNetworkMessagesSent, previousNetworkBytesSent, previousNetworkMessagesSentNonqueueable, previousNetworkBytesSentNonqueueable uint64
for {
<-timer.C
globalStatus.NetworkDataMessagesSentLastSec = globalStatus.NetworkDataMessagesSent - previousNetworkMessagesSent
globalStatus.NetworkDataBytesSentLastSec = globalStatus.NetworkDataBytesSent - previousNetworkBytesSent
globalStatus.NetworkDataMessagesSentNonqueueableLastSec = globalStatus.NetworkDataMessagesSentNonqueueable - previousNetworkMessagesSentNonqueueable
globalStatus.NetworkDataBytesSentNonqueueableLastSec = globalStatus.NetworkDataBytesSentNonqueueable - previousNetworkBytesSentNonqueueable
// debug option. Uncomment to log per-second network statistics. Useful for debugging WiFi instability.
//log.Printf("Network data messages sent: %d total, %d last second. Network data bytes sent: %d total, %d last second.\n", globalStatus.NetworkDataMessagesSent, globalStatus.NetworkDataMessagesSentLastSec, globalStatus.NetworkDataBytesSent, globalStatus.NetworkDataBytesSentLastSec)
previousNetworkMessagesSent = globalStatus.NetworkDataMessagesSent
previousNetworkBytesSent = globalStatus.NetworkDataBytesSent
previousNetworkMessagesSentNonqueueable = globalStatus.NetworkDataMessagesSentNonqueueable
previousNetworkBytesSentNonqueueable = globalStatus.NetworkDataBytesSentNonqueueable
}
}
/*
ffMonitor().
Watches for "i-want-to-play-ffm-udp", "i-can-play-ffm-udp", and "i-cannot-play-ffm-udp" UDP messages broadcasted on
port 50113. Tags the client, issues a warning, and disables AHRS GDL90 output.
*/
func ffMonitor() {
addr := net.UDPAddr{Port: 50113, IP: net.ParseIP("0.0.0.0")}
conn, err := net.ListenUDP("udp", &addr)
if err != nil {
log.Printf("ffMonitor(): error listening on port 50113: %s\n", err.Error())
return
}
defer conn.Close()
for {
buf := make([]byte, 1024)
n, addr, err := conn.ReadFrom(buf)
ipAndPort := strings.Split(addr.String(), ":")
ip := ipAndPort[0]
if err != nil {
log.Printf("err: %s\n", err.Error())
return
}
// Got message, check if it's in the correct format.
if n < 3 || buf[0] != 0xFF || buf[1] != 0xFE {
continue
}
s := string(buf[2:n])
s = strings.Replace(s, "\x00", "", -1)
ffIpAndPort := ip + ":4000"
netMutex.Lock()
p, ok := outSockets[ffIpAndPort]
if !ok {
// Can't do anything, the client isn't even technically connected.
netMutex.Unlock()
continue
}
if strings.HasPrefix(s, "i-want-to-play-ffm-udp") || strings.HasPrefix(s, "i-can-play-ffm-udp") || strings.HasPrefix(s, "i-cannot-play-ffm-udp") {
p.FFCrippled = true
//FIXME: AHRS output doesn't need to be disabled globally, just on the ForeFlight client IPs.
addSingleSystemErrorf("ff-warn", "Stratux is not supported by your EFB app. Your EFB app is known to regularly make changes that cause compatibility issues with Stratux. See the README for a list of apps that officially support Stratux.")
}
outSockets[ffIpAndPort] = p
netMutex.Unlock()
}
}
func initNetwork() {
messageQueue = make(chan networkMessage, 1024) // Buffered channel, 1024 messages.
serialOutputChan = make(chan []byte, 1024) // Buffered channel, 1024 GDL90 messages.
networkGDL90Chan = make(chan []byte, 1024)
outSockets = make(map[string]networkConnection)
pingResponse = make(map[string]time.Time)
netMutex = &sync.Mutex{}
@ -314,4 +651,7 @@ func initNetwork() {
go monitorDHCPLeases()
go messageQueueSender()
go sleepMonitor()
go networkStatsCounter()
go serialOutWatcher()
go networkOutWatcher()
}

271
main/ping.go 100644
Wyświetl plik

@ -0,0 +1,271 @@
/*
Copyright (c) 2016 uAvionix
Distributable under the terms of The "BSD New" License
that can be found in the LICENSE file, herein included
as part of this header.
ping.go: uAvionix Ping ADS-B monitoring and management.
*/
package main
import (
"bufio"
//"fmt"
"log"
"os"
"strings"
"sync"
//"sync/atomic"
"net"
"os/exec"
"time"
// Using forked version of tarm/serial to force Linux
// instead of posix code, allowing for higher baud rates
"github.com/uavionix/serial"
)
// Ping device data
var pingSerialConfig *serial.Config
var pingSerialPort *serial.Port
var pingWG *sync.WaitGroup
var closeCh chan int
func initPingSerial() bool {
var device string
baudrate := int(2000000)
log.Printf("Configuring Ping ADS-B\n")
if _, err := os.Stat("/dev/ping"); err == nil {
device = "/dev/ping"
} else if _, err := os.Stat("/dev/softrf"); err == nil {
device = "/dev/softrf"
baudrate = int(38400)
} else {
log.Printf("No suitable Ping device found.\n")
return false
}
log.Printf("Using %s for Ping\n", device)
// Open port
// No timeout specified as Ping does not heartbeat
pingSerialConfig = &serial.Config{Name: device, Baud: baudrate}
p, err := serial.OpenPort(pingSerialConfig)
if err != nil {
log.Printf("Error opening serial port: %s\n", err.Error())
return false
}
log.Printf("Ping opened serial port")
// No device configuration is needed, we should be ready
pingSerialPort = p
return true
}
func pingNetworkRepeater() {
defer pingWG.Done()
log.Println("Entered Ping network repeater ...")
cmd := exec.Command("/usr/bin/dump1090", "--net-only")
stdout, _ := cmd.StdoutPipe()
stderr, _ := cmd.StderrPipe()
err := cmd.Start()
if err != nil {
log.Printf("Error executing /usr/bin/dump1090: %s\n", err)
// don't return immediately, use the proper shutdown procedure
shutdownPing = true
for {
select {
case <-closeCh:
return
default:
time.Sleep(1 * time.Second)
}
}
}
log.Println("Executed /usr/bin/dump1090 successfully...")
scanStdout := bufio.NewScanner(stdout)
scanStderr := bufio.NewScanner(stderr)
for {
select {
case <-closeCh:
log.Println("Ping network repeater: shutdown msg received, calling cmd.Process.Kill() ...")
err := cmd.Process.Kill()
if err != nil {
log.Printf("\t couldn't kill dump1090: %s\n", err)
} else {
cmd.Wait()
log.Println("\t kill successful...")
}
return
default:
for scanStdout.Scan() {
m := Dump1090TermMessage{Text: scanStdout.Text(), Source: "stdout"}
logDump1090TermMessage(m)
}
if err := scanStdout.Err(); err != nil {
log.Printf("scanStdout error: %s\n", err)
}
for scanStderr.Scan() {
m := Dump1090TermMessage{Text: scanStderr.Text(), Source: "stderr"}
logDump1090TermMessage(m)
if shutdownES != true {
shutdownES = true
}
}
if err := scanStderr.Err(); err != nil {
log.Printf("scanStderr error: %s\n", err)
}
time.Sleep(1 * time.Second)
}
}
}
var dump1090Connection net.Conn = nil
var connectionError error
func pingNetworkConnection() {
// Send to dump1090 on port 30001
dump1090Addr := "127.0.0.1:30001"
dump1090Connection, connectionError = net.Dial("tcp", dump1090Addr)
// RCB monitor for connection failure and redial
}
func pingSerialReader() {
//defer pingWG.Done()
defer pingSerialPort.Close()
// RCB TODO channel control for terminate
log.Printf("Starting Ping serial reader")
scanner := bufio.NewScanner(pingSerialPort)
for scanner.Scan() && globalStatus.Ping_connected && globalSettings.Ping_Enabled {
s := scanner.Text()
// Trimspace removes newlines as well as whitespace
s = strings.TrimSpace(s)
//logString := fmt.Sprintf("Ping received: %s", s)
//log.Println(logString)
if s[0] == '*' {
// 1090ES report
// Ping appends a signal strength at the end of the message
// e.g. *8DC01C2860C37797E9732E555B23;ss=049D;
// Remove this before forwarding to dump1090
// We currently aren't doing anything with this information
// and need to develop a scaling equation - we're using a
// log detector for power so it should have a logarithmic
// relationship. In one example, at -25dBm input (upper limit
// of RX) we saw ~0x500. At -95dBm input (lower limit of RX)
// we saw 0x370
report := strings.Split(s, ";")
//replayLog(s, MSGCLASS_DUMP1090);
if dump1090Connection == nil {
log.Println("Starting dump1090 network connection")
pingNetworkConnection()
}
if len(report[0]) != 0 && dump1090Connection != nil {
dump1090Connection.Write([]byte(report[0] + ";\r\n"))
//log.Println("Relaying 1090ES message")
//logString := fmt.Sprintf("Relaying 1090ES: %s;", report[0]);
//log.Println(logString)
}
} else if s[0] == '+' || s[0] == '-' {
// UAT report
// Ping appends a signal strength and RS bit errors corrected
// at the end of the message
// e.g. -08A5DFDF3907E982585F029B00040080105C3AB4BC5C240700A206000000000000003A13C82F96C80A63191F05FCB231;rs=1;ss=A2;
// We need to rescale the signal strength for interpretation by dump978,
// which expects a 0-1000 base 10 (linear?) scale
// RSSI is in hex and represents an int8 with -128 (0x80) representing an
// errored measurement. There will be some offset from actual due to loss
// in the path. In one example we measured 0x93 (-98) when injecting a
// -102dBm signal
o, msgtype := parseInput(s)
if o != nil && msgtype != 0 {
//logString = fmt.Sprintf("Relaying message, type=%d", msgtype)
//log.Println(logString)
relayMessage(msgtype, o)
} else if o == nil {
//log.Println("Not relaying message, o == nil")
} else {
//log.Println("Not relaying message, msgtype == 0")
}
}
}
globalStatus.Ping_connected = false
log.Printf("Exiting Ping serial reader")
return
}
func pingShutdown() {
log.Println("Entered Ping shutdown() ...")
//close(closeCh)
//log.Println("Ping shutdown(): calling pingWG.Wait() ...")
//pingWG.Wait() // Wait for the goroutine to shutdown
//log.Println("Ping shutdown(): pingWG.Wait() returned...")
// RCB TODO FINISH
globalStatus.Ping_connected = false
}
func pingKill() {
// Send signal to shutdown to pingWatcher().
shutdownPing = true
// Spin until device has been de-initialized.
for globalStatus.Ping_connected != false {
time.Sleep(1 * time.Second)
}
}
// to keep our sync primitives synchronized, only exit a read
// method's goroutine via the close flag channel check, to
// include catastrophic dongle failures
var shutdownPing bool
// Watch for config/device changes.
func pingWatcher() {
prevPingEnabled := false
for {
time.Sleep(1 * time.Second)
// true when a serial call fails
if shutdownPing {
pingShutdown()
shutdownPing = false
}
if prevPingEnabled == globalSettings.Ping_Enabled {
continue
}
// Global settings have changed, reconfig
if globalSettings.Ping_Enabled && !globalStatus.Ping_connected {
globalStatus.Ping_connected = initPingSerial()
//count := 0
if globalStatus.Ping_connected {
//pingWG.Add(1)
go pingNetworkRepeater()
//pingNetworkConnection()
go pingSerialReader()
// Emulate SDR count
//count = 2
}
//atomic.StoreUint32(&globalStatus.Devices, uint32(count))
} else if !globalSettings.Ping_Enabled {
pingShutdown()
}
prevPingEnabled = globalSettings.Ping_Enabled
}
}
func pingInit() {
go pingWatcher()
}

13
main/plugin.go 100644
Wyświetl plik

@ -0,0 +1,13 @@
package main
import (
"time"
)
type StratuxPlugin struct {
InitFunc func() bool
ShutdownFunc func() bool
Name string
Clock time.Time
Input chan string
}

Wyświetl plik

@ -1,410 +0,0 @@
package main
import (
"fmt"
"log"
"strconv"
"strings"
"sync"
"time"
"bufio"
"github.com/kidoman/embd"
_ "github.com/kidoman/embd/host/all"
"github.com/kidoman/embd/sensor/bmp180"
"github.com/tarm/serial"
"../mpu6050"
"os"
)
type SituationData struct {
mu_GPS *sync.Mutex
// From GPS.
lastFixSinceMidnightUTC uint32
lat float32
lng float32
quality uint8
satellites uint16
accuracy float32 // Meters.
alt float32 // Feet.
alt_accuracy float32
lastFixLocalTime time.Time
trueCourse uint16
groundSpeed uint16
lastGroundTrackTime time.Time
mu_Attitude *sync.Mutex
// From BMP180 pressure sensor.
temp float64
pressure_alt float64
lastTempPressTime time.Time
// From MPU6050 accel/gyro.
pitch float64
roll float64
gyro_heading float64
lastAttitudeTime time.Time
}
var serialConfig *serial.Config
var serialPort *serial.Port
func initGPSSerial() bool {
var device string
if _, err := os.Stat("/dev/ttyACM0"); err == nil {
device = "/dev/ttyACM0"
} else {
device = "/dev/ttyAMA0"
}
log.Printf("Using %s for GPS\n", device)
serialConfig = &serial.Config{Name: device, Baud: 9600}
p, err := serial.OpenPort(serialConfig)
if err != nil {
log.Printf("serial port err: %s\n", err.Error())
return false
}
serialPort = p
return true
}
func processNMEALine(l string) bool {
x := strings.Split(l, ",")
if x[0] == "$GNVTG" { // Ground track information.
mySituation.mu_GPS.Lock()
defer mySituation.mu_GPS.Unlock()
if len(x) < 10 {
return false
}
trueCourse := uint16(0)
if len(x[1]) > 0 {
tc, err := strconv.ParseFloat(x[1], 32)
if err != nil {
return false
}
trueCourse = uint16(tc)
//FIXME: Experimental. Set heading to true heading on the MPU6050 reader.
if myMPU6050 != nil && globalStatus.RY835AI_connected && globalSettings.AHRS_Enabled {
myMPU6050.ResetHeading(float64(tc))
}
} else {
// No movement.
mySituation.trueCourse = 0
mySituation.groundSpeed = 0
mySituation.lastGroundTrackTime = time.Time{}
return true
}
groundSpeed, err := strconv.ParseFloat(x[5], 32) // Knots.
if err != nil {
return false
}
mySituation.trueCourse = uint16(trueCourse)
mySituation.groundSpeed = uint16(groundSpeed)
mySituation.lastGroundTrackTime = time.Now()
} else if x[0] == "$GNGGA" { // GPS fix.
if len(x) < 15 {
return false
}
mySituation.mu_GPS.Lock()
defer mySituation.mu_GPS.Unlock()
// Timestamp.
if len(x[1]) < 9 {
return false
}
hr, err1 := strconv.Atoi(x[1][0:2])
min, err2 := strconv.Atoi(x[1][2:4])
sec, err3 := strconv.Atoi(x[1][4:6])
if err1 != nil || err2 != nil || err3 != nil {
return false
}
mySituation.lastFixSinceMidnightUTC = uint32((hr * 60 * 60) + (min * 60) + sec)
// Latitude.
if len(x[2]) < 10 {
return false
}
hr, err1 = strconv.Atoi(x[2][0:2])
minf, err2 := strconv.ParseFloat(x[2][2:10], 32)
if err1 != nil || err2 != nil {
return false
}
mySituation.lat = float32(hr) + float32(minf/60.0)
if x[3] == "S" { // South = negative.
mySituation.lat = -mySituation.lat
}
// Longitude.
if len(x[4]) < 11 {
return false
}
hr, err1 = strconv.Atoi(x[4][0:3])
minf, err2 = strconv.ParseFloat(x[4][3:11], 32)
if err1 != nil || err2 != nil {
return false
}
mySituation.lng = float32(hr) + float32(minf/60.0)
if x[5] == "W" { // West = negative.
mySituation.lng = -mySituation.lng
}
// Quality indicator.
q, err1 := strconv.Atoi(x[6])
if err1 != nil {
return false
}
mySituation.quality = uint8(q)
// Satellites.
sat, err1 := strconv.Atoi(x[7])
if err1 != nil {
return false
}
mySituation.satellites = uint16(sat)
// Accuracy.
hdop, err1 := strconv.ParseFloat(x[8], 32)
if err1 != nil {
return false
}
mySituation.accuracy = float32(hdop * 5.0) //FIXME: 5 meters ~ 1.0 HDOP?
// Altitude.
alt, err1 := strconv.ParseFloat(x[9], 32)
if err1 != nil {
return false
}
mySituation.alt = float32(alt * 3.28084) // Covnert to feet.
//TODO: Altitude accuracy.
mySituation.alt_accuracy = 0
// Timestamp.
mySituation.lastFixLocalTime = time.Now()
}
return true
}
func gpsSerialReader() {
defer serialPort.Close()
for globalSettings.GPS_Enabled && globalStatus.GPS_connected {
scanner := bufio.NewScanner(serialPort)
for scanner.Scan() {
s := scanner.Text()
// log.Printf("Output: %s\n", s)
processNMEALine(s)
}
if err := scanner.Err(); err != nil {
log.Printf("reading standard input: %s\n", err.Error())
}
}
globalStatus.GPS_connected = false
}
var i2cbus embd.I2CBus
var myBMP180 *bmp180.BMP180
var myMPU6050 *mpu6050.MPU6050
func readBMP180() (float64, float64, error) { // ºCelsius, Meters
temp, err := myBMP180.Temperature()
if err != nil {
return temp, 0.0, err
}
altitude, err := myBMP180.Altitude()
altitude = float64(1/0.3048) * altitude // Convert meters to feet.
if err != nil {
return temp, altitude, err
}
return temp, altitude, nil
}
func readMPU6050() (float64, float64, error) { //TODO: error checking.
pitch, roll := myMPU6050.PitchAndRoll()
return pitch, roll, nil
}
func initBMP180() error {
myBMP180 = bmp180.New(i2cbus) //TODO: error checking.
return nil
}
func initMPU6050() error {
myMPU6050 = mpu6050.New(i2cbus) //TODO: error checking.
return nil
}
func initI2C() error {
i2cbus = embd.NewI2CBus(1) //TODO: error checking.
return nil
}
// Unused at the moment. 5 second update, since read functions in bmp180 are slow.
func tempAndPressureReader() {
timer := time.NewTicker(5 * time.Second)
for globalStatus.RY835AI_connected && globalSettings.AHRS_Enabled {
<-timer.C
// Read temperature and pressure altitude.
temp, alt, err_bmp180 := readBMP180()
// Process.
if err_bmp180 != nil {
log.Printf("readBMP180(): %s\n", err_bmp180.Error())
globalStatus.RY835AI_connected = false
} else {
mySituation.temp = temp
mySituation.pressure_alt = alt
mySituation.lastTempPressTime = time.Now()
}
}
globalStatus.RY835AI_connected = false
}
func makeFFAHRSSimReport() {
s := fmt.Sprintf("XATTStratux,%f,%f,%f", mySituation.gyro_heading, mySituation.pitch, mySituation.roll)
sendMsg([]byte(s), NETWORK_AHRS_FFSIM, false)
}
func makeAHRSGDL90Report() {
msg := make([]byte, 16)
msg[0] = 0x4c
msg[1] = 0x45
msg[2] = 0x01
msg[3] = 0x00
pitch := int16(float64(mySituation.pitch) * float64(10.0))
roll := int16(float64(mySituation.roll) * float64(10.0))
hdg := uint16(float64(mySituation.gyro_heading) * float64(10.0)) //TODO.
slip_skid := int16(float64(0) * float64(10.0)) //TODO.
yaw_rate := int16(float64(0) * float64(10.0)) //TODO.
g := int16(float64(1.0) * float64(10.0)) //TODO.
// Roll.
msg[4] = byte((roll >> 8) & 0xFF)
msg[5] = byte(roll & 0xFF)
// Pitch.
msg[6] = byte((pitch >> 8) & 0xFF)
msg[7] = byte(pitch & 0xFF)
// Heading.
msg[8] = byte((hdg >> 8) & 0xFF)
msg[9] = byte(hdg & 0xFF)
// Slip/skid.
msg[10] = byte((slip_skid >> 8) & 0xFF)
msg[11] = byte(slip_skid & 0xFF)
// Yaw rate.
msg[12] = byte((yaw_rate >> 8) & 0xFF)
msg[13] = byte(yaw_rate & 0xFF)
// "G".
msg[14] = byte((g >> 8) & 0xFF)
msg[15] = byte(g & 0xFF)
sendMsg(prepareMessage(msg), NETWORK_AHRS_GDL90, false)
}
func attitudeReaderSender() {
timer := time.NewTicker(100 * time.Millisecond) // ~10Hz update.
for globalStatus.RY835AI_connected && globalSettings.AHRS_Enabled {
<-timer.C
// Read pitch and roll.
pitch, roll, err_mpu6050 := readMPU6050()
mySituation.mu_Attitude.Lock()
if err_mpu6050 != nil {
log.Printf("readMPU6050(): %s\n", err_mpu6050.Error())
globalStatus.RY835AI_connected = false
break
} else {
mySituation.pitch = pitch
mySituation.roll = roll
mySituation.gyro_heading = myMPU6050.Heading() //FIXME. Experimental.
mySituation.lastAttitudeTime = time.Now()
}
// Send, if valid.
// if isGPSGroundTrackValid(), etc.
makeFFAHRSSimReport()
makeAHRSGDL90Report()
mySituation.mu_Attitude.Unlock()
}
globalStatus.RY835AI_connected = false
}
func isGPSValid() bool {
return time.Since(mySituation.lastFixLocalTime).Seconds() < 15
}
func isGPSGroundTrackValid() bool {
return time.Since(mySituation.lastGroundTrackTime).Seconds() < 15
}
func isAHRSValid() bool {
return time.Since(mySituation.lastAttitudeTime).Seconds() < 1 // If attitude information gets to be over 1 second old, declare invalid.
}
func isTempPressValid() bool {
return time.Since(mySituation.lastTempPressTime).Seconds() < 15
}
func initAHRS() error {
if err := initI2C(); err != nil { // I2C bus.
return err
}
if err := initBMP180(); err != nil { // I2C temperature and pressure altitude.
i2cbus.Close()
return err
}
if err := initMPU6050(); err != nil { // I2C accel/gyro.
i2cbus.Close()
myBMP180.Close()
return err
}
globalStatus.RY835AI_connected = true
go attitudeReaderSender()
go tempAndPressureReader()
return nil
}
func pollRY835AI() {
timer := time.NewTicker(10 * time.Second)
for {
<-timer.C
// GPS enabled, was not connected previously?
if globalSettings.GPS_Enabled && !globalStatus.GPS_connected {
globalStatus.GPS_connected = initGPSSerial() // via USB for now.
if globalStatus.GPS_connected {
go gpsSerialReader()
}
}
// RY835AI I2C enabled, was not connected previously?
if globalSettings.AHRS_Enabled && !globalStatus.RY835AI_connected {
err := initAHRS()
if err != nil {
log.Printf("initAHRS(): %s\ndisabling AHRS sensors.\n", err.Error())
globalStatus.RY835AI_connected = false
}
}
}
}
func initRY835AI() {
mySituation.mu_GPS = &sync.Mutex{}
mySituation.mu_Attitude = &sync.Mutex{}
go pollRY835AI()
}

Wyświetl plik

@ -1,131 +1,313 @@
/*
Copyright (c) 2015-2016 Christopher Young
Distributable under the terms of The "BSD New" License
that can be found in the LICENSE file, herein included
as part of this header.
sdr.go: SDR monitoring, SDR management, data input from UAT/1090ES channels.
*/
package main
import (
"log"
"os/exec"
"regexp"
"strconv"
"strings"
"sync"
"sync/atomic"
"syscall"
"time"
"../godump978"
rtl "github.com/jpoirier/gortlsdr"
"log"
"time"
)
var uatSDR int // Index.
var esSDR int // Index.
// Device holds per dongle values and attributes
type Device struct {
dev *rtl.Context
wg *sync.WaitGroup
closeCh chan int
indexID int
ppm int
serial string
idSet bool
}
// Read 978MHz from SDR.
func sdrReader() {
var err error
var dev *rtl.Context
// UAT is a 978 MHz device
type UAT Device
log.Printf("===== UAT Device name: %s =====\n", rtl.GetDeviceName(uatSDR))
if dev, err = rtl.Open(uatSDR); err != nil {
log.Printf("\tOpen Failed, exiting\n")
uatSDR = -1
return
}
defer dev.Close()
m, p, s, err := dev.GetUsbStrings()
// ES is a 1090 MHz device
type ES Device
// UATDev holds a 978 MHz dongle object
var UATDev *UAT
// ESDev holds a 1090 MHz dongle object
var ESDev *ES
type Dump1090TermMessage struct {
Text string
Source string
}
func (e *ES) read() {
defer e.wg.Done()
log.Println("Entered ES read() ...")
cmd := exec.Command("/usr/bin/dump1090", "--oversample", "--net", "--device-index", strconv.Itoa(e.indexID), "--ppm", strconv.Itoa(e.ppm))
stdout, _ := cmd.StdoutPipe()
stderr, _ := cmd.StderrPipe()
err := cmd.Start()
if err != nil {
log.Printf("\tGetUsbStrings Failed - error: %s\n", err)
} else {
log.Printf("\tGetUsbStrings - %s %s %s\n", m, p, s)
}
log.Printf("\tGetTunerType: %s\n", dev.GetTunerType())
//---------- Set Tuner Gain ----------
tgain := 480
err = dev.SetTunerGainMode(true)
if err != nil {
log.Printf("\tSetTunerGainMode Failed - error: %s\n", err)
} else {
log.Printf("\tSetTunerGainMode Successful\n")
log.Printf("Error executing /usr/bin/dump1090: %s\n", err)
// don't return immediately, use the proper shutdown procedure
shutdownES = true
for {
select {
case <-e.closeCh:
return
default:
time.Sleep(1 * time.Second)
}
}
}
err = dev.SetTunerGain(tgain)
if err != nil {
log.Printf("\tSetTunerGain Failed - error: %s\n", err)
} else {
log.Printf("\tSetTunerGain Successful\n")
}
log.Println("Executed /usr/bin/dump1090 successfully...")
//---------- Get/Set Sample Rate ----------
samplerate := 2083334
err = dev.SetSampleRate(samplerate)
if err != nil {
log.Printf("\tSetSampleRate Failed - error: %s\n", err)
} else {
log.Printf("\tSetSampleRate - rate: %d\n", samplerate)
}
log.Printf("\tGetSampleRate: %d\n", dev.GetSampleRate())
done := make(chan bool)
//---------- Get/Set Xtal Freq ----------
rtlFreq, tunerFreq, err := dev.GetXtalFreq()
if err != nil {
log.Printf("\tGetXtalFreq Failed - error: %s\n", err)
} else {
log.Printf("\tGetXtalFreq - Rtl: %d, Tuner: %d\n", rtlFreq, tunerFreq)
}
go func() {
for {
select {
case <-done:
return
case <-e.closeCh:
log.Println("ES read(): shutdown msg received, calling cmd.Process.Kill() ...")
err := cmd.Process.Kill()
if err == nil {
log.Println("\t kill successful...")
}
return
default:
time.Sleep(1 * time.Second)
}
}
}()
newRTLFreq := 28800000
newTunerFreq := 28800000
err = dev.SetXtalFreq(newRTLFreq, newTunerFreq)
if err != nil {
log.Printf("\tSetXtalFreq Failed - error: %s\n", err)
} else {
log.Printf("\tSetXtalFreq - Center freq: %d, Tuner freq: %d\n",
newRTLFreq, newTunerFreq)
}
stdoutBuf := make([]byte, 1024)
stderrBuf := make([]byte, 1024)
go func() {
for {
select {
case <-done:
return
default:
n, err := stdout.Read(stdoutBuf)
if err == nil && n > 0 {
m := Dump1090TermMessage{Text: string(stdoutBuf[:n]), Source: "stdout"}
logDump1090TermMessage(m)
}
}
}
}()
//---------- Get/Set Center Freq ----------
err = dev.SetCenterFreq(978000000)
if err != nil {
log.Printf("\tSetCenterFreq 978MHz Failed, error: %s\n", err)
} else {
log.Printf("\tSetCenterFreq 978MHz Successful\n")
}
go func() {
for {
select {
case <-done:
return
default:
n, err := stderr.Read(stderrBuf)
if err == nil && n > 0 {
m := Dump1090TermMessage{Text: string(stderrBuf[:n]), Source: "stderr"}
logDump1090TermMessage(m)
}
}
}
}()
log.Printf("\tGetCenterFreq: %d\n", dev.GetCenterFreq())
cmd.Wait()
//---------- Set Bandwidth ----------
bw := 1000000
log.Printf("\tSetting Bandwidth: %d\n", bw)
if err = dev.SetTunerBw(bw); err != nil {
log.Printf("\tSetTunerBw %d Failed, error: %s\n", bw, err)
} else {
log.Printf("\tSetTunerBw %d Successful\n", bw)
}
// we get here if A) the dump1090 process died
// on its own or B) cmd.Process.Kill() was called
// from within the goroutine, either way close
// the "done" channel, which ensures we don't leak
// goroutines...
close(done)
}
if err = dev.ResetBuffer(); err == nil {
log.Printf("\tResetBuffer Successful\n")
} else {
log.Printf("\tResetBuffer Failed - error: %s\n", err)
}
//---------- Get/Set Freq Correction ----------
freqCorr := dev.GetFreqCorrection()
log.Printf("\tGetFreqCorrection: %d\n", freqCorr)
err = dev.SetFreqCorrection(int(globalSettings.PPM))
if err != nil {
log.Printf("\tSetFreqCorrection %d Failed, error: %s\n", globalSettings.PPM, err)
} else {
log.Printf("\tSetFreqCorrection %d Successful\n", globalSettings.PPM)
}
func (u *UAT) read() {
defer u.wg.Done()
log.Println("Entered UAT read() ...")
var buffer = make([]uint8, rtl.DefaultBufLength)
for uatSDR != -1 {
var buffer = make([]uint8, rtl.DefaultBufLength)
nRead, err := dev.ReadSync(buffer, rtl.DefaultBufLength)
if err != nil {
log.Printf("\tReadSync Failed - error: %s\n", err)
uatSDR = -1
break
} else {
// log.Printf("\tReadSync %d\n", nRead)
buf := buffer[:nRead]
godump978.InChan <- buf
for {
select {
default:
nRead, err := u.dev.ReadSync(buffer, rtl.DefaultBufLength)
if err != nil {
if globalSettings.DEBUG {
log.Printf("\tReadSync Failed - error: %s\n", err)
}
if shutdownUAT != true {
shutdownUAT = true
}
break
}
if nRead > 0 {
buf := buffer[:nRead]
godump978.InChan <- buf
}
case <-u.closeCh:
log.Println("UAT read(): shutdown msg received...")
return
}
}
}
func getPPM(serial string) int {
r, err := regexp.Compile("str?a?t?u?x:\\d+:?(-?\\d*)")
if err != nil {
return globalSettings.PPM
}
arr := r.FindStringSubmatch(serial)
if arr == nil {
return globalSettings.PPM
}
ppm, err := strconv.Atoi(arr[1])
if err != nil {
return globalSettings.PPM
}
return ppm
}
func (e *ES) sdrConfig() (err error) {
e.ppm = getPPM(e.serial)
log.Printf("===== ES Device Serial: %s PPM %d =====\n", e.serial, e.ppm)
return
}
// 978 UAT configuration settings
const (
TunerGain = 480
SampleRate = 2083334
NewRTLFreq = 28800000
NewTunerFreq = 28800000
CenterFreq = 978000000
Bandwidth = 1000000
)
func (u *UAT) sdrConfig() (err error) {
log.Printf("===== UAT Device Name : %s =====\n", rtl.GetDeviceName(u.indexID))
log.Printf("===== UAT Device Serial: %s=====\n", u.serial)
if u.dev, err = rtl.Open(u.indexID); err != nil {
log.Printf("\tUAT Open Failed...\n")
return
}
log.Printf("\tGetTunerType: %s\n", u.dev.GetTunerType())
//---------- Set Tuner Gain ----------
err = u.dev.SetTunerGainMode(true)
if err != nil {
u.dev.Close()
log.Printf("\tSetTunerGainMode Failed - error: %s\n", err)
return
}
log.Printf("\tSetTunerGainMode Successful\n")
err = u.dev.SetTunerGain(TunerGain)
if err != nil {
u.dev.Close()
log.Printf("\tSetTunerGain Failed - error: %s\n", err)
return
}
log.Printf("\tSetTunerGain Successful\n")
tgain := u.dev.GetTunerGain()
log.Printf("\tGetTunerGain: %d\n", tgain)
//---------- Get/Set Sample Rate ----------
err = u.dev.SetSampleRate(SampleRate)
if err != nil {
u.dev.Close()
log.Printf("\tSetSampleRate Failed - error: %s\n", err)
return
}
log.Printf("\tSetSampleRate - rate: %d\n", SampleRate)
log.Printf("\tGetSampleRate: %d\n", u.dev.GetSampleRate())
//---------- Get/Set Xtal Freq ----------
rtlFreq, tunerFreq, err := u.dev.GetXtalFreq()
if err != nil {
u.dev.Close()
log.Printf("\tGetXtalFreq Failed - error: %s\n", err)
return
}
log.Printf("\tGetXtalFreq - Rtl: %d, Tuner: %d\n", rtlFreq, tunerFreq)
err = u.dev.SetXtalFreq(NewRTLFreq, NewTunerFreq)
if err != nil {
u.dev.Close()
log.Printf("\tSetXtalFreq Failed - error: %s\n", err)
return
}
log.Printf("\tSetXtalFreq - Center freq: %d, Tuner freq: %d\n",
NewRTLFreq, NewTunerFreq)
//---------- Get/Set Center Freq ----------
err = u.dev.SetCenterFreq(CenterFreq)
if err != nil {
u.dev.Close()
log.Printf("\tSetCenterFreq 978MHz Failed, error: %s\n", err)
return
}
log.Printf("\tSetCenterFreq 978MHz Successful\n")
log.Printf("\tGetCenterFreq: %d\n", u.dev.GetCenterFreq())
//---------- Set Bandwidth ----------
log.Printf("\tSetting Bandwidth: %d\n", Bandwidth)
if err = u.dev.SetTunerBw(Bandwidth); err != nil {
u.dev.Close()
log.Printf("\tSetTunerBw %d Failed, error: %s\n", Bandwidth, err)
return
}
log.Printf("\tSetTunerBw %d Successful\n", Bandwidth)
if err = u.dev.ResetBuffer(); err != nil {
u.dev.Close()
log.Printf("\tResetBuffer Failed - error: %s\n", err)
return
}
log.Printf("\tResetBuffer Successful\n")
//---------- Get/Set Freq Correction ----------
freqCorr := u.dev.GetFreqCorrection()
log.Printf("\tGetFreqCorrection: %d\n", freqCorr)
u.ppm = getPPM(u.serial)
err = u.dev.SetFreqCorrection(u.ppm)
if err != nil {
u.dev.Close()
log.Printf("\tSetFreqCorrection %d Failed, error: %s\n", u.ppm, err)
return
}
log.Printf("\tSetFreqCorrection %d Successful\n", u.ppm)
return
}
// Read from the godump978 channel - on or off.
func uatReader() {
log.Println("Entered uatReader() ...")
for {
uat := <-godump978.OutChan
o, msgtype := parseInput(uat)
@ -135,36 +317,245 @@ func uatReader() {
}
}
// Watch for config/device changes.
func sdrWatcher() {
timer := time.NewTicker(1 * time.Second)
for {
<-timer.C
// Update device count.
globalStatus.Devices = uint(rtl.GetDeviceCount())
func (u *UAT) writeID() error {
info, err := u.dev.GetHwInfo()
if err != nil {
return err
}
info.Serial = "stratux:978"
return u.dev.SetHwInfo(info)
}
if uatSDR == -1 && globalSettings.UAT_Enabled {
if globalStatus.Devices == 0 {
log.Printf("No RTL-SDR devices.\n")
continue
func (e *ES) writeID() error {
info, err := e.dev.GetHwInfo()
if err != nil {
return err
}
info.Serial = "stratux:1090"
return e.dev.SetHwInfo(info)
}
func (u *UAT) shutdown() {
log.Println("Entered UAT shutdown() ...")
close(u.closeCh) // signal to shutdown
log.Println("UAT shutdown(): calling u.wg.Wait() ...")
u.wg.Wait() // Wait for the goroutine to shutdown
log.Println("UAT shutdown(): u.wg.Wait() returned...")
log.Println("UAT shutdown(): closing device ...")
u.dev.Close() // preempt the blocking ReadSync call
log.Println("UAT shutdown() complete ...")
}
func (e *ES) shutdown() {
log.Println("Entered ES shutdown() ...")
close(e.closeCh) // signal to shutdown
log.Println("ES shutdown(): calling e.wg.Wait() ...")
e.wg.Wait() // Wait for the goroutine to shutdown
log.Println("ES shutdown() complete ...")
}
var sdrShutdown bool
func sdrKill() {
// Send signal to shutdown to sdrWatcher().
sdrShutdown = true
// Spin until all devices have been de-initialized.
for UATDev != nil || ESDev != nil {
time.Sleep(1 * time.Second)
}
}
func reCompile(s string) *regexp.Regexp {
// note , compile returns a nil pointer on error
r, _ := regexp.Compile(s)
return r
}
type regexUAT regexp.Regexp
type regexES regexp.Regexp
var rUAT = (*regexUAT)(reCompile("str?a?t?u?x:978"))
var rES = (*regexES)(reCompile("str?a?t?u?x:1090"))
func (r *regexUAT) hasID(serial string) bool {
if r == nil {
return strings.HasPrefix(serial, "stratux:978")
}
return (*regexp.Regexp)(r).MatchString(serial)
}
func (r *regexES) hasID(serial string) bool {
if r == nil {
return strings.HasPrefix(serial, "stratux:1090")
}
return (*regexp.Regexp)(r).MatchString(serial)
}
func createUATDev(id int, serial string, idSet bool) error {
UATDev = &UAT{indexID: id, serial: serial}
if err := UATDev.sdrConfig(); err != nil {
log.Printf("UATDev.sdrConfig() failed: %s\n", err)
UATDev = nil
return err
}
UATDev.wg = &sync.WaitGroup{}
UATDev.idSet = idSet
UATDev.closeCh = make(chan int)
UATDev.wg.Add(1)
go UATDev.read()
return nil
}
func createESDev(id int, serial string, idSet bool) error {
ESDev = &ES{indexID: id, serial: serial}
if err := ESDev.sdrConfig(); err != nil {
log.Printf("ESDev.sdrConfig() failed: %s\n", err)
ESDev = nil
return err
}
ESDev.wg = &sync.WaitGroup{}
ESDev.idSet = idSet
ESDev.closeCh = make(chan int)
ESDev.wg.Add(1)
go ESDev.read()
return nil
}
func configDevices(count int, esEnabled, uatEnabled bool) {
// once the tagged dongles have been assigned, explicitly range over
// the remaining IDs and assign them to any anonymous dongles
unusedIDs := make(map[int]string)
// loop 1: assign tagged dongles
for i := 0; i < count; i++ {
_, _, s, err := rtl.GetDeviceUsbStrings(i)
if err == nil {
//FIXME: Trim NULL from the serial. Best done in gortlsdr, but putting this here for now.
s = strings.Trim(s, "\x00")
// no need to check if createXDev returned an error; if it
// failed to config the error is logged and we can ignore
// it here so it doesn't get queued up again
if uatEnabled && UATDev == nil && rUAT.hasID(s) {
createUATDev(i, s, true)
} else if esEnabled && ESDev == nil && rES.hasID(s) {
createESDev(i, s, true)
} else {
unusedIDs[i] = s
}
uatSDR = 0
go sdrReader()
} else {
log.Printf("rtl.GetDeviceUsbStrings id %d: %s\n", i, err)
}
if esSDR == -1 && globalSettings.ES_Enabled {
if globalStatus.Devices == 0 || (globalStatus.Devices == 1 && globalSettings.UAT_Enabled) {
log.Printf("Not enough RTL-SDR devices.\n")
}
esSDR = 1
}
// loop 2: assign anonymous dongles but sanity check the serial ids
// so we don't cross config for dual assigned dongles. e.g. when two
// dongles are set to the same stratux id and the unconsumed,
// non-anonymous, dongle makes it to this loop.
for i, s := range unusedIDs {
if uatEnabled && !globalStatus.UATRadio_connected && UATDev == nil && !rES.hasID(s) {
createUATDev(i, s, false)
} else if esEnabled && ESDev == nil && !rUAT.hasID(s) {
createESDev(i, s, false)
}
}
}
// to keep our sync primitives synchronized, only exit a read
// method's goroutine via the close flag channel check, to
// include catastrophic dongle failures
var shutdownES bool
var shutdownUAT bool
// Watch for config/device changes.
func sdrWatcher() {
prevCount := 0
prevUATEnabled := false
prevESEnabled := false
// Get the system (RPi) uptime.
info := syscall.Sysinfo_t{}
err := syscall.Sysinfo(&info)
if err == nil {
// Got system uptime. Delay if and only if the system uptime is less than 120 seconds. This should be plenty of time
// for the RPi to come up and start Stratux. Keeps the delay from happening if the daemon is auto-restarted from systemd.
if info.Uptime < 120 {
time.Sleep(90 * time.Second)
} else if globalSettings.DeveloperMode {
// Throw a "critical error" if developer mode is enabled. Alerts the developer that the daemon was restarted (possibly)
// unexpectedly.
addSingleSystemErrorf("restart-warn", "System uptime %d seconds. Daemon was restarted.\n", info.Uptime)
}
}
for {
time.Sleep(1 * time.Second)
if sdrShutdown {
if UATDev != nil {
UATDev.shutdown()
UATDev = nil
}
if ESDev != nil {
ESDev.shutdown()
ESDev = nil
}
return
}
// true when a ReadSync call fails
if shutdownUAT {
if UATDev != nil {
UATDev.shutdown()
UATDev = nil
}
shutdownUAT = false
}
// true when we get stderr output
if shutdownES {
if ESDev != nil {
ESDev.shutdown()
ESDev = nil
}
shutdownES = false
}
// capture current state
esEnabled := globalSettings.ES_Enabled
uatEnabled := globalSettings.UAT_Enabled
count := rtl.GetDeviceCount()
interfaceCount := count
if globalStatus.UATRadio_connected {
interfaceCount++
}
atomic.StoreUint32(&globalStatus.Devices, uint32(interfaceCount))
// support up to two dongles
if count > 2 {
count = 2
}
if count == prevCount && prevESEnabled == esEnabled && prevUATEnabled == uatEnabled {
continue
}
// the device count or the global settings have changed, reconfig
if UATDev != nil {
UATDev.shutdown()
UATDev = nil
}
if ESDev != nil {
ESDev.shutdown()
ESDev = nil
}
configDevices(count, esEnabled, uatEnabled)
prevCount = count
prevUATEnabled = uatEnabled
prevESEnabled = esEnabled
}
}
func sdrInit() {
uatSDR = -1
esSDR = -1
go sdrWatcher()
go uatReader()
godump978.Dump978Init()
go godump978.ProcessDataFromChannel()
}

494
main/sensors.go 100644
Wyświetl plik

@ -0,0 +1,494 @@
package main
import (
"fmt"
"log"
"math"
"path/filepath"
"strings"
"time"
"../goflying/ahrs"
"../goflying/ahrsweb"
"../sensors"
"github.com/kidoman/embd"
_ "github.com/kidoman/embd/host/all"
)
const (
numRetries uint8 = 5
calCLimit = 0.15
calDLimit = 10.0
// WHO_AM_I values to differentiate between the different IMUs.
MPUREG_WHO_AM_I = 0x75
MPUREG_WHO_AM_I_VAL = 0x71 // Expected value.
ICMREG_WHO_AM_I = 0x00
ICMREG_WHO_AM_I_VAL = 0xEA // Expected value.
)
var (
i2cbus embd.I2CBus
myPressureReader sensors.PressureReader
myIMUReader sensors.IMUReader
cal chan (string)
analysisLogger *ahrs.AHRSLogger
ahrsCalibrating bool
logMap map[string]interface{}
)
func initI2CSensors() {
i2cbus = embd.NewI2CBus(1)
go pollSensors()
go sensorAttitudeSender()
go updateAHRSStatus()
}
func pollSensors() {
timer := time.NewTicker(4 * time.Second)
for {
<-timer.C
// If it's not currently connected, try connecting to pressure sensor
if globalSettings.BMP_Sensor_Enabled && !globalStatus.BMPConnected {
globalStatus.BMPConnected = initPressureSensor() // I2C temperature and pressure altitude.
go tempAndPressureSender()
}
// If it's not currently connected, try connecting to IMU
if globalSettings.IMU_Sensor_Enabled && !globalStatus.IMUConnected {
globalStatus.IMUConnected = initIMU() // I2C accel/gyro/mag.
}
}
}
func initPressureSensor() (ok bool) {
bmp, err := sensors.NewBMP280(&i2cbus, 100*time.Millisecond)
if err == nil {
myPressureReader = bmp
return true
}
//TODO westphae: make bmp180.go to fit bmp interface
return false
}
func tempAndPressureSender() {
var (
temp float64
press float64
altLast = -9999.9
altitude float64
err error
dt = 0.1
failNum uint8
)
// Initialize variables for rate of climb calc
u := 5 / (5 + float32(dt)) // Use 5 sec decay time for rate of climb, slightly faster than typical VSI
timer := time.NewTicker(time.Duration(1000*dt) * time.Millisecond)
for globalSettings.BMP_Sensor_Enabled && globalStatus.BMPConnected {
<-timer.C
// Read temperature and pressure altitude.
temp, err = myPressureReader.Temperature()
if err != nil {
addSingleSystemErrorf("pressure-sensor-temp-read", "AHRS Error: Couldn't read temperature from sensor: %s", err)
}
press, err = myPressureReader.Pressure()
if err != nil {
addSingleSystemErrorf("pressure-sensor-pressure-read", "AHRS Error: Couldn't read pressure from sensor: %s", err)
failNum++
if failNum > numRetries {
// log.Printf("AHRS Error: Couldn't read pressure from sensor %d times, closing BMP: %s", failNum, err)
myPressureReader.Close()
globalStatus.BMPConnected = false // Try reconnecting a little later
break
}
}
// Update the Situation data.
mySituation.muBaro.Lock()
mySituation.BaroLastMeasurementTime = stratuxClock.Time
mySituation.BaroTemperature = float32(temp)
altitude = CalcAltitude(press)
mySituation.BaroPressureAltitude = float32(altitude)
if altLast < -2000 {
altLast = altitude // Initialize
}
// Assuming timer is reasonably accurate, use a regular ewma
mySituation.BaroVerticalSpeed = u*mySituation.BaroVerticalSpeed + (1-u)*float32(altitude-altLast)/(float32(dt)/60)
mySituation.muBaro.Unlock()
altLast = altitude
}
mySituation.BaroPressureAltitude = 99999
mySituation.BaroVerticalSpeed = 99999
}
func initIMU() (ok bool) {
// Check if the chip is the ICM-20948 or MPU-9250.
v, err := i2cbus.ReadByteFromReg(0x68, ICMREG_WHO_AM_I)
if err != nil {
log.Printf("Error identifying IMU: %s\n", err.Error())
return false
}
v2, err := i2cbus.ReadByteFromReg(0x68, MPUREG_WHO_AM_I)
if err != nil {
log.Printf("Error identifying IMU: %s\n", err.Error())
return false
}
if v == ICMREG_WHO_AM_I_VAL {
log.Println("ICM-20948 detected.")
imu, err := sensors.NewICM20948(&i2cbus)
if err == nil {
myIMUReader = imu
return true
}
} else if v2 == MPUREG_WHO_AM_I_VAL {
log.Println("MPU-9250 detected.")
imu, err := sensors.NewMPU9250(&i2cbus)
if err == nil {
myIMUReader = imu
return true
}
} else {
log.Printf("Could not identify MPU. v=%02x, v2=%02x.\n", v, v2)
return false
}
return false
}
//FIXME: Shoud be moved to managementinterface.go and standardized on management interface port.
func sensorAttitudeSender() {
var (
t time.Time
roll, pitch, heading float64
mpuError, magError error
failNum uint8
)
s := ahrs.NewSimpleAHRS()
m := ahrs.NewMeasurement()
cal = make(chan (string), 1)
// Set up loggers for analysis
ahrswebListener, err := ahrsweb.NewKalmanListener()
if err != nil {
// addSingleSystemErrorf("ahrs-web-start", "AHRS Info: couldn't start ahrswebListener: %s\n", err.Error())
} else {
defer ahrswebListener.Close()
}
// Need a sampling freq faster than 10Hz
timer := time.NewTicker(50 * time.Millisecond) // ~20Hz update.
for {
// Set sensor gyro calibrations
if c, d := &globalSettings.C, &globalSettings.D; d[0]*d[0]+d[1]*d[1]+d[2]*d[2] > 0 {
s.SetCalibrations(c, d)
log.Printf("AHRS Info: IMU Calibrations read from settings: accel %6f %6f %6f; gyro %6f %6f %6f\n",
c[0], c[1], c[2], d[0], d[1], d[2])
} else {
// Do an initial calibration
select { // Don't block if cal isn't receiving: only need one calibration in the queue at a time.
case cal <- "cal":
default:
}
}
// Set sensor quaternion
if f := &globalSettings.SensorQuaternion; f[0]*f[0]+f[1]*f[1]+f[2]*f[2]+f[3]*f[3] > 0 {
s.SetSensorQuaternion(f)
} else {
select { // Don't block if cal isn't receiving: only need one calibration in the queue at a time.
case cal <- "level":
default:
}
}
failNum = 0
<-timer.C
time.Sleep(950 * time.Millisecond)
for globalSettings.IMU_Sensor_Enabled && globalStatus.IMUConnected {
<-timer.C
// Process calibration and level requests
select {
case action := <-cal:
log.Printf("AHRS Info: cal received action %s\n", action)
ahrsCalibrating = true
myIMUReader.Read() // Clear out the averages
var (
nTries uint8
cc, dd float64
)
for (math.Abs(cc-1) > calCLimit || dd > calDLimit) && nTries < numRetries {
time.Sleep(1 * time.Second)
_, d1, d2, d3, c1, c2, c3, _, _, _, mpuError, _ := myIMUReader.Read()
cc = math.Sqrt(c1*c1 + c2*c2 + c3*c3)
dd = math.Sqrt(d1*d1 + d2*d2 + d3*d3)
nTries++
log.Printf("AHRS Info: IMU calibration attempt #%d\n", nTries)
if mpuError != nil {
log.Printf("AHRS Info: Error reading IMU while calibrating: %s\n", mpuError)
} else {
if strings.Contains(action, "cal") { // Calibrate gyros
globalSettings.D = [3]float64{d1, d2, d3}
s.SetCalibrations(nil, &globalSettings.D)
log.Printf("AHRS Info: IMU gyro calibration: %3f %3f %3f\n", d1, d2, d3)
}
if strings.Contains(action, "level") { // Calibrate accel / level
globalSettings.C = [3]float64{c1, c2, c3}
s.SetCalibrations(&globalSettings.C, nil)
globalSettings.SensorQuaternion = *makeOrientationQuaternion(globalSettings.C)
s.SetSensorQuaternion(&globalSettings.SensorQuaternion)
s.Reset()
log.Printf("AHRS Info: IMU accel calibration: %3f %3f %3f\n", c1, c2, c3)
log.Printf("AHRS Info: Caged to quaternion %v\n", globalSettings.SensorQuaternion)
}
saveSettings()
}
}
ahrsCalibrating = false
<-timer.C // Make sure we get data for the actual algorithm
default:
}
// Make the IMU sensor measurements.
t = stratuxClock.Time
m.T = float64(t.UnixNano()/1000) / 1e6
_, m.B1, m.B2, m.B3, m.A1, m.A2, m.A3, m.M1, m.M2, m.M3, mpuError, magError = myIMUReader.Read()
m.SValid = mpuError == nil
m.MValid = magError == nil
if mpuError != nil {
log.Printf("AHRS Gyro/Accel Error: %s\n", mpuError)
failNum++
if failNum > numRetries {
log.Printf("AHRS Gyro/Accel Error: failed to read %d times, restarting: %s\n",
failNum-1, mpuError)
myIMUReader.Close()
globalStatus.IMUConnected = false
}
continue
}
failNum = 0
if magError != nil {
if globalSettings.DEBUG {
log.Printf("AHRS Magnetometer Error, not using for this run: %s\n", magError)
}
m.MValid = false
}
// Make the GPS measurements.
m.TW = float64(mySituation.GPSLastGroundTrackTime.UnixNano()/1000) / 1e6
m.WValid = isGPSGroundTrackValid()
if m.WValid {
m.W1 = mySituation.GPSGroundSpeed * math.Sin(float64(mySituation.GPSTrueCourse)*ahrs.Deg)
m.W2 = mySituation.GPSGroundSpeed * math.Cos(float64(mySituation.GPSTrueCourse)*ahrs.Deg)
if globalSettings.BMP_Sensor_Enabled && globalStatus.BMPConnected {
m.W3 = float64(mySituation.BaroVerticalSpeed * 60 / 6076.12)
} else {
m.W3 = float64(mySituation.GPSVerticalSpeed) * 3600 / 6076.12
}
}
// Run the AHRS calculations.
s.Compute(m)
// If we have valid AHRS info, then update mySituation.
mySituation.muAttitude.Lock()
if s.Valid() {
roll, pitch, heading = s.RollPitchHeading()
mySituation.AHRSRoll = roll / ahrs.Deg
mySituation.AHRSPitch = pitch / ahrs.Deg
mySituation.AHRSGyroHeading = heading
if !isAHRSInvalidValue(heading) {
mySituation.AHRSGyroHeading /= ahrs.Deg
}
//TODO westphae: until magnetometer calibration is performed, no mag heading
mySituation.AHRSMagHeading = ahrs.Invalid
mySituation.AHRSSlipSkid = s.SlipSkid()
mySituation.AHRSTurnRate = s.RateOfTurn()
mySituation.AHRSGLoad = s.GLoad()
if mySituation.AHRSGLoad < mySituation.AHRSGLoadMin || mySituation.AHRSGLoadMin == 0 {
mySituation.AHRSGLoadMin = mySituation.AHRSGLoad
}
if mySituation.AHRSGLoad > mySituation.AHRSGLoadMax {
mySituation.AHRSGLoadMax = mySituation.AHRSGLoad
}
mySituation.AHRSLastAttitudeTime = t
} else {
mySituation.AHRSRoll = ahrs.Invalid
mySituation.AHRSPitch = ahrs.Invalid
mySituation.AHRSGyroHeading = ahrs.Invalid
mySituation.AHRSMagHeading = ahrs.Invalid
mySituation.AHRSSlipSkid = ahrs.Invalid
mySituation.AHRSTurnRate = ahrs.Invalid
mySituation.AHRSGLoad = ahrs.Invalid
mySituation.AHRSGLoadMin = ahrs.Invalid
mySituation.AHRSGLoadMax = 0
mySituation.AHRSLastAttitudeTime = time.Time{}
s.Reset()
}
mySituation.muAttitude.Unlock()
makeAHRSGDL90Report() // Send whether or not valid - the function will invalidate the values as appropriate
// Send to AHRS debugging server.
if ahrswebListener != nil {
if err = ahrswebListener.Send(s.GetState(), m); err != nil {
log.Printf("AHRS Error: couldn't write to ahrsweb: %s\n", err)
ahrswebListener = nil
}
}
// Log it to csv for later analysis.
if globalSettings.AHRSLog && usage.Usage() < 0.95 {
if analysisLogger == nil {
analysisFilename := fmt.Sprintf("sensors_%s.csv", time.Now().Format("20060102_150405"))
logMap = s.GetLogMap()
updateExtraLogging()
analysisLogger = ahrs.NewAHRSLogger(filepath.Join(logDirf, analysisFilename), logMap)
}
if analysisLogger != nil {
updateExtraLogging()
analysisLogger.Log()
}
} else {
analysisLogger = nil
}
}
}
}
func updateExtraLogging() {
logMap["GPSNACp"] = float64(mySituation.GPSNACp)
logMap["GPSTrueCourse"] = mySituation.GPSTrueCourse
logMap["GPSVerticalAccuracy"] = mySituation.GPSVerticalAccuracy
logMap["GPSHorizontalAccuracy"] = mySituation.GPSHorizontalAccuracy
logMap["GPSAltitudeMSL"] = mySituation.GPSAltitudeMSL
logMap["GPSFixQuality"] = float64(mySituation.GPSFixQuality)
logMap["BaroPressureAltitude"] = float64(mySituation.BaroPressureAltitude)
logMap["BaroVerticalSpeed"] = float64(mySituation.BaroVerticalSpeed)
}
func makeOrientationQuaternion(g [3]float64) (f *[4]float64) {
if globalSettings.IMUMapping[0] == 0 { // if unset, default to some standard orientation
globalSettings.IMUMapping[0] = -1 // +2 for RY836AI
}
// This is the "forward direction" chosen during the orientation process.
var x *[3]float64 = new([3]float64)
if globalSettings.IMUMapping[0] < 0 {
x[-globalSettings.IMUMapping[0]-1] = -1
} else {
x[+globalSettings.IMUMapping[0]-1] = +1
}
// Normalize the gravity vector to be 1 G.
z, _ := ahrs.MakeUnitVector(g)
rotmat, _ := ahrs.MakeHardSoftRotationMatrix(*z, *x, [3]float64{0, 0, 1}, [3]float64{1, 0, 0})
f = new([4]float64)
f[0], f[1], f[2], f[3] = ahrs.RotationMatrixToQuaternion(*rotmat)
return
}
// This is used in the orientation process where the user specifies the forward and up directions.
func getMinAccelDirection() (i int, err error) {
_, _, _, _, a1, a2, a3, _, _, _, err, _ := myIMUReader.ReadOne()
if err != nil {
return
}
log.Printf("AHRS Info: sensor orientation accels %1.3f %1.3f %1.3f\n", a1, a2, a3)
switch {
case math.Abs(a1) > math.Abs(a2) && math.Abs(a1) > math.Abs(a3):
if a1 > 0 {
i = 1
} else {
i = -1
}
case math.Abs(a2) > math.Abs(a3) && math.Abs(a2) > math.Abs(a1):
if a2 > 0 {
i = 2
} else {
i = -2
}
case math.Abs(a3) > math.Abs(a1) && math.Abs(a3) > math.Abs(a2):
if a3 > 0 {
i = 3
} else {
i = -3
}
default:
err = fmt.Errorf("couldn't determine biggest accel from %1.3f %1.3f %1.3f", a1, a2, a3)
}
return
}
// CageAHRS sends a signal to the AHRSProvider that it should recalibrate and reset its level orientation.
func CageAHRS() {
cal <- "level"
}
// CageAHRS sends a signal to the AHRSProvider that it should recalibrate and reset its level orientation.
func CalibrateAHRS() {
cal <- "cal"
}
// ResetAHRSGLoad resets the min and max to the current G load value.
func ResetAHRSGLoad() {
mySituation.AHRSGLoadMax = mySituation.AHRSGLoad
mySituation.AHRSGLoadMin = mySituation.AHRSGLoad
}
func updateAHRSStatus() {
var (
msg uint8
imu bool
ticker *time.Ticker
)
ticker = time.NewTicker(250 * time.Millisecond)
for {
<-ticker.C
msg = 0
// GPS ground track valid?
if isGPSGroundTrackValid() {
msg++
}
// IMU is being used
imu = globalSettings.IMU_Sensor_Enabled && globalStatus.IMUConnected
if imu {
msg += 1 << 1
}
// BMP is being used
if globalSettings.BMP_Sensor_Enabled && globalStatus.BMPConnected {
msg += 1 << 2
}
// IMU is doing a calibration
if ahrsCalibrating {
msg += 1 << 3
}
// Logging to csv
if imu && analysisLogger != nil {
msg += 1 << 4
}
mySituation.AHRSStatus = msg
}
}
func isAHRSInvalidValue(val float64) bool {
return math.Abs(val-ahrs.Invalid) < 0.01
}

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,67 @@
/*
Copyright (c) 2015-2016 Christopher Young
Distributable under the terms of The "BSD New" License
that can be found in the LICENSE file, herein included
as part of this header.
uibroadcast.go: Helper functions for managementinterface - notification channels for update "subscriptions"
(used for weather and traffic websockets).
*/
package main
import (
"encoding/json"
"golang.org/x/net/websocket"
"sync"
"time"
)
type uibroadcaster struct {
sockets []*websocket.Conn
sockets_mu *sync.Mutex
messages chan []byte
}
func NewUIBroadcaster() *uibroadcaster {
ret := &uibroadcaster{
sockets: make([]*websocket.Conn, 0),
sockets_mu: &sync.Mutex{},
messages: make(chan []byte, 1024),
}
go ret.writer()
return ret
}
func (u *uibroadcaster) Send(msg []byte) {
u.messages <- msg
}
func (u *uibroadcaster) SendJSON(i interface{}) {
j, _ := json.Marshal(&i)
u.Send(j)
}
func (u *uibroadcaster) AddSocket(sock *websocket.Conn) {
u.sockets_mu.Lock()
u.sockets = append(u.sockets, sock)
u.sockets_mu.Unlock()
}
func (u *uibroadcaster) writer() {
for {
msg := <-u.messages
// Send to all.
p := make([]*websocket.Conn, 0) // Keep a list of the writeable sockets.
u.sockets_mu.Lock()
for _, sock := range u.sockets {
err := sock.SetWriteDeadline(time.Now().Add(time.Second))
_, err2 := sock.Write(msg)
if err == nil && err2 == nil {
p = append(p, sock)
}
}
u.sockets = p // Save the list of writeable sockets.
u.sockets_mu.Unlock()
}
}

Wyświetl plik

@ -1,273 +0,0 @@
// Package mpu6050 allows interfacing with InvenSense mpu6050 barometric pressure sensor. This sensor
// has the ability to provided compensated temperature and pressure readings.
package mpu6050
import (
"math"
"time"
// "github.com/golang/glog"
"github.com/kidoman/embd"
"log"
)
//https://www.olimex.com/Products/Modules/Sensors/MOD-MPU6050/resources/RM-MPU-60xxA_rev_4.pdf
const (
address = 0x68
GYRO_XOUT_H = 0x43
GYRO_YOUT_H = 0x45
GYRO_ZOUT_H = 0x47
ACCEL_XOUT_H = 0x3B
ACCEL_YOUT_H = 0x3D
ACCEL_ZOUT_H = 0x3F
PWR_MGMT_1 = 0x6B
GYRO_CONFIG = 0x1B
ACCEL_CONFIG = 0x1C
ACCEL_SCALE = 16384.0 // Assume AFS_SEL = 0.
GYRO_SCALE = 131.0 // Assume FS_SEL = 0.
pollDelay = 500 * time.Microsecond // 2000Hz
)
type XYZ struct {
x float32
y float32
z float32
}
// MPU6050 represents a InvenSense MPU6050 sensor.
type MPU6050 struct {
Bus embd.I2CBus
Poll time.Duration
started bool
//TODO
gyro_reading XYZ // "Integrated".
accel_reading XYZ // Directly from sensor.
pitch_history []float64
roll_history []float64
pitch_resting float64
roll_resting float64
pitch float64
roll float64
heading float64
// gyro chan XYZ
// accel chan XYZ
quit chan struct{}
}
// New returns a handle to a MPU6050 sensor.
func New(bus embd.I2CBus) *MPU6050 {
n := &MPU6050{Bus: bus, Poll: pollDelay}
n.StartUp()
return n
}
//TODO
func (d *MPU6050) StartUp() error {
d.Bus.WriteByteToReg(address, PWR_MGMT_1, 0) // Wake device up.
d.Bus.WriteByteToReg(address, GYRO_CONFIG, 0) // FS_SEL = 0
d.Bus.WriteByteToReg(address, ACCEL_CONFIG, 0) // AFS_SEL = 0
d.pitch_history = make([]float64, 0)
d.roll_history = make([]float64, 0)
d.started = true
d.Run()
return nil
}
func (d *MPU6050) calibrate() {
//TODO: Error checking to make sure that the histories are extensive enough to be significant.
//TODO: Error checking to do continuous calibrations.
pitch_adjust := float64(0)
for _, v := range d.pitch_history {
pitch_adjust = pitch_adjust + v
}
pitch_adjust = pitch_adjust / float64(len(d.pitch_history))
d.pitch_resting = pitch_adjust
roll_adjust := float64(0)
for _, v := range d.roll_history {
roll_adjust = roll_adjust + v
}
roll_adjust = roll_adjust / float64(len(d.roll_history))
d.roll_resting = roll_adjust
log.Printf("calibrate: pitch %f, roll %f\n", pitch_adjust, roll_adjust)
}
func (d *MPU6050) readGyro() (XYZ, error) {
var ret XYZ
x, err := d.Bus.ReadWordFromReg(address, GYRO_XOUT_H)
if err != nil {
return ret, err
}
y, err := d.Bus.ReadWordFromReg(address, GYRO_YOUT_H)
if err != nil {
return ret, err
}
z, err := d.Bus.ReadWordFromReg(address, GYRO_ZOUT_H)
if err != nil {
return ret, err
}
ret.x = float32(int16(x)) / GYRO_SCALE // º/sec
ret.y = float32(int16(y)) / GYRO_SCALE // º/sec
ret.z = float32(int16(z)) / GYRO_SCALE // º/sec
return ret, nil
}
func (d *MPU6050) readAccel() (XYZ, error) {
var ret XYZ
x, err := d.Bus.ReadWordFromReg(address, ACCEL_XOUT_H)
if err != nil {
return ret, err
}
y, err := d.Bus.ReadWordFromReg(address, ACCEL_YOUT_H)
if err != nil {
return ret, err
}
z, err := d.Bus.ReadWordFromReg(address, ACCEL_ZOUT_H)
if err != nil {
return ret, err
}
ret.x = float32(int16(x)) / ACCEL_SCALE
ret.y = float32(int16(y)) / ACCEL_SCALE
ret.z = float32(int16(z)) / ACCEL_SCALE
return ret, nil
}
func (d *MPU6050) calculatePitchAndRoll() {
accel := d.accel_reading
// log.Printf("accel: %f, %f, %f\n", accel.x, accel.y, accel.z)
// Accel.
p1 := math.Atan2(float64(accel.y), dist(accel.x, accel.z))
p1_deg := p1 * (180.0 / math.Pi)
r1 := math.Atan2(float64(accel.x), dist(accel.y, accel.z))
r1_deg := -r1 * (180.0 / math.Pi)
// Gyro.
p2 := float64(d.gyro_reading.x)
r2 := float64(d.gyro_reading.y) // Backwards?
// "Noise filter".
ft := float64(0.98)
sample_period := float64(1 / 2000.0)
d.pitch = float64(ft*(sample_period*p2+d.pitch) + (1-ft)*p1_deg)
d.roll = float64((ft*(sample_period*r2+d.roll) + (1-ft)*r1_deg))
d.pitch_history = append(d.pitch_history, d.pitch)
d.roll_history = append(d.roll_history, d.roll)
//FIXME: Experimental (heading).
f := math.Atan2(float64(d.gyro_reading.z), dist(float32(d.pitch), float32(d.roll)))
h1_deg := -float64(3.42857142857)*f * (180.0 / math.Pi)
// d.heading = float64((float64(3.42857142857)*sample_period * float64(-d.gyro_reading.z)) + d.heading)
d.heading = float64((sample_period * h1_deg) + d.heading)
if d.heading > 360.0 {
d.heading = d.heading - float64(360.0)
} else if d.heading < 0.0 {
d.heading = d.heading + float64(360.0)
}
}
func (d *MPU6050) measureGyro() error {
XYZ_gyro, err := d.readGyro()
if err != nil {
return err
}
d.gyro_reading = XYZ_gyro
return nil
}
func (d *MPU6050) measureAccel() error {
XYZ_accel, err := d.readAccel()
if err != nil {
return err
}
d.accel_reading = XYZ_accel
return nil
}
func (d *MPU6050) measure() error {
if err := d.measureGyro(); err != nil {
return err
}
if err := d.measureAccel(); err != nil {
return err
}
return nil
}
func dist(a, b float32) float64 {
a64 := float64(a)
b64 := float64(b)
return math.Sqrt((a64 * a64) + (b64 * b64))
}
// Temperature returns the current temperature reading.
func (d *MPU6050) PitchAndRoll() (float64, float64) {
return (d.pitch - d.pitch_resting), (d.roll - d.roll_resting)
}
func (d *MPU6050) Heading() float64 {
return d.heading
}
func (d *MPU6050) Run() {
go func() {
d.quit = make(chan struct{})
timer := time.NewTicker(d.Poll)
calibrateTimer := time.NewTicker(1 * time.Minute)
for {
select {
case <-timer.C:
d.measureGyro()
d.measureAccel()
d.calculatePitchAndRoll()
case <-calibrateTimer.C:
d.calibrate()
calibrateTimer.Stop()
case <-d.quit:
return
}
}
}()
return
}
// Set heading from a known value (usually GPS true heading).
func (d *MPU6050) ResetHeading(heading float64) {
log.Printf("reset true heading: %f\n", heading)
d.heading = heading
}
// Close.
func (d *MPU6050) Close() {
if d.quit != nil {
d.quit <- struct{}{}
}
}

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,285 @@
# app side integration
### Protocol & network information
Stratux uses GDL90 protocol over port 4000 UDP. All messages are sent as **unicast** messages. When a device is connected to the stratux Wi-Fi
network and a DHCP lease is issued to the device, the IP of the DHCP lease is added to the list of clients receiving GDL90 messages.
The GDL90 is "standard" with the exception of three non-standard GDL90-style messages: `0xCC` (stratux heartbeat), `0x5358` (another stratux heartbeat), and `0x4C` (AHRS report).
### How to recognize stratux
In order of preference:
1. Look for `0xCC` (or `0x5358`) GDL90 heartbeat message. This is sent at the same time as the GDL90 heartbeat (0x00) message.
2. Look for Wi-Fi network that **starts with** "stratux".
3. Detect 192.168.10.0/24 Wi-Fi connection, verify stratux status with JSON response from ws://192.168.10.1/status.
4. Use the the second [stratux status](http://hiltonsoftware.com/stratux/StratuxStatusMessage-V104.pdf) message.
See main/gen_gdl90.go:makeStratuxHeartbeat() for heartbeat (#1) format.
### Sleep mode
Stratux makes use of of ICMP Echo/Echo Reply and ICMP Destination Unreachable packets to determine the state of the application receiving GDL90 messages.
*Queueable messages* includes all UAT uplink messages, and in general: any messages whose value will not degrade for having been delayed for
the typical "sleep mode" period, whose content remains accurate despite said delay, and whose content is sufficiently redundant such
that if the typical delay period is exceeded then it can be discarded.
When a client enters sleep mode, queueable messages are entered into a FIFO queue of fixed size which should be sufficient to hold 10-25 minutes of data per client. Non-queueable messages that are directed
towards a client while in sleep mode are discarded. When in sleep mode, therefore, no GDL90 messages are received by the client.
There are three cases that are used to determine the state of a client:
1. Responding to ICMP Echo AND no ICMP Destination Unreachable received for destination port => not sleeping.
2. Not responding to ICMP Echo => sleeping.
3. Responding to ICMP Echo AND ICMP Destination Unreachable received for destination port => sleeping.
The sleep mode detection routine has two parts:
1. ICMP Echo packets are sent every 5 seconds. If a response is not received in the last 10 seconds, the client is in sleep mode.
2. If an ICMP Destination Unreachable is received in the last 5 seconds, the client is in sleep mode.
3. If an ICMP Destination Unreachable has been received in the last 15 seconds, but not in the last 5 seconds, the client is in *throttle mode*. In throttle mode, messages are sent at 0.1% of the normal rate. This gives the client a chance to recover or to respond that the port is closed.
__Note__: NEXRAD frames, METARs, and Winds Aloft, and other weather data may be delayed in reception to
the receiving application. The timestamp in the GDL90 message should always be used to for the observation
time, and **not the time the message was received**.
### Traffic handling
Stratux receives traffic updates from UAT downlink messages and/or 1090ES messages.
Traffic information roughly follows this path:
1. Traffic update is received (from any source). An entry for the target is created, indexed by the ICAO address of the target.
2. Any position/information updates received from any source for this ICAO address updates the entry created in #1.
3. If no updates are received from any source over 60 seconds, the target entry is deleted.
4. A GDL90 traffic report is sent for every target entry (having valid lat/lng) every 1 second.
When traffic information is being received both from UAT and 1090ES sources, it is not uncommon to see a flip/flop in tail numbers on targets.
Some 1090ES transponders will send the actual registration number of the aircraft, which then becomes a TIS-B target whose tail number may be
a squawk code.
### Additional data/control available to EFBs
Stratux makes available a webserver to retrieve statistics which may be useful to EFBs:
* `http://192.168.10.1/getTowers` - a list of ADS-B towers received with attached message receipt and signal level statistics. Example output:
```json
{
"(28.845592,-96.920400)": {
"Lat": 28.845591545105,
"Lng": -96.920399665833,
"Signal_strength_last_minute": 55,
"Signal_strength_max": 69,
"Messages_last_minute": 97,
"Messages_total": 196
},
"(29.266505,-98.309097)": {
"Lat": 29.266505241394,
"Lng": -98.309097290039,
"Signal_strength_last_minute": 78,
"Signal_strength_max": 78,
"Messages_last_minute": 1,
"Messages_total": 3
},
"(29.702547,-96.900787)": {
"Lat": 29.702546596527,
"Lng": -96.900787353516,
"Signal_strength_last_minute": 87,
"Signal_strength_max": 119,
"Messages_last_minute": 94,
"Messages_total": 203
}
}
```
* `http://192.168.10.1/getStatus` - device status and statistics. Example output (commented JSON):
```javascript
{
"Version": "v1.4r2",
"Build": "ebd6b9bf5049aa5bb31c345c1eaa39648bc219a2",
"HardwareBuild": "",
"Devices": 1,
"Connected_Users": 0,
"DiskBytesFree": 60625375232,
"UAT_messages_last_minute": 0,
"UAT_messages_max": 0,
"ES_messages_last_minute": 0,
"ES_messages_max": 0,
"UAT_traffic_targets_tracking": 0,
"ES_traffic_targets_tracking": 0,
"Ping_connected": false,
"GPS_satellites_locked": 5,
"GPS_satellites_seen": 7,
"GPS_satellites_tracked": 9,
"GPS_position_accuracy": 10.2,
"GPS_connected": true,
"GPS_solution": "GPS + SBAS (WAAS)",
"GPS_detected_type": 55,
"Uptime": 323020,
"UptimeClock": "0001-01-01T00:05:23.02Z",
"CPUTemp": 47.774,
"NetworkDataMessagesSent": 0,
"NetworkDataMessagesSentNonqueueable": 0,
"NetworkDataBytesSent": 0,
"NetworkDataBytesSentNonqueueable": 0,
"NetworkDataMessagesSentLastSec": 0,
"NetworkDataMessagesSentNonqueueableLastSec": 0,
"NetworkDataBytesSentLastSec": 0,
"NetworkDataBytesSentNonqueueableLastSec": 0,
"UAT_METAR_total": 0,
"UAT_TAF_total": 0,
"UAT_NEXRAD_total": 0,
"UAT_SIGMET_total": 0,
"UAT_PIREP_total": 0,
"UAT_NOTAM_total": 0,
"UAT_OTHER_total": 0,
"Errors": [
],
"Logfile_Size": 34487043,
"AHRS_LogFiles_Size": 0,
"BMPConnected": true,
"IMUConnected": true
}
```
* `http://192.168.10.1/getSettings` - get device settings. Example output:
```json
{
"UAT_Enabled": true,
"ES_Enabled": false,
"Ping_Enabled": false,
"GPS_Enabled": true,
"BMP_Sensor_Enabled": true,
"IMU_Sensor_Enabled": true,
"NetworkOutputs": [
{
"Conn": null,
"Ip": "",
"Port": 4000,
"Capability": 5,
"MessageQueueLen": 0,
"LastUnreachable": "0001-01-01T00:00:00Z",
"SleepFlag": false,
"FFCrippled": false
}
],
"SerialOutputs": null,
"DisplayTrafficSource": false,
"DEBUG": false,
"ReplayLog": false,
"AHRSLog": false,
"IMUMapping": [
-1,
0
],
"SensorQuaternion": [
0.0068582877312501,
0.0067230280142738,
0.7140806859355,
-0.69999752767998
],
"C": [
-0.019065523239845,
-0.99225684377575,
-0.019766228217414
],
"D": [
-2.7707754753258,
5.544145023957,
-1.890621662038
],
"PPM": 0,
"OwnshipModeS": "F00000",
"WatchList": "",
"DeveloperMode": false,
"GLimits": "",
"StaticIps": [
]
}
```
* `http://192.168.10.1/setSettings` - set device settings. Use an HTTP POST of JSON content in the format given above - posting only the fields containing the settings to be modified.
* `http://192.168.10.1/getSituation` - get GPS/AHRS information. Example output:
```json
{
"GPSLastFixSinceMidnightUTC": 67337.6,
"GPSLatitude": 39.108533,
"GPSLongitude": -76.770862,
"GPSFixQuality": 2,
"GPSHeightAboveEllipsoid": 115.51,
"GPSGeoidSep": -17.523,
"GPSSatellites": 5,
"GPSSatellitesTracked": 11,
"GPSSatellitesSeen": 8,
"GPSHorizontalAccuracy": 10.2,
"GPSNACp": 9,
"GPSAltitudeMSL": 170.10767,
"GPSVerticalAccuracy": 8,
"GPSVerticalSpeed": -0.6135171,
"GPSLastFixLocalTime": "0001-01-01T00:06:44.24Z",
"GPSTrueCourse": 0,
"GPSTurnRate": 0,
"GPSGroundSpeed": 0.77598433056951,
"GPSLastGroundTrackTime": "0001-01-01T00:06:44.24Z",
"GPSTime": "2017-09-26T18:42:17Z",
"GPSLastGPSTimeStratuxTime": "0001-01-01T00:06:43.65Z",
"GPSLastValidNMEAMessageTime": "0001-01-01T00:06:44.24Z",
"GPSLastValidNMEAMessage": "$PUBX,04,184426.00,260917,240266.00,1968,18,-177618,-952.368,21*1A",
"GPSPositionSampleRate": 0,
"BaroTemperature": 37.02,
"BaroPressureAltitude": 153.32,
"BaroVerticalSpeed": 1.3123479,
"BaroLastMeasurementTime": "0001-01-01T00:06:44.23Z",
"AHRSPitch": -0.97934145732801, // Degrees. 3276.7 = Invalid.
"AHRSRoll": -2.2013729217108, // Degrees. 3276.7 = Invalid.
"AHRSGyroHeading": 187741.08073052, // Degrees. Process mod 360. 3276.7 = Invalid.
"AHRSMagHeading": 3276.7, // Degrees. Process mod 360. 3276.7 = Invalid.
"AHRSSlipSkid": 0.52267604604907, // Degrees. 3276.7 = Invalid.
"AHRSTurnRate": 3276.7, // Degrees per second. 3276.7 = Invalid.
"AHRSGLoad": 0.99847599584255, // Current G load, in G's. Reads 1 G at rest.
"AHRSGLoadMin": 0.99815989027411, // Minimum recorded G load, in G's.
"AHRSGLoadMax": 1.0043409597397, // Maximum recorded G load, in G's.
"AHRSLastAttitudeTime": "0001-01-01T00:06:44.28Z", // Stratux clock ticks since last attitude update. Reference against /getStatus -> UptimeClock.
"AHRSStatus": 7 // Status bitmask. See main/sensors.go -> updateAHRSStatus().
}
```
* `ws://192.168.10.1/traffic` - traffic stream. On initial connect, all currently tracked traffic targets are dumped. Updates are streamed as they are received. Example output:
Initial connect:
```json
{"Icao_addr":2837120,"OnGround":false,"Lat":42.19293,"Lng":-83.92148,"Position_valid":true,"Alt":3400,"Track":9,"Speed":92,"Speed_valid":true,"Vvel":0,"Tail":"","Last_seen":"2015-12-22T21:29:22.241048727Z","Last_source":2}
{"Icao_addr":2836155,"OnGround":false,"Lat":42.122932,"Lng":-84.17615,"Position_valid":true,"Alt":2800,"Track":158,"Speed":105,"Speed_valid":true,"Vvel":0,"Tail":"","Last_seen":"2015-12-22T21:29:22.241543881Z","Last_source":2}
```
Subsequent update (2837120 = 2B4A80 reports a newer position, altitude increased from 2,800' to 3,400'):
```json
{"Icao_addr":2837120,"OnGround":false,"Lat":42.193336,"Lng":-83.92136,"Position_valid":true,"Alt":3400,"Track":9,"Speed":92,"Speed_valid":true,"Vvel":0,"Tail":"","Last_seen":"2015-12-22T21:29:22.252914555Z","Last_source":2}
```
* `http://192.168.10.1/calibrateAHRS` - run AHRS sensor calibration routine. Submit a blank POST to this URL.
* `http://192.168.10.1/cageAHRS` - "level" attitude display. Submit a blank POST to this URL.
* `http://192.168.10.1/resetGMeter` - reset G-meter to zero. Submit a blank POST to this URL.
* `http://192.168.10.1/restart` - restart Stratux application.
* `http://192.168.10.1/reboot` - reboot the system.
* `http://192.168.10.1/shutdown` - shutdown the system.

BIN
notes/logo.bmp 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 642 B

14942
notes/logo.dxf 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,82 @@
#!/bin/bash
#apt-get install -y dh-make
stratuxVersion=`git describe --tags --abbrev=0`
stratuxBuild=`git log -n 1 --pretty=%H`
echo
echo
echo "Packaging ${stratuxVersion} (${stratuxBuild})."
echo
echo
cd ..
make
rm -rf work
mkdir -p work/bin
cp gen_gdl90 work/bin/
cp fancontrol work/bin/
cp libdump978.so work/bin/
cp __lib__systemd__system__stratux.service work/bin/
cp __root__stratux-pre-start.sh work/bin/
cp dump1090/dump1090 work/bin/
cp -r web work/bin/
cp image/hostapd.conf work/bin/
cp image/hostapd-edimax.conf work/bin/
cp image/config.txt work/bin/
cp image/rtl-sdr-blacklist.conf work/bin/
cp image/bashrc.txt work/bin/
cp image/modules.txt work/bin/
cp image/stxAliases.txt work/bin/
cp image/hostapd_manager.sh work/bin/
cp image/sdr-tool.sh work/bin/
cp image/10-stratux.rules work/bin/
cp image/99-uavionix.rules work/bin/
cp image/motd work/bin/
cp image/stratux-wifi.sh work/bin/
cp image/rc.local work/bin/
cp image/dhcpd-not_smart.conf work/bin/
cp image/dhcpd-smart.conf work/bin/
cp image/interfaces work/bin/
cp image/logrotate.conf work/bin/
cp image/logrotate_d_stratux work/bin/
cp image/rsyslog_d_stratux work/bin/
cp test-data/ahrs/ahrs_table.log work/bin/
cp ahrs_approx work/bin/
#TODO: librtlsdr.
cd work/
cat ../selfupdate/update_header.sh >update.sh
echo "stratuxVersion=${stratuxVersion}" >>update.sh
echo "stratuxBuild=${stratuxBuild}" >>update.sh
find bin/ -type d | sed -e 's/^bin\///' | grep -v '^$' | while read dn; do
echo "mkdir -p $dn" >>update.sh
done
find bin/ -type f | while read fn; do
echo -n "packaging $fn... "
UPFN=`echo $fn | sed -e 's/^bin\///'`
echo "cat >${UPFN}.b64 <<__EOF__" >>update.sh
gzip -c $fn | base64 >>update.sh
echo "__EOF__" >>update.sh
echo "base64 -d ${UPFN}.b64 | gzip -d -c >${UPFN}" >>update.sh
echo "rm -f ${UPFN}.b64" >>update.sh
echo "done"
done
cat ../selfupdate/update_footer.sh >>update.sh
chmod +x update.sh
OUTF="update-stratux-${stratuxVersion}-${stratuxBuild:0:10}.sh"
mv update.sh $OUTF
echo
echo
echo "$OUTF ready."
echo
echo

Wyświetl plik

@ -0,0 +1,18 @@
#!/bin/bash
ssh -i ~/.ssh/id_rsa.updates stratux-updates@updates.stratux.me 'ls -1 queue/' | while read git_hash ; do
echo "***** Building $git_hash. *****"
git clone https://github.com/cyoung/stratux --recursive $git_hash
cd $git_hash
git reset --hard $git_hash
cd selfupdate
./makeupdate.sh
cd ..
for fl in `ls -1 work/update*.sh | cut -d/ -f2`
do
scp -i ~/.ssh/id_rsa.updates work/${fl} stratux-updates@updates.stratux.me:uploading/
ssh -i ~/.ssh/id_rsa.updates stratux-updates@updates.stratux.me "mv uploading/${fl} finished/"
done
cd ..
ssh -i ~/.ssh/id_rsa.updates stratux-updates@updates.stratux.me "rm -f queue/${git_hash}"
done

Wyświetl plik

@ -0,0 +1,105 @@
cp -f gen_gdl90 /usr/bin/gen_gdl90
chmod 755 /usr/bin/gen_gdl90
cp -f libdump978.so /usr/lib/libdump978.so
chmod 655 /usr/bin/gen_gdl90
# Startup script.
RASPBIAN_VERSION=`cat /etc/debian_version`
if test "$RASPBIAN_VERSION" = "8.0" ; then
# Install the systemd startup scripts in any case, even if they won't be used. If this is being run, then the old init.d script
# is still intact and we just leave it. If running Wheezy, then remove the old init.d script.
rm -f /etc/init.d/stratux
rm -f /etc/rc2.d/S01stratux
rm -f /etc/rc6.d/K01stratux
fi
cp -f __lib__systemd__system__stratux.service /lib/systemd/system/stratux.service
cp -f __root__stratux-pre-start.sh /root/stratux-pre-start.sh
chmod 644 /lib/systemd/system/stratux.service
chmod 744 /root/stratux-pre-start.sh
ln -fs /lib/systemd/system/stratux.service /etc/systemd/system/multi-user.target.wants/stratux.service
#wifi config
cp -f hostapd.conf /etc/hostapd/hostapd.conf
cp -f hostapd-edimax.conf /etc/hostapd/hostapd-edimax.conf
#rsyslog config
cp -f rsyslog_d_stratux /etc/rsyslog.d/stratux.conf
#logrotate config
cp -f logrotate.conf /etc/logrotate.conf
cp -f logrotate_d_stratux /etc/logrotate.d/stratux
#WiFi Hostapd ver test and hostapd.conf builder script
cp -f stratux-wifi.sh /usr/sbin/
chmod 755 /usr/sbin/stratux-wifi.sh
#WiFi Config Manager
cp -f hostapd_manager.sh /usr/sbin/
chmod 755 /usr/sbin/hostapd_manager.sh
#SDR Serial Script
cp -f sdr-tool.sh /usr/sbin/
chmod 755 /usr/sbin/sdr-tool.sh
#boot config
cp -f config.txt /boot/config.txt
#rc.local
cp -f rc.local /etc/
#disable serial console
sed -i /boot/cmdline.txt -e "s/console=ttyAMA0,[0-9]\+ //"
#modprobe.d blacklist
cp -f rtl-sdr-blacklist.conf /etc/modprobe.d/
#udev config
cp -f 10-stratux.rules /etc/udev/rules.d
cp -f 99-uavionix.rules /etc/udev/rules.d
#go setup
cp -f bashrc.txt /root/.bashrc
cp -f stxAliases.txt /root/.stxAliases
# /etc/modules
cp -f modules.txt /etc/modules
#motd
cp -f motd /etc/motd
#fan control utility
#remove old script
rm -f /usr/bin/fancontrol.py
#install new program
/usr/bin/fancontrol stop
/usr/bin/fancontrol remove
cp -f fancontrol /usr/bin/
chmod 755 /usr/bin/fancontrol
/usr/bin/fancontrol install
cp -f dump1090 /usr/bin/
chmod 755 /usr/bin/dump1090
# AHRS approx data.
cp -f ahrs_table.log /root/
cp -f ahrs_approx /usr/bin/
chmod 755 /usr/bin/ahrs_approx
# DHCPD Config.
cp -f dhcpd-not_smart.conf /etc/dhcp/
cp -f dhcpd-smart.conf /etc/dhcp/
ln -s /etc/dhcp/dhcpd-not_smart.conf /etc/dhcp/dhcpd.conf
# Interfaces file.
cp -f interfaces /etc/network/interfaces
# Web files install.
cd web/ && make stratuxBuild=${stratuxBuild}
# Remove old Wi-Fi watcher script.
rm -f /usr/sbin/wifi_watch.sh
sed -i "/\bwifi_watch\b/d" /etc/rc.local
cd /
rm -rf /root/stratux-update

Wyświetl plik

@ -0,0 +1,6 @@
#!/bin/bash
rm -rf /root/stratux-update
mkdir -p /root/stratux-update
cd /root/stratux-update
rm -f /var/log/stratux*

81
sensors/bmp280.go 100644
Wyświetl plik

@ -0,0 +1,81 @@
// Package sensors provides a stratux interface to sensors used for AHRS calculations.
package sensors
import (
"errors"
"time"
"../goflying/bmp280"
"github.com/kidoman/embd"
)
const (
bmp280PowerMode = bmp280.NormalMode
bmp280Standby = bmp280.StandbyTime63ms
bmp280FilterCoeff = bmp280.FilterCoeff16
bmp280TempRes = bmp280.Oversamp16x
bmp280PressRes = bmp280.Oversamp16x
)
// BMP280 represents a BMP280 sensor and implements the PressureSensor interface.
type BMP280 struct {
sensor *bmp280.BMP280
data *bmp280.BMPData
running bool
}
var errBMP = errors.New("BMP280 Error: BMP280 is not running")
// NewBMP280 looks for a BMP280 connected on the I2C bus having one of the valid addresses and begins reading it.
func NewBMP280(i2cbus *embd.I2CBus, freq time.Duration) (*BMP280, error) {
var (
bmp *bmp280.BMP280
errbmp error
)
bmp, errbmp = bmp280.NewBMP280(i2cbus, bmp280.Address1,
bmp280PowerMode, bmp280Standby, bmp280FilterCoeff, bmp280TempRes, bmp280PressRes)
if errbmp != nil { // Maybe the BMP280 isn't at Address1, try Address2
bmp, errbmp = bmp280.NewBMP280(i2cbus, bmp280.Address2,
bmp280PowerMode, bmp280Standby, bmp280FilterCoeff, bmp280TempRes, bmp280PressRes)
}
if errbmp != nil {
return nil, errbmp
}
newbmp := BMP280{sensor: bmp, data: new(bmp280.BMPData)}
go newbmp.run()
return &newbmp, nil
}
func (bmp *BMP280) run() {
bmp.running = true
clock := time.NewTicker(100 * time.Millisecond)
for bmp.running {
<-clock.C
bmp.data = <-bmp.sensor.C
}
}
// Temperature returns the current temperature in degrees C measured by the BMP280
func (bmp *BMP280) Temperature() (float64, error) {
if !bmp.running {
return 0, errBMP
}
return bmp.data.Temperature, nil
}
// Pressure returns the current pressure in mbar measured by the BMP280
func (bmp *BMP280) Pressure() (float64, error) {
if !bmp.running {
return 0, errBMP
}
return bmp.data.Pressure, nil
}
// Close stops the measurements of the BMP280
func (bmp *BMP280) Close() {
bmp.running = false
bmp.sensor.Close()
}

Wyświetl plik

@ -0,0 +1,98 @@
// Package sensors provides a stratux interface to sensors used for AHRS calculations.
package sensors
import (
"../goflying/icm20948"
"github.com/kidoman/embd"
)
const (
gyroRange = 250 // gyroRange is the default range to use for the Gyro.
accelRange = 4 // accelRange is the default range to use for the Accel.
updateFreq = 50 // updateFreq is the rate at which to update the sensor values.
)
// ICM20948 represents an InvenSense ICM-20948 attached to the I2C bus and satisfies
// the IMUReader interface.
type ICM20948 struct {
mpu *icm20948.ICM20948
}
// NewICM20948 returns an instance of the ICM-20948 IMUReader, connected to an
// ICM-20948 attached on the I2C bus with either valid address.
func NewICM20948(i2cbus *embd.I2CBus) (*ICM20948, error) {
var (
m ICM20948
mpu *icm20948.ICM20948
err error
)
mpu, err = icm20948.NewICM20948(i2cbus, gyroRange, accelRange, updateFreq, true, false)
if err != nil {
return nil, err
}
// Set Gyro (Accel) LPFs to 25 Hz to filter out prop/glareshield vibrations above 1200 (1260) RPM
mpu.SetGyroLPF(25)
mpu.SetAccelLPF(25)
m.mpu = mpu
return &m, nil
}
// Read returns the average (since last reading) time, Gyro X-Y-Z, Accel X-Y-Z, Mag X-Y-Z,
// error reading Gyro/Accel, and error reading Mag.
func (m *ICM20948) Read() (T int64, G1, G2, G3, A1, A2, A3, M1, M2, M3 float64, GAError, MAGError error) {
var (
data *icm20948.MPUData
i int8
)
data = new(icm20948.MPUData)
for data.N == 0 && i < 5 {
data = <-m.mpu.CAvg
T = data.T.UnixNano()
G1 = data.G1
G2 = data.G2
G3 = data.G3
A1 = data.A1
A2 = data.A2
A3 = data.A3
M1 = data.M1
M2 = data.M2
M3 = data.M3
GAError = data.GAError
MAGError = data.MagError
i++
}
return
}
// ReadOne returns the most recent time, Gyro X-Y-Z, Accel X-Y-Z, Mag X-Y-Z,
// error reading Gyro/Accel, and error reading Mag.
func (m *ICM20948) ReadOne() (T int64, G1, G2, G3, A1, A2, A3, M1, M2, M3 float64, GAError, MAGError error) {
var (
data *icm20948.MPUData
)
data = new(icm20948.MPUData)
data = <-m.mpu.C
T = data.T.UnixNano()
G1 = data.G1
G2 = data.G2
G3 = data.G3
A1 = data.A1
A2 = data.A2
A3 = data.A3
M1 = data.M1
M2 = data.M2
M3 = data.M3
GAError = data.GAError
MAGError = data.MagError
return
}
// Close stops reading the MPU.
func (m *ICM20948) Close() {
m.mpu.CloseMPU()
}

17
sensors/imu.go 100644
Wyświetl plik

@ -0,0 +1,17 @@
// Package sensors provides a stratux interface to sensors used for AHRS calculations.
package sensors
// IMUReader provides an interface to various Inertial Measurement Unit sensors,
// such as the InvenSense MPU9150 or MPU9250. It is a light abstraction on top
// of the current github.com/westphae/goflying MPU9250 driver so that it can accommodate other types
// of drivers.
type IMUReader interface {
// Read returns the average (since last reading) time, Gyro X-Y-Z, Accel X-Y-Z, Mag X-Y-Z,
// error reading Gyro/Accel, and error reading Mag.
Read() (T int64, G1, G2, G3, A1, A2, A3, M1, M2, M3 float64, GAError, MagError error)
// ReadOne returns the most recent time, Gyro X-Y-Z, Accel X-Y-Z, Mag X-Y-Z,
// error reading Gyro/Accel, and error reading Mag.
ReadOne() (T int64, G1, G2, G3, A1, A2, A3, M1, M2, M3 float64, GAError, MagError error)
// Close stops reading the MPU.
Close()
}

98
sensors/mpu9250.go 100644
Wyświetl plik

@ -0,0 +1,98 @@
// Package sensors provides a stratux interface to sensors used for AHRS calculations.
package sensors
import (
"../goflying/mpu9250"
"github.com/kidoman/embd"
)
const (
mpu9250GyroRange = 250 // mpu9250GyroRange is the default range to use for the Gyro.
mpu9250AccelRange = 4 // mpu9250AccelRange is the default range to use for the Accel.
mpu9250UpdateFreq = 50 // mpu9250UpdateFreq is the rate at which to update the sensor values.
)
// MPU9250 represents an InvenSense MPU9250 attached to the I2C bus and satisfies
// the IMUReader interface.
type MPU9250 struct {
mpu *mpu9250.MPU9250
}
// NewMPU9250 returns an instance of the MPU9250 IMUReader, connected to an
// MPU9250 attached on the I2C bus with either valid address.
func NewMPU9250(i2cbus *embd.I2CBus) (*MPU9250, error) {
var (
m MPU9250
mpu *mpu9250.MPU9250
err error
)
mpu, err = mpu9250.NewMPU9250(i2cbus, mpu9250GyroRange, mpu9250AccelRange, mpu9250UpdateFreq, true, false)
if err != nil {
return nil, err
}
// Set Gyro (Accel) LPFs to 20 (21) Hz to filter out prop/glareshield vibrations above 1200 (1260) RPM
mpu.SetGyroLPF(21)
mpu.SetAccelLPF(21)
m.mpu = mpu
return &m, nil
}
// Read returns the average (since last reading) time, Gyro X-Y-Z, Accel X-Y-Z, Mag X-Y-Z,
// error reading Gyro/Accel, and error reading Mag.
func (m *MPU9250) Read() (T int64, G1, G2, G3, A1, A2, A3, M1, M2, M3 float64, GAError, MAGError error) {
var (
data *mpu9250.MPUData
i int8
)
data = new(mpu9250.MPUData)
for data.N == 0 && i < 5 {
data = <-m.mpu.CAvg
T = data.T.UnixNano()
G1 = data.G1
G2 = data.G2
G3 = data.G3
A1 = data.A1
A2 = data.A2
A3 = data.A3
M1 = data.M1
M2 = data.M2
M3 = data.M3
GAError = data.GAError
MAGError = data.MagError
i++
}
return
}
// ReadOne returns the most recent time, Gyro X-Y-Z, Accel X-Y-Z, Mag X-Y-Z,
// error reading Gyro/Accel, and error reading Mag.
func (m *MPU9250) ReadOne() (T int64, G1, G2, G3, A1, A2, A3, M1, M2, M3 float64, GAError, MAGError error) {
var (
data *mpu9250.MPUData
)
data = new(mpu9250.MPUData)
data = <-m.mpu.C
T = data.T.UnixNano()
G1 = data.G1
G2 = data.G2
G3 = data.G3
A1 = data.A1
A2 = data.A2
A3 = data.A3
M1 = data.M1
M2 = data.M2
M3 = data.M3
GAError = data.GAError
MAGError = data.MagError
return
}
// Close stops reading the MPU.
func (m *MPU9250) Close() {
m.mpu.CloseMPU()
}

Wyświetl plik

@ -0,0 +1,10 @@
// Package sensors provides a stratux interface to sensors used for AHRS calculations.
package sensors
// PressureReader provides an interface to a sensor reading pressure and maybe
// temperature or humidity, like the BMP180 or BMP280.
type PressureReader interface {
Temperature() (temp float64, tempError error) // Temperature returns the temperature in degrees C.
Pressure() (press float64, pressError error) // Pressure returns the atmospheric pressure in mBar.
Close() // Close stops reading from the sensor.
}

Wyświetl plik

@ -1,4 +0,0 @@
#!/bin/bash
screen -S stratux -d -m /usr/bin/start_uat
screen -S dump1090 -d -m /usr/bin/dump1090 --net --device-index 1

Wyświetl plik

@ -1,4 +0,0 @@
#!/bin/bash
/usr/bin/gen_gdl90

Plik diff jest za duży Load Diff

14
test/Makefile 100644
Wyświetl plik

@ -0,0 +1,14 @@
ifeq "$(CIRCLECI)" "true"
#
else
$(if $(GOROOT),,$(error GOROOT is not set!))
endif
SRCS = $(wildcard *.go)
DEST = $(patsubst %.go,%,$(SRCS))
all: $(DEST)
%: %.go
go build $<

Wyświetl plik

@ -0,0 +1,67 @@
package main
import (
"fmt"
"github.com/kidoman/embd"
_ "github.com/kidoman/embd/host/all"
"github.com/kidoman/embd/sensor/bmp180"
)
var i2cbus embd.I2CBus
var myBMP180 *bmp180.BMP180
func readBMP180() (float64, float64, error) { // ºCelsius, Meters
temp, err := myBMP180.Temperature()
if err != nil {
return temp, 0.0, err
}
altitude, err := myBMP180.Altitude()
altitude = float64(1/0.3048) * altitude // Convert meters to feet.
if err != nil {
return temp, altitude, err
}
return temp, altitude, nil
}
func initBMP180() error {
myBMP180 = bmp180.New(i2cbus) //TODO: error checking.
return nil
}
func initI2C() error {
i2cbus = embd.NewI2CBus(1) //TODO: error checking.
return nil
}
// Unused at the moment. 5 second update, since read functions in bmp180 are slow.
func tempAndPressureReader() {
// Read temperature and pressure altitude.
temp, alt, err_bmp180 := readBMP180()
// Process.
if err_bmp180 != nil {
fmt.Printf("readBMP180(): %s\n", err_bmp180.Error())
} else {
fmt.Printf("Temp %f Alt %f\n", temp, alt)
}
}
func initAHRS() error {
if err := initI2C(); err != nil { // I2C bus.
return err
}
if err := initBMP180(); err != nil { // I2C temperature and pressure altitude.
i2cbus.Close()
return err
}
go tempAndPressureReader()
return nil
}
func main() {
fmt.Printf("Hello world!\n")
initAHRS()
for {
tempAndPressureReader()
}
}

134
test/es_dump_csv.go 100644
Wyświetl plik

@ -0,0 +1,134 @@
package main
import (
"database/sql"
"encoding/csv"
"encoding/json"
"fmt"
_ "github.com/mattn/go-sqlite3"
"os"
"time"
)
type dump1090Data struct {
Icao_addr uint32
DF int // Mode S downlink format.
CA int // Lowest 3 bits of first byte of Mode S message (DF11 and DF17 capability; DF18 control field, zero for all other DF types)
TypeCode int // Mode S type code
SubtypeCode int // Mode S subtype code
SBS_MsgType int // type of SBS message (used in "old" 1090 parsing)
SignalLevel float64 // Decimal RSSI (0-1 nominal) as reported by dump1090-mutability. Convert to dB RSSI before setting in TrafficInfo.
Tail *string
Squawk *int // 12-bit squawk code in octal format
Emitter_category *int
OnGround *bool
Lat *float32
Lng *float32
Position_valid bool
NACp *int
Alt *int
AltIsGNSS bool //
GnssDiffFromBaroAlt *int16 // GNSS height above baro altitude in feet; valid range is -3125 to 3125. +/- 3138 indicates larger difference.
Vvel *int16
Speed_valid bool
Speed *uint16
Track *uint16
Timestamp time.Time // time traffic last seen, UTC
}
func main() {
if len(os.Args) < 2 {
fmt.Printf("es_dump_csv <sqlite file>\n")
return
}
db, err := sql.Open("sqlite3", os.Args[1])
if err != nil {
fmt.Printf("sql.Open(): %s\n", err.Error())
return
}
defer db.Close()
rows, err := db.Query("SELECT Data FROM es_messages")
if err != nil {
fmt.Printf("db.Exec(): %s\n", err.Error())
return
}
defer rows.Close()
csvOut := make([][]string, 0)
for rows.Next() {
var Data string
if err := rows.Scan(&Data); err != nil {
fmt.Printf("rows.Scan(): %s\n", err.Error())
continue
}
var d dump1090Data
err := json.Unmarshal([]byte(Data), &d)
if err != nil {
fmt.Printf("json.Unmarshal(): %s\n", err.Error())
continue
}
r := make([]string, 23)
r[0] = fmt.Sprintf("%06x", d.Icao_addr)
r[1] = fmt.Sprintf("%d", d.DF)
r[2] = fmt.Sprintf("%d", d.CA)
r[3] = fmt.Sprintf("%d", d.TypeCode)
r[4] = fmt.Sprintf("%d", d.SubtypeCode)
r[5] = fmt.Sprintf("%d", d.SBS_MsgType)
r[6] = fmt.Sprintf("%f", d.SignalLevel)
if d.Tail != nil {
r[7] = fmt.Sprintf("%s", *d.Tail)
}
if d.Squawk != nil {
r[8] = fmt.Sprintf("%d", *d.Squawk)
}
if d.Emitter_category != nil {
r[9] = fmt.Sprintf("%d", *d.Emitter_category)
}
if d.OnGround != nil {
r[10] = fmt.Sprintf("%t", *d.OnGround)
}
if d.Lat != nil {
r[11] = fmt.Sprintf("%f", *d.Lat)
}
if d.Lng != nil {
r[12] = fmt.Sprintf("%f", *d.Lng)
}
r[13] = fmt.Sprintf("%t", d.Position_valid)
if d.NACp != nil {
r[14] = fmt.Sprintf("%d", *d.NACp)
}
if d.Alt != nil {
r[15] = fmt.Sprintf("%d", *d.Alt)
}
r[16] = fmt.Sprintf("%t", d.AltIsGNSS)
if d.GnssDiffFromBaroAlt != nil {
r[17] = fmt.Sprintf("%d", *d.GnssDiffFromBaroAlt)
}
if d.Vvel != nil {
r[18] = fmt.Sprintf("%d", *d.Vvel)
}
r[19] = fmt.Sprintf("%t", d.Speed_valid)
if d.Speed != nil {
r[20] = fmt.Sprintf("%d", *d.Speed)
}
if d.Track != nil {
r[21] = fmt.Sprintf("%d", *d.Track)
}
r[22] = fmt.Sprintf("%s", d.Timestamp)
csvOut = append(csvOut, r)
}
w := csv.NewWriter(os.Stdout)
w.WriteAll(csvOut)
if err := rows.Err(); err != nil {
fmt.Printf("rows.Scan(): %s\n", err.Error())
return
}
}

Wyświetl plik

@ -0,0 +1,4 @@
#!/bin/bash
cat $1 | grep -a -v ^START | grep -a -v ^PAUSE | grep -a -v ^UNPAUSE | grep -a PUBX,00 | cut -d, -f1,5,6,7,8,9

Wyświetl plik

@ -33,7 +33,7 @@ var logger *log.Logger
var buf bytes.Buffer
func dlac_decode(data []byte, data_len uint32) string {
fmt.Printf("dlac on %s\n", hex.Dump(data))
// fmt.Printf("dlac on %s\n", hex.Dump(data))
step := 0
tab := false
ret := ""
@ -78,7 +78,7 @@ func decodeInfoFrame(frame []byte, frame_start int, frame_len uint32, frame_type
t_opt := ((uint32(data[1]) & 0x01) << 1) | (uint32(data[2]) >> 7)
product_id := ((uint32(data[0]) & 0x1f) << 6) | (uint32(data[1]) >> 2)
fmt.Printf("%d %d\n", data[0], data[1])
// fmt.Printf("%d %d\n", data[0], data[1])
if product_id != 413 { // FIXME.
return
}
@ -184,7 +184,10 @@ func main() {
logger = log.New(&buf, "logger: ", log.Lshortfile)
reader := bufio.NewReader(os.Stdin)
for {
buf, _ := reader.ReadString('\n')
buf, err := reader.ReadString('\n')
if err != nil { // All done.
break
}
parseInput(buf)
}
}

150
test/getairmet.go 100644
Wyświetl plik

@ -0,0 +1,150 @@
package main
import (
"../uatparse"
"bufio"
"encoding/json"
"flag"
"fmt"
"github.com/gansidui/geohash"
"os"
"strconv"
"strings"
)
type UATFrame struct {
FISB_month uint32
FISB_day uint32
FISB_hours uint32
FISB_minutes uint32
FISB_seconds uint32
Product_id uint32
// Text data, if applicable.
Text_data []string
// For AIRMET/NOTAM.
//FIXME: Temporary.
Points map[string][]uatparse.GeoPoint
ReportNumber uint16
ReportYear uint16
LocationIdentifier string
RecordFormat uint8
ReportStart string
ReportEnd string
}
var reports map[string]UATFrame
func groupPoints(f *uatparse.UATFrame) map[string][]uatparse.GeoPoint {
// Index all of the points by GeoHash. Group points together.
res := make(map[string][]uatparse.GeoPoint)
precision := 5 // 6 maybe, 0.000687.
for _, p := range f.Points {
hash, _ := geohash.Encode(p.Lat, p.Lon, precision)
if r, ok := res[hash]; ok {
r = append(r, p)
res[hash] = r
} else {
res[hash] = []uatparse.GeoPoint{p}
}
}
return res
}
func updateReport(f *uatparse.UATFrame) {
if f.ReportNumber == 0 || f.ReportYear == 0 || f.RecordFormat == 0 {
return
}
s := strconv.Itoa(int(f.ReportNumber)) + "-" + strconv.Itoa(int(f.ReportYear))
f.LocationIdentifier = strings.Replace(f.LocationIdentifier, "\x03", "", -1)
if len(f.Points) == 0 && len(f.Text_data) == 0 {
return
}
if p, ok := reports[s]; ok {
if len(f.Points) > 0 {
p.Points = groupPoints(f)
reports[s] = p
}
if len(f.Text_data) > 0 {
p.Text_data = f.Text_data
reports[s] = p
}
} else {
var z UATFrame
z.FISB_month = f.FISB_month
z.FISB_day = f.FISB_day
z.FISB_hours = f.FISB_hours
z.FISB_minutes = f.FISB_minutes
z.FISB_seconds = f.FISB_seconds
z.Product_id = f.Product_id
z.Points = groupPoints(f)
z.ReportNumber = f.ReportNumber
z.ReportYear = f.ReportYear
z.LocationIdentifier = f.LocationIdentifier
z.RecordFormat = f.RecordFormat
z.ReportStart = f.ReportStart
z.ReportEnd = f.ReportEnd
reports[s] = z
}
}
func main() {
reports = make(map[string]UATFrame)
s := "+3cc0978aa66ca3a02100002d3f29688210000000ff0dc45e1e00000000efd305071c142d071d0300bef1e3f1900abdf823bc440abe9ee394a80ac088439a980abfefa3e45c0abef1e3f1900a248000353f6a002210000000ff003e51987c4d5060cb9cb1c30833df2c78cf87f2d74c307d77cf7c10893053857f1d70df2e72c70c1fc75c37cb9cb2cf07f3c707f3c707c17d97df7df780260000353f6a002210000000ff004146247c4d5060cb9cb1c30833df2cf3df07f2d35c307d77cf7d7b71e3881420f3417f1d70df2e72c70c1fc75c37cf0c35d797f0c307f2d707c17d97df7df780648000213c66b022102c45170000bec0487c38f50136d1202c4517bb0defcf0da0c77c79cb26a0844517830defcf0da01145e05176605f1b205f3b205f4b205f6b205176605e00943a0497660e52bf2dcc8013848145d9817c6c8145d980a80250e8145d98178013848125d98334afcb132c8145d981680250e8145d981780138480140322014e120497660cb74ac8145d981780250e8145d9810d2004e1205176605f68033131203075048013848020524890c1105120c75c37c77c79cb2b71d71c31df0cf0c054d47800;rs=31;"
// s := "+3c2643887cdca4802100002d3f29688210000000ff0dc45e1e00000000efd305071c142d071d0300bef1e3f1900abdf823bc440abe9ee394a80ac088439a980abfefa3e45c0abef1e3f1900a248000353f6a002210000000ff003e51987c4d5060cb9cb1c30833df2c78cf87f2d74c307d77cf7c10893053857f1d70df2e72c70c1fc75c37cb9cb2cf07f3c707f3c707c17d97df7df7806c80002d3f29682210000000ff00ce11787c04948d15480b0c8260cb8cb0d358032094e05c1832e32c34d5e04948d1548132454920605501148348063d280919281604c24481539424c832e70cf0c1e04948d154809192baeb8d3a024180d3e05c980931e1923cd833c138050558143e0cb039780430c8143e0d304d31600841a050f833c0538580948b8143e0d703858044cd7943e0cf04e014155e0c91e008c5e0c31c2f5894e008c5e0cd336040340ebc24ae8033ce11380458c407830c2dc336ae8033ce1138033ce507782644830cda814212560c3969e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;rs=17;"
// s := "+3bb40f8953d8b1b0360000353f54002210000000ff006185947c4d5060cb9c70c30833df0d78d707f2e72d5f5df49fcf4c3105fc75c37cb9c70c307f1d70df3c30df0c1fc30c1fcb2c1f05f65f7f3d30c417d2cf4c3105f0545054825526604854c549616018f48315381448e1e0052141b2024e78006c80002d3f29682210000000ff00ce11787c04948d15480b0c8260cb8cb0d358032094e05c1832e32c34d5e04948d1548132454920605501148348063d280919281604c24481539424c832e70cf0c1e04948d154809192baeb8d3a024180d3e05c980931e1923cd833c138050558143e0cb039780430c8143e0d304d31600841a050f833c0538580948b8143e0d703858044cd7943e0cf04e014155e0c91e008c5e0c31c2f5894e008c5e0cd336040340ebc24ae8033ce11380458c407830c2dc336ae8033ce1138033ce507782644830cda814212560c3969e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;rs=29;"
// s := "+3c2643887cdcb780480000213e955822102cc5c1000085bb887c38f50136d1202cc5c1bb0defc30ca0cb6c70d336a084c5c1830defc30ca03170603c24d48143d715280c1d48280534a0c72c34e30ca9834cb2c33c2ec303b0e36c38d38bb1c17828d2ee4e360160317069831c31d6ec46520a33cf1bb01948011cca603d55203c68131525890c5831d70df2db1c34cedc75c38c70c70d3378005700002d3f29688210000000ff28c4631e00000000efd317071c142d071d0300ce1a242695a4ce03a3e63da4cc01039cbda4ca5f633345a4c93ca31db1a4c899034aa1a4c8328379fda4c73fe39e15a4c75fa3d24da4cac703fe89a4ccf3840731a4ce1a242695a4ce1a24269540ce03a3e63d40cc01039cbd40ca5f63334540c93ca31db140c899034aa140c8328379fd40c73fe39e1540c75fa3d24d40cac703fe8940ccf384073140ce1a24269540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;"
replayUATFilename := flag.Bool("stdin", false, "Read from stdin")
flag.Parse()
if *replayUATFilename == true {
reader := bufio.NewReader(os.Stdin)
for {
text, err := reader.ReadString('\n')
if err != nil {
break
}
msg, err := uatparse.New(text)
if err != nil {
// fmt.Printf("err: %s\n", err.Error())
// return
continue
}
msg.DecodeUplink()
for _, frame := range msg.Frames {
updateReport(frame)
}
}
} else {
msg, err := uatparse.New(s)
if err != nil {
fmt.Printf("err: %s\n", err.Error())
return
}
msg.DecodeUplink()
for _, frame := range msg.Frames {
updateReport(frame)
}
}
r := make([]UATFrame, 0)
for _, p := range reports {
if len(p.Points) > 0 && len(p.Text_data) > 0 {
r = append(r, p)
}
}
j, _ := json.Marshal(&r)
fmt.Printf("%s\n", j)
}

Some files were not shown because too many files have changed in this diff Show More