Skip to content

Commit d2c9fe7

Browse files
committedMar 23, 2014
First major checkin. Windows only working right now.
Ajax server working. List ports working. Serial send/receive working. Former-commit-id: 50b35315b4a4eb8805b272befbbe31890878e383
1 parent 2590934 commit d2c9fe7

13 files changed

+774
-0
lines changed
 

‎.project

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>sps</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>com.googlecode.goclipse.goBuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
</buildSpec>
14+
<natures>
15+
<nature>goclipse.goNature</nature>
16+
</natures>
17+
</projectDescription>

‎A_WebSocket_Example.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
This gist is the source code for http://gary.beagledreams.com/page/go-websocket-chat.html
2+
3+
Copyright (c) 2013 Gary Burd
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.
22+
23+

‎conn.go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package main
2+
3+
import (
4+
"github.com/gorilla/websocket"
5+
"log"
6+
"net/http"
7+
)
8+
9+
type connection struct {
10+
// The websocket connection.
11+
ws *websocket.Conn
12+
13+
// Buffered channel of outbound messages.
14+
send chan []byte
15+
}
16+
17+
func (c *connection) reader() {
18+
for {
19+
_, message, err := c.ws.ReadMessage()
20+
if err != nil {
21+
break
22+
}
23+
24+
h.broadcast <- message
25+
}
26+
c.ws.Close()
27+
}
28+
29+
func (c *connection) writer() {
30+
for message := range c.send {
31+
err := c.ws.WriteMessage(websocket.TextMessage, message)
32+
if err != nil {
33+
break
34+
}
35+
}
36+
c.ws.Close()
37+
}
38+
39+
func wsHandler(w http.ResponseWriter, r *http.Request) {
40+
log.Print("Started a new websocket handler")
41+
ws, err := websocket.Upgrade(w, r, nil, 1024, 1024)
42+
if _, ok := err.(websocket.HandshakeError); ok {
43+
http.Error(w, "Not a websocket handshake", 400)
44+
return
45+
} else if err != nil {
46+
return
47+
}
48+
c := &connection{send: make(chan []byte, 256), ws: ws}
49+
h.register <- c
50+
defer func() { h.unregister <- c }()
51+
go c.writer()
52+
c.reader()
53+
}

‎dummy.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"time"
6+
)
7+
8+
type dummy struct {
9+
//myvar mytype string
10+
}
11+
12+
var d = dummy{
13+
//myvar: make(mytype string),
14+
}
15+
16+
func (d *dummy) run() {
17+
for {
18+
//h.broadcast <- message
19+
log.Print("dummy data")
20+
h.broadcast <- []byte("dummy data")
21+
time.Sleep(15000 * time.Millisecond)
22+
}
23+
}

‎home.html

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<html>
2+
<head>
3+
<title>Serial Port Example</title>
4+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
5+
<script type="text/javascript">
6+
$(function() {
7+
8+
var conn;
9+
var msg = $("#msg");
10+
var log = $("#log");
11+
12+
function appendLog(msg) {
13+
var d = log[0]
14+
var doScroll = d.scrollTop == d.scrollHeight - d.clientHeight;
15+
msg.appendTo(log)
16+
if (doScroll) {
17+
d.scrollTop = d.scrollHeight - d.clientHeight;
18+
}
19+
}
20+
21+
$("#form").submit(function() {
22+
if (!conn) {
23+
return false;
24+
}
25+
if (!msg.val()) {
26+
return false;
27+
}
28+
conn.send(msg.val());
29+
msg.val("");
30+
return false
31+
});
32+
33+
if (window["WebSocket"]) {
34+
conn = new WebSocket("ws://{{$}}/ws");
35+
conn.onclose = function(evt) {
36+
appendLog($("<div><b>Connection closed.</b></div>"))
37+
}
38+
conn.onmessage = function(evt) {
39+
appendLog($("<div/>").text(evt.data))
40+
}
41+
} else {
42+
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"))
43+
}
44+
});
45+
</script>
46+
<style type="text/css">
47+
html {
48+
overflow: hidden;
49+
}
50+
51+
body {
52+
overflow: hidden;
53+
padding: 0;
54+
margin: 0;
55+
width: 100%;
56+
height: 100%;
57+
background: gray;
58+
}
59+
60+
#log {
61+
background: white;
62+
margin: 0;
63+
padding: 0.5em 0.5em 0.5em 0.5em;
64+
position: absolute;
65+
top: 0.5em;
66+
left: 0.5em;
67+
right: 0.5em;
68+
bottom: 3em;
69+
overflow: auto;
70+
}
71+
72+
#form {
73+
padding: 0 0.5em 0 0.5em;
74+
margin: 0;
75+
position: absolute;
76+
bottom: 1em;
77+
left: 0px;
78+
width: 100%;
79+
overflow: hidden;
80+
}
81+
82+
</style>
83+
</head>
84+
<body>
85+
<div id="log"></div>
86+
<form id="form">
87+
<input type="submit" value="Send" />
88+
<input type="text" id="msg" size="64"/>
89+
</form>
90+
</body>
91+
</html>

‎hub.go

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"strconv"
6+
"strings"
7+
)
8+
9+
type hub struct {
10+
// Registered connections.
11+
connections map[*connection]bool
12+
13+
// Inbound messages from the connections.
14+
broadcast chan []byte
15+
16+
// Inbound messages from the system
17+
broadcastSys chan []byte
18+
19+
// Register requests from the connections.
20+
register chan *connection
21+
22+
// Unregister requests from connections.
23+
unregister chan *connection
24+
}
25+
26+
var h = hub{
27+
broadcast: make(chan []byte),
28+
broadcastSys: make(chan []byte),
29+
register: make(chan *connection),
30+
unregister: make(chan *connection),
31+
connections: make(map[*connection]bool),
32+
}
33+
34+
func (h *hub) run() {
35+
for {
36+
select {
37+
case c := <-h.register:
38+
h.connections[c] = true
39+
case c := <-h.unregister:
40+
delete(h.connections, c)
41+
close(c.send)
42+
case m := <-h.broadcast:
43+
log.Print("Got a broadcast")
44+
log.Print(m)
45+
//log.Print(h.broadcast)
46+
checkCmd(m)
47+
log.Print("-----")
48+
49+
for c := range h.connections {
50+
select {
51+
case c.send <- m:
52+
log.Print("did broadcast to ")
53+
log.Print(c.ws.RemoteAddr())
54+
//c.send <- []byte("hello world")
55+
default:
56+
delete(h.connections, c)
57+
close(c.send)
58+
go c.ws.Close()
59+
}
60+
}
61+
case m := <-h.broadcastSys:
62+
log.Print("Got a system broadcast")
63+
log.Print(m)
64+
log.Print("-----")
65+
66+
for c := range h.connections {
67+
select {
68+
case c.send <- m:
69+
log.Print("did broadcast to ")
70+
log.Print(c.ws.RemoteAddr())
71+
//c.send <- []byte("hello world")
72+
default:
73+
delete(h.connections, c)
74+
close(c.send)
75+
go c.ws.Close()
76+
}
77+
}
78+
}
79+
}
80+
}
81+
82+
func checkCmd(m []byte) {
83+
log.Print("Inside checkCmd")
84+
s := string(m[:])
85+
log.Print(s)
86+
87+
sl := strings.ToLower(s)
88+
89+
if strings.HasPrefix(sl, "open") {
90+
91+
args := strings.Split(s, " ")
92+
if len(args) < 3 {
93+
go spErr("You did not specify a port and baud rate in your open cmd")
94+
return
95+
}
96+
if len(args[1]) < 1 {
97+
go spErr("You did not specify a serial port")
98+
return
99+
}
100+
baud, err := strconv.Atoi(args[2])
101+
if err != nil {
102+
go spErr("Problem converting baud rate " + args[2])
103+
return
104+
}
105+
go spHandlerOpen(args[1], baud)
106+
107+
} else if strings.HasPrefix(sl, "close") {
108+
109+
args := strings.Split(s, " ")
110+
go spClose(args[1])
111+
112+
} else if strings.HasPrefix(sl, "send ") {
113+
114+
//args := strings.Split(s, "send ")
115+
go spWrite(s)
116+
117+
} else if s == "list" {
118+
go spList()
119+
//go getListViaWmiPnpEntity()
120+
}
121+
122+
log.Print("Done with checkCmd")
123+
}

‎main.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"go/build"
6+
"log"
7+
"net/http"
8+
"path/filepath"
9+
"text/template"
10+
)
11+
12+
var (
13+
addr = flag.String("addr", ":8989", "http service address")
14+
assets = flag.String("assets", defaultAssetPath(), "path to assets")
15+
homeTempl *template.Template
16+
)
17+
18+
func defaultAssetPath() string {
19+
//p, err := build.Default.Import("gary.burd.info/go-websocket-chat", "", build.FindOnly)
20+
p, err := build.Default.Import("github.com/johnlauer/serial-port-json-server", "", build.FindOnly)
21+
if err != nil {
22+
return "."
23+
}
24+
return p.Dir
25+
}
26+
27+
func homeHandler(c http.ResponseWriter, req *http.Request) {
28+
homeTempl.Execute(c, req.Host)
29+
}
30+
31+
func main() {
32+
//getList()
33+
flag.Parse()
34+
f := flag.Lookup("addr")
35+
log.Print("Started server and websocket on localhost" + f.Value.String())
36+
homeTempl = template.Must(template.ParseFiles(filepath.Join(*assets, "home.html")))
37+
38+
// launch the hub routine which is the singleton for the websocket server
39+
go h.run()
40+
// launch our serial port routine
41+
go sh.run()
42+
// launch our dummy data routine
43+
//go d.run()
44+
45+
http.HandleFunc("/", homeHandler)
46+
http.HandleFunc("/ws", wsHandler)
47+
if err := http.ListenAndServe(*addr, nil); err != nil {
48+
log.Fatal("ListenAndServe:", err)
49+
}
50+
}

‎main.go.old

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package main
2+
3+
import (
4+
"github.com/tarm/goserial"
5+
"log"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
"code.google.com/p/go.net/websocket"
10+
)
11+
12+
// Echo the data received on the WebSocket.
13+
func EchoServer(ws *websocket.Conn) {
14+
io.Copy(ws, ws)
15+
io.
16+
}
17+
18+
// This example demonstrates a trivial echo server.
19+
func ExampleHandler() {
20+
http.Handle("/echo", websocket.Handler(EchoServer))
21+
err := http.ListenAndServe(":12345", nil)
22+
if err != nil {
23+
panic("ListenAndServe: " + err.Error())
24+
}
25+
}
26+
27+
func wsHandler(ws *websocket.Conn) {
28+
var in []byte
29+
err := websocket.Message.Receive(ws, &in);
30+
if err != nil {
31+
log.Fatal(err)
32+
}
33+
fmt.Printf("Received: %s\n", string(in))
34+
websocket.Message.Send(ws, in)
35+
}
36+
37+
func rootHandler(w http.ResponseWriter, r *http.Request) {
38+
//url := r.URL.Path[1:]
39+
//fmt.Fprintf(w, "Hi there, I love %s!", url)
40+
fmt.Fprintf(w, "<script>ws = new WebSocket(\"ws://localhost:8080/echo\");\n" +
41+
"ws.onmessage = function(e) {\n" +
42+
"console.log(\"websock: \" + e.data);\n" +
43+
"};\n" +
44+
"ws.send(\"hello\");\n" +
45+
"</script>You should now be connected to our websocket.")
46+
}
47+
48+
func main() {
49+
50+
fmt.Println("Starting web server on localhost:8080 and websocket server: ")
51+
52+
//ExampleHandler()
53+
http.Handle("/echo", websocket.Handler(wsHandler))
54+
http.HandleFunc("/", rootHandler)
55+
http.ListenAndServe(":8080", nil)
56+
57+
c := &serial.Config{Name: "COM22", Baud: 115200}
58+
s, err := serial.OpenPort(c)
59+
if err != nil {
60+
log.Fatal(err)
61+
}
62+
63+
n, err := s.Write([]byte("?\n"))
64+
if err != nil {
65+
log.Fatal(err)
66+
}
67+
68+
//buf := make([]byte, 128)
69+
buf := make([]byte, 2048)
70+
n, err = s.Read(buf)
71+
for (n > 0) {
72+
if err != nil {
73+
log.Fatal(err)
74+
n = 0; // to break for loop
75+
}
76+
//log.Print
77+
//log.Printf("%q", buf[:n])
78+
fmt.Printf("%s", buf[:n])
79+
n = 0
80+
n, err = s.Read(buf)
81+
}
82+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cd57584c8bf3137abc9f8681e9f06ec752f77089

‎serial.go

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"strings"
6+
)
7+
8+
type writeRequest struct {
9+
p *serport
10+
d []byte
11+
}
12+
13+
type serialhub struct {
14+
// Opened serial ports.
15+
ports map[*serport]bool
16+
17+
//open chan *io.ReadWriteCloser
18+
//write chan *serport, chan []byte
19+
write chan writeRequest
20+
//read chan []byte
21+
22+
// Register requests from the connections.
23+
register chan *serport
24+
25+
// Unregister requests from connections.
26+
unregister chan *serport
27+
}
28+
29+
var sh = serialhub{
30+
//write: make(chan *serport, chan []byte),
31+
write: make(chan writeRequest),
32+
register: make(chan *serport),
33+
unregister: make(chan *serport),
34+
ports: make(map[*serport]bool),
35+
}
36+
37+
func (sh *serialhub) run() {
38+
39+
log.Print("Inside run of serialhub")
40+
//s := ser.open()
41+
//ser.s := s
42+
//ser.write(s, []byte("hello serial data"))
43+
for {
44+
select {
45+
case p := <-sh.register:
46+
log.Print("Registering a port ")
47+
log.Print(p)
48+
sh.ports[p] = true
49+
case p := <-sh.unregister:
50+
delete(sh.ports, p)
51+
close(p.send)
52+
case wr := <-sh.write:
53+
log.Print("Got a write to a port")
54+
log.Print("Port is ")
55+
log.Print(wr.p)
56+
log.Print("Data is ")
57+
log.Print(wr.d)
58+
log.Print("Data as string:" + string(wr.d))
59+
log.Print("-----")
60+
select {
61+
case wr.p.send <- wr.d:
62+
log.Print("Did write to serport")
63+
default:
64+
delete(sh.ports, wr.p)
65+
close(wr.p.send)
66+
//wr.p.port.Close()
67+
//go wr.p.port.Close()
68+
}
69+
}
70+
}
71+
}
72+
73+
func spList() {
74+
ls := "{serialports:[\n"
75+
list, _ := getList()
76+
for _, item := range list {
77+
ls += "{name:'" + item.Name + "', friendly:'" + item.FriendlyName + "'}\n"
78+
}
79+
ls += "]}\n"
80+
h.broadcastSys <- []byte(ls)
81+
}
82+
83+
func spErr(err string) {
84+
log.Println("Sending err back: ", err)
85+
h.broadcastSys <- []byte(err)
86+
}
87+
88+
func spClose(portname string) {
89+
// look up the registered port by name
90+
// then call the close method inside serialport
91+
// that should cause an unregister channel call back
92+
// to myself
93+
94+
myport, isFound := findPortByName(portname)
95+
96+
if isFound {
97+
// we found our port
98+
spHandlerClose(myport)
99+
} else {
100+
// we couldn't find the port, so send err
101+
spErr("We could not find the serial port " + portname + " that you were trying to close.")
102+
}
103+
}
104+
105+
func spWrite(arg string) {
106+
// we will get a string of comXX asdf asdf asdf
107+
log.Println("Inside spWrite arg: " + arg)
108+
arg = strings.TrimPrefix(arg, " ")
109+
log.Println("arg after trim: " + arg)
110+
args := strings.SplitN(arg, " ", 3)
111+
if len(args) != 3 {
112+
errstr := "Could not parse send command: " + arg
113+
log.Println(errstr)
114+
spErr(errstr)
115+
return
116+
}
117+
portname := strings.Trim(args[1], " ")
118+
log.Println("The port to write to is:" + portname + "---")
119+
log.Println("The data is:" + args[2])
120+
121+
// see if we have this port open
122+
myport, isFound := findPortByName(portname)
123+
124+
if !isFound {
125+
// we couldn't find the port, so send err
126+
spErr("We could not find the serial port " + portname + " that you were trying to write to.")
127+
return
128+
}
129+
130+
// we found our port
131+
// create our write request
132+
var wr writeRequest
133+
wr.p = myport
134+
wr.d = []byte(args[2] + "\n")
135+
136+
// send it to the write channel
137+
sh.write <- wr
138+
139+
}
140+
141+
func findPortByName(portname string) (*serport, bool) {
142+
portnamel := strings.ToLower(portname)
143+
for port := range sh.ports {
144+
if strings.ToLower(port.portConf.Name) == portnamel {
145+
// we found our port
146+
//spHandlerClose(port)
147+
return port, true
148+
}
149+
}
150+
return nil, false
151+
}

‎seriallist.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package main
2+
3+
import (
4+
"os"
5+
)
6+
7+
type OsSerialPort struct {
8+
Name string
9+
FriendlyName string
10+
}
11+
12+
func GetList() ([]OsSerialPort, os.SyscallError) {
13+
return getList()
14+
}

‎seriallist_windows.go.REMOVED.git-id

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
d5e327a410c6763d6f0302cfe499d2f0fd4257f1

‎serialport.go

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"github.com/tarm/goserial"
6+
"io"
7+
"log"
8+
"strconv"
9+
)
10+
11+
type serport struct {
12+
// The serial port connection.
13+
portConf *serial.Config
14+
portIo io.ReadWriteCloser
15+
16+
// Keep track of whether we're being actively closed
17+
// just so we don't show scary error messages
18+
isClosing bool
19+
20+
// Buffered channel of outbound messages.
21+
send chan []byte
22+
}
23+
24+
func (p *serport) reader() {
25+
//var buf bytes.Buffer
26+
for {
27+
ch := make([]byte, 1024)
28+
n, err := p.portIo.Read(ch)
29+
30+
// read can return legitimate bytes as well as an error
31+
// so process the bytes if n > 0
32+
if n > 0 {
33+
log.Print("Read " + strconv.Itoa(n) + " bytes ch: " + string(ch))
34+
h.broadcastSys <- []byte("{p: '" + p.portConf.Name + "', d: '" + string(ch[:n]) + "'}\n")
35+
}
36+
37+
if p.isClosing {
38+
strmsg := "Shutting down reader on " + p.portConf.Name
39+
log.Println(strmsg)
40+
h.broadcastSys <- []byte(strmsg)
41+
break
42+
}
43+
44+
if err == io.EOF || err == io.ErrUnexpectedEOF {
45+
// hit end of file
46+
log.Println("Hit end of file on serial port")
47+
}
48+
if err != nil {
49+
log.Println(err)
50+
h.broadcastSys <- []byte("Error reading on " + p.portConf.Name + " " +
51+
err.Error() + " Closing port.")
52+
break
53+
}
54+
55+
// loop thru and look for a newline
56+
/*
57+
for i := 0; i < n; i++ {
58+
// see if we hit a newline
59+
if ch[i] == '\n' {
60+
// we are done with the line
61+
h.broadcastSys <- buf.Bytes()
62+
buf.Reset()
63+
} else {
64+
// append to buffer
65+
buf.WriteString(string(ch[:n]))
66+
}
67+
}*/
68+
/*
69+
buf.WriteString(string(ch[:n]))
70+
log.Print(string(ch[:n]))
71+
if string(ch[:n]) == "\n" {
72+
h.broadcastSys <- buf.Bytes()
73+
buf.Reset()
74+
}
75+
*/
76+
}
77+
p.portIo.Close()
78+
}
79+
80+
func (p *serport) writer() {
81+
for data := range p.send {
82+
n2, err := p.portIo.Write(data)
83+
log.Print("Just wrote ")
84+
log.Print(n2)
85+
log.Print(" bytes to serial: ")
86+
log.Print(data)
87+
if err != nil {
88+
errstr := "Error writing to " + p.portConf.Name + " " + err.Error() + " Closing port."
89+
log.Fatal(errstr)
90+
h.broadcastSys <- []byte(errstr)
91+
break
92+
}
93+
}
94+
msgstr := "Shutting down writer on " + p.portConf.Name
95+
log.Println(msgstr)
96+
h.broadcastSys <- []byte(msgstr)
97+
p.portIo.Close()
98+
}
99+
100+
func spHandlerOpen(portname string, baud int) {
101+
102+
log.Print("Inside spHandler")
103+
104+
var out bytes.Buffer
105+
106+
out.WriteString("Opening serial port ")
107+
out.WriteString(portname)
108+
out.WriteString(" at ")
109+
out.WriteString(strconv.Itoa(baud))
110+
out.WriteString(" baud")
111+
log.Print(out.String())
112+
113+
//h.broadcast <- []byte("Opened a serial port bitches")
114+
h.broadcastSys <- out.Bytes()
115+
116+
conf := &serial.Config{Name: portname, Baud: baud}
117+
log.Print("Created config for port")
118+
log.Print(conf)
119+
120+
sp, err := serial.OpenPort(conf)
121+
log.Print("Just tried to open port")
122+
if err != nil {
123+
//log.Fatal(err)
124+
log.Print("Error opening port " + err.Error())
125+
h.broadcastSys <- []byte("Error opening port. " + err.Error())
126+
return
127+
}
128+
log.Print("Opened port successfully")
129+
p := &serport{send: make(chan []byte, 256), portConf: conf, portIo: sp}
130+
sh.register <- p
131+
defer func() { sh.unregister <- p }()
132+
go p.writer()
133+
p.reader()
134+
}
135+
136+
func spHandlerClose(p *serport) {
137+
p.isClosing = true
138+
// close the port
139+
p.portIo.Close()
140+
// unregister myself
141+
// we already have a deferred unregister in place from when
142+
// we opened. the only thing holding up that thread is the p.reader()
143+
// so if we close the reader we should get an exit
144+
h.broadcastSys <- []byte("Closing serial port " + p.portConf.Name)
145+
}

0 commit comments

Comments
 (0)
Please sign in to comment.