Alt Beacon Parser is not working even after adding new parser layout - altbeacon

Even after updating the beacon manager with new parser the scan-filter is still using old beacon parser and failing to parse.
The old beacon parser is
beaconParserList: altbeacon, m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25
Setting new beacon parser
beaconManager.getBeaconParsers().clear();
BeaconParser beaconParser = new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
beaconManager.getBeaconParsers().add(beaconParser);
Scan results after enabling debug on Alt-Beacon library
D/BeaconParser: Processing pdu type FF: 0201061aff4c000215fb7dd88a496f42c49f4a382d8258b4ee03e8044ec41e09354141413d6d536d21366534563b74395a3d42497b2a4d6e417166474800 with startIndex: 5, endIndex: 29
D/BeaconParser: This is not a matching Beacon advertisement. (Was expecting be ac. The bytes I see are: 0201061aff4c000215fb7dd88a496f42c49f4a382d8258b4ee03e8044ec41e09354141413d6d536d21366534563b74395a3d42497b2a4d6e417166474800

If you modify your beacon parsers after you start scanning by calling beaconManager.bind() or constructing RegionBootrap(...), then you need to manually apply your changes with beaconManager.applySettings()
While the above works, it is usually easier just to move the code that sets the beacon parsers above the code that starts scanning.

Related

What does CBATTError Code insufficientResources really mean?

I'm trying to send data over BLE from my iPhone to an ESP32 board. I'm developing in flutter platform and I'm using flutter_reactive_ble library.
My iPhone can connect to the other device and it can also send 1 byte using writeCharacterisiticWithResponse function. But when I try to send my real data which is large (>7000 bytes), it then gives me the error:
flutter: Error occured when writing 9f714672-888c-4450-845f-602c1331cdeb :
Exception: GenericFailure<WriteCharacteristicFailure>(
code: WriteCharacteristicFailure.unknown,
message: "Error Domain=CBATTErrorDomain Code=17
"Resources are insufficient."
UserInfo={NSLocalizedDescription=Resources are insufficient.}")
I tried searching for this error but didn't find additional info, even in Apple Developer website. It just says:
Resources are insufficient to complete the ATT request.
What does this error really means? Which resources are not sufficient and how to work around this problem?
This is almost certainly larger than this characteristic's maximum value length (which is probably on the order of 10s of bytes, not 1000s of bytes). Before writing, you need to call maximumWriteValueLength(for:) to see how much data can be written. If you're trying to send serial data over a characteristic (which is common, but not really what they were designed for), you'll need to break your data up into chunks and reassemble them on the peripheral. You will likely either need an "end" indicator of some kind, or you will need to send the length of the payload first so that the receiver knows how much to excpect.
First of all, a characteristic value cannot be larger than 512 bytes. This is set by the ATT standard (Bluetooth Core Specification v5.3, Vol 3, Part F (ATT), section 3.2.9). This number has been set arbitrarily by the protocol designers and does not map to any technical limitation of the protocol.
So, don't send 7000 bytes in a single write. You need to keep it at most 512 to be standard compliant.
If you say that it works with another Bluetooth stack running on the GATT server, then I guess CoreBluetooth does not enforce/check the maximum length of 512 bytes on the client side (I haven't tested). Therefore I also guess the error code you see was sent by the remote device rather than by CoreBluetooth locally as a pre-check.
There are three different common ways of writing a characteristic on the protocol level (Bluetooth Core Specification v5.3, Vol 3, Part G (GATT), section 4.9 Characteristic Value Write):
Write Without Response (4.9.1)
Write Characteristic Value (4.9.3)
Write Long Characteristic Values (4.9.4)
Number one is unidirectional and does not result in a response packet. It uses a single ATT_WRITE_CMD packet where the value must be at most ATT_MTU-3 bytes in length. This length can be retrieved using maximumWriteValueLength(for:) with .withoutResponse. The requestMtu method in flutter_reactive_ble uses this method internally. If you execute many writes of this type rapidly, be sure to add flow control to avoid CoreBluetooth dropping outgoing packets before they are sent. This can be done through peripheralIsReadyToSendWriteWithoutResponse by simply always waiting for this callback after each write, before you write the next packet. Unfortunately, it seems flutter_reactive_ble does not implement this flow control mechanism.
Number two uses a single ATT_WRITE_REQ where the value must be at most ATT_MTU-3 bytes in length, just as above. Use the same approach as above to retrieve that maximum length (note that maximumWriteValueLength with .withResponse always returns 512 and is not what you want). Here however, either an ATT_WRITE_RSP will be returned on success or an error packet will be received with an error code. Only one ATT transaction can be outstanding at a time, which significantly lowers throughput compared to Write Without Response.
Number three uses a sequence of multiple ATT_PREPARE_WRITE_REQ packets (containing offset and value) followed by an ATT_EXECUTE_WRITE_REQ. The maximum length of the value in each each chunk is ATT_MTU-5. Each _REQ packet also requires a corresponding _RSP packet before it can continue (alternatively, an error code could be sent by the remote device). This approach is used when the characteristic value to be written is too long to be sent using a single ATT_WRITE_REQ.
For any of the above write methods, you are always also limited by the maximum attribute size of 512 bytes as per the specification.
Any Bluetooth stack I know of transparently chooses between "Write Characteristic Value" and "Write Long Characteristic Values" when you tell it to write with response, depending on the value length and MTU. Server side it's a bit different. Some stacks put the burden on the user to combine all packets but it seems nimble handles that on its own. From what I can see in the source code (https://github.com/apache/mynewt-nimble/blob/26ccb8af1f3ea6ad81d5d7cbb762747c6e06a24b/nimble/host/src/ble_att_svr.c#L2099) it can return the "Insufficient Resources" error code when it tries to allocate memory but fails (most likely due to too much buffered data). This is what might happen for you. To answer your first actual question, the standard itself does not say anything else about this error code than simply "Insufficient Resources to complete the request".
The error has nothing to do with LE Data Length extension, which is simply an optimization for a lower layer (BLE Link Layer) that does not affect the functionality of the host stack. The L2CAP layer will take care of the reassembling of smaller link layer packets if necessary, and must always support up to the negotiated MTU without overflowing any buffers.
Now, to answer your second question, if you send very large amounts of data (7000 bytes), you must divide the data in multiple chunks and come up with a way to correctly be able to combine them. Each chunk is written as a full characteristic value. When you do this, be sure to send values at most of size ATT_MTU-3 (but never larger than 512 bytes), to avoid the inefficient overheads of "Write Long Characteristic Values". It's then up to your application code to make sure you don't run out of memory in case too much data is sent.

Filtering Alt beacon with manufacturer identifier and UUID begins with specific format

One of my use case requires to filter all the beacons which is generated by specific manufacturer and UUID starts with specific string.
The ALT beacon library (https://altbeacon.github.io/android-beacon-library/javadoc/reference/org/altbeacon/beacon/Region.html) provides Region class to filter the beacon based on the ID1, ID2, ID3.
I could not find any option to filter all the beacons at the library level which has specific manufacturer ID and the UUID begins with specific characters.
The API documentation with sample code to configure ALT Beacon library for filtering is appreciated and this helps to avoid additional filtering logic implementation at the application.
Filtering on a prefix of the UUID is unusual, but it is possible by defining a custom beacon layout and defining an additional identifier to be the UUID prefix. Because this new extra identifier will be treated as an independent identifier, it won't work like a string prefix -- its default representation will.be a hex string (without dashes).
If you want to filter on the first five bytes of the UUID for iBeacon, you'd set up a beacon parser like this:
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=0215,i:4-8,i:4-19,i:20-21,i:22-23,p:24-24")); // note the new 5 byte prefix identifier: i:4-8
Now each beacon will have four identifiers instead of three, the first of which will be the beginning 5 bytes of the UUID, the second the full UUID, the third the major and the fourth the minor.
You can set up a region to match the first five bytes of this UUID, 2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6 like this:
Region region = new Region("prefixRegion", "0x2F234454CF", null, null);
If you want the prefix to be a different length than 5, simply adjust the i:4-8 part of the layout above to end in a different offset than 8.

Writing BLE to Cycling Control Point - Adding Resistance

I have bee working with BLE for a while now, but primarily for reading and notifying characteristics.
The devices specifically are Virtual cycle trainers that support GATTS Cycling Power Service - 0x1818 link
I know that it's possible to increase resistance on this trainer, but I have read the documentation on Cycling Power Control Point - 0x2A66 [link][2] which is the only one with Mandatory write functions, but non of the documentation seem to be make sense.
Trainer: Cycleops Magnus
Reading and writing characteristic
// Reads all characteristics
var characteristics = service.characteristics;
for(BluetoothCharacteristic c in characteristics) {
List<int> value = await device.readCharacteristic(c);
print(value);
}
// Writes to a characteristic
await device.writeCharacteristic(c, [0x12, 0x34])
Reading and writing descriptors
// Reads all descriptors
var descriptors = characteristic.descriptors;
for(BluetoothDescriptor d in descriptors) {
List<int> value = await device.readDescriptor(d);
print(value);
}
// Writes to a descriptor
await device.writeDescriptor(d, [0x12, 0x34])
The closest I can see is setting the crank length, or chain weight but at this stage I am only guessing and am looking for some guidance.
The questions is this..
What characteristic or descriptor should I use to adjust Virtual Power
trainer resistance and what is the best way to do this?
Any coding Language is fine, I can transpose it.
Screenshot of services available for device
[2]: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.cycling_power_control_point.xml
I think you're using the wrong Bluetooth service for this. The Cycling Power Service is for collecting data from cycling power meters like this one: https://www.cyclist.co.uk/reviews/6705/long-term-review-fsa-powerbox-carbon-power-cranks
For your requirements, I believe you should be using the Fitness Machine Service (0x1826) which includes the Indoor Bike Data characteristic (0x2AD2) and most importantly for you, the Fitness Machine Control Point characteristic. Take a look at section 4.16.1 of the Fitness Machine Service specification and you'll see details of operations which the control point supports, including a reference to 4.16.2.5 Set Target Resistance Level Procedure. I think this is what you need.
You cannot use cycling control point(CPP) for adding resistance. CPP can only be used to copy data like wheel Revolution from old peripheral to new one or if you want to reset data on peripheral you can use cpp.
If you want to add resistance you need to check for fitness machine i am using elite and elite have Fitness Machine Control point you can write resistance and other things like inclination, elevation etc using FTCP.
Few of the vendor support fitness machine and other have given their api or source code you can use that to add resistance and other stuff like that.
Indoor trainers have a few services:
Cycling Power Service (ANT+ or BT also have)
ANT+FEC (ANT only)
BTLE Fitness control (FTMS)
TACX ANT+ FEC. over Bluetooth (https://blog.lazerwalker.com/2019/02/15/bike-game-part-2.html)
Wahoo's Extension to the Cycling Power Service (to be able to set Target power for instance)
To Add Resistance to the trainer to #1, you need to check if it also has the #5 service as well. (this is the UUID used - A026E005-0A7D-4AB3-97FA-F1500F9FEB8B)
#4 is actually a protocol which Tacx came up w/ before FTMS was a standard and some trainers still use this.

Data recovery of QFSK signal in GNURadio

I'm pretty new to using GNURadio and I'm having trouble recovering the data from a signal that I've saved into a file. The signal is a carrier frequency of 56KHz with a frequency shift key of +/- 200hz at 600 baud.
So far, I've been able to demodulate the signal that looks similar to the signal I get from the source:
I'm trying to get this into a repeating string of 1s and 0s (the whole telegram is 38 bytes long and it continuously repeats). I've tried to use a clock recovery block in order to have only one byte per sample, but I'm not having much luck. Using the M&M clock recovery block, the whole telegram sometimes comes out correct, but it is not consistent. I've tried to adjust the omega and Mu values, but it doesn't seem to help that much. I've also tried using the Polyphase Clock sync, but I keep getting a runtime error of 'please specify a filter'. Is this asking me to add a tap? what tap would i use?
So I guess my overall question would be: What's the best way to get the telegram out of the demodulated fsk signal?
Again, pretty new at this so please let me know if I've missed something crucial. GNU flow graph below:
You're recovering the bit timing, but you're not recovering the byte boundaries – that needs to happen "one level higher", eg. by a well-known packet format with a defined preamble that you can look for.

reading arduino serial output line by line using redpark cable?

I'm developing an IOS app that reads Arduino serial output via redpark cable.
In the Arduino side, it uses Serial.println() to send out strings.
The string is in the format of "12.34x334.45x0.34x123x33". Essentially it's a combination of doubles with "x" in between as a special split character.
My initial thought was that in the app side, it would get the Arduino output line by line so I would just use
NSString *testString= #"12.34x334.45x0.34x123x33";
NSArray *array = [testString componentsSeparatedByString:#"x"];
to get a NSArray contains 12.34 334.45 0.34 123 and 33.
Somehow after reading questions and answers posted here, I figured out there is no way for redpark sdk to treat the Arduino output line by line, it's always in a X bytes basis.
In order to parse the Arduino output string correctly, what should i do? Would it be a good idea to add leading and tailing 0 to my double data to make the original string to be sent in a fixed length?
(i.e. "03.45x45.50x02.30" to make it 17 bytes and try to read 17 bytes of data using redpark sdk?)
The Redpark SDK only grabs the incoming serial data stream, but doesn't (despite having a few helper routines) interpret it as packets. You'll need to code that yourself. As suggested by agentatlarge in the comments to your question, read the data into a buffer using readBytesAvailable:numBytes until you get a new line character (ASCII 13), at which point you have your string to parse and can start over.
Alternatively, skip the initial string: read the incoming data until you get an "x" (at which time you add a string to an NSMutableArray) or a new line character (at which point you process the array and start a new one.
Be aware that, using the default settings (configurable in redparkSerial.h) data will be fed to you in chunks limited to 100ms (rxForwardingTimeout) or 16 bytes (rxForwardCount), whichever comes sooner. So your system will need to be able to handle multiple reads until it is certain that it has received all the data in a packet (printed line), evidenced by the arrival of the new line character.

Resources