diff --git a/collector.go b/collector.go index 6177637..2d0f3d5 100644 --- a/collector.go +++ b/collector.go @@ -2,7 +2,6 @@ package hamview import ( "context" - "database/sql" "encoding/hex" "fmt" "strings" @@ -173,22 +172,22 @@ func (c *Collector) processRadio(ctx context.Context, received *Radio) { } } -func (c *Collector) processAPRSPacket(ctx context.Context, received *Packet) { - radio, err := c.getRadioByID(ctx, received.RadioID) +func (c *Collector) processAPRSPacket(ctx context.Context, packet *Packet) { + radio, err := c.getRadioByID(ctx, packet.RadioID) if err != nil { - Logger.Warnf("collector: process %s packet: can't find radio %q: %v", received.Protocol, received.RadioID, err) + Logger.Warnf("collector: process %s packet: can't find radio %q: %v", packet.Protocol, packet.RadioID, err) return } - decoded, err := aprs.Parse(string(received.Raw)) + decoded, err := aprs.Parse(string(packet.Raw)) if err != nil { - Logger.Warnf("collector: invalid %s packet: %v", received.Protocol, err) + Logger.Warnf("collector: invalid %s packet: %v", packet.Protocol, err) return } Logger.Tracef("collector: process %s packet (%d bytes)", - received.Protocol, - len(received.Raw)) + packet.Protocol, + len(packet.Raw)) engine := schema.Query(ctx) station := new(schema.APRSStation) @@ -198,10 +197,10 @@ func (c *Collector) processAPRSPacket(ctx context.Context, received *Packet) { return } else if has { cols := []string{"last_heard_at"} - station.LastHeardAt = received.Time + station.LastHeardAt = packet.Time if decoded.Latitude != 0 { - station.LastLatitude = sql.NullFloat64{Float64: decoded.Latitude, Valid: true} - station.LastLongitude = sql.NullFloat64{Float64: decoded.Longitude, Valid: true} + station.LastLatitude = &decoded.Latitude + station.LastLongitude = &decoded.Longitude cols = append(cols, "last_latitude", "last_longitude") } if _, err = engine.ID(station.ID).Cols(cols...).Update(station); err != nil { @@ -212,18 +211,12 @@ func (c *Collector) processAPRSPacket(ctx context.Context, received *Packet) { station = &schema.APRSStation{ Call: strings.ToUpper(decoded.Source.String()), Symbol: decoded.Symbol, - FirstHeardAt: received.Time, - LastHeardAt: received.Time, + FirstHeardAt: packet.Time, + LastHeardAt: packet.Time, } if decoded.Latitude != 0 { - station.LastLatitude = sql.NullFloat64{ - Float64: decoded.Latitude, - Valid: decoded.Latitude != 0, - } - station.LastLongitude = sql.NullFloat64{ - Float64: decoded.Longitude, - Valid: decoded.Longitude != 0, - } + station.LastLatitude = &decoded.Latitude + station.LastLongitude = &decoded.Longitude } if station.ID, err = engine.Insert(station); err != nil { Logger.Warnf("collector: can't insert APRS station: %v", err) @@ -231,7 +224,7 @@ func (c *Collector) processAPRSPacket(ctx context.Context, received *Packet) { } } - packet := &schema.APRSPacket{ + save := &schema.APRSPacket{ RadioID: radio.ID, StationID: station.ID, Source: station.Call, @@ -239,20 +232,15 @@ func (c *Collector) processAPRSPacket(ctx context.Context, received *Packet) { Path: decoded.Path.String(), Comment: decoded.Comment, Symbol: string(decoded.Symbol[:]), - Raw: string(received.Raw), + Raw: string(packet.Raw), + ReceivedAt: packet.Time, } if decoded.Latitude != 0 { - packet.Latitude = sql.NullFloat64{ - Float64: decoded.Latitude, - Valid: decoded.Latitude != 0, - } - packet.Longitude = sql.NullFloat64{ - Float64: decoded.Longitude, - Valid: decoded.Longitude != 0, - } + save.Latitude = &decoded.Latitude + save.Longitude = &decoded.Longitude } - if _, err = engine.Insert(packet); err != nil { + if _, err = engine.Insert(save); err != nil { Logger.Warnf("collector: can't insert APRS packet: %v", err) } } @@ -287,22 +275,20 @@ func (c *Collector) processMeshCorePacket(ctx context.Context, packet *Packet) { } } - var ( - save = &schema.MeshCorePacket{ - RadioID: radio.ID, - SNR: packet.SNR, - RSSI: packet.RSSI, - RouteType: uint8(parsed.RouteType), - PayloadType: uint8(parsed.PayloadType), - Version: parsed.Version, - Hash: hex.EncodeToString(parsed.Hash()), - Path: parsed.Path, - Payload: parsed.Payload, - ChannelHash: channelHash, - Raw: packet.Raw, - ReceivedAt: packet.Time, - } - ) + save := &schema.MeshCorePacket{ + RadioID: radio.ID, + SNR: packet.SNR, + RSSI: packet.RSSI, + RouteType: uint8(parsed.RouteType), + PayloadType: uint8(parsed.PayloadType), + Version: parsed.Version, + Hash: hex.EncodeToString(parsed.Hash()), + Path: parsed.Path, + Payload: parsed.Payload, + ChannelHash: channelHash, + Raw: packet.Raw, + ReceivedAt: packet.Time, + } if _, err = schema.Query(ctx).Insert(save); err != nil { Logger.Warnf("collector: error storing packet: %v", err) return diff --git a/schema/aprs.go b/schema/aprs.go index f43ff1e..07f8fc7 100644 --- a/schema/aprs.go +++ b/schema/aprs.go @@ -2,7 +2,6 @@ package schema import ( "context" - "database/sql" "os" "strings" "time" @@ -21,8 +20,8 @@ type APRSStation struct { Symbol string `xorm:"varchar(2)" json:"symbol"` FirstHeardAt time.Time `xorm:"timestamp not null"` LastHeardAt time.Time `xorm:"timestamp not null"` - LastLatitude sql.NullFloat64 - LastLongitude sql.NullFloat64 + LastLatitude *float64 `xorm:"numeric(10,8)" json:"latitude,omitempty"` + LastLongitude *float64 `xorm:"numeric(11,8)" json:"longitude,omitempty"` } func GetAPRSStation(ctx context.Context, call string) (*APRSStation, error) { @@ -46,20 +45,20 @@ func (station APRSStation) GetPackets(ctx context.Context) ([]*APRSPacket, error } type APRSPacket struct { - ID int64 `xorm:"pk autoincr" json:"id"` - RadioID int64 `xorm:"index" json:"radio_id"` - Radio Radio `json:"radio"` - StationID int64 `json:"-"` - Station *APRSStation `xorm:"-" json:"station"` - Source string `xorm:"varchar(10) not null" json:"src"` - Destination string `xorm:"varchar(10) not null" json:"dst"` - Path string `xorm:"varchar(88) not null default ''" json:"path"` - Comment string `xorm:"varchar(250)" json:"comment"` - Latitude sql.NullFloat64 `json:"latitude,omitempty"` - Longitude sql.NullFloat64 `json:"longitude,omitempty"` - Symbol string `xorm:"varchar(2)" json:"symbol"` - Raw string `json:"raw"` - ReceivedAt time.Time `json:"received_at"` + ID int64 `xorm:"pk autoincr" json:"id"` + RadioID int64 `xorm:"index" json:"radio_id"` + Radio *Radio `xorm:"-" json:"radio"` + StationID int64 `json:"-"` + Source string `xorm:"varchar(10) not null" json:"src"` + Destination string `xorm:"varchar(10) not null" json:"dst"` + Path string `xorm:"varchar(88) not null default ''" json:"path"` + Comment string `xorm:"varchar(250)" json:"comment"` + Latitude *float64 `xorm:"numeric(10,8)" json:"latitude,omitempty"` + Longitude *float64 `xorm:"numeric(11,8)" json:"longitude,omitempty"` + Symbol string `xorm:"varchar(2)" json:"symbol"` + Raw string `json:"raw"` + ReceivedAt time.Time `json:"received_at"` + //Station *APRSStation `xorm:"-" json:"station"` } func GetAPRSPackets(ctx context.Context, limit int) ([]*APRSPacket, error) { diff --git a/schema/engine.go b/schema/engine.go index 7e3672a..810d9d8 100644 --- a/schema/engine.go +++ b/schema/engine.go @@ -3,6 +3,7 @@ package schema import ( "context" "database/sql" + "fmt" "time" "github.com/sirupsen/logrus" @@ -89,7 +90,11 @@ func Open(driver, config string) error { names.LintGonicMapper[name] = true } xormEngine.SetMapper(names.GonicMapper{}) - xormEngine.SetLogger(xormLogger{}) + + logger := &xormLogger{} + //logger.SetLevel(log.LOG_DEBUG) + xormEngine.SetLogger(logger) + xormEngine.ShowSQL(true) for _, model := range registeredModels { Logger.Debugf("schema: sync schema %T", model) @@ -136,10 +141,32 @@ func NULLTime(t time.Time) *time.Time { return &t } -type xormLogger struct{} +type xormLogger struct { + showSQL bool +} + +func (l xormLogger) BeforeSQL(ctx log.LogContext) { + var sessionPart string + v := ctx.Ctx.Value(log.SessionIDKey) + if key, ok := v.(string); ok { + sessionPart = fmt.Sprintf(" [%s]", key) + } + Logger.Debugf("[SQL (before)]%s %s %v", sessionPart, ctx.SQL, ctx.Args) +} + +func (l xormLogger) AfterSQL(ctx log.LogContext) { + var sessionPart string + v := ctx.Ctx.Value(log.SessionIDKey) + if key, ok := v.(string); ok { + sessionPart = fmt.Sprintf(" [%s]", key) + } + if ctx.ExecuteTime > 0 { + Logger.Infof("[SQL (after)]%s %s %v - %v", sessionPart, ctx.SQL, ctx.Args, ctx.ExecuteTime) + } else { + Logger.Infof("[SQL (after)]%s %s %v", sessionPart, ctx.SQL, ctx.Args) + } +} // only invoked when IsShowSQL is true -func (l xormLogger) BeforeSQL(context log.LogContext) {} // only invoked when IsShowSQL is true -func (l xormLogger) AfterSQL(context log.LogContext) {} // only invoked when IsShowSQL is true func (l xormLogger) Debug(args ...any) { Logger.Debug(append([]any{"engine: "}, args...)...) } func (l xormLogger) Debugf(format string, args ...any) { Logger.Debugf("engine: "+format, args...) } func (l xormLogger) Error(args ...any) { Logger.Error(append([]any{"engine: "}, args...)...) } @@ -181,12 +208,14 @@ func (l xormLogger) SetLevel(level log.LogLevel) { } } -func (l xormLogger) ShowSQL(show ...bool) { - _ = show +func (l *xormLogger) ShowSQL(show ...bool) { + if len(show) > 0 { + l.showSQL = show[0] + } } func (l xormLogger) IsShowSQL() bool { - return false + return l.showSQL } var _ log.ContextLogger = (*xormLogger)(nil)