-
Notifications
You must be signed in to change notification settings - Fork 271
gopcua in the browser
Frank Schröder edited this page Apr 9, 2019
·
3 revisions
This code is based on an older version of the library and will not work as described. We will leave it as a reference for someone who is interested. Feel free to update it to the current state of the library.
With the latest Go 1.11 you're able to compile Go code to WebAssembly. OPC UA is able to communicate via websockets. So why not use gopcua in the browser to decode/encode binary OPC UA messages directly in the browser?
Here is a very rough demo with a hard coded float value. Much of the code is taken from the Go WebAssembly wiki.
- You need a
server.go
to serve some static files from disk.
package main
import (
"flag"
"log"
"net/http"
)
var (
listen = flag.String("listen", ":7070", "listen address")
dir = flag.String("dir", ".", "directory to serve")
)
func main() {
flag.Parse()
log.Printf("listening on %q...", *listen)
log.Fatal(http.ListenAndServe(*listen, http.FileServer(http.Dir(*dir))))
}
- You need an
index.html
file to load wasm_exec.js and instantiate the WebAssembly code.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Go wasm</title>
</head>
<body>
<script src="wasm_exec.js"></script>
<script>
const go = new Go()
const awesome = () => {
// same data as in datatypes/float_test.go
const data = [0x64, 0x06, 0xa0, 0x40]
// decode is a global function created by main.go / lib.wasm
decode(data)
}
WebAssembly.instantiateStreaming(fetch("lib.wasm"), go.importObject).then(async result => {
await go.run(result.instance)
}).catch((err) => {
console.error(err)
})
</script>
<button onClick="awesome()" id="addButton">Add</button>
</body>
</html>
- Your Go code in
main.go
looks like this. This is the code that will be compiled to WebAssembly and run in the browser.
package main
import (
"fmt"
"log"
"syscall/js"
"github.com/wmnsk/gopcua/datatypes"
)
func decode(args []js.Value) {
data := args[0]
// convert incoming values into byte slice
b := make([]byte, data.Length())
for index := 0; index < data.Length(); index++ {
b[index] = byte(data.Index(index).Int())
}
// decode byte slice
s, err := datatypes.DecodeFloat(b)
if err != nil {
log.Println(err)
}
// prints 5.00078 as expected \o/
log.Println(s.Value)
}
func main() {
c := make(chan struct{}, 0)
// just to make sure everything is running
fmt.Println("hello world")
js.Global().Set("decode", js.NewCallback(decode))
<-c
}
- Compile
main.go
tolib.wasm
. I've created a littleMakefile
to make this easier.
.PHONY: wasm
wasm:
GOARCH=wasm GOOS=js go build -o lib.wasm main.go
Now go to http://localhost:7070 and click the button. You should see the result in the console.