I'm not going to proclaim to be an expert on this subject. There is a lot of information on-line about how to do it, but this is how I would go about it (this approach has served me well in the past and it's the approach I still use today, because I find it clean and simple).
- Identify the states - Think logically about the states you will need. Don't be afraid of very simple states (i.e. don't have one state that does lots of things), you can always optimise later on
- Identify the transitions - Think about how you move from state to state (not when at this point, just how). In other words, if I'm in state X, which states can I move to?
- Identify the triggers - Once you have a list of states and the transitions, think about when you move from state X to state Y
Let's consider a simple example.
We're going to use a modem to listen for an incoming call, answer the call, wait for a command, process the command, close the connection when instructed by the remote caller and tidy up and wait for the next call if the line is dropped.
So, caveat time... I'm not going to concern myself with the complexities of dealing with the modem, so for the purposes of this tutorial the modem will be represented by an object with the following methods and properties.
- Method 'initialise' - Setup the modem
- Method 'waitForCall' - Begin waiting for a call (when a call comes in ring indicator will be signalled)
- Method 'cancelWaitForCall' - Cancel waiting for a call
- Method 'sendString' - Sends a string (the string will be terminated by #13 - CR)
- Method 'readString' - Reads a string (the string is terminated by #13 - CR)
- Method 'pickup' - Answer an incoming call
- Method 'hangup' - Hangup on a connected call
- Property 'signalRingIndicator' - Returns true if there is an incoming call
- Property 'signalCarrierDetect' - Returns true if the carrier is present
- Property 'dataReady' - Returns true if there is one or more string available to be read
All commands will be terminated by a CR, so it's safe to simply read the command using r'. And finally one biggie... for the purposes of this tutorial we are not going to concern ourselves with success or failure. If I tell the modem to hangup, it will do it without question and the command will succeed every time. I'm also going to assume that all actions performed by the modem will take no time.
Caveats out of the way, onto design.
Stage 1... identifying the states
First things first, think about what you are going to do... initialise the modem, set it up to wait for a call, check to see if a call is coming in, answer it, wait for a command, process it, hang up if instructed and then reset and start again. If a call is in progress, check the state of the carrier detect line, if it drops, reset and start again. Turning this into a rough state list we get:-
- InitialiseModem
- BeginWaiting
- WaitingForCall
- CallDetected
- CallInProgress
- EndCall
- CallDisconnected
That's a fairly short list, but it's also fairly complete.
Stage 2... identifying transitions
For each state, you need to work out to which other states it's possible to move.
- InitialiseModem - From here we can move to 2. BeginWaiting
- BeingWaiting - From here we can move to 3. WaitingForCall
- WaitingForCall - From here we can move to 4. CallDetected
- CallDetected - From here we can move to 5. CallInProgress
- CallInProgress - From here we can move to 6. EndCall and 7. CallDisconnected
- EndCall - From here we can move to 1. InitialiseModem
- CallDisconnected - From here we can move to 1. InitialiseModem
Now we know what states we can move to, we need to decided what triggers each transition.
Stage 3... identifying triggers
For this, list each transition and then next to it, list the trigger for that transition.
- 1. InitialiseModem -> 2. BeginWaiting - No trigger
- 2. BeginWaiting -> 3. WaitingForCall - No trigger
- 3. WaitingForCall -> 4. CallDetected - Ring Indicator is signalled
- 4. CallDetected -> 5. CallInProgress - No trigger
- 5. CallInProgress -> 6. EndCall - User issues the QUIT command
- 5. CallInProgress -> 7. CallDisconnected - Carrier Detect is not signalled
- 6. EndCall -> 1. InitialiseModem - No Trigger
- 7. CallDisconnected -> 1. InitialiseModem - No Trigger
vBulletin Message