package station import ( "fmt" "os" "strings" "time" ) // Close releases the log file. It is safe to call more than once. func (s *Station) Close() { s.mu.Lock() defer s.mu.Unlock() s.closeLogLocked() } func (s *Station) openLog() { f, err := os.OpenFile(s.logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o600) if err != nil { s.logNotice = "Cannot write " + s.logPath if s.state.Talker == "" { s.state.Detail = s.logNotice } return } s.logFile = f } func (s *Station) closeLogLocked() { if s.logFile != nil { s.logFile.Close() s.logFile = nil } } func (s *Station) writeLog(ts time.Time, msg string) { if s.logFile == nil { return } line := ts.Format(time.RFC3339) + " " + msg + "\n" if _, err := s.logFile.Write([]byte(line)); err != nil { s.closeLogLocked() if s.logNotice == "" { s.logNotice = "Cannot write " + s.logPath } } } func (s *Station) noteTransmitLocked() { s.noteTransmitAt(s.clock.Now()) } func (s *Station) noteTransmitAt(now time.Time) { tx := s.transmitting() if tx && !s.sending { s.sending = true s.sendStart = now return } if !tx && s.sending { start := s.sendStart s.sending = false s.writeLog(start, fmt.Sprintf("sending for %d seconds.", wholeSeconds(start, now))) } } func (s *Station) closeTalkerLocked(now time.Time) { if s.talkCall == "" { return } call := s.talkCall start := s.talkStart s.talkCall = "" s.writeLog(start, fmt.Sprintf("%s talked for %d seconds.", call, wholeSeconds(start, now))) } func (s *Station) noteDownLocked(now time.Time, dial bool) { s.closeTalkerLocked(now) s.state.Connection = "Disconnected" s.remoteTalker = "" s.roomBusy = false s.noteTransmitAt(now) switch { case s.up: s.up = false s.outage = true s.writeLog(now, "disconnected") case dial && !s.outage: s.outage = true s.writeLog(now, "disconnected") } s.publish() } func (s *Station) endFatal(msg string, log bool) { s.mu.Lock() defer s.mu.Unlock() if s.fatal != "" { return } now := s.clock.Now() s.closeTalkerLocked(now) s.fatal = msg s.remoteTalker = "" s.roomBusy = false s.noteTransmitAt(now) if log { s.up = false s.outage = true s.writeLog(now, oneLine(msg)) } s.publish() } func wholeSeconds(start, end time.Time) int { d := end.Sub(start) if d <= 0 { return 0 } return int(d / time.Second) } func oneLine(msg string) string { return strings.NewReplacer("\r\n", " ", "\n", " ", "\r", " ").Replace(msg) }