How to subscribe to multiple BLE characteristics that have the same service and characteristic UUID
I am trying to figure out how to subscribe to multiple temperature sensors from a BLE device. My goal is to read all 8 temperature sensors at 1Hz. The BLE device has an environmental sensing service, here are what it’s characteristics look like.
"ServiceName" "ServiceUUID" "CharacteristicName" "CharacteristicUUID" "Attributes"
"Generic Attribute" "1801" "Service Changed" "2A05" "Indicate"
"Generic Attribute" "1801" "Custom" "2B29" 1×2 string
"Generic Attribute" "1801" "Custom" "2B2A" "Read"
"Generic Access" "1800" "Device Name" "2A00" "Read"
"Generic Access" "1800" "Appearance" "2A01" "Read"
"Generic Access" "1800" "Peripheral Preferred Connection Parameters" "2A04" "Read"
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
The 1×2 string is
"Read" "Notify"
The line that I am using works when there is one temperature sensor but not when there are multiple. The line is
characteristic(sensor, "Environmental Sensing", "Temperature")
When I call this line when there are multiple sensors present I get the following error Failed to discover descriptors. If device is disconnected, then clear existing ble object and recreate it. The BLE device is a nRF52 based chip that I wrote the code for with Zephyr. If there is something wrong with how I made the GATT then I can go fix it to work with Matlab better. The descriptors have a characteristic user data field that gives a name for each temperature sensor as Sensor X where X is 0-7. I have confirmed hat the device is not the issue and is programmed correctly by testing it nRF connect.
Update:
Stepping through the code I found the error coming from how the ble message is being given to the transport. It is passing a vector and not a scalar that it seems like it is expecting. For example in Characteristic.m line 315,
methods(Access = {?matlabshared.blelib.Descriptor, ?matlabshared.blelib.read.characteristic.Interface, ?matlabshared.blelib.write.characteristic.Interface})
function output = execute(obj, cmd, varargin)
peripheral = obj.getParent;
% Supress warning that might be thrown in get.Connected
ws = warning(‘off’, ‘MATLAB:ble:ble:deviceDisconnected’);
c = onCleanup(@() cleanup(ws));
if ~peripheral.Connected
matlabshared.blelib.internal.localizedError(‘MATLAB:ble:ble:failToExecuteDeviceDisconnected’);
end
output = peripheral.execute(cmd, obj.ServiceIndex, obj.CharacteristicIndex, varargin{:});
function cleanup(ws)
warning(ws.state, ‘MATLAB:ble:ble:deviceDisconnected’);
end
end
end
For the line
output = peripheral.execute(cmd, obj.ServiceIndex, obj.CharacteristicIndex, varargin{:});
the arguments are
cmd = DISCOVER_DESCRIPTORS
obj.ServiceIndex = 3
obj.CharacteristicIndex = [1;2;3;4;5;6;7;8]
It seems like obj.CharacteristicIndex should be just a number to get it to work.
It seems like the source of the issue starts in ble.m line 411 when
cinfo.Index = find(subtable.CharacteristicUUID == uuid);
returns a column vector instead of a scalar
function cinfo = validateCharacteristic(obj, sinfo, input)
% Check if input is a valid characteristic name or UUID supported
% on the peripheral and return index of the characteristic for
% the specified service
% Validate data type
info = matlabshared.blelib.internal.ServicesCharacteristicsDescriptorsInfo.getInstance;
uuid = info.getCharacteristicUUID(sinfo.UUID, input);
uuid = info.getShortestUUID(uuid);
% Find portion of the table that has the same ServiceUUID
subtable = obj.Characteristics(obj.Characteristics.ServiceUUID == obj.Services.ServiceUUID(sinfo.Index), :);
try
uuid = validatestring(uuid, subtable.CharacteristicUUID);
catch e
if strcmpi(e.identifier,’MATLAB:ambiguousStringChoice’)
throwAsCaller(e);
else
matlabshared.blelib.internal.localizedError(‘MATLAB:ble:ble:unsupportedCharacteristic’);
end
end
cinfo = info.getCharacteristicInfoByUUID(sinfo.UUID, uuid);
cinfo.Index = find(subtable.CharacteristicUUID == uuid);
cinfo.Attributes = subtable.Attributes{cinfo.Index};
end
end
It looks like edits to the files are locked so I can’t quite write a new version of the functions to try and handle the case of multiple entries.I am trying to figure out how to subscribe to multiple temperature sensors from a BLE device. My goal is to read all 8 temperature sensors at 1Hz. The BLE device has an environmental sensing service, here are what it’s characteristics look like.
"ServiceName" "ServiceUUID" "CharacteristicName" "CharacteristicUUID" "Attributes"
"Generic Attribute" "1801" "Service Changed" "2A05" "Indicate"
"Generic Attribute" "1801" "Custom" "2B29" 1×2 string
"Generic Attribute" "1801" "Custom" "2B2A" "Read"
"Generic Access" "1800" "Device Name" "2A00" "Read"
"Generic Access" "1800" "Appearance" "2A01" "Read"
"Generic Access" "1800" "Peripheral Preferred Connection Parameters" "2A04" "Read"
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
The 1×2 string is
"Read" "Notify"
The line that I am using works when there is one temperature sensor but not when there are multiple. The line is
characteristic(sensor, "Environmental Sensing", "Temperature")
When I call this line when there are multiple sensors present I get the following error Failed to discover descriptors. If device is disconnected, then clear existing ble object and recreate it. The BLE device is a nRF52 based chip that I wrote the code for with Zephyr. If there is something wrong with how I made the GATT then I can go fix it to work with Matlab better. The descriptors have a characteristic user data field that gives a name for each temperature sensor as Sensor X where X is 0-7. I have confirmed hat the device is not the issue and is programmed correctly by testing it nRF connect.
Update:
Stepping through the code I found the error coming from how the ble message is being given to the transport. It is passing a vector and not a scalar that it seems like it is expecting. For example in Characteristic.m line 315,
methods(Access = {?matlabshared.blelib.Descriptor, ?matlabshared.blelib.read.characteristic.Interface, ?matlabshared.blelib.write.characteristic.Interface})
function output = execute(obj, cmd, varargin)
peripheral = obj.getParent;
% Supress warning that might be thrown in get.Connected
ws = warning(‘off’, ‘MATLAB:ble:ble:deviceDisconnected’);
c = onCleanup(@() cleanup(ws));
if ~peripheral.Connected
matlabshared.blelib.internal.localizedError(‘MATLAB:ble:ble:failToExecuteDeviceDisconnected’);
end
output = peripheral.execute(cmd, obj.ServiceIndex, obj.CharacteristicIndex, varargin{:});
function cleanup(ws)
warning(ws.state, ‘MATLAB:ble:ble:deviceDisconnected’);
end
end
end
For the line
output = peripheral.execute(cmd, obj.ServiceIndex, obj.CharacteristicIndex, varargin{:});
the arguments are
cmd = DISCOVER_DESCRIPTORS
obj.ServiceIndex = 3
obj.CharacteristicIndex = [1;2;3;4;5;6;7;8]
It seems like obj.CharacteristicIndex should be just a number to get it to work.
It seems like the source of the issue starts in ble.m line 411 when
cinfo.Index = find(subtable.CharacteristicUUID == uuid);
returns a column vector instead of a scalar
function cinfo = validateCharacteristic(obj, sinfo, input)
% Check if input is a valid characteristic name or UUID supported
% on the peripheral and return index of the characteristic for
% the specified service
% Validate data type
info = matlabshared.blelib.internal.ServicesCharacteristicsDescriptorsInfo.getInstance;
uuid = info.getCharacteristicUUID(sinfo.UUID, input);
uuid = info.getShortestUUID(uuid);
% Find portion of the table that has the same ServiceUUID
subtable = obj.Characteristics(obj.Characteristics.ServiceUUID == obj.Services.ServiceUUID(sinfo.Index), :);
try
uuid = validatestring(uuid, subtable.CharacteristicUUID);
catch e
if strcmpi(e.identifier,’MATLAB:ambiguousStringChoice’)
throwAsCaller(e);
else
matlabshared.blelib.internal.localizedError(‘MATLAB:ble:ble:unsupportedCharacteristic’);
end
end
cinfo = info.getCharacteristicInfoByUUID(sinfo.UUID, uuid);
cinfo.Index = find(subtable.CharacteristicUUID == uuid);
cinfo.Attributes = subtable.Attributes{cinfo.Index};
end
end
It looks like edits to the files are locked so I can’t quite write a new version of the functions to try and handle the case of multiple entries. I am trying to figure out how to subscribe to multiple temperature sensors from a BLE device. My goal is to read all 8 temperature sensors at 1Hz. The BLE device has an environmental sensing service, here are what it’s characteristics look like.
"ServiceName" "ServiceUUID" "CharacteristicName" "CharacteristicUUID" "Attributes"
"Generic Attribute" "1801" "Service Changed" "2A05" "Indicate"
"Generic Attribute" "1801" "Custom" "2B29" 1×2 string
"Generic Attribute" "1801" "Custom" "2B2A" "Read"
"Generic Access" "1800" "Device Name" "2A00" "Read"
"Generic Access" "1800" "Appearance" "2A01" "Read"
"Generic Access" "1800" "Peripheral Preferred Connection Parameters" "2A04" "Read"
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Temperature" "2A6E" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
"Environmental Sensing" "181A" "Humidity" "2A6F" 1×2 string
The 1×2 string is
"Read" "Notify"
The line that I am using works when there is one temperature sensor but not when there are multiple. The line is
characteristic(sensor, "Environmental Sensing", "Temperature")
When I call this line when there are multiple sensors present I get the following error Failed to discover descriptors. If device is disconnected, then clear existing ble object and recreate it. The BLE device is a nRF52 based chip that I wrote the code for with Zephyr. If there is something wrong with how I made the GATT then I can go fix it to work with Matlab better. The descriptors have a characteristic user data field that gives a name for each temperature sensor as Sensor X where X is 0-7. I have confirmed hat the device is not the issue and is programmed correctly by testing it nRF connect.
Update:
Stepping through the code I found the error coming from how the ble message is being given to the transport. It is passing a vector and not a scalar that it seems like it is expecting. For example in Characteristic.m line 315,
methods(Access = {?matlabshared.blelib.Descriptor, ?matlabshared.blelib.read.characteristic.Interface, ?matlabshared.blelib.write.characteristic.Interface})
function output = execute(obj, cmd, varargin)
peripheral = obj.getParent;
% Supress warning that might be thrown in get.Connected
ws = warning(‘off’, ‘MATLAB:ble:ble:deviceDisconnected’);
c = onCleanup(@() cleanup(ws));
if ~peripheral.Connected
matlabshared.blelib.internal.localizedError(‘MATLAB:ble:ble:failToExecuteDeviceDisconnected’);
end
output = peripheral.execute(cmd, obj.ServiceIndex, obj.CharacteristicIndex, varargin{:});
function cleanup(ws)
warning(ws.state, ‘MATLAB:ble:ble:deviceDisconnected’);
end
end
end
For the line
output = peripheral.execute(cmd, obj.ServiceIndex, obj.CharacteristicIndex, varargin{:});
the arguments are
cmd = DISCOVER_DESCRIPTORS
obj.ServiceIndex = 3
obj.CharacteristicIndex = [1;2;3;4;5;6;7;8]
It seems like obj.CharacteristicIndex should be just a number to get it to work.
It seems like the source of the issue starts in ble.m line 411 when
cinfo.Index = find(subtable.CharacteristicUUID == uuid);
returns a column vector instead of a scalar
function cinfo = validateCharacteristic(obj, sinfo, input)
% Check if input is a valid characteristic name or UUID supported
% on the peripheral and return index of the characteristic for
% the specified service
% Validate data type
info = matlabshared.blelib.internal.ServicesCharacteristicsDescriptorsInfo.getInstance;
uuid = info.getCharacteristicUUID(sinfo.UUID, input);
uuid = info.getShortestUUID(uuid);
% Find portion of the table that has the same ServiceUUID
subtable = obj.Characteristics(obj.Characteristics.ServiceUUID == obj.Services.ServiceUUID(sinfo.Index), :);
try
uuid = validatestring(uuid, subtable.CharacteristicUUID);
catch e
if strcmpi(e.identifier,’MATLAB:ambiguousStringChoice’)
throwAsCaller(e);
else
matlabshared.blelib.internal.localizedError(‘MATLAB:ble:ble:unsupportedCharacteristic’);
end
end
cinfo = info.getCharacteristicInfoByUUID(sinfo.UUID, uuid);
cinfo.Index = find(subtable.CharacteristicUUID == uuid);
cinfo.Attributes = subtable.Attributes{cinfo.Index};
end
end
It looks like edits to the files are locked so I can’t quite write a new version of the functions to try and handle the case of multiple entries. bluetooth, ble, identical characteristics, subscriptions MATLAB Answers — New Questions