Skip to content
This repository was archived by the owner on Jul 20, 2025. It is now read-only.

Commit 4f3d92d

Browse files
author
Stephen Schiffli
committed
Merge branch 'release-2.8.2'
2 parents 6a4c6d6 + 28eca4f commit 4f3d92d

File tree

166 files changed

+12825
-13872
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

166 files changed

+12825
-13872
lines changed

Docs/gen_api_reference.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
appledoc -p "MetaWear iOS/macOS/tvOS API 2.8.1" --project-version "2.8.1" -c "MBIENTLAB INC" --company-id com.mbientlab --no-create-docset --no-repeat-first-par --ignore .m -o . ../MetaWear/Classes
1+
appledoc -p "MetaWear iOS/macOS/tvOS API 2.8.2" --project-version "2.8.2" -c "MBIENTLAB INC" --company-id com.mbientlab --no-create-docset --no-repeat-first-par --ignore .m -o . ../MetaWear/Classes
22
open html/index.html
33

44
make html

Docs/source/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@
5555
# built documents.
5656
#
5757
# The short X.Y version.
58-
version = '2.8.1'
58+
version = '2.8.2'
5959
# The full version, including alpha/beta/rc tags.
60-
release = '2.8.1'
60+
release = '2.8.2'
6161

6262
# The language for content autogenerated by Sphinx. Refer to documentation
6363
# for a list of supported languages.

Docs/source/metawear_manager.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ It's simple to start scanning for advertising MetaWear devices using the `MBLMet
2121

2222
::
2323

24-
[[MBLMetaWearManager sharedManager] startScanForMetaWearsAllowDuplicates:NO handler:^(NSArray *array) {
24+
[[MBLMetaWearManager sharedManager] startScanForMetaWearsAllowDuplicates:NO handler:^(NSArray<MBLMetaWear *> *array) {
2525
for (MBLMetaWear *device in array) {
2626
NSLog(@"Found MetaWear: %@", device);
2727
}
@@ -39,7 +39,7 @@ This feature is handy because the ``discoveryTimeRSSI`` property on the discover
3939
static const int MAX_ALLOWED_RSSI = -15; // The RSSI calculation sometimes produces erroneous values, we know anything above this value is invalid
4040
static const int MIN_ALLOWED_RSSI = -45; // Depending on your specific application this value will change!
4141
42-
[[MBLMetaWearManager sharedManager] startScanForMetaWearsAllowDuplicates:YES handler:^(NSArray *array) {
42+
[[MBLMetaWearManager sharedManager] startScanForMetaWearsAllowDuplicates:YES handler:^(NSArray<MBLMetaWear *> *array) {
4343
for (MBLMetaWear *device in array) {
4444
// Reject any value above a reasonable range
4545
if (device.discoveryTimeRSSI.integerValue > MAX_ALLOWED_RSSI) {

MetaWear.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'MetaWear'
3-
s.version = '2.8.1'
3+
s.version = '2.8.2'
44
s.license = { :type => 'Commercial', :text => 'See https://www.mbientlab.com/terms/', :file => 'LICENSE' }
55
s.homepage = 'https://mbientlab.com'
66
s.summary = 'iOS/macOS/tvOS API and documentation for the MetaWear platform'

MetaWear/Classes/Core/MBLConstants.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
@class MBLAccelerometerData;
3939
@class MBLDeviceInfo;
4040
@class MBLFirmwareBuild;
41+
@class MBLMetaWear;
4142

4243
#if TARGET_OS_IOS || TARGET_OS_TV
4344
#import <UIKit/UIKit.h>
@@ -71,7 +72,8 @@ typedef NS_ENUM(uint8_t, MBLFirmwareVersion) {
7172
MBLFirmwareVersion1_2_4,
7273
MBLFirmwareVersion1_2_5,
7374
MBLFirmwareVersion1_3_0,
74-
MBLFirmwareVersion1_3_1
75+
MBLFirmwareVersion1_3_1,
76+
MBLFirmwareVersion1_3_2
7577
};
7678
NSString *MBLFirmwareVersionString(MBLFirmwareVersion version);
7779

@@ -85,14 +87,14 @@ typedef NS_ENUM(uint8_t, MBLModel) {
8587
MBLModelMetaWearRPro,
8688
MBLModelMetaWearC,
8789
MBLModelMetaWearCPro,
88-
MBLModelMetaWearCEnv,
89-
MBLModelMetaWearCDet,
90-
MBLModelMetaWearHR,
91-
MBLModelMetaWearPPG,
90+
MBLModelMetaEnvironment,
91+
MBLModelMetaDetector,
92+
MBLModelMetaHealth,
9293
MBLModelMetaTracker,
9394
MBLModelMetaMotionR,
9495
MBLModelMetaMotionC
9596
};
97+
NSString *MBLModelString(MBLModel model);
9698

9799
/**
98100
Verbosity of log messages coming from the MetaWear SDK
@@ -122,7 +124,7 @@ typedef void (^MBLVoidHandler)();
122124
typedef void (^MBLErrorHandler)(NSError *__nullable error);
123125
typedef void (^MBLDataHandler)(NSData *__nullable data, NSError *__nullable error);
124126
typedef void (^MBLObjectHandler)(id __nullable obj, NSError *__nullable error);
125-
typedef void (^MBLArrayHandler)(NSArray *__nonnull array);
127+
typedef void (^MBLArrayHandler)(NSArray<MBLMetaWear *> *__nonnull array);
126128
typedef void (^MBLArrayErrorHandler)(NSArray *__nullable array, NSError *__nullable error);
127129
#pragma clang diagnostic push
128130
#pragma clang diagnostic ignored "-Wdeprecated-declarations"

MetaWear/Classes/Core/MBLConstants.m

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#import "MBLConstants.h"
3737
#import "MBLConstants+Private.h"
3838

39-
NSString *const kMBLAPIVersion = @"2.8.1";
39+
NSString *const kMBLAPIVersion = @"2.8.2";
4040

4141
NSString *MBLFirmwareVersionString(MBLFirmwareVersion version)
4242
{
@@ -71,6 +71,38 @@
7171
return @"1.3.0";
7272
case MBLFirmwareVersion1_3_1:
7373
return @"1.3.1";
74+
case MBLFirmwareVersion1_3_2:
75+
return @"1.3.2";
76+
}
77+
}
78+
79+
NSString *MBLModelString(MBLModel model)
80+
{
81+
switch (model) {
82+
case MBLModelUnknown:
83+
return @"Unknown";
84+
case MBLModelMetaWearR:
85+
return @"MetaWear R";
86+
case MBLModelMetaWearRG:
87+
return @"MetaWear RG";
88+
case MBLModelMetaWearRPro:
89+
return @"MetaWear RPro";
90+
case MBLModelMetaWearC:
91+
return @"MetaWear C";
92+
case MBLModelMetaWearCPro:
93+
return @"MetaWear CPro";
94+
case MBLModelMetaEnvironment:
95+
return @"MetaEnvironment";
96+
case MBLModelMetaDetector:
97+
return @"MetaDetector";
98+
case MBLModelMetaHealth:
99+
return @"MetaHealth";
100+
case MBLModelMetaTracker:
101+
return @"MetaTracker";
102+
case MBLModelMetaMotionR:
103+
return @"MetaMotion R";
104+
case MBLModelMetaMotionC:
105+
return @"MetaMotion C";
74106
}
75107
}
76108

MetaWear/Classes/Core/MBLEvent.m

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#import "MBLConversion.h"
4343
#import "MBLConstants+Private.h"
4444
#import "BFTask+MBLPrivate.h"
45+
#import "MBLDeviceInfo.h"
4546

4647

4748
@interface MBLEvent ()
@@ -503,8 +504,13 @@ - (MBLFilter *)periodicSampleOfEvent:(uint32_t)periodInMsec
503504

504505
deltat_param_t params = {0};
505506
params.filter_id = 8;
506-
params.datalen = self.format.length - 1;
507-
params.filter_mode = 0;
507+
if (self.module.device.dataProcessor.moduleInfo.moduleRevision == 0) {
508+
params.datalen = self.format.length - 1;
509+
params.filter_mode = 0;
510+
} else {
511+
params.datalen = 7; // This is now ignored by passthrough output mode
512+
params.filter_mode = 2;
513+
}
508514
uint32_t *tmp = (uint32_t *)params.deltat_ms;
509515
*tmp = periodInMsec;
510516

MetaWear/Classes/Core/MBLMetaWear.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ typedef NS_ENUM(NSInteger, MBLConnectionState) {
262262
if you wish to change the advertised name, max 8 characters!
263263
*/
264264
@property (nonatomic) NSString *name;
265+
/**
266+
The model of this MetaWear. This is only valid after a successful connection!
267+
@see MBLModelString for turning this into a friendly string
268+
*/
269+
@property (nonatomic) MBLModel model;
265270

266271
///----------------------------------
267272
/// @name Connect/Disconnect
@@ -287,6 +292,13 @@ typedef NS_ENUM(NSInteger, MBLConnectionState) {
287292
*/
288293
- (BFTask<MBLMetaWear *> *)disconnectAsync;
289294

295+
/**
296+
Create a task that will complete once this device disconnects, either expectedly
297+
or unexpectedly. This is useful for observing unexpected disconnects and
298+
automatically issing a re-connect request or otherwise updating the UI.
299+
*/
300+
- (BFTask<MBLMetaWear *> *)waitForDisconnect;
301+
290302
///----------------------------------
291303
/// @name Remember/Forget
292304
///----------------------------------
@@ -361,7 +373,7 @@ typedef NS_ENUM(NSInteger, MBLConnectionState) {
361373
/// @name Debug and Testing Utilities
362374
///----------------------------------
363375

364-
/*
376+
/**
365377
This causues the device to immediately disconnect with an error. Useful for testing
366378
error handling flows.
367379
*/

MetaWear/Classes/Core/MBLMetaWear.m

Lines changed: 90 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ - (instancetype)initWithPeripheral:(id<MBLBluetoothPeripheral>)peripheral
218218
self.identifier = peripheral.identifier;
219219
self.nameImpl = peripheral.name;
220220
self.discoveryTimeRSSI = RSSI;
221+
self.model = MBLModelUnknown;
221222

222223
self.state = MBLConnectionStateDisconnected;
223224

@@ -528,6 +529,7 @@ - (BFTask *)resetModulesAsync
528529
self.photometer ? self.photometer : [NSNull null],
529530
self.proximity ? self.proximity : [NSNull null],
530531
self.sensorFusion ? self.sensorFusion : [NSNull null]];
532+
self.model = [self calculateModelType];
531533

532534
// Save this as the reset state of the device
533535
// Do this on the bleQueue so that we don't process events while the save state is happening
@@ -616,7 +618,7 @@ - (BFTask *)setConfigurationAsync:(id<MBLRestorable>)configuration
616618
[self removeResetFile];
617619

618620
// When the disconnect occurs we know the device has been cleared and is ready for a fresh programming
619-
[[self waitForDisconnection] continueOnMetaWearWithBlock:^id _Nullable(BFTask * _Nonnull t) {
621+
[[self waitForDisconnect] continueOnMetaWearWithBlock:^id _Nullable(BFTask * _Nonnull t) {
620622
// Reconnect if we need to program the beast
621623
if (configuration) {
622624
[[[self connectAsync] success:^(id _Nonnull result) {
@@ -768,7 +770,7 @@ - (BFTask *)disconnectAsync
768770
switch (self.state) {
769771
case MBLConnectionStateConnected:
770772
{
771-
BFTask *task = [self waitForDisconnection];
773+
BFTask *task = [self waitForDisconnect];
772774
[[self waitForCommandCompletion] continueOnMetaWearWithBlock:^id _Nullable(BFTask * _Nonnull t) {
773775
self.state = MBLConnectionStateDisconnecting;
774776
[[MBLMetaWearManager sharedManager] disconnectMetaWear:self fromPeripheralSide:YES];
@@ -780,22 +782,63 @@ - (BFTask *)disconnectAsync
780782
case MBLConnectionStateDiscovery:
781783
{
782784
self.state = MBLConnectionStateDisconnecting;
783-
BFTask *task = [self waitForDisconnection];
785+
BFTask *task = [self waitForDisconnect];
784786
[[self waitForCommandCompletion] continueOnMetaWearWithBlock:^id _Nullable(BFTask * _Nonnull t) {
785787
[[MBLMetaWearManager sharedManager] disconnectMetaWear:self fromPeripheralSide:NO];
786788
return nil;
787789
}];
788790
return task;
789791
}
790792
case MBLConnectionStateDisconnecting:
791-
return [self waitForDisconnection];
793+
return [self waitForDisconnect];
792794
case MBLConnectionStateDisconnected:
793795
return nil;
794796
}
795797
}];
796798
}
797799

798-
- (BFTask *)waitForDisconnection
800+
- (MBLModel)calculateModelType
801+
{
802+
if ([self.deviceInfo.modelNumber isEqualToString:@"0"]) {
803+
return MBLModelMetaWearR;
804+
} else if ([self.deviceInfo.modelNumber isEqualToString:@"1"]) {
805+
if (self.modules) {
806+
if (self.barometer) {
807+
return MBLModelMetaWearRPro;
808+
} else {
809+
return MBLModelMetaWearRG;
810+
}
811+
} else {
812+
return MBLModelUnknown;
813+
}
814+
} else if ([self.deviceInfo.modelNumber isEqualToString:@"2"]) {
815+
if (self.modules) {
816+
if (self.proximity) {
817+
return MBLModelMetaDetector;
818+
} else if (self.hygrometer) {
819+
return MBLModelMetaEnvironment;
820+
} else if (self.magnetometer) {
821+
return MBLModelMetaWearCPro;
822+
} else {
823+
return MBLModelMetaWearC;
824+
}
825+
} else {
826+
return MBLModelUnknown;
827+
}
828+
} else if ([self.deviceInfo.modelNumber isEqualToString:@"3"]) {
829+
return MBLModelMetaHealth;
830+
} else if ([self.deviceInfo.modelNumber isEqualToString:@"4"]) {
831+
return MBLModelMetaTracker;
832+
} else if ([self.deviceInfo.modelNumber isEqualToString:@"5"]) {
833+
return MBLModelMetaMotionR;
834+
} else if ([self.deviceInfo.modelNumber isEqualToString:@"6"]) {
835+
return MBLModelMetaMotionC;
836+
} else {
837+
return MBLModelUnknown;
838+
}
839+
}
840+
841+
- (BFTask<MBLMetaWear *> *)waitForDisconnect;
799842
{
800843
BFTaskCompletionSource *taskSource = [BFTaskCompletionSource taskCompletionSource];
801844
@synchronized(disconnectionSources) {
@@ -1113,6 +1156,13 @@ - (void)peripheral:(id<MBLBluetoothPeripheral>)peripheral didReadRSSI:(NSNumber
11131156

11141157
- (BFTask<NSNumber *> *)readBatteryLifeAsync
11151158
{
1159+
// Use the new age thing if we have it.
1160+
if (self.settings.batteryRemaining) {
1161+
return [[self.settings.batteryRemaining readAsync] continueWithSuccessBlock:^id _Nullable(BFTask<MBLNumericData *> * _Nonnull t) {
1162+
return t.result.value;
1163+
}];
1164+
}
1165+
// Fall back on the battery characteristic
11161166
if (!batteryLifeCharacteristic) {
11171167
return [BFTask taskWithError:[NSError errorWithDomain:kMBLErrorDomain
11181168
code:kMBLErrorNotConnected
@@ -1246,7 +1296,7 @@ - (BFTask *)prepareForFirmwareUpdateToVersionAsync:(MBLFirmwareBuild *)firmware
12461296
}
12471297
// Getting into DFU causes the device to disconnect, so we execute this
12481298
// async to make sure our disconnection handler gets registered first.
1249-
BFTask *disconnectTask = [self waitForDisconnection];
1299+
BFTask *disconnectTask = [self waitForDisconnect];
12501300
if (alreadyInDFU) {
12511301
// See to simulate the disconnect that occurs when we jump to bootloader
12521302
[[MBLMetaWearManager sharedManager] disconnectMetaWear:self fromPeripheralSide:NO];
@@ -1492,12 +1542,24 @@ -(void)peripheral:(id<MBLBluetoothPeripheral>)peripheral didUpdateValueForCharac
14921542
if (!characteristic.value.length) {
14931543
return;
14941544
}
1495-
uint8_t moduleId = *(uint8_t *)characteristic.value.bytes;
1496-
@synchronized(moduleInfoTaskSources) {
1497-
BFTaskCompletionSource *source = moduleInfoTaskSources[[NSNumber numberWithInt:moduleId]];
1498-
if (source) {
1545+
uint8_t *bytes = (uint8_t *)characteristic.value.bytes;
1546+
uint8_t moduleId = *bytes; bytes++;
1547+
uint8_t registerId = *bytes;
1548+
// The first register is special and should only be read during initialization
1549+
if (registerId == 0x80) {
1550+
@synchronized(moduleInfoTaskSources) {
1551+
BFTaskCompletionSource *source = moduleInfoTaskSources[[NSNumber numberWithInt:moduleId]];
1552+
if (!source) {
1553+
// If another app tries to connect to this MetaWear it could issue these discovery
1554+
// commands again, so lets track any unexpected reads of the these registers and use that
1555+
// as an indicator someone is trying to use 2 apps simultaneously which is very
1556+
// dangerous and unsupported. Our only option is to disconnect this app.
1557+
MBLLog(MBLLogLevelWarning, @"Simultaneous Connection - Disconnecting %@ because another App has initiated a connection", self);
1558+
[[MBLMetaWearManager sharedManager] disconnectMetaWear:self fromPeripheralSide:NO];
1559+
}
14991560
[moduleInfoTaskSources removeObjectForKey:[NSNumber numberWithInt:moduleId]];
15001561
if (error) {
1562+
// TODO: This can probably never be hit
15011563
[source trySetError:error];
15021564
} else if (characteristic.value.length >= 4) {
15031565
// 4 or more bytes indicates the module is present and active
@@ -1507,22 +1569,27 @@ -(void)peripheral:(id<MBLBluetoothPeripheral>)peripheral didUpdateValueForCharac
15071569
[source trySetResult:nil];
15081570
}
15091571
[self decrementCount];
1510-
} else if (moduleId < self.modules.count) {
1511-
id module = self.modules[moduleId];
1512-
if ([module respondsToSelector:@selector(recievedData:error:)]) {
1513-
[module recievedData:characteristic.value error:error];
1514-
} else {
1515-
assert(NO && "No module found");
1516-
}
1517-
} else if (moduleId == self.testDebug.moduleInfo.moduleId) {
1518-
if ([self.testDebug respondsToSelector:@selector(recievedData:error:)]) {
1519-
[self.testDebug recievedData:characteristic.value error:error];
1520-
} else {
1521-
assert(NO && "No testDebug module found");
1522-
}
1572+
}
1573+
} else if (moduleId < self.modules.count) {
1574+
id module = self.modules[moduleId];
1575+
if ([module respondsToSelector:@selector(recievedData:error:)]) {
1576+
[module recievedData:characteristic.value error:error];
1577+
} else {
1578+
assert(NO && "No module found");
1579+
}
1580+
} else if (moduleId == self.testDebug.moduleInfo.moduleId) {
1581+
if ([self.testDebug respondsToSelector:@selector(recievedData:error:)]) {
1582+
[self.testDebug recievedData:characteristic.value error:error];
1583+
} else {
1584+
assert(NO && "No testDebug module found");
15231585
}
15241586
}
15251587
} else if (characteristic == batteryLifeCharacteristic) {
1588+
if (!characteristic.value.length) {
1589+
// Retry if no data received
1590+
[peripheral readValueForCharacteristic:characteristic];
1591+
return;
1592+
}
15261593
@synchronized(batteryLifeSources) {
15271594
for (BFTaskCompletionSource *source in batteryLifeSources) {
15281595
if (error) {

0 commit comments

Comments
 (0)