forked from hybridgroup/gobot
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request hybridgroup#297 from caledhwa/platform-nats
Adding the initial NATS platform support
- Loading branch information
Showing
6 changed files
with
301 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
"github.com/hybridgroup/gobot" | ||
"github.com/hybridgroup/gobot/platforms/nats" | ||
) | ||
|
||
func main() { | ||
gbot := gobot.NewGobot() | ||
|
||
natsAdaptor := nats.NewNatsAdaptorWithAuth("nats", "localhost:4222", 1234) | ||
|
||
work := func() { | ||
natsAdaptor.On("hello", func(data []byte) { | ||
fmt.Println("hello") | ||
}) | ||
natsAdaptor.On("hola", func(data []byte) { | ||
fmt.Println("hola") | ||
}) | ||
data := []byte("o") | ||
gobot.Every(1*time.Second, func() { | ||
natsAdaptor.Publish("hello", data) | ||
}) | ||
gobot.Every(5*time.Second, func() { | ||
natsAdaptor.Publish("hola", data) | ||
}) | ||
} | ||
|
||
robot := gobot.NewRobot("natsBot", | ||
[]gobot.Connection{natsAdaptor}, | ||
work, | ||
) | ||
|
||
gbot.AddRobot(robot) | ||
|
||
gbot.Start() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# NATS | ||
|
||
NATS is a lightweight messaging protocol perfect for your IoT/Robotics projects. It operates over TCP, offers a great number of features but an incredibly simple Pub Sub style model of communicating broadcast messages. NATS is blazingly fast as it is written in Go. | ||
|
||
This repository contains the Gobot adaptor/drivers to connect to NATS servers. It uses the NATS Go Client available at https://github.com/nats-io/nats. The NATS project is maintained by Nats.io and sponsored by Apcera. Find more information on setting up a NATS server and its capability at http://nats.io/. | ||
|
||
The NATS messaging protocol (http://www.nats.io/documentation/internals/nats-protocol-demo/) is really easy to work with and can be practiced by setting up a NATS server using Go or Docker. For information on setting up a server using the source code, visit https://github.com/nats-io/gnatsd. For information on the Docker image up on Docker Hub, see https://hub.docker.com/_/nats/. Getting the server set up is very easy. The server itself is Golang, can be built for different architectures and installs in a small footprint. This is an excellent way to get communications going between your IoT and Robotics projects. | ||
|
||
## How to Install | ||
|
||
Install running: | ||
|
||
``` | ||
go get -d -u github.com/hybridgroup/gobot/... && go install github.com/hybridgroup/gobot/platforms/nats | ||
``` | ||
|
||
## How to Use | ||
|
||
Before running the example, make sure you have an NATS server running somewhere you can connect to | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
"github.com/hybridgroup/gobot" | ||
"github.com/hybridgroup/gobot/platforms/nats" | ||
) | ||
|
||
func main() { | ||
gbot := gobot.NewGobot() | ||
|
||
natsAdaptor := nats.NewNatsAdaptor("nats", "localhost:4222", 1234) | ||
|
||
work := func() { | ||
natsAdaptor.On("hello", func(data []byte) { | ||
fmt.Println("hello") | ||
}) | ||
natsAdaptor.On("hola", func(data []byte) { | ||
fmt.Println("hola") | ||
}) | ||
data := []byte("o") | ||
gobot.Every(1*time.Second, func() { | ||
natsAdaptor.Publish("hello", data) | ||
}) | ||
gobot.Every(5*time.Second, func() { | ||
natsAdaptor.Publish("hola", data) | ||
}) | ||
} | ||
|
||
robot := gobot.NewRobot("natsBot", | ||
[]gobot.Connection{natsAdaptor}, | ||
work, | ||
) | ||
|
||
gbot.AddRobot(robot) | ||
|
||
gbot.Start() | ||
} | ||
``` | ||
|
||
## Supported Features | ||
|
||
* Publish messages | ||
* Respond to incoming message events | ||
|
||
## Upcoming Features | ||
|
||
* Support for Username/password | ||
* Encoded messages (JSON) | ||
* Exposing more NATS Features (tls) | ||
* Simplified tests | ||
|
||
## Contributing | ||
|
||
For our contribution guidelines, please go to https://github.com/hybridgroup/gobot/blob/master/CONTRIBUTING.md | ||
|
||
## License | ||
|
||
Copyright (c) 2013-2016 The Hybrid Group. Licensed under the Apache 2.0 license. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
Package nats provides Gobot adaptor for the nats message service. | ||
Installing: | ||
go get github.com/hybridgroup/gobot/platforms/nats | ||
For further information refer to mqtt README: | ||
https://github.com/hybridgroup/gobot/blob/master/platforms/nats/README.md | ||
*/ | ||
package nats |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package nats | ||
|
||
import ( | ||
"github.com/nats-io/nats" | ||
) | ||
|
||
// NatsAdaptor is a configuration struct for interacting with a nats server. | ||
// Name is a logical name for the adaptor/nats server connection. | ||
// Host is in the form "localhost:4222" which is the hostname/ip and port of the nats server. | ||
// ClientID is a unique identifier integer that specifies the identity of the client. | ||
type NatsAdaptor struct { | ||
name string | ||
Host string | ||
clientID int | ||
username string | ||
password string | ||
client *nats.Conn | ||
} | ||
|
||
// NewNatsAdaptor populates a new NatsAdaptor. | ||
func NewNatsAdaptor(name string, host string, clientID int) *NatsAdaptor { | ||
return &NatsAdaptor{ | ||
name: name, | ||
Host: host, | ||
clientID: clientID, | ||
} | ||
} | ||
|
||
// NewNatsAdaptorWithAuth populates a NatsAdaptor including username and password. | ||
func NewNatsAdaptorWithAuth(name string, host string, clientID int, username string, password string) *NatsAdaptor { | ||
return &NatsAdaptor{ | ||
name: name, | ||
Host: host, | ||
clientID: clientID, | ||
username: username, | ||
password: password, | ||
} | ||
} | ||
|
||
// Name returns the logical client name. | ||
func (a *NatsAdaptor) Name() string { return a.name } | ||
|
||
// Connect makes a connection to the Nats server. | ||
func (a *NatsAdaptor) Connect() (errs []error) { | ||
|
||
auth := "" | ||
if a.username != "" && a.password != "" { | ||
auth = a.username + ":" + a.password + "@" | ||
} | ||
|
||
defaultURL := "nats://" + auth + a.Host | ||
|
||
var err error | ||
a.client, err = nats.Connect(defaultURL) | ||
if err != nil { | ||
return append(errs, err) | ||
} | ||
return | ||
} | ||
|
||
// Disconnect from the nats server. Returns an error if the client doesn't exist. | ||
func (a *NatsAdaptor) Disconnect() (err error) { | ||
if a.client != nil { | ||
a.client.Close() | ||
} | ||
return | ||
} | ||
|
||
// Finalize is simply a helper method for the disconnect. | ||
func (a *NatsAdaptor) Finalize() (errs []error) { | ||
a.Disconnect() | ||
return | ||
} | ||
|
||
// Publish sends a message with the particular topic to the nats server. | ||
func (a *NatsAdaptor) Publish(topic string, message []byte) bool { | ||
if a.client == nil { | ||
return false | ||
} | ||
a.client.Publish(topic, message) | ||
return true | ||
} | ||
|
||
// On is an event-handler style subscriber to a particular topic (named event). | ||
// Supply a handler function to use the bytes returned by the server. | ||
func (a *NatsAdaptor) On(event string, f func(s []byte)) bool { | ||
if a.client == nil { | ||
return false | ||
} | ||
a.client.Subscribe(event, func(msg *nats.Msg) { | ||
f(msg.Data) | ||
}) | ||
return true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package nats | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hybridgroup/gobot" | ||
"github.com/hybridgroup/gobot/gobottest" | ||
) | ||
|
||
var _ gobot.Adaptor = (*NatsAdaptor)(nil) | ||
|
||
func TestNatsAdaptorReturnsName(t *testing.T) { | ||
a := NewNatsAdaptor("Nats", "localhost:4222", 9999) | ||
gobottest.Assert(t, a.Name(), "Nats") | ||
} | ||
|
||
func TestNatsAdaptorPublishWhenConnected(t *testing.T) { | ||
a := NewNatsAdaptor("Nats", "localhost:4222", 9999) | ||
a.Connect() | ||
data := []byte("o") | ||
gobottest.Assert(t, a.Publish("test", data), true) | ||
} | ||
|
||
func TestNatsAdaptorOnWhenConnected(t *testing.T) { | ||
a := NewNatsAdaptor("Nats", "localhost:4222", 9999) | ||
a.Connect() | ||
gobottest.Assert(t, a.On("hola", func(data []byte) { | ||
fmt.Println("hola") | ||
}), true) | ||
} | ||
|
||
func TestNatsAdaptorPublishWhenConnectedWithAuth(t *testing.T) { | ||
a := NewNatsAdaptorWithAuth("Nats", "localhost:4222", 9999, "test", "testwd") | ||
a.Connect() | ||
data := []byte("o") | ||
gobottest.Assert(t, a.Publish("test", data), true) | ||
} | ||
|
||
func TestNatsAdaptorOnWhenConnectedWithAuth(t *testing.T) { | ||
a := NewNatsAdaptorWithAuth("Nats", "localhost:4222", 9999, "test", "testwd") | ||
a.Connect() | ||
gobottest.Assert(t, a.On("hola", func(data []byte) { | ||
fmt.Println("hola") | ||
}), true) | ||
} | ||
|
||
func TestNatsAdaptorConnect(t *testing.T) { | ||
a := NewNatsAdaptor("Nats", "localhost:9999", 9999) | ||
gobottest.Assert(t, a.Connect()[0].Error(), "nats: no servers available for connection") | ||
} | ||
|
||
func TestNatsAdaptorFinalize(t *testing.T) { | ||
a := NewNatsAdaptor("Nats", "localhost:9999", 9999) | ||
gobottest.Assert(t, len(a.Finalize()), 0) | ||
} | ||
|
||
func TestNatsAdaptorCannotPublishUnlessConnected(t *testing.T) { | ||
a := NewNatsAdaptor("Nats", "localhost:9999", 9999) | ||
data := []byte("o") | ||
gobottest.Assert(t, a.Publish("test", data), false) | ||
} | ||
|
||
func TestNatsAdaptorCannotOnUnlessConnected(t *testing.T) { | ||
a := NewNatsAdaptor("Nats", "localhost:9999", 9999) | ||
gobottest.Assert(t, a.On("hola", func(data []byte) { | ||
fmt.Println("hola") | ||
}), false) | ||
} |