Hi Hameed,
Related to your question about the name of services and characteristics, do you mean the human readable name?
For example, 0x180D is the reserved name for "Heart Rate Service". If this is what you mean, some services and some characteristics, when you print out the description of them, a few will include the human readable name. You're better off doing a look-up-table with the service / characteristic's CBUUID to convert to a string.
A few open source projects convey my point like this one: https://github.com/adafruit/Bluefruit_LE_Connect_Android_V2/blob/c8271518a64469350796698a84b7fb731b29f8c9/app/src/main/assets/GattUUIDs.json
If the CBUUID isn't found in your table, there would be no way to identify it. For more information about the spec/standard check out the available information on the Bluetooth org's website. I can't seem to post the URL here in the forum for some reason.
Do a search for "Bluetooth assigned numbers" or "Bluetooth GATT" and you should find yourself with the adopted list from the Bluetooth SIG.
As for extracting data, I'd refer to the Core Bluetooth Programming Guide. It is in the archive, but is still accurate.
https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/AboutCoreBluetooth/Introduction.html#//apple_ref/doc/uid/TP40013257
Post
Replies
Boosts
Views
Activity
As to why there is an unknown state:
This probably gets down into how the OS works. Both Android and iOS pull off BLE using technologies like IPC. Android uses Binders and services; iOS likely uses XPC technologies based on the log events that get printed to console when using Core Bluetooth.
https://developer.apple.com/documentation/xpc
Imagine if you have a client (CBManger) state machine and you initialize it, it wouldn't have an IPC connection yet to the Bluetooth process. The CBManagers will in fact give you an "unknown" state when you initialize them. This is just how things work. Keep listening to your delegate and you'll get another callback with the state poweredOn, poweredOff, unauthorized (iOS 13, you'll get a new privacy/permission prompt), etc. I've never seen it NOT transition to another state within moments after initializing the manager class in the last 6 years I've been using Core Bluetooth.
How is the CBManager.State property unreliable? Can you provide more details on this?
One way you could achieve this is by using CoreLocation and the beacon region monitoring APIs.
Idea:
iPad subscribed to monitoring beacon, works in background.
iPhone comes into range, foreground, advertises as beacon, wakes up iPad.
You could then use technologies like MultipeerConnectivity or straight up BLE peripheral / central roles to exchange data.
Be aware of the new location requirements of this solution, beacon region monitoring I believe requires the new allow precise location authorization.
Yes, CoreBluetooth is designed to work while the app is in the background. Be sure to check the appropriate background mode capability in your target's capabilities tab. Watch some of the old WWDC videos on Core Bluetooth. There are limitations in background, i.e. you must be scanning for one or more UUIDs--scans without CBUUID's do not invoke callbacks when the app is in the background state. Based on what you've described sounds like you'd want to check the box "Uses Bluetooth LE accessories".
As far as predictable in background goes, this is an older doc but should still apply. Please refer to the Bluetooth accessory guidelines. Take note of the advertisement intervals that are recommended to aid with background discovery.
https://developer.apple.com/accessories/Accessory-Design-Guidelines.pdf
I will make the assumption that your BLE product advertises frequently and the app would connect and then retrieve data from the device? OR your advertisement payload contains the data you're looking for?
It is always funny when you search the web and Google refers you to a post you made half a year ago. I had overlooked the time since Jan 1, 2001, which initializes to the correct date timestamp. No further hits on the phy keys...I submitted this Feedback to request the key be added to the API officially: FB7689571I'm creating a nested struct in CBPeripheral to get at the contents of the advertisementData. The advantage behind [String: Any] is that Apple can stuff what ever they want in there and it doesn't need to be in the documentation, for example the three mentioned keys in this convo. Disadvantage is we have to perform key value lookup and conditional casting. 🙂I'll post a GIST if I get around to it and will edit this reply.The PHY is related to Bluetooth 5.0 and chipset support for 2 MB PHY. I'd quote the 5.0 spec, but who wants to download 2000 page pdf and hunt and find. Punch has a good article here if you are interested in learing more about the physical layer: https://punchthrough.com/crash-course-in-2m-bluetooth-low-energy-phy/
This looks good for earlier releases. I don't know when I quit experiencing the issue, but as of iOS 13.3 I no longer see this.
Check to see the device's water rating. In addition to GPS, Series 2 also got a higher water spec.https://developer.apple.com/documentation/watchkit/wkinterfacedevice/2293683-waterresistanceratingAccording to the tech spec listings in the following URL, Series 2 and newer have a rating of wr50.https://support.apple.com/en_US/specs/applewatchSo check this property on WKInterfaceDevice, if 50 rating, then gps!Good luck.
Yes you can connect to CBPeripherals on watchOS. Check out thew WWDC video for details, I forget which year it was, but one outlined some limitations on both watch and tv if I remember correctly.Something like up-to two peripherals per system, not per app as you may expect. This would not count the iPhone, or so I would expect. Additionally the connection interval is limited to 30ms.
Did you come up with anything on this? Is your objective to determine your launch reason before returning from didFinishLaunching?My use case is to prompt the user to complete onboarding on their phone which includes several user agreements (i.e. Terms of Service and Privacy Statement). I was curious about this. Through experimentation with the simulator, I may have found a way to detect it, but I wouldn't rely on it if your timing or initialization depends on it.watchOSOn InterfaceController X, Y, or Z (activate, load, appear) do:1. Set the delegate to the WCSession.default2. Activate the session3. onActivation, send message (or on controlled event from interface)iOSIn your app delegate, immediately do:1. Set the WCSession delegate2. Activate the session3. Observe the message come inIn this test scenario, I observed that the didReceiveMessage is invoked right away in a different thread.default20:18:54.456641-0600appnameApplication-DelegatesubsystemdidFinishLaunching() options: nildefault20:18:54.468903-0600appnameApplication-DelegatesubsystemReceived message ["OnboardingRequest": 1]default20:18:54.493954-0600appnameApplication-DelegatesubsystemFinished launchingNote: The middle message was captured on a background thread (not the same thread invoking didFinishLaunching). Not ideal but it might work, as long as you account for a potential race condition nightmare.
If you're still looking for some details, Chepiok asked a similar question and I replied at length here: https://forums.developer.apple.com/thread/126051
The preferred approach would be to take an HKWorkout and then create a predicate/query to find associated route samples. I don't think it is possible to go the inverse of that.Check out this link for details: https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/reading_route_dataOut of curiosity, how are you getting references to your HKWorkoutRoute objects now?
Half the battle is knowing what classes to look for. The WWDC videos are a good start to finding your answers.TLDW, here are the things you're looking for.For discussion purposes, if you wanted to make a step counter application, that monitors progress throughout the day and sends local notifications when milestones have been met, I would take a look at one of these two long-running queries:1. https://developer.apple.com/documentation/healthkit/hkanchoredobjectquery2. https://developer.apple.com/documentation/healthkit/hkobserverqueryAs for getting the background updates, refer to: https://developer.apple.com/documentation/healthkit/hkhealthstore/1614175-enablebackgrounddeliveryJump down to the discussion and view the note, depending on the type of data you want to collect, you can get throttled."NoteSome data types, such as step counts, have a minimum frequency of HKUpdateFrequency.hourly. This frequency is enforced transparently."Make sure you're clear and up front with your user about this data you're going to collect and send to your server. Privacy is important.
You're using two different types of queries.The HKQuantitySeriesSampleQuery that is available iOS 13+ will give you different results than just the simple HKSampleQuery.1. Is the HeartRate data you are expecting to have returned recorded by your app?2. Does the Health app on the iOS 12 device show many more samples than what you're getting in your query?From your samples provided from iOS 12, looks like the recordings are every 10 minutes. This could be the standard recording from the watch, I can't remember if it was every 6, 8, or 10 minutes that samples would be recroded (when not in an active workout).
Are you running this on simulator? Sometimes the methods to change state react really slowly on sim, but not real device. I've had to wait upwards to 15 seconds when calling .stopActivity(date) on the session.
I've had some success with this. Out of curiosity, how soon after you deploy the iPhone app do you attempt to launch the watch app? I've noticed when deploying with Xcode to iPhone that the watch app isn't immediately installed. You can check this by viewing all apps and see the watch app icon fill the pie as it installs. Could this be what you were experiencing? Another trick, put both devices in airplane mode, delay, disable airplane, then use your watch to "ping" your iPhone. Seems to have done the trick sometimes too.