Updating TXTRecordDictionary doesn't always notify monitoring services - ios

I'm using bonjour to find other devices. Each device uses TXTRecordData to share its name:
NSDictionary* dictionary = #{ #"name": #"Goose" };
[service setTXTRecordData:[NSNetService dataFromTXTRecordDictionary:dictionary]];
Each device listens for changes:
- (void) netService:(NSNetService *)sender didUpdateTXTRecordData:(NSData *)data
{
...
}
About 80% of the time it works - didUpdateTXTRecordData is called when a name is changed.
Sometimes the other devices are never notified.
I've checked and setTXTRecordData returns YES when the data is lost.
How can I make sure updates to the TXTRecordData makes it to other devices?

Someone posted a gist demonstrating what is possibly the above bug.
For you Apple people out there, the gist says the relevant rdar is rdar://11018654

Related

How do you cancel a Nest ETA using Firebase on iOS?

According to the nest API docs:
"To cancel an eta, send estimated_arrival_window_begin = 0. Check that you're sending an integer (0) in this call, not a string ("0"), or the call will fail."
See https://developers.nest.com/documentation/cloud/eta-reference/
My code is based on the iOS NestDK sample which uses Firebase.
I set things up using the addSubscriptionToURL method as follows: ​
[[FirebaseManager sharedManager] addSubscriptionToURL:[NSString stringWithFormat:#"structures/%#/eta", structureId] withBlock:^(FDataSnapshot *snapshot) {}];
I can then make successful calls to set an eta window for a specific trip.
However, i can't seem to be able to cancel the eta for the same trip. If i just specify the trip_id and estimated_arrival_window_begin properties i get an error message complaining that the estimated_arrival_window_end field is missing.
NSMutableDictionary *values = [[NSMutableDictionary alloc] init];
[values setValue:[_tripId UUIDString] forKey:#"trip_id"];
[values setValue:[NSNumber numberWithInt:0] forKey:#"estimated_arrival_window_begin"];
[[FirebaseManager sharedManager] setValues:values forURL:[NSString stringWithFormat:#"structures/%#/eta", structureId]];
I tried also setting estimated_arrival_window_end to 0 but i then get an error message saying that the estimated_arrival_window_begin is in the past. It seems to be interpreting the 0 value as the beginning of time. Well some time in 1970 anyway!
What am i doing wrong here?!
Thanks!
Are you using a Nest account with virtual devices created with the Nest Home Simulator? There appears to be a bug using virtual devices versus real devices. Please try using a Nest account with real devices.

Objective-C HealthKit identify if source is from Apple iPhone or Apple Watch

I have an app where I am trying to integrate the HealthKit and pull steps related data aggregated by day using the HKStatisticsCollectionQuery. Requirement is to pull steps data specific to only iPhone and Apple Watch devices separately (no de-duplication) which have contributed to the health app.
The HKSource class only exposes the following properties:
name - Cannot be used as the user can change this to anything from just 'XXXX iPhone'
bundleIdentifier - Provides us the UUID for the device (unique per device, so different for every iPhone/Watch), and it looks like com.apple.health.UUID, here's what the Apple documentation says : "For apps, this property holds the app’s bundle identifier. For supported Bluetooth LE devices, this property holds a UUID for the device."
I am able to pull all sources (using a HKSourceQuery) which have the bundleIdentifier prefix of 'com.apple.health', but am unable to deduce which is an Apple iPhone versus which is an Apple iWatch.
Has anybody faced a similar situation before, and is there any other way to identify which source is an iPhone or Apple Watch?
Any help would be great!.Thanks!
Not the best solution but, I have figured out a way to distinguish between the watch and the phone using the following process:
I noticed that all step data coming from the iPhone/Watch have the following bundleIdentifier format:
com.apple.health.DeviceUUID
Note that manually entered data into the Health app has a bundle identifier of com.apple.Health (with a capital 'H').
So, first thing, get the device name for the phone using:
NSString *deviceName = [[UIDevice currentDevice] name];
Next, fetch all the sources for which there is a prefix match of 'com.apple.health' in the bundleIdentifier. This should give you the iPhone and the Apple watch as the valid sources and ignore the manual entries and all other apps.
Next, check if the name of the device is the same in the source, then its your iPhone, the other source should be your Apple Watch.
Here's a sample source query for fetching the sources :
- (void)fetchSources
{
NSString *deviceName = [[UIDevice currentDevice] name];
NSMutableArray *dataSources = [[NSMutableArray alloc] init];
HKQuantityType *stepsCount = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
HKSourceQuery *sourceQuery = [[HKSourceQuery alloc] initWithSampleType:stepsCount
samplePredicate:nil
completionHandler:^(HKSourceQuery *query, NSSet *sources, NSError *error)
{
for (HKSource *source in sources)
{
if ([source.bundleIdentifier hasPrefix:sourceIdentifier])
{
if ([source.name isEqualToString:deviceName])
// Iphone
else
// Apple Watch
[dataSources addObject:source];
}
}
}];
[self.healthStore executeQuery:sourceQuery];
}
You can now create a predicate with each source for your data pull using the NSPredicate class:
NSPredicate *sourcesPredicate = [HKQuery predicateForObjectsFromSource:source];
Note that my first thought was to match the UUID, but when I generate a UUID using the NSUUID class, it does not match with the one present in the bundle identifier in the pulled sources.
Also, you can change the name of the phone to whatever you want, it will automatically update in the Health app as well.
As I said, not the best solution but works for me, and it's the only way I could find to do this. Please let me know if you were able to find a better solution. Thanks.

What's CTSubscriber (and how to use it) on iOS 7?

On iOS 7, CTSubscriber was added to the CoreTelephony framework. There is no documentation available, only its header file:
/*
* CTSubscriberTokenRefreshed
*
* Description:
* The name of the NSNotification sent when the carrier token is available.
*/
CORETELEPHONY_EXTERN NSString * const CTSubscriberTokenRefreshed __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);
CORETELEPHONY_CLASS_AVAILABLE(7_0)
#interface CTSubscriber : NSObject
/*
* carrierToken
*
* Description:
* A data blob containing authorization information about the subscriber.
*
* May return nil if no token is available.
*/
#property (nonatomic, readonly, retain) NSData* carrierToken __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);
#end
Also, on What's new on iOS 7, this is mentioned:
The Core Telephony framework (CoreTelephony.framework) lets you get information about the type of radio technology in use by the device. Apps developed in conjunction with a carrier can also authenticate against a particular subscriber for that carrier.
I think that CTSubscriber is related to the bold part of the text. However, I haven't found anything related on how this happens.
I have tried to use the following code (added to application:didFinishLaunchingWithOptions:) to experiment with this API, but the notification is never fired and carrierToken returns nil:
CTSubscriber *subscriber = [CTSubscriberInfo subscriber];
NSLog(#"%#", subscriber.carrierToken);
[[NSNotificationCenter defaultCenter] addObserverForName:CTSubscriberTokenRefreshed object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
NSLog(#"==========");
NSLog(#"%#", note);
NSLog(#"%#", subscriber.carrierToken);
}];
So, I have the following questions:
What exactly ("authorization information") does carrierToken return and how to make it not nil?
How does Apple know if your app is "developed in conjunction with a carrier"?
Is this how Evernote is giving 1 year of premium account to Telefonica users (http://blog.evernote.com/blog/2013/08/13/evernote-and-telefonica-announce-global-partnership/)? (Probably not, since the information they need can be obtained on CTCarrier)
I asked the same question in the developer forums and got this reply :
You should escalate this via the carrier you're working with, who can in turn escalate it to their contact at Apple.
Link to the thread: https://devforums.apple.com/message/934226#934226
The reason you can’t find any documentation is because much of Core Telephony consists of private APIs. Consequently, there isn’t any way to access the SIM card from an app published on the App Store. A jailbroken device is, of course, another story, but in that case you’re pretty much on your own.
Edit:
The Core Telephony framework (CoreTelephony.framework) lets you get
information about the type of radio technology in use by the device.
Apps developed in conjunction with a carrier can also authenticate
against a particular subscriber for that carrier.

Saving Roster for Offline/Disconnects proposes

I downloaded the SampleProject off XMPPFramework for iOS and connected it already to my Jabber Server. Everything ok.
But I would like to have my Buddys to stay in the Buddys overview even if I have been disconnected (Connection lost). Is that possible? As I understood the XMPPCoreStorage save them in CoreData. Why do it get cleaned at a disconnect? Is it possible to disable the clean at disconnect? I unfornatly didnt found the method.
Would be really annoying & much traffic if it isnt persistent or?
Any help would be great!
So I came up with a solution:
On the XMPPRoster.m xmppStreamDidDisconnect:
i commented 4 lines out. It looks now like this:
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
// This method is invoked on the moduleQueue.
XMPPLogTrace();
// [xmppRosterStorage clearAllUsersAndResourcesForXMPPStream:xmppStream];
//
// [self _setRequestedRoster:NO];
// [self _setHasRoster:NO];
//
// [earlyPresenceElements removeAllObjects];
}
So it will not clear the storage on a disconnect. On a reconnect it will clean and refill the storage with updated information. Hope it helps other people. Its not a perfect solution . A preffered one is to build your own CoreData model & fetch the XMPP stuff in there..

Bluetooth peripheral doesn't answer

I am in big trouble with my exams.
I have to write an iOS app that uses an external sensor made by Texas Instruments, it's called TI Sensortag.
TI's documentation, in my humble opinion, is really poor and complicated to understand for an entry level programmer.
I tried to ask in the E2E forum but they weren't able to help me, their answer was something like "Um, well, we don't know, go away and ask someone else", ...
I added the CoreBluetooth framework to my project an created a CentralManager. I am able to find my device, connect and get his name and (sometimes) his RSSI.
Now what I'm trying to do is to ask my CBPeripheral object if it has some services for me or something like that. I've found the Complete Attribute Table but I have no idea how to use it...
I know I have to activate some services or something like that but I really don't now ho to do it, I googled a lot but I've not found something helpful...
I'm trying to enable my sensor with this method, but I'm doing something wrong.
-(void) configureSensorTag
{
uint8_t myData = 0x01;
NSData *data = [[NSData alloc] initWithBytes:&myData length:1];
[BLEUtility writeCharacteristic:myPer sUUID:#"F000AA00-0451-4000-B000-000000000000" cUUID:#"F000AA02-0451-4000-B000-000000000000" data:data];
[BLEUtility setNotificationForCharacteristic:myPer sUUID:#"F000AA00-0451-4000-B000-000000000000" cUUID:#"F000AA01-0451-4000-B000-000000000000" enable:YES];
NSLog(#"Configured TI SensorTag IR Termometer Service profile");
}
Moreover I'm trying to retrive Sensortag's services with this method
[peripheral discoverServices:nil];
and his delegate
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
NSLog(#"Found service");
if (error) {
NSLog(#"Error: %#", error);
}
}
but it is never called.
Has someone any idea?
Thank you very much!
Unfortunately I can't help you with the details of the iOS, but I can help you with understanding the sensor tag. If you look at that attribute PDF you linked you'll find entries marked "GATT_CLIENT_CHAR_CFG_UUID". It's 16 bits of flags where only the 2 least significant bits are used. It even says in there 'Write "01:00" to enable notifications, "00:00" to disable'. (That's the least significant bit because it's encoded in little-endian format)
So, you're sending a 0x01 to turn on the IR temperature sensor, but you haven't turned on the notifications. Turning it on will then cause the device to stream notifications back to the client. The accelerometer doesn't require turning on, so maybe you should try that first.
I have no idea what that second chunk of code is supposed to be doing... sorry.
Ok ok I got it,
there were any software problem, I mean, not by iOS side.
Sensortag has a wrong firmware and so it did'n work.
I've changed Sensortag and now everything works fine.
Thank you anyway!

Resources