fix: filter raw frames by vehicle key

This commit is contained in:
lingniu
2026-07-02 00:24:53 +08:00
parent f3ecf430cc
commit cc89e0d537
2 changed files with 70 additions and 25 deletions

View File

@@ -18,6 +18,7 @@ type Queryer interface {
type RawFrameQuery struct { type RawFrameQuery struct {
Protocol string Protocol string
VehicleKey string
VIN string VIN string
Phone string Phone string
DeviceID string DeviceID string
@@ -123,6 +124,7 @@ func (r *RawFrameRepository) tableName() string {
func normalizeRawFrameQuery(query RawFrameQuery) RawFrameQuery { func normalizeRawFrameQuery(query RawFrameQuery) RawFrameQuery {
query.Protocol = strings.ToUpper(strings.TrimSpace(query.Protocol)) query.Protocol = strings.ToUpper(strings.TrimSpace(query.Protocol))
query.VehicleKey = strings.TrimSpace(query.VehicleKey)
query.VIN = strings.TrimSpace(query.VIN) query.VIN = strings.TrimSpace(query.VIN)
query.Phone = strings.TrimSpace(query.Phone) query.Phone = strings.TrimSpace(query.Phone)
query.DeviceID = strings.TrimSpace(query.DeviceID) query.DeviceID = strings.TrimSpace(query.DeviceID)
@@ -143,6 +145,9 @@ func buildRawFrameSQL(table string, query RawFrameQuery) (string, []any) {
if query.Protocol != "" { if query.Protocol != "" {
add("protocol = '" + quote(query.Protocol) + "'") add("protocol = '" + quote(query.Protocol) + "'")
} }
if query.VehicleKey != "" {
add("vehicle_key = '" + quote(query.VehicleKey) + "'")
}
if query.VIN != "" { if query.VIN != "" {
add("vin = '" + quote(query.VIN) + "'") add("vin = '" + quote(query.VIN) + "'")
} }
@@ -222,6 +227,7 @@ func parseRawFrameQuery(r *http.Request) (RawFrameQuery, error) {
} }
query := RawFrameQuery{ query := RawFrameQuery{
Protocol: values.Get("protocol"), Protocol: values.Get("protocol"),
VehicleKey: values.Get("vehicleKey"),
VIN: values.Get("vin"), VIN: values.Get("vin"),
Phone: values.Get("phone"), Phone: values.Get("phone"),
DeviceID: values.Get("deviceId"), DeviceID: values.Get("deviceId"),

View File

@@ -94,6 +94,43 @@ func TestRawFrameHandlerReturnsRawFrames(t *testing.T) {
} }
} }
func TestRawFrameHandlerFiltersByVehicleKey(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("sqlmock.New() error = %v", err)
}
defer db.Close()
mock.ExpectQuery("vehicle_key = 'JT808:013307811350'").
WillReturnRows(sqlmock.NewRows([]string{
"ts", "frame_id", "event_id", "message_id", "event_time", "received_at", "raw_size_bytes",
"raw_hex", "raw_text", "parsed_json", "fields_json", "parse_status", "parse_error", "source_endpoint",
"protocol", "vehicle_key", "vin", "phone", "device_id",
}).AddRow(
"2026-07-02 00:18:22", "go_frame", "event-3", 0x0200, "2026-07-02 00:18:22", "2026-07-02 00:22:43",
63, "7E0200", "", `{"header":{"message_id":"0x0200"}}`, `{"total_mileage_km":8792.8}`,
"OK", "", "115.231.168.135:22170", "JT808", "JT808:013307811350", "", "013307811350", "",
))
handler := NewRawFrameHandler(NewRawFrameRepository(db, "lingniu_vehicle_ts"))
request := httptest.NewRequest(http.MethodGet, "/api/history/raw-frames?vehicleKey=JT808:013307811350&protocol=JT808&limit=1", nil)
response := httptest.NewRecorder()
handler.ServeHTTP(response, request)
if response.Code != http.StatusOK {
t.Fatalf("status = %d body=%s", response.Code, response.Body.String())
}
body := response.Body.String()
for _, want := range []string{`"vehicle_key":"JT808:013307811350"`, `"phone":"013307811350"`, `"total":1`} {
if !strings.Contains(body, want) {
t.Fatalf("response missing %s: %s", want, body)
}
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Fatalf("sql expectations: %v", err)
}
}
func TestRawFrameHandlerRejectsInvalidLimit(t *testing.T) { func TestRawFrameHandlerRejectsInvalidLimit(t *testing.T) {
handler := NewRawFrameHandler(NewRawFrameRepository(&sql.DB{}, "")) handler := NewRawFrameHandler(NewRawFrameRepository(&sql.DB{}, ""))
request := httptest.NewRequest(http.MethodGet, "/api/history/raw-frames?limit=501", nil) request := httptest.NewRequest(http.MethodGet, "/api/history/raw-frames?limit=501", nil)
@@ -122,6 +159,7 @@ func TestParseMessageIDSupportsDecimalAndHex(t *testing.T) {
func TestBuildRawFrameSQLUsesLiteralsForTDengine(t *testing.T) { func TestBuildRawFrameSQLUsesLiteralsForTDengine(t *testing.T) {
sqlText, args := buildRawFrameSQL("lingniu_vehicle_ts.raw_frames", RawFrameQuery{ sqlText, args := buildRawFrameSQL("lingniu_vehicle_ts.raw_frames", RawFrameQuery{
Protocol: "JT808", Protocol: "JT808",
VehicleKey: "JT808:013307811350",
VIN: "VIN'1", VIN: "VIN'1",
MessageID: "0x0200", MessageID: "0x0200",
DateFrom: "2026-07-01 00:00:00", DateFrom: "2026-07-01 00:00:00",
@@ -134,6 +172,7 @@ func TestBuildRawFrameSQLUsesLiteralsForTDengine(t *testing.T) {
} }
for _, want := range []string{ for _, want := range []string{
"protocol = 'JT808'", "protocol = 'JT808'",
"vehicle_key = 'JT808:013307811350'",
"vin = 'VIN''1'", "vin = 'VIN''1'",
"message_id = 512", "message_id = 512",
"LIMIT 20 OFFSET 5", "LIMIT 20 OFFSET 5",