1

I am using a device called a WiFly that has ip address:169.254.1.1 and port 2000. I am trying to connect to this device via an iOS application. I use the following code to connect:

CFReadStreamRef readStream;
CFWriteStreamRef writeStream;

UInt32 port = 2000;
CFStringRef host = CFSTR("169.254.1.1");

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, &readStream, &writeStream);

inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;

// set the delegates to this view controller
[inputStream setDelegate:self];
[outputStream setDelegate:self];

// Set run loops to continuous receive information
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

// Finally, open the connection
[inputStream open];
[outputStream open];

Then I use the following to handle stream events:

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
    NSLog(@"stream event %i", streamEvent);

    switch (streamEvent) {

        case NSStreamEventOpenCompleted:
            NSLog(@"Stream opened");
            break;

        case NSStreamEventHasBytesAvailable:
            if (theStream == inputStream) {

                uint8_t buffer[1024];
                int len;

                while ([inputStream hasBytesAvailable]) {
                    len = [inputStream read:buffer maxLength:sizeof(buffer)];
                    if (len > 0) {

                        NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];

                        if (nil != output) {
                            NSLog(@"server said: %@", output);
                            [self messageReceived:output];
                        }
                    }
                }
            }
            break;

        case NSStreamEventErrorOccurred:
            NSLog(@"Can't connect to server");
            break;

        case NSStreamEventEndEncountered:
            [theStream close];
            [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            break;

        default:
            NSLog(@"Unknown event");
    }

So, I can see that the first two streams are opened correctly. Then it follows immediately with a stream event 4, which from my understanding is to be expected. However, I then try to call a function:

- (IBAction)moveForward
{
    NSLog(@"move forward called");
    NSString *response  = [NSString stringWithFormat:@"2"];
    NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
    [outputStream write:[data bytes] maxLength:[data length]];
}

Which should return "forward" from an arduino uno via the wifly. However, when I click, I get another NSStreamEvent 4 for some reason. I also telnetted in to the device via the terminal with:

telnet 169.254.1.1 2000

and subsequently type a "2"... This returned the desired "forward" immediately. What am I doing wrong from the perspective of the iPad?

Help is much appreciated!

EDIT For some reason, everytime the handler is accessed, the stream that is passed is the output stream, which is completely wrong... Why wouldn't the input stream ever be passed through?

And here is the arduino code:

void loop() 
{ while (Serial.available() > 0) {
    int next = Serial.parseInt();if(Serial.available() > 0)
    {
        if(next == 20) {
            Serial.println("leftMove");
 }}}}
thebiglebowski11
  • 1,451
  • 10
  • 41
  • 76
  • I don't think there's anything wrong about getting `NSStreamEventHasSpaceAvailable` again - it indicates that you can write to the output stream again, if you need, you should get this event after the `write` call. In `telnet`, do you need to confirm '2' with Enter? – Code Painters Nov 29 '12 at 21:01
  • yes, I hit '2' then 'enter' and the wifly sends the command to the arduino which then prints 'forward' to the terminal. I should be getting 'server said: forward' in the log of the iOS application, but instead I get the NSStreamEventHasSpaceAvailable. – thebiglebowski11 Nov 29 '12 at 23:16
  • As expected, as telnet by default buffers the whole line. So effectively you are also sending a new line character - possibly the Arduino doesn't respond until it gets a full line? How does the code look like on the Arduino side? – Code Painters Nov 30 '12 at 08:58
  • I'm pretty sure the arduino code is fine. – thebiglebowski11 Nov 30 '12 at 15:00
  • I've no Arduino experience, but this code doesn't seem correct to me. If the `if` condition is false, you throw away the result of `parseInt()`. Also, this loop ends as soon as serial port receive buffer us empty. How can you be sure it doesn't stop before you even send anything? – Code Painters Nov 30 '12 at 17:19
  • the serial bus is what takes in the data, so if the if condition is false, it hasnt receive anything... this is fine. It works by telnetting. – thebiglebowski11 Nov 30 '12 at 17:20
  • Well, if you send e.g. '20' (without any characters following it), then `Serial.parseInt()` would consume it, I suppose. Thus, subsequent `Serial.available() > 0` would be false. Perhaps it is OK with telnet because the number entered is immediately followed by '\n'. Just a blind guess, of course. – Code Painters Nov 30 '12 at 17:25

0 Answers0