Command-Response

kejpa

Junior Contributor
Joined
Oct 10, 2003
Messages
320
Hi,
I'm using a derived Serialports class for handling all talking/listening on a Serialport. This class is referenced from a number of other classes.
What I basically want is that it handles each call separately, send a command, wait for a respose the given time and return the response or a timeout exception.
If another object is trying to talk during this time it's put on hold, and if the second objects Write timeout time is reached while on hold it will get a TimeOutException too.

One thing that complicates it is that the application have to move on as if no waiting is done. Another thing is I want it simple...
Visual Basic:
try
   sResponse=myCommPort.CommandResponse(sCommand)
catch ex as TimeOutException
    Debug.Print"Timed out"
catch ex as Exception
    Stop
end try

Any help appreciated
/Kejpa
 
The first thing that comes to my mind with what you described is to set up something like a signal queue. Basically, this would be a class that your application talks to and that handles all the communication between the serial port and your application. Your application would fire off a command and keep doing whatever it needs to do. Meanwhile, in another thread the signal queue would run the code that you printed above (or something like it). When you get some kind of feedback from the serial port commands, you'll pass information back to the calling class, probably via events.

While all of this is going on for that first command you entered, the user could still enter other commands. Those other commands just get queued up in your signal queue class and once the first command is completed and reported back to the application, the next command is run (or possibly not run depending on error conditions).

I'm not too familiar with design patterns, but I've seen this done in a lot of places (at least in code in my industry) so you might be able to find more information on this potential implementation on the web.
 
mskeel said:
The first thing that comes to my mind with what you described is to set up something like a signal queue. Basically, this would be a class that your application talks to and that handles all the communication between the serial port and your application.
Correct, that's my approach too, but I can't get it further. I seems to be painting myself into different corners most of the time, (the other times I just get tied up by all the threads created ;))

mskeel said:
Your application would fire off a command and keep doing whatever it needs to do. Meanwhile, in another thread the signal queue would run the code that you printed above (or something like it). When you get some kind of feedback from the serial port commands, you'll pass information back to the calling class, probably via events.
Not so sure about using events as all objects would receive the notification, and it's actually just the caller that needs to be noticed.

Thanx
/Kejpa
 
kejpa said:
Not so sure about using events as all objects would receive the notification, and it's actually just the caller that needs to be noticed.
True, the event is available to all classes, but only classes with valid event handlers will take any action. So if you only want the calling class to handle the event, then that would be the only place that gets an event handler and that will be the only class that really cares that an event was fired. A delegate passed to the signal queue by the calling class is another way to do it, but with threading I think you'll have to fire an event at some point to get the message back to your display thread in a thread-safe way.
 
Hi!
The problem is that I probably will have a couple of different classes all with a couple of instances that will use the call. With event handlers I'd have the response in half a dozen places it shouldn't be.
Is passing a delegate a way to ensure that only the calling object will receive the response?

Many thanx!
/Kejpa
 
kejpa said:
Is passing a delegate a way to ensure that only the calling object will receive the response?
It's one way you can do it, yes. A possible solution might look like this in psuedo code:
C#:
Class CallerOne  //One class that can call the serial port.
{
   SignalQueue queue
   Delegate Result(String feedback)  //this would actually need to be in a different place so more than just this class could use it.

   Function TalkToSerialPort()
   {
      this.queue.Talk(new Signal(command, AddressOf GetResults)) //put your signal in the queue with the command and pointer to the method of getting results back to this caller.
   }

   Function GetResults(String feedback)
   {
      Give Results to display   //You will probably need to throw an event here to avoid concurency issues.  The display class would be the only class to catch that event.
   }
}

Class SignalQueue
{
   Function Talk(Signal command)
   {
      this.Enqueue(command)
    }
  
   Function ProcessNextCommand() //When it's time to process another command...
   {
      nextSignal = this.Dequeue   //returns something of type Signal
      result = Run(nextSignal.command)  //send the command to the serial port
      ProcessResult(result)   //failure, you'll probably want to bail out and send a big fat exception or event to kill everything
      nextSignal.giveResults(result) //using the delegate, give the result back to the caller.
   }
}

Class Signal
{
   String command     //the command to be run
   Result giveResults  //a pointer to the class to give results to
}
I used C# BBcode block for the syntax highlighting, it isn't actually C# code. There still are some details that will need to be worked out, but hopefully this conveys the general gist.
 
mskeel said:
It's one way you can do it, yes. A possible solution might look like this in psuedo code:

I used C# BBcode block for the syntax highlighting, it isn't actually C# code. There still are some details that will need to be worked out, but hopefully this conveys the general gist.

Hi mskeel!
I've got it working now, thanks to you.
With some tweaking I got it into my existing Comm-wrapper too so now I'm really pleased.

/Kejpa :D
 
Command/Response -revisited...

Hi,
I was sooo happy yesterday when I got it tweaked into my existing CommPort class.
But today I realize that I need the response in the statements following the call :(

Visual Basic:
'UI 
try
   sResponse=myCommPort.CmdResponse(sCommand)
   select case sResponse
      case "<"
         DoThis
      case "!"
         DoThat
      case "?"
         DoSomethingElse
   end select
catch ex as TimeOutException
   console.writeline(ex.message)
end try

Asynchonous handling comes to mind, but I can't find any good samples.
The UI calls once a second and the calls should pile up but if no respose has come within 1.5 sec it should timeout and process next message not that has not timed out.
The message queue was pretty but I couldn't get the response back to the calling method :(

TIA
/Kejpa
 
These look like two decent tutorials on asynchrounous callbacks (events) and delegates:
The code project
Dev City

I think what you want to do is fire and forget the command from the gui, then have a differnet method wait for the response which will either come synchronously via a delegate or asynchronously via an event. Here's an example of what the asynchrounous code might look like in the GUI.

Visual Basic:
'UI 
Sub RunCommand(ByVal command As String)
      myCommPort.CmdResponse(command)
End Sub
'
Sub HandleCommandResponse(ByVal sender As Object, ByVal response As String) Handles CommandResponseEvent
   Select Case sResponse
      case "<"
         DoThis
      case "!"
         DoThat
      case "?"
         DoSomethingElse
       case Default
          Fail()
   end select
End Sub
Waiting for the time out exception should probably happen when you are sending the command to the serial port. The GUI isn't waiting for anything to happen, but it does need to be ready to get a response. All of the really hard stuff, waiting for a response, determining if there was a timeout, and possibly even interpriting the response (return something like a pass/fail/timeout enum to the gui for example) should probably be happening in the class that sends the commands to the serial port.

Hopefully that makes sense.
 
Back
Top