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 ( import (
"encoding/binary" "encoding/binary"
"gopkg.in/mgo.v2" "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"net" "net"
"os" "os"
"os/signal" "os/signal"
@@ -132,7 +133,13 @@ func (manager *LEDManager) start() {
for { for {
select { select {
case led := <-manager.add: 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 manager.leds[led.name] = led
go manager.color(led) go manager.color(led)
err := LEDCollection.Insert(led) err := LEDCollection.Insert(led)
@@ -141,7 +148,8 @@ func (manager *LEDManager) start() {
} }
case led := <-manager.remove: case led := <-manager.remove:
if _, ok := manager.leds[led.name]; ok { 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) delete(manager.leds, led.name)
} }
case color := <-manager.broadcast: case color := <-manager.broadcast:
@@ -158,7 +166,33 @@ func (manager *LEDManager) color(led *LED) {
for { for {
select { select {
case color := <-led.color: 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 { select {
case backend := <-manager.register: case backend := <-manager.register:
manager.backends[backend.name] = backend 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{ wrapperMsg := &ledd.BackendWrapperMessage{
Msg: &ledd.BackendWrapperMessage_MLedd{ Msg: &ledd.BackendWrapperMessage_MLedd{
MLedd: &ledd.LedD{ MLedd: &ledd.LedD{
@@ -187,7 +221,7 @@ func (manager *BackendManager) start() {
backend.data <- prepareProtobuf(data) backend.data <- prepareProtobuf(data)
case backend := <-manager.unregister: case backend := <-manager.unregister:
if _, ok := manager.backends[backend.name]; ok { 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) close(backend.data)
delete(manager.backends, backend.name) delete(manager.backends, backend.name)
} }
@@ -238,10 +272,10 @@ func (manager *BackendManager) receive(backend *Backend) {
if length > 0 { if length > 0 {
msgLen := binary.BigEndian.Uint32(message[0:4]) 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{} backendMsg := &ledd.BackendWrapperMessage{}
err = proto.Unmarshal(message[4:msgLen+1], backendMsg) err = proto.Unmarshal(message[4:msgLen+4], backendMsg)
if err != nil { if err != nil {
log.Warningf("[%s] Couldn't decode protobuf msg!", backend.niceName()) log.Warningf("[%s] Couldn't decode protobuf msg!", backend.niceName())
continue continue
@@ -269,10 +303,46 @@ func (manager *ClientManager) start() {
select { select {
case client := <-manager.register: case client := <-manager.register:
manager.clients[client] = true 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: case client := <-manager.unregister:
if _, ok := manager.clients[client]; ok { 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) close(client.data)
delete(manager.clients, client) delete(manager.clients, client)
} }
@@ -313,55 +383,95 @@ func (manager *ClientManager) receive(client *Client) {
break break
} }
if length > 0 { 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{} // log.Debugf("[%s] Reading protobuf after %d (len=%d)", client.socket.RemoteAddr(), i+4, msgLen)
err = proto.Unmarshal(message[4:msgLen+1], clientMsg)
if err != nil {
log.Warningf("[%s] Couldn't decode protobuf msg!", client.socket.RemoteAddr())
continue
}
switch msg := clientMsg.Msg.(type) { clientMsg := &ledd.ClientWrapperMessage{}
case *ledd.ClientWrapperMessage_MClient: err = proto.Unmarshal(message[i+4:i+msgLen+4], clientMsg)
client.platform = msg.MClient.Type i += msgLen + 4
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})
if err != nil { 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) switch msg := clientMsg.Msg.(type) {
case *ledd.ClientWrapperMessage_MAddLed: case *ledd.ClientWrapperMessage_MClient:
backend, ok := backManager.backends[msg.MAddLed.Backend] client.platform = msg.MClient.Type
if !ok { log.Infof("[%s] %s is now identified as client (%s)", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform)
log.Warningf("[%s] Can't add LED for non-existing backend %s", client.socket.RemoteAddr(), msg.MAddLed.Backend) clientManager.register <- client
} case *ledd.ClientWrapperMessage_MGetLed:
allLED := make([]*ledd.LED, 0)
nLED := &LED{ for _, led := range ledManager.leds {
name: msg.MAddLed.Name, allLED = append(allLED, &ledd.LED{Name: led.name})
channel: msg.MAddLed.Channel, }
backend: backend.name,
}
ledManager.add <- nLED data, err := proto.Marshal(&ledd.ClientWrapperMessage{Leds: allLED})
case *ledd.ClientWrapperMessage_MSetLed: if err != nil {
led, ok := ledManager.leds[msg.MSetLed.Name] log.Errorf("[%s] Error encoding protobuf: %s", client.socket.RemoteAddr(), err)
if !ok { break
log.Warningf("[%s] Failed to set LED %s: LED not found", client.socket.RemoteAddr(), msg.MSetLed.Name) }
}
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) { func (backend Backend) setChannel(channel int32, val int32) {
backend := backManager.backends[led.backend]
if len(led.channel) != 3 {
log.Warningf("[%s] Currently only RGB LEDs are supported", led.name)
return
}
cMap := make(map[int32]int32) cMap := make(map[int32]int32)
cMap[led.channel[0]] = int32(color.R * float64(backend.resolution)) cMap[channel] = val
cMap[led.channel[1]] = int32(color.G * float64(backend.resolution))
cMap[led.channel[2]] = int32(color.B * float64(backend.resolution))
wrapperMsg := &ledd.BackendWrapperMessage{ wrapperMsg := &ledd.BackendWrapperMessage{
Msg: &ledd.BackendWrapperMessage_MSetChannel{ Msg: &ledd.BackendWrapperMessage_MSetChannel{
@@ -404,7 +505,7 @@ func (led *LED) setColor(color colorful.Color) {
data, err := proto.Marshal(wrapperMsg) data, err := proto.Marshal(wrapperMsg)
if err != nil { 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) backend.data <- prepareProtobuf(data)

2
proto

Submodule proto updated: c0b46db0cf...b0f65bb09a