Odd (and new) issue with serial polling/parsing sequence


edwardewilliams

Recommended Posts

We use the following custom sequence to poll remote serial device over telemetry links. The link is established elswhere in DF and the Device Number (dn) is passed to this function.

function PollLogger(dn)
ispolling = 1
 try
   private string datain = "junk"
   private string chan
   private ch
   private val 
   private count = 0
   while (1)  
      try
         purge() 
         write(chr(13))
         delay(2)
         write(chr(13))
         delay(2)
         write(chr(13))
         delay(3)         
         read(3) 
         purge()
         if (resetpulse[dn]) //sitenum or dn?
            write("ch,p1"+chr(13))
            delay(3)
            purge()
            write("pm=3"+chr(13))
            delay(3)
            purge()
            resetpulse[dn] = 0//sitenum or dn?
         endif
         write("cr,a"+chr(13))
            break
      catch()
         ? strLastError
      endcatch
         count++
      if (count > 3)
         return
      endif     
      delay(10)
   endwhile

   while (1)
      try
         datain = readuntil(10) // read a line:  BV:  12.831310
         chan = right(parse(datain,0,":"),2)
         val = strtodouble(parse(datain,1,":"))
         if (val == NaN())
            val = 0
         endif
         if (chan == "BV")
            ch = 0
         else
            ch = strtodouble(mid(chan,1,10))
         endif
         chan = left(chan,1)
         switch
            case (chan == "B")
               Channel.AddValue(strDevice,dn,"BatteryVoltage",0,val)
            case (chan == "S")
               Channel.AddValue(strDevice,dn,"SDISensor",ch,val)
            case (chan == "A")
               Channel.AddValue(strDevice,dn,"AnalogInput",ch,val)
            case (chan == "P")
               Channel.AddValue(strDevice,dn,"PulseInput",ch,val)
         endcase
      catch()
         ? "PollLogger: " + strLastError
         timepolled[dn] = systime()
         return
      endcatch
   endwhile
catch()
   ? strLastError
endcatch
timepolled[dn] = systime()

This has worked well for us in the past, but recently we've started having a problem where the last value read and placed in the "DATAIN" string will continue to parse over and over and over again - about every 8 seconds or so.

Setting the timeout for the remote device to a shorter time solves the problem (the sequence relies on comm timeout to move on out of the read/parse loop) but then we have a problem where some of the devices may not connect since sometimes, depending on the device, it can take 10-15 seconds to obtain a connect - if device timeout is set shorter than that to avoid this problem, then we never connect in the first place.

Thoughts as to how to make this more predictable? We can't have a "hard out" from the read/parse loop since depending on the device, we get a different number and combination of channels and channel types with no "end of data" character or similar termination sequence available.

Link to comment
Share on other sites

I'm assuming of course, that your device isn't actually sending the same string over and over again. The monitor would tell you this. I'm also assuming you don't have an ignore("all") or similar somewhere. I'd try two things first:

1) put a breakpoint in and walk through the code. If you have this in a protocol, you'll have to move it to a sequence to walk through it. Put a using("device.myserial") in front so you don't have to expand all the readuntil() and other serial functions. Or, if you don't want to do that, add a bunch of ? statements so you can trace what is happening.

2) Put datain = "" just before the readuntil(10). This will ensure that the previous reading doesn't get carried forward.

Link to comment
Share on other sites

Sorry, I should have clarified. The parsing loop exectues properly for each of the inbound reading as they come and get placed in to the "DATAIN" string. (no, the remote device isn't sending the same stirng over and over) Say for instance I'm reading five channels, they all get read and properly parsed. Then, the remote device gets done sending and while we're waiting for the timeout to occur in order to cause the while loop to error out and the function to exit, the last reading (the fifth channel in my example, for instance) just continually re-parses. In other words, the parsing loop just re-executes on whatever the last string was that was placed in to "DATAIN"

In the copy of this I have running on my machine, I've added a number of "?" statements and they show that the parsing loop simply keeps repeating, re-parsing that last piece of data and creating new entries on the associated channel over and over until manually stopped. It's as if the connection isn't timing out or the function isn't seeing the timeout.... ?

We did, however, have an "ingnore("all")" call in the startup routine...... I'll see how it works now.

Link to comment
Share on other sites

ignore("all") only affects the current thread, so if your startup routine did beginseq() it won't affect the sequence started. However, if a sequence has ignore("all") and then calls another as a function I believe it will also ignore all errors.

The easy workaround if you don't want to chase it down is simply this:

datain = "junk"
datain = readuntil(10) // read a line: BV: 12.831310
if (datain == "junk")
   throw()
endif

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.