Skip to content

Commit

Permalink
websocket reconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
gaetancollaud committed Dec 29, 2023
1 parent 16ae0b4 commit 09f4d32
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 11 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ tests/

digitalstrom-mqtt

node_modules/

docs/docker/homeassistant
.env
/config.yaml
Expand Down
18 changes: 18 additions & 0 deletions docs/websocket-server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { WebSocketServer } from 'ws';

/**
* This websocket server is here just to simulate a digitalstrom server and how to reconnect
* @type {WebSocketServer}
*/

const wss = new WebSocketServer({ port: 8090 });

wss.on('connection', function connection(ws) {
ws.on('message', function message(data) {
console.log('received: %s', data);
});

// ws.send('something');
});

console.log('Started')
32 changes: 32 additions & 0 deletions docs/websocket-server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions docs/websocket-server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "module",
"dependencies": {
"ws": "^8.16.0"
}
}
45 changes: 34 additions & 11 deletions pkg/digitalstrom/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ import (
"net/url"
"strconv"
"strings"
"time"
)

const WEBSOCKET_RECONNECT_DELAY = 5 * time.Second

type NotificationCallback func(notification WebsocketNotification)

// Client is the interface definition as used by this library, the
Expand Down Expand Up @@ -43,9 +46,10 @@ type Client interface {
// client implements the DigitalStrom interface.
// Clients are safe for concurrent use by multiple goroutines.
type client struct {
httpClient *http.Client
options ClientOptions
websocketConnection *websocket.Conn
httpClient *http.Client
options ClientOptions
websocketConnection *websocket.Conn
websocketConnectionOpen bool

notificationCallbacks map[string]NotificationCallback
}
Expand All @@ -67,8 +71,7 @@ func NewClient(options *ClientOptions) Client {
}
}

func (c *client) Connect() error {
// TODO handle reconnection
func (c *client) websocketConnect() error {
websocketHost := "ws://" + c.options.Host + ":8090/api/v1/apartment/notifications"
log.Trace().Str("host", websocketHost).Msg("Connecting to websocket")
headers := http.Header{}
Expand All @@ -86,15 +89,36 @@ func (c *client) Connect() error {
if err != nil {
return fmt.Errorf("error writing to websocket: %w", err)
}
log.Info().Msg("Connected to websocket for notifications")
c.websocketConnectionOpen = true
return nil
}

func (c *client) Connect() error {
c.websocketConnectionOpen = false
err := c.websocketConnect()
if err != nil {
return err
}

// websocket message reader
go func() {
firstMessage := true
for {
var notification WebsocketNotification
err := c.websocketConnection.ReadJSON(&notification)
if err != nil {
log.Error().Err(err).Msg("Websocket reading error")
break
if !c.websocketConnectionOpen {
// we're closing, ignore read errors
break
} else {
log.Error().Err(err).Msg("Websocket reading error, will try to reconnect")
time.Sleep(WEBSOCKET_RECONNECT_DELAY)
err = c.websocketConnect()
if err != nil {
log.Error().Err(err).Msg("Websocket reconnect error")
}
}
} else if notification.Arguments == nil || len(notification.Arguments) == 0 {
if !firstMessage {
log.Warn().Msg("No argument received in notification")
Expand All @@ -107,18 +131,17 @@ func (c *client) Connect() error {
}
firstMessage = false
}
log.Warn().Msg("Closing websocket reader")
log.Info().Msg("Closing websocket reader")
}()

return nil
}

// Disconnect stops all the ongoing calls and unsubscribe from the notification websocket
func (c *client) Disconnect() error {

c.websocketConnectionOpen = false
c.httpClient.CloseIdleConnections()
c.websocketConnection.Close()

_ = c.websocketConnection.Close()
return nil
}

Expand Down

0 comments on commit 09f4d32

Please sign in to comment.