-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add server part based on old status-board-server
- Loading branch information
Showing
7 changed files
with
258 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,3 +19,6 @@ yarn-error.log* | |
*.njsproj | ||
*.sln | ||
*.sw? | ||
|
||
# application specific | ||
board-config.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package board | ||
|
||
import ( | ||
"log" | ||
"net" | ||
) | ||
|
||
// MaxDatagramSize is the maximum read buffer size for network communication | ||
const MaxDatagramSize = 8192 | ||
|
||
// OpenMulticastUdpConnection opens a UDP multicast connection for read and returns it | ||
func OpenMulticastUdpConnection(address string) (err error, listener *net.UDPConn) { | ||
addr, err := net.ResolveUDPAddr("udp", address) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
listener, err = net.ListenMulticastUDP("udp", nil, addr) | ||
if err != nil { | ||
log.Fatal("could not connect to ", address) | ||
} | ||
err = listener.SetReadBuffer(MaxDatagramSize) | ||
if err != nil { | ||
log.Fatalln("could not set read buffer") | ||
} | ||
log.Printf("Listening on %s", address) | ||
return | ||
} | ||
|
||
// HandleIncomingMessages listens for data from a multicast connection and passes data to the consumer | ||
func HandleIncomingMessages(address string, consumer func([]byte)) { | ||
err, listener := OpenMulticastUdpConnection(address) | ||
if err != nil { | ||
log.Println("Could not connect to ", address) | ||
} | ||
|
||
for { | ||
data := make([]byte, MaxDatagramSize) | ||
n, _, err := listener.ReadFromUDP(data) | ||
if err != nil { | ||
log.Println("ReadFromUDP failed: ", err) | ||
break | ||
} | ||
|
||
consumer(data[:n]) | ||
} | ||
|
||
err = listener.Close() | ||
if err != nil { | ||
log.Println("Could not close referee multicast connection") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package board | ||
|
||
import ( | ||
"fmt" | ||
"github.com/RoboCup-SSL/ssl-game-controller/pkg/refproto" | ||
"github.com/golang/protobuf/proto" | ||
"github.com/gorilla/websocket" | ||
"log" | ||
"net/http" | ||
"time" | ||
) | ||
|
||
// Board contains the state of this referee board | ||
type Board struct { | ||
cfg RefereeConfig | ||
referee *refproto.Referee | ||
} | ||
|
||
// NewBoard creates a new referee board | ||
func NewBoard(cfg RefereeConfig) Board { | ||
return Board{cfg: cfg} | ||
} | ||
|
||
// HandleIncomingMessages listens for new messages and stores the latest ones | ||
func (b *Board) HandleIncomingMessages() { | ||
HandleIncomingMessages(b.cfg.ConnectionConfig.MulticastAddress, b.handlingMessage) | ||
} | ||
|
||
func (b *Board) handlingMessage(data []byte) { | ||
message := new(refproto.Referee) | ||
err := proto.Unmarshal(data, message) | ||
if err != nil { | ||
log.Print("Could not parse referee message: ", err) | ||
} else { | ||
b.referee = message | ||
} | ||
} | ||
|
||
// SendToWebSocket sends latest data to the given websocket | ||
func (b *Board) SendToWebSocket(conn *websocket.Conn) { | ||
for { | ||
if b.referee != nil { | ||
data, err := proto.Marshal(b.referee) | ||
if err != nil { | ||
fmt.Println("Marshal error:", err) | ||
} | ||
if err := conn.WriteMessage(websocket.BinaryMessage, data); err != nil { | ||
log.Println("Could not write to referee websocket: ", err) | ||
return | ||
} | ||
} | ||
|
||
time.Sleep(b.cfg.SendingInterval) | ||
} | ||
} | ||
|
||
// WsHandler handles referee websocket connections | ||
func (b *Board) WsHandler(w http.ResponseWriter, r *http.Request) { | ||
WsHandler(w, r, b.SendToWebSocket) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package board | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/pkg/errors" | ||
"gopkg.in/yaml.v2" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"path/filepath" | ||
"time" | ||
) | ||
|
||
// ConnectionConfig contains parameters for multicast -> websocket connections | ||
type ConnectionConfig struct { | ||
SubscribePath string `yaml:"SubscribePath"` | ||
SendingInterval time.Duration `yaml:"SendingInterval"` | ||
MulticastAddress string `yaml:"MulticastAddress"` | ||
} | ||
|
||
// RefereeConfig contains referee specific connection parameters | ||
type RefereeConfig struct { | ||
ConnectionConfig `yaml:"Connection"` | ||
} | ||
|
||
// Config is the root config containing all configs for the server | ||
type Config struct { | ||
ListenAddress string `yaml:"ListenAddress"` | ||
RefereeConnection RefereeConfig `yaml:"RefereeConfig"` | ||
} | ||
|
||
// String converts the config to a string | ||
func (c Config) String() string { | ||
str, err := json.Marshal(c) | ||
if err != nil { | ||
return err.Error() | ||
} | ||
return string(str) | ||
} | ||
|
||
// ReadConfig reads the server config from a yaml file | ||
func ReadConfig(fileName string) (config Config, err error) { | ||
config = DefaultConfig() | ||
f, err := os.Open(fileName) | ||
if err != nil { | ||
return | ||
} | ||
d, err := ioutil.ReadAll(f) | ||
if err != nil { | ||
log.Fatalln("Could not read config file: ", err) | ||
} | ||
err = yaml.Unmarshal(d, &config) | ||
if err != nil { | ||
log.Fatalln("Could not unmarshal config file: ", err) | ||
} | ||
return | ||
} | ||
|
||
// WriteTo writes the config to the specified file | ||
func (c *Config) WriteTo(fileName string) (err error) { | ||
b, err := yaml.Marshal(c) | ||
if err != nil { | ||
err = errors.Wrapf(err, "Could not marshal config %v", c) | ||
return | ||
} | ||
err = os.MkdirAll(filepath.Dir(fileName), 0755) | ||
if err != nil { | ||
err = errors.Wrapf(err, "Could not create directly for config file: %v", fileName) | ||
return | ||
} | ||
err = ioutil.WriteFile(fileName, b, 0600) | ||
return | ||
} | ||
|
||
// DefaultConfig creates a config instance filled with default values | ||
func DefaultConfig() Config { | ||
return Config{ | ||
ListenAddress: ":8082", | ||
RefereeConnection: RefereeConfig{ | ||
ConnectionConfig: ConnectionConfig{ | ||
MulticastAddress: "224.5.23.1:10003", | ||
SendingInterval: time.Millisecond * 100, | ||
SubscribePath: "/api/referee", | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package board | ||
|
||
import ( | ||
"github.com/gorilla/websocket" | ||
"log" | ||
"net/http" | ||
) | ||
|
||
var upgrader = websocket.Upgrader{ | ||
ReadBufferSize: 1024, | ||
WriteBufferSize: 1024, | ||
CheckOrigin: func(*http.Request) bool { return true }, | ||
} | ||
|
||
// WsHandler converts the request into a websocket connection and passes it to the consumer | ||
func WsHandler(w http.ResponseWriter, r *http.Request, consumer func(conn *websocket.Conn)) { | ||
conn, err := upgrader.Upgrade(w, r, nil) | ||
if err != nil { | ||
log.Println(err) | ||
return | ||
} | ||
|
||
log.Println("Client connected") | ||
consumer(conn) | ||
log.Println("Client disconnected") | ||
|
||
err = conn.Close() | ||
if err != nil { | ||
log.Println("Could not close connection") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters