diff --git a/platforms/firmata/client/client.go b/platforms/firmata/client/client.go index 9227ac4c..c9e66e77 100644 --- a/platforms/firmata/client/client.go +++ b/platforms/firmata/client/client.go @@ -218,10 +218,10 @@ func (b *Client) ServoConfig(pin int, max int, min int) error { ret := []byte{ ServoConfig, byte(pin), - byte(max & 0x7F), - byte((max >> 7) & 0x7F), byte(min & 0x7F), byte((min >> 7) & 0x7F), + byte(max & 0x7F), + byte((max >> 7) & 0x7F), } return b.writeSysex(ret) } diff --git a/platforms/firmata/client/client_test.go b/platforms/firmata/client/client_test.go index 8ade6331..fd4a175e 100644 --- a/platforms/firmata/client/client_test.go +++ b/platforms/firmata/client/client_test.go @@ -1,6 +1,7 @@ package client import ( + "bytes" "testing" "time" @@ -11,10 +12,11 @@ import ( type readWriteCloser struct{} func (readWriteCloser) Write(p []byte) (int, error) { - return len(p), nil + return testWriteData.Write(p) } var testReadData = []byte{} +var testWriteData = bytes.Buffer{} func (readWriteCloser) Read(b []byte) (int, error) { size := len(b) @@ -218,3 +220,38 @@ func TestConnect(t *testing.T) { gobottest.Assert(t, b.Connect(readWriteCloser{}), nil) } + +func TestServoConfig(t *testing.T) { + b := New() + b.connection = readWriteCloser{} + + tests := []struct { + description string + arguments [3]int + expected []byte + result error + }{ + { + description: "Min values for min & max", + arguments: [3]int{9, 0, 0}, + expected: []byte{0xF0, 0x70, 9, 0, 0, 0, 0, 0xF7}, + }, + { + description: "Max values for min & max", + arguments: [3]int{9, 0x3FFF, 0x3FFF}, + expected: []byte{0xF0, 0x70, 9, 0x7F, 0x7F, 0x7F, 0x7F, 0xF7}, + }, + { + description: "Clipped max values for min & max", + arguments: [3]int{9, 0xFFFF, 0xFFFF}, + expected: []byte{0xF0, 0x70, 9, 0x7F, 0x7F, 0x7F, 0x7F, 0xF7}, + }, + } + + for _, test := range tests { + testWriteData.Reset() + err := b.ServoConfig(test.arguments[0], test.arguments[1], test.arguments[2]) + gobottest.Assert(t, testWriteData.Bytes(), test.expected) + gobottest.Assert(t, err, test.result) + } +} diff --git a/platforms/firmata/firmata_adaptor.go b/platforms/firmata/firmata_adaptor.go index 442a5504..26b89792 100644 --- a/platforms/firmata/firmata_adaptor.go +++ b/platforms/firmata/firmata_adaptor.go @@ -34,6 +34,7 @@ type firmataBoard interface { I2cRead(int, int) error I2cWrite(int, []byte) error I2cConfig(int) error + ServoConfig(int, int, int) error Event(string) *gobot.Event } @@ -115,6 +116,16 @@ func (f *FirmataAdaptor) Port() string { return f.port } // Name returns the FirmataAdaptors name func (f *FirmataAdaptor) Name() string { return f.name } +// ServoConfig sets the pulse width in microseconds for a pin attached to a servo +func (f *FirmataAdaptor) ServoConfig(pin string, min, max int) error { + p, err := strconv.Atoi(pin) + if err != nil { + return err + } + + return f.board.ServoConfig(p, max, min) +} + // ServoWrite writes the 0-180 degree angle to the specified pin. func (f *FirmataAdaptor) ServoWrite(pin string, angle byte) (err error) { p, err := strconv.Atoi(pin) diff --git a/platforms/firmata/firmata_adaptor_test.go b/platforms/firmata/firmata_adaptor_test.go index 0d995bb9..b6ed7372 100644 --- a/platforms/firmata/firmata_adaptor_test.go +++ b/platforms/firmata/firmata_adaptor_test.go @@ -1,8 +1,11 @@ package firmata import ( + "bytes" "errors" + "fmt" "io" + "strings" "testing" "time" @@ -14,10 +17,11 @@ import ( type readWriteCloser struct{} func (readWriteCloser) Write(p []byte) (int, error) { - return len(p), nil + return testWriteData.Write(p) } var testReadData = []byte{} +var testWriteData = bytes.Buffer{} func (readWriteCloser) Read(b []byte) (int, error) { size := len(b) @@ -61,14 +65,15 @@ func (m mockFirmataBoard) Disconnect() error { func (m mockFirmataBoard) Pins() []client.Pin { return m.pins } -func (mockFirmataBoard) AnalogWrite(int, int) error { return nil } -func (mockFirmataBoard) SetPinMode(int, int) error { return nil } -func (mockFirmataBoard) ReportAnalog(int, int) error { return nil } -func (mockFirmataBoard) ReportDigital(int, int) error { return nil } -func (mockFirmataBoard) DigitalWrite(int, int) error { return nil } -func (mockFirmataBoard) I2cRead(int, int) error { return nil } -func (mockFirmataBoard) I2cWrite(int, []byte) error { return nil } -func (mockFirmataBoard) I2cConfig(int) error { return nil } +func (mockFirmataBoard) AnalogWrite(int, int) error { return nil } +func (mockFirmataBoard) SetPinMode(int, int) error { return nil } +func (mockFirmataBoard) ReportAnalog(int, int) error { return nil } +func (mockFirmataBoard) ReportDigital(int, int) error { return nil } +func (mockFirmataBoard) DigitalWrite(int, int) error { return nil } +func (mockFirmataBoard) I2cRead(int, int) error { return nil } +func (mockFirmataBoard) I2cWrite(int, []byte) error { return nil } +func (mockFirmataBoard) I2cConfig(int) error { return nil } +func (mockFirmataBoard) ServoConfig(int, int, int) error { return nil } func initTestFirmataAdaptor() *FirmataAdaptor { a := NewFirmataAdaptor("board", "/dev/null") @@ -166,3 +171,13 @@ func TestFirmataAdaptorI2cWrite(t *testing.T) { a := initTestFirmataAdaptor() a.I2cWrite(0x00, []byte{0x00, 0x01}) } + +func TestServoConfig(t *testing.T) { + a := initTestFirmataAdaptor() + err := a.ServoConfig("9", 0, 0) + gobottest.Assert(t, err, nil) + + // test atoi error + err = a.ServoConfig("a", 0, 0) + gobottest.Assert(t, true, strings.Contains(fmt.Sprintf("%v", err), "invalid syntax")) +}