kopia lustrzana https://github.com/cyoung/stratux
Merge branch 'master' into wac/improve-ownship-report-v2
commit
e0a22baeac
|
@ -25,6 +25,7 @@ Apps with stratux recognition/support:
|
|||
* iFly GPS 9.4+.
|
||||
* DroidEFB 2.1.1+.
|
||||
* kwikEFIS
|
||||
* Pilots Atlas
|
||||
|
||||
Tested weather/traffic displays:
|
||||
* Avare
|
||||
|
|
|
@ -43,3 +43,6 @@ SUBSYSTEMS=="usb", ATTRS{interface}=="Stratux Serialout", SYMLINK+="serialout%n"
|
|||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1128,6 +1128,8 @@ type settings struct {
|
|||
WiFiChannel int
|
||||
WiFiSecurityEnabled bool
|
||||
WiFiPassphrase string
|
||||
WiFiSmartEnabled bool // "Smart WiFi" - disables the default gateway for iOS.
|
||||
NoSleep bool
|
||||
}
|
||||
|
||||
type status struct {
|
||||
|
@ -1202,6 +1204,7 @@ func defaultSettings() {
|
|||
globalSettings.OwnshipModeS = "F00000"
|
||||
globalSettings.DeveloperMode = false
|
||||
globalSettings.StaticIps = make([]string, 0)
|
||||
globalSettings.NoSleep = false
|
||||
}
|
||||
|
||||
func readSettings() {
|
||||
|
@ -1312,6 +1315,14 @@ func saveWiFiUserSettings() {
|
|||
fmt.Fprintf(writer, "wpa_passphrase=%s\n", globalSettings.WiFiPassphrase)
|
||||
}
|
||||
writer.Flush()
|
||||
|
||||
// "Smart WiFi". Just use one of two pre-made dhcpd config files.
|
||||
dhcpd_config := "/etc/dhcp/dhcpd-not_smart.conf"
|
||||
if globalSettings.WiFiSmartEnabled {
|
||||
dhcpd_config = "/etc/dhcp/dhcpd-smart.conf"
|
||||
}
|
||||
os.Remove("/etc/dhcp/dhcpd.conf")
|
||||
os.Symlink(dhcpd_config, "/etc/dhcp/dhcpd.conf")
|
||||
}
|
||||
|
||||
func openReplay(fn string, compressed bool) (WriteCloser, error) {
|
||||
|
|
|
@ -378,6 +378,9 @@ func handleSettingsSetRequest(w http.ResponseWriter, r *http.Request) {
|
|||
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)
|
||||
}
|
||||
|
|
|
@ -145,6 +145,9 @@ func getDHCPLeases() (map[string]string, error) {
|
|||
***WARNING***: netMutex must be locked before calling this function.
|
||||
*/
|
||||
func isSleeping(k string) bool {
|
||||
if globalSettings.NoSleep == true {
|
||||
return false
|
||||
}
|
||||
ipAndPort := strings.Split(k, ":")
|
||||
// No ping response. Assume disconnected/sleeping device.
|
||||
if lastPing, ok := pingResponse[ipAndPort[0]]; !ok || stratuxClock.Since(lastPing) > (10*time.Second) {
|
||||
|
|
|
@ -36,7 +36,8 @@ 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.conf 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/
|
||||
|
|
|
@ -87,7 +87,9 @@ cp -f ahrs_approx /usr/bin/
|
|||
chmod 755 /usr/bin/ahrs_approx
|
||||
|
||||
# DHCPD Config.
|
||||
cp -f dhcpd.conf /etc/dhcp/dhcpd.conf
|
||||
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
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/gonum/plot"
|
||||
"github.com/gonum/plot/plotter"
|
||||
"github.com/gonum/plot/plotutil"
|
||||
"github.com/gonum/plot/vg"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type XY struct {
|
||||
X float64
|
||||
Y float64
|
||||
}
|
||||
|
||||
func imageWriter() {
|
||||
for {
|
||||
p, err := plot.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.Title.Text = "AHRS Plot"
|
||||
p.X.Label.Text = "Roll"
|
||||
p.Y.Label.Text = "Pitch"
|
||||
|
||||
file, err := os.Open("ahrs_table.log")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
vals := make([]XY, 0)
|
||||
for scanner.Scan() {
|
||||
l := scanner.Text()
|
||||
x := strings.Split(l, ",")
|
||||
if len(x) < 3 {
|
||||
continue
|
||||
}
|
||||
roll, err := strconv.ParseFloat(x[0], 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
pitch, err := strconv.ParseFloat(x[1], 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
v := XY{X: roll, Y: pitch}
|
||||
vals = append(vals, v)
|
||||
}
|
||||
vals_XY := make(plotter.XYs, len(vals))
|
||||
for i := 0; i < len(vals); i++ {
|
||||
vals_XY[i].X = vals[i].X
|
||||
vals_XY[i].Y = vals[i].Y
|
||||
}
|
||||
err = plotutil.AddScatters(p, "First", vals_XY)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := p.Save(8*vg.Inch, 8*vg.Inch, "out.png"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
go imageWriter()
|
||||
http.Handle("/", http.FileServer(http.Dir(".")))
|
||||
err := http.ListenAndServe(":8080", nil)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("managementInterface ListenAndServe: %s\n", err.Error())
|
||||
}
|
||||
|
||||
for {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
SITUATION_URL = "http://127.0.0.1/getSituation"
|
||||
)
|
||||
|
||||
type MySituation struct {
|
||||
AHRSRoll float64
|
||||
AHRSPitch float64
|
||||
}
|
||||
|
||||
var Location MySituation
|
||||
|
||||
var situationMutex *sync.Mutex
|
||||
|
||||
func chkErr(err error) {
|
||||
if err != nil {
|
||||
fmt.Printf("error: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
var currentAHRSString string
|
||||
|
||||
func listener() {
|
||||
t := time.Now()
|
||||
addr := net.UDPAddr{Port: 41504, IP: net.ParseIP("0.0.0.0")}
|
||||
conn, err := net.ListenUDP("udp", &addr)
|
||||
if err != nil {
|
||||
fmt.Printf("error listening: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
for {
|
||||
buf := make([]byte, 1024)
|
||||
n, _, err := conn.ReadFrom(buf)
|
||||
if err != nil {
|
||||
fmt.Printf("Err receive: %s\n", err.Error())
|
||||
continue
|
||||
}
|
||||
buf_encoded := make([]byte, hex.EncodedLen(n))
|
||||
hex.Encode(buf_encoded, buf[:n])
|
||||
t2 := time.Now()
|
||||
time_diff := t2.Sub(t)
|
||||
t = t2
|
||||
|
||||
fmt.Sprintf("%d,%s\n", time_diff/time.Millisecond, buf_encoded)
|
||||
currentAHRSString = string(buf_encoded)
|
||||
}
|
||||
}
|
||||
|
||||
func situationUpdater() {
|
||||
situationUpdateTicker := time.NewTicker(100 * time.Millisecond)
|
||||
for {
|
||||
<-situationUpdateTicker.C
|
||||
situationMutex.Lock()
|
||||
|
||||
resp, err := http.Get(SITUATION_URL)
|
||||
if err != nil {
|
||||
fmt.Printf("HTTP GET error: %s\n", err.Error())
|
||||
situationMutex.Unlock()
|
||||
continue
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
fmt.Printf("HTTP GET body error: %s\n", err.Error())
|
||||
resp.Body.Close()
|
||||
situationMutex.Unlock()
|
||||
continue
|
||||
}
|
||||
|
||||
// fmt.Printf("body: %s\n", string(body))
|
||||
err = json.Unmarshal(body, &Location)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("HTTP JSON unmarshal error: %s\n", err.Error())
|
||||
}
|
||||
resp.Body.Close()
|
||||
situationMutex.Unlock()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
situationMutex = &sync.Mutex{}
|
||||
|
||||
go listener()
|
||||
go situationUpdater()
|
||||
|
||||
tm := time.NewTicker(125 * time.Millisecond)
|
||||
for {
|
||||
<-tm.C
|
||||
fmt.Printf("%f,%f,%s\n", Location.AHRSRoll, Location.AHRSPitch, currentAHRSString)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
t := time.Now()
|
||||
addr := net.UDPAddr{Port: 41504, IP: net.ParseIP("0.0.0.0")}
|
||||
conn, err := net.ListenUDP("udp", &addr)
|
||||
if err != nil {
|
||||
fmt.Printf("ffMonitor(): error listening: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
for {
|
||||
buf := make([]byte, 1024)
|
||||
n, _, err := conn.ReadFrom(buf)
|
||||
if err != nil {
|
||||
fmt.Printf("Err receive: %s\n", err.Error())
|
||||
continue
|
||||
}
|
||||
buf_encoded := make([]byte, hex.EncodedLen(n))
|
||||
hex.Encode(buf_encoded, buf[:n])
|
||||
t2 := time.Now()
|
||||
time_diff := t2.Sub(t)
|
||||
t = t2
|
||||
|
||||
fmt.Printf("%d,%s\n", time_diff/time.Millisecond, buf_encoded)
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Printf("%s: <file>\n", os.Args[0])
|
||||
return
|
||||
}
|
||||
|
||||
f, err := os.Open(os.Args[1])
|
||||
if err != nil {
|
||||
fmt.Printf("error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
|
||||
// Open a socket.
|
||||
BROADCAST_IPv4 := net.IPv4(255, 255, 255, 255)
|
||||
|
||||
// addr, _ := net.ResolveUDPAddr("udp", "192.168.10.10:41501")
|
||||
// laddr, _ := net.ResolveUDPAddr("udp", "192.168.10.1:58814")
|
||||
// conn, err := net.DialUDP("udp", laddr, addr)
|
||||
conn, err := net.DialUDP("udp", nil, &net.UDPAddr{
|
||||
IP: BROADCAST_IPv4,
|
||||
Port: 41504,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("DialUDP(): %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
s := scanner.Text()
|
||||
x := strings.Split(s, ",")
|
||||
if len(x) < 2 {
|
||||
continue
|
||||
}
|
||||
i, err := strconv.ParseInt(x[0], 10, 32)
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing '%s': %s.\n", x[0], err.Error())
|
||||
continue
|
||||
}
|
||||
buf := make([]byte, hex.DecodedLen(len(x[1])))
|
||||
n, err := hex.Decode(buf, []byte(x[1]))
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing '%s': %s.\n", x[1], err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("sleeping %dms, sending %s\n", i, x[1])
|
||||
time.Sleep(time.Duration(i) * time.Millisecond)
|
||||
conn.Write(buf[:n])
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ function SettingsCtrl($rootScope, $scope, $state, $location, $window, $http) {
|
|||
$scope.WiFiPassphrase = settings.WiFiPassphrase;
|
||||
$scope.WiFiSecurityEnabled = settings.WiFiSecurityEnabled;
|
||||
$scope.WiFiChannel = settings.WiFiChannel;
|
||||
$scope.WiFiSmartEnabled = settings.WiFiSmartEnabled;
|
||||
|
||||
$scope.Channels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
||||
}
|
||||
|
@ -287,7 +288,8 @@ function SettingsCtrl($rootScope, $scope, $state, $location, $window, $http) {
|
|||
"WiFiSSID" : $scope.WiFiSSID,
|
||||
"WiFiSecurityEnabled" : $scope.WiFiSecurityEnabled,
|
||||
"WiFiPassphrase" : $scope.WiFiPassphrase,
|
||||
"WiFiChannel" : parseInt($scope.WiFiChannel)
|
||||
"WiFiChannel" : parseInt($scope.WiFiChannel),
|
||||
"WiFiSmartEnabled": $scope.WiFiSmartEnabled
|
||||
};
|
||||
|
||||
// console.log(angular.toJson(newsettings));
|
||||
|
|
|
@ -134,6 +134,12 @@
|
|||
<select id="WiFiChannel" class="input-small col-sm-2 form-control-sm"
|
||||
ng-model="WiFiChannel" ng-options="x for x in Channels"></select>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-7">Smart WiFi</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model="WiFiSmartEnabled" settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<button class="btn btn-primary btn-block" ng-click="updateWiFi()">Submit WiFi Changes</button>
|
||||
</div>
|
||||
|
@ -383,6 +389,7 @@
|
|||
<p>WiFi Security: <b>{{WiFiSecurityEnabled}}</b></p>
|
||||
<p>WiFi Passphrase: <b>{{WiFiPassphrase}}</b></p>
|
||||
<p>WiFi Channel: <b>{{WiFiChannel}}</b></p>
|
||||
<p>Smart mode: <b>{{WiFiSmartEnabled}}</b></p>
|
||||
<p>Your Stratux's WiFi services are now restarting to apply the new settings. This could take up to 30 seconds.<br/>
|
||||
You might have to reconnect to your new WiFi SSID. </p>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="col-sm-12">
|
||||
<div class="text-center">
|
||||
<a ng-click="VersionClick()" class="btn btn-hidden"<strong>Version: <span>{{Version}} ({{Build}})</span></strong></a>
|
||||
<a ng-click="VersionClick()" class="btn btn-hidden"><strong>Version: <span>{{Version}} ({{Build}})</span></strong></a>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
|
|
Ładowanie…
Reference in New Issue