arlo-go/events_stream.go
2018-09-16 23:44:41 -05:00

148 lines
3.3 KiB
Go

package arlo_golang
import (
"bytes"
"encoding/json"
"fmt"
"log"
"sync"
"github.com/pkg/errors"
"github.com/r3labs/sse"
)
var FAILED_TO_PUBLISH = errors.New("Failed to publish")
var FAILED_TO_DECODE_JSON = errors.New("Failed to decode JSON")
var FAILED_TO_SUBSCRIBE = errors.New("Failed to subscribe to SSEClient")
type Subscriber chan NotifyResponse
type EventStream struct {
Registered bool
Connected bool
SSEClient *sse.Client
Events chan *sse.Event
Subscriptions map[string]*Subscriber
ErrorChan chan error
Responses map[string]NotifyResponse
Verbose bool
sync.Mutex
}
func NewEventStream(url string, headers map[string]string) *EventStream {
SSEClient := sse.NewClient(url)
SSEClient.Headers = headers
return &EventStream{
SSEClient: SSEClient,
Events: make(chan *sse.Event),
Subscriptions: map[string]*Subscriber{},
ErrorChan: make(chan error, 1),
}
}
func (e *EventStream) Listen() {
go func() {
err := e.SSEClient.SubscribeChan("", e.Events)
if err != nil {
fmt.Println(FAILED_TO_SUBSCRIBE)
e.ErrorChan <- FAILED_TO_SUBSCRIBE
}
}()
for event := range e.Events {
fmt.Println("Got event message here.")
fmt.Printf("EVENT: %s\n", event.Event)
fmt.Printf("DATA: %s\n", event.Data)
if event.Data != nil {
notifyResponse := &NotifyResponse{}
b := bytes.NewBuffer(event.Data)
err := json.NewDecoder(b).Decode(notifyResponse)
if err != nil {
e.ErrorChan <- errors.WithMessage(err, "failed to decode JSON")
break
}
if notifyResponse.Status == "connected" {
e.Connected = true
fmt.Println("Connected.")
break
}
}
}
go func() {
for event := range e.Events {
fmt.Println("Got event message.")
fmt.Printf("EVENT: %X\n", event.Event)
fmt.Printf("DATA: %X\n", event.Data)
if event.Data != nil {
notifyResponse := &NotifyResponse{}
b := bytes.NewBuffer(event.Data)
err := json.NewDecoder(b).Decode(notifyResponse)
if err != nil {
e.ErrorChan <- FAILED_TO_DECODE_JSON
break
}
if notifyResponse.Status == "connected" {
fmt.Println("Connected.")
e.Connected = true
} else if notifyResponse.Status == "disconnected" {
fmt.Println("Disconnected.")
e.Connected = false
} else {
fmt.Printf("Message for transId: %s", notifyResponse.TransId)
if subscriber, ok := e.Subscriptions[notifyResponse.TransId]; ok {
e.Lock()
*subscriber <- *notifyResponse
close(*subscriber)
delete(e.Subscriptions, notifyResponse.TransId)
e.Unlock()
} else {
// Throw away the message.
fmt.Println("Throwing away message.")
}
}
}
}
}()
/*
go func() {
fmt.Println("go func to recieve a subscription.")
for {
fmt.Println("go func for loop to recieve a subscription.")
select {
case s := <-e.Subscriptions:
if resp, ok := e.Responses[s.transId]; ok {
fmt.Println("Recieved a subscription, sending response.")
s.ResponseChan <- resp
e.Lock()
delete(e.Responses, s.transId)
e.Unlock()
} else {
fmt.Println("Recieved a subscription error, sending error response.")
e.ErrorChan <- FAILED_TO_PUBLISH
break
}
}
}
}()
*/
}
func (e *EventStream) verbose(params ...interface{}) {
if e.Verbose {
log.Println(params...)
}
}