# 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 >= 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 > ~180 RPM if timestamp > (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 >> 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
// // BTLE.m // doraPhone // #import "BTLE.h" #import "AppDelegate.h" static CBUUID *kServiceCbuuidCadence, *kServiceDeviceInfo, *kCharacteristicDeviceModel, *kCharacteristicDeviceSerial, *kCharacteristicCadence ; static const char* cbCentralStateNames[] = { "CBCentralManagerStateUnknown", "CBCentralManagerStateResetting", "CBCentralManagerState", "CBCentralManagerStateUnauthorized", "CBCentralManagerStatePoweredOff", "CBCentralManagerStatePoweredOn" }; static const char* btleStateName(int state) { const char* stateName = "INVALID"; if (state >= 0 && state < sizeof(cbCentralStateNames)/sizeof(const char*)) { stateName = cbCentralStateNames[state]; } return stateName; } @implementation BTLE + (void)initialize { kServiceCbuuidCadence = [CBUUID UUIDWithString:@"1816"]; kServiceDeviceInfo = [CBUUID UUIDWithString:@"180A"]; kCharacteristicDeviceModel = [CBUUID UUIDWithString:@"2A24"]; kCharacteristicDeviceSerial = [CBUUID UUIDWithString:@"2A25"]; kCharacteristicCadence = [CBUUID UUIDWithString:@"2A5B"]; } - (void)startScan { if (![self isLECapableHardware]) { return; } [_manager scanForPeripheralsWithServices:@[kServiceCbuuidCadence] options:@{CBCentralManagerScanOptionAllowDuplicatesKey: @YES}]; NSLog(@"Started BLE scan"); } - (void)stopScan { [_manager stopScan]; } - (void)centralManagerDidUpdateState:(CBCentralManager *)central { NSLog(@"New Bluetooth state: %s", 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(@"Discovered services for peripheral"); for (CBService* s in peripheral.services) { NSLog(@"Service: %@", s.UUID); } for (CBService* s in peripheral.services) { if ([s.UUID isEqual:kServiceDeviceInfo]) { NSLog(@"Device info service found"); [peripheral discoverCharacteristics:[NSArray arrayWithObjects:kCharacteristicDeviceModel, kCharacteristicDeviceSerial, nil] forService:s]; } else if ([s.UUID isEqual:kServiceCbuuidCadence]) { NSLog(@"Cadence service found"); [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(@"Found characteristic: Cadence"); [peripheral setNotifyValue:YES forCharacteristic:c]; } else { NSLog(@"Discovered unsupported characteristic %@", c.UUID); } } } else if ([service.UUID isEqual:kServiceDeviceInfo]) { for (CBCharacteristic* c in service.characteristics) { NSLog(@"Discovered characteristic %@", c.UUID); if ([c.UUID isEqual:kCharacteristicDeviceModel] || [c.UUID isEqual:kCharacteristicDeviceSerial]) { [peripheral readValueForCharacteristic:c]; } } } else { NSLog(@"ERROR: got characteristics for service %@ - was not requesting those", service.UUID); return; } } - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { NSLog(@"Connected peripheral %@", 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(@"Device model: %@", _model); _model = model; } else if ([characteristic.UUID isEqual:kCharacteristicDeviceSerial]) { // // Convert to a hex string _serial = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding]; NSLog(@"Device serial: %@", _serial); } else { NSLog(@"ERROR: unexpected BLE Notify: %@ %@=%@", 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(@"Disconnected from %@ (%@)", 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(@"Connecting to \"%@\"", 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 = @"The platform/hardware doesn't support Bluetooth Low Energy."; break; case CBCentralManagerStateUnauthorized: errorString = @"The app is not authorized to use Bluetooth Low Energy."; break; case CBCentralManagerStatePoweredOff: errorString = @"Bluetooth is currently powered off."; break; case CBCentralManagerStatePoweredOn: result = TRUE; case CBCentralManagerStateUnknown: default: unknownState = YES; errorString = @"Unknown state"; ; //result = FALSE; } const char* stateName = btleStateName(state); NSLog(@"Central manager state: %s (%u)", stateName, state); if (!result && !unknownState) { UIAlertView *alert = [[UIAlertView alloc] init]; alert.message = errorString; [alert addButtonWithTitle:@"OK"]; [alert show]; } return result; } - (id)init { _queue = dispatch_queue_create("ru.intersofteurasia.do-ra.ble", NULL); _manager = [[CBCentralManager alloc] initWithDelegate:self queue:_queue]; return self; } - (void)dealloc { [self stopScan]; } @end
Source: https://habr.com/ru/post/230101/
All Articles