Function bodies 80 total
main.NewApp function · go · L39-L45 (7 LOC)app.go
func NewApp() *App {
return &App{
defs: sensor.DefaultDefinitions(),
units: sensor.UnitMetric,
commLog: newCommLog(),
}
}main.App.Connect method · go · L67-L95 (29 LOC)app.go
func (a *App) Connect(port string, baud int) error {
a.mu.Lock()
defer a.mu.Unlock()
if a.connected {
return fmt.Errorf("already connected")
}
if baud <= 0 {
baud = protocol.DefaultBaudRate
}
a.conn = protocol.NewSerialConn(port, baud)
if err := a.conn.Open(); err != nil {
return err
}
a.ecu = protocol.NewECU(a.conn, a.defs)
a.connected = true
runtime.EventsEmit(a.ctx, "connection:status", map[string]interface{}{
"connected": true,
"port": port,
"baud": baud,
})
a.log("info", "Connected to ECU", fmt.Sprintf("port=%s baud=%d", port, baud))
return nil
}main.App.ConnectDemo method · go · L98-L119 (22 LOC)app.go
func (a *App) ConnectDemo() error {
a.mu.Lock()
defer a.mu.Unlock()
if a.connected {
return fmt.Errorf("already connected")
}
a.sim = protocol.NewSimulator(a.defs)
a.connected = true
a.demoMode = true
runtime.EventsEmit(a.ctx, "connection:status", map[string]interface{}{
"connected": true,
"port": "DEMO",
"baud": 0,
"demo": true,
})
a.log("info", "Connected in DEMO mode", "simulated ECU")
return nil
}main.App.Disconnect method · go · L129-L160 (32 LOC)app.go
func (a *App) Disconnect() error {
a.mu.Lock()
defer a.mu.Unlock()
if a.lg != nil && a.lg.IsRunning() {
a.lg.Stop()
}
if a.csvWriter != nil {
a.csvWriter.Close()
a.csvWriter = nil
}
if a.conn != nil {
a.conn.Close()
}
a.connected = false
a.demoMode = false
a.ecu = nil
a.sim = nil
a.conn = nil
a.lg = nil
if a.ctx != nil {
runtime.EventsEmit(a.ctx, "connection:status", map[string]interface{}{
"connected": false,
})
}
return nil
}main.App.SetActiveSensors method · go · L175-L212 (38 LOC)app.go
func (a *App) SetActiveSensors(slugs []string) error {
a.mu.Lock()
defer a.mu.Unlock()
upperSlugs := make([]string, len(slugs))
for i, s := range slugs {
upperSlugs[i] = strings.ToUpper(s)
}
indices, notFound := sensor.SlugsToIndices(a.defs, upperSlugs)
if len(notFound) > 0 {
slog.Warn("unknown sensors", "slugs", notFound)
}
// Add INJD if RPM and INJP are both selected
hasRPM, hasINJP := false, false
for _, idx := range indices {
if a.defs[idx].Slug == "RPM" {
hasRPM = true
}
if a.defs[idx].Slug == "INJP" {
hasINJP = true
}
}
if hasRPM && hasINJP {
if injdIdx, _ := sensor.FindBySlug(a.defs, "INJD"); injdIdx >= 0 {
indices = append(indices, injdIdx)
}
}
a.activeIndices = indices
if a.lg != nil {
a.lg.SetIndices(indices)
}
return nil
}main.App.StartMonitoring method · go · L215-L289 (75 LOC)app.go
func (a *App) StartMonitoring() error {
a.mu.Lock()
defer a.mu.Unlock()
if !a.connected {
return fmt.Errorf("not connected")
}
if a.lg != nil && a.lg.IsRunning() {
return nil // already running
}
indices := a.activeIndices
if len(indices) == 0 {
indices = sensor.AllPollableIndices(a.defs)
a.activeIndices = indices
}
var poller logger.SamplePoller
var pollRate time.Duration
if a.demoMode {
poller = a.sim
pollRate = 50 * time.Millisecond // 20Hz for smooth UI updates
} else {
poller = a.ecu
pollRate = 1 * time.Millisecond // as fast as possible for real ECU
}
a.lg = logger.NewWithRate(poller, a.defs, indices, a.units, pollRate)
a.lg.OnError(func(err error) {
a.log("warn", "Poll error", err.Error())
})
a.lg.OnDisconnect(func() {
a.log("error", "ECU communication lost", "Too many consecutive errors — check cable")
if a.ctx != nil {
runtime.EventsEmit(a.ctx, "connection:status", map[string]interface{}{
"connected": false,
"reason": main.App.StopMonitoring method · go · L292-L300 (9 LOC)app.go
func (a *App) StopMonitoring() {
a.mu.Lock()
defer a.mu.Unlock()
if a.lg != nil {
a.lg.Stop()
a.log("info", "Monitoring stopped", "")
}
}Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
main.App.StartLogging method · go · L303-L336 (34 LOC)app.go
func (a *App) StartLogging(filename string) error {
a.mu.Lock()
defer a.mu.Unlock()
if a.csvWriter != nil {
return fmt.Errorf("already logging")
}
indices := a.activeIndices
if len(indices) == 0 {
indices = sensor.AllPollableIndices(a.defs)
}
var err error
a.csvWriter, err = logger.NewCSVWriter(filename, a.defs, indices, a.units)
if err != nil {
return err
}
if a.lg != nil {
a.lg.OnSample(func(sample sensor.Sample) {
if a.csvWriter != nil {
a.csvWriter.WriteSample(sample)
}
})
}
runtime.EventsEmit(a.ctx, "logging:status", map[string]interface{}{
"logging": true,
"filename": filename,
})
return nil
}main.App.StopLogging method · go · L339-L357 (19 LOC)app.go
func (a *App) StopLogging() error {
a.mu.Lock()
defer a.mu.Unlock()
if a.csvWriter == nil {
return nil
}
count := a.csvWriter.Count()
err := a.csvWriter.Close()
a.csvWriter = nil
runtime.EventsEmit(a.ctx, "logging:status", map[string]interface{}{
"logging": false,
"count": count,
})
return err
}main.App.ReadDTCs method · go · L360-L405 (46 LOC)app.go
func (a *App) ReadDTCs() (*protocol.DTCResult, error) {
a.mu.Lock()
defer a.mu.Unlock()
if !a.connected {
return nil, fmt.Errorf("not connected")
}
if a.demoMode {
a.log("info", "Reading DTCs (DEMO)", "")
result := &protocol.DTCResult{
ActiveRaw: 0x0022, // bits 1 + 5
StoredRaw: 0x0406, // bits 1, 2, 10
Active: []protocol.DTCCode{
{Bit: 1, Code: "12", Description: "Intake air flow sensor"},
{Bit: 5, Code: "21", Description: "Engine coolant temperature sensor"},
},
Stored: []protocol.DTCCode{
{Bit: 1, Code: "12", Description: "Intake air flow sensor"},
{Bit: 2, Code: "13", Description: "Intake air temperature sensor"},
{Bit: 10, Code: "31", Description: "Knock sensor"},
},
}
a.log("info", "DTCs read (DEMO)", fmt.Sprintf("active=%d stored=%d", len(result.Active), len(result.Stored)))
return result, nil
}
// Pause monitoring if running to avoid serial bus contention
wasRunning := a.lg != nil && a.lg.IsRunning()
if wasRunning {
main.App.EraseDTCs method · go · L408-L441 (34 LOC)app.go
func (a *App) EraseDTCs() error {
a.mu.Lock()
defer a.mu.Unlock()
if !a.connected {
return fmt.Errorf("not connected")
}
if a.demoMode {
a.log("info", "Erasing DTCs (DEMO)", "")
time.Sleep(500 * time.Millisecond)
a.log("info", "DTCs erased (DEMO)", "OK")
return nil
}
// Pause monitoring if running to avoid serial bus contention
wasRunning := a.lg != nil && a.lg.IsRunning()
if wasRunning {
a.lg.Stop()
}
a.log("info", "Erasing DTCs", "")
err := a.ecu.EraseDTCs()
if wasRunning {
a.lg.Start()
}
if err != nil {
a.log("error", "DTC erase failed", err.Error())
} else {
a.log("info", "DTCs erased", "OK")
}
return err
}main.App.RunActuatorTest method · go · L444-L502 (59 LOC)app.go
func (a *App) RunActuatorTest(command string) (string, error) {
a.mu.Lock()
defer a.mu.Unlock()
if !a.connected {
return "", fmt.Errorf("not connected")
}
commands := map[string]byte{
"fuel-pump": 0xF6,
"purge": 0xF5,
"pressure": 0xF4,
"egr": 0xF3,
"mvic": 0xF2,
"boost": 0xF1,
"inj1": 0xFC,
"inj2": 0xFB,
"inj3": 0xFA,
"inj4": 0xF9,
"inj5": 0xF8,
"inj6": 0xF7,
}
addr, ok := commands[strings.ToLower(command)]
if !ok {
return "", fmt.Errorf("unknown command: %s", command)
}
if a.demoMode {
a.log("info", "Running actuator test (DEMO)", fmt.Sprintf("%s (0x%02X)", command, addr))
time.Sleep(6 * time.Second)
a.log("info", "Actuator test complete (DEMO)", fmt.Sprintf("%s → OK", command))
return "OK (DEMO)", nil
}
// Pause monitoring if running to avoid serial bus contention
wasRunning := a.lg != nil && a.lg.IsRunning()
if wasRunning {
a.lg.Stop()
}
a.log("info", "Running actuator test",main.App.GetAboutInfo method · go · L517-L528 (12 LOC)app.go
func (a *App) GetAboutInfo() *AboutInfo {
return &AboutInfo{
Name: version.Name,
Version: version.Version,
Description: version.Description,
Developers: version.Developers,
Copyright: version.Copyright,
License: version.License,
Attribution: version.Attribution,
URL: version.URL,
}
}main.App.LoadLogFile method · go · L548-L579 (32 LOC)app.go
func (a *App) LoadLogFile() (*LogData, error) {
selection, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
Title: "Open Log File",
Filters: []runtime.FileFilter{
{DisplayName: "Log Files (*.csv, *.mmcd, *.pdb)", Pattern: "*.csv;*.mmcd;*.pdb;*.PDB"},
{DisplayName: "CSV Files (*.csv)", Pattern: "*.csv"},
{DisplayName: "MMCD Binary (*.mmcd)", Pattern: "*.mmcd"},
{DisplayName: "PalmOS PDB (*.pdb)", Pattern: "*.pdb;*.PDB"},
{DisplayName: "All Files (*.*)", Pattern: "*.*"},
},
})
if err != nil {
return nil, err
}
if selection == "" {
return nil, fmt.Errorf("cancelled")
}
slog.Info("loading log file", "path", selection)
lower := strings.ToLower(selection)
switch {
case strings.HasSuffix(lower, ".csv"):
return a.loadCSVLog(selection)
case strings.HasSuffix(lower, ".mmcd"):
return a.loadBinaryLog(selection)
case strings.HasSuffix(lower, ".pdb"):
return a.loadPDBLog(selection)
default:
return nil, fmt.Errorf("unsupported file type: main.App.loadCSVLog method · go · L581-L602 (22 LOC)app.go
func (a *App) loadCSVLog(path string) (*LogData, error) {
csvLog, err := logger.ReadCSVLog(path)
if err != nil {
return nil, err
}
// Generate elapsed times: assume ~50ms per sample if no real timestamps
elapsed := make([]float64, csvLog.Count)
for i := range elapsed {
elapsed[i] = float64(i) * 50.0
}
// Use Elapsed_ms from CSV if available
if csvLog.ElapsedMs != nil && len(csvLog.ElapsedMs) == csvLog.Count {
elapsed = csvLog.ElapsedMs
}
return &LogData{
Slugs: csvLog.Slugs,
Data: csvLog.Data,
ElapsedMs: elapsed,
Count: csvLog.Count,
Name: path,
}, nil
}All rows scored by the Repobility analyzer (https://repobility.com)
main.App.loadBinaryLog method · go · L604-L649 (46 LOC)app.go
func (a *App) loadBinaryLog(path string) (*LogData, error) {
binLog, err := logger.ReadBinaryLog(path)
if err != nil {
return nil, err
}
// Convert samples to float data keyed by slug
data := make(map[string][]float64)
var slugs []string
for _, idx := range binLog.Indices {
if idx >= 0 && idx < len(a.defs) && a.defs[idx].Exists {
slug := a.defs[idx].Slug
slugs = append(slugs, slug)
data[slug] = make([]float64, 0, len(binLog.Samples))
}
}
elapsed := make([]float64, 0, len(binLog.Samples))
var startTime time.Time
for i, sample := range binLog.Samples {
if i == 0 {
startTime = sample.Time
}
elapsed = append(elapsed, float64(sample.Time.Sub(startTime).Milliseconds()))
sample.ComputeDerivatives(a.defs)
for _, idx := range binLog.Indices {
if idx >= 0 && idx < len(a.defs) && a.defs[idx].Exists {
slug := a.defs[idx].Slug
if sample.HasData(idx) {
data[slug] = append(data[slug], a.defs[idx].Convert(sample.RawData[idx], binLog.Units))
main.App.loadPDBLog method · go · L651-L700 (50 LOC)app.go
func (a *App) loadPDBLog(path string) (*LogData, error) {
pdbLog, err := logger.ParsePDB(path)
if err != nil {
return nil, err
}
// Determine which sensors are present across all samples
var presentMask uint32
for _, s := range pdbLog.Samples {
presentMask |= s.DataPresent
}
data := make(map[string][]float64)
var slugs []string
var indices []int
for i, def := range a.defs {
if def.Exists && presentMask&(1<<uint(i)) != 0 {
slugs = append(slugs, def.Slug)
indices = append(indices, i)
data[def.Slug] = make([]float64, 0, len(pdbLog.Samples))
}
}
elapsed := make([]float64, 0, len(pdbLog.Samples))
var startTime time.Time
for i, sample := range pdbLog.Samples {
if i == 0 {
startTime = sample.Time
}
elapsed = append(elapsed, float64(sample.Time.Sub(startTime).Milliseconds()))
sample.ComputeDerivatives(a.defs)
for _, idx := range indices {
slug := a.defs[idx].Slug
if sample.HasData(idx) {
data[slug] = append(data[slug], a.defs[idx].Convmain.CommLog.add method · go · L43-L50 (8 LOC)commlog.go
func (cl *CommLog) add(entry LogEntry) {
cl.mu.Lock()
defer cl.mu.Unlock()
cl.entries = append(cl.entries, entry)
if len(cl.entries) > maxLogEntries {
cl.entries = cl.entries[len(cl.entries)-maxLogEntries:]
}
}main.CommLog.getAll method · go · L52-L58 (7 LOC)commlog.go
func (cl *CommLog) getAll() []LogEntry {
cl.mu.Lock()
defer cl.mu.Unlock()
out := make([]LogEntry, len(cl.entries))
copy(out, cl.entries)
return out
}main.App.log method · go · L61-L88 (28 LOC)commlog.go
func (a *App) log(level, message, detail string) {
entry := LogEntry{
Time: time.Now().Format("15:04:05.000"),
Level: level,
Message: message,
Detail: detail,
}
if a.commLog == nil {
a.commLog = newCommLog()
}
a.commLog.add(entry)
// Emit to frontend
if a.ctx != nil {
runtime.EventsEmit(a.ctx, "comm:log", entry)
}
// Also log via slog
switch level {
case "error":
slog.Error(message, "detail", detail)
case "warn":
slog.Warn(message, "detail", detail)
default:
slog.Info(message, "detail", detail)
}
}main.App.GetCommLog method · go · L91-L96 (6 LOC)commlog.go
func (a *App) GetCommLog() []LogEntry {
if a.commLog == nil {
return nil
}
return a.commLog.getAll()
}main.App.GetCommStats method · go · L99-L112 (14 LOC)commlog.go
func (a *App) GetCommStats() *CommStats {
a.mu.Lock()
defer a.mu.Unlock()
stats := &CommStats{}
if a.lg != nil {
ls := a.lg.Stats()
stats.SamplesTotal = ls.SampleCount
stats.ErrorsTotal = ls.ErrorCount
stats.CurrentHz = ls.CurrentHz
stats.UptimeSeconds = ls.UptimeSeconds
}
return stats
}main.App.emitStats method · go · L115-L137 (23 LOC)commlog.go
func (a *App) emitStats() {
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for {
<-ticker.C
a.mu.Lock()
if a.lg == nil || !a.lg.IsRunning() {
a.mu.Unlock()
return
}
ls := a.lg.Stats()
a.mu.Unlock()
if a.ctx != nil {
runtime.EventsEmit(a.ctx, "comm:stats", CommStats{
SamplesTotal: ls.SampleCount,
ErrorsTotal: ls.ErrorCount,
CurrentHz: ls.CurrentHz,
UptimeSeconds: ls.UptimeSeconds,
})
}
}
}Repobility · MCP-ready · https://repobility.com
cli.init function · go · L111-L116 (6 LOC)internal/cli/import.go
func init() {
importCmd.Flags().StringVarP(&importFile, "file", "f", "", "PDB file to import")
importCmd.Flags().StringVarP(&importOutput, "output", "o", "", "Output file (auto-generated if empty)")
importCmd.Flags().StringVar(&importFormat, "format", "csv", "Output format: csv or mmcd")
rootCmd.AddCommand(importCmd)
}cli.init function · go · L175-L180 (6 LOC)internal/cli/log.go
func init() {
logCmd.Flags().StringVarP(&logSensors, "sensors", "s", "", "Sensor slugs to poll (comma-separated, or 'all')")
logCmd.Flags().StringVarP(&logOutput, "output", "o", "", "Output CSV file path")
logCmd.Flags().BoolVarP(&logDisplay, "display", "d", true, "Show live values in terminal")
rootCmd.AddCommand(logCmd)
}cli.init function · go · L59-L69 (11 LOC)internal/cli/root.go
func init() {
rootCmd.PersistentFlags().StringVarP(&cfgPort, "port", "p", "", "Serial port (e.g. /dev/ttyUSB0, COM3)")
rootCmd.PersistentFlags().IntVarP(&cfgBaud, "baud", "b", 1953, "Serial baud rate")
rootCmd.PersistentFlags().StringVarP(&cfgUnits, "units", "u", "metric", "Unit system: metric, imperial, raw")
rootCmd.PersistentFlags().BoolVarP(&cfgVerbose, "verbose", "v", false, "Enable debug logging")
rootCmd.PersistentFlags().StringVar(&cfgLogFile, "log-file", "", "Write log output to file")
rootCmd.PersistentFlags().BoolVar(&cfgYes, "yes", false, "Skip confirmation prompts")
rootCmd.AddCommand(aboutCmd)
cobra.OnInitialize(initLogging)
}cli.initLogging function · go · L71-L89 (19 LOC)internal/cli/root.go
func initLogging() {
level := slog.LevelInfo
if cfgVerbose {
level = slog.LevelDebug
}
var w io.Writer = os.Stderr
if cfgLogFile != "" {
f, err := os.OpenFile(cfgLogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Fprintf(os.Stderr, "Warning: could not open log file %s: %v\n", cfgLogFile, err)
} else {
w = io.MultiWriter(os.Stderr, f)
}
}
handler := slog.NewTextHandler(w, &slog.HandlerOptions{Level: level})
slog.SetDefault(slog.New(handler))
}cli.confirmPrompt function · go · L93-L102 (10 LOC)internal/cli/root.go
func confirmPrompt(msg string) bool {
if cfgYes {
return true
}
fmt.Printf("%s (y/N): ", msg)
reader := bufio.NewReader(os.Stdin)
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(strings.ToLower(line))
return line == "y" || line == "yes"
}cli.Execute function · go · L105-L110 (6 LOC)internal/cli/root.go
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}logger.NewCSVWriter function · go · L26-L55 (30 LOC)internal/logger/csv.go
func NewCSVWriter(filename string, defs []sensor.Definition, indices []int, units sensor.UnitSystem) (*CSVWriter, error) {
f, err := os.Create(filename)
if err != nil {
return nil, fmt.Errorf("failed to create CSV file %s: %w", filename, err)
}
w := csv.NewWriter(f)
// Write header row
header := []string{"Timestamp", "Elapsed_ms"}
for _, idx := range indices {
if idx >= 0 && idx < len(defs) && defs[idx].Exists {
header = append(header, defs[idx].Slug)
header = append(header, defs[idx].Slug+"_raw")
}
}
if err := w.Write(header); err != nil {
f.Close()
return nil, fmt.Errorf("failed to write CSV header: %w", err)
}
w.Flush()
return &CSVWriter{
file: f,
writer: w,
defs: defs,
indices: indices,
units: units,
}, nil
}logger.CSVWriter.WriteSample method · go · L58-L98 (41 LOC)internal/logger/csv.go
func (cw *CSVWriter) WriteSample(sample sensor.Sample) error {
cw.mu.Lock()
defer cw.mu.Unlock()
if cw.count == 0 {
cw.startTime = sample.Time
}
elapsed := sample.Time.Sub(cw.startTime).Milliseconds()
row := []string{
sample.Time.Format("2006-01-02T15:04:05.000"),
fmt.Sprintf("%d", elapsed),
}
for _, idx := range cw.indices {
if idx >= 0 && idx < len(cw.defs) && cw.defs[idx].Exists {
if sample.HasData(idx) {
row = append(row, cw.defs[idx].Format(sample.RawData[idx], cw.units))
row = append(row, fmt.Sprintf("%d", sample.RawData[idx]))
} else {
row = append(row, "")
row = append(row, "")
}
}
}
if err := cw.writer.Write(row); err != nil {
return fmt.Errorf("failed to write CSV row: %w", err)
}
cw.count++
// Flush every write for crash safety
cw.writer.Flush()
if err := cw.writer.Error(); err != nil {
return fmt.Errorf("CSV flush error: %w", err)
}
return nil
}Source: Repobility analyzer · https://repobility.com
logger.CSVWriter.Close method · go · L101-L111 (11 LOC)internal/logger/csv.go
func (cw *CSVWriter) Close() error {
cw.mu.Lock()
defer cw.mu.Unlock()
cw.writer.Flush()
if err := cw.writer.Error(); err != nil {
cw.file.Close()
return fmt.Errorf("CSV flush error: %w", err)
}
return cw.file.Close()
}logger.ReadCSVLog function · go · L21-L106 (86 LOC)internal/logger/csv_reader.go
func ReadCSVLog(filename string) (*CSVLog, error) {
f, err := os.Open(filename)
if err != nil {
return nil, fmt.Errorf("failed to open CSV: %w", err)
}
defer f.Close()
reader := csv.NewReader(f)
records, err := reader.ReadAll()
if err != nil {
return nil, fmt.Errorf("failed to parse CSV: %w", err)
}
if len(records) < 2 {
return nil, fmt.Errorf("CSV has no data rows")
}
header := records[0]
// Identify converted value columns (not Timestamp, Elapsed_ms, or *_raw)
type colInfo struct {
slug string
col int
}
var cols []colInfo
elapsedCol := -1
for i, h := range header {
if h == "Elapsed_ms" {
elapsedCol = i
continue
}
if h == "Timestamp" || h == "" {
continue
}
if strings.HasSuffix(h, "_raw") {
continue
}
cols = append(cols, colInfo{slug: h, col: i})
}
if len(cols) == 0 {
return nil, fmt.Errorf("no sensor columns found in CSV header")
}
slugs := make([]string, len(cols))
data := make(map[string][]float64, len(cols))
for ilogger.New function · go · L57-L65 (9 LOC)internal/logger/logger.go
func New(poller SamplePoller, defs []sensor.Definition, indices []int, units sensor.UnitSystem) *Logger {
return &Logger{
poller: poller,
defs: defs,
indices: indices,
units: units,
pollRate: 1 * time.Millisecond, // as fast as possible for real ECU
}
}logger.Logger.Stats method · go · L96-L112 (17 LOC)internal/logger/logger.go
func (l *Logger) Stats() LoggerStats {
l.mu.Lock()
defer l.mu.Unlock()
var hz float64
if !l.startTime.IsZero() {
elapsed := time.Since(l.startTime).Seconds()
if elapsed > 0 {
hz = float64(l.sampleCount) / elapsed
}
}
return LoggerStats{
SampleCount: l.sampleCount,
ErrorCount: l.errorCount,
CurrentHz: hz,
UptimeSeconds: time.Since(l.startTime).Seconds(),
}
}logger.Logger.Start method · go · L115-L130 (16 LOC)internal/logger/logger.go
func (l *Logger) Start() error {
l.mu.Lock()
if l.running {
l.mu.Unlock()
return nil
}
ctx, cancel := context.WithCancel(context.Background())
l.cancel = cancel
l.running = true
l.mu.Unlock()
go l.pollLoop(ctx)
slog.Info("logger started", "sensors", len(l.indices))
return nil
}logger.Logger.Stop method · go · L133-L144 (12 LOC)internal/logger/logger.go
func (l *Logger) Stop() {
l.mu.Lock()
defer l.mu.Unlock()
if !l.running {
return
}
l.cancel()
l.running = false
slog.Info("logger stopped")
}logger.Logger.pollLoop method · go · L170-L237 (68 LOC)internal/logger/logger.go
func (l *Logger) pollLoop(ctx context.Context) {
ticker := time.NewTicker(l.pollRate)
defer ticker.Stop()
l.mu.Lock()
l.startTime = time.Now()
l.sampleCount = 0
l.errorCount = 0
l.consecutiveErrs = 0
l.mu.Unlock()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
l.mu.Lock()
indices := make([]int, len(l.indices))
copy(indices, l.indices)
l.mu.Unlock()
if len(indices) == 0 {
time.Sleep(100 * time.Millisecond)
continue
}
sample, err := l.poller.PollSensors(indices)
if err != nil {
l.mu.Lock()
l.errorCount++
l.consecutiveErrs++
consecErrs := l.consecutiveErrs
errCbs := make([]ErrorCallback, len(l.errCbs))
copy(errCbs, l.errCbs)
disconnCb := l.disconnCb
l.mu.Unlock()
slog.Debug("poll error", "error", err, "consecutive", consecErrs)
for _, cb := range errCbs {
cb(err)
}
// Watchdog: if too many consecutive errors, assume disconnect
if consecErrs >= watchdogThreshold {
logger.ParsePDB function · go · L66-L196 (131 LOC)internal/logger/pdb.go
func ParsePDB(filename string) (*PDBLog, error) {
f, err := os.Open(filename)
if err != nil {
return nil, fmt.Errorf("failed to open PDB file: %w", err)
}
defer f.Close()
// Read header
var hdr pdbHeader
if err := binary.Read(f, binary.BigEndian, &hdr); err != nil {
return nil, fmt.Errorf("failed to read PDB header: %w", err)
}
// Validate type and creator
typeStr := string(hdr.Type[:])
creatorStr := string(hdr.Creator[:])
if typeStr != "strm" || creatorStr != "MMCd" {
return nil, fmt.Errorf("not an MMCd log file: type=%q creator=%q", typeStr, creatorStr)
}
// Extract null-terminated name
nameBytes := hdr.Name[:]
nameEnd := 0
for i, b := range nameBytes {
if b == 0 {
nameEnd = i
break
}
}
if nameEnd == 0 {
nameEnd = len(nameBytes)
}
log := &PDBLog{
Name: string(nameBytes[:nameEnd]),
}
// Read record index entries
records := make([]pdbRecordEntry, hdr.NumRecords)
for i := 0; i < int(hdr.NumRecords); i++ {
if err := binary.Read(f, binarMethodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
logger.PDBToCSV function · go · L199-L239 (41 LOC)internal/logger/pdb.go
func PDBToCSV(pdbLog *PDBLog, outputFile string, defs []sensor.Definition, units sensor.UnitSystem) error {
if len(pdbLog.Samples) == 0 {
return fmt.Errorf("no samples in PDB log")
}
// Determine which sensor indices have any data across all samples
var presentMask uint32
for _, s := range pdbLog.Samples {
presentMask |= s.DataPresent
}
var indices []int
for i := 0; i < sensor.MaxSensors; i++ {
if presentMask&(1<<uint(i)) != 0 {
indices = append(indices, i)
}
}
// Also add INJD if RPM and INJP are present
hasRPM := presentMask&(1<<17) != 0
hasINJP := presentMask&(1<<19) != 0
if hasRPM && hasINJP {
indices = append(indices, 20) // INJD
}
writer, err := NewCSVWriter(outputFile, defs, indices, units)
if err != nil {
return err
}
defer writer.Close()
for i := range pdbLog.Samples {
// Compute derivatives (INJD) for each sample
pdbLog.Samples[i].ComputeDerivatives(defs)
if err := writer.WriteSample(pdbLog.Samples[i]); err != nil {
return fmt.Elogger.NewBinaryWriter function · go · L53-L84 (32 LOC)internal/logger/store.go
func NewBinaryWriter(filename string, indices []int, units sensor.UnitSystem) (*BinaryWriter, error) {
f, err := os.Create(filename)
if err != nil {
return nil, fmt.Errorf("failed to create binary log %s: %w", filename, err)
}
// Write header
header := make([]byte, mmcdHeaderSize)
copy(header[0:4], mmcdMagic)
header[4] = mmcdVersion
header[5] = byte(units)
binary.LittleEndian.PutUint16(header[6:8], uint16(len(indices)))
binary.LittleEndian.PutUint32(header[8:12], 0) // sample count placeholder
// header[12:16] reserved
if _, err := f.Write(header); err != nil {
f.Close()
return nil, fmt.Errorf("failed to write header: %w", err)
}
// Write sensor index table
indexTable := make([]byte, len(indices))
for i, idx := range indices {
indexTable[i] = byte(idx)
}
if _, err := f.Write(indexTable); err != nil {
f.Close()
return nil, fmt.Errorf("failed to write index table: %w", err)
}
return &BinaryWriter{file: f}, nil
}logger.BinaryWriter.WriteSample method · go · L87-L99 (13 LOC)internal/logger/store.go
func (bw *BinaryWriter) WriteSample(sample sensor.Sample) error {
buf := make([]byte, mmcdSampleSize)
binary.LittleEndian.PutUint64(buf[0:8], uint64(sample.Time.UnixNano()))
binary.LittleEndian.PutUint32(buf[8:12], sample.DataPresent)
// buf[12:16] padding
copy(buf[16:48], sample.RawData[:])
if _, err := bw.file.Write(buf); err != nil {
return fmt.Errorf("failed to write sample: %w", err)
}
bw.sampleCount++
return nil
}logger.BinaryWriter.Close method · go · L102-L110 (9 LOC)internal/logger/store.go
func (bw *BinaryWriter) Close() error {
// Update sample count in header
if _, err := bw.file.Seek(8, io.SeekStart); err == nil {
countBuf := make([]byte, 4)
binary.LittleEndian.PutUint32(countBuf, bw.sampleCount)
bw.file.Write(countBuf)
}
return bw.file.Close()
}logger.ReadBinaryLog function · go · L127-L184 (58 LOC)internal/logger/store.go
func ReadBinaryLog(filename string) (*BinaryLog, error) {
f, err := os.Open(filename)
if err != nil {
return nil, fmt.Errorf("failed to open binary log: %w", err)
}
defer f.Close()
// Read header
header := make([]byte, mmcdHeaderSize)
if _, err := io.ReadFull(f, header); err != nil {
return nil, fmt.Errorf("failed to read header: %w", err)
}
if string(header[0:4]) != mmcdMagic {
return nil, fmt.Errorf("not an MMCD binary log (bad magic)")
}
log := &BinaryLog{
Version: header[4],
Units: sensor.UnitSystem(header[5]),
SampleCount: binary.LittleEndian.Uint32(header[8:12]),
}
sensorCount := binary.LittleEndian.Uint16(header[6:8])
// Read sensor index table
indexTable := make([]byte, sensorCount)
if _, err := io.ReadFull(f, indexTable); err != nil {
return nil, fmt.Errorf("failed to read index table: %w", err)
}
log.Indices = make([]int, sensorCount)
for i, b := range indexTable {
log.Indices[i] = int(b)
}
// Read samples
log.Samples = maprotocol.decodeDTCs function · go · L54-L62 (9 LOC)internal/protocol/dtc.go
func decodeDTCs(bitmap uint16) []DTCCode {
var codes []DTCCode
for i := 0; i < 16; i++ {
if bitmap&(1<<uint(i)) != 0 {
codes = append(codes, dtcTable[i])
}
}
return codes
}protocol.ECU.ReadDTCs method · go · L65-L109 (45 LOC)internal/protocol/dtc.go
func (e *ECU) ReadDTCs() (*DTCResult, error) {
if !e.conn.IsOpen() {
if err := e.conn.Open(); err != nil {
return nil, err
}
defer e.conn.Close()
}
// Flush stale bytes before reading DTCs
e.conn.Flush()
result := &DTCResult{}
// Read active DTCs (low byte)
activeLow, err := e.QuerySensor(AddrActiveDTCLow)
if err != nil {
return nil, fmt.Errorf("failed to read active DTC low byte: %w", err)
}
// Read active DTCs (high byte)
activeHigh, err := e.QuerySensor(AddrActiveDTCHigh)
if err != nil {
return nil, fmt.Errorf("failed to read active DTC high byte: %w", err)
}
result.ActiveRaw = uint16(activeLow) | (uint16(activeHigh) << 8)
result.Active = decodeDTCs(result.ActiveRaw)
// Read stored DTCs (low byte)
storedLow, err := e.QuerySensor(AddrStoredDTCLow)
if err != nil {
return nil, fmt.Errorf("failed to read stored DTC low byte: %w", err)
}
// Read stored DTCs (high byte)
storedHigh, err := e.QuerySensor(AddrStoredDTCHigh)
if err != nil {
returnprotocol.ECU.EraseDTCs method · go · L112-L130 (19 LOC)internal/protocol/dtc.go
func (e *ECU) EraseDTCs() error {
if !e.conn.IsOpen() {
if err := e.conn.Open(); err != nil {
return err
}
defer e.conn.Close()
}
result, err := e.SendCommand(AddrEraseDTC, 2*time.Second)
if err != nil {
return fmt.Errorf("failed to erase DTCs: %w", err)
}
if result != 0x00 {
return fmt.Errorf("unexpected erase DTC response: 0x%02X", result)
}
return nil
}All rows scored by the Repobility analyzer (https://repobility.com)
protocol.NewECU function · go · L28-L33 (6 LOC)internal/protocol/ecu.go
func NewECU(conn *SerialConn, defs []sensor.Definition) *ECU {
return &ECU{
conn: conn,
defs: defs,
}
}protocol.ECU.QuerySensor method · go · L39-L80 (42 LOC)internal/protocol/ecu.go
func (e *ECU) QuerySensor(addr byte) (byte, error) {
if addr >= 0xC0 {
return 0, fmt.Errorf("address 0x%02X is in command range (>=0xC0), refusing to poll", addr)
}
e.busMu.Lock()
defer e.busMu.Unlock()
// Send the address byte
_, err := e.conn.Send([]byte{addr})
if err != nil {
return 0, fmt.Errorf("failed to send sensor address 0x%02X: %w", addr, err)
}
// Read 2 bytes: echo + data
buf := make([]byte, 2)
totalRead := 0
deadline := time.Now().Add(500 * time.Millisecond)
for totalRead < 2 && time.Now().Before(deadline) {
n, err := e.conn.Receive(buf[totalRead:])
if err != nil {
e.conn.Flush()
return 0, fmt.Errorf("failed to read response for 0x%02X: %w", addr, err)
}
totalRead += n
}
if totalRead < 2 {
e.conn.Flush()
return 0, fmt.Errorf("timeout reading response for 0x%02X: got %d bytes", addr, totalRead)
}
// Verify echo — discard sample on mismatch
if buf[0] != addr {
slog.Warn("ECU echo mismatch", "expected", fmt.Sprintf("0x%02X", addprotocol.ECU.PollSensors method · go · L83-L109 (27 LOC)internal/protocol/ecu.go
func (e *ECU) PollSensors(indices []int) (sensor.Sample, error) {
var sample sensor.Sample
sample.Time = time.Now()
for _, idx := range indices {
if idx < 0 || idx >= len(e.defs) {
continue
}
def := e.defs[idx]
if !def.Exists || def.Computed || def.Addr == 0xFF {
continue
}
data, err := e.QuerySensor(def.Addr)
if err != nil {
slog.Debug("sensor query failed", "slug", def.Slug, "addr", fmt.Sprintf("0x%02X", def.Addr), "error", err)
continue
}
sample.SetData(idx, data)
}
// Compute derived values (e.g., injector duty cycle)
sample.ComputeDerivatives(e.defs)
return sample, nil
}page 1 / 2next ›