kopia lustrzana https://github.com/cyoung/stratux
Merge remote-tracking branch 'origin/master'
# Conflicts: # selfupdate/makeupdate.shadsbexchange
commit
7338ad4336
|
@ -1,6 +1,6 @@
|
||||||
[submodule "dump1090"]
|
[submodule "dump1090"]
|
||||||
path = dump1090
|
path = dump1090
|
||||||
url = https://github.com/AvSquirrel/dump1090
|
url = https://github.com/stratux/dump1090
|
||||||
[submodule "goflying"]
|
[submodule "goflying"]
|
||||||
path = goflying
|
path = goflying
|
||||||
url = https://github.com/cyoung/goflying
|
url = https://github.com/cyoung/goflying
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -14,7 +14,7 @@ all:
|
||||||
make ahrs_approx xdump978 xdump1090 xgen_gdl90 $(PLATFORMDEPENDENT)
|
make ahrs_approx xdump978 xdump1090 xgen_gdl90 $(PLATFORMDEPENDENT)
|
||||||
|
|
||||||
xgen_gdl90:
|
xgen_gdl90:
|
||||||
go get -t -d -v ./main ./test ./godump978 ./uatparse ./sensors
|
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
|
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
|
||||||
|
|
||||||
fancontrol:
|
fancontrol:
|
||||||
|
|
|
@ -47,3 +47,5 @@ Jet tests (high gain antennas):
|
||||||
* Embraer ERJ 145
|
* Embraer ERJ 145
|
||||||
* Cessna Citation 501
|
* Cessna Citation 501
|
||||||
* Lear 35
|
* Lear 35
|
||||||
|
* Rockwell B-1b
|
||||||
|
* Boeing C-17
|
||||||
|
|
|
@ -5,13 +5,13 @@ machine:
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
pre:
|
pre:
|
||||||
- sudo apt-get update; sudo apt-get install libusb-1.0-0-dev; cd ~/; git clone https://github.com/jpoirier/librtlsdr; cd librtlsdr; mkdir build; cd build; cmake ../; make; sudo make install; sudo ldconfig; cd ~/; mkdir gopath; cd ~/; mkdir gopath; wget https://storage.googleapis.com/golang/go1.6.src.tar.gz; tar -zxvf go1.6.src.tar.gz; cd go/src; export GOROOT_BOOTSTRAP=/usr/local/go; ./make.bash; echo $PATH; echo $GOPATH; go version; env
|
- 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:
|
override:
|
||||||
- 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
|
- 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:
|
test:
|
||||||
override:
|
override:
|
||||||
- make test
|
- make
|
||||||
|
|
||||||
deployment:
|
deployment:
|
||||||
production:
|
production:
|
||||||
|
|
|
@ -11,6 +11,7 @@ iface wlan0 inet static
|
||||||
address 10.26.36.1
|
address 10.26.36.1
|
||||||
netmask 255.255.255.0
|
netmask 255.255.255.0
|
||||||
post-up /usr/sbin/stratux-wifi.sh
|
post-up /usr/sbin/stratux-wifi.sh
|
||||||
|
wireless-power off
|
||||||
|
|
||||||
auto eth0:0
|
auto eth0:0
|
||||||
iface eth0:0 inet static
|
iface eth0:0 inet static
|
||||||
|
|
|
@ -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
|
|
@ -61,6 +61,9 @@ chmod 755 mnt/usr/sbin/sdr-tool.sh
|
||||||
#ping udev
|
#ping udev
|
||||||
cp -f 99-uavionix.rules mnt/etc/udev/rules.d
|
cp -f 99-uavionix.rules mnt/etc/udev/rules.d
|
||||||
|
|
||||||
|
#logrotate conf
|
||||||
|
cp -f logrotate.conf mnt/etc/logrotate.conf
|
||||||
|
|
||||||
#fan/temp control script
|
#fan/temp control script
|
||||||
#remove old script
|
#remove old script
|
||||||
rm -rf mnt/usr/bin/fancontrol.py
|
rm -rf mnt/usr/bin/fancontrol.py
|
||||||
|
|
|
@ -17,6 +17,13 @@ if [ "$_IP" ]; then
|
||||||
printf "My IP address is %s\n" "$_IP"
|
printf "My IP address is %s\n" "$_IP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rotate logs on boot.
|
||||||
|
#
|
||||||
|
/usr/sbin/logrotate /etc/logrotate.conf
|
||||||
|
|
||||||
|
|
||||||
/usr/bin/stratux-screen.py start
|
/usr/bin/stratux-screen.py start
|
||||||
|
|
||||||
route add default gw 10.26.36.1
|
route add default gw 10.26.36.1
|
||||||
|
|
|
@ -1172,12 +1172,25 @@ func addSystemError(err error) {
|
||||||
globalStatus.Errors = append(globalStatus.Errors, err.Error())
|
globalStatus.Errors = append(globalStatus.Errors, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var systemErrsMutex *sync.Mutex
|
||||||
|
var systemErrs map[string]string
|
||||||
|
|
||||||
|
func addSingleSystemErrorf(ident string, format string, a ...interface{}) {
|
||||||
|
systemErrsMutex.Lock()
|
||||||
|
if _, ok := systemErrs[ident]; !ok {
|
||||||
|
// Error hasn't been thrown yet.
|
||||||
|
systemErrs[ident] = fmt.Sprintf(format, a...)
|
||||||
|
globalStatus.Errors = append(globalStatus.Errors, systemErrs[ident])
|
||||||
|
log.Printf("Added critical system error: %s\n", systemErrs[ident])
|
||||||
|
}
|
||||||
|
// Do nothing on this call if the error has already been thrown.
|
||||||
|
systemErrsMutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
func saveSettings() {
|
func saveSettings() {
|
||||||
fd, err := os.OpenFile(configLocation, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0644))
|
fd, err := os.OpenFile(configLocation, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0644))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err_ret := fmt.Errorf("can't save settings %s: %s", configLocation, err.Error())
|
addSingleSystemErrorf("save-settings", "can't save settings %s: %s", configLocation, err.Error())
|
||||||
addSystemError(err_ret)
|
|
||||||
log.Printf("%s\n", err_ret.Error())
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer fd.Close()
|
defer fd.Close()
|
||||||
|
@ -1225,7 +1238,6 @@ func fsWriteTest(dir string) error {
|
||||||
|
|
||||||
func printStats() {
|
func printStats() {
|
||||||
statTimer := time.NewTicker(30 * time.Second)
|
statTimer := time.NewTicker(30 * time.Second)
|
||||||
diskUsageWarning := false
|
|
||||||
for {
|
for {
|
||||||
<-statTimer.C
|
<-statTimer.C
|
||||||
var memstats runtime.MemStats
|
var memstats runtime.MemStats
|
||||||
|
@ -1250,10 +1262,8 @@ func printStats() {
|
||||||
log.Printf("- " + strings.Join(sensorsOutput, ", ") + "\n")
|
log.Printf("- " + strings.Join(sensorsOutput, ", ") + "\n")
|
||||||
}
|
}
|
||||||
// Check if we're using more than 95% of the free space. If so, throw a warning (only once).
|
// Check if we're using more than 95% of the free space. If so, throw a warning (only once).
|
||||||
if !diskUsageWarning && usage.Usage() > 0.95 {
|
if usage.Usage() > 0.95 {
|
||||||
err_p := fmt.Errorf("Disk bytes used = %s (%.1f %%), Disk bytes free = %s (%.1f %%)", humanize.Bytes(usage.Used()), 100*usage.Usage(), humanize.Bytes(usage.Free()), 100*(1-usage.Usage()))
|
addSingleSystemErrorf("disk-space", "Disk bytes used = %s (%.1f %%), Disk bytes free = %s (%.1f %%)", humanize.Bytes(usage.Used()), 100*usage.Usage(), humanize.Bytes(usage.Free()), 100*(1-usage.Usage()))
|
||||||
addSystemError(err_p)
|
|
||||||
diskUsageWarning = true
|
|
||||||
}
|
}
|
||||||
logStatus()
|
logStatus()
|
||||||
}
|
}
|
||||||
|
@ -1385,6 +1395,10 @@ func main() {
|
||||||
mySituation.muBaro = &sync.Mutex{}
|
mySituation.muBaro = &sync.Mutex{}
|
||||||
mySituation.muSatellite = &sync.Mutex{}
|
mySituation.muSatellite = &sync.Mutex{}
|
||||||
|
|
||||||
|
// Set up system error tracking.
|
||||||
|
systemErrsMutex = &sync.Mutex{}
|
||||||
|
systemErrs = make(map[string]string)
|
||||||
|
|
||||||
// Set up status.
|
// Set up status.
|
||||||
globalStatus.Version = stratuxVersion
|
globalStatus.Version = stratuxVersion
|
||||||
globalStatus.Build = stratuxBuild
|
globalStatus.Build = stratuxBuild
|
||||||
|
@ -1410,13 +1424,11 @@ func main() {
|
||||||
vtF, err := strconv.ParseFloat(vtS, 32)
|
vtF, err := strconv.ParseFloat(vtS, 32)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if vtF < 8.0 {
|
if vtF < 8.0 {
|
||||||
var err_os error
|
|
||||||
if globalStatus.HardwareBuild == "FlightBox" {
|
if globalStatus.HardwareBuild == "FlightBox" {
|
||||||
err_os = fmt.Errorf("You are running an old Stratux image that can't be updated fully and is now deprecated. Visit https://www.openflightsolutions.com/flightbox/image-update-required for further information.")
|
addSingleSystemErrorf("deprecated-image", "You are running an old Stratux image that can't be updated fully and is now deprecated. Visit https://www.openflightsolutions.com/flightbox/image-update-required for further information.")
|
||||||
} else {
|
} else {
|
||||||
err_os = fmt.Errorf("You are running an old Stratux image that can't be updated fully and is now deprecated. Visit http://stratux.me/ to update using the latest release image.")
|
addSingleSystemErrorf("deprecated-image", "You are running an old Stratux image that can't be updated fully and is now deprecated. Visit http://stratux.me/ to update using the latest release image.")
|
||||||
}
|
}
|
||||||
addSystemError(err_os)
|
|
||||||
} else {
|
} else {
|
||||||
// Running Jessie or better. Remove some old init.d files.
|
// Running Jessie or better. Remove some old init.d files.
|
||||||
// This made its way in here because /etc/init.d/stratux invokes the update script, which can't delete the init.d file.
|
// This made its way in here because /etc/init.d/stratux invokes the update script, which can't delete the init.d file.
|
||||||
|
@ -1453,9 +1465,7 @@ func main() {
|
||||||
// Duplicate log.* output to debugLog.
|
// Duplicate log.* output to debugLog.
|
||||||
fp, err := os.OpenFile(debugLogf, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
fp, err := os.OpenFile(debugLogf, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err_log := fmt.Errorf("Failed to open '%s': %s", debugLogf, err.Error())
|
addSingleSystemErrorf(debugLogf, "Failed to open '%s': %s", debugLogf, err.Error())
|
||||||
addSystemError(err_log)
|
|
||||||
log.Printf("%s\n", err_log.Error())
|
|
||||||
} else {
|
} else {
|
||||||
defer fp.Close()
|
defer fp.Close()
|
||||||
// Keep the logfile handle for later use
|
// Keep the logfile handle for later use
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -21,13 +22,12 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
"archive/zip"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SettingMessage struct {
|
type SettingMessage struct {
|
||||||
|
@ -403,7 +403,7 @@ func handleDeleteAHRSLogFiles(w http.ResponseWriter, r *http.Request) {
|
||||||
var fn string
|
var fn string
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
fn = f.Name()
|
fn = f.Name()
|
||||||
if v, _ := filepath.Match("sensors_*.csv", fn) ; v {
|
if v, _ := filepath.Match("sensors_*.csv", fn); v {
|
||||||
os.Remove("/var/log/" + fn)
|
os.Remove("/var/log/" + fn)
|
||||||
log.Printf("Deleting AHRS log file %s\n", fn)
|
log.Printf("Deleting AHRS log file %s\n", fn)
|
||||||
}
|
}
|
||||||
|
@ -654,14 +654,12 @@ func defaultServer(w http.ResponseWriter, r *http.Request) {
|
||||||
func handleroPartitionRebuild(w http.ResponseWriter, r *http.Request) {
|
func handleroPartitionRebuild(w http.ResponseWriter, r *http.Request) {
|
||||||
out, err := exec.Command("/usr/sbin/rebuild_ro_part.sh").Output()
|
out, err := exec.Command("/usr/sbin/rebuild_ro_part.sh").Output()
|
||||||
|
|
||||||
var ret_err error
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ret_err = fmt.Errorf("Rebuild RO Partition error: %s", err.Error())
|
addSingleSystemErrorf("partition-rebuild", "Rebuild RO Partition error: %s", err.Error())
|
||||||
} else {
|
} else {
|
||||||
ret_err = fmt.Errorf("Rebuild RO Partition success: %s", out)
|
addSingleSystemErrorf("partition-rebuild", "Rebuild RO Partition success: %s", out)
|
||||||
}
|
}
|
||||||
|
|
||||||
addSystemError(ret_err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://gist.github.com/alexisrobert/982674.
|
// https://gist.github.com/alexisrobert/982674.
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"github.com/tarm/serial"
|
"github.com/tarm/serial"
|
||||||
"golang.org/x/net/icmp"
|
"golang.org/x/net/icmp"
|
||||||
"golang.org/x/net/ipv4"
|
"golang.org/x/net/ipv4"
|
||||||
|
@ -76,19 +74,16 @@ const (
|
||||||
extra_hosts_file = "/etc/stratux-static-hosts.conf"
|
extra_hosts_file = "/etc/stratux-static-hosts.conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
var dhcpLeaseFileWarning bool
|
|
||||||
var dhcpLeaseDirectoryLastTest time.Time // Last time fsWriteTest() was run on the DHCP lease directory.
|
var dhcpLeaseDirectoryLastTest time.Time // Last time fsWriteTest() was run on the DHCP lease directory.
|
||||||
|
|
||||||
// Read the "dhcpd.leases" file and parse out IP/hostname.
|
// Read the "dhcpd.leases" file and parse out IP/hostname.
|
||||||
func getDHCPLeases() (map[string]string, error) {
|
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.
|
// 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.
|
// Only perform the test once every 5 minutes to minimize writes.
|
||||||
if !dhcpLeaseFileWarning && (stratuxClock.Since(dhcpLeaseDirectoryLastTest) >= 5*time.Minute) {
|
if stratuxClock.Since(dhcpLeaseDirectoryLastTest) >= 5*time.Minute {
|
||||||
err := fsWriteTest(dhcp_lease_dir)
|
err := fsWriteTest(dhcp_lease_dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err_p := fmt.Errorf("Write error on '%s', your EFB may have issues receiving weather and traffic.", dhcp_lease_dir)
|
addSingleSystemErrorf("fs-write", "Write error on '%s', your EFB may have issues receiving weather and traffic.", dhcp_lease_dir)
|
||||||
addSystemError(err_p)
|
|
||||||
dhcpLeaseFileWarning = true
|
|
||||||
}
|
}
|
||||||
dhcpLeaseDirectoryLastTest = stratuxClock.Time
|
dhcpLeaseDirectoryLastTest = stratuxClock.Time
|
||||||
}
|
}
|
||||||
|
@ -602,8 +597,6 @@ func networkStatsCounter() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func ffMonitor() {
|
func ffMonitor() {
|
||||||
ff_warned := false // Has a warning been issued via globalStatus.Errors?
|
|
||||||
|
|
||||||
addr := net.UDPAddr{Port: 50113, IP: net.ParseIP("0.0.0.0")}
|
addr := net.UDPAddr{Port: 50113, IP: net.ParseIP("0.0.0.0")}
|
||||||
conn, err := net.ListenUDP("udp", &addr)
|
conn, err := net.ListenUDP("udp", &addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -637,11 +630,7 @@ func ffMonitor() {
|
||||||
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") {
|
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
|
p.FFCrippled = true
|
||||||
//FIXME: AHRS output doesn't need to be disabled globally, just on the ForeFlight client IPs.
|
//FIXME: AHRS output doesn't need to be disabled globally, just on the ForeFlight client IPs.
|
||||||
if !ff_warned {
|
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.")
|
||||||
e := errors.New("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.")
|
|
||||||
addSystemError(e)
|
|
||||||
ff_warned = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
outSockets[ffIpAndPort] = p
|
outSockets[ffIpAndPort] = p
|
||||||
netMutex.Unlock()
|
netMutex.Unlock()
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -484,8 +483,7 @@ func sdrWatcher() {
|
||||||
} else if globalSettings.DeveloperMode {
|
} else if globalSettings.DeveloperMode {
|
||||||
// Throw a "critical error" if developer mode is enabled. Alerts the developer that the daemon was restarted (possibly)
|
// Throw a "critical error" if developer mode is enabled. Alerts the developer that the daemon was restarted (possibly)
|
||||||
// unexpectedly.
|
// unexpectedly.
|
||||||
daemonRestartedErr := fmt.Errorf("System uptime %d seconds. Daemon was restarted.\n", info.Uptime)
|
addSingleSystemErrorf("restart-warn", "System uptime %d seconds. Daemon was restarted.\n", info.Uptime)
|
||||||
addSystemError(daemonRestartedErr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ func pollSensors() {
|
||||||
|
|
||||||
// If it's not currently connected, try connecting to IMU
|
// If it's not currently connected, try connecting to IMU
|
||||||
if globalSettings.IMU_Sensor_Enabled && !globalStatus.IMUConnected {
|
if globalSettings.IMU_Sensor_Enabled && !globalStatus.IMUConnected {
|
||||||
log.Println("AHRS Info: attempting IMU connection.")
|
|
||||||
globalStatus.IMUConnected = initIMU() // I2C accel/gyro/mag.
|
globalStatus.IMUConnected = initIMU() // I2C accel/gyro/mag.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,13 +61,11 @@ func initPressureSensor() (ok bool) {
|
||||||
bmp, err := sensors.NewBMP280(&i2cbus, 100*time.Millisecond)
|
bmp, err := sensors.NewBMP280(&i2cbus, 100*time.Millisecond)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
myPressureReader = bmp
|
myPressureReader = bmp
|
||||||
log.Println("AHRS Info: Successfully initialized BMP280")
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO westphae: make bmp180.go to fit bmp interface
|
//TODO westphae: make bmp180.go to fit bmp interface
|
||||||
|
|
||||||
log.Println("AHRS Info: couldn't initialize BMP280 or BMP180")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,14 +90,14 @@ func tempAndPressureSender() {
|
||||||
// Read temperature and pressure altitude.
|
// Read temperature and pressure altitude.
|
||||||
temp, err = myPressureReader.Temperature()
|
temp, err = myPressureReader.Temperature()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("AHRS Error: Couldn't read temperature from sensor: %s", err)
|
addSingleSystemErrorf("pressure-sensor-temp-read", "AHRS Error: Couldn't read temperature from sensor: %s", err)
|
||||||
}
|
}
|
||||||
press, err = myPressureReader.Pressure()
|
press, err = myPressureReader.Pressure()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("AHRS Error: Couldn't read pressure from sensor: %s", err)
|
addSingleSystemErrorf("pressure-sensor-pressure-read", "AHRS Error: Couldn't read pressure from sensor: %s", err)
|
||||||
failNum++
|
failNum++
|
||||||
if failNum > numRetries {
|
if failNum > numRetries {
|
||||||
log.Printf("AHRS Error: Couldn't read pressure from sensor %d times, closing BMP: %s", failNum, err)
|
// log.Printf("AHRS Error: Couldn't read pressure from sensor %d times, closing BMP: %s", failNum, err)
|
||||||
myPressureReader.Close()
|
myPressureReader.Close()
|
||||||
globalStatus.BMPConnected = false // Try reconnecting a little later
|
globalStatus.BMPConnected = false // Try reconnecting a little later
|
||||||
break
|
break
|
||||||
|
@ -129,16 +126,16 @@ func initIMU() (ok bool) {
|
||||||
imu, err := sensors.NewMPU9250()
|
imu, err := sensors.NewMPU9250()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
myIMUReader = imu
|
myIMUReader = imu
|
||||||
log.Println("AHRS Info: Successfully connected MPU9250")
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO westphae: try to connect to MPU9150 or other IMUs.
|
// TODO westphae: try to connect to MPU9150 or other IMUs.
|
||||||
|
|
||||||
log.Println("AHRS Error: couldn't initialize an IMU")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIXME: Shoud be moved to managementinterface.go and standardized on management interface port.
|
||||||
|
|
||||||
func sensorAttitudeSender() {
|
func sensorAttitudeSender() {
|
||||||
var (
|
var (
|
||||||
t time.Time
|
t time.Time
|
||||||
|
@ -147,7 +144,6 @@ func sensorAttitudeSender() {
|
||||||
failNum uint8
|
failNum uint8
|
||||||
)
|
)
|
||||||
|
|
||||||
log.Println("AHRS Info: initializing new Simple AHRS")
|
|
||||||
s := ahrs.NewSimpleAHRS()
|
s := ahrs.NewSimpleAHRS()
|
||||||
m := ahrs.NewMeasurement()
|
m := ahrs.NewMeasurement()
|
||||||
cal = make(chan (string), 1)
|
cal = make(chan (string), 1)
|
||||||
|
@ -155,9 +151,8 @@ func sensorAttitudeSender() {
|
||||||
// Set up loggers for analysis
|
// Set up loggers for analysis
|
||||||
ahrswebListener, err := ahrsweb.NewKalmanListener()
|
ahrswebListener, err := ahrsweb.NewKalmanListener()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("AHRS Info: couldn't start ahrswebListener: %s\n", err.Error())
|
// addSingleSystemErrorf("ahrs-web-start", "AHRS Info: couldn't start ahrswebListener: %s\n", err.Error())
|
||||||
} else {
|
} else {
|
||||||
log.Println("AHRS Info: ahrswebListener started on port 8000")
|
|
||||||
defer ahrswebListener.Close()
|
defer ahrswebListener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +160,7 @@ func sensorAttitudeSender() {
|
||||||
timer := time.NewTicker(50 * time.Millisecond) // ~20Hz update.
|
timer := time.NewTicker(50 * time.Millisecond) // ~20Hz update.
|
||||||
for {
|
for {
|
||||||
// Set sensor gyro calibrations
|
// Set sensor gyro calibrations
|
||||||
if c, d := &globalSettings.C, &globalSettings.D; d[0]*d[0] + d[1]*d[1] + d[2]*d[2] > 0 {
|
if c, d := &globalSettings.C, &globalSettings.D; d[0]*d[0]+d[1]*d[1]+d[2]*d[2] > 0 {
|
||||||
s.SetCalibrations(c, d)
|
s.SetCalibrations(c, d)
|
||||||
log.Printf("AHRS Info: IMU Calibrations read from settings: accel %6f %6f %6f; gyro %6f %6f %6f\n",
|
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])
|
c[0], c[1], c[2], d[0], d[1], d[2])
|
||||||
|
@ -178,7 +173,7 @@ func sensorAttitudeSender() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sensor quaternion
|
// Set sensor quaternion
|
||||||
if f := &globalSettings.SensorQuaternion; f[0]*f[0] + f[1]*f[1] + f[2]*f[2] + f[3]*f[3] > 0 {
|
if f := &globalSettings.SensorQuaternion; f[0]*f[0]+f[1]*f[1]+f[2]*f[2]+f[3]*f[3] > 0 {
|
||||||
s.SetSensorQuaternion(f)
|
s.SetSensorQuaternion(f)
|
||||||
} else {
|
} else {
|
||||||
select { // Don't block if cal isn't receiving: only need one calibration in the queue at a time.
|
select { // Don't block if cal isn't receiving: only need one calibration in the queue at a time.
|
||||||
|
|
|
@ -55,7 +55,7 @@ Some 1090ES transponders will send the actual registration number of the aircraf
|
||||||
a squawk code.
|
a squawk code.
|
||||||
|
|
||||||
|
|
||||||
### Additional data available to EFBs
|
### Additional data/control available to EFBs
|
||||||
|
|
||||||
Stratux makes available a webserver to retrieve statistics which may be useful to EFBs:
|
Stratux makes available a webserver to retrieve statistics which may be useful to EFBs:
|
||||||
|
|
||||||
|
@ -262,3 +262,16 @@ Subsequent update (2837120 = 2B4A80 reports a newer position, altitude increased
|
||||||
```json
|
```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}
|
{"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.
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ mkdir -p work/bin
|
||||||
cp gen_gdl90 work/bin/
|
cp gen_gdl90 work/bin/
|
||||||
cp fancontrol work/bin/
|
cp fancontrol work/bin/
|
||||||
cp libdump978.so work/bin/
|
cp libdump978.so work/bin/
|
||||||
cp linux-mpu9150/libimu.so work/bin/
|
|
||||||
cp __lib__systemd__system__stratux.service work/bin/
|
cp __lib__systemd__system__stratux.service work/bin/
|
||||||
cp __root__stratux-pre-start.sh work/bin/
|
cp __root__stratux-pre-start.sh work/bin/
|
||||||
cp dump1090/dump1090 work/bin/
|
cp dump1090/dump1090 work/bin/
|
||||||
|
@ -39,10 +38,11 @@ cp image/stratux-wifi.sh work/bin/
|
||||||
cp image/rc.local work/bin/
|
cp image/rc.local work/bin/
|
||||||
cp image/dhcpd.conf work/bin/
|
cp image/dhcpd.conf work/bin/
|
||||||
cp image/interfaces work/bin/
|
cp image/interfaces work/bin/
|
||||||
|
cp image/logrotate.conf work/bin
|
||||||
|
|
||||||
cp test-data/ahrs/ahrs_table.log work/bin/
|
cp test-data/ahrs/ahrs_table.log work/bin/
|
||||||
cp ahrs_approx work/bin/
|
cp ahrs_approx work/bin/
|
||||||
|
|
||||||
|
|
||||||
#TODO: librtlsdr.
|
#TODO: librtlsdr.
|
||||||
cd work/
|
cd work/
|
||||||
cat ../selfupdate/update_header.sh >update.sh
|
cat ../selfupdate/update_header.sh >update.sh
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
cp -f gen_gdl90 /usr/bin/gen_gdl90
|
cp -f gen_gdl90 /usr/bin/gen_gdl90
|
||||||
cp -f libdump978.so /usr/lib/libdump978.so
|
cp -f libdump978.so /usr/lib/libdump978.so
|
||||||
cp -f libimu.so /usr/lib/libimu.so
|
|
||||||
|
|
||||||
|
|
||||||
# Startup script.
|
# Startup script.
|
||||||
|
@ -23,6 +22,9 @@ ln -fs /lib/systemd/system/stratux.service /etc/systemd/system/multi-user.target
|
||||||
cp -f hostapd.conf /etc/hostapd/hostapd.conf
|
cp -f hostapd.conf /etc/hostapd/hostapd.conf
|
||||||
cp -f hostapd-edimax.conf /etc/hostapd/hostapd-edimax.conf
|
cp -f hostapd-edimax.conf /etc/hostapd/hostapd-edimax.conf
|
||||||
|
|
||||||
|
#logrotate config
|
||||||
|
cp -f logrotate.conf /etc/logrotate.conf
|
||||||
|
|
||||||
#WiFi Hostapd ver test and hostapd.conf builder script
|
#WiFi Hostapd ver test and hostapd.conf builder script
|
||||||
cp -f stratux-wifi.sh /usr/sbin/
|
cp -f stratux-wifi.sh /usr/sbin/
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,4 @@
|
||||||
rm -rf /root/stratux-update
|
rm -rf /root/stratux-update
|
||||||
mkdir -p /root/stratux-update
|
mkdir -p /root/stratux-update
|
||||||
cd /root/stratux-update
|
cd /root/stratux-update
|
||||||
rm -f /var/log/stratux.sqlite /var/log/stratux.sqlite-wal /var/log/stratux.sqlite-shm
|
rm -f /var/log/stratux*
|
||||||
rm -f /var/log/stratux.log
|
|
||||||
|
|
|
@ -1,5 +1,110 @@
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="panel-group col-sm-6">
|
<div class="panel-group col-sm-6">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">AHRS</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<span style="position:relative; overflow: hidden;">
|
||||||
|
<button class="btn btn-primary btn-block" ui-turn-on="modalCalibrateForward"
|
||||||
|
ng-disabled="!IMU_Sensor_Enabled">Set AHRS Sensor Orientation</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group reset-flow">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<button class="btn btn-primary btn-block" ui-turn-on="modalCalibrateGyros"
|
||||||
|
ng-disabled="!IMU_Sensor_Enabled">Calibrate Gyros</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group reset-flow">
|
||||||
|
<label class="control-label col-xs-5">G Limits</label>
|
||||||
|
<form name="GLimitForm" ng-submit="updateGLimits()" novalidate ng-disabled="!IMU_Sensor_Enabled">
|
||||||
|
<input class="col-xs-7" type="string" required ng-model="GLimits" ng-blur="updateGLimits()"
|
||||||
|
placeholder="Space-separated negative and positive G meter limits"/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-group col-sm-6">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Configuration</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="form-group reset-flow">
|
||||||
|
<label class="control-label col-xs-5">Mode S Code (Hex)</label>
|
||||||
|
<form name="modeForm" ng-submit="updatemodes()" novalidate>
|
||||||
|
<!-- type="number" not supported except on mobile -->
|
||||||
|
<!-- RegEx for validation: ^[A-Fa-f0-9]{6}$ -->
|
||||||
|
<input class="col-xs-7" type="string" required ng-model="OwnshipModeS" placeholder="FAA HEX code" ng-blur="updatemodes()" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="form-group reset-flow">
|
||||||
|
<label class="control-label col-xs-5">Watch List</label>
|
||||||
|
<form name="watchForm" ng-submit="updatewatchlist()" novalidate>
|
||||||
|
<!-- type="number" not supported except on mobile -->
|
||||||
|
<input class="col-xs-7" type="string" required ng-model="WatchList" placeholder="space-delimited identifiers" ng-blur="updatewatchlist()" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div ng-show="DeveloperMode" class="form-group reset-flow">
|
||||||
|
<label class="control-label col-xs-5">PPM Correction</label>
|
||||||
|
<form name="ppmForm" ng-submit="updateppm()" novalidate>
|
||||||
|
<!-- type="number" not supported except on mobile -->
|
||||||
|
<input class="col-xs-7" type="number_format" required ng-model="PPM" placeholder="integer" ng-blur="updateppm()" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="form-group reset-flow" ng-class="{ 'section_invisible': (!visible_serialout)}">
|
||||||
|
<label class="control-label col-xs-5">Serial Output Baudrate</label>
|
||||||
|
<form name="ppmForm" ng-submit="updateBaud()" novalidate>
|
||||||
|
<!-- type="number" not supported except on mobile -->
|
||||||
|
<input class="col-xs-7" type="number_format" required ng-model="Baud" placeholder="integer" ng-blur="updateBaud()" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="form-group reset-flow">
|
||||||
|
<label class="control-label col-xs-5">Static IPs</label>
|
||||||
|
<form name="staticipForm" ng-submit="updatestaticips()" novalidate>
|
||||||
|
<input class="col-xs-7" type="string" required ng-model="StaticIps" ng-list=" " ng-trim="false" placeholder="space-delimited ip's to send network data" ng-blur="updatestaticips()" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel-group col-sm-6">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Commands</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<!-- Upload. Temporary. -->
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<span ng-show="update_files == ''">
|
||||||
|
<span style="position:relative; overflow: hidden;">
|
||||||
|
<span class="fake-btn fake-btn-block">Click to select System Update file</span>
|
||||||
|
<input style="opacity:0.0; position: absolute; top: 0; right: 0;" class="col-xs-12" type="file" name="update_file" onchange="angular.element(this).scope().setUploadFile(this.files)"/>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span ng-hide="update_files == ''">
|
||||||
|
<button class="btn btn-block" onclick="angular.element(this).scope().uploadFile()">Install {{update_files[0].name}}</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group reset-flow">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<button class="btn btn-primary btn-block" ui-turn-on="modalReboot">Reboot</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group reset-flow">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<button class="btn btn-primary btn-block"ui-turn-on="modalShutdown">Shutdown</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Developer mode area -->
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div ng-show="DeveloperMode" class="panel-group col-sm-6">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">Hardware</div>
|
<div class="panel-heading">Hardware</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -42,8 +147,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div ng-show="DeveloperMode" class="panel-group col-sm-6">
|
||||||
<div class="panel-group col-sm-6">
|
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">Diagnostics</div>
|
<div class="panel-heading">Diagnostics</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -75,120 +179,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel-group col-sm-6">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">AHRS</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<span style="position:relative; overflow: hidden;">
|
|
||||||
<button class="btn btn-primary btn-block" ui-turn-on="modalCalibrateForward"
|
|
||||||
ng-disabled="!IMU_Sensor_Enabled">Set AHRS Sensor Orientation</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="form-group reset-flow">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<button class="btn btn-primary btn-block" ui-turn-on="modalCalibrateGyros"
|
|
||||||
ng-disabled="!IMU_Sensor_Enabled">Calibrate Gyros</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group reset-flow">
|
|
||||||
<label class="control-label col-xs-5">G Limits</label>
|
|
||||||
<form name="GLimitForm" ng-submit="updateGLimits()" novalidate ng-disabled="!IMU_Sensor_Enabled">
|
|
||||||
<input class="col-xs-7" type="string" required ng-model="GLimits" ng-blur="updateGLimits()"
|
|
||||||
placeholder="Space-separated negative and positive G meter limits"/>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div class="panel-group col-sm-6">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">Configuration</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="form-group reset-flow">
|
|
||||||
<label class="control-label col-xs-5">Mode S Code (Hex)</label>
|
|
||||||
<form name="modeForm" ng-submit="updatemodes()" novalidate>
|
|
||||||
<!-- type="number" not supported except on mobile -->
|
|
||||||
<!-- RegEx for validation: ^[A-Fa-f0-9]{6}$ -->
|
|
||||||
<input class="col-xs-7" type="string" required ng-model="OwnshipModeS" placeholder="FAA HEX code" ng-blur="updatemodes()" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="form-group reset-flow">
|
|
||||||
<label class="control-label col-xs-5">Watch List</label>
|
|
||||||
<form name="watchForm" ng-submit="updatewatchlist()" novalidate>
|
|
||||||
<!-- type="number" not supported except on mobile -->
|
|
||||||
<input class="col-xs-7" type="string" required ng-model="WatchList" placeholder="space-delimited identifiers" ng-blur="updatewatchlist()" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="form-group reset-flow">
|
|
||||||
<label class="control-label col-xs-5">PPM Correction</label>
|
|
||||||
<form name="ppmForm" ng-submit="updateppm()" novalidate>
|
|
||||||
<!-- type="number" not supported except on mobile -->
|
|
||||||
<input class="col-xs-7" type="number_format" required ng-model="PPM" placeholder="integer" ng-blur="updateppm()" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="form-group reset-flow" ng-class="{ 'section_invisible': (!visible_serialout)}">
|
|
||||||
<label class="control-label col-xs-5">Serial Output Baudrate</label>
|
|
||||||
<form name="ppmForm" ng-submit="updateBaud()" novalidate>
|
|
||||||
<!-- type="number" not supported except on mobile -->
|
|
||||||
<input class="col-xs-7" type="number_format" required ng-model="Baud" placeholder="integer" ng-blur="updateBaud()" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel-group col-sm-6">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">Commands</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<!-- Upload. Temporary. -->
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<span ng-show="update_files == ''">
|
|
||||||
<span style="position:relative; overflow: hidden;">
|
|
||||||
<span class="fake-btn fake-btn-block">Click to select System Update file</span>
|
|
||||||
<input style="opacity:0.0; position: absolute; top: 0; right: 0;" class="col-xs-12" type="file" name="update_file" onchange="angular.element(this).scope().setUploadFile(this.files)"/>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span ng-hide="update_files == ''">
|
|
||||||
<button class="btn btn-block" onclick="angular.element(this).scope().uploadFile()">Install {{update_files[0].name}}</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="form-group reset-flow">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<button class="btn btn-primary btn-block" ui-turn-on="modalReboot">Reboot</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group reset-flow">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<button class="btn btn-primary btn-block"ui-turn-on="modalShutdown">Shutdown</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Developer mode area -->
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div ng-show="DeveloperMode" class="panel-group col-sm-6">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">Developer Options</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<div class="form-group reset-flow">
|
|
||||||
<label class="control-label col-xs-5">Static IPs</label>
|
|
||||||
<form name="staticipForm" ng-submit="updatestaticips()" novalidate>
|
|
||||||
<input class="col-xs-7" type="string" required ng-model="StaticIps" ng-list=" " ng-trim="false" placeholder="space-delimited ip's to send network data" ng-blur="updatestaticips()" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue