-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathRemoteMatrix.go
136 lines (105 loc) · 2.4 KB
/
RemoteMatrix.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package remote
import (
"encoding/gob"
"image"
"io"
"net"
"time"
"github.com/ninjasphere/gestic-tools/go-gestic-sdk"
"github.com/ninjasphere/go-ninja/logger"
)
var log = logger.GetLogger("remote")
type pane interface {
IsEnabled() bool
KeepAwake() bool
Render() (*image.RGBA, error)
Gesture(*gestic.GestureMessage)
}
type lockable interface {
Locked() bool
}
type Matrix struct {
Disconnected chan bool
log *logger.Logger
conn net.Conn
incoming *gob.Decoder
outgoing *gob.Encoder
pane pane
}
func NewTCPMatrix(pane pane, host string) *Matrix {
matrix := NewMatrix(pane)
// Connect to the led controller remote pane interface
go func() {
for {
tcpAddr, err := net.ResolveTCPAddr("tcp", host)
if err != nil {
println("ResolveTCPAddr failed:", err.Error())
} else {
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
log.Errorf("Dial failed: %s", err)
} else {
log.Infof("Connected")
go matrix.start(conn)
<-matrix.Disconnected
log.Infof("Disconnected")
}
}
log.Infof("Waiting to reconnect")
time.Sleep(time.Second / 2)
}
}()
return matrix
}
func NewMatrix(pane pane) *Matrix {
matrix := &Matrix{
log: logger.GetLogger("Matrix"),
Disconnected: make(chan bool, 1),
pane: pane,
}
return matrix
}
func (m *Matrix) Close() {
if m.conn != nil {
m.conn.Close()
}
m.Disconnected <- true
}
func (m *Matrix) start(conn net.Conn) {
m.conn = conn
m.incoming = gob.NewDecoder(m.conn)
m.outgoing = gob.NewEncoder(m.conn)
for {
var msg Outgoing
err := m.incoming.Decode(&msg)
if err != nil {
if err == io.EOF {
m.log.Warningf("Lost connection to led controller: %s", err)
} else {
m.log.Errorf("Error communicating with led controller: %s", err)
}
m.Close()
break
}
if msg.Gesture != nil {
m.pane.Gesture(msg.Gesture)
}
if msg.FrameRequested {
//m.log.Debugf("Rendering pane...")
img, err := m.pane.Render()
if err != nil {
m.log.Errorf("Pane returned an error: %s", err)
}
var locked = false
if lockablePane, ok := m.pane.(lockable); ok {
locked = lockablePane.Locked()
}
if err := m.outgoing.Encode(&Incoming{img, err, m.pane.KeepAwake(), locked}); err != nil {
m.log.Errorf("Remote matrix error: %s. Disconnecting.", err)
m.Close()
break
}
//m.log.Debugf("Sent frame")
}
}
}