28 |
29 | @implementation RNLBeacon
30 | -(NSString *) id1 {
31 | NSString *id = Nil;
32 | if (self.identifiers.count > 0) {
33 | id = [self.identifiers objectAtIndex:0];
34 | }
35 | return id;
36 | }
37 | -(NSString *) id2 {
38 | NSString *id = Nil;
39 | if (self.identifiers.count > 1) {
40 | id = [self.identifiers objectAtIndex:1];
41 | }
42 | return id;
43 | }
44 | -(NSString *) id3 {
45 | NSString *id = Nil;
46 | if (self.identifiers.count > 2) {
47 | id = [self.identifiers objectAtIndex:2];
48 | }
49 | return id;
50 | }
51 |
52 | -(double) coreLocationAccuracy {
53 | if (self.beaconObject != Nil && [self.beaconObject isKindOfClass:[CLBeacon class]]) {
54 | return ((CLBeacon *)self.beaconObject).accuracy;
55 | }
56 | return -1.0;
57 | }
58 | + (NSArray *) wrapCLBeacons:(NSArray *) clBeacons {
59 | NSMutableArray *beacons = [[NSMutableArray alloc] init];
60 | for (CLBeacon * clBeacon in clBeacons) {
61 | [beacons addObject: [RNLBeacon wrapCLBeacon: clBeacon]];
62 | }
63 | return beacons;
64 | }
65 |
66 | + (RNLBeacon *) wrapCLBeacon:(CLBeacon *)clBeacon {
67 | RNLBeacon *beacon = [[RNLBeacon alloc] init];
68 | beacon.beaconObject = clBeacon;
69 | beacon.rssi = [NSNumber numberWithInteger:clBeacon.rssi];
70 | beacon.identifiers = @[[clBeacon.proximityUUID UUIDString],[clBeacon.major stringValue],[clBeacon.minor stringValue]];
71 | beacon.measuredPower = nil; // cannot read from a CLBeacon
72 | beacon.manufacturer = @0x004c;
73 | beacon.beaconTypeCode = @0x0215;
74 | beacon.dataFields = @[];
75 | return beacon;
76 | }
77 |
78 | - (BOOL) isEqualToBeacon: (RNLBeacon *)other {
79 | BOOL equal = true;
80 | // must have same number of identifiers
81 | if (self.identifiers.count != other.identifiers.count) {
82 | equal = false;
83 | }
84 | else {
85 | // All identifiers must match
86 | for (int i = 0; i < self.identifiers.count; i++) {
87 | if (![[self.identifiers objectAtIndex:i] isEqualToString:[other.identifiers objectAtIndex:i]]) {
88 | equal = false;
89 | break;
90 | }
91 | }
92 | }
93 | if (self.bluetoothIdentifier != nil && other.bluetoothIdentifier != nil) {
94 | if (![self.bluetoothIdentifier isEqualToString:other.bluetoothIdentifier]) {
95 | equal = false;
96 | }
97 | }
98 | else {
99 | if (self.bluetoothIdentifier != nil || other.bluetoothIdentifier != nil) {
100 | // if one is nil but not the other, then they are not the same
101 | equal = false;
102 | }
103 | }
104 | return equal;
105 |
106 | }
107 |
108 | + (NSData *) dataFromIdentifier: (NSString*) identifier {
109 | NSMutableData* data = [NSMutableData data];
110 | if ([identifier containsString:@"-"]) {
111 | // convert uuid to regular hex string
112 | identifier = [identifier stringByReplacingOccurrencesOfString:@"-" withString:@""];
113 | identifier = [NSString stringWithFormat:@"0x%@", identifier];
114 | }
115 |
116 | if ([identifier hasPrefix:@"0x"]) {
117 | int bytes = (int) (identifier.length-2)/2;
118 | // convert hex number
119 | for (int i = 0; i < bytes; i++) {
120 | NSString *hexByte = [identifier substringWithRange: NSMakeRange(i*2+2,2)];
121 | NSScanner* scanner = [NSScanner scannerWithString:hexByte];
122 | unsigned int intValue;
123 | [scanner scanHexInt:&intValue];
124 | [data appendBytes:&intValue length:1];
125 | }
126 | }
127 | else {
128 | // convert int 0-65535
129 | int intIdentifier = [identifier intValue];
130 | int highByte = intIdentifier >> 8;
131 | int lowByte = intIdentifier & 0xff;
132 | [data appendBytes:&highByte length: 1];
133 | [data appendBytes:&lowByte length: 1];
134 | }
135 | return data;
136 | }
137 |
138 | + (NSArray *) matchBeacons: (NSArray * ) beacons bluetoothIdentifier:(NSString *)bluetoothIdentifier id1: (NSString *) id1 id2: (NSString *) id2 id3: (NSString *) id3 {
139 | NSMutableArray * matchingBeacons = [[NSMutableArray alloc] init];
140 | for (RNLBeacon *beacon in beacons) {
141 | BOOL match = YES;
142 | if (bluetoothIdentifier != nil) {
143 | if (beacon.bluetoothIdentifier != nil) {
144 | if (![bluetoothIdentifier isEqualToString:beacon.bluetoothIdentifier]) {
145 | match = NO;
146 | }
147 | }
148 | }
149 | if (id1 != nil) {
150 | if (beacon.id1 != nil) {
151 | if (![id1 isEqualToString:beacon.id1]) {
152 | match = NO;
153 | }
154 | }
155 | }
156 | if (id2 != nil) {
157 | if (beacon.id2 != nil) {
158 | if (![id2 isEqualToString:beacon.id2]) {
159 | match = NO;
160 | }
161 | }
162 | }
163 | if (id3 != nil) {
164 | if (beacon.id3 != nil) {
165 | if (![id3 isEqualToString:beacon.id3]) {
166 | match = NO;
167 | }
168 | }
169 | }
170 | if (match) {
171 | [matchingBeacons addObject: beacon];
172 | }
173 | }
174 | return matchingBeacons;
175 | }
176 |
177 | - (id)copyWithZone:(NSZone *)zone {
178 | RNLBeacon *copy = [[RNLBeacon alloc] init];
179 |
180 | if (self.beaconObject != nil) {
181 | copy.beaconObject = [self.beaconObject copyWithZone: nil];
182 | }
183 | copy.identifiers = [self.identifiers copyWithZone:nil];
184 | copy.dataFields = [self.identifiers copyWithZone:nil];
185 | if (self.bluetoothIdentifier != nil) {
186 | copy.bluetoothIdentifier = [self.bluetoothIdentifier copyWithZone:nil];
187 | }
188 | copy.manufacturer = self.manufacturer;
189 | copy.rssi = self.rssi;
190 | copy.beaconTypeCode = self.beaconTypeCode;
191 | copy.serviceUuid = self.serviceUuid;
192 | return copy;
193 | }
194 |
195 | @end
196 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2014 Radius Networks
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/ios-beacon-tools/RNLBeaconParser.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Radius Networks, Inc.
3 | * http://www.radiusnetworks.com
4 | *
5 | * @author David G. Young
6 | *
7 | * Licensed to the Apache Software Foundation (ASF) under one
8 | * or more contributor license agreements. See the NOTICE file
9 | * distributed with this work for additional information
10 | * regarding copyright ownership. The ASF licenses this file
11 | * to you under the Apache License, Version 2.0 (the
12 | * "License"); you may not use this file except in compliance
13 | * with the License. You may obtain a copy of the License at
14 | *
15 | * http://www.apache.org/licenses/LICENSE-2.0
16 | *
17 | * Unless required by applicable law or agreed to in writing,
18 | * software distributed under the License is distributed on an
19 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 | * KIND, either express or implied. See the License for the
21 | * specific language governing permissions and limitations
22 | * under the License.
23 | */
24 |
25 |
26 | #import "RNLBeaconParser.h"
27 |
28 | @interface RNLBeaconParser()
29 | @property (strong, nonatomic) NSNumber *matchingBeaconTypeCode;
30 | @property (strong, nonatomic) NSMutableArray *identifierStartOffsets;
31 | @property (strong, nonatomic) NSMutableArray *identifierEndOffsets;
32 | @property (strong, nonatomic) NSMutableArray *identifierLittleEndianFlags;
33 | @property (strong, nonatomic) NSMutableArray *identifierVariableLengthFlags;
34 | @property (strong, nonatomic) NSMutableArray *dataStartOffsets;
35 | @property (strong, nonatomic) NSMutableArray *dataEndOffsets;
36 | @property (strong, nonatomic) NSMutableArray *dataLittleEndianFlags;
37 | @property (strong, nonatomic) NSNumber *matchingBeaconTypeCodeStartOffset;
38 | @property (strong, nonatomic) NSNumber *matchingBeaconTypeCodeEndOffset;
39 | @property (strong, nonatomic) NSNumber *powerStartOffset;
40 | @property (strong, nonatomic) NSNumber *powerEndOffset;
41 | @property (strong, nonatomic) NSNumber *powerCorrection;
42 | @property (strong, nonatomic) NSNumber *serviceUuidStartOffset;
43 | @property (strong, nonatomic) NSNumber *serviceUuidEndOffset;
44 | @property (strong, nonatomic) NSNumber *serviceUuid;
45 | @property (nonatomic) BOOL extraFrame;
46 | @end
47 |
48 | @implementation RNLBeaconParser {
49 | }
50 |
51 | static const NSString *I_PATTERN = @"i\\:(\\d+)\\-(\\d+)([blv]*)?";
52 | static const NSString *M_PATTERN = @"m\\:(\\d+)-(\\d+)\\=([0-9A-F-a-f]+)";
53 | static const NSString *D_PATTERN = @"d\\:(\\d+)\\-(\\d+)([bl]*)?";
54 | static const NSString *P_PATTERN = @"p\\:(\\d+)\\-(\\d+)\\:?([\\-\\d]+)?";
55 | static const NSString *S_PATTERN = @"s\\:(\\d+)-(\\d+)\\=([0-9A-Fa-f]+)";
56 | static const NSString *X_PATTERN = @"x";
57 |
58 | /**
59 | * Makes a new BeaconParser. Should normally be immediately followed by a call to #setLayout
60 | */
61 | - (id)init {
62 | if (self = [super init]) {
63 | self.identifierStartOffsets = [[NSMutableArray alloc] init];
64 | self.identifierEndOffsets = [[NSMutableArray alloc] init];
65 | self.dataStartOffsets = [[NSMutableArray alloc] init];
66 | self.dataEndOffsets = [[NSMutableArray alloc] init];
67 | self.dataLittleEndianFlags = [[NSMutableArray alloc] init];
68 | self.identifierLittleEndianFlags = [[NSMutableArray alloc] init];
69 | self.identifierVariableLengthFlags = [[NSMutableArray alloc] init];
70 | }
71 | return self;
72 | }
73 |
74 | /**
75 | * Defines a beacon field parsing algorithm based on a string designating the zero-indexed
76 | * offsets to bytes within a BLE advertisement.
77 | *
78 | * If you want to see examples of how other folks have set up BeaconParsers for different
79 | * kinds of beacons, try doing a Google search for "getBeaconParsers" (include the quotes in
80 | * the search.)
81 | *
82 | * Four prefixes are allowed in the string:
83 | *
84 | *
85 | * m - matching byte sequence for this beacon type to parse (exactly one required)
86 | * i - identifier (at least one required, multiple allowed)
87 | * p - power calibration field (exactly one required)
88 | * d - data field (optional, multiple allowed)
89 | * x - extra layout. Signifies that the layout is secondary to a primary layout with the same
90 | * matching byte sequence (or ServiceUuid). Extra layouts do not require power or
91 | * identifier fields and create Beacon objects without identifiers.
92 | *
93 | *
94 | * Each prefix is followed by a colon, then an inclusive decimal byte offset for the field from
95 | * the beginning of the advertisement. In the case of the m prefix, an = sign follows the byte
96 | * offset, followed by a big endian hex representation of the bytes that must be matched for
97 | * this beacon type. When multiple i or d entries exist in the string, they will be added in
98 | * order of definition to the identifier or data array for the beacon when parsing the beacon
99 | * advertisement. Terms are separated by commas.
100 | *
101 | * All offsets from the start of the advertisement are relative to the first byte of the
102 | * two byte manufacturer code. The manufacturer code is therefore always at position 0-1
103 | *
104 | * All data field and identifier expressions may be optionally suffixed with the letter l, which
105 | * indicates the field should be parsed as little endian. If not present, the field will be presumed
106 | * to be big endian.
107 | *
108 | *
If the expression cannot be parsed, a BeaconLayoutException is thrown.
109 | *
110 | * Example of a parser string for AltBeacon:
111 | *
112 | *
113 | * "m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"
114 | *
115 | *
116 | * This signifies that the beacon type will be decoded when an advertisement is found with
117 | * 0xbeac in bytes 2-3, and a three-part identifier will be pulled out of bytes 4-19, bytes
118 | * 20-21 and bytes 22-23, respectively. A signed power calibration value will be pulled out of
119 | * byte 24, and a data field will be pulled out of byte 25.
120 | *
121 | * Note: bytes 0-1 of the BLE manufacturer advertisements are the two byte manufacturer code.
122 | * Generally you should not match on these two bytes when using a BeaconParser, because it will
123 | * limit your parser to matching only a transmitter made by a specific manufacturer. Software
124 | * and operating systems that scan for beacons typically ignore these two bytes, allowing beacon
125 | * manufacturers to use their own company code assigned by Bluetooth SIG. The default parser
126 | * implementation will already pull out this company code and store it in the
127 | * beacon.manufacturer field. Matcher expressions should therefore start with "m2-3:" followed
128 | * by the multi-byte hex value that signifies the beacon type.
129 | *
130 | */
131 | -(BOOL) setBeaconLayout: (NSString *)beaconLayout error:(NSError **)errorPtr; {
132 |
133 | NSArray *terms = [beaconLayout componentsSeparatedByString:@","];
134 | int errorCode = 0;
135 | NSString *errorString;
136 |
137 | for (NSString *term in terms) {
138 | Boolean found = NO;
139 |
140 | NSRange textRange = NSMakeRange(0, term.length);
141 | NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern: (NSString *)I_PATTERN options:0 error:nil];
142 | NSArray* matches = [regex matchesInString:term options:0 range: textRange];
143 | for (NSTextCheckingResult* match in matches) {
144 | found = YES;
145 | NSString *group1 = [term substringWithRange:[match rangeAtIndex:1]];
146 | NSString *group2 = [term substringWithRange:[match rangeAtIndex:2]];
147 | NSString *group3 = [term substringWithRange:[match rangeAtIndex:3]];
148 | NSNumber *startOffset = [NSNumber numberWithLong:[group1 integerValue]];
149 | NSNumber *endOffset = [NSNumber numberWithLong:[group2 integerValue]];
150 | NSNumber *littleEndian = [NSNumber numberWithBool: [group3 isEqualToString:@"l"]];
151 | NSNumber *variableLength = [NSNumber numberWithBool: [group3 isEqualToString:@"v"]];
152 | [self.identifierLittleEndianFlags addObject: littleEndian];
153 | [self.identifierStartOffsets addObject: startOffset];
154 | [self.identifierEndOffsets addObject: endOffset];
155 | [self.identifierVariableLengthFlags addObject: variableLength];
156 | }
157 |
158 | regex = [NSRegularExpression regularExpressionWithPattern: (NSString *)X_PATTERN options:0 error:nil];
159 | matches = [regex matchesInString:term options:0 range: textRange];
160 | if (matches.count > 0) {
161 | found = YES;
162 | self.extraFrame = YES;
163 | }
164 |
165 | regex = [NSRegularExpression regularExpressionWithPattern: (NSString *)S_PATTERN options:0 error:nil];
166 | matches = [regex matchesInString:term options:0 range: textRange];
167 | for (NSTextCheckingResult* match in matches) {
168 | found = YES;
169 | NSString *group1 = [term substringWithRange:[match rangeAtIndex:1]];
170 | NSString *group2 = [term substringWithRange:[match rangeAtIndex:2]];
171 | NSString *group3 = [term substringWithRange:[match rangeAtIndex:3]];
172 | self.serviceUuidStartOffset = [NSNumber numberWithLong:[group1 integerValue]];
173 | self.serviceUuidEndOffset = [NSNumber numberWithLong:[group2 integerValue]];
174 | self.serviceUuid = [NSNumber numberWithLong:[group3 integerValue]];
175 | }
176 |
177 | regex = [NSRegularExpression regularExpressionWithPattern: (NSString *)D_PATTERN options:0 error:nil];
178 | matches = [regex matchesInString:term options:0 range: textRange];
179 | for (NSTextCheckingResult* match in matches) {
180 | found = YES;
181 | NSString *group1 = [term substringWithRange:[match rangeAtIndex:1]];
182 | NSString *group2 = [term substringWithRange:[match rangeAtIndex:2]];
183 | NSString *group3 = [term substringWithRange:[match rangeAtIndex:3]];
184 | NSNumber *startOffset = [NSNumber numberWithLong:[group1 integerValue]];
185 | NSNumber *endOffset = [NSNumber numberWithLong:[group2 integerValue]];
186 | NSNumber *littleEndian = [NSNumber numberWithBool: [group3 isEqualToString:@"l"]];
187 | [self.dataLittleEndianFlags addObject: littleEndian];
188 | [self.dataStartOffsets addObject: startOffset];
189 | [self.dataEndOffsets addObject: endOffset];
190 | }
191 |
192 | regex = [NSRegularExpression regularExpressionWithPattern: (NSString *)P_PATTERN options:0 error:nil];
193 | matches = [regex matchesInString:term options:0 range: textRange];
194 | for (NSTextCheckingResult* match in matches) {
195 | found = YES;
196 | NSString *group1 = [term substringWithRange:[match rangeAtIndex:1]];
197 | NSString *group2 = [term substringWithRange:[match rangeAtIndex:2]];
198 | NSRange correctionRange =[match rangeAtIndex:3];
199 | if (correctionRange.location != NSNotFound) {
200 | NSString *group3 = [term substringWithRange:correctionRange];
201 | self.powerCorrection = [NSNumber numberWithLong:[group3 integerValue]];
202 | }
203 | else {
204 | self.powerCorrection = @0;
205 | }
206 | self.powerStartOffset = [NSNumber numberWithLong:[group1 integerValue]];
207 | self.powerEndOffset = [NSNumber numberWithLong:[group2 integerValue]];
208 | }
209 |
210 | regex = [NSRegularExpression regularExpressionWithPattern: (NSString *)M_PATTERN options:0 error:nil];
211 | matches = [regex matchesInString:term options:0 range: textRange];
212 | for (NSTextCheckingResult* match in matches) {
213 | found = YES;
214 | NSString *group1 = [term substringWithRange:[match rangeAtIndex:1]];
215 | NSString *group2 = [term substringWithRange:[match rangeAtIndex:2]];
216 | NSString *group3 = [term substringWithRange:[match rangeAtIndex:3]];
217 | self.matchingBeaconTypeCodeStartOffset = [NSNumber numberWithLong:[group1 integerValue]];
218 | self.matchingBeaconTypeCodeEndOffset = [NSNumber numberWithLong:[group2 integerValue]];
219 | unsigned code = 0;
220 | NSScanner *scanner = [NSScanner scannerWithString:group3];
221 | [scanner scanHexInt:&code];
222 | self.matchingBeaconTypeCode = [NSNumber numberWithUnsignedInt:code];
223 | }
224 | if (!found) {
225 | NSLog(@"cannot parse term %@", term);
226 | errorCode = -1;
227 | errorString = NSLocalizedString(@"Cannot parse beacon layout term %@", term);
228 | }
229 | }
230 | if ((self.powerStartOffset == Nil || self.powerEndOffset == Nil) && self.extraFrame == NO) {
231 | errorCode = -2;
232 | errorString = NSLocalizedString(@"You must supply a power byte offset with a prefix of 'p'", @"");
233 | }
234 | if (self.serviceUuid == Nil && (self.matchingBeaconTypeCodeStartOffset == Nil || self.matchingBeaconTypeCodeEndOffset == Nil)) {
235 | errorCode = -3;
236 | errorString = NSLocalizedString(@"You must supply a matching beacon type expression with a prefix of 'm', or a service uuid expression with a prefix of 's'", @"");
237 | }
238 | if ((self.identifierStartOffsets.count == 0 || self.identifierEndOffsets.count == 0) && self.extraFrame == NO) {
239 | errorCode = -4;
240 | errorString = NSLocalizedString(@"You must supply at least one identifier offset withh a prefix of 'i'", @"");
241 | }
242 | if (errorPtr && errorCode < 0) {
243 | NSString *domain = @"org.altbeacon.beaconparser.ErrorDomain";
244 | NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : errorString };
245 |
246 | *errorPtr = [NSError errorWithDomain:domain
247 | code:errorCode
248 | userInfo:userInfo];
249 | return NO;
250 | }
251 |
252 | return YES;
253 | }
254 |
255 |
256 | /**
257 | * Construct a Beacon from a Bluetooth LE packet collected by CoreBluetooth,
258 | * including the raw bluetooth device info
259 | *
260 | * param scanData The actual packet bytes
261 | * param rssi The measured signal strength of the packet
262 | * param device The bluetooth device that was detected
263 | * returns An instance of a Beacon
264 | */
265 | -(RNLBeacon *) fromScanData: (NSData *)scanData withRssi: (NSNumber *) rssi forDevice: (CBPeripheral *)device serviceUuid:(NSNumber *) serviceUuid {
266 | return [self fromScanData: scanData withRssi: rssi forDevice: device serviceUuid: serviceUuid withBeacon:[[RNLBeacon alloc] init]];
267 | }
268 |
269 | -(RNLBeacon *) fromScanData: (NSData *)scanData withRssi: (NSNumber *) rssi forDevice: (CBPeripheral *)device serviceUuid: (NSNumber *) serviceUuid withBeacon: (RNLBeacon *)beacon {
270 |
271 | BOOL patternFound = NO;
272 | const unsigned char *bytes = [scanData bytes];
273 |
274 | int beaconTypeCodeLength = [self.matchingBeaconTypeCodeEndOffset intValue]-[self.matchingBeaconTypeCodeStartOffset intValue]+1;
275 | long matchingBeaconTypeCodeLong = [self.matchingBeaconTypeCode longValue];
276 | unsigned char beaconTypeCodeBytes[4] = { 0, 0, 0, 0 };
277 | if (beaconTypeCodeLength > 4) {
278 | NSLog(@"beacon type code is specified to be too long");
279 | return Nil;
280 | }
281 | [self value: matchingBeaconTypeCodeLong toByteArray: beaconTypeCodeBytes withLength: beaconTypeCodeLength];
282 |
283 | int startByte = 0;
284 | if (serviceUuid != Nil) {
285 | startByte = -2; // serviceUuids are stripped out of the data on iOS, so we have to adjust offsets
286 | }
287 | if ([self biggestOffset] +1 > scanData.length - startByte) {
288 | BOOL variableLength = NO;
289 | for (NSNumber *variableLengthFlag in self.identifierVariableLengthFlags) {
290 | if ([variableLengthFlag isEqual: @1]) {
291 | variableLength = YES;
292 | }
293 | }
294 | if (!variableLength) {
295 | return Nil;
296 | }
297 | }
298 |
299 | if (scanData.length < startByte+beaconTypeCodeLength+[self.matchingBeaconTypeCodeStartOffset intValue]) {
300 | // advertisement is too small
301 | }
302 | else {
303 | if ([self byteArray: bytes+startByte+[self.matchingBeaconTypeCodeStartOffset intValue] matchesByteArray: beaconTypeCodeBytes withLength: beaconTypeCodeLength]) {
304 | patternFound = YES;
305 | }
306 | }
307 |
308 | if (patternFound == NO) {
309 | // This is not a beacon
310 | return Nil;
311 | }
312 |
313 | beacon.extraFrame = self.extraFrame;
314 | beacon.name = device.name;
315 | beacon.rssi = rssi;
316 | beacon.beaconTypeCode = self.matchingBeaconTypeCode;
317 | beacon.measuredPower = [NSNumber numberWithInt: 0];
318 |
319 | NSMutableArray *identifiers = [[NSMutableArray alloc] init];
320 |
321 | for (int i = 0; i < self.identifierEndOffsets.count; i++) {
322 | int startOffset = [[self.identifierStartOffsets objectAtIndex: i] intValue];
323 | int endOffset = [[self.identifierEndOffsets objectAtIndex: i] intValue];
324 | BOOL littleEndian = [[self.identifierLittleEndianFlags objectAtIndex: i] boolValue];
325 | BOOL variableLength = [[self.identifierVariableLengthFlags objectAtIndex: i] boolValue];
326 | if (variableLength) {
327 | if (endOffset+startByte >= scanData.length) {
328 | endOffset = (int) scanData.length-1-startByte;
329 | }
330 | }
331 | int length = endOffset - startOffset +1;
332 | NSString *idString = [self formattedStringIdentiferFromByteArray: bytes+startOffset+startByte ofLength: length asLittleEndian:littleEndian];
333 | [identifiers addObject:idString];
334 | }
335 | beacon.identifiers = identifiers;
336 |
337 | int measuredPower = 0;
338 | if (self.powerStartOffset != nil) { // Don't parse measured power if it is not in format
339 | int startOffset = [self.powerStartOffset intValue];
340 | int endOffset = [self.powerEndOffset intValue];
341 | int length = endOffset-startOffset +1;
342 | NSString *powerString = [self formattedStringIdentiferFromByteArray:bytes+startOffset+startByte ofLength:length asLittleEndian:NO];
343 | measuredPower = (int) [powerString integerValue];
344 | // make sure it is a signed integer
345 | if (measuredPower > 127) {
346 | measuredPower -= 256;
347 | }
348 | measuredPower += [self.powerCorrection integerValue];
349 | beacon.measuredPower = [NSNumber numberWithInt: measuredPower];
350 | }
351 |
352 |
353 | NSMutableArray *dataFields = [[NSMutableArray alloc] init];
354 | for (int i = 0; i < self.dataEndOffsets.count; i++) {
355 | int startOffset = [[self.dataStartOffsets objectAtIndex: i] intValue];
356 | int endOffset = [[self.dataEndOffsets objectAtIndex: i] intValue];
357 | int length = endOffset - startOffset +1;
358 | BOOL littleEndian = [[self.dataLittleEndianFlags objectAtIndex: i] boolValue];
359 | NSString *idString = [self formattedStringIdentiferFromByteArray: bytes+startOffset+startByte ofLength: length asLittleEndian:littleEndian];
360 | [dataFields addObject:idString];
361 | }
362 |
363 | beacon.dataFields = dataFields;
364 | beacon.serviceUuid = serviceUuid;
365 |
366 | // We will not expose the bluetooth mac address because it gets spoofed on iOS and is of no value
367 | // but we will track the uuid as a bluetooth identifier proxy
368 | beacon.bluetoothIdentifier = [device.identifier UUIDString];
369 |
370 | if (beacon.serviceUuid.intValue != -1) {
371 | NSString *manufacturerString = [self formattedStringIdentiferFromByteArray:bytes ofLength:2 asLittleEndian:NO];
372 | beacon.manufacturer = [NSNumber numberWithLong: [manufacturerString integerValue]];
373 | }
374 | else {
375 | beacon.manufacturer = @-1;
376 | }
377 |
378 | return beacon;
379 | }
380 |
381 | - (void) value: (long) value toByteArray: (unsigned char *)bytes withLength: (int) length {
382 | for (int i = 0; i < length; i++) {
383 | bytes[length-i-1] = (value >> i*8) & 0xFF;
384 | }
385 | }
386 |
387 | -(NSString *) hexStringFromData: (NSData *) data {
388 | return [self hexStringFromBytes: [data bytes] ofLength: data.length withSpaces: YES];
389 | }
390 |
391 | -(NSString *) hexStringFromBytes: (const unsigned char *) bytes ofLength: (unsigned long) length withSpaces: (BOOL) addSpaces {
392 | NSString *str = @"";
393 | for (int i = 0; i < length; i++) {
394 | if (addSpaces) {
395 | str = [NSString stringWithFormat:@"%@ %02X", str, bytes[i]];
396 | }
397 | else {
398 | str = [NSString stringWithFormat:@"%@%02X", str, bytes[i]];
399 | }
400 | }
401 | return str;
402 | }
403 |
404 | -(BOOL) byteArray: (const unsigned char *)bytes1 matchesByteArray: (const unsigned char *) bytes2 withLength: (int) length {
405 | for (int i = 0; i < length; i++) {
406 | if (bytes1[i] != bytes2[i]) {
407 | return NO;
408 | }
409 | }
410 | return YES;
411 | }
412 |
413 | -(NSString *) formattedStringIdentiferFromByteArray: (const unsigned char *) byteArray ofLength: (int) length asLittleEndian: (BOOL) littleEndian {
414 | unsigned char* bytes = malloc(length * sizeof(unsigned char));
415 | NSString *formattedIdentifier = Nil;
416 |
417 | if (littleEndian) {
418 | for (int i = 0; i < length; i++) {
419 | bytes[i] = byteArray[length-1-i];
420 | }
421 | }
422 | else {
423 | for (int i = 0; i < length; i++) {
424 | bytes[i] = byteArray[i];
425 | }
426 | }
427 |
428 | // We treat a 1-4 byte number as decimal string
429 | if (length < 5) {
430 | long number = 0l;
431 | for (int i = 0; i < length; i++) {
432 | long byteValue = (long) (bytes[length - i-1] & 0xff);
433 | long positionValue = 1 << i*8;
434 | long calculatedValue = (long) (byteValue * positionValue);
435 | number += calculatedValue;
436 | }
437 | formattedIdentifier = [NSString stringWithFormat:@"%ld", number];
438 | }
439 |
440 | if (formattedIdentifier == Nil) {
441 | // We treat a 6+ byte number as a hex string
442 | NSString *hexString = [self hexStringFromBytes: bytes ofLength: length withSpaces: NO];
443 | // And if it is a 16 byte number we add dashes to it to make it look like a standard UUID
444 | if (length == 16) {
445 | NSMutableString *guid = [NSMutableString stringWithString: hexString];
446 | [guid insertString: @"-" atIndex: 8];
447 | [guid insertString: @"-" atIndex: 13];
448 | [guid insertString: @"-" atIndex: 18];
449 | [guid insertString: @"-" atIndex: 23];
450 | formattedIdentifier = guid;
451 | }
452 | else {
453 | formattedIdentifier = [NSString stringWithFormat:@"0x%@", hexString];
454 | }
455 | }
456 |
457 | free(bytes);
458 | return formattedIdentifier;
459 | }
460 |
461 | -(int) biggestOffset {
462 | int biggestOffset = [self.matchingBeaconTypeCodeEndOffset intValue];
463 | if ([self.powerEndOffset intValue] > biggestOffset) {
464 | biggestOffset = [self.powerEndOffset intValue];
465 | }
466 | for (NSNumber *identifierEndOffset in self.identifierEndOffsets) {
467 | if ([identifierEndOffset intValue] > biggestOffset) {
468 | biggestOffset = [identifierEndOffset intValue];
469 | }
470 | }
471 | for (NSNumber *dataEndOffset in self.dataEndOffsets) {
472 | if ([dataEndOffset intValue] > biggestOffset) {
473 | biggestOffset = [dataEndOffset intValue];
474 | }
475 | }
476 | return biggestOffset;
477 | }
478 |
479 | @end
480 |
481 |
--------------------------------------------------------------------------------
/ios-beacon-tools.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | EEAF8D92210153D3003E6402 /* sample.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEAF8D91210153D3003E6402 /* sample.swift */; };
11 | EEAF8D95210158AD003E6402 /* RNLURLBeaconCompressor.m in Sources */ = {isa = PBXBuildFile; fileRef = EEAF8D94210158AD003E6402 /* RNLURLBeaconCompressor.m */; };
12 | EEAF8D96210158AD003E6402 /* RNLURLBeaconCompressor.m in Sources */ = {isa = PBXBuildFile; fileRef = EEAF8D94210158AD003E6402 /* RNLURLBeaconCompressor.m */; };
13 | EEDCDB771B9F92FA00AE693C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDB761B9F92FA00AE693C /* main.m */; };
14 | EEDCDB7A1B9F92FA00AE693C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDB791B9F92FA00AE693C /* AppDelegate.m */; };
15 | EEDCDB801B9F92FA00AE693C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EEDCDB7E1B9F92FA00AE693C /* Main.storyboard */; };
16 | EEDCDB821B9F92FA00AE693C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EEDCDB811B9F92FA00AE693C /* Images.xcassets */; };
17 | EEDCDB851B9F92FA00AE693C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = EEDCDB831B9F92FA00AE693C /* LaunchScreen.xib */; };
18 | EEDCDB911B9F92FA00AE693C /* ios_beacon_toolsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDB901B9F92FA00AE693C /* ios_beacon_toolsTests.m */; };
19 | EEDCDBAF1B9F935500AE693C /* RNLAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDB9B1B9F935500AE693C /* RNLAppDelegate.m */; };
20 | EEDCDBB01B9F935500AE693C /* RNLAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDB9B1B9F935500AE693C /* RNLAppDelegate.m */; };
21 | EEDCDBB31B9F935500AE693C /* RNLBeaconTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDB9F1B9F935500AE693C /* RNLBeaconTracker.m */; };
22 | EEDCDBB41B9F935500AE693C /* RNLBeaconTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDB9F1B9F935500AE693C /* RNLBeaconTracker.m */; };
23 | EEDCDBB51B9F935500AE693C /* RNLLocationTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBA11B9F935500AE693C /* RNLLocationTracker.m */; };
24 | EEDCDBB61B9F935500AE693C /* RNLLocationTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBA11B9F935500AE693C /* RNLLocationTracker.m */; };
25 | EEDCDBB71B9F935500AE693C /* RNLSignalMeasurement.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBA31B9F935500AE693C /* RNLSignalMeasurement.m */; };
26 | EEDCDBB81B9F935500AE693C /* RNLSignalMeasurement.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBA31B9F935500AE693C /* RNLSignalMeasurement.m */; };
27 | EEDCDBB91B9F935500AE693C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EEDCDBA41B9F935500AE693C /* Main.storyboard */; };
28 | EEDCDBBA1B9F935500AE693C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EEDCDBA41B9F935500AE693C /* Main.storyboard */; };
29 | EEDCDBBB1B9F935500AE693C /* RNLBeacon+Distance.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBA61B9F935500AE693C /* RNLBeacon+Distance.m */; };
30 | EEDCDBBC1B9F935500AE693C /* RNLBeacon+Distance.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBA61B9F935500AE693C /* RNLBeacon+Distance.m */; };
31 | EEDCDBBD1B9F935500AE693C /* RNLBeaconScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBA81B9F935500AE693C /* RNLBeaconScanner.m */; };
32 | EEDCDBBE1B9F935500AE693C /* RNLBeaconScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBA81B9F935500AE693C /* RNLBeaconScanner.m */; };
33 | EEDCDBBF1B9F935500AE693C /* RNLBeaconParser.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBAA1B9F935500AE693C /* RNLBeaconParser.m */; };
34 | EEDCDBC01B9F935500AE693C /* RNLBeaconParser.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBAA1B9F935500AE693C /* RNLBeaconParser.m */; };
35 | EEDCDBC11B9F935500AE693C /* RNLBeacon.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBAC1B9F935500AE693C /* RNLBeacon.m */; };
36 | EEDCDBC21B9F935500AE693C /* RNLBeacon.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBAC1B9F935500AE693C /* RNLBeacon.m */; };
37 | EEDCDBC31B9F935500AE693C /* RNLBeaconTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBAE1B9F935500AE693C /* RNLBeaconTableViewController.m */; };
38 | EEDCDBC41B9F935500AE693C /* RNLBeaconTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDCDBAE1B9F935500AE693C /* RNLBeaconTableViewController.m */; };
39 | EEDCDBC61B9F93BD00AE693C /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = EEDCDBC51B9F93BD00AE693C /* LICENSE */; };
40 | EEDCDBC71B9F93BD00AE693C /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = EEDCDBC51B9F93BD00AE693C /* LICENSE */; };
41 | /* End PBXBuildFile section */
42 |
43 | /* Begin PBXContainerItemProxy section */
44 | EEDCDB8B1B9F92FA00AE693C /* PBXContainerItemProxy */ = {
45 | isa = PBXContainerItemProxy;
46 | containerPortal = EEDCDB691B9F92FA00AE693C /* Project object */;
47 | proxyType = 1;
48 | remoteGlobalIDString = EEDCDB701B9F92FA00AE693C;
49 | remoteInfo = "ios-beacon-tools";
50 | };
51 | /* End PBXContainerItemProxy section */
52 |
53 | /* Begin PBXFileReference section */
54 | EEAF8D90210153D3003E6402 /* ios-beacon-tools-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ios-beacon-tools-Bridging-Header.h"; sourceTree = ""; };
55 | EEAF8D91210153D3003E6402 /* sample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = sample.swift; sourceTree = ""; };
56 | EEAF8D93210158AD003E6402 /* RNLURLBeaconCompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLURLBeaconCompressor.h; sourceTree = ""; };
57 | EEAF8D94210158AD003E6402 /* RNLURLBeaconCompressor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLURLBeaconCompressor.m; sourceTree = ""; };
58 | EEDCDB711B9F92FA00AE693C /* ios-beacon-tools.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ios-beacon-tools.app"; sourceTree = BUILT_PRODUCTS_DIR; };
59 | EEDCDB751B9F92FA00AE693C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
60 | EEDCDB761B9F92FA00AE693C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
61 | EEDCDB781B9F92FA00AE693C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
62 | EEDCDB791B9F92FA00AE693C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
63 | EEDCDB7F1B9F92FA00AE693C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
64 | EEDCDB811B9F92FA00AE693C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
65 | EEDCDB841B9F92FA00AE693C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
66 | EEDCDB8A1B9F92FA00AE693C /* ios-beacon-toolsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ios-beacon-toolsTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
67 | EEDCDB8F1B9F92FA00AE693C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
68 | EEDCDB901B9F92FA00AE693C /* ios_beacon_toolsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ios_beacon_toolsTests.m; sourceTree = ""; };
69 | EEDCDB9A1B9F935500AE693C /* RNLAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLAppDelegate.h; sourceTree = ""; };
70 | EEDCDB9B1B9F935500AE693C /* RNLAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLAppDelegate.m; sourceTree = ""; };
71 | EEDCDB9E1B9F935500AE693C /* RNLBeaconTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLBeaconTracker.h; sourceTree = ""; };
72 | EEDCDB9F1B9F935500AE693C /* RNLBeaconTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLBeaconTracker.m; sourceTree = ""; };
73 | EEDCDBA01B9F935500AE693C /* RNLLocationTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLLocationTracker.h; sourceTree = ""; };
74 | EEDCDBA11B9F935500AE693C /* RNLLocationTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLLocationTracker.m; sourceTree = ""; };
75 | EEDCDBA21B9F935500AE693C /* RNLSignalMeasurement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLSignalMeasurement.h; sourceTree = ""; };
76 | EEDCDBA31B9F935500AE693C /* RNLSignalMeasurement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLSignalMeasurement.m; sourceTree = ""; };
77 | EEDCDBA41B9F935500AE693C /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
78 | EEDCDBA51B9F935500AE693C /* RNLBeacon+Distance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RNLBeacon+Distance.h"; sourceTree = ""; };
79 | EEDCDBA61B9F935500AE693C /* RNLBeacon+Distance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RNLBeacon+Distance.m"; sourceTree = ""; };
80 | EEDCDBA71B9F935500AE693C /* RNLBeaconScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLBeaconScanner.h; sourceTree = ""; };
81 | EEDCDBA81B9F935500AE693C /* RNLBeaconScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLBeaconScanner.m; sourceTree = ""; };
82 | EEDCDBA91B9F935500AE693C /* RNLBeaconParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLBeaconParser.h; sourceTree = ""; };
83 | EEDCDBAA1B9F935500AE693C /* RNLBeaconParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLBeaconParser.m; sourceTree = ""; };
84 | EEDCDBAB1B9F935500AE693C /* RNLBeacon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLBeacon.h; sourceTree = ""; };
85 | EEDCDBAC1B9F935500AE693C /* RNLBeacon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLBeacon.m; sourceTree = ""; };
86 | EEDCDBAD1B9F935500AE693C /* RNLBeaconTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLBeaconTableViewController.h; sourceTree = ""; };
87 | EEDCDBAE1B9F935500AE693C /* RNLBeaconTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLBeaconTableViewController.m; sourceTree = ""; };
88 | EEDCDBC51B9F93BD00AE693C /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; };
89 | /* End PBXFileReference section */
90 |
91 | /* Begin PBXFrameworksBuildPhase section */
92 | EEDCDB6E1B9F92FA00AE693C /* Frameworks */ = {
93 | isa = PBXFrameworksBuildPhase;
94 | buildActionMask = 2147483647;
95 | files = (
96 | );
97 | runOnlyForDeploymentPostprocessing = 0;
98 | };
99 | EEDCDB871B9F92FA00AE693C /* Frameworks */ = {
100 | isa = PBXFrameworksBuildPhase;
101 | buildActionMask = 2147483647;
102 | files = (
103 | );
104 | runOnlyForDeploymentPostprocessing = 0;
105 | };
106 | /* End PBXFrameworksBuildPhase section */
107 |
108 | /* Begin PBXGroup section */
109 | EEDCDB681B9F92FA00AE693C = {
110 | isa = PBXGroup;
111 | children = (
112 | EEAF8D91210153D3003E6402 /* sample.swift */,
113 | EEDCDBC51B9F93BD00AE693C /* LICENSE */,
114 | EEDCDB731B9F92FA00AE693C /* ios-beacon-tools */,
115 | EEDCDB8D1B9F92FA00AE693C /* ios-beacon-toolsTests */,
116 | EEDCDB721B9F92FA00AE693C /* Products */,
117 | EEAF8D90210153D3003E6402 /* ios-beacon-tools-Bridging-Header.h */,
118 | );
119 | sourceTree = "";
120 | };
121 | EEDCDB721B9F92FA00AE693C /* Products */ = {
122 | isa = PBXGroup;
123 | children = (
124 | EEDCDB711B9F92FA00AE693C /* ios-beacon-tools.app */,
125 | EEDCDB8A1B9F92FA00AE693C /* ios-beacon-toolsTests.xctest */,
126 | );
127 | name = Products;
128 | sourceTree = "";
129 | };
130 | EEDCDB731B9F92FA00AE693C /* ios-beacon-tools */ = {
131 | isa = PBXGroup;
132 | children = (
133 | EEAF8D93210158AD003E6402 /* RNLURLBeaconCompressor.h */,
134 | EEAF8D94210158AD003E6402 /* RNLURLBeaconCompressor.m */,
135 | EEDCDB9A1B9F935500AE693C /* RNLAppDelegate.h */,
136 | EEDCDB9B1B9F935500AE693C /* RNLAppDelegate.m */,
137 | EEDCDB9E1B9F935500AE693C /* RNLBeaconTracker.h */,
138 | EEDCDB9F1B9F935500AE693C /* RNLBeaconTracker.m */,
139 | EEDCDBA01B9F935500AE693C /* RNLLocationTracker.h */,
140 | EEDCDBA11B9F935500AE693C /* RNLLocationTracker.m */,
141 | EEDCDBA21B9F935500AE693C /* RNLSignalMeasurement.h */,
142 | EEDCDBA31B9F935500AE693C /* RNLSignalMeasurement.m */,
143 | EEDCDBA41B9F935500AE693C /* Main.storyboard */,
144 | EEDCDBA51B9F935500AE693C /* RNLBeacon+Distance.h */,
145 | EEDCDBA61B9F935500AE693C /* RNLBeacon+Distance.m */,
146 | EEDCDBA71B9F935500AE693C /* RNLBeaconScanner.h */,
147 | EEDCDBA81B9F935500AE693C /* RNLBeaconScanner.m */,
148 | EEDCDBA91B9F935500AE693C /* RNLBeaconParser.h */,
149 | EEDCDBAA1B9F935500AE693C /* RNLBeaconParser.m */,
150 | EEDCDBAB1B9F935500AE693C /* RNLBeacon.h */,
151 | EEDCDBAC1B9F935500AE693C /* RNLBeacon.m */,
152 | EEDCDBAD1B9F935500AE693C /* RNLBeaconTableViewController.h */,
153 | EEDCDBAE1B9F935500AE693C /* RNLBeaconTableViewController.m */,
154 | EEDCDB781B9F92FA00AE693C /* AppDelegate.h */,
155 | EEDCDB791B9F92FA00AE693C /* AppDelegate.m */,
156 | EEDCDB7E1B9F92FA00AE693C /* Main.storyboard */,
157 | EEDCDB811B9F92FA00AE693C /* Images.xcassets */,
158 | EEDCDB831B9F92FA00AE693C /* LaunchScreen.xib */,
159 | EEDCDB741B9F92FA00AE693C /* Supporting Files */,
160 | );
161 | path = "ios-beacon-tools";
162 | sourceTree = "";
163 | };
164 | EEDCDB741B9F92FA00AE693C /* Supporting Files */ = {
165 | isa = PBXGroup;
166 | children = (
167 | EEDCDB751B9F92FA00AE693C /* Info.plist */,
168 | EEDCDB761B9F92FA00AE693C /* main.m */,
169 | );
170 | name = "Supporting Files";
171 | sourceTree = "";
172 | };
173 | EEDCDB8D1B9F92FA00AE693C /* ios-beacon-toolsTests */ = {
174 | isa = PBXGroup;
175 | children = (
176 | EEDCDB901B9F92FA00AE693C /* ios_beacon_toolsTests.m */,
177 | EEDCDB8E1B9F92FA00AE693C /* Supporting Files */,
178 | );
179 | path = "ios-beacon-toolsTests";
180 | sourceTree = "";
181 | };
182 | EEDCDB8E1B9F92FA00AE693C /* Supporting Files */ = {
183 | isa = PBXGroup;
184 | children = (
185 | EEDCDB8F1B9F92FA00AE693C /* Info.plist */,
186 | );
187 | name = "Supporting Files";
188 | sourceTree = "";
189 | };
190 | /* End PBXGroup section */
191 |
192 | /* Begin PBXNativeTarget section */
193 | EEDCDB701B9F92FA00AE693C /* ios-beacon-tools */ = {
194 | isa = PBXNativeTarget;
195 | buildConfigurationList = EEDCDB941B9F92FA00AE693C /* Build configuration list for PBXNativeTarget "ios-beacon-tools" */;
196 | buildPhases = (
197 | EEDCDB6D1B9F92FA00AE693C /* Sources */,
198 | EEDCDB6E1B9F92FA00AE693C /* Frameworks */,
199 | EEDCDB6F1B9F92FA00AE693C /* Resources */,
200 | );
201 | buildRules = (
202 | );
203 | dependencies = (
204 | );
205 | name = "ios-beacon-tools";
206 | productName = "ios-beacon-tools";
207 | productReference = EEDCDB711B9F92FA00AE693C /* ios-beacon-tools.app */;
208 | productType = "com.apple.product-type.application";
209 | };
210 | EEDCDB891B9F92FA00AE693C /* ios-beacon-toolsTests */ = {
211 | isa = PBXNativeTarget;
212 | buildConfigurationList = EEDCDB971B9F92FA00AE693C /* Build configuration list for PBXNativeTarget "ios-beacon-toolsTests" */;
213 | buildPhases = (
214 | EEDCDB861B9F92FA00AE693C /* Sources */,
215 | EEDCDB871B9F92FA00AE693C /* Frameworks */,
216 | EEDCDB881B9F92FA00AE693C /* Resources */,
217 | );
218 | buildRules = (
219 | );
220 | dependencies = (
221 | EEDCDB8C1B9F92FA00AE693C /* PBXTargetDependency */,
222 | );
223 | name = "ios-beacon-toolsTests";
224 | productName = "ios-beacon-toolsTests";
225 | productReference = EEDCDB8A1B9F92FA00AE693C /* ios-beacon-toolsTests.xctest */;
226 | productType = "com.apple.product-type.bundle.unit-test";
227 | };
228 | /* End PBXNativeTarget section */
229 |
230 | /* Begin PBXProject section */
231 | EEDCDB691B9F92FA00AE693C /* Project object */ = {
232 | isa = PBXProject;
233 | attributes = {
234 | LastUpgradeCheck = 0640;
235 | ORGANIZATIONNAME = Altbeacon.org;
236 | TargetAttributes = {
237 | EEDCDB701B9F92FA00AE693C = {
238 | CreatedOnToolsVersion = 6.4;
239 | LastSwiftMigration = 0940;
240 | };
241 | EEDCDB891B9F92FA00AE693C = {
242 | CreatedOnToolsVersion = 6.4;
243 | TestTargetID = EEDCDB701B9F92FA00AE693C;
244 | };
245 | };
246 | };
247 | buildConfigurationList = EEDCDB6C1B9F92FA00AE693C /* Build configuration list for PBXProject "ios-beacon-tools" */;
248 | compatibilityVersion = "Xcode 3.2";
249 | developmentRegion = English;
250 | hasScannedForEncodings = 0;
251 | knownRegions = (
252 | English,
253 | en,
254 | Base,
255 | );
256 | mainGroup = EEDCDB681B9F92FA00AE693C;
257 | productRefGroup = EEDCDB721B9F92FA00AE693C /* Products */;
258 | projectDirPath = "";
259 | projectRoot = "";
260 | targets = (
261 | EEDCDB701B9F92FA00AE693C /* ios-beacon-tools */,
262 | EEDCDB891B9F92FA00AE693C /* ios-beacon-toolsTests */,
263 | );
264 | };
265 | /* End PBXProject section */
266 |
267 | /* Begin PBXResourcesBuildPhase section */
268 | EEDCDB6F1B9F92FA00AE693C /* Resources */ = {
269 | isa = PBXResourcesBuildPhase;
270 | buildActionMask = 2147483647;
271 | files = (
272 | EEDCDB801B9F92FA00AE693C /* Main.storyboard in Resources */,
273 | EEDCDB851B9F92FA00AE693C /* LaunchScreen.xib in Resources */,
274 | EEDCDB821B9F92FA00AE693C /* Images.xcassets in Resources */,
275 | EEDCDBB91B9F935500AE693C /* Main.storyboard in Resources */,
276 | EEDCDBC61B9F93BD00AE693C /* LICENSE in Resources */,
277 | );
278 | runOnlyForDeploymentPostprocessing = 0;
279 | };
280 | EEDCDB881B9F92FA00AE693C /* Resources */ = {
281 | isa = PBXResourcesBuildPhase;
282 | buildActionMask = 2147483647;
283 | files = (
284 | EEDCDBC71B9F93BD00AE693C /* LICENSE in Resources */,
285 | EEDCDBBA1B9F935500AE693C /* Main.storyboard in Resources */,
286 | );
287 | runOnlyForDeploymentPostprocessing = 0;
288 | };
289 | /* End PBXResourcesBuildPhase section */
290 |
291 | /* Begin PBXSourcesBuildPhase section */
292 | EEDCDB6D1B9F92FA00AE693C /* Sources */ = {
293 | isa = PBXSourcesBuildPhase;
294 | buildActionMask = 2147483647;
295 | files = (
296 | EEDCDBC31B9F935500AE693C /* RNLBeaconTableViewController.m in Sources */,
297 | EEAF8D92210153D3003E6402 /* sample.swift in Sources */,
298 | EEDCDBB71B9F935500AE693C /* RNLSignalMeasurement.m in Sources */,
299 | EEDCDBBF1B9F935500AE693C /* RNLBeaconParser.m in Sources */,
300 | EEDCDBBD1B9F935500AE693C /* RNLBeaconScanner.m in Sources */,
301 | EEDCDBB51B9F935500AE693C /* RNLLocationTracker.m in Sources */,
302 | EEDCDBC11B9F935500AE693C /* RNLBeacon.m in Sources */,
303 | EEDCDB7A1B9F92FA00AE693C /* AppDelegate.m in Sources */,
304 | EEDCDB771B9F92FA00AE693C /* main.m in Sources */,
305 | EEDCDBAF1B9F935500AE693C /* RNLAppDelegate.m in Sources */,
306 | EEDCDBBB1B9F935500AE693C /* RNLBeacon+Distance.m in Sources */,
307 | EEAF8D95210158AD003E6402 /* RNLURLBeaconCompressor.m in Sources */,
308 | EEDCDBB31B9F935500AE693C /* RNLBeaconTracker.m in Sources */,
309 | );
310 | runOnlyForDeploymentPostprocessing = 0;
311 | };
312 | EEDCDB861B9F92FA00AE693C /* Sources */ = {
313 | isa = PBXSourcesBuildPhase;
314 | buildActionMask = 2147483647;
315 | files = (
316 | EEDCDBC21B9F935500AE693C /* RNLBeacon.m in Sources */,
317 | EEDCDBB61B9F935500AE693C /* RNLLocationTracker.m in Sources */,
318 | EEDCDB911B9F92FA00AE693C /* ios_beacon_toolsTests.m in Sources */,
319 | EEDCDBB41B9F935500AE693C /* RNLBeaconTracker.m in Sources */,
320 | EEDCDBC41B9F935500AE693C /* RNLBeaconTableViewController.m in Sources */,
321 | EEAF8D96210158AD003E6402 /* RNLURLBeaconCompressor.m in Sources */,
322 | EEDCDBBE1B9F935500AE693C /* RNLBeaconScanner.m in Sources */,
323 | EEDCDBB81B9F935500AE693C /* RNLSignalMeasurement.m in Sources */,
324 | EEDCDBB01B9F935500AE693C /* RNLAppDelegate.m in Sources */,
325 | EEDCDBBC1B9F935500AE693C /* RNLBeacon+Distance.m in Sources */,
326 | EEDCDBC01B9F935500AE693C /* RNLBeaconParser.m in Sources */,
327 | );
328 | runOnlyForDeploymentPostprocessing = 0;
329 | };
330 | /* End PBXSourcesBuildPhase section */
331 |
332 | /* Begin PBXTargetDependency section */
333 | EEDCDB8C1B9F92FA00AE693C /* PBXTargetDependency */ = {
334 | isa = PBXTargetDependency;
335 | target = EEDCDB701B9F92FA00AE693C /* ios-beacon-tools */;
336 | targetProxy = EEDCDB8B1B9F92FA00AE693C /* PBXContainerItemProxy */;
337 | };
338 | /* End PBXTargetDependency section */
339 |
340 | /* Begin PBXVariantGroup section */
341 | EEDCDB7E1B9F92FA00AE693C /* Main.storyboard */ = {
342 | isa = PBXVariantGroup;
343 | children = (
344 | EEDCDB7F1B9F92FA00AE693C /* Base */,
345 | );
346 | name = Main.storyboard;
347 | sourceTree = "";
348 | };
349 | EEDCDB831B9F92FA00AE693C /* LaunchScreen.xib */ = {
350 | isa = PBXVariantGroup;
351 | children = (
352 | EEDCDB841B9F92FA00AE693C /* Base */,
353 | );
354 | name = LaunchScreen.xib;
355 | sourceTree = "";
356 | };
357 | /* End PBXVariantGroup section */
358 |
359 | /* Begin XCBuildConfiguration section */
360 | EEDCDB921B9F92FA00AE693C /* Debug */ = {
361 | isa = XCBuildConfiguration;
362 | buildSettings = {
363 | ALWAYS_SEARCH_USER_PATHS = NO;
364 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
365 | CLANG_CXX_LIBRARY = "libc++";
366 | CLANG_ENABLE_MODULES = YES;
367 | CLANG_ENABLE_OBJC_ARC = YES;
368 | CLANG_WARN_BOOL_CONVERSION = YES;
369 | CLANG_WARN_CONSTANT_CONVERSION = YES;
370 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
371 | CLANG_WARN_EMPTY_BODY = YES;
372 | CLANG_WARN_ENUM_CONVERSION = YES;
373 | CLANG_WARN_INT_CONVERSION = YES;
374 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
375 | CLANG_WARN_UNREACHABLE_CODE = YES;
376 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
377 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
378 | COPY_PHASE_STRIP = NO;
379 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
380 | ENABLE_STRICT_OBJC_MSGSEND = YES;
381 | GCC_C_LANGUAGE_STANDARD = gnu99;
382 | GCC_DYNAMIC_NO_PIC = NO;
383 | GCC_NO_COMMON_BLOCKS = YES;
384 | GCC_OPTIMIZATION_LEVEL = 0;
385 | GCC_PREPROCESSOR_DEFINITIONS = (
386 | "DEBUG=1",
387 | "$(inherited)",
388 | );
389 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
390 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
391 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
392 | GCC_WARN_UNDECLARED_SELECTOR = YES;
393 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
394 | GCC_WARN_UNUSED_FUNCTION = YES;
395 | GCC_WARN_UNUSED_VARIABLE = YES;
396 | IPHONEOS_DEPLOYMENT_TARGET = 8.4;
397 | MTL_ENABLE_DEBUG_INFO = YES;
398 | ONLY_ACTIVE_ARCH = YES;
399 | SDKROOT = iphoneos;
400 | TARGETED_DEVICE_FAMILY = "1,2";
401 | };
402 | name = Debug;
403 | };
404 | EEDCDB931B9F92FA00AE693C /* Release */ = {
405 | isa = XCBuildConfiguration;
406 | buildSettings = {
407 | ALWAYS_SEARCH_USER_PATHS = NO;
408 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
409 | CLANG_CXX_LIBRARY = "libc++";
410 | CLANG_ENABLE_MODULES = YES;
411 | CLANG_ENABLE_OBJC_ARC = YES;
412 | CLANG_WARN_BOOL_CONVERSION = YES;
413 | CLANG_WARN_CONSTANT_CONVERSION = YES;
414 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
415 | CLANG_WARN_EMPTY_BODY = YES;
416 | CLANG_WARN_ENUM_CONVERSION = YES;
417 | CLANG_WARN_INT_CONVERSION = YES;
418 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
419 | CLANG_WARN_UNREACHABLE_CODE = YES;
420 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
421 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
422 | COPY_PHASE_STRIP = NO;
423 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
424 | ENABLE_NS_ASSERTIONS = NO;
425 | ENABLE_STRICT_OBJC_MSGSEND = YES;
426 | GCC_C_LANGUAGE_STANDARD = gnu99;
427 | GCC_NO_COMMON_BLOCKS = YES;
428 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
429 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
430 | GCC_WARN_UNDECLARED_SELECTOR = YES;
431 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
432 | GCC_WARN_UNUSED_FUNCTION = YES;
433 | GCC_WARN_UNUSED_VARIABLE = YES;
434 | IPHONEOS_DEPLOYMENT_TARGET = 8.4;
435 | MTL_ENABLE_DEBUG_INFO = NO;
436 | SDKROOT = iphoneos;
437 | TARGETED_DEVICE_FAMILY = "1,2";
438 | VALIDATE_PRODUCT = YES;
439 | };
440 | name = Release;
441 | };
442 | EEDCDB951B9F92FA00AE693C /* Debug */ = {
443 | isa = XCBuildConfiguration;
444 | buildSettings = {
445 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
446 | CLANG_ENABLE_MODULES = YES;
447 | INFOPLIST_FILE = "ios-beacon-tools/Info.plist";
448 | IPHONEOS_DEPLOYMENT_TARGET = 17.6;
449 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
450 | PRODUCT_NAME = "$(TARGET_NAME)";
451 | SWIFT_OBJC_BRIDGING_HEADER = "ios-beacon-tools-Bridging-Header.h";
452 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
453 | SWIFT_VERSION = 5.0;
454 | };
455 | name = Debug;
456 | };
457 | EEDCDB961B9F92FA00AE693C /* Release */ = {
458 | isa = XCBuildConfiguration;
459 | buildSettings = {
460 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
461 | CLANG_ENABLE_MODULES = YES;
462 | INFOPLIST_FILE = "ios-beacon-tools/Info.plist";
463 | IPHONEOS_DEPLOYMENT_TARGET = 17.6;
464 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
465 | PRODUCT_NAME = "$(TARGET_NAME)";
466 | SWIFT_OBJC_BRIDGING_HEADER = "ios-beacon-tools-Bridging-Header.h";
467 | SWIFT_VERSION = 5.0;
468 | };
469 | name = Release;
470 | };
471 | EEDCDB981B9F92FA00AE693C /* Debug */ = {
472 | isa = XCBuildConfiguration;
473 | buildSettings = {
474 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
475 | BUNDLE_LOADER = "$(TEST_HOST)";
476 | FRAMEWORK_SEARCH_PATHS = (
477 | "$(SDKROOT)/Developer/Library/Frameworks",
478 | "$(inherited)",
479 | );
480 | GCC_PREPROCESSOR_DEFINITIONS = (
481 | "DEBUG=1",
482 | "$(inherited)",
483 | );
484 | INFOPLIST_FILE = "ios-beacon-toolsTests/Info.plist";
485 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
486 | PRODUCT_NAME = "$(TARGET_NAME)";
487 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ios-beacon-tools.app/ios-beacon-tools";
488 | };
489 | name = Debug;
490 | };
491 | EEDCDB991B9F92FA00AE693C /* Release */ = {
492 | isa = XCBuildConfiguration;
493 | buildSettings = {
494 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
495 | BUNDLE_LOADER = "$(TEST_HOST)";
496 | FRAMEWORK_SEARCH_PATHS = (
497 | "$(SDKROOT)/Developer/Library/Frameworks",
498 | "$(inherited)",
499 | );
500 | INFOPLIST_FILE = "ios-beacon-toolsTests/Info.plist";
501 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
502 | PRODUCT_NAME = "$(TARGET_NAME)";
503 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ios-beacon-tools.app/ios-beacon-tools";
504 | };
505 | name = Release;
506 | };
507 | /* End XCBuildConfiguration section */
508 |
509 | /* Begin XCConfigurationList section */
510 | EEDCDB6C1B9F92FA00AE693C /* Build configuration list for PBXProject "ios-beacon-tools" */ = {
511 | isa = XCConfigurationList;
512 | buildConfigurations = (
513 | EEDCDB921B9F92FA00AE693C /* Debug */,
514 | EEDCDB931B9F92FA00AE693C /* Release */,
515 | );
516 | defaultConfigurationIsVisible = 0;
517 | defaultConfigurationName = Release;
518 | };
519 | EEDCDB941B9F92FA00AE693C /* Build configuration list for PBXNativeTarget "ios-beacon-tools" */ = {
520 | isa = XCConfigurationList;
521 | buildConfigurations = (
522 | EEDCDB951B9F92FA00AE693C /* Debug */,
523 | EEDCDB961B9F92FA00AE693C /* Release */,
524 | );
525 | defaultConfigurationIsVisible = 0;
526 | defaultConfigurationName = Release;
527 | };
528 | EEDCDB971B9F92FA00AE693C /* Build configuration list for PBXNativeTarget "ios-beacon-toolsTests" */ = {
529 | isa = XCConfigurationList;
530 | buildConfigurations = (
531 | EEDCDB981B9F92FA00AE693C /* Debug */,
532 | EEDCDB991B9F92FA00AE693C /* Release */,
533 | );
534 | defaultConfigurationIsVisible = 0;
535 | defaultConfigurationName = Release;
536 | };
537 | /* End XCConfigurationList section */
538 | };
539 | rootObject = EEDCDB691B9F92FA00AE693C /* Project object */;
540 | }
541 |
--------------------------------------------------------------------------------