|
|
package client
import ( "bytes" "context" "encoding/json" "fmt" "git.aiterp.net/lucifer/new-server/models" "io" "net" "net/http" "strings" "time" )
type Client struct { APIRoot string }
func (client *Client) GetDevices(ctx context.Context, fetchStr string) ([]models.Device, error) { devices := make([]models.Device, 0, 16) err := client.Fetch(ctx, "GET", "/api/devices/"+fetchStr, &devices, nil) if err != nil { return nil, err }
return devices, nil }
func (client *Client) PutDevice(ctx context.Context, fetchStr string, update models.DeviceUpdate) ([]models.Device, error) { devices := make([]models.Device, 0, 16) err := client.Fetch(ctx, "PUT", "/api/devices/"+fetchStr, &devices, update) if err != nil { return nil, err }
return devices, nil }
func (client *Client) PutDeviceState(ctx context.Context, fetchStr string, update models.NewDeviceState) ([]models.Device, error) { devices := make([]models.Device, 0, 16) err := client.Fetch(ctx, "PUT", "/api/devices/"+fetchStr+"/state", &devices, update) if err != nil { return nil, err }
return devices, nil }
func (client *Client) PutDeviceTags(ctx context.Context, fetchStr string, addTags []string, removeTags []string) ([]models.Device, error) { devices := make([]models.Device, 0, 16) err := client.Fetch(ctx, "PUT", "/api/devices/"+fetchStr+"/tags", &devices, map[string][]string{ "add": addTags, "remove": removeTags, }) if err != nil { return nil, err }
return devices, nil }
func (client *Client) AssignDevice(ctx context.Context, fetchStr string, assignment models.DeviceSceneAssignment) ([]models.Device, error) { devices := make([]models.Device, 0, 16) err := client.Fetch(ctx, "PUT", "/api/devices/"+fetchStr+"/scene", &devices, assignment) if err != nil { return nil, err }
return devices, nil }
func (client *Client) FireEvent(ctx context.Context, event models.Event) error { err := client.Fetch(ctx, "POST", "/api/events", nil, event) if err != nil { return err }
return nil }
func (client *Client) Fetch(ctx context.Context, method string, path string, dst interface{}, body interface{}) error { var reqBody io.ReadWriter if body != nil && method != "GET" { reqBody = bytes.NewBuffer(make([]byte, 0, 512))
err := json.NewEncoder(reqBody).Encode(body) if err != nil { return err } }
req, err := http.NewRequest(method, client.APIRoot+path, reqBody) if err != nil { return err }
res, err := httpClient.Do(req.WithContext(ctx)) if err != nil { return err } defer res.Body.Close()
if !strings.HasPrefix(res.Header.Get("Content-Type"), "application/json") { return fmt.Errorf("%s: %s", path, res.Status) }
var resJson struct { Code int `json:"code"` Message *string `json:"message"` Data json.RawMessage `json:"data"` } err = json.NewDecoder(res.Body).Decode(&resJson) if err != nil { return err }
if resJson.Code != 200 { msg := "" if resJson.Message != nil { msg = *resJson.Message }
return fmt.Errorf("%d: %s", resJson.Code, msg) }
if dst == nil { return nil }
return json.Unmarshal(resJson.Data, dst) }
var httpClient = &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, }).DialContext, MaxIdleConns: 16, MaxIdleConnsPerHost: 16, IdleConnTimeout: time.Minute, }, Timeout: time.Minute, }
|