some errors still causing crashes, error handling work needed

This commit is contained in:
2017-12-13 16:26:29 +01:00
parent 7a0358109a
commit 67d4d5f1d9
2 changed files with 163 additions and 62 deletions

223
ledd.go
View File

@@ -3,6 +3,7 @@ package main
import (
"encoding/binary"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"net"
"os"
"os/signal"
@@ -132,7 +133,13 @@ func (manager *LEDManager) start() {
for {
select {
case led := <-manager.add:
log.Debugf("[%s] Request to add led: %s", led.backend, led.name)
log.Debugf("[%s] Request to add LED: %s (%s)", led.backend, led.name, led.channel)
if led.name == "" || len(led.channel) == 0 || led.backend == "" {
log.Warningf("[%s] Can't add LED without required information! (%s)", LOG_CLIENTS, led)
continue
}
manager.leds[led.name] = led
go manager.color(led)
err := LEDCollection.Insert(led)
@@ -141,7 +148,8 @@ func (manager *LEDManager) start() {
}
case led := <-manager.remove:
if _, ok := manager.leds[led.name]; ok {
log.Debugf("[%s] Request to remove led %s", led.backend, led.name)
log.Debugf("[%s] Request to remove %s", led.backend, led.name)
LEDCollection.RemoveAll(bson.M{"name": led.name})
delete(manager.leds, led.name)
}
case color := <-manager.broadcast:
@@ -158,7 +166,33 @@ func (manager *LEDManager) color(led *LED) {
for {
select {
case color := <-led.color:
led.setColor(color)
if backend, ok := backManager.backends[led.backend]; ok {
if len(led.channel) != 3 {
log.Warningf("[%s] Currently only RGB LEDs are supported", led.name)
return
}
cMap := make(map[int32]int32)
r, g, b := color.Clamped().RGB255()
cMap[led.channel[0]] = int32((float64(r) / 255) * float64(backend.resolution))
cMap[led.channel[1]] = int32((float64(g) / 255) * float64(backend.resolution))
cMap[led.channel[2]] = int32((float64(b) / 255) * float64(backend.resolution))
wrapperMsg := &ledd.BackendWrapperMessage{
Msg: &ledd.BackendWrapperMessage_MSetChannel{
MSetChannel: &ledd.BackendSetChannel{
NewChannelValues: cMap}}}
data, err := proto.Marshal(wrapperMsg)
if err != nil {
log.Warningf("[%s] Failed to encode protobuf msg to %s: %s", led.name, backend.name, err)
}
backend.data <- prepareProtobuf(data)
} else {
log.Warningf("[LM] Failed to set color for %s: backend %s not found", led.name, led.backend)
}
}
}
}
@@ -170,7 +204,7 @@ func (manager *BackendManager) start() {
select {
case backend := <-manager.register:
manager.backends[backend.name] = backend
log.Debugf("[%s] New backend: %s", LOG_BACKEND, backend.niceName())
log.Debugf("[%s] %s registered", LOG_BACKEND, backend.niceName())
wrapperMsg := &ledd.BackendWrapperMessage{
Msg: &ledd.BackendWrapperMessage_MLedd{
MLedd: &ledd.LedD{
@@ -187,7 +221,7 @@ func (manager *BackendManager) start() {
backend.data <- prepareProtobuf(data)
case backend := <-manager.unregister:
if _, ok := manager.backends[backend.name]; ok {
log.Debugf("[%s] Backend %s removed: connection terminated", LOG_BACKEND, backend.socket.RemoteAddr())
log.Debugf("[%s] %s removed: connection terminated", LOG_BACKEND, backend.socket.RemoteAddr())
close(backend.data)
delete(manager.backends, backend.name)
}
@@ -238,10 +272,10 @@ func (manager *BackendManager) receive(backend *Backend) {
if length > 0 {
msgLen := binary.BigEndian.Uint32(message[0:4])
log.Debugf("[%s] Read %d bytes, first protobuf is %d long", backend.niceName(), length, msgLen)
// log.Debugf("[%s] Read %d bytes, first protobuf is %d long", backend.niceName(), length, msgLen)
backendMsg := &ledd.BackendWrapperMessage{}
err = proto.Unmarshal(message[4:msgLen+1], backendMsg)
err = proto.Unmarshal(message[4:msgLen+4], backendMsg)
if err != nil {
log.Warningf("[%s] Couldn't decode protobuf msg!", backend.niceName())
continue
@@ -269,10 +303,46 @@ func (manager *ClientManager) start() {
select {
case client := <-manager.register:
manager.clients[client] = true
log.Debugf("[%s] New frontend (%s)", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform)
log.Debugf("[%s] Client %s (%s) registered", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform)
backends := make([]*ledd.Backend, 0, len(backManager.backends))
leds := make([]*ledd.LED, 0, len(ledManager.leds))
for _, led := range ledManager.leds {
leds = append(leds, &ledd.LED{
Name: led.name,
})
}
for _, backend := range backManager.backends {
backends = append(backends, &ledd.Backend{
Name: backend.name,
Channel: backend.channel,
Resolution: backend.resolution,
Type: backend.platformType,
Version: backend.version,
})
}
wrapperMsg := &ledd.ClientWrapperMessage{
Leds: leds,
Backends: backends,
Msg: &ledd.ClientWrapperMessage_MLedd{
MLedd: &ledd.LedD{
Name: config.Name,
},
},
}
data, err := proto.Marshal(wrapperMsg)
if err != nil {
log.Warningf("[%s] Failed to encode protobuf msg: %s", client.socket.RemoteAddr(), err)
}
client.data <- prepareProtobuf(data)
case client := <-manager.unregister:
if _, ok := manager.clients[client]; ok {
log.Debugf("[%s] Removed client (%s)", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform)
log.Debugf("[%s] %s (%s) removed", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform)
close(client.data)
delete(manager.clients, client)
}
@@ -313,55 +383,95 @@ func (manager *ClientManager) receive(client *Client) {
break
}
if length > 0 {
msgLen := binary.BigEndian.Uint32(message[0:4])
//log.Debugf("[%s] Read %d bytes", client.socket.RemoteAddr(), length)
log.Debugf("[%s] Read %d bytes, first protobuf is %d long", client.socket.RemoteAddr(), length, msgLen)
for i := 0; i < length; {
msgLen := int(binary.BigEndian.Uint32(message[i:i+4]))
clientMsg := &ledd.ClientWrapperMessage{}
err = proto.Unmarshal(message[4:msgLen+1], clientMsg)
if err != nil {
log.Warningf("[%s] Couldn't decode protobuf msg!", client.socket.RemoteAddr())
continue
}
// log.Debugf("[%s] Reading protobuf after %d (len=%d)", client.socket.RemoteAddr(), i+4, msgLen)
switch msg := clientMsg.Msg.(type) {
case *ledd.ClientWrapperMessage_MClient:
client.platform = msg.MClient.Type
log.Infof("[%s] %s is now identified as client (%s)", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform)
clientManager.register <- client
case *ledd.ClientWrapperMessage_MGetLed:
allLED := make([]*ledd.LED, 0)
for _, led := range ledManager.leds {
allLED = append(allLED, &ledd.LED{Name: led.name})
}
data, err := proto.Marshal(&ledd.ClientWrapperMessage{Leds: allLED})
clientMsg := &ledd.ClientWrapperMessage{}
err = proto.Unmarshal(message[i+4:i+msgLen+4], clientMsg)
i += msgLen + 4
if err != nil {
log.Errorf("[%s] Error encoding protobuf: %s", client.socket.RemoteAddr(), err)
log.Warningf("[%s] Couldn't decode protobuf msg!", client.socket.RemoteAddr())
continue
}
client.data <- prepareProtobuf(data)
case *ledd.ClientWrapperMessage_MAddLed:
backend, ok := backManager.backends[msg.MAddLed.Backend]
if !ok {
log.Warningf("[%s] Can't add LED for non-existing backend %s", client.socket.RemoteAddr(), msg.MAddLed.Backend)
}
switch msg := clientMsg.Msg.(type) {
case *ledd.ClientWrapperMessage_MClient:
client.platform = msg.MClient.Type
log.Infof("[%s] %s is now identified as client (%s)", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform)
clientManager.register <- client
case *ledd.ClientWrapperMessage_MGetLed:
allLED := make([]*ledd.LED, 0)
nLED := &LED{
name: msg.MAddLed.Name,
channel: msg.MAddLed.Channel,
backend: backend.name,
}
for _, led := range ledManager.leds {
allLED = append(allLED, &ledd.LED{Name: led.name})
}
ledManager.add <- nLED
case *ledd.ClientWrapperMessage_MSetLed:
led, ok := ledManager.leds[msg.MSetLed.Name]
if !ok {
log.Warningf("[%s] Failed to set LED %s: LED not found", client.socket.RemoteAddr(), msg.MSetLed.Name)
}
data, err := proto.Marshal(&ledd.ClientWrapperMessage{Leds: allLED})
if err != nil {
log.Errorf("[%s] Error encoding protobuf: %s", client.socket.RemoteAddr(), err)
break
}
led.color <- colorful.Hcl(msg.MSetLed.Colour.Hue, msg.MSetLed.Colour.Chroma, msg.MSetLed.Colour.Light)
client.data <- prepareProtobuf(data)
case *ledd.ClientWrapperMessage_MAddLed:
backend, ok := backManager.backends[msg.MAddLed.Backend]
if !ok {
log.Warningf("[%s] Can't add LED for non-existing backend %s", client.socket.RemoteAddr(), msg.MAddLed.Backend)
break
}
if _, ok := ledManager.leds[msg.MAddLed.Name]; ok {
log.Warningf("[%s] Can't add LED with exisiting name %s", client.socket.RemoteAddr(), msg.MAddLed.Name)
break
}
nLED := &LED{
name: msg.MAddLed.Name,
channel: msg.MAddLed.Channel,
backend: backend.name,
color: make(chan colorful.Color),
}
ledManager.add <- nLED
case *ledd.ClientWrapperMessage_MSetLed:
leds := clientMsg.Leds
if len(leds) == 0 {
log.Warningf("[%s] Got setLED with no LEDs attached!", client.socket.RemoteAddr())
break
}
for _, pLED := range leds {
led, ok := ledManager.leds[pLED.Name]
if !ok {
log.Warningf("[%s] Failed to set %s: not found", client.socket.RemoteAddr(), pLED.Name)
break
}
// log.Debugf("[%s] Set %s to %s", client.socket.RemoteAddr(), led.name, colorful.Hcl(msg.MSetLed.Colour.Hue, msg.MSetLed.Colour.Chroma, msg.MSetLed.Colour.Light))
led.color <- colorful.Hcl(msg.MSetLed.Colour.Hue, msg.MSetLed.Colour.Chroma, msg.MSetLed.Colour.Light)
}
case *ledd.ClientWrapperMessage_MSetDirect:
backend, ok := backManager.backends[msg.MSetDirect.Backend]
if !ok {
log.Warningf("[%s] Can't set channel for non-existing backend %s", client.socket.RemoteAddr(), msg.MSetDirect.Backend)
break
}
backend.setChannel(msg.MSetDirect.Channel, msg.MSetDirect.Value)
case *ledd.ClientWrapperMessage_MRemoveLed:
led, ok := ledManager.leds[msg.MRemoveLed.Name]
if !ok {
log.Warningf("[%s] Failed to remove %s: not found", client.socket.RemoteAddr(), msg.MRemoveLed.Name)
break
}
ledManager.remove <- led
}
}
}
}
@@ -383,19 +493,10 @@ func (backend *Backend) niceName() string {
}
}
func (led *LED) setColor(color colorful.Color) {
backend := backManager.backends[led.backend]
if len(led.channel) != 3 {
log.Warningf("[%s] Currently only RGB LEDs are supported", led.name)
return
}
func (backend Backend) setChannel(channel int32, val int32) {
cMap := make(map[int32]int32)
cMap[led.channel[0]] = int32(color.R * float64(backend.resolution))
cMap[led.channel[1]] = int32(color.G * float64(backend.resolution))
cMap[led.channel[2]] = int32(color.B * float64(backend.resolution))
cMap[channel] = val
wrapperMsg := &ledd.BackendWrapperMessage{
Msg: &ledd.BackendWrapperMessage_MSetChannel{
@@ -404,7 +505,7 @@ func (led *LED) setColor(color colorful.Color) {
data, err := proto.Marshal(wrapperMsg)
if err != nil {
log.Warningf("[%s] Failed to encode protobuf msg to %s: %s", led.name, backend.name, err)
log.Warningf("[%s] Failed to encode protobuf msg: %s", backend.niceName(), err)
}
backend.data <- prepareProtobuf(data)