{"id":230101,"date":"2014-07-16T18:13:03","date_gmt":"2014-07-16T14:13:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=230101"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=230101","title":{"rendered":"<span class=\"post_title\">\u041a\u0440\u0443\u0447\u0443, \u043a\u0440\u0443\u0447\u0443, \u043a\u0440\u0443\u0447\u0443, \u043a\u0440\u0443\u0447\u0443 \u043f\u0435\u0434\u0430\u043b\u0438, \u043a\u0440\u0443\u0447\u0443<\/span>"},"content":{"rendered":"<div class=\"content html_format\">     \t\u0414\u0435\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0441\u043b\u0438 \u0438 \u043e\u0431\u043e\u0440\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0432\u043e\u0434\u0430 \u043d\u0430 \u0442\u0440\u0435\u043d\u0430\u0436\u0435\u0440\u0435. \u0412\u0435\u043b\u043e-\u0442\u0430\u0431\u043b\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u043a\u0440\u0443\u0442\u0438\u0442\u044c \u043f\u0435\u0434\u0430\u043b\u0438 \u0441\u0442\u0430\u043b\u043e \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e. \u042f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0447\u0438\u043d\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u043e \u043f\u043e-\u043d\u0430\u0448\u0435\u043d\u0441\u043a\u0438, \u043f\u043e ios-\u043e\u0432\u0441\u043a\u0438. <\/p>\n<p>  \u0418 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438   <\/p>\n<ul>\n<li>\u043f\u0440\u0438\u043c\u043e\u0442\u0430\u043b \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 BLE \u0434\u0430\u0442\u0447\u0438\u043a \u043a \u043a\u043e\u0440\u043f\u0443\u0441\u0443 \u0442\u0440\u0435\u043d\u0430\u0436\u0435\u0440\u0430<\/li>\n<li>\u043f\u0440\u0438\u043b\u0435\u043f\u0438\u043b \u043c\u0430\u0433\u043d\u0438\u0442 \u043a \u0448\u0430\u0442\u0443\u043d\u0443<\/li>\n<li>\u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u043f\u043e\u0434 iPad<\/li>\n<\/ul>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435, \u0441\u043e \u0441\u0445\u0435\u043c\u043e\u0439, \u0442\u0435\u043a\u0441\u0442\u043e\u043c, \u0444\u043e\u0442\u043e \u0438 \u0432\u0438\u0434\u0435\u043e.<br \/>  <a name=\"habracut\"><\/a><\/p>\n<h4>Cadence sensor<\/h4>\n<p>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/24d\/32b\/9f3\/24d32b9f30508dae563c197feb04a1e9.png\" alt=\"image\"\/><br \/>  \u0420\u0438\u0441. 1 \u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f \u0434\u0430\u0442\u0447\u0438\u043a\u0430<\/p>\n<p>  \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u2014 \u0433\u0435\u0440\u043a\u043e\u043d \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u0435\u0442 \u043d\u0430 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435 \u043c\u0430\u0433\u043d\u0438\u0442\u0430, \u0437\u0430\u043c\u044b\u043a\u0430\u0435\u0442 \u0446\u0435\u043f\u044c, BLE-\u0434\u0430\u0442\u0447\u0438\u043a \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 \u0441\u0438\u0433\u043d\u0430\u043b \u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0438.<\/p>\n<p>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/dac\/945\/ea8\/dac945ea81b4b949e4e050a2abd8f5f0.png\" alt=\"image\"\/><br \/>  \u0420\u0438\u0441. 2 \u0421\u0445\u0435\u043c\u0430 \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u0430 \u043e\u0431\u043e\u0440\u043c\u043e\u0442\u043e\u0432<\/p>\n<p>  \u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u0430\u0442\u0447\u0438\u043a\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043a\u0443\u043f\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0434\u0435\u0442\u0430\u043b\u0438  <\/p>\n<ul>\n<li>BLE112 \u2014 <a href=\"http:\/\/www.compel.ru\/infosheet\/BLUEGIGA\/BLE112-A-v1\/\">\u0431\u043b\u0443\u0442\u0443\u0437-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440<\/a> \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 BlueGiga<\/li>\n<li>\u043b\u0438\u0442\u0438\u0435\u0432\u0443\u044e \u0431\u0430\u0442\u0430\u0440\u0435\u0439\u043a\u0443 3 \u0432\u043e\u043b\u044c\u0442\u0430<\/li>\n<li><a href=\"http:\/\/ru.aliexpress.com\/item\/Magnetic-reed-switches-MKA-14103-AT10-15-2mm-14mm\/954776340.html\">\u0433\u0435\u0440\u043a\u043e\u043d<\/a> (\u043d\u0430 \u0441\u0445\u0435\u043c\u0435 S1)<\/li>\n<li>\u0441\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0434\u0432\u0430 \u043a\u043e\u043d\u0434\u0435\u043d\u0441\u0430\u0442\u043e\u0440\u0430<\/li>\n<li>\u0447\u0435\u0440\u043d\u0443\u044e \u043a\u043e\u0440\u043e\u0431\u043e\u0447\u043a\u0443<\/li>\n<\/ul>\n<p>   \u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0441\u0445\u0435\u043c\u0435.<br \/>  \u041e\u0431\u0449\u0430\u044f \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u2014 \u043c\u0435\u043d\u0435\u0435 $20.<\/p>\n<p>  \u0420\u0430\u0437\u043c\u0435\u0440 \u0434\u0430\u0442\u0447\u0438\u043a\u0430 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0435 3, \u0432\u0435\u0441 \u2014 50 \u0433\u0440\u0430\u043c\u043c\u043e\u0432.<br \/>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/0a1\/dfe\/fbe\/0a1dfefbea3e56ec10b11a9794cfcad4.png\" alt=\"image\"\/><br \/>  \u0420\u0438\u0441. 3 \u0420\u0430\u0437\u043c\u0435\u0440\u044b \u0434\u0430\u0442\u0447\u0438\u043a\u0430<\/p>\n<p>  BLE112 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0422\u0435\u043a\u0441\u0442 \u043f\u0440\u043e\u0448\u0438\u0432\u043a\u0438<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"perl\"># Cadence sensor prototype dim tmp(12) dim counter dim result dim last dim sleep_counter dim awake dim connected  event system_boot(major,minor,patch,build,ll_version,protocol,hw)     # call gap_set_mode(gap_general_discoverable,gap_undirected_connectable)     # call sm_set_bondable_mode(1)     # call hardware_set_soft_timer(32000 * 30, 0, 0)     # Set pins P1_0, P1_1 as output to prevent current leak (BLE112_Datasheet.pdf section 2.1)     call hardware_io_port_config_direction(1, 3)(result)     call hardware_io_port_write(1, 3, 3)(result)      # # Pull P0 up and enable interrupts on P0_0 (on falling edge)     #call hardware_io_port_config_pull(0, 0, 1)(result)     call hardware_io_port_config_irq(0, 1, 0)(result) end  event hardware_soft_timer(handle)     if connected = 0 then         sleep_counter = sleep_counter + 1         if sleep_counter &gt;= 2 then             # go to sleep                          # disable timer             call hardware_set_soft_timer(0, 0, 0)             awake = 0                          # disable BT broadcast             call gap_set_mode(gap_non_discoverable, gap_non_connectable)         end if     else         # read battery level         call hardware_adc_read(15,3,0)     end if end  event hardware_io_port_status(timestamp, port, irq, state)     # Debounce filter: ignore events with rates &gt; ~180 RPM     if timestamp &gt; (last + 10000) then         if awake = 0 then             call gap_set_mode(gap_general_discoverable, gap_undirected_connectable)             #call sm_set_bondable_mode(1)             call hardware_set_soft_timer(32000 * 60, 0, 0) # single shot sleep timer             awake = 1         end if         sleep_counter = 0         counter = counter + 1         result = timestamp &gt;&gt; 5         # S+C         tmp(0:1) = $3         tmp(1:4) = counter         tmp(5:2) = result         tmp(7:2) = counter         tmp(9:2) = result          call attributes_write(xgatt_cadence, 0, 11, tmp(0:11))     end if     last = timestamp end  event hardware_adc_result(input,value)     #battery level reading received, store to gatt     if input = 15 then         call attributes_write(xgatt_battery, 0, 2, value)     end if end  event connection_status(connection, flags, address, address_type, conn_interval, timeout, latency, bonding)     connected = 1 end  event connection_disconnected(handle,result)     call gap_set_mode(gap_general_discoverable, gap_undirected_connectable)     connected = 0 end <\/code><\/pre>\n<\/p><\/div>\n<\/div>\n<h4>\u041c\u0430\u0433\u043d\u0438\u0442<\/h4>\n<p>  \u041c\u0430\u0433\u043d\u0438\u0442 \u043a\u0440\u0435\u043f\u0438\u0442\u0441\u044f \u043a \u043b\u044e\u0431\u043e\u0439 \u0434\u0432\u0438\u0433\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u0447\u0430\u0441\u0442\u0438 \u0412\u0430\u0448\u0435\u0433\u043e \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u0430, \u0442\u0440\u0435\u043d\u0430\u0436\u0435\u0440\u0430, \u0448\u0430\u0433\u043e\u0436\u043e\u0440\u0430 \u0438 \u0442.\u0434. \u041d\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0435 4 \u043c\u0430\u0433\u043d\u0438\u0442 \u0432 \u0432\u0438\u0434\u0435 \u0448\u0430\u0439\u0431\u044b \u043f\u0440\u0438\u043b\u0435\u043f\u043b\u0435\u043d \u043a \u0448\u0430\u0433\u043e-\u0442\u0440\u0435\u043d\u0430\u0436\u0435\u0440\u0443.<\/p>\n<p>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/158\/5f6\/4e2\/1585f64e261a6637eb4d0629855bf8b5.jpg\" alt=\"image\"\/><br \/>  \u0420\u0438\u0441. 4 \u041a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0435 \u043c\u0430\u0433\u043d\u0438\u0442\u0430 \u043a \u0448\u0430\u0442\u0443\u043d\u0443<\/p>\n<p>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/749\/dda\/ccd\/749ddaccd3f0ae8d33d4967336668685.jpg\" alt=\"image\"\/><br \/>  \u0420\u0438\u0441. 5 \u041f\u0440\u0438 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0438 \u043c\u0430\u0433\u043d\u0438\u0442\u0430 \u043a \u0434\u0430\u0442\u0447\u0438\u043a\u0443, \u0434\u0430\u0442\u0447\u0438\u043a \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0438 \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430 iPad<\/p>\n<p>  \u041f\u0440\u0438 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0438 \u043a \u043c\u0430\u0433\u043d\u0438\u0442\u0443 \u0433\u0435\u0440\u043a\u043e\u043d \u0438\u0437\u0434\u0430\u0435\u0442 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u044b\u0439 \u0449\u0435\u043b\u0447\u043e\u043a \u2014 \u044d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u0440\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.<\/p>\n<h4>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u0434 iOS<\/h4>\n<p>  \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0435\u0445 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439  <\/p>\n<ul>\n<li>\u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0432\u0430\u044f \u2014 \u043f\u0440\u0438\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0442 BLE<\/li>\n<li>\u0447\u0430\u0441\u0442\u044c \u0432\u0442\u043e\u0440\u0430\u044f \u2014 \u0440\u0430\u0441\u0447\u0435\u0442 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0442\u0430<\/li>\n<li>\u0447\u0430\u0441\u0442\u044c \u0442\u0440\u0435\u0442\u044c\u044f \u2014 3D \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f <\/li>\n<\/ul>\n<h4>\u041f\u0440\u0438\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0442 BLE<\/h4>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u043a\u0430\u043d\u0438\u0440\u0443\u0435\u043c \u0441\u0438\u0433\u043d\u0430\u043b \u043e\u0442 BLE<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">\/\/ \/\/  BTLE.m \/\/  doraPhone \/\/ \/\/  Created by Kirill Novichikhin on 2\/5\/13. \/\/ \/\/  #import &quot;BTLE.h&quot; #import &quot;AppDelegate.h&quot;   static CBUUID     *kServiceCbuuidCadence,     *kServiceDeviceInfo,     *kCharacteristicDeviceModel,     *kCharacteristicDeviceSerial,     *kCharacteristicCadence ;  static const char* cbCentralStateNames[] = {     &quot;CBCentralManagerStateUnknown&quot;,     &quot;CBCentralManagerStateResetting&quot;,     &quot;CBCentralManagerState&quot;,     &quot;CBCentralManagerStateUnauthorized&quot;,     &quot;CBCentralManagerStatePoweredOff&quot;,     &quot;CBCentralManagerStatePoweredOn&quot; };  static const char* btleStateName(int state) {     const char* stateName = &quot;INVALID&quot;;     if (state &gt;= 0 && state &lt; sizeof(cbCentralStateNames)\/sizeof(const char*)) {         stateName = cbCentralStateNames[state];     }     return stateName; }  @implementation BTLE  + (void)initialize {     kServiceCbuuidCadence = [CBUUID UUIDWithString:@&quot;1816&quot;];     kServiceDeviceInfo = [CBUUID UUIDWithString:@&quot;180A&quot;];     kCharacteristicDeviceModel = [CBUUID UUIDWithString:@&quot;2A24&quot;];     kCharacteristicDeviceSerial = [CBUUID UUIDWithString:@&quot;2A25&quot;];     kCharacteristicCadence = [CBUUID UUIDWithString:@&quot;2A5B&quot;]; }  - (void)startScan {     if (![self isLECapableHardware]) {         return;     }     [_manager scanForPeripheralsWithServices:@[kServiceCbuuidCadence]                                      options:@{CBCentralManagerScanOptionAllowDuplicatesKey: @YES}];     NSLog(@&quot;Started BLE scan&quot;); }  - (void)stopScan {     [_manager stopScan]; }  - (void)centralManagerDidUpdateState:(CBCentralManager *)central {     NSLog(@&quot;New Bluetooth state: %s&quot;, btleStateName(central.state));     switch (central.state) {         case CBCentralManagerStatePoweredOn:             [self startScan];             break;         case CBCentralManagerStateResetting:         case CBCentralManagerStateUnauthorized:         case CBCentralManagerStateUnknown:         case CBCentralManagerStateUnsupported:         case CBCentralManagerStatePoweredOff:             break;     } }  - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {     NSLog(@&quot;Discovered services for peripheral&quot;);     for (CBService* s in peripheral.services) {         NSLog(@&quot;Service: %@&quot;, s.UUID);     }     for (CBService* s in peripheral.services) {         if ([s.UUID isEqual:kServiceDeviceInfo]) {             NSLog(@&quot;Device info service found&quot;);             [peripheral discoverCharacteristics:[NSArray arrayWithObjects:kCharacteristicDeviceModel, kCharacteristicDeviceSerial, nil] forService:s];         } else if ([s.UUID isEqual:kServiceCbuuidCadence]) {             NSLog(@&quot;Cadence service found&quot;);             [peripheral discoverCharacteristics:@[kCharacteristicCadence] forService:s];         }     } }  - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {     if ([service.UUID isEqual:kServiceCbuuidCadence]) {         for (CBCharacteristic* c in service.characteristics) {             if ([c.UUID isEqual:kCharacteristicCadence]) {                 NSLog(@&quot;Found characteristic: Cadence&quot;);                 [peripheral setNotifyValue:YES forCharacteristic:c];             } else {                 NSLog(@&quot;Discovered unsupported characteristic %@&quot;, c.UUID);             }         }     } else if ([service.UUID isEqual:kServiceDeviceInfo]) {         for (CBCharacteristic* c in service.characteristics) {             NSLog(@&quot;Discovered characteristic %@&quot;, c.UUID);             if ([c.UUID isEqual:kCharacteristicDeviceModel] || [c.UUID isEqual:kCharacteristicDeviceSerial]) {                 [peripheral readValueForCharacteristic:c];             }         }     } else {         NSLog(@&quot;ERROR: got characteristics for service %@ - was not requesting those&quot;, service.UUID);         return;     } }  - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {     NSLog(@&quot;Connected peripheral %@&quot;, peripheral);      AppDelegate *appRoot = (AppDelegate *)[[UIApplication sharedApplication] delegate];      \/\/ TODO     appRoot.isConnected = true;      \/\/ FIXME: delegate needs to be set to blePeripheral     peripheral.delegate = self;     [peripheral discoverServices:@[kServiceCbuuidCadence, kServiceDeviceInfo]]; }   -(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {     if ([characteristic.UUID isEqual:kCharacteristicCadence]) {         NSData* data = characteristic.value;         AppDelegate *appRoot = (AppDelegate *)[[UIApplication sharedApplication] delegate];         \/\/ TODO         appRoot.serial = _serial;         appRoot.model = _model;         [appRoot performSelectorOnMainThread:@selector(newCadenceMeasurement:)                                    withObject:data                                 waitUntilDone:NO];     } else if ([characteristic.UUID isEqual:kCharacteristicDeviceModel]) {         NSString* model = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];         NSLog(@&quot;Device model: %@&quot;, _model);         _model = model;     } else if ([characteristic.UUID isEqual:kCharacteristicDeviceSerial]) { \/\/        \/\/ Convert to a hex string         _serial = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];          NSLog(@&quot;Device serial: %@&quot;, _serial);     } else {         NSLog(@&quot;ERROR: unexpected BLE Notify: %@ %@=%@&quot;, peripheral, characteristic.UUID, characteristic.value);     } }   - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {     AppDelegate *appRoot = (AppDelegate *)[[UIApplication sharedApplication] delegate];          appRoot.isConnected = false;     self.peripheral = nil;  \/\/    BLEPeripheral* blePeripheral = [_peripherals ensurePeripheral:peripheral];     NSLog(@&quot;Disconnected from %@ (%@)&quot;, peripheral.name, error.description); }  - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {     if (self.peripheral == nil) {         [central connectPeripheral:peripheral options:nil];         NSLog(@&quot;Connecting to \\&quot;%@\\&quot;&quot;, peripheral.name);         self.peripheral = peripheral;     } }  \/*  Uses CBCentralManager to check whether the current platform\/hardware supports Bluetooth LE. An alert is raised if Bluetooth LE is not enabled or is not supported.  *\/ - (BOOL)isLECapableHardware {     BOOL result = FALSE;     BOOL unknownState = NO;     NSString * errorString = nil;          int state = [_manager state];     switch (state)     {         case CBCentralManagerStateUnsupported:             errorString = @&quot;The platform\/hardware doesn't support Bluetooth Low Energy.&quot;;             break;         case CBCentralManagerStateUnauthorized:             errorString = @&quot;The app is not authorized to use Bluetooth Low Energy.&quot;;             break;         case CBCentralManagerStatePoweredOff:             errorString = @&quot;Bluetooth is currently powered off.&quot;;             break;         case CBCentralManagerStatePoweredOn:             result = TRUE;         case CBCentralManagerStateUnknown:         default:             unknownState = YES;             errorString = @&quot;Unknown state&quot;;             ;             \/\/result = FALSE;     }               const char* stateName = btleStateName(state);          NSLog(@&quot;Central manager state: %s (%u)&quot;, stateName, state);          if (!result && !unknownState) {         UIAlertView *alert = [[UIAlertView alloc] init];         alert.message = errorString;         [alert addButtonWithTitle:@&quot;OK&quot;];         [alert show];     }     return result; }  - (id)init {     _queue = dispatch_queue_create(&quot;ru.intersofteurasia.do-ra.ble&quot;, NULL);     _manager = [[CBCentralManager alloc] initWithDelegate:self queue:_queue];     return self; }  - (void)dealloc {     [self stopScan]; } @end  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<h4>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f<\/h4>\n<p>  \u0411\u044b\u0441\u0442\u0440\u043e \u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0440\u0430\u0441\u0441\u0443 \u2014 \u043c\u043e\u0441\u0442 \u0432 \u041a\u0440\u044b\u043c. \u041a\u0442\u043e-\u0431\u044b \u043d\u0435 \u0432\u043b\u0430\u0434\u0435\u043b \u041a\u0440\u044b\u043c\u043e\u043c \u2014 \u043c\u043e\u0441\u0442 \u043d\u0443\u0436\u0435\u043d. \u0414\u043b\u0438\u043d\u0430 6.2 \u043a\u043c. \u0428\u0438\u0440\u0438\u043d\u0430 10 \u043c\u0435\u0442\u0440\u043e\u0432. \u042f \u0441\u0434\u0435\u043b\u0430\u043b 256 \u0430\u0441\u0444\u0430\u043b\u044c\u0442\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u0438\u0433\u043e\u043d\u043e\u0432 \u0434\u043b\u0438\u043d\u043e\u0439 2 \u043c\u0435\u0442\u0440\u0430 \u0438 \u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0436\u0435 \u0442\u0440\u0430\u0432\u044b \u043f\u043e \u043e\u0431\u043e\u0447\u0438\u043d\u0430\u043c (\u0440\u0438\u0441\u0443\u043d\u043e\u043a 6)<\/p>\n<p>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/679\/7ee\/5ee\/6797ee5ee0346db1e974139a2e9b1cc9.jpg\" alt=\"image\"\/><br \/>  \u0420\u0438\u0441\u0443\u043d\u043e\u043a 6. \u041c\u043e\u0441\u0442<br \/>  \u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0441\u043e\u043f\u0435\u0440\u043d\u0438\u043a\u0430.<br \/>  \u0421\u043e\u043f\u0435\u0440\u043d\u0438\u043a \u0432\u0437\u044f\u0442 \u0441 \u0422\u0443\u0440 \u0414\u0435 \u0424\u0440\u0430\u043d\u0441. \u042f\u043d \u0423\u043b\u044c\u0440\u0438\u0445. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e 4-\u0435\u0445 \u043a\u0430\u0434\u0440\u043e\u0432 \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u042f\u043d\u0430. 4 \u043a\u0430\u0434\u0440\u0430 \u043d\u0430 1 \u043e\u0431\u043e\u0440\u043e\u0442 \u043f\u0435\u0434\u0430\u043b\u0435\u0439. \u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0435 \u0430\u0445\u0442\u0438, \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0431\u044b\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u0430 \u0437\u0430 \u0434\u0435\u043d\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0435\u0437 \u0438\u0437\u044b\u0441\u043a\u043e\u0432.<br \/>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/4be\/311\/093\/4be311093c0f6dafba3a988b03fa9d8d.jpg\" alt=\"image\"\/><br \/>  \u0420\u0438\u0441\u0443\u043d\u043e\u043a 7. \u042f\u043d \u0423\u043b\u044c\u0440\u0438\u0445<\/p>\n<p>  \u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0441\u0435\u0431\u044f \u2014 \u044d\u0442\u043e \u0441\u0432\u044f\u0442\u043e\u0435.<br \/>  \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0443\u0448\u043b\u043e \u043d\u0430 \u0441\u0435\u0431\u044f. \u042f \u043f\u0440\u0438\u0441\u043b\u043e\u043d\u0438\u043b \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434 \u0432 \u0443\u0433\u043e\u043b \u043e\u0444\u0438\u0441\u0430 \u0438 \u0432\u0437\u0433\u0440\u043e\u043c\u043e\u0437\u0434\u0438\u043b\u0441\u044f \u043d\u0430 \u043d\u0435\u0433\u043e, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0430\u044f \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435.<br \/>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/d22\/4ba\/675\/d224ba67551823030b609b8cb9c2d6a2.jpg\" alt=\"image\"\/><br \/>  \u0420\u0438\u0441\u0443\u043d\u043e\u043a 8. \u042f \u0432 \u043e\u0444\u0438\u0441\u0435 \u043d\u0430 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u0435.<\/p>\n<p>  16 \u0440\u0430\u0437 \u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u043e \u043a\u0440\u0443\u0442\u0430\u043d\u0443\u043b \u043f\u0435\u0434\u0430\u043b\u0438 \u2014 \u0441\u0434\u0435\u043b\u0430\u043b 16 \u043a\u0430\u0434\u0440\u043e\u0432, \u043f\u043e\u0447\u0438\u0441\u0442\u0438\u043b \u0432 \u0444\u043e\u0442\u043e\u0448\u043e\u043f\u0435, \u0441\u043a\u043b\u0435\u0438\u043b \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e. \u041f\u043e\u0441\u043b\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c 12 \u043a\u0430\u0434\u0440\u043e\u0432 \u043d\u0430 1 \u043e\u0431\u043e\u0440\u043e\u0442 \u043f\u0435\u0434\u0430\u043b\u0435\u0439.<\/p>\n<p>  \u0414\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0430 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0440\u0430\u0437\u043c\u043d\u043e\u0436\u0438\u0442\u044c \u042f\u043d\u0430 \u0423\u043b\u044c\u0440\u0438\u0445\u0430 \u0434\u043e 50 \u043a\u043e\u043f\u0438\u0439 \u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430.<br \/>  \u0417\u0430\u043c\u0435\u0447\u0443, \u043f\u043e\u043a\u0430 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u043b\u0441\u044f \u2014 \u043d\u0430\u043a\u0430\u0447\u0430\u043b \u043b\u044f\u0445\u0438.<\/p>\n<p>  \u041f\u043e\u043b\u0435\u0437\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0441\u043a\u0430\u0436\u0443 \u0412\u0430\u043c, \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0448\u044c \u0433\u043e\u043d\u043a\u0443 \u0438 \u0443\u0436\u0435 \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f.<\/p>\n<p>  \u0412 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 45-\u0441\u0435\u043a\u0443\u043d\u0434\u043d\u043e\u0435 \u0432\u0438\u0434\u0435\u043e, \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442<\/p>\n<p>  <iframe loading=\"lazy\" width=\"560\" height=\"349\" src=\"\/\/www.youtube.com\/embed\/MwbnpZTCEbo?wmode=opaque\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n<p>  \u0418\u0437\u0432\u0438\u043d\u044f\u044e\u0441\u044c \u0437\u0430 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0438\u0434\u0435\u043e, \u0437\u0430\u0442\u043e \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0441\u043d\u0438\u043c\u0430\u043b\u043e\u0441\u044c \u043d\u0430 5-\u044b\u0439 iPhone).<\/p>\n<p>  \u0412\u0441\u0435\u043c \u0441\u043f\u0430\u0441\u0438\u0431\u043e. \u041a\u0440\u0443\u0442\u0438\u0442\u0435 \u043f\u0435\u0434\u0430\u043b\u0438.      \t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/230101\/\"> http:\/\/habrahabr.ru\/post\/230101\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">     \t\u0414\u0435\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0441\u043b\u0438 \u0438 \u043e\u0431\u043e\u0440\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0432\u043e\u0434\u0430 \u043d\u0430 \u0442\u0440\u0435\u043d\u0430\u0436\u0435\u0440\u0435. \u0412\u0435\u043b\u043e-\u0442\u0430\u0431\u043b\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u043a\u0440\u0443\u0442\u0438\u0442\u044c \u043f\u0435\u0434\u0430\u043b\u0438 \u0441\u0442\u0430\u043b\u043e \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e. \u042f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0447\u0438\u043d\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u043e \u043f\u043e-\u043d\u0430\u0448\u0435\u043d\u0441\u043a\u0438, \u043f\u043e ios-\u043e\u0432\u0441\u043a\u0438. <\/p>\n<p>  \u0418 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438   <\/p>\n<ul>\n<li>\u043f\u0440\u0438\u043c\u043e\u0442\u0430\u043b \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 BLE \u0434\u0430\u0442\u0447\u0438\u043a \u043a \u043a\u043e\u0440\u043f\u0443\u0441\u0443 \u0442\u0440\u0435\u043d\u0430\u0436\u0435\u0440\u0430<\/li>\n<li>\u043f\u0440\u0438\u043b\u0435\u043f\u0438\u043b \u043c\u0430\u0433\u043d\u0438\u0442 \u043a \u0448\u0430\u0442\u0443\u043d\u0443<\/li>\n<li>\u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u043f\u043e\u0434 iPad<\/li>\n<\/ul>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435, \u0441\u043e \u0441\u0445\u0435\u043c\u043e\u0439, \u0442\u0435\u043a\u0441\u0442\u043e\u043c, \u0444\u043e\u0442\u043e \u0438 \u0432\u0438\u0434\u0435\u043e.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-230101","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/230101","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=230101"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/230101\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=230101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=230101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=230101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}