vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

MacとiOSをBLEで連携 - Peripheral編2

前回の続きです。

UI部分とBLEの呼び出し部分を作成します。

やりたいこと

  • 0.05秒に一度ずつ、Central端末から受け取った値を更新してTextFieldに表示します。
  • 1秒に一度ずつ値を更新して、Central端末にNotifyが届くようにする。

AppDelegate.h

プロジェクト作成時に生成されたものから変更はありません。

#import < Cocoa / Cocoa.h >

@interface AppDelegate : NSObject 
@end

AppDelegate.m

#import "AppDelegate.h"
#import "PeripheralController.h"

@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
@property (weak) IBOutlet NSTextField               *txtGotValue;
@property (weak) IBOutlet NSTextField               *txtSendValue;
@property (weak) IBOutlet NSButton                  *btnStop;
@property (strong, nonatomic) PeripheralController  *ctrPeripheral;
@property (strong, nonatomic) NSTimer               *tmrUpdateText;
@property (strong, nonatomic) NSTimer               *tmrSendValue;
@property (nonatomic) int                           intSendValue;
- (IBAction)btnStopClicked:(id)sender;
@end
@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    _ctrPeripheral = [[PeripheralController alloc] init];
    // Bluetoothの使用準備. PeripheralManagerの初期化.
    [_ctrPeripheral initPeripheralController];
    
    // タイマーの起動.
    [self startUpdateTextTimer];
    [self startSendValueTimer];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
    // Insert code here to tear down your application
}
- (void)startUpdateTextTimer
{
    // 0.05秒ごとにCentralから取得した値を更新.
    _tmrUpdateText = [NSTimer scheduledTimerWithTimeInterval:0.05f target:self selector:@selector(updateText:) userInfo:nil repeats:YES];
}
- (void)updateText:(NSTimer *)timer
{
    // Centralから取得した値をTextFieldに入れる.
    _txtGotValue.stringValue = [_ctrPeripheral getCentralValue];
}
- (void)stopUpdateLabelTimer
{
    if(_tmrUpdateText)
    {
        [_tmrUpdateText invalidate];
        _tmrUpdateText = nil;
    }
}
- (void)startSendValueTimer
{
    // Centralに送信する値の更新は1秒ごとに実行.
    _tmrSendValue = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(sendValue:) userInfo:nil repeats:YES];
}
- (void)sendValue:(NSTimer *)timer
{
    // 999までの乱数をCentralに送信する.
    _intSendValue = (int)arc4random_uniform(999);
    [_ctrPeripheral updatePeripheralValue:_intSendValue];
    
    _txtSendValue.stringValue = [NSString stringWithFormat:@"%d", _intSendValue];
}
- (void)stopSendValueTimer
{
    if(_tmrSendValue)
    {
        [_tmrSendValue invalidate];
        _tmrSendValue = nil;
    }
}

- (IBAction)btnStopClicked:(id)sender
{
    [self stopUpdateLabelTimer];
    [self stopSendValueTimer];
    [_ctrPeripheral close];
}
@end

ほぼコメント通りなのですが、NSTimerはSelectorを実行する時間を設定して初期化した時点でタイマーが動作開始されるのですね。

2つ同時に実行しても、動作上特に問題はなさそうでしたので、UnityやopenFrameworksでのupdate関数のような動作を実現したい場合に使えそうです。

次はiPhone側、Centralについて。

参考

Objective-C(Timer, 乱数)