0

I'm currently developing an iPhone application regarding the communication between iPhone and OBDKey via wifi. So far so good. I managed to establish the TCP/IP communication using CFStream. My problem now: When I send some message to the OBDKey, the response is the exact same message.

I think the faulty code is somewhere in the stream method of the application. But I can't figure it out.

I hope you can give me some advice.

Here is the code:

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

Thank you in advance!!!

EDIT 1: I've tried my code using the terminal application on my Mac with Telnet (127.0.0.1:23). Both, sending and receiving works perfectly. But the response from the OBKey is the same as the request I'm sending.

EDIT 2: I figured it out: I have to send the initialising handshake commands to start the actual communication (ATZ, ATSP0 and ATL1). I've done this in a seperate method that is called up in the connection process of the app.

Greets, qoob

1 Answers1

0

I'm not into ios applications, so you might want to double-check if you didn't make any tyopo's in declaring the input/output seperately. Could be the case that you are using the input stream when you should have used your output-stream in 1 rule?

Something else popped into my head. Might be usefull to somebody who has the same symptoms. I don't really can see what data you receive, but because you said you receive the data you send, your echo could be turned on.

For a ELM327 device, you can turn the echo off by sending

E0
Eric Smekens
  • 1,602
  • 20
  • 32
  • Thank you for the response! I managed to figure it out. It was the initialisation handshake in general. The AT commands ATZ, ATSP0 and ATL1 have to be send before the actual communication can start. Thank you for your advice aswell!! – Marko Popovic May 03 '14 at 10:25