Skip to content

Commit d2c9fe7

Browse files
committed
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+
}

0 commit comments

Comments
 (0)