From e6f655551617d170dce03c21732b3ad0101e8d2f Mon Sep 17 00:00:00 2001 From: cam Date: Tue, 15 Oct 2024 18:37:08 +1300 Subject: [PATCH 1/2] Improve flow control for reading sim card status --- cmd/modemd/main.go | 52 ++++++++++++++++-------------- cmd/modemd/modem.go | 44 +++++++++++++------------- cmd/modemd/modemController.go | 59 ++++++++++++++++++++--------------- 3 files changed, 86 insertions(+), 69 deletions(-) diff --git a/cmd/modemd/main.go b/cmd/modemd/main.go index c1e07e6..08345e9 100644 --- a/cmd/modemd/main.go +++ b/cmd/modemd/main.go @@ -84,15 +84,15 @@ func runMain() error { mc := ModemController{ StartTime: time.Now(), //ModemsConfig: conf.ModemsConfig, - ModemsConfig: m, - TestHosts: conf.TestHosts, - TestInterval: conf.TestInterval, - PowerPin: conf.PowerPin, - InitialOnDuration: conf.InitialOnDuration, - FindModemDuration: conf.FindModemDuration, - ConnectionTimeout: conf.ConnectionTimeout, - PingWaitTime: conf.PingWaitTime, - PingRetries: conf.PingRetries, + ModemsConfig: m, + TestHosts: conf.TestHosts, + TestInterval: conf.TestInterval, + PowerPin: conf.PowerPin, + InitialOnDuration: conf.InitialOnDuration, + FindModemDuration: conf.FindModemDuration, + ConnectionTimeout: conf.ConnectionTimeout, + PingWaitTime: conf.PingWaitTime, + //PingRetries: conf.PingRetries, RequestOnDuration: conf.RequestOnDuration, RetryInterval: conf.RetryInterval, RetryFindModemInterval: conf.RetryFindModemInterval, @@ -112,13 +112,19 @@ func runMain() error { } for { - // =========== Wait until modem should be on =========== + // =========== Power off modem if it shouldn't be on then wait until it should be on =========== if !mc.ShouldBeOn() { - log.Println("Waiting until modem should be powered on.") + log.Println("Powering off USB modem.") + if err := mc.SetModemPower(false); err != nil { + return err + } + mc.Modem = nil for !mc.ShouldBeOn() { time.Sleep(5 * time.Second) } } + + // =========== Power on modem =========== if err := mc.SetModemPower(true); err != nil { return err } @@ -183,17 +189,20 @@ func runMain() error { for retries := 5; retries > 0; retries-- { simStatus, err := mc.CheckSimCard() if err == nil && simStatus == "READY" { - mc.Modem.SimReady = true + mc.Modem.SimCardStatus = SimCardReady break } - log.Printf("SIM card not ready. Will cycle power %d more time(s) to find SIM card", retries) + log.Printf("SIM card not ready. Will try %d more time(s) to find SIM card", retries) time.Sleep(5 * time.Second) } - if !mc.Modem.SimReady { - mc.failedToFindSimCard = true + if mc.Modem.SimCardStatus != SimCardReady { + mc.Modem.SimCardStatus = SimCardFailed makeModemEvent("noModemSimCard", &mc) + mc.failedToFindSimCard = true continue } + mc.failedToFindSimCard = false + log.Info("SIM card ready.") // ========== Checking signal strength. ============= log.Println("Checking signal strength.") @@ -222,8 +231,11 @@ func runMain() error { return err } if !connected { - mc.lastFailedConnection = time.Now() - makeModemEvent("modemPingFail", &mc) + // If the modem should be on but failed to connect, then make an event + if mc.ShouldBeOn() { + mc.lastFailedConnection = time.Now() + makeModemEvent("modemPingFail", &mc) + } continue } @@ -248,12 +260,6 @@ func runMain() error { break } } - - log.Println("Powering off USB modem.") - if err := mc.SetModemPower(false); err != nil { - return err - } - mc.Modem = nil } } diff --git a/cmd/modemd/modem.go b/cmd/modemd/modem.go index be2e595..53c67d1 100644 --- a/cmd/modemd/modem.go +++ b/cmd/modemd/modem.go @@ -4,7 +4,6 @@ import ( "fmt" "os/exec" "strings" - "time" goconfig "github.com/TheCacophonyProject/go-config" ) @@ -14,40 +13,43 @@ type Modem struct { Netdev string VendorProduct string ATReady bool - SimReady bool + SimCardStatus SimCardStatus } +type SimCardStatus string + +const ( + SimCardFinding SimCardStatus = "finding" + SimCardReady SimCardStatus = "ready" + SimCardFailed SimCardStatus = "failed" +) + // NewModem return a new modem from the config func NewModem(config goconfig.Modem) *Modem { m := &Modem{ Name: config.Name, Netdev: config.NetDev, VendorProduct: config.VendorProductID, + SimCardStatus: SimCardFinding, } return m } // PingTest will try connecting to one of the provides hosts -func (m *Modem) PingTest(timeoutSec int, retries int, hosts []string) bool { - for i := retries; i > 0; i-- { - for _, host := range hosts { - cmd := exec.Command( - "ping", - "-I", - m.Netdev, - "-n", - "-q", - "-c1", - fmt.Sprintf("-w%d", timeoutSec), - host) - if err := cmd.Run(); err == nil { - return true - } - } - if i > 1 { - log.Printf("ping test failed. %d more retries\n", i-1) +func (m *Modem) PingTest(timeoutSec int, hosts []string) bool { + for _, host := range hosts { + cmd := exec.Command( + "ping", + "-I", + m.Netdev, + "-n", + "-q", + "-c1", + fmt.Sprintf("-w%d", timeoutSec), + host) + if err := cmd.Run(); err == nil { + return true } - time.Sleep(2 * time.Second) } return false } diff --git a/cmd/modemd/modemController.go b/cmd/modemd/modemController.go index 4b84d9b..cdb7d90 100644 --- a/cmd/modemd/modemController.go +++ b/cmd/modemd/modemController.go @@ -39,17 +39,17 @@ import ( ) type ModemController struct { - StartTime time.Time - Modem *Modem - ModemsConfig []goconfig.Modem - TestHosts []string - TestInterval time.Duration - PowerPin string - InitialOnDuration time.Duration - FindModemDuration time.Duration // Time in seconds after USB powered on for the modem to be found - ConnectionTimeout time.Duration // Time in seconds for modem to make a connection to the network - PingWaitTime time.Duration - PingRetries int + StartTime time.Time + Modem *Modem + ModemsConfig []goconfig.Modem + TestHosts []string + TestInterval time.Duration + PowerPin string + InitialOnDuration time.Duration + FindModemDuration time.Duration // Time in seconds after USB powered on for the modem to be found + ConnectionTimeout time.Duration // Time in seconds for modem to make a connection to the network + PingWaitTime time.Duration + //PingRetries int RequestOnDuration time.Duration // Time the modem will stay on in seconds after a request was made RetryInterval time.Duration RetryFindModemInterval time.Duration @@ -257,6 +257,8 @@ func (mc *ModemController) GetStatus() (map[string]interface{}, error) { status["timestamp"] = time.Now().Format(time.RFC1123Z) status["powered"] = mc.IsPowered status["onOffReason"] = mc.onOffReason + status["failedToFindModem"] = mc.failedToFindModem + status["failedToFindSimCard"] = mc.failedToFindSimCard if mc.Modem != nil { // Set details for modem @@ -265,7 +267,6 @@ func (mc *ModemController) GetStatus() (map[string]interface{}, error) { modem["netdev"] = mc.Modem.Netdev modem["vendor"] = mc.Modem.VendorProduct modem["atReady"] = mc.Modem.ATReady - modem["simReady"] = mc.Modem.SimReady modem["connectedTime"] = mc.connectedTime.Format(time.RFC1123Z) if mc.Modem.ATReady { modem["voltage"] = valueOrErrorStr(mc.readVoltage()) @@ -300,13 +301,13 @@ func (mc *ModemController) GetStatus() (map[string]interface{}, error) { } // Set details for SIM card - if mc.Modem.SimReady { - simCard := make(map[string]interface{}) - simCard["simCardStatus"] = valueOrErrorStr(mc.CheckSimCard()) + simCard := make(map[string]interface{}) + simCard["simCardStatus"] = mc.Modem.SimCardStatus + if mc.Modem.SimCardStatus == SimCardReady { simCard["ICCID"] = valueOrErrorStr(mc.readSimICCID()) simCard["provider"] = valueOrErrorStr(mc.readSimProvider()) - status["simCard"] = simCard } + status["simCard"] = simCard /* if gpsEnabled, err := mc.gpsEnabled(); err != nil { @@ -821,6 +822,10 @@ func (mc *ModemController) WaitForConnection() (bool, error) { log.Printf("Waiting %s for modem to connect", mc.ConnectionTimeout) timeout := time.After(mc.ConnectionTimeout) for { + if !mc.ShouldBeOn() { + log.Info("Canceling ping test as modem should be off.") + return false, nil + } select { case <-timeout: mc.lastFailedConnection = time.Now() @@ -837,7 +842,7 @@ func (mc *ModemController) WaitForConnection() (bool, error) { if mc.PingTest() { return true, nil } else { - log.Println("Ping test failed.") + log.Infof("Ping test failed. Trying again until the %s timeout.", mc.ConnectionTimeout) } } } @@ -848,20 +853,24 @@ func (mc *ModemController) WaitForConnection() (bool, error) { // - LastOnRequest: Check if the last "StayOn" request was less than 'RequestOnTime' ago. // - OnWindow: //TODO func (mc *ModemController) shouldBeOnWithReason() (bool, string) { + if time.Now().Before(mc.stayOffUntil) { + return false, fmt.Sprintf("Modem should be off because it was requested to stay off until %s.", mc.stayOffUntil.Format("2006-01-02 15:04:05")) + } + + if time.Now().Before(mc.stayOnUntil) { + return true, fmt.Sprintf("Modem should be on because it was requested to stay on until %s.", mc.stayOnUntil.Format("2006-01-02 15:04:05")) + } + if mc.failedToFindModem { return false, "Modem should be off because it could not be found on boot." } if mc.failedToFindSimCard { - return false, "Modem should be off because it failed to find a SIM card." + return false, "Modem should be off because it could not find a SIM card." } - if time.Now().Before(mc.stayOffUntil) { - return false, fmt.Sprintf("Modem should be off because it was requested to stay off until %s.", mc.stayOffUntil.Format("2006-01-02 15:04:05")) - } - - if time.Now().Before(mc.stayOnUntil) { - return true, fmt.Sprintf("Modem should be on because it was requested to stay on until %s.", mc.stayOnUntil.Format("2006-01-02 15:04:05")) + if mc.Modem != nil && mc.Modem.SimCardStatus == SimCardFailed { + return false, "Modem should be off because it failed to find a SIM card." } if time.Since(mc.lastFailedConnection) < mc.RetryInterval { @@ -941,5 +950,5 @@ func (mc *ModemController) WaitForNextPingTest() bool { func (mc *ModemController) PingTest() bool { seconds := int(mc.PingWaitTime / time.Second) - return mc.Modem.PingTest(seconds, mc.PingRetries, mc.TestHosts) + return mc.Modem.PingTest(seconds, mc.TestHosts) } From a120f0c082bb649834a33b44e2d42ac9394500a6 Mon Sep 17 00:00:00 2001 From: cam Date: Wed, 16 Oct 2024 12:16:48 +1300 Subject: [PATCH 2/2] Only check if a salt command is running when the modem is already powered --- cmd/modemd/modemController.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/modemd/modemController.go b/cmd/modemd/modemController.go index cdb7d90..570969d 100644 --- a/cmd/modemd/modemController.go +++ b/cmd/modemd/modemController.go @@ -893,7 +893,7 @@ func (mc *ModemController) shouldBeOnWithReason() (bool, string) { return true, fmt.Sprintf("Modem should be on because minimum connection duration is %v.", mc.MinConnDuration) } - if saltCommandsRunning() { + if mc.IsPowered && saltCommandsRunning() { return true, fmt.Sprintln("Modem should be on because salt commands are running.") }