【问题标题】:Inappropriate response from OBDKey (inputStream)来自 OBDKey (inputStream) 的不适当响应
【发布时间】:2014-04-23 18:22:06
【问题描述】:

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

我认为错误代码位于应用程序的 stream 方法 中。但我想不通。

希望你能给我一些建议。

代码如下:

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)。我已经在应用程序连接过程中调用的单独方法中完成了此操作。

您好, 呸呸呸

【问题讨论】:

    标签: ios objective-c inputstream obd-ii


    【解决方案1】:

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

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

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

    E0
    

    【讨论】:

    • 感谢您的回复!我设法弄清楚了。一般来说,这是初始化握手。必须先发送 AT 命令 ATZ、ATSP0 和 ATL1,然后才能开始实际通信。也谢谢你的建议!!
    猜你喜欢
    • 1970-01-01
    • 2022-12-02
    • 2011-10-19
    • 2013-02-28
    • 2012-01-07
    • 1970-01-01
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多