Add depot, attendant, jetfire, optimus, ota services with kustomize overlays

This commit is contained in:
Chris Rai
2026-01-31 15:35:07 -05:00
parent a0ec642ca1
commit 9a5cb2f547
404 changed files with 38817 additions and 16 deletions

View File

@@ -0,0 +1,194 @@
package handlers
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"time"
"github.com/fiskerinc/cloud-services/pkg/common"
orm "github.com/fiskerinc/cloud-services/pkg/db/queries"
"github.com/fiskerinc/cloud-services/pkg/mongo"
"github.com/fiskerinc/cloud-services/pkg/utils"
"github.com/fiskerinc/cloud-services/pkg/validator"
"github.com/julienschmidt/httprouter"
"github.com/pkg/errors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
"otaupdate/services"
"github.com/fiskerinc/cloud-services/pkg/logger"
"github.com/fiskerinc/cloud-services/pkg/loggerdataresp"
)
// HandleECUDTCGet godoc
// @Summary Get ECU DTCs for a specific vehicle
// @Description Get ECU diagnostic trouble codes (DTCs) for a specific vehicle within a given time range
// @Tags ECU
// @Accept json
// @Produce json
// @Param Authorization header string false "Bearer <ID token>"
// @Param Api-Key header string false "<API token>"
// @Param vin path string true "VIN"
// @Param ecu query string false "ECU"
// @Param trouble_code query string false "Trouble Code"
// @Param start_time query string false "Start time (RFC3339 format)"
// @Param end_time query string false "End time (RFC3339 format)"
// @Param limit query int false "Max number of records"
// @Param offset query int false "Records offset"
// @Param order query string false "Sort on column with asc or desc"
// @Param decode query bool false "Return decoded dtc information"
// @Success 200 {object} common.JSONDBQueryResult{data=[]common.DTC_ECU} "List of DTC ECU data"
// @Failure 400 {object} common.JSONError "Bad request"
// @Failure 401 {object} common.JSONError "Unauthorized"
// @Failure 404 {object} common.JSONError "Not found"
// @Failure 503 {object} common.JSONError "Service unavailable"
// @Router /dtcs/{vin} [get]
func HandleECUDTCGet(w http.ResponseWriter, r *http.Request) {
params := httprouter.ParamsFromContext(r.Context())
vin := params.ByName("vin")
queryParams := r.URL.Query()
ecu := queryParams.Get("ecu")
troubleCode := queryParams.Get("trouble_code")
startStr := queryParams.Get("start_time")
endStr := queryParams.Get("end_time")
decode, _ := strconv.ParseBool(queryParams.Get("decode"))
filter := bson.M{
"vin": vin}
if ecu != "" {
filter["ecu"] = ecu
}
if troubleCode != "" {
troubleCodeInt, err := strconv.ParseInt(troubleCode, 10, 64)
if err != nil {
http.Error(w, "Invalid trouble_code format, use int64", http.StatusBadRequest)
return
}
filter["dtc"] = troubleCodeInt
}
err := validator.GetValidator().Var(vin, "vin|vinsuffix")
if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
return
}
var start time.Time
if startStr != "" {
start, err = time.Parse(time.RFC3339, startStr)
if err != nil {
http.Error(w, "Invalid start_time format, use RFC3339 format", http.StatusBadRequest)
return
}
}
var end time.Time
if endStr != "" {
end, err = time.Parse(time.RFC3339, endStr)
if err != nil {
http.Error(w, "Invalid end_time format, use RFC3339 format", http.StatusBadRequest)
return
}
}
if !start.IsZero() && !end.IsZero() {
filter["created_at"] = bson.M{
"$gte": start,
"$lte": end,
}
} else if !start.IsZero() {
filter["created_at"] = bson.M{
"$gte": start,
}
} else if !end.IsZero() {
filter["created_at"] = bson.M{
"$lte": end,
}
}
mongoOpts := options.Find()
query_params, err := orm.ParsePageQuery(r)
if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
return
}
mongoOpts.SetLimit(int64(query_params.Limit))
if query_params.Order != "" {
mongoOpts.SetSort(bson.D{
{"created_at", -1}}) // Descending order for 'created_at'.
}
if query_params.Offset != 0 {
mongoOpts.SetSkip(int64(query_params.Offset))
}
mongo, err := services.GetMongoClient()
if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
return
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
var total int64
if query_params.Offset == 0 {
total, err = mongo.Collection("dtcs").CountDocuments(ctx, filter)
if loggerdataresp.BadDataErrorResp(w, err, http.StatusServiceUnavailable, loggerdataresp.PostgresNoRowsErrorCheck) {
return
}
}
cursor, err := mongo.Collection("dtcs").Find(ctx, filter, mongoOpts)
if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
return
}
var dtcs []common.DTC_ECU
for cursor.Next(ctx) {
var result common.DTC_ECU
err := cursor.Decode(&result)
if err != nil {
logger.Warn().Msg(err.Error())
continue
}
if decode {
fetchDTCDataFromMongo(&result)
}
dtcs = append(dtcs, result)
}
utils.RespJSON(w, http.StatusOK, common.JSONDBQueryResult{
Data: dtcs,
Total: int(total),
})
}
func fetchDTCDataFromMongo(dtc *common.DTC_ECU) (err error) {
client, err := mongo.GetPDXMongoClient()
if err != nil {
err = errors.WithStack(err)
return
}
// Handle the dtc string, need to drop the first byte as its the status code
troubleCodeHex := fmt.Sprintf("%X", dtc.TroubleCode)
troubleCodeHex = strings.ToUpper(troubleCodeHex)
info, err := client.GetDTCDefinitionByHexString(troubleCodeHex, dtc.ECU)
if err != nil {
return
}
if info == nil {
logger.Warn().Msgf("Failed to find dtc code from ecu: %s troubleCodeHex: %s", dtc.ECU, troubleCodeHex)
}
dtc.Information = info
dtc.StatusByteDecode = dtc.DTCStatusByteMeaning()
return
}