mirror of
https://github.com/Xevion/go-ha.git
synced 2025-12-06 13:15:14 -06:00
docs: normalize & make basic corrections to documentation
This commit is contained in:
27
app.go
27
app.go
@@ -42,16 +42,16 @@ type App struct {
|
|||||||
|
|
||||||
type Item types.Item
|
type Item types.Item
|
||||||
|
|
||||||
func (mi Item) Compare(other queue.Item) int {
|
func (i Item) Compare(other queue.Item) int {
|
||||||
if mi.Priority > other.(Item).Priority {
|
if i.Priority > other.(Item).Priority {
|
||||||
return 1
|
return 1
|
||||||
} else if mi.Priority == other.(Item).Priority {
|
} else if i.Priority == other.(Item).Priority {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateHomeZone verifies that the home zone entity exists and has latitude/longitude
|
// validateHomeZone verifies that the home zone entity exists and has latitude/longitude.
|
||||||
func validateHomeZone(state State, entityID string) error {
|
func validateHomeZone(state State, entityID string) error {
|
||||||
entity, err := state.Get(entityID)
|
entity, err := state.Get(entityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -75,10 +75,7 @@ func validateHomeZone(state State, entityID string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// NewApp establishes the WebSocket connection and returns an object you can use to register schedules and listeners.
|
||||||
NewApp establishes the websocket connection and returns an object
|
|
||||||
you can use to register schedules and listeners.
|
|
||||||
*/
|
|
||||||
func NewApp(request types.NewAppRequest) (*App, error) {
|
func NewApp(request types.NewAppRequest) (*App, error) {
|
||||||
if (request.URL == "" && request.IpAddress == "") || request.HAAuthToken == "" {
|
if (request.URL == "" && request.IpAddress == "") || request.HAAuthToken == "" {
|
||||||
slog.Error("URL and HAAuthToken are required arguments in NewAppRequest")
|
slog.Error("URL and HAAuthToken are required arguments in NewAppRequest")
|
||||||
@@ -138,11 +135,9 @@ func (app *App) Cleanup() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close performs a clean shutdown of the application.
|
// Close performs a clean shutdown of the application. It cancels the context, closes the WebSocket connection, and ensures all background processes are properly terminated.
|
||||||
// It cancels the context, closes the websocket connection,
|
|
||||||
// and ensures all background processes are properly terminated.
|
|
||||||
func (app *App) Close() error {
|
func (app *App) Close() error {
|
||||||
// Close websocket connection if it exists
|
// Close WebSocket connection if it exists
|
||||||
if app.conn != nil {
|
if app.conn != nil {
|
||||||
deadline := time.Now().Add(10 * time.Second)
|
deadline := time.Now().Add(10 * time.Second)
|
||||||
err := app.conn.Conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""), deadline)
|
err := app.conn.Conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""), deadline)
|
||||||
@@ -151,15 +146,15 @@ func (app *App) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the websocket connection
|
// Close the WebSocket connection
|
||||||
err = app.conn.Conn.Close()
|
err = app.conn.Conn.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Warn("Error closing websocket connection", "error", err)
|
slog.Warn("Error closing WebSocket connection", "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait a short time for the websocket connection to close
|
// Wait a short time for the WebSocket connection to close
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
|
||||||
// Cancel context to signal all goroutines to stop
|
// Cancel context to signal all goroutines to stop
|
||||||
@@ -338,7 +333,7 @@ func (app *App) Start() {
|
|||||||
select {
|
select {
|
||||||
case msg, ok := <-elChan:
|
case msg, ok := <-elChan:
|
||||||
if !ok {
|
if !ok {
|
||||||
slog.Info("Websocket channel closed, stopping main loop")
|
slog.Info("WebSocket channel closed, stopping main loop")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if app.entityListenersId == msg.Id {
|
if app.entityListenersId == msg.Id {
|
||||||
|
|||||||
@@ -133,11 +133,11 @@ func TestAppWithNilFields(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAppWithWebsocketConnection(t *testing.T) {
|
func TestAppWithWebsocketConnection(t *testing.T) {
|
||||||
// Test app with websocket connection (mocked)
|
// Test app with WebSocket connection (mocked)
|
||||||
app := &App{
|
app := &App{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
ctxCancel: func() {},
|
ctxCancel: func() {},
|
||||||
conn: nil, // In real test, this would be a mock websocket
|
conn: nil, // In real test, this would be a mock WebSocket
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that Close() handles nil connection gracefully
|
// Test that Close() handles nil connection gracefully
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func toCamelCase(s string) string {
|
|||||||
return result.String()
|
return result.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateHomeZone verifies that the home zone entity exists and is valid
|
// validateHomeZone verifies that the home zone entity exists and is valid.
|
||||||
func validateHomeZone(state ha.State, entityID string) error {
|
func validateHomeZone(state ha.State, entityID string) error {
|
||||||
entity, err := state.Get(entityID)
|
entity, err := state.Get(entityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -93,7 +93,7 @@ func validateHomeZone(state ha.State, entityID string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate creates the entities.go file with constants for all Home Assistant entities
|
// generate creates the entities.go file with constants for all Home Assistant entities.
|
||||||
func generate(config Config) error {
|
func generate(config Config) error {
|
||||||
if config.HomeZoneEntityId == "" {
|
if config.HomeZoneEntityId == "" {
|
||||||
config.HomeZoneEntityId = "zone.home"
|
config.HomeZoneEntityId = "zone.home"
|
||||||
|
|||||||
@@ -67,8 +67,6 @@ type msgState struct {
|
|||||||
Attributes map[string]any `json:"attributes"`
|
Attributes map[string]any `json:"attributes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Methods */
|
|
||||||
|
|
||||||
func NewEntityListener() elBuilder1 {
|
func NewEntityListener() elBuilder1 {
|
||||||
return elBuilder1{EntityListener{
|
return elBuilder1{EntityListener{
|
||||||
lastRan: carbon.Now().StartOfCentury(),
|
lastRan: carbon.Now().StartOfCentury(),
|
||||||
@@ -154,10 +152,8 @@ func (b elBuilder3) RunOnStartup() elBuilder3 {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// EnabledWhen enables this listener only when the current state of {entityId} matches {state}.
|
||||||
Enable this listener only when the current state of {entityId} matches {state}.
|
// If there is a network error while retrieving state, the listener runs if {runOnNetworkError} is true.
|
||||||
If there is a network error while retrieving state, the listener runs if {runOnNetworkError} is true.
|
|
||||||
*/
|
|
||||||
func (b elBuilder3) EnabledWhen(entityId, state string, runOnNetworkError bool) elBuilder3 {
|
func (b elBuilder3) EnabledWhen(entityId, state string, runOnNetworkError bool) elBuilder3 {
|
||||||
if entityId == "" {
|
if entityId == "" {
|
||||||
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
||||||
@@ -171,10 +167,8 @@ func (b elBuilder3) EnabledWhen(entityId, state string, runOnNetworkError bool)
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// DisabledWhen disables this listener when the current state of {entityId} matches {state}.
|
||||||
Disable this listener when the current state of {entityId} matches {state}.
|
// If there is a network error while retrieving state, the listener runs if {runOnNetworkError} is true.
|
||||||
If there is a network error while retrieving state, the listener runs if {runOnNetworkError} is true.
|
|
||||||
*/
|
|
||||||
func (b elBuilder3) DisabledWhen(entityId, state string, runOnNetworkError bool) elBuilder3 {
|
func (b elBuilder3) DisabledWhen(entityId, state string, runOnNetworkError bool) elBuilder3 {
|
||||||
if entityId == "" {
|
if entityId == "" {
|
||||||
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ type EventData struct {
|
|||||||
RawEventJSON []byte
|
RawEventJSON []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Methods */
|
|
||||||
|
|
||||||
func NewEventListener() eventListenerBuilder1 {
|
func NewEventListener() eventListenerBuilder1 {
|
||||||
return eventListenerBuilder1{EventListener{
|
return eventListenerBuilder1{EventListener{
|
||||||
lastRan: carbon.Now().StartOfCentury(),
|
lastRan: carbon.Now().StartOfCentury(),
|
||||||
@@ -96,10 +94,8 @@ func (b eventListenerBuilder3) ExceptionRange(start, end time.Time) eventListene
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// EnabledWhen enables this listener only when the current state of {entityId} matches {state}.
|
||||||
Enable this listener only when the current state of {entityId} matches {state}.
|
// If there is a network error while retrieving state, the listener runs if {runOnNetworkError} is true.
|
||||||
If there is a network error while retrieving state, the listener runs if {runOnNetworkError} is true.
|
|
||||||
*/
|
|
||||||
func (b eventListenerBuilder3) EnabledWhen(entityId, state string, runOnNetworkError bool) eventListenerBuilder3 {
|
func (b eventListenerBuilder3) EnabledWhen(entityId, state string, runOnNetworkError bool) eventListenerBuilder3 {
|
||||||
if entityId == "" {
|
if entityId == "" {
|
||||||
panic(fmt.Sprintf("entityId is empty in eventListener EnabledWhen entityId='%s' state='%s' runOnNetworkError='%t'", entityId, state, runOnNetworkError))
|
panic(fmt.Sprintf("entityId is empty in eventListener EnabledWhen entityId='%s' state='%s' runOnNetworkError='%t'", entityId, state, runOnNetworkError))
|
||||||
@@ -113,10 +109,8 @@ func (b eventListenerBuilder3) EnabledWhen(entityId, state string, runOnNetworkE
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// DisabledWhen disables this listener when the current state of {entityId} matches {state}.
|
||||||
Disable this listener when the current state of {entityId} matches {state}.
|
// If there is a network error while retrieving state, the listener runs if {runOnNetworkError} is true.
|
||||||
If there is a network error while retrieving state, the listener runs if {runOnNetworkError} is true.
|
|
||||||
*/
|
|
||||||
func (b eventListenerBuilder3) DisabledWhen(entityId, state string, runOnNetworkError bool) eventListenerBuilder3 {
|
func (b eventListenerBuilder3) DisabledWhen(entityId, state string, runOnNetworkError bool) eventListenerBuilder3 {
|
||||||
if entityId == "" {
|
if entityId == "" {
|
||||||
panic(fmt.Sprintf("entityId is empty in eventListener EnabledWhen entityId='%s' state='%s' runOnNetworkError='%t'", entityId, state, runOnNetworkError))
|
panic(fmt.Sprintf("entityId is empty in eventListener EnabledWhen entityId='%s' state='%s' runOnNetworkError='%t'", entityId, state, runOnNetworkError))
|
||||||
@@ -140,7 +134,6 @@ type BaseEventMsg struct {
|
|||||||
} `json:"event"`
|
} `json:"event"`
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Functions */
|
|
||||||
func callEventListeners(app *App, msg connect.ChannelMessage) {
|
func callEventListeners(app *App, msg connect.ChannelMessage) {
|
||||||
baseEventMsg := BaseEventMsg{}
|
baseEventMsg := BaseEventMsg{}
|
||||||
_ = json.Unmarshal(msg.Raw, &baseEventMsg)
|
_ = json.Unmarshal(msg.Raw, &baseEventMsg)
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
// Package websocket is used to interact with the Home Assistant
|
|
||||||
// websocket API. All HA interaction is done via websocket
|
|
||||||
// except for cases explicitly called out in http package
|
|
||||||
// documentation.
|
|
||||||
package connect
|
package connect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -20,13 +16,13 @@ import (
|
|||||||
|
|
||||||
var ErrInvalidToken = errors.New("invalid authentication token")
|
var ErrInvalidToken = errors.New("invalid authentication token")
|
||||||
|
|
||||||
// HAConnection is a wrapper around a websocket connection that provides a mutex for thread safety.
|
// HAConnection is a wrapper around a WebSocket connection that provides a mutex for thread safety.
|
||||||
type HAConnection struct {
|
type HAConnection struct {
|
||||||
Conn *websocket.Conn // Note: this is not thread safe except for Close() and WriteControl()
|
Conn *websocket.Conn // Note: this is not thread safe except for Close() and WriteControl()
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteMessage writes a message to the websocket connection.
|
// WriteMessage writes a message to the WebSocket connection.
|
||||||
func (w *HAConnection) WriteMessage(msg any) error {
|
func (w *HAConnection) WriteMessage(msg any) error {
|
||||||
w.mutex.Lock()
|
w.mutex.Lock()
|
||||||
defer w.mutex.Unlock()
|
defer w.mutex.Unlock()
|
||||||
@@ -34,7 +30,7 @@ func (w *HAConnection) WriteMessage(msg any) error {
|
|||||||
return w.Conn.WriteJSON(msg)
|
return w.Conn.WriteJSON(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadMessageRaw reads a raw message from the websocket connection.
|
// ReadMessageRaw reads a raw message from the WebSocket connection.
|
||||||
func ReadMessageRaw(conn *websocket.Conn) ([]byte, error) {
|
func ReadMessageRaw(conn *websocket.Conn) ([]byte, error) {
|
||||||
_, msg, err := conn.ReadMessage()
|
_, msg, err := conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -43,7 +39,7 @@ func ReadMessageRaw(conn *websocket.Conn) ([]byte, error) {
|
|||||||
return msg, nil
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadMessage reads a message from the websocket connection and unmarshals it into the given type.
|
// ReadMessage reads a message from the WebSocket connection and unmarshals it into the given type.
|
||||||
func ReadMessage[T any](conn *websocket.Conn) (T, error) {
|
func ReadMessage[T any](conn *websocket.Conn) (T, error) {
|
||||||
var result T
|
var result T
|
||||||
_, msg, err := conn.ReadMessage()
|
_, msg, err := conn.ReadMessage()
|
||||||
@@ -59,14 +55,14 @@ func ReadMessage[T any](conn *websocket.Conn) (T, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectionFromUri creates a new websocket connection from the given base URL and authentication token.
|
// ConnectionFromUri creates a new WebSocket connection from the given base URL and authentication token.
|
||||||
func ConnectionFromUri(baseUrl *url.URL, token string) (*HAConnection, context.Context, context.CancelFunc, error) {
|
func ConnectionFromUri(baseUrl *url.URL, token string) (*HAConnection, context.Context, context.CancelFunc, error) {
|
||||||
// Build the websocket URL
|
// Build the WebSocket URL
|
||||||
urlWebsockets := *baseUrl
|
urlWebsockets := *baseUrl
|
||||||
urlWebsockets.Path = "/api/websocket"
|
urlWebsockets.Path = "/api/websocket"
|
||||||
scheme, err := internal.GetEquivalentWebsocketScheme(baseUrl.Scheme)
|
scheme, err := internal.GetEquivalentWebsocketScheme(baseUrl.Scheme)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, fmt.Errorf("failed to build websocket URL: %w", err)
|
return nil, nil, nil, fmt.Errorf("failed to build WebSocket URL: %w", err)
|
||||||
}
|
}
|
||||||
urlWebsockets.Scheme = scheme
|
urlWebsockets.Scheme = scheme
|
||||||
|
|
||||||
@@ -74,11 +70,11 @@ func ConnectionFromUri(baseUrl *url.URL, token string) (*HAConnection, context.C
|
|||||||
connCtx, connCtxCancel := context.WithTimeout(context.Background(), time.Second*3)
|
connCtx, connCtxCancel := context.WithTimeout(context.Background(), time.Second*3)
|
||||||
defer connCtxCancel() // Always cancel the connection context when we're done
|
defer connCtxCancel() // Always cancel the connection context when we're done
|
||||||
|
|
||||||
// Init websocket connection
|
// Init WebSocket connection
|
||||||
dialer := websocket.DefaultDialer
|
dialer := websocket.DefaultDialer
|
||||||
conn, _, err := dialer.DialContext(connCtx, urlWebsockets.String(), nil)
|
conn, _, err := dialer.DialContext(connCtx, urlWebsockets.String(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("Failed to connect to websocket. Check URI\n", "url", urlWebsockets)
|
slog.Error("Failed to connect to WebSocket. Check URI\n", "url", urlWebsockets)
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +83,7 @@ func ConnectionFromUri(baseUrl *url.URL, token string) (*HAConnection, context.C
|
|||||||
MsgType string `json:"type"`
|
MsgType string `json:"type"`
|
||||||
}](conn)
|
}](conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("Unknown error creating websocket client\n")
|
slog.Error("Unknown error creating WebSocket client\n")
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
} else if msg.MsgType != "auth_required" {
|
} else if msg.MsgType != "auth_required" {
|
||||||
slog.Error("Expected auth_required message, got", "msgType", msg.MsgType)
|
slog.Error("Expected auth_required message, got", "msgType", msg.MsgType)
|
||||||
@@ -97,7 +93,7 @@ func ConnectionFromUri(baseUrl *url.URL, token string) (*HAConnection, context.C
|
|||||||
// Send auth message
|
// Send auth message
|
||||||
err = SendAuthMessage(conn, connCtx, token)
|
err = SendAuthMessage(conn, connCtx, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("Unknown error creating websocket client\n")
|
slog.Error("Unknown error creating WebSocket client\n")
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +110,7 @@ func ConnectionFromUri(baseUrl *url.URL, token string) (*HAConnection, context.C
|
|||||||
return &HAConnection{Conn: conn}, appCtx, appCtxCancel, nil
|
return &HAConnection{Conn: conn}, appCtx, appCtxCancel, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendAuthMessage sends an auth message to the websocket connection.
|
// SendAuthMessage sends an auth message to the WebSocket connection.
|
||||||
func SendAuthMessage(conn *websocket.Conn, ctx context.Context, token string) error {
|
func SendAuthMessage(conn *websocket.Conn, ctx context.Context, token string) error {
|
||||||
type AuthMessage struct {
|
type AuthMessage struct {
|
||||||
MsgType string `json:"type"`
|
MsgType string `json:"type"`
|
||||||
@@ -174,7 +170,7 @@ func SubscribeToEventType(eventType string, conn *HAConnection, ctx context.Cont
|
|||||||
err := conn.WriteMessage(e)
|
err := conn.WriteMessage(e)
|
||||||
// TODO: Handle errors better
|
// TODO: Handle errors better
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wrappedErr := fmt.Errorf("error writing to websocket: %w", err)
|
wrappedErr := fmt.Errorf("error writing to WebSocket: %w", err)
|
||||||
slog.Error(wrappedErr.Error())
|
slog.Error(wrappedErr.Error())
|
||||||
panic(wrappedErr)
|
panic(wrappedErr)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseMessage is the base message type for all messages sent by the websocket server.
|
// BaseMessage is the base message type for all messages sent by the WebSocket server.
|
||||||
type BaseMessage struct {
|
type BaseMessage struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
@@ -21,14 +21,14 @@ type ChannelMessage struct {
|
|||||||
Raw []byte
|
Raw []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenWebsocket reads messages from the websocket connection and sends them to the channel.
|
// ListenWebsocket reads messages from the WebSocket connection and sends them to the channel.
|
||||||
// It will close the channel if it encounters an error, or if the channel is full, and return.
|
// It will close the channel if it encounters an error, or if the channel is full, and return.
|
||||||
// It ignores errors in deserialization.
|
// It ignores errors in deserialization.
|
||||||
func ListenWebsocket(conn *websocket.Conn, c chan ChannelMessage) {
|
func ListenWebsocket(conn *websocket.Conn, c chan ChannelMessage) {
|
||||||
for {
|
for {
|
||||||
raw, err := ReadMessageRaw(conn)
|
raw, err := ReadMessageRaw(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("Error reading from websocket", "err", err)
|
slog.Error("Error reading from WebSocket", "err", err)
|
||||||
close(c)
|
close(c)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ func ListenWebsocket(conn *websocket.Conn, c chan ChannelMessage) {
|
|||||||
// Message sent successfully
|
// Message sent successfully
|
||||||
default:
|
default:
|
||||||
// Channel is full or closed, break out of loop
|
// Channel is full or closed, break out of loop
|
||||||
slog.Warn("Websocket message channel is full or closed, stopping listener",
|
slog.Warn("WebSocket message channel is full or closed, stopping listener",
|
||||||
"channel_capacity", cap(c),
|
"channel_capacity", cap(c),
|
||||||
"channel_length", len(c))
|
"channel_length", len(c))
|
||||||
close(c)
|
close(c)
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// http is used to interact with the home assistant
|
|
||||||
// REST API. Currently only used to retrieve state for
|
|
||||||
// a single entity_id
|
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -44,7 +41,7 @@ func NewHttpClient(ctx context.Context, baseUrl *url.URL, token string) *HttpCli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRequest returns a new request
|
// getRequest returns a new request.
|
||||||
func (c *HttpClient) getRequest() *resty.Request {
|
func (c *HttpClient) getRequest() *resty.Request {
|
||||||
return c.baseRequest.Clone(c.client.Context())
|
return c.baseRequest.Clone(c.client.Context())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ var (
|
|||||||
id atomic.Int64 // default value is 0
|
id atomic.Int64 // default value is 0
|
||||||
)
|
)
|
||||||
|
|
||||||
// NextId returns a unique integer (for the given process), often used for providing a uniquely identifiable
|
// NextId returns a unique integer (for the given process), often used for providing a uniquely identifiable ID for a request. This function is thread-safe.
|
||||||
// id for a request. This function is thread-safe.
|
|
||||||
func NextId() int64 {
|
func NextId() int64 {
|
||||||
return id.Add(1)
|
return id.Add(1)
|
||||||
}
|
}
|
||||||
@@ -32,7 +31,7 @@ func GetFunctionName(i interface{}) string {
|
|||||||
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEquivalentWebsocketScheme returns the equivalent websocket scheme for the given scheme.
|
// GetEquivalentWebsocketScheme returns the equivalent WebSocket scheme for the given scheme.
|
||||||
// If the scheme is http or https, it returns ws or wss respectively.
|
// If the scheme is http or https, it returns ws or wss respectively.
|
||||||
// If the scheme is ws or wss, it returns the same scheme.
|
// If the scheme is ws or wss, it returns the same scheme.
|
||||||
// If the scheme is not any of the above, it returns an error.
|
// If the scheme is not any of the above, it returns an error.
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import (
|
|||||||
"github.com/dromara/carbon/v2"
|
"github.com/dromara/carbon/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parses a HH:MM string.
|
// ParseTime parses a HH:MM string.
|
||||||
func ParseTime(s string) *carbon.Carbon {
|
func ParseTime(s string) *carbon.Carbon {
|
||||||
t, err := time.Parse("15:04", s)
|
t, err := time.Parse("15:04", s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
parsingErr := fmt.Errorf("failed to parse time string \"%s\"; format must be HH:MM.: %w", s, err)
|
parsingErr := fmt.Errorf("failed to parse time string \"%s\"; format must be HH:MM: %w", s, err)
|
||||||
slog.Error(parsingErr.Error())
|
slog.Error(parsingErr.Error())
|
||||||
panic(parsingErr)
|
panic(parsingErr)
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ func ParseTime(s string) *carbon.Carbon {
|
|||||||
func ParseDuration(s string) time.Duration {
|
func ParseDuration(s string) time.Duration {
|
||||||
d, err := time.ParseDuration(s)
|
d, err := time.ParseDuration(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
parsingErr := fmt.Errorf("couldn't parse string duration: \"%s\" see https://pkg.go.dev/time#ParseDuration for valid time units: %w", s, err)
|
parsingErr := fmt.Errorf("couldn't parse string duration: \"%s\"; see https://pkg.go.dev/time#ParseDuration for valid time units: %w", s, err)
|
||||||
slog.Error(parsingErr.Error())
|
slog.Error(parsingErr.Error())
|
||||||
panic(parsingErr)
|
panic(parsingErr)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ type AlarmControlPanel struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the alarm the command for arm away.
|
// Send the alarm the command for arm away. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (acp AlarmControlPanel) ArmAway(entityId string, serviceData ...map[string]any) error {
|
func (acp AlarmControlPanel) ArmAway(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "alarm_control_panel"
|
req.Domain = "alarm_control_panel"
|
||||||
@@ -22,9 +20,7 @@ func (acp AlarmControlPanel) ArmAway(entityId string, serviceData ...map[string]
|
|||||||
return acp.conn.WriteMessage(req)
|
return acp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the alarm the command for arm away.
|
// Send the alarm the command for arm away. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (acp AlarmControlPanel) ArmWithCustomBypass(entityId string, serviceData ...map[string]any) error {
|
func (acp AlarmControlPanel) ArmWithCustomBypass(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "alarm_control_panel"
|
req.Domain = "alarm_control_panel"
|
||||||
@@ -36,9 +32,7 @@ func (acp AlarmControlPanel) ArmWithCustomBypass(entityId string, serviceData ..
|
|||||||
return acp.conn.WriteMessage(req)
|
return acp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the alarm the command for arm home.
|
// Send the alarm the command for arm home. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (acp AlarmControlPanel) ArmHome(entityId string, serviceData ...map[string]any) error {
|
func (acp AlarmControlPanel) ArmHome(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "alarm_control_panel"
|
req.Domain = "alarm_control_panel"
|
||||||
@@ -50,9 +44,7 @@ func (acp AlarmControlPanel) ArmHome(entityId string, serviceData ...map[string]
|
|||||||
return acp.conn.WriteMessage(req)
|
return acp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the alarm the command for arm night.
|
// Send the alarm the command for arm night. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (acp AlarmControlPanel) ArmNight(entityId string, serviceData ...map[string]any) error {
|
func (acp AlarmControlPanel) ArmNight(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "alarm_control_panel"
|
req.Domain = "alarm_control_panel"
|
||||||
@@ -64,9 +56,7 @@ func (acp AlarmControlPanel) ArmNight(entityId string, serviceData ...map[string
|
|||||||
return acp.conn.WriteMessage(req)
|
return acp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the alarm the command for arm vacation.
|
// Send the alarm the command for arm vacation. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (acp AlarmControlPanel) ArmVacation(entityId string, serviceData ...map[string]any) error {
|
func (acp AlarmControlPanel) ArmVacation(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "alarm_control_panel"
|
req.Domain = "alarm_control_panel"
|
||||||
@@ -78,9 +68,7 @@ func (acp AlarmControlPanel) ArmVacation(entityId string, serviceData ...map[str
|
|||||||
return acp.conn.WriteMessage(req)
|
return acp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the alarm the command for disarm.
|
// Send the alarm the command for disarm. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (acp AlarmControlPanel) Disarm(entityId string, serviceData ...map[string]any) error {
|
func (acp AlarmControlPanel) Disarm(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "alarm_control_panel"
|
req.Domain = "alarm_control_panel"
|
||||||
@@ -92,9 +80,7 @@ func (acp AlarmControlPanel) Disarm(entityId string, serviceData ...map[string]a
|
|||||||
return acp.conn.WriteMessage(req)
|
return acp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the alarm the command for trigger.
|
// Send the alarm the command for trigger. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (acp AlarmControlPanel) Trigger(entityId string, serviceData ...map[string]any) error {
|
func (acp AlarmControlPanel) Trigger(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "alarm_control_panel"
|
req.Domain = "alarm_control_panel"
|
||||||
|
|||||||
@@ -44,8 +44,7 @@ func (c Cover) OpenTilt(entityId string) error {
|
|||||||
return c.conn.WriteMessage(req)
|
return c.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to specific position all or specified cover. Takes an entityId and an optional
|
// Move to specific position all or specified cover. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (c Cover) SetPosition(entityId string, serviceData ...map[string]any) error {
|
func (c Cover) SetPosition(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "cover"
|
req.Domain = "cover"
|
||||||
@@ -57,8 +56,7 @@ func (c Cover) SetPosition(entityId string, serviceData ...map[string]any) error
|
|||||||
return c.conn.WriteMessage(req)
|
return c.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to specific position all or specified cover tilt. Takes an entityId and an optional
|
// Move to specific position all or specified cover tilt. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (c Cover) SetTiltPosition(entityId string, serviceData ...map[string]any) error {
|
func (c Cover) SetTiltPosition(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "cover"
|
req.Domain = "cover"
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ type FireEventRequest struct {
|
|||||||
EventData map[string]any `json:"event_data,omitempty"`
|
EventData map[string]any `json:"event_data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire an event. Takes an event type and an optional map that is sent
|
// Fire an event. Takes an event type and an optional map that is sent as `event_data`.
|
||||||
// as `event_data`.
|
|
||||||
func (e Event) Fire(eventType string, eventData ...map[string]any) error {
|
func (e Event) Fire(eventType string, eventData ...map[string]any) error {
|
||||||
req := FireEventRequest{
|
req := FireEventRequest{
|
||||||
Id: internal.NextId(),
|
Id: internal.NextId(),
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ type HomeAssistant struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
// TurnOn a Home Assistant entity. Takes an entityId and an optional
|
// TurnOn a Home Assistant entity. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (ha *HomeAssistant) TurnOn(entityId string, serviceData ...map[string]any) error {
|
func (ha *HomeAssistant) TurnOn(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "homeassistant"
|
req.Domain = "homeassistant"
|
||||||
@@ -21,8 +20,7 @@ func (ha *HomeAssistant) TurnOn(entityId string, serviceData ...map[string]any)
|
|||||||
return ha.conn.WriteMessage(req)
|
return ha.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle a Home Assistant entity. Takes an entityId and an optional
|
// Toggle a Home Assistant entity. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (ha *HomeAssistant) Toggle(entityId string, serviceData ...map[string]any) error {
|
func (ha *HomeAssistant) Toggle(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "homeassistant"
|
req.Domain = "homeassistant"
|
||||||
@@ -34,6 +32,7 @@ func (ha *HomeAssistant) Toggle(entityId string, serviceData ...map[string]any)
|
|||||||
return ha.conn.WriteMessage(req)
|
return ha.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TurnOff turns off a Home Assistant entity.
|
||||||
func (ha *HomeAssistant) TurnOff(entityId string) error {
|
func (ha *HomeAssistant) TurnOff(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "homeassistant"
|
req.Domain = "homeassistant"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ type InputBoolean struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TurnOn turns on an input boolean entity.
|
||||||
func (ib InputBoolean) TurnOn(entityId string) error {
|
func (ib InputBoolean) TurnOn(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "input_boolean"
|
req.Domain = "input_boolean"
|
||||||
@@ -16,6 +17,7 @@ func (ib InputBoolean) TurnOn(entityId string) error {
|
|||||||
return ib.conn.WriteMessage(req)
|
return ib.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle toggles an input boolean entity.
|
||||||
func (ib InputBoolean) Toggle(entityId string) error {
|
func (ib InputBoolean) Toggle(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "input_boolean"
|
req.Domain = "input_boolean"
|
||||||
@@ -24,6 +26,7 @@ func (ib InputBoolean) Toggle(entityId string) error {
|
|||||||
return ib.conn.WriteMessage(req)
|
return ib.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TurnOff turns off an input boolean entity.
|
||||||
func (ib InputBoolean) TurnOff(entityId string) error {
|
func (ib InputBoolean) TurnOff(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "input_boolean"
|
req.Domain = "input_boolean"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ type InputButton struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Press presses an input button entity.
|
||||||
func (ib InputButton) Press(entityId string) error {
|
func (ib InputButton) Press(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "input_button"
|
req.Domain = "input_button"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ type InputText struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set sets the value of an input text entity.
|
||||||
func (ib InputText) Set(entityId string, value string) error {
|
func (ib InputText) Set(entityId string, value string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "input_text"
|
req.Domain = "input_text"
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ type Light struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
// TurnOn a light entity. Takes an entityId and an optional
|
// TurnOn a light entity. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (l Light) TurnOn(entityId string, serviceData ...map[string]any) error {
|
func (l Light) TurnOn(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "light"
|
req.Domain = "light"
|
||||||
@@ -21,8 +20,7 @@ func (l Light) TurnOn(entityId string, serviceData ...map[string]any) error {
|
|||||||
return l.conn.WriteMessage(req)
|
return l.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle a light entity. Takes an entityId and an optional
|
// Toggle a light entity. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (l Light) Toggle(entityId string, serviceData ...map[string]any) error {
|
func (l Light) Toggle(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "light"
|
req.Domain = "light"
|
||||||
@@ -34,6 +32,7 @@ func (l Light) Toggle(entityId string, serviceData ...map[string]any) error {
|
|||||||
return l.conn.WriteMessage(req)
|
return l.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TurnOff turns off a light entity.
|
||||||
func (l Light) TurnOff(entityId string) error {
|
func (l Light) TurnOff(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "light"
|
req.Domain = "light"
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ type Lock struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock a lock entity. Takes an entityId and an optional
|
// Lock a lock entity. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (l Lock) Lock(entityId string, serviceData ...map[string]any) error {
|
func (l Lock) Lock(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "lock"
|
req.Domain = "lock"
|
||||||
@@ -21,8 +20,7 @@ func (l Lock) Lock(entityId string, serviceData ...map[string]any) error {
|
|||||||
return l.conn.WriteMessage(req)
|
return l.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock a lock entity. Takes an entityId and an optional
|
// Unlock a lock entity. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (l Lock) Unlock(entityId string, serviceData ...map[string]any) error {
|
func (l Lock) Unlock(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "lock"
|
req.Domain = "lock"
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ type MediaPlayer struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the command to clear players playlist.
|
// Send the media player the command to clear players playlist. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) ClearPlaylist(entityId string) error {
|
func (mp MediaPlayer) ClearPlaylist(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -18,9 +17,7 @@ func (mp MediaPlayer) ClearPlaylist(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group players together. Only works on platforms with support for player groups.
|
// Group players together. Only works on platforms with support for player groups. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (mp MediaPlayer) Join(entityId string, serviceData ...map[string]any) error {
|
func (mp MediaPlayer) Join(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -32,8 +29,7 @@ func (mp MediaPlayer) Join(entityId string, serviceData ...map[string]any) error
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the command for next track.
|
// Send the media player the command for next track. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) Next(entityId string) error {
|
func (mp MediaPlayer) Next(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -42,8 +38,7 @@ func (mp MediaPlayer) Next(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the command for pause.
|
// Send the media player the command for pause. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) Pause(entityId string) error {
|
func (mp MediaPlayer) Pause(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -52,8 +47,7 @@ func (mp MediaPlayer) Pause(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the command for play.
|
// Send the media player the command for play. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) Play(entityId string) error {
|
func (mp MediaPlayer) Play(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -62,8 +56,7 @@ func (mp MediaPlayer) Play(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle media player play/pause state.
|
// Toggle media player play/pause state. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) PlayPause(entityId string) error {
|
func (mp MediaPlayer) PlayPause(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -72,8 +65,7 @@ func (mp MediaPlayer) PlayPause(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the command for previous track.
|
// Send the media player the command for previous track. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) Previous(entityId string) error {
|
func (mp MediaPlayer) Previous(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -82,9 +74,7 @@ func (mp MediaPlayer) Previous(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the command to seek in current playing media.
|
// Send the media player the command to seek in current playing media. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (mp MediaPlayer) Seek(entityId string, serviceData ...map[string]any) error {
|
func (mp MediaPlayer) Seek(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -96,8 +86,7 @@ func (mp MediaPlayer) Seek(entityId string, serviceData ...map[string]any) error
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the stop command.
|
// Send the media player the stop command. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) Stop(entityId string) error {
|
func (mp MediaPlayer) Stop(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -106,9 +95,7 @@ func (mp MediaPlayer) Stop(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the command for playing media.
|
// Send the media player the command to play a media. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (mp MediaPlayer) PlayMedia(entityId string, serviceData ...map[string]any) error {
|
func (mp MediaPlayer) PlayMedia(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -120,8 +107,7 @@ func (mp MediaPlayer) PlayMedia(entityId string, serviceData ...map[string]any)
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set repeat mode. Takes an entityId and an optional
|
// Set repeat mode. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (mp MediaPlayer) RepeatSet(entityId string, serviceData ...map[string]any) error {
|
func (mp MediaPlayer) RepeatSet(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -133,9 +119,7 @@ func (mp MediaPlayer) RepeatSet(entityId string, serviceData ...map[string]any)
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the command to change sound mode.
|
// Select a sound mode. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (mp MediaPlayer) SelectSoundMode(entityId string, serviceData ...map[string]any) error {
|
func (mp MediaPlayer) SelectSoundMode(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -147,9 +131,7 @@ func (mp MediaPlayer) SelectSoundMode(entityId string, serviceData ...map[string
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the media player the command to change input source.
|
// Select a source. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (mp MediaPlayer) SelectSource(entityId string, serviceData ...map[string]any) error {
|
func (mp MediaPlayer) SelectSource(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -161,9 +143,7 @@ func (mp MediaPlayer) SelectSource(entityId string, serviceData ...map[string]an
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set shuffling state.
|
// Toggle shuffle state. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (mp MediaPlayer) Shuffle(entityId string, serviceData ...map[string]any) error {
|
func (mp MediaPlayer) Shuffle(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -175,8 +155,7 @@ func (mp MediaPlayer) Shuffle(entityId string, serviceData ...map[string]any) er
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggles a media player power state.
|
// Toggle a media player on/off. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) Toggle(entityId string) error {
|
func (mp MediaPlayer) Toggle(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -185,8 +164,7 @@ func (mp MediaPlayer) Toggle(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn a media player power off.
|
// Turn off a media player. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) TurnOff(entityId string) error {
|
func (mp MediaPlayer) TurnOff(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -195,8 +173,7 @@ func (mp MediaPlayer) TurnOff(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn a media player power on.
|
// Turn on a media player. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) TurnOn(entityId string) error {
|
func (mp MediaPlayer) TurnOn(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -205,9 +182,7 @@ func (mp MediaPlayer) TurnOn(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unjoin the player from a group. Only works on
|
// Separate a player from a group. Only works on platforms with support for player groups. Takes an entityId.
|
||||||
// platforms with support for player groups.
|
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) Unjoin(entityId string) error {
|
func (mp MediaPlayer) Unjoin(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -216,8 +191,7 @@ func (mp MediaPlayer) Unjoin(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn a media player volume down.
|
// Send the media player the command for volume down. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) VolumeDown(entityId string) error {
|
func (mp MediaPlayer) VolumeDown(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -226,9 +200,7 @@ func (mp MediaPlayer) VolumeDown(entityId string) error {
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mute a media player's volume.
|
// Mute a media player. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (mp MediaPlayer) VolumeMute(entityId string, serviceData ...map[string]any) error {
|
func (mp MediaPlayer) VolumeMute(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -240,9 +212,7 @@ func (mp MediaPlayer) VolumeMute(entityId string, serviceData ...map[string]any)
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a media player's volume level.
|
// Set volume level. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (mp MediaPlayer) VolumeSet(entityId string, serviceData ...map[string]any) error {
|
func (mp MediaPlayer) VolumeSet(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
@@ -254,8 +224,7 @@ func (mp MediaPlayer) VolumeSet(entityId string, serviceData ...map[string]any)
|
|||||||
return mp.conn.WriteMessage(req)
|
return mp.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn a media player volume up.
|
// Send the media player the command for volume up. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (mp MediaPlayer) VolumeUp(entityId string) error {
|
func (mp MediaPlayer) VolumeUp(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "media_player"
|
req.Domain = "media_player"
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ func (s Scene) Apply(serviceData ...map[string]any) error {
|
|||||||
return s.conn.WriteMessage(req)
|
return s.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a scene entity. Takes an entityId and an optional
|
// Create a scene entity. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (s Scene) Create(entityId string, serviceData ...map[string]any) error {
|
func (s Scene) Create(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "scene"
|
req.Domain = "scene"
|
||||||
@@ -42,8 +41,7 @@ func (s Scene) Reload() error {
|
|||||||
return s.conn.WriteMessage(req)
|
return s.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TurnOn a scene entity. Takes an entityId and an optional
|
// TurnOn a scene entity. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (s Scene) TurnOn(entityId string, serviceData ...map[string]any) error {
|
func (s Scene) TurnOn(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "scene"
|
req.Domain = "scene"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ type Switch struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TurnOn turns on a switch entity.
|
||||||
func (s Switch) TurnOn(entityId string) error {
|
func (s Switch) TurnOn(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "switch"
|
req.Domain = "switch"
|
||||||
@@ -16,6 +17,7 @@ func (s Switch) TurnOn(entityId string) error {
|
|||||||
return s.conn.WriteMessage(req)
|
return s.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle toggles a switch entity.
|
||||||
func (s Switch) Toggle(entityId string) error {
|
func (s Switch) Toggle(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "switch"
|
req.Domain = "switch"
|
||||||
@@ -24,6 +26,7 @@ func (s Switch) Toggle(entityId string) error {
|
|||||||
return s.conn.WriteMessage(req)
|
return s.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TurnOff turns off a switch entity.
|
||||||
func (s Switch) TurnOff(entityId string) error {
|
func (s Switch) TurnOff(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "switch"
|
req.Domain = "switch"
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ func (tts TTS) ClearCache() error {
|
|||||||
return tts.conn.WriteMessage(req)
|
return tts.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Say something using text-to-speech on a media player with cloud.
|
// Say something using text-to-speech on a media player with cloud. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (tts TTS) CloudSay(entityId string, serviceData ...map[string]any) error {
|
func (tts TTS) CloudSay(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "tts"
|
req.Domain = "tts"
|
||||||
@@ -31,9 +29,7 @@ func (tts TTS) CloudSay(entityId string, serviceData ...map[string]any) error {
|
|||||||
return tts.conn.WriteMessage(req)
|
return tts.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Say something using text-to-speech on a media player with google_translate.
|
// Say something using text-to-speech on a media player with google_translate. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// Takes an entityId and an optional
|
|
||||||
// map that is translated into service_data.
|
|
||||||
func (tts TTS) GoogleTranslateSay(entityId string, serviceData ...map[string]any) error {
|
func (tts TTS) GoogleTranslateSay(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "tts"
|
req.Domain = "tts"
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ type Vacuum struct {
|
|||||||
conn *connect.HAConnection
|
conn *connect.HAConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the vacuum cleaner to do a spot clean-up.
|
// Tell the vacuum cleaner to do a spot clean-up. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (v Vacuum) CleanSpot(entityId string) error {
|
func (v Vacuum) CleanSpot(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -18,8 +17,7 @@ func (v Vacuum) CleanSpot(entityId string) error {
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locate the vacuum cleaner robot.
|
// Locate the vacuum cleaner robot. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (v Vacuum) Locate(entityId string) error {
|
func (v Vacuum) Locate(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -28,8 +26,7 @@ func (v Vacuum) Locate(entityId string) error {
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pause the cleaning task.
|
// Pause the cleaning task. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (v Vacuum) Pause(entityId string) error {
|
func (v Vacuum) Pause(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -38,8 +35,7 @@ func (v Vacuum) Pause(entityId string) error {
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the vacuum cleaner to return to its dock.
|
// Tell the vacuum cleaner to return to its dock. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (v Vacuum) ReturnToBase(entityId string) error {
|
func (v Vacuum) ReturnToBase(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -48,8 +44,7 @@ func (v Vacuum) ReturnToBase(entityId string) error {
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a raw command to the vacuum cleaner. Takes an entityId and an optional
|
// Send a raw command to the vacuum cleaner. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (v Vacuum) SendCommand(entityId string, serviceData ...map[string]any) error {
|
func (v Vacuum) SendCommand(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -61,8 +56,7 @@ func (v Vacuum) SendCommand(entityId string, serviceData ...map[string]any) erro
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the fan speed of the vacuum cleaner. Takes an entityId and an optional
|
// Set the fan speed of the vacuum cleaner. Takes an entityId and an optional map that is translated into service_data.
|
||||||
// map that is translated into service_data.
|
|
||||||
func (v Vacuum) SetFanSpeed(entityId string, serviceData ...map[string]any) error {
|
func (v Vacuum) SetFanSpeed(entityId string, serviceData ...map[string]any) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -75,8 +69,7 @@ func (v Vacuum) SetFanSpeed(entityId string, serviceData ...map[string]any) erro
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start or resume the cleaning task.
|
// Start or resume the cleaning task. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (v Vacuum) Start(entityId string) error {
|
func (v Vacuum) Start(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -85,8 +78,7 @@ func (v Vacuum) Start(entityId string) error {
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start, pause, or resume the cleaning task.
|
// Start, pause, or resume the cleaning task. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (v Vacuum) StartPause(entityId string) error {
|
func (v Vacuum) StartPause(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -95,8 +87,7 @@ func (v Vacuum) StartPause(entityId string) error {
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop the current cleaning task.
|
// Stop the current cleaning task. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (v Vacuum) Stop(entityId string) error {
|
func (v Vacuum) Stop(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -105,8 +96,7 @@ func (v Vacuum) Stop(entityId string) error {
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop the current cleaning task and return to home.
|
// Stop the current cleaning task and return to home. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (v Vacuum) TurnOff(entityId string) error {
|
func (v Vacuum) TurnOff(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
@@ -115,8 +105,7 @@ func (v Vacuum) TurnOff(entityId string) error {
|
|||||||
return v.conn.WriteMessage(req)
|
return v.conn.WriteMessage(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a new cleaning task.
|
// Start a new cleaning task. Takes an entityId.
|
||||||
// Takes an entityId.
|
|
||||||
func (v Vacuum) TurnOn(entityId string) error {
|
func (v Vacuum) TurnOn(entityId string) error {
|
||||||
req := NewBaseServiceRequest(entityId)
|
req := NewBaseServiceRequest(entityId)
|
||||||
req.Domain = "vacuum"
|
req.Domain = "vacuum"
|
||||||
|
|||||||
22
interval.go
22
interval.go
@@ -79,20 +79,20 @@ func (ib intervalBuilder) Call(callback IntervalCallback) intervalBuilderCall {
|
|||||||
return intervalBuilderCall(ib)
|
return intervalBuilderCall(ib)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a DurationString ("2h", "5m", etc) to set the frequency of the interval.
|
// Every takes a DurationString ("2h", "5m", etc.) to set the frequency of the interval.
|
||||||
func (ib intervalBuilderCall) Every(s types.DurationString) intervalBuilderEnd {
|
func (ib intervalBuilderCall) Every(s types.DurationString) intervalBuilderEnd {
|
||||||
d := internal.ParseDuration(string(s))
|
d := internal.ParseDuration(string(s))
|
||||||
ib.interval.frequency = d
|
ib.interval.frequency = d
|
||||||
return intervalBuilderEnd(ib)
|
return intervalBuilderEnd(ib)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a TimeString ("HH:MM") when this interval will start running for the day.
|
// StartingAt takes a TimeString ("HH:MM") when this interval will start running for the day.
|
||||||
func (ib intervalBuilderEnd) StartingAt(s types.TimeString) intervalBuilderEnd {
|
func (ib intervalBuilderEnd) StartingAt(s types.TimeString) intervalBuilderEnd {
|
||||||
ib.interval.startTime = s
|
ib.interval.startTime = s
|
||||||
return ib
|
return ib
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a TimeString ("HH:MM") when this interval will stop running for the day.
|
// EndingAt takes a TimeString ("HH:MM") when this interval will stop running for the day.
|
||||||
func (ib intervalBuilderEnd) EndingAt(s types.TimeString) intervalBuilderEnd {
|
func (ib intervalBuilderEnd) EndingAt(s types.TimeString) intervalBuilderEnd {
|
||||||
ib.interval.endTime = s
|
ib.interval.endTime = s
|
||||||
return ib
|
return ib
|
||||||
@@ -111,10 +111,8 @@ func (ib intervalBuilderEnd) ExceptionRange(start, end time.Time) intervalBuilde
|
|||||||
return ib
|
return ib
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Enable this interval only when the current state of {entityId} matches {state}.
|
||||||
Enable this interval only when the current state of {entityId} matches {state}.
|
// If there is a network error while retrieving state, the interval runs if {runOnNetworkError} is true.
|
||||||
If there is a network error while retrieving state, the interval runs if {runOnNetworkError} is true.
|
|
||||||
*/
|
|
||||||
func (ib intervalBuilderEnd) EnabledWhen(entityId, state string, runOnNetworkError bool) intervalBuilderEnd {
|
func (ib intervalBuilderEnd) EnabledWhen(entityId, state string, runOnNetworkError bool) intervalBuilderEnd {
|
||||||
if entityId == "" {
|
if entityId == "" {
|
||||||
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
||||||
@@ -128,10 +126,8 @@ func (ib intervalBuilderEnd) EnabledWhen(entityId, state string, runOnNetworkErr
|
|||||||
return ib
|
return ib
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Disable this interval when the current state of {entityId} matches {state}.
|
||||||
Disable this interval when the current state of {entityId} matches {state}.
|
// If there is a network error while retrieving state, the interval runs if {runOnNetworkError} is true.
|
||||||
If there is a network error while retrieving state, the interval runs if {runOnNetworkError} is true.
|
|
||||||
*/
|
|
||||||
func (ib intervalBuilderEnd) DisabledWhen(entityId, state string, runOnNetworkError bool) intervalBuilderEnd {
|
func (ib intervalBuilderEnd) DisabledWhen(entityId, state string, runOnNetworkError bool) intervalBuilderEnd {
|
||||||
if entityId == "" {
|
if entityId == "" {
|
||||||
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
||||||
@@ -188,10 +184,10 @@ func runIntervals(a *App) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i Interval) maybeRunCallback(a *App) {
|
func (i Interval) maybeRunCallback(a *App) {
|
||||||
if c := CheckStartEndTime(i.startTime /* isStart = */, true); c.fail {
|
if c := CheckStartEndTime(i.startTime, true); c.fail {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if c := CheckStartEndTime(i.endTime /* isStart = */, false); c.fail {
|
if c := CheckStartEndTime(i.endTime, false); c.fail {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if c := CheckExceptionDates(i.exceptionDates); c.fail {
|
if c := CheckExceptionDates(i.exceptionDates); c.fail {
|
||||||
|
|||||||
18
schedule.go
18
schedule.go
@@ -83,8 +83,7 @@ func (sb scheduleBuilderCall) At(s string) scheduleBuilderEnd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sunrise takes an optional duration string that is passed to time.ParseDuration.
|
// Sunrise takes an optional duration string that is passed to time.ParseDuration.
|
||||||
// Examples include "-1.5h", "30m", etc. See https://pkg.go.dev/time#ParseDuration
|
// Examples include "-1.5h", "30m", etc. See https://pkg.go.dev/time#ParseDuration for the full list.
|
||||||
// for full list.
|
|
||||||
func (sb scheduleBuilderCall) Sunrise(offset ...types.DurationString) scheduleBuilderEnd {
|
func (sb scheduleBuilderCall) Sunrise(offset ...types.DurationString) scheduleBuilderEnd {
|
||||||
sb.schedule.isSunrise = true
|
sb.schedule.isSunrise = true
|
||||||
if len(offset) > 0 {
|
if len(offset) > 0 {
|
||||||
@@ -94,8 +93,7 @@ func (sb scheduleBuilderCall) Sunrise(offset ...types.DurationString) scheduleBu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sunset takes an optional duration string that is passed to time.ParseDuration.
|
// Sunset takes an optional duration string that is passed to time.ParseDuration.
|
||||||
// Examples include "-1.5h", "30m", etc. See https://pkg.go.dev/time#ParseDuration
|
// Examples include "-1.5h", "30m", etc. See https://pkg.go.dev/time#ParseDuration for the full list.
|
||||||
// for full list.
|
|
||||||
func (sb scheduleBuilderCall) Sunset(offset ...types.DurationString) scheduleBuilderEnd {
|
func (sb scheduleBuilderCall) Sunset(offset ...types.DurationString) scheduleBuilderEnd {
|
||||||
sb.schedule.isSunset = true
|
sb.schedule.isSunset = true
|
||||||
if len(offset) > 0 {
|
if len(offset) > 0 {
|
||||||
@@ -114,10 +112,8 @@ func (sb scheduleBuilderEnd) OnlyOnDates(t time.Time, tl ...time.Time) scheduleB
|
|||||||
return sb
|
return sb
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// EnabledWhen enables this schedule only when the current state of {entityId} matches {state}.
|
||||||
Enable this schedule only when the current state of {entityId} matches {state}.
|
// If there is a network error while retrieving state, the schedule runs if {runOnNetworkError} is true.
|
||||||
If there is a network error while retrieving state, the schedule runs if {runOnNetworkError} is true.
|
|
||||||
*/
|
|
||||||
func (sb scheduleBuilderEnd) EnabledWhen(entityId, state string, runOnNetworkError bool) scheduleBuilderEnd {
|
func (sb scheduleBuilderEnd) EnabledWhen(entityId, state string, runOnNetworkError bool) scheduleBuilderEnd {
|
||||||
if entityId == "" {
|
if entityId == "" {
|
||||||
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
||||||
@@ -131,10 +127,8 @@ func (sb scheduleBuilderEnd) EnabledWhen(entityId, state string, runOnNetworkErr
|
|||||||
return sb
|
return sb
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// DisabledWhen disables this schedule when the current state of {entityId} matches {state}.
|
||||||
Disable this schedule when the current state of {entityId} matches {state}.
|
// If there is a network error while retrieving state, the schedule runs if {runOnNetworkError} is true.
|
||||||
If there is a network error while retrieving state, the schedule runs if {runOnNetworkError} is true.
|
|
||||||
*/
|
|
||||||
func (sb scheduleBuilderEnd) DisabledWhen(entityId, state string, runOnNetworkError bool) scheduleBuilderEnd {
|
func (sb scheduleBuilderEnd) DisabledWhen(entityId, state string, runOnNetworkError bool) scheduleBuilderEnd {
|
||||||
if entityId == "" {
|
if entityId == "" {
|
||||||
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
panic(fmt.Sprintf("entityId is empty in EnabledWhen entityId='%s' state='%s'", entityId, state))
|
||||||
|
|||||||
6
state.go
6
state.go
@@ -81,7 +81,7 @@ func (s *StateImpl) Get(entityId string) (EntityState, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListEntities returns a list of all entities in Home Assistant.
|
// ListEntities returns a list of all entities in Home Assistant.
|
||||||
// see rest documentation for more details: https://developers.home-assistant.io/docs/api/rest/#actions
|
// See REST documentation for more details: https://developers.home-assistant.io/docs/api/rest/#actions
|
||||||
func (s *StateImpl) ListEntities() ([]EntityState, error) {
|
func (s *StateImpl) ListEntities() ([]EntityState, error) {
|
||||||
resp, err := s.httpClient.GetStates()
|
resp, err := s.httpClient.GetStates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -101,7 +101,7 @@ func (s *StateImpl) Equals(entityId string, expectedState string) (bool, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateImpl) BeforeSunrise(offset ...types.DurationString) bool {
|
func (s *StateImpl) BeforeSunrise(offset ...types.DurationString) bool {
|
||||||
sunrise := getSunriseSunset(s /* sunrise = */, true, carbon.Now(), offset...)
|
sunrise := getSunriseSunset(s, true, carbon.Now(), offset...)
|
||||||
return carbon.Now().Lt(sunrise)
|
return carbon.Now().Lt(sunrise)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ func (s *StateImpl) AfterSunrise(offset ...types.DurationString) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateImpl) BeforeSunset(offset ...types.DurationString) bool {
|
func (s *StateImpl) BeforeSunset(offset ...types.DurationString) bool {
|
||||||
sunset := getSunriseSunset(s /* sunrise = */, false, carbon.Now(), offset...)
|
sunset := getSunriseSunset(s, false, carbon.Now(), offset...)
|
||||||
return carbon.Now().Lt(sunset)
|
return carbon.Now().Lt(sunset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
types/app.go
10
types/app.go
@@ -7,7 +7,7 @@ type NewAppRequest struct {
|
|||||||
|
|
||||||
// Optional
|
// Optional
|
||||||
// Deprecated: use URL instead
|
// Deprecated: use URL instead
|
||||||
// IpAddress of your Home Assistant instance i.e. "localhost"
|
// IpAddress of your Home Assistant instance, e.g. "localhost"
|
||||||
// or "192.168.86.59" etc.
|
// or "192.168.86.59" etc.
|
||||||
IpAddress string
|
IpAddress string
|
||||||
|
|
||||||
@@ -18,18 +18,18 @@ type NewAppRequest struct {
|
|||||||
|
|
||||||
// Required
|
// Required
|
||||||
// Auth token generated in Home Assistant. Used
|
// Auth token generated in Home Assistant. Used
|
||||||
// to connect to the Websocket API.
|
// to connect to the WebSocket API.
|
||||||
HAAuthToken string
|
HAAuthToken string
|
||||||
|
|
||||||
// Required
|
// Required
|
||||||
// EntityId of the zone representing your home e.g. "zone.home".
|
// EntityId of the zone representing your home, e.g. "zone.home".
|
||||||
// Used to pull latitude/longitude from Home Assistant
|
// Used to pull latitude/longitude from Home Assistant
|
||||||
// to calculate sunset/sunrise times.
|
// to calculate sunset/sunrise times.
|
||||||
HomeZoneEntityId string
|
HomeZoneEntityId string
|
||||||
|
|
||||||
// Optional
|
// Optional
|
||||||
// Whether to use secure connections for http and websockets.
|
// Whether to use secure connections for HTTP and WebSockets.
|
||||||
// Setting this to `true` will use `https://` instead of `https://`
|
// Setting this to `true` will use `https://` instead of `http://`
|
||||||
// and `wss://` instead of `ws://`.
|
// and `wss://` instead of `ws://`.
|
||||||
Secure bool
|
Secure bool
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user