From 90d460bb5b668aa9c4a17aaba6cf7ef05ff7fdd1 Mon Sep 17 00:00:00 2001 From: liming Date: Wed, 18 Sep 2024 10:19:29 +0800 Subject: [PATCH 1/3] update the EnableNotifications Method, add the parameter to specifing the notify or indicate mode of characters, just for windows os --- gattc_windows.go | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/gattc_windows.go b/gattc_windows.go index 69ff5f4..236cf6e 100644 --- a/gattc_windows.go +++ b/gattc_windows.go @@ -19,7 +19,8 @@ var ( errNoWriteWithoutResponse = errors.New("bluetooth: write without response not supported") errWriteFailed = errors.New("bluetooth: write failed") errNoRead = errors.New("bluetooth: read not supported") - errNoNotify = errors.New("bluetooth: notify/indicate not supported") + errNoNotify = errors.New("bluetooth: notify not supported") + errNoIndicate = errors.New("bluetooth: indicate not supported") errEnableNotificationsFailed = errors.New("bluetooth: enable notifications failed") ) @@ -364,10 +365,15 @@ func (c DeviceCharacteristic) Read(data []byte) (int, error) { // Configuration Descriptor (CCCD). This means that most peripherals will send a // notification with a new value every time the value of the characteristic // changes. -func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) error { - if (c.properties&genericattributeprofile.GattCharacteristicPropertiesNotify == 0) && - (c.properties&genericattributeprofile.GattCharacteristicPropertiesIndicate == 0) { - return errNoNotify +func (c DeviceCharacteristic) EnableNotifications(usingIndicate bool, callback func(buf []byte)) error { + if usingIndicate { + if c.properties&genericattributeprofile.GattCharacteristicPropertiesIndicate == 0 { + return errNoIndicate + } + } else { + if c.properties&genericattributeprofile.GattCharacteristicPropertiesNotify == 0 { + return errNoNotify + } } // listen value changed event @@ -405,10 +411,14 @@ func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) err } var writeOp *foundation.IAsyncOperation - if c.properties&genericattributeprofile.GattCharacteristicPropertiesNotify != 0 { - writeOp, err = c.characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(genericattributeprofile.GattClientCharacteristicConfigurationDescriptorValueNotify) + if usingIndicate { + if c.properties&genericattributeprofile.GattCharacteristicPropertiesIndicate != 0 { + writeOp, err = c.characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(genericattributeprofile.GattClientCharacteristicConfigurationDescriptorValueIndicate) + } } else { - writeOp, err = c.characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(genericattributeprofile.GattClientCharacteristicConfigurationDescriptorValueIndicate) + if c.properties&genericattributeprofile.GattCharacteristicPropertiesNotify != 0 { + writeOp, err = c.characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(genericattributeprofile.GattClientCharacteristicConfigurationDescriptorValueNotify) + } } if err != nil { return err From 7146c908ff807dfbbb70c7ad3a289314ba51ca95 Mon Sep 17 00:00:00 2001 From: liming Date: Wed, 18 Sep 2024 10:54:20 +0800 Subject: [PATCH 2/3] update to fix last update, specify indicate or notify mode of character --- gattc_windows.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gattc_windows.go b/gattc_windows.go index 236cf6e..406502d 100644 --- a/gattc_windows.go +++ b/gattc_windows.go @@ -361,11 +361,21 @@ func (c DeviceCharacteristic) Read(data []byte) (int, error) { return len(readBuffer), nil } +// EnableNotifications enables notifications in the Client Characteristic +// Configuration Descriptor (CCCD). Just the Notify mode is supported. +func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) error { + err := c.EnableNotificationsWithMode(false, callback) + if err != nil { + return err + } + return nil +} + // EnableNotifications enables notifications in the Client Characteristic // Configuration Descriptor (CCCD). This means that most peripherals will send a // notification with a new value every time the value of the characteristic // changes. -func (c DeviceCharacteristic) EnableNotifications(usingIndicate bool, callback func(buf []byte)) error { +func (c DeviceCharacteristic) EnableNotificationsWithMode(usingIndicate bool, callback func(buf []byte)) error { if usingIndicate { if c.properties&genericattributeprofile.GattCharacteristicPropertiesIndicate == 0 { return errNoIndicate From e97083a307bd0f037fb50a4c7b2028e3273888ca Mon Sep 17 00:00:00 2001 From: liming Date: Tue, 12 Nov 2024 12:29:28 +0800 Subject: [PATCH 3/3] update the EnableNotificationsWithMode and EnableNotifications methods --- gattc_windows.go | 51 +++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/gattc_windows.go b/gattc_windows.go index 406502d..cde3fcf 100644 --- a/gattc_windows.go +++ b/gattc_windows.go @@ -21,9 +21,18 @@ var ( errNoRead = errors.New("bluetooth: read not supported") errNoNotify = errors.New("bluetooth: notify not supported") errNoIndicate = errors.New("bluetooth: indicate not supported") + errNoNotifyOrIndicate = errors.New("bluetooth: notify or indicate not supported") + errInvalidNotificationMode = errors.New("bluetooth: invalid notification mode") errEnableNotificationsFailed = errors.New("bluetooth: enable notifications failed") ) +type NotificationMode = genericattributeprofile.GattCharacteristicProperties + +const ( + NotificationModeNotify NotificationMode = genericattributeprofile.GattCharacteristicPropertiesNotify + NotificationModeIndicate NotificationMode = genericattributeprofile.GattCharacteristicPropertiesIndicate +) + // DiscoverServices starts a service discovery procedure. Pass a list of service // UUIDs you are interested in to this function. Either a slice of all services // is returned (of the same length as the requested UUIDs and in the same @@ -361,29 +370,44 @@ func (c DeviceCharacteristic) Read(data []byte) (int, error) { return len(readBuffer), nil } -// EnableNotifications enables notifications in the Client Characteristic -// Configuration Descriptor (CCCD). Just the Notify mode is supported. +// EnableNotifications enables notifications or indicate in the Client Characteristic +// Configuration Descriptor (CCCD). And it favors Notify over Indicate. func (c DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) error { - err := c.EnableNotificationsWithMode(false, callback) + var err error + if c.properties&genericattributeprofile.GattCharacteristicPropertiesNotify == 0 { + err = c.EnableNotificationsWithMode(NotificationModeNotify, callback) + } else if c.properties&genericattributeprofile.GattCharacteristicPropertiesIndicate == 0 { + err = c.EnableNotificationsWithMode(NotificationModeIndicate, callback) + } else { + return errNoNotifyOrIndicate + } + if err != nil { return err } return nil } -// EnableNotifications enables notifications in the Client Characteristic +// EnableNotificationsWithMode enables notifications in the Client Characteristic // Configuration Descriptor (CCCD). This means that most peripherals will send a // notification with a new value every time the value of the characteristic -// changes. -func (c DeviceCharacteristic) EnableNotificationsWithMode(usingIndicate bool, callback func(buf []byte)) error { - if usingIndicate { +// changes. And you can select the notify/indicate mode as you need. +func (c DeviceCharacteristic) EnableNotificationsWithMode(mode NotificationMode, callback func(buf []byte)) error { + configValue := genericattributeprofile.GattClientCharacteristicConfigurationDescriptorValueNone + if mode == NotificationModeIndicate { if c.properties&genericattributeprofile.GattCharacteristicPropertiesIndicate == 0 { return errNoIndicate } - } else { + // set to indicate mode + configValue = genericattributeprofile.GattClientCharacteristicConfigurationDescriptorValueIndicate + } else if mode == NotificationModeNotify { if c.properties&genericattributeprofile.GattCharacteristicPropertiesNotify == 0 { return errNoNotify } + // set to notify mode + configValue = genericattributeprofile.GattClientCharacteristicConfigurationDescriptorValueNotify + } else { + return errInvalidNotificationMode } // listen value changed event @@ -420,16 +444,7 @@ func (c DeviceCharacteristic) EnableNotificationsWithMode(usingIndicate bool, ca return err } - var writeOp *foundation.IAsyncOperation - if usingIndicate { - if c.properties&genericattributeprofile.GattCharacteristicPropertiesIndicate != 0 { - writeOp, err = c.characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(genericattributeprofile.GattClientCharacteristicConfigurationDescriptorValueIndicate) - } - } else { - if c.properties&genericattributeprofile.GattCharacteristicPropertiesNotify != 0 { - writeOp, err = c.characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(genericattributeprofile.GattClientCharacteristicConfigurationDescriptorValueNotify) - } - } + writeOp, err := c.characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(configValue) if err != nil { return err }