http://playground.arduino.cc/Interfacing/Cocoa ( IOKit/ioctl method )で提供されているコードに従って、Arduino から Cocoa アプリケーションにデータを送信するために、シリアル通信の例を実行しようとしています。動作しますが、一度開始した受信スレッドを停止することはできません。
開始時にシリアル ポートを開き、レシーバー スレッドを起動するスイッチ ボタン ( Start/Stop ) を実装しました。
- (IBAction) startButton: (NSButton *) btn {
(…)
error = [self openSerialPort: [SelectPort titleOfSelectedItem] baud:[Baud intValue]];
(…)
[self refreshSerialList:[SelectPort titleOfSelectedItem]];
[self performSelectorInBackground:@selector(incomingTextUpdateThread:) withObject:[NSThread currentThread]];
(…)
}
スレッド コードは、受信したバッファからシリアル パケットを再構築し、SQLite データベースに保存するコードを含めたことを除いて、例と実質的に同じです。
- (void)incomingTextUpdateThread: (NSThread *) parentThread {
// mark that the thread is running
readThreadRunning = TRUE;
const int BUFFER_SIZE = 100;
char byte_buffer[BUFFER_SIZE]; // buffer for holding incoming data
int numBytes=0; // number of bytes read during read
(…)
// assign a high priority to this thread
[NSThread setThreadPriority:1.0];
// this will loop until the serial port closes
while(TRUE) {
// read() blocks until some data is available or the port is closed
numBytes = (int) read(serialFileDescriptor, byte_buffer, BUFFER_SIZE); // read up to the size of the buffer
if(numBytes>0) {
// format serial data into packets, but first append at start the end of last read
buffer = [[NSMutableString alloc] initWithBytes:byte_buffer length:numBytes encoding:NSASCIIStringEncoding];
if (status == 1 && [ipacket length] != 0) {
[buffer insertString:ipacket atIndex:0];
numBytes = (int) [buffer length];
}
ipacket = [self processSerialData:buffer length:numBytes]; // Recompose data and save to database.
} else {
break; // Stop the thread if there is an error
}
}
// make sure the serial port is closed
if (serialFileDescriptor != -1) {
close(serialFileDescriptor);
serialFileDescriptor = -1;
}
// mark that the thread has quit
readThreadRunning = FALSE;
}
提供された例に従って、これも startButton セレクターの一部であるこのコードを使用して、メイン スレッドのポートを閉じようとします。
if (serialFileDescriptor != -1) {
[self appendToIncomingText:@"Trying to close the serial port...\n"];
close(serialFileDescriptor);
serialFileDescriptor = -1;
// Revisar... crec que el thread no s'adona que s'ha tancat el file descriptor...
// wait for the reading thread to die
while(readThreadRunning);
// re-opening the same port REALLY fast will fail spectacularly... better to sleep a sec
sleep(0.5);
//[btn setTitle:@"Start"];
[Start setTitle:@"Start"];
}
しかし、グローバル変数serialFileDescriptorの状態変化を受信スレッドが認識していないようです。