vrushali has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I am accessing the serial port through perl script, I am trying to detect some pattern in the incoming serial port data (lets say i am trying to find "abcd" in incoming serial port data like "zcfgsdbabcdppuahjajg") and till the pattern is detected i want to execute some command using until loop in perl and once the pattern is detected the perl script should come out of the loop and should execute the next command after the loop. But after detecting the pattern the perl script is executing the command inside the loop one more time. How can i stop the execution of the loop and come out of it after the pattern detection and send next command? Here is the code that i am using..

#!/usr/bin/perl use Win32::SerialPort; $PortObj->are_match("abcd"); # Pattern to match my $gotit = ""; until ("" ne $gotit) { $gotit = $PortObj->lookfor(); # Look for the pattern "abcd" in the inc +oming data if($gotit){last;} # to exit the loop after the pattern detection print("Pattern is not detected\n"); # print the message till pattern i +s detected. # send some command through serial port in loop till the pattern is de +tectd } # send next command after the pattern detection.

Replies are listed 'Best First'.
Re: pattern detection inside until loop in perl
by chrestomanci (Priest) on Dec 13, 2010 at 09:46 UTC

    You say execute a command from the loop while the pattern is not detected, then another command when it is, and then the command from the loop one more time afterwards

    If so then it sounds fairly simple:

    my $data = read_port(); while( 0 == match_data($data) ) { do_if_no_match(); $data = read_port(); } process_match($data); do_if_no_match(); # End.

    If on the other hand, you want to Resume your loop after you have processed a match, then I suggest a for loop with the loop variable initialised outside the outer loop that reads the port:

    my $loop_i = 0; my $max_i = 100; my $data = read_port(); while( $loop_i < $max_i ) { if( match_data($data) ) { do_if_no_match($data); } else { do_if_no_match( $loop_i ); } $data = read_port(); $loop_i ++; } # End.
Re: pattern detection inside until loop in perl
by jethro (Monsignor) on Dec 13, 2010 at 10:23 UTC

    And that is just what your script is already doing. I changed your script slightly to make it a bit more obvious:

    #!/usr/bin/perl use warnings; my $gotit = ""; until ("" ne $gotit) { $gotit = <DATA>; # Look for the pattern "abcd" in the incoming data chomp $gotit; if($gotit){last;} # to exit the loop after the pattern detection print("Pattern is not detected\n"); # print the message till pattern i +s detected. } print "action after the loop\n"; __DATA__ bingo

    This prints:

    Pattern is not detected Pattern is not detected Pattern is not detected action after the loop
Re: pattern detection inside until loop in perl
by Marshall (Canon) on Dec 14, 2010 at 00:22 UTC
    Your code does appear to do what you are asking for so I find your question a bit confusing. However some simplifications are possible to make things more clear.

    You have 2 ways to exit the loop:

    - until ("" ne $gotit) - if($gotit){last;}
    I would simplify to one condition. Note null string is "false". Also $gotit doesn't appear to be necessary because it appears that the lookfor() method is looking for what you told it to with the are_match() method.
    $PortObj->are_match("abcd"); # Pattern to match send_prompt(); #I presume this happens? while (!$PortObj->lookfor() ) { print("Pattern is not detected\n"); send_prompt(); #re-prompt } # pattern is detected here ... we continue
    unless and until can sometimes confuse folks, so I tend to prefer using "while" for the vast majority of my loops like this.

      Thank u for your response, it helped me a lot. Can you please tell me any other method apart from the lookfor method for pattern detection in streaming data coming from the serial port.
        Communicating 2-way over a serial port in a simple, reliable way is actually a lot more complicated than it sounds!

        The crux of the matter is that there is no "end-to-end" protocol like TCP/IP. This is low level.
        You send out bytes. You listen for bytes.

        There is no guarantee that what you sent is what was received. In either direction it is possible that characters are deleted, inserted or transposed into other characters - this is due to how the hardware works.

        You don't send "messages" and listen for "messages". You have to deal with streams of raw characters sent and received.

        For sending, perhaps you send the string: "CMD=save\n" and that gets received as: "CMD=sav@#". If the listener is waiting for "\n", to signal the "end of incoming message", then there is going to be a problem! Probably you have to resend: "CMD=save\n" due to no response within some time out period.

        The listener maybe then sees the "\n" and parses its incoming command line as: "CMD=sav@#CMD=save\n", well that may not work out so well.

        Without knowing more about the protocol between the computer and the external device, I can't help more.

        Most of these communication protocols are fairly "stupid": send one line, get one line. But even that can get complex when the "receiver" doesn't get the "line" that was sent (meaning that the line termination character was missed) and you have to re-send the line.

Re: pattern detection inside until loop in perl
by Marshall (Canon) on Dec 14, 2010 at 00:20 UTC
    Blanked - this is a duplicate post