package handlers import ( "encoding/json" "fmt" "net/http" "github.com/fiskerinc/cloud-services/pkg/grpc/kafka_grpc" "otaupdate/services" "github.com/fiskerinc/cloud-services/pkg/carcommand" "github.com/fiskerinc/cloud-services/pkg/common" "github.com/fiskerinc/cloud-services/pkg/common/actionlogger" "github.com/fiskerinc/cloud-services/pkg/httphandlers" "github.com/fiskerinc/cloud-services/pkg/kafka" "github.com/fiskerinc/cloud-services/pkg/logger" "github.com/fiskerinc/cloud-services/pkg/loggerdataresp" "github.com/fiskerinc/cloud-services/pkg/utils" "google.golang.org/protobuf/proto" ) // HandleVehicleCommand godoc // @Summary Send command to car // @Description Send command to car // @Accept json // @Produce json // @Param Authorization header string false "Bearer " // @Param Api-Key header string false "" // @Param Command body common.BulkCarCommands true "Command to send to cars" // @Success 200 {object} common.JSONMessage // @Failure 400 {object} common.JSONError "Bad request" // @Failure 401 {object} common.JSONError "Unauthorized" // @Failure 503 {object} common.JSONError "Service unavailable" // @Router /vehiclecommand [post] func HandleVehicleCommand(w http.ResponseWriter, r *http.Request) { var request common.BulkCarCommands err := httphandlers.ParseRequest(r, &request) if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) { return } err = carcommand.ValidateCommand(request.Command) if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) { return } k := services.GetKafkaProducer() alDB := services.GetDB().GetActionLog() // Throwing away error, do not need description, _ := json.Marshal(request.RemoteCommandSource) for _, vin := range request.VINs { go func(vin string) { actionLog := actionlogger.ActionLog{ VIN: vin, Action: actionlogger.RemoteCommand, UserIdentifier: httphandlers.GetClientID(r), CallLocation: "github.com/fiskerinc/cloud-services/services/ota_update_go/handlers/vehicle_command.go", Description: string(description), } err = alDB.Insert(actionLog) if err != nil { logger.Err(err).Msg("failed to insert action log inside HandleVehicleCommand") } }(vin) data := common.RemoteCommandRequest{ VIN: vin, Source: httphandlers.GetClientID(r), RemoteCommandSource: request.RemoteCommandSource, } dataBytes, _ := json.Marshal(data) var cmd kafka_grpc.RemoteCommand err := json.Unmarshal(dataBytes, &cmd) // I don't know if there is any reason to stick these in kafka. Like I think they are just // inserted into the redis pub sub if err == nil { payload := kafka_grpc.GRPC_ValetPayload{ Handler: "remote_command", Data: &kafka_grpc.GRPC_ValetPayload_RemoteCmd{ RemoteCmd: &cmd, }, } binaryPayload, _ := proto.Marshal(&payload) err = k.ProduceBinary( kafka.ValetServiceGRPCKafka, common.Service.Key(vin), binaryPayload, nil, ) } if loggerdataresp.BadDataErrorResp(w, err, http.StatusServiceUnavailable) { return } } utils.RespJSON(w, http.StatusOK, &common.JSONMessage{ Message: fmt.Sprintf("remote command sent to %d vehicles", len(request.VINs)), }) }