Skip to content

Commit

Permalink
merge with tc2 latest
Browse files Browse the repository at this point in the history
This commit tries to get any of the latest changes that are usable on the old cameras, will need further cleaning
  • Loading branch information
Zainrax committed May 7, 2024
1 parent d7b45d5 commit bca32b9
Show file tree
Hide file tree
Showing 10 changed files with 388 additions and 134 deletions.
66 changes: 52 additions & 14 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"
Expand All @@ -44,6 +45,8 @@ import (
saltrequester "github.com/TheCacophonyProject/salt-updater"
"github.com/godbus/dbus"
"github.com/gorilla/mux"
"golang.org/x/text/cases"
"golang.org/x/text/language"

"github.com/TheCacophonyProject/event-reporter/eventclient"
"github.com/TheCacophonyProject/trap-controller/trapdbusclient"
Expand Down Expand Up @@ -121,6 +124,10 @@ func (api *ManagementAPI) GetVersion(w http.ResponseWriter, r *http.Request) {
}

func readFile(file string) string {
if runtime.GOOS == "windows" {
return ""
}

// The /etc/salt/minion_id file contains the ID.
out, err := os.ReadFile(file)
if err != nil {
Expand All @@ -129,6 +136,19 @@ func readFile(file string) string {
return string(out)
}

// Return the time of the last salt update.
func getLastSaltUpdate() string {
timeStr := strings.TrimSpace(readFile("/etc/cacophony/last-salt-update"))
if timeStr == "" {
return ""
}
t, err := time.Parse(time.RFC3339, timeStr)
if err != nil {
return ""
}
return t.Format("2006-01-02 15:04:05")
}

// GetDeviceInfo returns information about this device
func (api *ManagementAPI) GetDeviceInfo(w http.ResponseWriter, r *http.Request) {
var device goconfig.Device
Expand All @@ -140,20 +160,22 @@ func (api *ManagementAPI) GetDeviceInfo(w http.ResponseWriter, r *http.Request)
}

type deviceInfo struct {
ServerURL string `json:"serverURL"`
Groupname string `json:"groupname"`
Devicename string `json:"devicename"`
DeviceID int `json:"deviceID"`
SaltID string `json:"saltID"`
Type string `json:"type"`
ServerURL string `json:"serverURL"`
GroupName string `json:"groupname"`
Devicename string `json:"devicename"`
DeviceID int `json:"deviceID"`
SaltID string `json:"saltID"`
LastUpdated string `json:"lastUpdated"`
Type string `json:"type"`
}
info := deviceInfo{
ServerURL: device.Server,
Groupname: device.Group,
Devicename: device.Name,
DeviceID: device.ID,
SaltID: strings.TrimSpace(readFile("/etc/salt/minion_id")),
Type: getDeviceType(),
ServerURL: device.Server,
GroupName: device.Group,
Devicename: device.Name,
DeviceID: device.ID,
SaltID: strings.TrimSpace(readFile("/etc/salt/minion_id")),
LastUpdated: getLastSaltUpdate(),
Type: getDeviceType(),
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(info)
Expand Down Expand Up @@ -411,6 +433,12 @@ func (api *ManagementAPI) GetConfig(w http.ResponseWriter, r *http.Request) {
}
}

configValuesCC := map[string]interface{}{}
for k, v := range configValues {
configValuesCC[toCamelCase(k)] = v
}
configValues = configValuesCC

valuesAndDefaults := map[string]interface{}{
"values": configValues,
"defaults": configDefaults,
Expand All @@ -424,6 +452,17 @@ func (api *ManagementAPI) GetConfig(w http.ResponseWriter, r *http.Request) {
w.Write(jsonString)
}

func toCamelCase(s string) string {
words := strings.FieldsFunc(s, func(r rune) bool {
return r == '-' || r == '_'
})
c := cases.Title(language.English)
for i := 1; i < len(words); i++ {
words[i] = c.String(words[i])
}
return strings.Join(words, "")
}

// ClearConfigSection will delete the config from a section so the default values will be used.
func (api *ManagementAPI) ClearConfigSection(w http.ResponseWriter, r *http.Request) {
section := r.FormValue("section")
Expand Down Expand Up @@ -774,11 +813,10 @@ func CheckInternetConnection(interfaceName string) bool {
}
return true
}

func (api *ManagementAPI) CheckModemInternetConnection(w http.ResponseWriter, r *http.Request) {
// Check if connected to modem
log.Println("Checking modem connection")
connected := CheckInternetConnection("eth1")
connected := CheckInternetConnection("usb0")
log.Printf("Modem connection: %v", connected)

// Send the current network as a JSON response
Expand Down
115 changes: 115 additions & 0 deletions api/clock.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ package api
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os/exec"
"strings"
"time"

"github.com/TheCacophonyProject/rtc-utils/rtc"
"github.com/godbus/dbus"
)

const (
Expand All @@ -41,9 +43,14 @@ type clockInfo struct {
LowRTCBattery bool
RTCIntegrity bool
NTPSynced bool
Timezone string
}

func (api *ManagementAPI) GetClock(w http.ResponseWriter, r *http.Request) {
if getDeviceType() == "tc2" {
api.GetClockTC2(w, r)
return
}
out, err := exec.Command("date", dateCmdFormat).CombinedOutput()
if err != nil {
serverError(&w, err)
Expand Down Expand Up @@ -72,6 +79,7 @@ func (api *ManagementAPI) GetClock(w http.ResponseWriter, r *http.Request) {
LowRTCBattery: rtcState.LowBattery,
RTCIntegrity: rtcState.ClockIntegrity,
NTPSynced: ntpSynced,
Timezone: getTimezone(),
})
if err != nil {
serverError(&w, err)
Expand All @@ -81,6 +89,19 @@ func (api *ManagementAPI) GetClock(w http.ResponseWriter, r *http.Request) {
}

func (api *ManagementAPI) PostClock(w http.ResponseWriter, r *http.Request) {
timezone := r.FormValue("timezone")
if timezone != "" {
cmd := exec.Command("timedatectl", "set-timezone", timezone)
_, err := cmd.CombinedOutput()
if err != nil {
log.Println(err)
}
}

if getDeviceType() == "tc2" {
api.PostClockTC2(w, r)
return
}
date, err := time.Parse(timeFormat, r.FormValue("date"))
if err != nil {
badRequest(&w, err)
Expand All @@ -96,3 +117,97 @@ func (api *ManagementAPI) PostClock(w http.ResponseWriter, r *http.Request) {
serverError(&w, err)
}
}

func getTimezone() string {
cmd := exec.Command("timedatectl", "show", "-p", "Timezone", "--value")

out, err := cmd.Output()
if err != nil {
fmt.Printf("Error getting timezone: %v\n", err)
return ""
}
return strings.TrimSpace(string(out))
}

func (api *ManagementAPI) GetClockTC2(w http.ResponseWriter, r *http.Request) {
conn, err := dbus.SystemBus()
if err != nil {
log.Println(err)
http.Error(w, "Failed to connect to DBus", http.StatusInternalServerError)
return
}
rtcDBus := conn.Object("org.cacophony.RTC", "/org/cacophony/RTC")

var t string
var integrity bool
err = rtcDBus.Call("org.cacophony.RTC.GetTime", 0).Store(&t, &integrity)
if err != nil {
log.Println(err)
http.Error(w, "Failed to get rtc status", http.StatusInternalServerError)
return
}
rtcTime, err := time.Parse("2006-01-02T15:04:05Z07:00", t)
if err != nil {
log.Println(err)
http.Error(w, "Failed to get rtc status", http.StatusInternalServerError)
return
}

out, err := exec.Command("date", dateCmdFormat).CombinedOutput()
if err != nil {
serverError(&w, err)
return
}
systemTime, err := time.Parse(timeFormat, strings.TrimSpace(string(out)))
if err != nil {
serverError(&w, err)
return
}

ntpSynced, err := isNTPSynced()
if err != nil {
serverError(&w, err)
return
}

b, err := json.Marshal(&clockInfo{
RTCTimeUTC: rtcTime.UTC().Format(timeFormat),
RTCTimeLocal: rtcTime.Local().Format(timeFormat),
SystemTime: systemTime.Format(timeFormat),
RTCIntegrity: integrity,
NTPSynced: ntpSynced,
Timezone: getTimezone(),
})
if err != nil {
serverError(&w, err)
return
}
w.Write(b)
}

func (api *ManagementAPI) PostClockTC2(w http.ResponseWriter, r *http.Request) {
date, err := time.Parse(timeFormat, r.FormValue("date"))
if err != nil {
badRequest(&w, err)
return
}

conn, err := dbus.SystemBus()
if err != nil {
log.Println(err)
http.Error(w, "Failed to connect to DBus", http.StatusInternalServerError)
return
}
rtcDBus := conn.Object("org.cacophony.RTC", "/org/cacophony/RTC")
err = rtcDBus.Call("org.cacophony.RTC.SetTime", 0, date.Format("2006-01-02T15:04:05Z07:00")).Store()
if err != nil {
log.Println(err)
http.Error(w, "Failed to get rtc status", http.StatusInternalServerError)
return
}
}

func isNTPSynced() (bool, error) {
out, err := exec.Command("timedatectl", "status").Output()
return strings.Contains(string(out), "synchronized: yes"), err
}
21 changes: 12 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/TheCacophonyProject/audiobait/v3 v3.0.1
github.com/TheCacophonyProject/event-reporter v1.3.2-0.20200210010421-ca3fcb76a231
github.com/TheCacophonyProject/go-api v1.1.0
github.com/TheCacophonyProject/go-config v1.9.1
github.com/TheCacophonyProject/go-config v1.9.2
github.com/TheCacophonyProject/go-cptv v0.0.0-20201215230510-ae7134e91a71
github.com/TheCacophonyProject/lepton3 v0.0.0-20211005194419-22311c15d6ee
github.com/TheCacophonyProject/rtc-utils v1.2.0
Expand All @@ -15,33 +15,36 @@ require (
github.com/godbus/dbus v4.1.0+incompatible
github.com/gorilla/mux v1.8.0
github.com/nathan-osman/go-sunrise v1.0.0 // indirect
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4
golang.org/x/net v0.10.0
)

require github.com/TheCacophonyProject/trap-controller v0.0.0-20230227002937-262a1adfaa47
require (
github.com/TheCacophonyProject/trap-controller v0.0.0-20230227002937-262a1adfaa47
golang.org/x/text v0.14.0
)

require (
github.com/TheCacophonyProject/event-reporter/v3 v3.3.0 // indirect
github.com/TheCacophonyProject/window v0.0.0-20200312071457-7fc8799fdce7 // indirect
github.com/boltdb/bolt v1.3.1 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/gobuffalo/envy v1.9.0 // indirect
github.com/gobuffalo/packd v1.0.0 // indirect
github.com/gobuffalo/envy v1.10.2 // indirect
github.com/gobuffalo/packd v1.0.2 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/joho/godotenv v1.4.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/mitchellh/mapstructure v1.4.2 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/rogpeppe/go-internal v1.8.0 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.9.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/sys v0.14.0 // indirect
gopkg.in/ini.v1 v1.64.0 // indirect
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
Loading

0 comments on commit bca32b9

Please sign in to comment.