I'm currently building an app that turns my device into a Beacon while simultaneously scanning for other Beacons.
So I can keep track of beacons that I had come in contact with.
Problem
Current I've tested this code in the following Scenarios:
Android TO Android - Broadcasting & Scanning - Working well
Android To IOS - BroadCasting & Scanning Both ways - Working well
IOS to IOS - Not Working (When I broadcast UUID from IOS Device, I can see UUID in Android device but I can't see UUID in any IOS device.)
I installed this piece of code in 4 devices (2 Android & 2 IOS). Now all 4 devices are broadcasting different UUID's and at the same time listening.
In Android Devices, I see 1 UUID of another Android Device and 2 UUID's of IOS Devices
In IOS Devices, I see 2 Android UUID's but I cannot see another IOS Device UUID.
This is very strange, and I need help to solve this, please!
I've currently implemented 2 packages to achieve this functionality :
(1) For broadcast
beacon_broadcast: https://pub.dev/packages/beacon_broadcast
version : 0.2.1
(2) For scan other beacons
flutter_blue: https://pub.dev/packages/flutter_blue
version : 0.6.3+1
These are some glimpse of my code
(1) For Broadcasting
String UUID = 'DYNAMIC_UUID_FOR_EACH_DEVICE';
static const MAJOR_ID = 1;
static const MINOR_ID = 30;
static const TRANSMISSION_POWER = -59;
static const IDENTIFIER = 'com.example.myDeviceRegion';
static const LAYOUT = 'm:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24';
static const MANUFACTURER_ID = 0x004c;
BeaconBroadcast beaconBroadcast = BeaconBroadcast();
beaconBroadcast
.setUUID(UUID)
.setMajorId(MAJOR_ID)
.setMinorId(MINOR_ID)
.setTransmissionPower(TRANSMISSION_POWER)
.setIdentifier(IDENTIFIER)
.setLayout(LAYOUT)
.setManufacturerId(MANUFACTURER_ID);
.start();
(2) For Scanning
FlutterBlue flutterBlue = FlutterBlue.instance;
flutterBlue.startScan(timeout: Duration(seconds: 30));
flutterBlue.scanResults.listen((List<ScanResult> results) {
print('scanningListen...');
for (ScanResult result in results) {
result.advertisementData.manufacturerData.forEach((item, hexcodeAsArray) => {
print("calculated UUID String : " + calculateHexFromArray(v));
_addToScanResult(calculateHexFromArray(v));
});
}
}
String calculateHexFromArray(decimalArray) {
String uuid = '';
decimalArray.forEach((i) => {uuid += i.toRadixString(16).padLeft(2, '0')});
String uuid1 = uuid.substring(4, uuid.length - 12);
return uuid1.toUpperCase();
}
Unfortunately, you cannot use FlutterBlue to detect iBeacon packets on iOS.
Why? FlutterBlue uses raw bluetooth scanning to detect beacons, which under the hood means using the native CoreBluetooth scanning APIs on iOS. Apple blocks CoreBluetooth APIs from reading the raw bytes of any bluetooth advertisement decodable as an iBeacon advertisement. While this may sound crazy, it is likely motivated by misguided security concerns by Apple. Read more in my blog post here: CoreBluetooth Doesn't Let You See iBeacons
Two options to fix this:
Switch to using the AltBeacon format. Simply change LAYOUT = 'm:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25'; and MANUFACTURER_ID = 0x0118;
This will work, but has the disadvantage of the advertisement only being detectable on iOS in the foreground.
Switch to using a different detection library on iOS that uses CoreLocation (the only API allowed to detect iBeacon on iOS) instead of CoreBluetooth. That means giving up FlutterBlue in favor of FlutterBeacon or similar.
Related
In Android API level 26, "setScannable" is added.
"setScannable" Added in API level 26
public AdvertisingSetParameters.Builder setScannable (boolean scannable)
Set whether the advertisement type should be scannable. Legacy advertisements can be both connectable and scannable. Non-legacy advertisements can be only scannable or only connectable.
I am creating a beacon and want to set it non-scannable mode.
Just wondering if the latest Altbeacon Lib. v2.16.2 support this setting? If not, is there a way to use Android API and Altbeacon Lib. together to set a beacon's advertising parameters?
Thanks!
Tried Altbeacon Lib. v2.15.2, it seems that Android API level 26 is not support, which means that "setScannable" is not available.
String id1 = "3b710c27-acf7-4225-8753-4aca354f5bec"; // UUID
String id2 = "1";
String id3 = "2";
Beacon beacon = new Beacon.Builder()
.setId1(id1)
.setId2(id2)
.setId3(id3)
.setManufacturer(0x01F1)
.setTxPower(iTxPower)
.setDataFields(Arrays.asList(new Long[] {0l}))
.build();
BeaconParser beaconParser = new BeaconParser().
setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
BeaconTransmitter beaconTransmitter = new
BeaconTransmitter(getApplicationContext(), beaconParser);
beaconTransmitter.startAdvertising(beacon);
...
I would hope Altbeacon Lib. v2.16.2 could support Android API Level 26 so that "setScannable" is supported.
There is no such configuration ability in the 2.16.2 version of the library. It is logged as a feature request here:
https://github.com/AltBeacon/android-beacon-library/issues/813
This would not be difficult to add if you would like to work on that feature request. Please comment on that linked page above, if so, and I can give you guidance on what to do.
I'm writing my code using Xamarin. I'm developing my IOS app which allows me to read the BLE devices, Services, characteristic value and activation of the notification.
My BLE beacon have one custom Services that contain two custom characteristics and both have the notification implemented using CCCD.
My ble devices work correctly I test it with BLE scanner app and it working well without any problem.
I can read value and I can active the notification for both characteristic. See picture here.
The app that I wrote using xamarin work correctly (reading services, characteristic value....) the only problem that didn't work is the activation of the notification. Here's a portion of the code :
public UUID Charac_UUID0 = UUID.FromString("0000beef-1212-efde-1523-785fef13d123");
public UUID Charac_UUID = UUID.FromString("0000b1e0-1212-efde-1523-785fef13d123") ;
public UUID Descr_UUID = UUID.FromString("00002902-1212-efde-1523-785fef13d123");
protected BluetoothGattCharacteristic _charac;
....
....
this._charac = App.Current.State.SelectedService.GetCharacteristic(Charac_UUID0);
BluetoothLEManager.Current.ConnectedDevices[App.Current.State.SelectedDevice].SetCharacteristicNotification(_charac, true);
BluetoothGattDescriptor descriptor = _charac.GetDescriptor(Descr_UUID0);
descriptor.SetValue(BluetoothGattDescriptor.EnableNotificationValue.ToArray());
BluetoothLEManager.Current.ConnectedDevices[App.Current.State.SelectedDevice].WriteDescriptor(descriptor);
The code always give me an error at descriptor.SetValue and it indicate me that the descriptor is NULL meaning that _charac.GetDescriptor didn't return any value.
I suspect the Descriptor UUID value (Descr_UUID) is not correct. I don't know excatly how can I determine the Descr_UUID but I saw many example in the internet of people replacing the custom UUID of the caracteristic by 2902 which give me in my case a 128 descriptor UUID equal to 00002902-1212-efde-1523-785fef13d123.
But there is a problem here. The descriptor UUID for both characteristic will be the same because the base UUID is the same for both characteristic?
Any solution?
3 years later im sure you figured it out but, 2902 is the 16 bit value for a Client Characteristic Configuration Descriptor, and I believe it should also be inflated using the "BASE UUID" not just whatever your characteristic descriptor uses. See this: answer
This will convert your 16 (or 32) bit uuids to full 128 bit uuids using the BASE UUID:
public static UUID ConvertUuid(uint uuid)
{
const long msbMask = 0x0000000000001000;
const ulong lsb = 0x800000805f9b34fb;
var msb = msbMask | ((ulong)(uuid & uint.MaxValue) << 32);
return new UUID((long)msb, unchecked((long)lsb));
}
After successfully detecting iBeacons from the Esimote SDK, I started working with Eddystone beacons in the same SDK with help of
<EstimoteSDK/ESTEddystone.h>
I provided namespace id in ESTEddystoneFilterUID object as below and then started discovering beacons from startEddystoneDiscoveryWithFilter method.
ESTEddystoneUID *eddystoneUID = [[ESTEddystoneUID alloc] initWithNamespaceID:#"0x2f234454f4911ba9ffa6" instanceID:#"1"];
self.uidFilter = [[ESTEddystoneFilterUID alloc] initWithUID:eddystoneUID];
[self.eddystoneManager startEddystoneDiscoveryWithFilter:self.uidFilter];
Later I came to the delegate eddystoneManager:didDiscoverEddystones:withFilter , with empty eddystones array.
Is there any thing missing? Can anyone please help to get UUID/Name space of beacon in range.
You should skip the 0x part in your Namespace ID, Estimote SDK already expects a hex-encoded string. (i.e., you should use 2f234454f4911ba9ffa6)
I’m currently writing an iOS app that passes strings to the Arduino via Bluetooth Low Energy (BLE). I’m using RedBearLab’s BLE shield and my code for iOS and Arduino are based on their open source code from their GitHub https://github.com/RedBearLab/iOS.
The problem I’m having is I don’t know how to store the NSData that I sent from my iOS app via BLE to a variable in my Arduino’s sketch.
Here is my iOS code:
#import “BLE.h” // from RedBearLab’s Github
- (IBAction)sendText:(id)sender
{
NSData *textInput = [self.textField.text dataUsingEncoding:NSUTF8StringEncoding];
if (ble.activePeripheral.state == CBPeripheralStateConnected) {
[ble write:textInput]; // ble is a object that follows the CoreBluetooth protocol written by RedBearLab
NSLog(#"Date sent..");
}
}
Here you can find the write:(NSData *)d method from the BLE.m
My Arduino has no problem receiving my textInput. Now let say my textInput is “Hello”. Arduino’s serial monitor will show the following message when I run the Arduino’s sketch provided by RedBearLab SimpleChat.ino:
Evt Device Started: Standby
Advertising started
Evt Connected
Evt Pipe Status
Evt Pipe Status
Pipe Number: 2
Hello // <--------my inputString
Evt link connection interval changed
So by looking at the serial monitor, my Arduino have no problem receiving my NSData from my iOS app. However, I have no idea how to store Hello into a variable (preferably a char[]) so I could put it into another function in my own Arduino sketch. If you look at the SimpleChat.ino, the program has a line which is Serial.write(ble_read());. I know I have to store the result of ble_read() into a variable, but I have no idea what type I should use to store the variable. According to the ble_shield.cpp, the ble_read() function returns a int, but what I really want is something like char[] so it can represent the textInput. Can someone familiar with C and Arduino help me out? Thanks.
I am looking to connect my phone to my Google Glass and transfer data (photos, text, etc.) between the two.
I was thinking of using Bluetooth LTE but as I understand it, Glass does not support it because it is only running version 4.0.3 (or similar) of Android.
I know you can connect the phone and glass via the myGlass app, so clearly, what I am looking to do is possible. However, I was wondering if someone could point me in the right direction to get started? Specifically, what technologies should I look at if not CoreBluetooth on the iOS side? Has anyone else done this?
Also, if it would be better served to use Bonjour, or even to create the hotspot on my iPhone and connect that way, any tutorials you could point me to would be great.
Thanks in advance.
I'm writing a Google Glass Development book for Apress and just finished the chapter Network and Bluetooth, with some working samples to let Glass communicate with iPhone for data transfer. You're right that Glass as of now (API level 15) doesn't support Bluetooth Low Energy (BLE). I have implemented three ways to make the data transfer between Glass and iOS happen:
Let Glass talk to an Android device, such as Nexus 7 with Android 4.3 or above with BLE support, via Classic Bluetooth or socket, and Nexus 7 acts as a BLE central to talk to iOS as a BLE peripheral. Notice you shouldn't use BLE to send large data such as photo.
Let Glass talk to iOS directly via socket - you can use C socket code running as a server and Glass Java socket client, or vice versa. This would require your Glass and iOS device on the same Wifi, but can transfer large data.
Use a server-based solution - upload data from Glass to a server and let iOS get it via Apple Push Notification. I used this method to share photos on Glass with friends on WhatsApp and WeChat, both apps run on iOS.
Sample iOS code acting as socket server:
- (void) runSocketServer {
int listenfd = 0;
__block int connfd = 0;
struct sockaddr_in serv_addr;
__block char sendBuff[1025];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(6682);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
int count = 1;
while (count++ < 120) {
char rate[100];
sprintf(rate, "%i\n", bpm);
write(connfd, rate, strlen(rate));
sleep(1);
}
close(connfd);
});
}
Sample Glass code acting as a socket client:
public void run()
{
String serverName = "192.168.1.11";
int port = 6682;
try
{
socket = new Socket(serverName, port);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
do {
result = input.readLine();
runOnUiThread(new Runnable() {
public void run() {
mTvInfo.setText(result);
}
});
} while (result != null);
});
}
catch(Exception e) {
try { socket.close(); }
catch (Exception e2) {};
e.printStackTrace();
}
}
Have you tried setting up Google backup? You can instantly get your pictures from glass and view them on your phone (but not vice versa).
Otherwise, there is currently no way on the market for this, but here are a couple of ideas:
You could submit it as an app idea to one of these:
http://glass-apps.org/google/glass-app-ideas
https://plus.google.com/communities/107405100380970813362/stream/b18a5f3c-e170-40a8-991f-823f018e75af
Or you could build it yourself. The GDK is pretty powerful. You can't submit gdk apps to Google yet, but it would be great for personal use. This guy started working on it and his github is here:
https://github.com/NathanielWaggoner/GoogleGlassBlutooth