Skip to content

Commit

Permalink
Merge pull request #31 from CameronRP/add-better-sim-status
Browse files Browse the repository at this point in the history
Improve flow control for reading sim card status
  • Loading branch information
CameronRP authored Oct 16, 2024
2 parents eced3dd + a120f0c commit b9dec37
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 70 deletions.
52 changes: 29 additions & 23 deletions cmd/modemd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
}
Expand Down Expand Up @@ -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.")
Expand Down Expand Up @@ -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
}

Expand All @@ -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
}
}

Expand Down
44 changes: 23 additions & 21 deletions cmd/modemd/modem.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"os/exec"
"strings"
"time"

goconfig "github.com/TheCacophonyProject/go-config"
)
Expand All @@ -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
}
Expand Down
61 changes: 35 additions & 26 deletions cmd/modemd/modemController.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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())
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
Expand All @@ -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)
}
}
}
Expand All @@ -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 {
Expand All @@ -884,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.")
}

Expand Down Expand Up @@ -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)
}

0 comments on commit b9dec37

Please sign in to comment.