0

我目前正在开发一个关于 iPhone 和 OBDKey 通过 wifi 进行通信的 iPhone 应用程序。到目前为止,一切都很好。我设法使用 CFStream 建立 TCP/IP 通信。我现在的问题:当我向 OBDKey 发送一些消息时,响应是完全相同的消息。

我认为错误代码位于应用程序的流方法中。但我无法弄清楚。

我希望你能给我一些建议。

这是代码:

CFReadStreamRef readStream;
CFWriteStreamRef writeStream;

NSInputStream *inputStream;
NSOutputStream *outputStream;

@implementation Communicator
@synthesize textField; //Gegenstück zu @property im .h File
@synthesize textView;  //Gegenstück zu @property im .h File


- (IBAction)connectPressed:(id)sender {

    host = @"192.168.0.74";
    port = 23;

    //Ausgabe
    [self debugPrint:[NSString stringWithFormat:@"Setting up connection to %@ : %i", host, port]];

    //Stream wird erzeugt mit Host, Port, Read & Write stream
    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,  (__bridge CFStringRef)(host), port, &readStream, &writeStream);


    //Überprüfung ob Write Stream funktioniert
    if (!CFWriteStreamOpen(writeStream))     {

        [self debugPrint:[NSString stringWithFormat:@"Error, writeStream not open"]];

        return;
    }


    //Methode open wird geöffnet
    [self open];

    [self debugPrint:[NSString stringWithFormat:@"Status of outputStream: %i", [outputStream streamStatus]]];

    return;
}

//Hier werden sowohl der Output(Write)- als auch der Input(Read)-Stream geöffnet.
- (void)open {

    [self debugPrint:[NSString stringWithFormat:@"Opening streams..."]];

    //Da Automatic Reference Counting betrieben wird, muss eine __bridge Notation gesetzt werden um
    //das Objekt hin und her verwenden zu können.
    inputStream = (__bridge NSInputStream *)readStream;
    outputStream = (__bridge NSOutputStream *)writeStream;

    [inputStream setDelegate:self];
    [outputStream setDelegate:self];

    //RunLoop wird verwendet um input und output Objekte zu managen (Reihenfolgen usw.)
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];



    [inputStream open];
    [outputStream open];

    //Überprüfung ob beide Streams geöffnet wurden
    if (!inputStream && !outputStream)
    {
        [self debugPrint:[NSString stringWithFormat:@"Error. Could not open streams!"]];

        return;
    }

    //[self debugPrint:[NSString stringWithFormat:@"Streams are open"]];


}

//Disconnect Button wird gedrückt - Hierbei werden alle input und output streams geschlossen
//und RunLoops geschlossen
- (IBAction)disconnectPressed:(id)sender {

    [inputStream close];
    [outputStream close];

    [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [inputStream setDelegate:nil];
    [outputStream setDelegate:nil];

    inputStream = nil;
    outputStream = nil;


    [self debugPrint:[NSString stringWithFormat:@"Session closed!"]];


}

//Methode welche den eingegeben Text vom TextField in das TextView schreibt
- (IBAction)sendPressed:(id)sender {

    //Hier wird überprüft ob eine Eingabe im textField erfolgt ist (ob Zeichen eingegeben wurden)
    if ([[textField text] length] > 0) {
        NSString *textFieldString = [textField text];

        [self writeOut:(NSString *)textFieldString];

        [self.textField endEditing:YES];
    }

}

- (IBAction)clearViewPressed:(id)sender {

    textView.text = nil;

}

//Methode in der Text formatiert im textView angezeigt werden kann
- (void)debugPrint:(NSString *)text {
    textView.text = [textView.text stringByAppendingFormat: @"\n%@", text];
}

//Methode die Zuständig ist zum Stream handling
//NSStreamEventNone = 0
//NSStreamEventOpenCompleted = 1
//NSStreamHasBytesAvailable = 2
//NSStreamHasSpaceAvailable = 4
//NSStreamEventErrorOccurred = 8
//NSStreamEventEndEncountered = 16

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event {

    if (stream.streamStatus == 2){

    [self debugPrint:[NSString stringWithFormat:@"Stream opened"]];

    }

    switch (event) {

        case NSStreamEventHasSpaceAvailable: {
            if (stream == outputStream){
                [self debugPrint:[NSString stringWithFormat:@"Ouput stream is ready!"]];
            }
            break;
        }
        case NSStreamEventHasBytesAvailable: {
            if (stream == inputStream) {

            [self debugPrint:[NSString stringWithFormat:@"Input stream is ready!"]];

                uint8_t buf[1024];
                unsigned int len = 0; //len wird nie negativ sein => unsigned

                len = [inputStream read:buf maxLength:1024];

                if (len > 0) {

                    NSMutableData* data=[[NSMutableData alloc] initWithLength:0];

                    //data wird mit Daten aus dem Buffer buf gefüttert (maximale Länge len)
                    [data appendBytes: (const void *)buf length:len];

                    //Erlaubt die Konvertierung eines Datenstrings in einen Characterstring
                    NSString *raw_data = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

                    //sends raw_data to readIn method
                    [self readIn:raw_data];


                }


            }
            break;

        }
        default: {

            [self debugPrint:[NSString stringWithFormat:@"Stream is sending an Event: %u", event]];
            break;
        }
    }
}


- (void)readIn:(NSString *)s {
    [self debugPrint:[NSString stringWithFormat:@"Reading:"]];
    [self debugPrint:[NSString stringWithFormat:@"%@",s]];
}

- (void)writeOut:(NSString *)string {

    uint8_t *buf = (uint8_t *)[string UTF8String];

    [outputStream write:buf maxLength:strlen((char *)buf)];
    [self debugPrint:[NSString stringWithFormat:@"%s\r\n",buf]];
    //[self debugPrint:[NSString stringWithFormat:@"Sent:"]];
    //[self debugPrint:[NSString stringWithFormat:@"%@\r\n",string]];
}

@end

先感谢您!!!

编辑 1:我已经在我的 Mac 上使用 Telnet (127.0.0.1:23) 的终端应用程序尝试了我的代码。发送和接收都完美无缺。但是来自 OBKey 的响应与我发送的请求相同。

编辑 2:我想通了:我必须发送初始化握手命令才能开始实际通信(ATZ、ATSP0 和 ATL1)。我已经在应用程序连接过程中调用的单独方法中完成了此操作。

问候,qoob

4

1 回答 1

0

我不喜欢 ios 应用程序,因此您可能需要仔细检查是否在单独声明输入/输出时没有做出任何错误。当您应该在 1 条规则中使用输出流时,您可能会使用输入流吗?

别的东西突然出现在我的脑海里。可能对有相同症状的人有用。我真的看不出你收到了什么数据,但是因为你说你收到了你发送的数据,你的回声可以打开。

对于 ELM327 设备,您可以通过发送关闭回声

E0
于 2014-04-24T19:43:50.940 回答