Add Heart rate measurement service to iPhone as peripheral - iphone

I'm using Apple BLTE Transfer to emulate the iPhone as a peripheral.
My goal is to simulate a heart rate monitor that uses the heart rate measurement profile.
(I know how to generate the data but needs to define the service on the peripheral side)
I've already have a code on the other side to collect data from BLE heart rate monitors.
I need some guidance how to define the Heart rate service and it's characteristics (ON the peripheral side).
I've also seen the use of specific service UUID (180D) and some characteristics UUID's (such as 2A37 for Heart rate measurement, 2A29 for manufacturer name etc.) Where do I get those numbers? and where they are defined?
If any other information need please advise.

The heart rate service is detailed on the bluetooth developer portal.
Say you have a CBPeripheralManager named peripheralManager initialized and you already received the peripheralManagerDidUpdateState: callback with the CBPeripheralManagerStatePoweredOn state. Here is how you can set up the service itself after this.
// Define the heart rate service
CBMutableService *heartRateService = [[CBMutableService alloc]
initWithType:[CBUUID UUIDWithString:#"180D"] primary:true];
// Define the sensor location characteristic
char sensorLocation = 5;
CBMutableCharacteristic *heartRateSensorLocationCharacteristic = [[CBMutableCharacteristic alloc]
initWithType:[CBUUID UUIDWithString:#"0x2A38"]
properties:CBCharacteristicPropertyRead
value:[NSData dataWithBytesNoCopy:&sensorLocation length:1]
permissions:CBAttributePermissionsReadable];
// Define the heart rate reading characteristic
char heartRateData[2]; heartRateData[0] = 0; heartRateData[1] = 60;
CBMutableCharacteristic *heartRateSensorHeartRateCharacteristic = [[CBMutableCharacteristic alloc]
initWithType:[CBUUID UUIDWithString:#"2A37"]
properties: CBCharacteristicPropertyNotify
value:[NSData dataWithBytesNoCopy:&heartRateData length:2]
permissions:CBAttributePermissionsReadable];
// Add the characteristics to the service
heartRateService.characteristics =
#[heartRateSensorLocationCharacteristic, heartRateSensorHeartRateCharacteristic];
// Add the service to the peripheral manager
[peripheralManager addService:heartRateService];
After this you should receive the peripheralManager:didAddService:error: callback indicating the successful addition. You should add the device information service (0x180A) similarly Finally, you should start advertising with:
NSDictionary *data = #{
CBAdvertisementDataLocalNameKey:#"iDeviceName",
CBAdvertisementDataServiceUUIDsKey:#[[CBUUID UUIDWithString:#"180D"]]};
[peripheralManager startAdvertising:data];
Note: The heart rate service was the first I implemented too. Good choice. ;)

Everything regarding Gatt Specifications can be found on the Bluetooth Developer Site. What you need to do is basically this:
1.)Set up your CBPeripheralManager
2.)After it is powered on, create the CBMutableService and CBMutableCharacteristics that match the Heart rate service. Advertise them and you'll be good to go.

Related

iOS WatchOS5 - how to detect programmatically if Apple Watch was on the wrist (worn) at specific time interval?

I'm interested if there is some HealthKit or other data source I can query to know if the Apple Watch was worn/in contact with the wrist at a given time interval. Currently I'm relying on HealthKit query for HeartRate and it appears that if I get no heart rate readings within a certain window, then the watch was most likely off the wrist or charging.
Is there a better way to detect if the Apple Watch was worn on the wrist?
The problem with this method is that it is not very descriptive - if the user put on the watch at the last minute and got a measurement, this logic would consider the entire period as having the watch "On". Is there something better?
// obtain heartRateSamples from HealthKit and filter them
let hrFilterStart = startDate.addingTimeInterval(startSecondsOffset)
let hrFilterEnd = hrFilterStart.addingTimeInterval(Double(30 * 60) )
let heartRateDuringTimeSlice = heartRateSamples.filter{ sample -> Bool in
let fallsBetween = (hrFilterStart ... hrFilterEnd).contains(sample.startDate)
return fallsBetween
}
if heartRateDuringTimeSlice.count == 0 {
//watch is not on the wrist - probably charging, ignore this interval
}
HealthKit does not expose any information that you can use to reliably determine whether the Apple Watch was on-wrist. Using the presence of heart rate or other automatically collected samples will work well enough for most users, but keep in mind that there are situations where heart rate samples might not be collected at a consistent frequency even when the watch is on-wrist.

Using multiple audio devices simultaneously on osx

My aim is to write an audio app for low latency realtime audio analysis on OSX. This will involve connecting to one or more USB interfaces and taking specific channels from these devices.
I started with the learning core audio book and writing this using C. As I went down this path it came to light that a lot of the old frameworks have been deprecated. It appears that the majority of what I would like to achieve can be written using AVAudioengine and connecting AVAudioUnits, digging down into core audio level only for the lower things like configuring the hardware devices.
I am confused here as to how to access two devices simultaneously. I do not want to create an aggregate device as I would like to treat the devices individually.
Using core audio I can list the audio device ID for all devices and change the default system output device here (and can do the input device using similar methods). However this only allows me one physical device, and will always track the device in system preferences.
static func setOutputDevice(newDeviceID: AudioDeviceID) {
let propertySize = UInt32(MemoryLayout<UInt32>.size)
var deviceID = newDeviceID
var propertyAddress = AudioObjectPropertyAddress(
mSelector: AudioObjectPropertySelector(kAudioHardwarePropertyDefaultOutputDevice),
mScope: AudioObjectPropertyScope(kAudioObjectPropertyScopeGlobal),
mElement: AudioObjectPropertyElement(kAudioObjectPropertyElementMaster))
AudioObjectSetPropertyData(AudioObjectID(kAudioObjectSystemObject), &propertyAddress, 0, nil, propertySize, &deviceID)
}
I then found that the kAudioUnitSubType_HALOutput is the way to go for specifying a static device only accessible through this property. I can create a component of this type using:
var outputHAL = AudioComponentDescription(componentType: kAudioUnitType_Output, componentSubType: kAudioUnitSubType_HALOutput, componentManufacturer: kAudioUnitManufacturer_Apple, componentFlags: 0, componentFlagsMask: 0)
let component = AudioComponentFindNext(nil, &outputHAL)
guard component != nil else {
print("Can't get input unit")
exit(-1)
}
However I am confused about how you create a description of this component and then find the next device that matches the description. Is there a property where I can select the audio device ID and link the AUHAL to this?
I also cannot figure out how to assign an AUHAL to an AVAudioEngine. I can create a node for the HAL but cannot attach this to the engine. Finally is it possible to create multiple kAudioUnitSubType_HALOutput components and feed these into the mixer?
I have been trying to research this for the last week, but nowhere closer to the answer. I have read up on channel mapping and everything I need to know down the line, but at this level getting the audio at. lower level seems pretty undocumented, especially when using swift.

Confusion over CoreMIDI Destinations

Given the following code if I use the first method in the if branch to obtain a MIDIDestination the code works correctly, and MIDI data is sent. If I use the second method from the else branch, no data is sent.
var client = MIDIClientRef()
var port = MIDIPortRef()
var dest = MIDIEndpointRef()
MIDIClientCreate("jveditor" as CFString, nil, nil, &client)
MIDIOutputPortCreate(client, "output" as CFString, &port)
if false {
dest = MIDIGetDestination(1)
} else {
var device = MIDIGetExternalDevice(0)
var entity = MIDIDeviceGetEntity(device, 0)
dest = MIDIEntityGetDestination(entity, 0)
}
var name: Unmanaged<CFString>?
MIDIObjectGetStringProperty(dest, kMIDIPropertyDisplayName, &name)
print(name?.takeUnretainedValue() as! String)
var gmOn : [UInt8] = [ 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 ]
var pktlist = MIDIPacketList()
var current = MIDIPacketListInit(&pktlist)
current = MIDIPacketListAdd(&pktlist, MemoryLayout<MIDIPacketList>.stride, current, 0, gmOn.count, &gmOn)
MIDISend(port, dest, &pktlist)
In both cases the printed device name is correct, and the status of every call is noErr.
I have noticed that if I ask for the kMIDIManufacturerName property that I get different results - specifically using the first method I get Generic, from the USB MIDI interface to which the MIDI device is connected, and with the second method I get the value of Roland configured via the Audio MIDI Setup app.
The reason I want to use the second method is specifically so that I can filter out devices that don't have the desired manufacturer name, but as above I can't then get working output.
Can anyone explain the difference between these two methods, and why the latter doesn't work, and ideally offer a suggestion as to how I can work around that?
It sounds like you want to find only the MIDI destination endpoints to talk to a certain manufacturer's devices. Unfortunately that isn't really possible, since there is no protocol for discovering what MIDI devices exist, what their attributes are, and how they are connected to the computer.
(Remember that MIDI is primitive 1980s technology. It doesn't even require bidirectional communication. There are perfectly valid MIDI setups with MIDI devices that you can send data to, but can never receive data from, and vice versa.)
The computer knows what MIDI interfaces are connected to it (for instance, a USB-MIDI interface). CoreMIDI calls these "Devices". You can find out how many there are, how many ports each has, etc. But there is no way to find out anything about the physical MIDI devices like keyboards and synthesizers that are connected to them.
"External devices" are an attempt to get around the discovery problem. They are the things that appear in Audio MIDI Setup when you press the "Add Device" button. That's all!
Ideally your users would create an external device for each physical MIDI device in their setup, enter all the attributes of each one, and set up all the connections in a way that perfectly mirrors their physical MIDI cables.
Unfortunately, in reality:
There may not be any external devices. There is not much benefit to creating them in Audio MIDI Setup, and it's a lot of boring data entry, so most people don't bother.
If there are external devices, you can't trust any of the information that the users added. The manufacturer might not be right, or might be spelled wrong, for instance.
It's pretty unfriendly to force your users to set things up in Audio MIDI Setup before they can use your software. Therefore, no apps do that... and therefore nobody sets anything up in Audio MIDI Setup. It's a chicken-and-egg problem.
Even if there are external devices, your users might want to send MIDI to other endpoints (like virtual endpoints created by other apps) that are not apparently connected to external devices. You should let them do what they want.
The documentation for MIDIGetDevice() makes a good suggestion:
If a client iterates through the devices and entities in the system, it will not ever visit any virtual sources and destinations created by other clients. Also, a device iteration will return devices which are "offline" (were present in the past but are not currently present), while iterations through the system's sources and destinations will not include the endpoints of offline devices.
Thus clients should usually use MIDIGetNumberOfSources, MIDIGetSource, MIDIGetNumberOfDestinations and MIDIGetDestination, rather iterating through devices and entities to locate endpoints.
In other words: use MIDIGetNumberOfDestinations and MIDIGetDestination to get the possible destinations, then let your users pick one of them. That's all.
If you really want to do more:
Given a destination endpoint, you can use MIDIEndpointGetEntity and MIDIEndpointGetDevice to get to the MIDI interface.
Given any MIDI object, you can find its connections to other objects. Use MIDIObjectGetDataProperty to get the value of property kMIDIPropertyConnectionUniqueID, which is an array of the unique IDs of connected objects. Then use MIDIObjectFindByUniqueID to get to the object. The outObjectType will tell you what kind of object it is.
But that's pretty awkward, and you're not guaranteed to find any useful information.
Based on a hint from Kurt Revis's answer, I've found the solution.
The destination that I needed to find is associated with the source of the external device, with the connection between them found using the kMIDIPropertyConnectionUniqueID property of that source.
Replacing the code in the if / else branch in the question with the code below works:
var external = MIDIGetExternalDevice(0)
var entity = MIDIDeviceGetEntity(external, 0)
var src = MIDIEntityGetSource(entity, 0)
var connID : Int32 = 0
var dest = MIDIObjectRef()
var type = MIDIObjectType.other
MIDIObjectGetIntegerProperty(src, kMIDIPropertyConnectionUniqueID, &connID)
MIDIObjectFindByUniqueID(connID, &dest, &type)
A property dump suggests that the connection Unique ID property is really a data property (perhaps containing multiple IDs) but the resulting CFData appears to be in big-endian format so reading it as an integer property instead seems to work fine.

JTAG: How do I know the width of the Instruction Register?

Assumed I have a JTAG-chain with several devices from different manufactures:
How does my software, which shall communicate with a specific system within that chain, known the length of the IR for all the others devices within the chain? I do have to know them to send a certain instruction to my device, right?
It is possible to detect the total length of all IR registers in your JTAG daisy-chain. It is also possible to detect the number of devices (or TAPs) in your chain. But you can't detect the individual IR length of a single TAP.
What you can do: You can read out the JTAG ID code register of all of you TAPs. The ID code register (in DR path) is always 32 bit and gets selected by test-logic-reset.
With the ID code you can identify the existing TAPs and look up in the datasheet the length of the individual IR registers.
And yes: In general you do have to know the individual IR length of all the TAPs in your chain to communicate with one of them.
try here: http://www.fpga4fun.com/JTAG3.html
When IR = '1...1', the BYPASS is selected.
The idea is to send a lot of '1' so regardless of IR length all devices will select BYPASS.

How to calculate Voice and Data usage in BlackBerry 10 application

Hi I am developing an application in BlackBerry 10 platform which will calculate data usage and voice usage of user device for particular duration.
There are some of the feasibility check need to be done for this which are as follows
Does BB10 API supports data usage calculation? If yes, Can I differentiate 3G/Cellular data from WiFi data?If yes, how can I achieve this?
How can I calculate Voice usage in BB 10 application? Voice usage is nothing but duration of all calls happened within particular timespan
Is there any API BB10 provides through which I can check if device is currently in Roaming or not?
Please let me know if this can be done in BB 10 application
Does BB10 API supports data usage calculation?
Yes, there are a few for API's for this
Can I differentiate 3G/Cellular data from WiFi data?
Yurp you can.
1) Add the following line to your .pro file:
LIBS += -lbbdevice
2) Make sure you include:
#include <bb/device/NetworkDataUsage>
3) Getting data useage for cellular network only
bb::device::NetworkDataUsage *nduCell = new bb::device::NetworkDataUsage("cellular0");
nduCell ->update();
quint64 bytesSent = nduCell ->bytesSent();
quint64 bytesReceived = nduCell ->bytesReceived();
4) Getting data useage for wifi only
bb::device::NetworkDataUsage *nduWifi = new bb::device::NetworkDataUsage("tiw_sta0");
nduWifi ->update();
quint64 bytesSent = nduWifi ->bytesSent();
quint64 bytesReceived = nduWifi ->bytesReceived();
That will give your the data useage since the device has started.
You will need to call ndu->update() regularly to get the most recent data usage statistics.
Extra Info:
Changing the parameter for the NetworkDataUsage changes the interface it minitors:
cellular0 == Cellular
tiw_sta0 == Wifi
ecm0 == USB
To find out which interfaces are available on your device:
1) Add the following line to your .pro file:
QT += network
2) Make sure you include:
#include <QNetworkInterface>
3) Displaying available interfaces
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < interfaces.size(); i++) {
qDebug() << QString::number(i) + ": " + interfaces.value(i).humanReadableName();
}
How can I calculate Voice usage in BB 10 application? Voice usage is nothing but duration of all calls happened within particular timespan
This can be done using Phone class.
There is signal call void callUpdated (const bb::system::phone::Call &call, ) using which we can get to know if incoming call is received or outgoing call is initiated.
With the combination of this and Timer class we can calculate Voice usage of device. (This code is not tested)