From 1130ea86cd477959efa06606125671347b944328 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 12 Nov 2015 12:53:20 +0100 Subject: [PATCH 1/2] Add bufferflow timedraw encodes data in base64 so it needs to be decoded on the other side --- bufferflow.go | 2 +- bufferflow_timedraw.go | 102 +++++++++++++++++++++++++++++++++++++++++ serialport.go | 7 +++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 bufferflow_timedraw.go diff --git a/bufferflow.go b/bufferflow.go index ff5bcf1b7..42ee9e9b4 100644 --- a/bufferflow.go +++ b/bufferflow.go @@ -5,7 +5,7 @@ import ( //"time" ) -var availableBufferAlgorithms = []string{"default", "timed"} +var availableBufferAlgorithms = []string{"default", "timed", "timedraw"} type BufferMsg struct { Cmd string diff --git a/bufferflow_timedraw.go b/bufferflow_timedraw.go new file mode 100644 index 000000000..27de6da48 --- /dev/null +++ b/bufferflow_timedraw.go @@ -0,0 +1,102 @@ +package main + +import ( + "encoding/json" + "time" + + log "github.com/Sirupsen/logrus" +) + +type BufferflowTimedRaw struct { + Name string + Port string + Output chan []byte + Input chan string + ticker *time.Ticker +} + +var ( + bufferedOutputRaw []byte +) + +func (b *BufferflowTimedRaw) Init() { + log.Println("Initting timed buffer flow (output once every 16ms)") + + go func() { + for data := range b.Input { + bufferedOutputRaw = append(bufferedOutputRaw, []byte(data)...) + } + }() + + go func() { + b.ticker = time.NewTicker(16 * time.Millisecond) + for _ = range b.ticker.C { + if len(bufferedOutputRaw) != 0 { + m := SpPortMessageRaw{bufferedOutputRaw} + buf, _ := json.Marshal(m) + // data is now encoded in base64 format + // need a decoder on the other side + b.Output <- []byte(buf) + bufferedOutputRaw = nil + } + } + }() + +} + +func (b *BufferflowTimedRaw) BlockUntilReady(cmd string, id string) (bool, bool) { + //log.Printf("BlockUntilReady() start\n") + return true, false +} + +func (b *BufferflowTimedRaw) OnIncomingData(data string) { + b.Input <- data +} + +// Clean out b.sem so it can truly block +func (b *BufferflowTimedRaw) ClearOutSemaphore() { +} + +func (b *BufferflowTimedRaw) BreakApartCommands(cmd string) []string { + return []string{cmd} +} + +func (b *BufferflowTimedRaw) Pause() { + return +} + +func (b *BufferflowTimedRaw) Unpause() { + return +} + +func (b *BufferflowTimedRaw) SeeIfSpecificCommandsShouldSkipBuffer(cmd string) bool { + return false +} + +func (b *BufferflowTimedRaw) SeeIfSpecificCommandsShouldPauseBuffer(cmd string) bool { + return false +} + +func (b *BufferflowTimedRaw) SeeIfSpecificCommandsShouldUnpauseBuffer(cmd string) bool { + return false +} + +func (b *BufferflowTimedRaw) SeeIfSpecificCommandsShouldWipeBuffer(cmd string) bool { + return false +} + +func (b *BufferflowTimedRaw) SeeIfSpecificCommandsReturnNoResponse(cmd string) bool { + return false +} + +func (b *BufferflowTimedRaw) ReleaseLock() { +} + +func (b *BufferflowTimedRaw) IsBufferGloballySendingBackIncomingData() bool { + return true +} + +func (b *BufferflowTimedRaw) Close() { + b.ticker.Stop() + close(b.Input) +} diff --git a/serialport.go b/serialport.go index 9aafcfbc9..b578603e9 100755 --- a/serialport.go +++ b/serialport.go @@ -88,6 +88,11 @@ type SpPortMessage struct { D string // the data, i.e. G0 X0 Y0 } +type SpPortMessageRaw struct { + // P string // the port, i.e. com22 + D []byte // the data, i.e. G0 X0 Y0 +} + func (p *serport) reader() { //var buf bytes.Buffer @@ -344,6 +349,8 @@ func spHandlerOpen(portname string, baud int, buftype string, isSecondary bool) if buftype == "timed" { bw = &BufferflowTimed{Name: "timed", Port: portname, Output: h.broadcastSys, Input: make(chan string)} + } else if buftype == "timedraw" { + bw = &BufferflowTimedRaw{Name: "timedraw", Port: portname, Output: h.broadcastSys, Input: make(chan string)} } else { bw = &BufferflowDefault{Port: portname} } From 6c1c6fa1712ee55c16f9949a0870f9f17d2c5acd Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 12 Nov 2015 14:59:43 +0100 Subject: [PATCH 2/2] add sendjsonraw command usage: sendjsonraw { "P": "/dev/ttyACM0", "Data": [ { "D": "Zg==" } ] } D field contains base64 encoded data --- hub.go | 4 +++ main.go | 4 +-- serial.go | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/hub.go b/hub.go index b03ec0a75..8d17c3ad3 100755 --- a/hub.go +++ b/hub.go @@ -171,6 +171,10 @@ func checkCmd(m []byte) { // kill the running process (assumes singleton for now) go spHandlerProgramKill() + } else if strings.HasPrefix(sl, "sendjsonraw") { + // will catch sendjsonraw + go spWriteJsonRaw(s) + } else if strings.HasPrefix(sl, "sendjson") { // will catch sendjson go spWriteJson(s) diff --git a/main.go b/main.go index 9cc38346d..3ef4fcca8 100755 --- a/main.go +++ b/main.go @@ -334,8 +334,8 @@ const homeTemplateHtml = ` return false; } socket.emit("command", msg.val()); - if (msg.val().indexOf("log off") != -1) {only_log = true;} - if (msg.val().indexOf("log on") != -1) {only_log = false;} + if (msg.val().indexOf("log off") != -1) {only_log = true} + if (msg.val().indexOf("log on") != -1) {only_log = false} msg.val(""); return false }); diff --git a/serial.go b/serial.go index c111ee016..721675e18 100755 --- a/serial.go +++ b/serial.go @@ -26,12 +26,24 @@ type writeRequestJson struct { Data []writeRequestJsonData } +type writeRequestJsonRaw struct { + p *serport + P string + Data []writeRequestJsonDataRaw +} + type writeRequestJsonData struct { D string Id string Buf string } +type writeRequestJsonDataRaw struct { + D []byte + Id string + Buf string +} + type qReportJson struct { Cmd string QCnt int @@ -73,7 +85,8 @@ type serialhub struct { unregister chan *serport // regexp for json trimming - reJsonTrim *regexp.Regexp + reJsonTrim *regexp.Regexp + reJsonRawTrim *regexp.Regexp } type SpPortList struct { @@ -103,12 +116,13 @@ var NetworkPorts SpPortList var sh = serialhub{ //write: make(chan *serport, chan []byte), - write: make(chan writeRequest), - writeJson: make(chan writeRequestJson), - register: make(chan *serport), - unregister: make(chan *serport), - ports: make(map[*serport]bool), - reJsonTrim: regexp.MustCompile("sendjson"), + write: make(chan writeRequest), + writeJson: make(chan writeRequestJson), + register: make(chan *serport), + unregister: make(chan *serport), + ports: make(map[*serport]bool), + reJsonTrim: regexp.MustCompile("sendjson"), + reJsonRawTrim: regexp.MustCompile("sendjsonraw"), } func (sh *serialhub) run() { @@ -615,6 +629,64 @@ func spWriteJson(arg string) { sh.writeJson <- m } +func spWriteJsonRaw(arg string) { + + log.Printf("spWriteJson. arg:%v\n", arg) + + // remove sendjson string + arg = sh.reJsonRawTrim.ReplaceAllString(arg, "") + //log.Printf("string we're going to parse:%v\n", arg) + + // this is a structured command now for sending in serial commands multiple at a time + // with an ID so we can send back the ID when the command is done + var m writeRequestJsonRaw + /* + m.P = "COM22" + var data writeRequestJsonData + data.Id = "234" + str := "yeah yeah" + data.D = str //[]byte(str) //[]byte(string("blah blah")) + m.Data = append(m.Data, data) + //m.Data = append(m.Data, data) + bm, err2 := json.Marshal(m) + if err2 == nil { + log.Printf("Test json serialize:%v\n", string(bm)) + } + */ + + err := json.Unmarshal([]byte(arg), &m) + + if err != nil { + log.Printf("Problem decoding json. giving up. json:%v, err:%v\n", arg, err) + spErr(fmt.Sprintf("Problem decoding json. giving up. json:%v, err:%v", arg, err)) + return + } + + // see if we have this port open + portname := m.P + myport, isFound := findPortByName(portname) + + if !isFound { + // we couldn't find the port, so send err + spErr("We could not find the serial port " + portname + " that you were trying to write to.") + return + } + + // we found our port + m.p = myport + + var mr writeRequestJson + + mr.p = m.p + mr.P = m.P + var data writeRequestJsonData + data.D = string(m.Data[0].D) + mr.Data = append(mr.Data, data) + + // send it to the writeJson channel + sh.writeJson <- mr +} + func spWrite(arg string) { // we will get a string of comXX asdf asdf asdf log.Println("Inside spWrite arg: " + arg)