package MessageHandler import ( "fmt" "log" "net/http" "strconv" "strings" "sync" "github.com/gorilla/websocket" ) type SerialInteraction interface { ListComports() []string Connect(string) error Disconnect() Write([]byte) (int, error) Read([]byte) (int, error) GetPortPath() string } type MessageHandler struct { Serial SerialInteraction socket *websocket.Conn socketLock sync.Mutex } const ( VERSION = "1" ) func (mh *MessageHandler) WebsocketHandle(w http.ResponseWriter, r *http.Request, c *websocket.Conn) { for { mt, message, err := c.ReadMessage() if err != nil { log.Printf("read: %v", err) break } log.Printf("recv: %s", message) answer := mh.messageDispatcher(string(message)) mh.socketLock.Lock() err = c.WriteMessage(mt, []byte(answer)) mh.socketLock.Unlock() if err != nil { log.Printf("write: %v", err) break } } } // message format, ";" seperated message version;command;argc;args....? func (mh *MessageHandler) messageDispatcher(message string) string { messageParts := strings.Split(message, ";") if len(messageParts) < 3 { log.Printf("Message to Short, %v", message) return "" } switch messageParts[0] { case VERSION: break default: log.Printf("Unknow Version %v in Message %v", messageParts[0], message) return "" } switch messageParts[1] { case "listports": return mh.ListComports() case "connect": return mh.Connect(messageParts[4]) case "disconnect": return mh.Disconnect() case "write": return mh.Write(messageParts[4]) case "read": return mh.Read() default: log.Printf("unknow command %v", message) break } return "" } func (mh *MessageHandler) ListComports() string { ports := mh.Serial.ListComports() message := MessageBuilder("portlist", ports...) return message } func (mh *MessageHandler) Connect(portname string) string { err := mh.Serial.Connect(portname) message := "" if err != nil { message = MessageBuilder("error", "connection") } else { message = MessageBuilder("connected", "portname") } return message } func (mh *MessageHandler) Disconnect() string { mh.Serial.Disconnect() return MessageBuilder("disconnected") } func (mh *MessageHandler) Write(msg string) string { _, err := mh.Serial.Write([]byte(msg)) if err != nil { return MessageBuilder("write", fmt.Sprintf("write error %v", err)) } return MessageBuilder("write") } func (mh *MessageHandler) Read() string { buffer := make([]byte, 1024) _, err := mh.Serial.Read(buffer) if err != nil { return MessageBuilder("read", fmt.Sprintf("read error %v", err)) } return MessageBuilder("read", string(buffer)) } // version;command;argc;argv; // recv: 1;connect;1;/dev/ttyUSB0; // send: 1;connected;0; // no args can be used as a acc command // send: 1;connected;1;error: port not found; // recv: 1;discoonect;0; // send: 1;discoonect;0; // recv: 1;write;1;viele viele bunte bytes; // send: 1;write;0; // send: 1;write;1;error: port not connected; // send: 1:read:1;das hab ich gelesen junge; func MessageBuilder(command string, args ...string) string { return VERSION + ";" + command + ";" + strconv.Itoa(len(args)) + ";" + strings.Join(args, ";") }