mirror of
https://github.com/tobiasehlert/teslamateapi.git
synced 2026-02-27 09:54:18 +08:00
Merge pull request #60 from tobiasehlert/feature-10-logging-commands
Feature 10 logging commands
This commit is contained in:
@@ -100,6 +100,9 @@ Basically the same environment variables for the database, mqqt and timezone nee
|
||||
|
||||
**Optional** environment variables
|
||||
|
||||
- **TESLAMATE_SSL** boolean *(default: false)*
|
||||
- **TESLAMATE_HOST** string *(default: teslamate)*
|
||||
- **TESLAMATE_PORT** string *(default: 4000)*
|
||||
- **API_TOKEN** string *(default: )*
|
||||
- **DATABASE_PORT** integer *(default: 5432)*
|
||||
- **DATABASE_TIMEOUT** integer *(default: 60000)*
|
||||
@@ -117,6 +120,7 @@ Basically the same environment variables for the database, mqqt and timezone nee
|
||||
- **ENABLE_COMMANDS** boolean *(default: false)*
|
||||
- **COMMANDS_ALL** boolean *(default: false)*
|
||||
- **COMMANDS_ALLOWLIST** string *(default: allow_list.json)*
|
||||
- **COMMANDS_LOGGING** boolean *(deafault: false)*
|
||||
- **COMMANDS_WAKE** boolean *(default: false)*
|
||||
- **COMMANDS_ALERT** boolean *(default: false)*
|
||||
- **COMMANDS_REMOTESTART** boolean *(default: false)*
|
||||
@@ -150,6 +154,8 @@ More detailed documentation of every endpoint will come..
|
||||
- POST `/api/v1/cars/:CarID/command/:Command`
|
||||
- GET `/api/v1/cars/:CarID/drives`
|
||||
- GET `/api/v1/cars/:CarID/drives/:DriveID`
|
||||
- PUT `/api/v1/cars/:CarID/logging/:Command`
|
||||
- GET `/api/v1/cars/:CarID/logging`
|
||||
- GET `/api/v1/cars/:CarID/status`
|
||||
- GET `/api/v1/cars/:CarID/updates`
|
||||
- POST `/api/v1/cars/:CarID/wake_up`
|
||||
@@ -158,7 +164,7 @@ More detailed documentation of every endpoint will come..
|
||||
|
||||
### Authentication
|
||||
|
||||
If you want to use command endpoints such as `/api/v1/cars/:CarID/command/:Command` and `/api/v1/cars/:CarID/wake_up`, you need to add authentication to your request.
|
||||
If you want to use command or logging endpoints such as `/api/v1/cars/:CarID/command/:Command`, `/api/v1/cars/:CarID/wake_up`, or `/api/v1/cars/:CarID/logging/:Command` you need to add authentication to your request.
|
||||
|
||||
You need to specify a token yourself (called **API_TOKEN**) in the environment variables file, to set it. The token has the requirement to be a minimum of 32 characters long.
|
||||
|
||||
|
||||
@@ -16,6 +16,13 @@ func initCommandAllowList() {
|
||||
// allow all commands available below
|
||||
allowAll := getEnvAsBool("COMMANDS_ALL", false)
|
||||
|
||||
// https://github.com/adriankumpf/teslamate/discussions/1433
|
||||
if getEnvAsBool("COMMANDS_LOGGING", false) || allowAll {
|
||||
allowList = append(allowList,
|
||||
"/logging/resume",
|
||||
"/logging/suspend")
|
||||
}
|
||||
|
||||
// https://tesla-api.timdorr.com/vehicle/commands/wake
|
||||
if getEnvAsBool("COMMANDS_WAKE", false) || allowAll {
|
||||
allowList = append(allowList, "/wake_up")
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
// TeslaMateAPICarsLoggingV1 func
|
||||
func TeslaMateAPICarsLoggingV1(c *gin.Context) {
|
||||
|
||||
// creating required vars
|
||||
var jsonData map[string]interface{}
|
||||
var err error
|
||||
|
||||
// check if commands are enabled.. if not we need to abort
|
||||
if getEnvAsBool("ENABLE_COMMANDS", false) == false {
|
||||
log.Println("[warning] TeslaMateAPICarsLoggingV1 ENABLE_COMMANDS is not true.. returning 403 forbidden.")
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "You are not allowed to access logging commands"})
|
||||
return
|
||||
}
|
||||
|
||||
// if request method is GET return list of commands
|
||||
if c.Request.Method == http.MethodGet {
|
||||
c.JSON(http.StatusOK, gin.H{"enabled_commands": allowList})
|
||||
return
|
||||
}
|
||||
|
||||
// authentication for the endpoint
|
||||
validToken, errorMessage := validateAuthToken(c)
|
||||
if !validToken {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": errorMessage})
|
||||
return
|
||||
}
|
||||
|
||||
// getting CarID param from URL
|
||||
ParamCarID := c.Param("CarID")
|
||||
var CarID int
|
||||
if ParamCarID != "" {
|
||||
CarID = convertStringToInteger(ParamCarID)
|
||||
}
|
||||
|
||||
// validating that CarID is not zero
|
||||
if CarID == 0 {
|
||||
log.Println("[error] TeslaMateAPICarsLoggingV1 CarID is invalid (zero)!")
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "CarID invalid"})
|
||||
return
|
||||
}
|
||||
|
||||
// getting request body to pass to Tesla
|
||||
reqBody, err := ioutil.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
log.Println("[error] TeslaMateAPICarsLoggingV1 error in first ioutil.ReadAll", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal"})
|
||||
return
|
||||
}
|
||||
|
||||
// getting :Command
|
||||
command := ("/logging/" + c.Param("Command"))
|
||||
log.Println("[debug] TeslaMateAPICarsLoggingV1 command received:", command)
|
||||
|
||||
if !checkArrayContainsString(allowList, command) {
|
||||
log.Print("[warning] TeslaMateAPICarsLoggingV1 command: " + command + " not allowed")
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
return
|
||||
}
|
||||
|
||||
client := &http.Client{}
|
||||
putURL := ""
|
||||
if getEnvAsBool("TESLAMATE_SSL", false) {
|
||||
putURL = "https://"
|
||||
} else {
|
||||
putURL = "http://"
|
||||
}
|
||||
putURL = putURL + getEnv("TESLAMATE_HOST", "teslamate") + ":" + getEnv("TESLAMATE_PORT", "4000") + "/api/car/" + ParamCarID + command
|
||||
req, _ := http.NewRequest(http.MethodPut, putURL, strings.NewReader(string(reqBody)))
|
||||
req.Header.Set("User-Agent", "TeslaMateApi/"+apiVersion+" https://github.com/tobiasehlert/teslamateapi")
|
||||
resp, err := client.Do(req)
|
||||
|
||||
// check response error
|
||||
if err != nil {
|
||||
log.Println("[error] TeslaMateAPICarsLoggingV1 error in http request to http://teslamate:", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal"})
|
||||
return
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
defer client.CloseIdleConnections()
|
||||
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Println("[error] TeslaMateAPICarsLoggingV1 error in second ioutil.ReadAll:", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal"})
|
||||
return
|
||||
}
|
||||
json.Unmarshal([]byte(respBody), &jsonData)
|
||||
|
||||
// print to log about request
|
||||
if gin.IsDebugging() {
|
||||
log.Println("[debug] TeslaMateAPICarsLoggingV1 " + c.Request.RequestURI + " returned data:")
|
||||
js, _ := json.Marshal(jsonData)
|
||||
log.Printf("[debug] %s\n", js)
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNoContent {
|
||||
log.Println("[info] TeslaMateAPICarsLoggingV1 " + c.Request.RequestURI + " executed successful.")
|
||||
} else {
|
||||
log.Println("[error] TeslaMateAPICarsLoggingV1 " + c.Request.RequestURI + " error in execution!")
|
||||
}
|
||||
c.JSON(resp.StatusCode, jsonData)
|
||||
}
|
||||
@@ -100,6 +100,10 @@ func main() {
|
||||
v1.GET("/cars/:CarID/drives", TeslaMateAPICarsDrivesV1)
|
||||
v1.GET("/cars/:CarID/drives/:DriveID", TeslaMateAPICarsDrivesDetailsV1)
|
||||
|
||||
// v1 /api/v1/cars/:CarID/logging endpoints
|
||||
v1.GET("/cars/:CarID/logging", TeslaMateAPICarsLoggingV1)
|
||||
v1.PUT("/cars/:CarID/logging/:Command", TeslaMateAPICarsLoggingV1)
|
||||
|
||||
// v1 /api/v1/cars/:CarID/status endpoints
|
||||
v1.GET("/cars/:CarID/status", statusCache.TeslaMateAPICarsStatusV1)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user