Skip to content

Conversation

deadprogram
Copy link
Member

This PR adds the initial support for macOS with nothing more than scanning implemented.

It is currently WIP so I am making it draft.

@deadprogram deadprogram mentioned this pull request Aug 28, 2020
@deadprogram
Copy link
Member Author

Latest commit builds and can scan on macOS.

make smoketest-macos
# Test on macos.
GOOS=darwin CGO_ENABLED=1 go build -o /tmp/go-build-discard ./examples/scanner

/tmp/go-build-discard
scanning...
found device: ba3cd17f-dbbb-aaba-2f40-e0cffe748605 -94
found device: e8e09032-f1bd-5ebb-874e-11a05eb47579 -95
found device: 1a6b3f14-d497-a284-1e4d-2c6f2d0a0003 -94
found device: 01a84b85-e3eb-589f-ac48-81ed9f578e01 -91
found device: 305648ff-a112-bbab-f648-3e342adad436 -91
found device: 305648ff-a112-bbab-f648-3e342adad436 -91
found device: 44c60243-30f6-d8af-0d47-4a15280d7025 -83
found device: 01a84b85-e3eb-589f-ac48-81ed9f578e01 -91
found device: 01a84b85-e3eb-589f-ac48-81ed9f578e01 -90
found device: 01a84b85-e3eb-589f-ac48-81ed9f578e01 -90 [AV] Samsung Soundbar MS650
found device: 01a84b85-e3eb-589f-ac48-81ed9f578e01 -89
found device: 01a84b85-e3eb-589f-ac48-81ed9f578e01 -89
found device: 01a84b85-e3eb-589f-ac48-81ed9f578e01 -89 [AV] Samsung Soundbar MS650
found device: 21dbaf72-81ca-beb6-a44e-4dc128116156 -93

@deadprogram deadprogram changed the base branch from master to dev August 28, 2020 10:57
Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few initial comments on the draft.

Too bad CoreBluetooth doesn't expose MAC addresses, that makes the whole API less uniform. I had made the (apparently incorrect) assumption that a MAC is so basic that it'll be exposed everywhere.

@deadprogram deadprogram changed the title macos: initial support for scanning macos: initial support for scanning/connecting Aug 29, 2020
@deadprogram deadprogram marked this pull request as ready for review August 29, 2020 07:36
@deadprogram
Copy link
Member Author

I have now marked this PR as ready for review. I think it wold be good to get any other changes and then get it merged into dev before moving on to additional implementation.

@deadprogram
Copy link
Member Author

I added the last functionality needed to declare this PR "done" which was to implement DiscoverServices() and DiscoverCharacteristics() both of which are now complete.

@deadprogram deadprogram changed the title macos: initial support for scanning/connecting macos: initial support for scanning/connecting/write characteristics Aug 29, 2020
@deadprogram
Copy link
Member Author

OK, just two more commits now with write characteristics.

@aykevl
Copy link
Member

aykevl commented Aug 29, 2020

So, if I understand correctly the methods such as DidDiscoverPeripheral are necessary as a callback mechanism?
I'm not so sure about exposing those. They clutter the API, and are really an implementation detail (many functions that a user of the API should never call). Would it be possible to put them on an unexported struct, so that they don't affect the public API?

@deadprogram
Copy link
Member Author

In order to take advantage of a bunch of the predemined functionality by using https://github.com/tinygo-org/bluetooth/blob/macos/adapter_darwin.go#L12 you need to implement those methods. I think without this there would be a lot more of them! macOS is macOS, we just do what they say.

}

// Connect starts a connection attempt to the given peripheral device address.
func (a *Adapter) Connect(address Addresser, params ConnectionParams) (*Device, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be a good idea to use some sort of check or mutex, right now it appears that it is not possible to connect to more than one device at once (because of a.connectChan for example).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initial implementation only allows for one device, I was not planning on working on that now.

p.SetDelegate(d)
return d, nil
case <-time.NewTimer(10 * time.Second).C:
return nil, errors.New("timeout on Connect")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation says:

After successfully establishing a local connection to a peripheral, the central manager object calls the centralManager:didConnectPeripheral: method of its delegate object. If the connection attempt fails, the central manager object calls the centralManager:didFailToConnectPeripheral:error: method of its delegate object instead. Attempts to connect to a peripheral don’t time out.

Ideally we'd use these instead of laying our own error handling on top of this.
(Of course, didFailToConnectPeripheral is secretly just a timeout but it's a timeout on a much lower level).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just a simple implementation, but can probably connect that easily enough.

Comment on lines +37 to +42
case <-time.NewTimer(10 * time.Second).C:
return nil, errors.New("timeout on DiscoverServices")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this doesn't really time out either, it either succeeds or the entire connection is broken.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above comment.

Comment on lines +85 to +89
case <-time.NewTimer(10 * time.Second).C:
return nil, errors.New("timeout on DiscoverCharacteristics")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as my previous comment.

return errors.New("must provide a callback for EnableNotifications")
}

return nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to leave this function unimplemented?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I am working on it, and left it unimplemented for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has now been implemented.

@aykevl
Copy link
Member

aykevl commented Aug 29, 2020

I see. However, they don't need to be on the Adapter type I think. They would be hidden from the user with something like this:

type Adapter struct {
    delegate centralManagerDelegate
}

type centralManagerDelegate struct {
    cbgo.CentralManagerDelegateBase
    a *Adapter
}


// CentralManagerDidUpdateState when central manager state updated.
func (delegate *centralManagerDelegate) CentralManagerDidUpdateState(cmgr cbgo.CentralManager) {
	// powered on?
	if cmgr.State() == cbgo.ManagerStatePoweredOn {
		close(delegate.a.poweredChan)
	}

	// TODO: handle other state changes.
}

This provides the same functionality without cluttering the API.

@deadprogram
Copy link
Member Author

I discovered I can remove a bunch of the implementation that is not being used, coming in future commit. Also, I was trying to have a simpler implementation with less indirection, since there is already a lot of complexity in the macOS CB code itself.

@deadprogram
Copy link
Member Author

Added some delegate types, and have otherwise handled all outstanding feedback items, I think.

@deadprogram
Copy link
Member Author

Added characteristic notifications. No more features in this PR, I mean it! 😺

@deadprogram deadprogram changed the title macos: initial support for scanning/connecting/write characteristics macos: initial support for scanning/connecting/write characteristics/notifications Aug 29, 2020
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Signed-off-by: Ron Evans <ron@hybridgroup.com>
…ead of MAC as the BLE address for a peripheral

Signed-off-by: Ron Evans <ron@hybridgroup.com>
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Signed-off-by: Ron Evans <ron@hybridgroup.com>
…ntation

Signed-off-by: Ron Evans <ron@hybridgroup.com>
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Signed-off-by: deadprogram <ron@hybridgroup.com>
@deadprogram
Copy link
Member Author

I squashed the commits in this branch down based on the functionality, and rebased against dev. Also, have tested on macOS and Linux plus Circuit Playground Bluefruit.

Basically, we can now finally ready to merge! Thanks for all your help on this @aykevl

@deadprogram
Copy link
Member Author

@aykevl any more feedback on this PR?

@aykevl
Copy link
Member

aykevl commented Aug 31, 2020

I'll try to get to this PR tomorrow. I was a bit busy with unrelated things (which is now mostly done).

Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Feel free to merge, unless you want to fix the nit.

Signed-off-by: deadprogram <ron@hybridgroup.com>
@deadprogram
Copy link
Member Author

Now merging, thank you very much @aykevl for your help landing this PR!

@deadprogram deadprogram merged commit d570aa5 into dev Sep 2, 2020
@deadprogram deadprogram deleted the macos branch September 2, 2020 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants