diff --git a/README.md b/README.md index 44bef575..7ee21ddb 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,7 @@ Gobot has a extensible system for connecting to hardware devices. The following - [Leap Motion](https://www.leapmotion.com/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/leapmotion) - [MavLink](http://qgroundcontrol.org/mavlink/start) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/mavlink) - [MegaPi](http://www.makeblock.com/megapi) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/megapi) +- [Microbit](http://microbit.org/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/microbit) - [MQTT](http://mqtt.org/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/mqtt) - [NATS](http://nats.io/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/nats) - [Neurosky](http://neurosky.com/products-markets/eeg-biosensors/hardware/) <=> [Package](https://github.com/hybridgroup/gobot/tree/master/platforms/neurosky) diff --git a/examples/microbit_accelerometer.go b/examples/microbit_accelerometer.go new file mode 100644 index 00000000..4da0611b --- /dev/null +++ b/examples/microbit_accelerometer.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "os" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" + "gobot.io/x/gobot/platforms/microbit" +) + +func main() { + bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + ubit := microbit.NewAccelerometerDriver(bleAdaptor) + + work := func() { + ubit.On(microbit.Accelerometer, func(data interface{}) { + fmt.Println("Accelerometer", data) + }) + } + + robot := gobot.NewRobot("buttonBot", + []gobot.Connection{bleAdaptor}, + []gobot.Device{ubit}, + work, + ) + + robot.Start() +} diff --git a/examples/microbit_buttons.go b/examples/microbit_buttons.go new file mode 100644 index 00000000..53dc14c3 --- /dev/null +++ b/examples/microbit_buttons.go @@ -0,0 +1,33 @@ +package main + +import ( + "fmt" + "os" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" + "gobot.io/x/gobot/platforms/microbit" +) + +func main() { + bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + ubit := microbit.NewButtonDriver(bleAdaptor) + + work := func() { + ubit.On(microbit.ButtonA, func(data interface{}) { + fmt.Println("button A", data) + }) + + ubit.On(microbit.ButtonB, func(data interface{}) { + fmt.Println("button B", data) + }) + } + + robot := gobot.NewRobot("buttonBot", + []gobot.Connection{bleAdaptor}, + []gobot.Device{ubit}, + work, + ) + + robot.Start() +} diff --git a/examples/microbit_buttons_leds.go b/examples/microbit_buttons_leds.go new file mode 100644 index 00000000..d65bfccf --- /dev/null +++ b/examples/microbit_buttons_leds.go @@ -0,0 +1,43 @@ +package main + +import ( + "os" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" + "gobot.io/x/gobot/platforms/microbit" +) + +func main() { + bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + buttons := microbit.NewButtonDriver(bleAdaptor) + leds := microbit.NewLEDDriver(bleAdaptor) + + work := func() { + buttons.On(microbit.ButtonA, func(data interface{}) { + if data.([]byte)[0] == 1 { + leds.UpLeftArrow() + return + } + + leds.Blank() + }) + + buttons.On(microbit.ButtonB, func(data interface{}) { + if data.([]byte)[0] == 1 { + leds.UpRightArrow() + return + } + + leds.Blank() + }) + } + + robot := gobot.NewRobot("buttonBot", + []gobot.Connection{bleAdaptor}, + []gobot.Device{buttons, leds}, + work, + ) + + robot.Start() +} diff --git a/examples/microbit_led.go b/examples/microbit_led.go new file mode 100644 index 00000000..c0085509 --- /dev/null +++ b/examples/microbit_led.go @@ -0,0 +1,33 @@ +package main + +import ( + "os" + "time" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" + "gobot.io/x/gobot/platforms/microbit" +) + +func main() { + bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + ubit := microbit.NewLEDDriver(bleAdaptor) + + work := func() { + ubit.Blank() + gobot.After(1*time.Second, func() { + ubit.WriteText("Hello") + }) + gobot.After(7*time.Second, func() { + ubit.Smile() + }) + } + + robot := gobot.NewRobot("blinkBot", + []gobot.Connection{bleAdaptor}, + []gobot.Device{ubit}, + work, + ) + + robot.Start() +} diff --git a/examples/microbit_magnetometer.go b/examples/microbit_magnetometer.go new file mode 100644 index 00000000..21f7e758 --- /dev/null +++ b/examples/microbit_magnetometer.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "os" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" + "gobot.io/x/gobot/platforms/microbit" +) + +func main() { + bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + ubit := microbit.NewMagnetometerDriver(bleAdaptor) + + work := func() { + ubit.On(microbit.Magnetometer, func(data interface{}) { + fmt.Println("Magnetometer", data) + }) + } + + robot := gobot.NewRobot("magnetoBot", + []gobot.Connection{bleAdaptor}, + []gobot.Device{ubit}, + work, + ) + + robot.Start() +} diff --git a/examples/microbit_temperature.go b/examples/microbit_temperature.go new file mode 100644 index 00000000..a481b266 --- /dev/null +++ b/examples/microbit_temperature.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "os" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" + "gobot.io/x/gobot/platforms/microbit" +) + +func main() { + bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + ubit := microbit.NewTemperatureDriver(bleAdaptor) + + work := func() { + ubit.On(microbit.Temperature, func(data interface{}) { + fmt.Println("Temperature", data) + }) + } + + robot := gobot.NewRobot("thermoBot", + []gobot.Connection{bleAdaptor}, + []gobot.Device{ubit}, + work, + ) + + robot.Start() +} diff --git a/platforms/microbit/LICENSE b/platforms/microbit/LICENSE new file mode 100644 index 00000000..11e7f03c --- /dev/null +++ b/platforms/microbit/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2014-2017 The Hybrid Group + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/platforms/microbit/README.md b/platforms/microbit/README.md new file mode 100644 index 00000000..2163299c --- /dev/null +++ b/platforms/microbit/README.md @@ -0,0 +1,91 @@ +# Microbit + +The [Microbit](http://microbit.org/) is a tiny computer with built-in Bluetooth LE aka Bluetooth 4.0. + +## How to Install +``` +go get -d -u gobot.io/x/gobot/... && go install gobot.io/x/gobot/platforms/microbit +``` + +You must install the Microbit firmware from [@sandeepmistry] located at [https://github.com/sandeepmistry/node-bbc-microbit](https://github.com/sandeepmistry/node-bbc-microbit) to use the Microbit with Gobot. This firmware is based on the micro:bit template, but with a few changes. + +You can either use the [Gort](https://gort.io) command line tool's `gort microbit` commands, or follow the firmware installation instructions at [https://github.com/sandeepmistry/node-bbc-microbit#flashing-microbit-firmware](https://github.com/sandeepmistry/node-bbc-microbit#flashing-microbit-firmware). + +The source code for the firmware is located at [https://github.com/sandeepmistry/node-bbc-microbit/files/546610/node-bbc-microbit_zip_nrf51_microbit.zip](https://github.com/sandeepmistry/node-bbc-microbit/files/546610/node-bbc-microbit_zip_nrf51_microbit.zip) however you do not need this source code to install the firmware using the installation instructions. + +## How to Use + +The Gobot platform for the Microbit includes several different drivers, each one corresponding to a different capability: + +- AccelerometerDriver +- ButtonDriver +- LEDDriver +- MagnetometerDriver +- TemperatureDriver + +The following example uses the LEDDriver: + +```go +package main + +import ( + "os" + "time" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" + "gobot.io/x/gobot/platforms/microbit" +) + +func main() { + bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + ubit := microbit.NewLEDDriver(bleAdaptor) + + work := func() { + ubit.Blank() + gobot.After(1*time.Second, func() { + ubit.WriteText("Hello") + }) + gobot.After(7*time.Second, func() { + ubit.Smile() + }) + } + + robot := gobot.NewRobot("blinkBot", + []gobot.Connection{bleAdaptor}, + []gobot.Device{ubit}, + work, + ) + + robot.Start() +} +``` + +## How to Connect + +The Microbit is a Bluetooth LE device. + +You need to know the BLE ID of the Microbit that you want to connect to. + +### OSX + +To run any of the Gobot BLE code you must use the `GODEBUG=cgocheck=0` flag in order to get around some of the issues in the CGo-based implementation. + +For example: + + GODEBUG=cgocheck=0 go run examples/microbit_blink.go "BBC micro:bit" + +OSX uses its own Bluetooth ID system which is different from the IDs used on Linux. The code calls thru the XPC interfaces provided by OSX, so as a result does not need to run under sudo. + +### Ubuntu + +On Linux the BLE code will need to run as a root user account. The easiest way to accomplish this is probably to use `go build` to build your program, and then to run the requesting executable using `sudo`. + +For example: + + go build examples/microbit_blink.go + sudo ./microbit_blink "BBC micro:bit" + +### Windows + +Hopefully coming soon... diff --git a/platforms/microbit/accelerometer_driver.go b/platforms/microbit/accelerometer_driver.go new file mode 100644 index 00000000..c30b8004 --- /dev/null +++ b/platforms/microbit/accelerometer_driver.go @@ -0,0 +1,93 @@ +package microbit + +import ( + "bytes" + "encoding/binary" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" +) + +// AccelerometerDriver is the Gobot driver for the Microbit's built-in accelerometer +type AccelerometerDriver struct { + name string + connection gobot.Connection + gobot.Eventer +} + +type RawAccelerometerData struct { + X int16 + Y int16 + Z int16 +} + +type AccelerometerData struct { + X float32 + Y float32 + Z float32 +} + +const ( + // BLE services + accelerometerService = "e95d0753251d470aa062fa1922dfa9a8" + + // BLE characteristics + accelerometerCharacteristic = "e95dca4b251d470aa062fa1922dfa9a8" + + // Accelerometer event + Accelerometer = "accelerometer" +) + +// NewAccelerometerDriver creates a Microbit AccelerometerDriver +func NewAccelerometerDriver(a *ble.ClientAdaptor) *AccelerometerDriver { + n := &AccelerometerDriver{ + name: gobot.DefaultName("Microbit Accelerometer"), + connection: a, + Eventer: gobot.NewEventer(), + } + + n.AddEvent(Accelerometer) + + return n +} + +// Connection returns the BLE connection +func (b *AccelerometerDriver) Connection() gobot.Connection { return b.connection } + +// Name returns the Driver Name +func (b *AccelerometerDriver) Name() string { return b.name } + +// SetName sets the Driver Name +func (b *AccelerometerDriver) SetName(n string) { b.name = n } + +// adaptor returns BLE adaptor +func (b *AccelerometerDriver) adaptor() *ble.ClientAdaptor { + return b.Connection().(*ble.ClientAdaptor) +} + +// Start tells driver to get ready to do work +func (b *AccelerometerDriver) Start() (err error) { + // subscribe to accelerometer notifications + b.adaptor().Subscribe(accelerometerCharacteristic, func(data []byte, e error) { + a := &RawAccelerometerData{X: 0, Y: 0, Z: 0} + + buf := bytes.NewBuffer(data) + binary.Read(buf, binary.LittleEndian, &a.X) + binary.Read(buf, binary.LittleEndian, &a.Y) + binary.Read(buf, binary.LittleEndian, &a.Z) + + result := &AccelerometerData{ + X: float32(a.X) / 1000.0, + Y: float32(a.Y) / 1000.0, + Z: float32(a.Z) / 1000.0} + + b.Publish(b.Event(Accelerometer), result) + }) + + return +} + +// Halt stops LED driver (void) +func (b *AccelerometerDriver) Halt() (err error) { + return +} diff --git a/platforms/microbit/accelerometer_driver_test.go b/platforms/microbit/accelerometer_driver_test.go new file mode 100644 index 00000000..159d231d --- /dev/null +++ b/platforms/microbit/accelerometer_driver_test.go @@ -0,0 +1,23 @@ +package microbit + +import ( + "strings" + "testing" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/gobottest" + + "gobot.io/x/gobot/platforms/ble" +) + +var _ gobot.Driver = (*AccelerometerDriver)(nil) + +func initTestAccelerometerDriver() *AccelerometerDriver { + d := NewAccelerometerDriver(ble.NewClientAdaptor("D7:99:5A:26:EC:38")) + return d +} + +func TestAccelerometerDriver(t *testing.T) { + d := initTestAccelerometerDriver() + gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit Accelerometer"), true) +} diff --git a/platforms/microbit/button_driver.go b/platforms/microbit/button_driver.go new file mode 100644 index 00000000..14871388 --- /dev/null +++ b/platforms/microbit/button_driver.go @@ -0,0 +1,76 @@ +package microbit + +import ( + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" +) + +// ButtonDriver is the Gobot driver for the Microbit's built-in buttons +type ButtonDriver struct { + name string + connection gobot.Connection + gobot.Eventer +} + +const ( + // BLE services + buttonService = "e95d9882251d470aa062fa1922dfa9a8" + + // BLE characteristics + buttonACharacteristic = "e95dda90251d470aa062fa1922dfa9a8" + buttonBCharacteristic = "e95dda91251d470aa062fa1922dfa9a8" + + // ButtonA event + ButtonA = "buttonA" + + // ButtonB event + ButtonB = "buttonB" +) + +// NewButtonDriver creates a Microbit ButtonDriver +func NewButtonDriver(a *ble.ClientAdaptor) *ButtonDriver { + n := &ButtonDriver{ + name: gobot.DefaultName("Microbit Button"), + connection: a, + Eventer: gobot.NewEventer(), + } + + n.AddEvent(ButtonA) + n.AddEvent(ButtonB) + + return n +} + +// Connection returns the BLE connection +func (b *ButtonDriver) Connection() gobot.Connection { return b.connection } + +// Name returns the Driver Name +func (b *ButtonDriver) Name() string { return b.name } + +// SetName sets the Driver Name +func (b *ButtonDriver) SetName(n string) { b.name = n } + +// adaptor returns BLE adaptor +func (b *ButtonDriver) adaptor() *ble.ClientAdaptor { + return b.Connection().(*ble.ClientAdaptor) +} + +// Start tells driver to get ready to do work +func (b *ButtonDriver) Start() (err error) { + // subscribe to button A notifications + b.adaptor().Subscribe(buttonACharacteristic, func(data []byte, e error) { + b.Publish(b.Event(ButtonA), data) + }) + + // subscribe to button B notifications + b.adaptor().Subscribe(buttonBCharacteristic, func(data []byte, e error) { + b.Publish(b.Event(ButtonB), data) + }) + + return +} + +// Halt stops LED driver (void) +func (b *ButtonDriver) Halt() (err error) { + return +} diff --git a/platforms/microbit/button_driver_test.go b/platforms/microbit/button_driver_test.go new file mode 100644 index 00000000..77363b29 --- /dev/null +++ b/platforms/microbit/button_driver_test.go @@ -0,0 +1,23 @@ +package microbit + +import ( + "strings" + "testing" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/gobottest" + + "gobot.io/x/gobot/platforms/ble" +) + +var _ gobot.Driver = (*ButtonDriver)(nil) + +func initTestButtonDriver() *ButtonDriver { + d := NewButtonDriver(ble.NewClientAdaptor("D7:99:5A:26:EC:38")) + return d +} + +func TestButtonDriver(t *testing.T) { + d := initTestButtonDriver() + gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit Button"), true) +} diff --git a/platforms/microbit/doc.go b/platforms/microbit/doc.go new file mode 100644 index 00000000..471bb7ed --- /dev/null +++ b/platforms/microbit/doc.go @@ -0,0 +1,7 @@ +/* +Package microbit contains the Gobot drivers for the Microbit. + +For more information refer to the microbit README: +https://github.com/hybridgroup/gobot/blob/master/platforms/microbit/README.md +*/ +package microbit // import "gobot.io/x/gobot/platforms/microbit" diff --git a/platforms/microbit/led_driver.go b/platforms/microbit/led_driver.go new file mode 100644 index 00000000..f693a7a7 --- /dev/null +++ b/platforms/microbit/led_driver.go @@ -0,0 +1,149 @@ +package microbit + +import ( + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" +) + +// LEDDriver is the Gobot driver for the Microbit's LED array +type LEDDriver struct { + name string + connection gobot.Connection + gobot.Eventer +} + +const ( + // BLE services + ledService = "e95dd91d251d470aa062fa1922dfa9a8" + + // BLE characteristics + ledMatrixStateCharacteristic = "e95d7b77251d470aa062fa1922dfa9a8" + ledTextCharacteristic = "e95d93ee251d470aa062fa1922dfa9a8" + ledScrollingDelayCharacteristic = "e95d0d2d251d470aa062fa1922dfa9a8" +) + +// NewLEDDriver creates a Microbit LEDDriver +func NewLEDDriver(a *ble.ClientAdaptor) *LEDDriver { + n := &LEDDriver{ + name: gobot.DefaultName("Microbit LED"), + connection: a, + Eventer: gobot.NewEventer(), + } + + return n +} + +// Connection returns the BLE connection +func (b *LEDDriver) Connection() gobot.Connection { return b.connection } + +// Name returns the Driver Name +func (b *LEDDriver) Name() string { return b.name } + +// SetName sets the Driver Name +func (b *LEDDriver) SetName(n string) { b.name = n } + +// adaptor returns BLE adaptor +func (b *LEDDriver) adaptor() *ble.ClientAdaptor { + return b.Connection().(*ble.ClientAdaptor) +} + +// Start tells driver to get ready to do work +func (b *LEDDriver) Start() (err error) { + return +} + +// Halt stops LED driver (void) +func (b *LEDDriver) Halt() (err error) { + return +} + +// ReadMatrix read the current LED matrix state +func (b *LEDDriver) ReadMatrix() (data []byte, err error) { + data, err = b.adaptor().ReadCharacteristic(ledMatrixStateCharacteristic) + return +} + +// WriteMatrix writes an array of 5 bytes to set the LED matrix +func (b *LEDDriver) WriteMatrix(data []byte) (err error) { + err = b.adaptor().WriteCharacteristic(ledMatrixStateCharacteristic, data) + return +} + +// WriteText writes a text message to the Microbit LED matrix +func (b *LEDDriver) WriteText(msg string) (err error) { + err = b.adaptor().WriteCharacteristic(ledTextCharacteristic, []byte(msg)) + return err +} + +func (b *LEDDriver) ReadScrollingDelay() (delay uint16, err error) { + return +} + +func (b *LEDDriver) WriteScrollingDelay(delay uint16) (err error) { + buf := []byte{byte(delay)} + err = b.adaptor().WriteCharacteristic(ledScrollingDelayCharacteristic, buf) + return +} + +// Blank clears the LEDs on the Microbit +func (b *LEDDriver) Blank() (err error) { + buf := []byte{0x00, 0x00, 0x00, 0x00, 0x00} + err = b.WriteMatrix(buf) + return +} + +// Solid turns on all of the Microbit LEDs +func (b *LEDDriver) Solid() (err error) { + buf := []byte{0x1F, 0x1F, 0x1F, 0x1F, 0x1F} + err = b.WriteMatrix(buf) + return +} + +// UpRightArrow displays an arrow pointing upwards and to the right on the Microbit LEDs +func (b *LEDDriver) UpRightArrow() (err error) { + buf := []byte{0x0F, 0x03, 0x05, 0x09, 0x10} + err = b.WriteMatrix(buf) + return +} + +// UpLeftArrow displays an arrow pointing upwards and to the left on the Microbit LEDs +func (b *LEDDriver) UpLeftArrow() (err error) { + buf := []byte{0x1E, 0x18, 0x14, 0x12, 0x01} + err = b.WriteMatrix(buf) + return +} + +// DownRightArrow displays an arrow pointing down and to the right on the Microbit LEDs +func (b *LEDDriver) DownRightArrow() (err error) { + buf := []byte{0x10, 0x09, 0x05, 0x03, 0x0F} + err = b.WriteMatrix(buf) + return +} + +// DownLeftArrow displays an arrow pointing down and to the left on the Microbit LEDs +func (b *LEDDriver) DownLeftArrow() (err error) { + buf := []byte{0x01, 0x12, 0x14, 0x18, 0x1E} + err = b.WriteMatrix(buf) + return +} + +// Dimond displays a dimond on the Microbit LEDs +func (b *LEDDriver) Dimond() (err error) { + buf := []byte{0x04, 0x0A, 0x11, 0x0A, 0x04} + err = b.WriteMatrix(buf) + return +} + +// Smile displays a smile on the Microbit LEDs +func (b *LEDDriver) Smile() (err error) { + buf := []byte{0x0A, 0x0A, 0x00, 0x11, 0x0E} + err = b.WriteMatrix(buf) + return +} + +// Wink displays a wink on the Microbit LEDs +func (b *LEDDriver) Wink() (err error) { + buf := []byte{0x08, 0x0B, 0x00, 0x11, 0x0E} + err = b.WriteMatrix(buf) + return +} diff --git a/platforms/microbit/led_driver_test.go b/platforms/microbit/led_driver_test.go new file mode 100644 index 00000000..46bb38bc --- /dev/null +++ b/platforms/microbit/led_driver_test.go @@ -0,0 +1,23 @@ +package microbit + +import ( + "strings" + "testing" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/gobottest" + + "gobot.io/x/gobot/platforms/ble" +) + +var _ gobot.Driver = (*LEDDriver)(nil) + +func initTestLEDDriver() *LEDDriver { + d := NewLEDDriver(ble.NewClientAdaptor("D7:99:5A:26:EC:38")) + return d +} + +func TestLEDDriver(t *testing.T) { + d := initTestLEDDriver() + gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit LED"), true) +} diff --git a/platforms/microbit/magnetometer_driver.go b/platforms/microbit/magnetometer_driver.go new file mode 100644 index 00000000..af79ba60 --- /dev/null +++ b/platforms/microbit/magnetometer_driver.go @@ -0,0 +1,93 @@ +package microbit + +import ( + "bytes" + "encoding/binary" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" +) + +// MagnetometerDriver is the Gobot driver for the Microbit's built-in magnetometer +type MagnetometerDriver struct { + name string + connection gobot.Connection + gobot.Eventer +} + +type RawMagnetometerData struct { + X int16 + Y int16 + Z int16 +} + +type MagnetometerData struct { + X float32 + Y float32 + Z float32 +} + +const ( + // BLE services + magnetometerService = "e95df2d8251d470aa062fa1922dfa9a8" + + // BLE characteristics + magnetometerCharacteristic = "e95dfb11251d470aa062fa1922dfa9a8" + + // Magnetometer event + Magnetometer = "magnetometer" +) + +// NewMagnetometerDriver creates a Microbit MagnetometerDriver +func NewMagnetometerDriver(a *ble.ClientAdaptor) *MagnetometerDriver { + n := &MagnetometerDriver{ + name: gobot.DefaultName("Microbit Magnetometer"), + connection: a, + Eventer: gobot.NewEventer(), + } + + n.AddEvent(Magnetometer) + + return n +} + +// Connection returns the BLE connection +func (b *MagnetometerDriver) Connection() gobot.Connection { return b.connection } + +// Name returns the Driver Name +func (b *MagnetometerDriver) Name() string { return b.name } + +// SetName sets the Driver Name +func (b *MagnetometerDriver) SetName(n string) { b.name = n } + +// adaptor returns BLE adaptor +func (b *MagnetometerDriver) adaptor() *ble.ClientAdaptor { + return b.Connection().(*ble.ClientAdaptor) +} + +// Start tells driver to get ready to do work +func (b *MagnetometerDriver) Start() (err error) { + // subscribe to magnetometer notifications + b.adaptor().Subscribe(magnetometerCharacteristic, func(data []byte, e error) { + a := &RawMagnetometerData{X: 0, Y: 0, Z: 0} + + buf := bytes.NewBuffer(data) + binary.Read(buf, binary.LittleEndian, &a.X) + binary.Read(buf, binary.LittleEndian, &a.Y) + binary.Read(buf, binary.LittleEndian, &a.Z) + + result := &MagnetometerData{ + X: float32(a.X) / 1000.0, + Y: float32(a.Y) / 1000.0, + Z: float32(a.Z) / 1000.0} + + b.Publish(b.Event(Magnetometer), result) + }) + + return +} + +// Halt stops LED driver (void) +func (b *MagnetometerDriver) Halt() (err error) { + return +} diff --git a/platforms/microbit/magnetometer_driver_test.go b/platforms/microbit/magnetometer_driver_test.go new file mode 100644 index 00000000..20700f97 --- /dev/null +++ b/platforms/microbit/magnetometer_driver_test.go @@ -0,0 +1,23 @@ +package microbit + +import ( + "strings" + "testing" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/gobottest" + + "gobot.io/x/gobot/platforms/ble" +) + +var _ gobot.Driver = (*MagnetometerDriver)(nil) + +func initTestMagnetometerDriver() *MagnetometerDriver { + d := NewMagnetometerDriver(ble.NewClientAdaptor("D7:99:5A:26:EC:38")) + return d +} + +func TestMagnetometerDriver(t *testing.T) { + d := initTestMagnetometerDriver() + gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit Magnetometer"), true) +} diff --git a/platforms/microbit/temperature_driver.go b/platforms/microbit/temperature_driver.go new file mode 100644 index 00000000..0592d448 --- /dev/null +++ b/platforms/microbit/temperature_driver.go @@ -0,0 +1,73 @@ +package microbit + +import ( + "bytes" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" +) + +// TemperatureDriver is the Gobot driver for the Microbit's built-in thermometer +type TemperatureDriver struct { + name string + connection gobot.Connection + gobot.Eventer +} + +const ( + // BLE services + temperatureService = "e95d6100251d470aa062fa1922dfa9a8" + + // BLE characteristics + temperatureCharacteristic = "e95d9250251d470aa062fa1922dfa9a8" + + // Temperature event + Temperature = "temperature" +) + +// NewTemperatureDriver creates a Microbit TemperatureDriver +func NewTemperatureDriver(a *ble.ClientAdaptor) *TemperatureDriver { + n := &TemperatureDriver{ + name: gobot.DefaultName("Microbit Temperature"), + connection: a, + Eventer: gobot.NewEventer(), + } + + n.AddEvent(Temperature) + + return n +} + +// Connection returns the BLE connection +func (b *TemperatureDriver) Connection() gobot.Connection { return b.connection } + +// Name returns the Driver Name +func (b *TemperatureDriver) Name() string { return b.name } + +// SetName sets the Driver Name +func (b *TemperatureDriver) SetName(n string) { b.name = n } + +// adaptor returns BLE adaptor +func (b *TemperatureDriver) adaptor() *ble.ClientAdaptor { + return b.Connection().(*ble.ClientAdaptor) +} + +// Start tells driver to get ready to do work +func (b *TemperatureDriver) Start() (err error) { + // subscribe to temperature notifications + b.adaptor().Subscribe(temperatureCharacteristic, func(data []byte, e error) { + var l int8 + buf := bytes.NewBuffer(data) + val, _ := buf.ReadByte() + l = int8(val) + + b.Publish(b.Event(Temperature), l) + }) + + return +} + +// Halt stops Temperature driver (void) +func (b *TemperatureDriver) Halt() (err error) { + return +} diff --git a/platforms/microbit/temperature_driver_test.go b/platforms/microbit/temperature_driver_test.go new file mode 100644 index 00000000..5604a1ae --- /dev/null +++ b/platforms/microbit/temperature_driver_test.go @@ -0,0 +1,23 @@ +package microbit + +import ( + "strings" + "testing" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/gobottest" + + "gobot.io/x/gobot/platforms/ble" +) + +var _ gobot.Driver = (*TemperatureDriver)(nil) + +func initTestTemperatureDriver() *TemperatureDriver { + d := NewTemperatureDriver(ble.NewClientAdaptor("D7:99:5A:26:EC:38")) + return d +} + +func TestTemperatureDriver(t *testing.T) { + d := initTestTemperatureDriver() + gobottest.Assert(t, strings.HasPrefix(d.Name(), "Microbit Temperature"), true) +}