Rob Smyth

Monday 30 July 2007

Serial Protocol Driver Stack

The static structure diagram shown to the left is a typical protocol driver stack.

This static structure provides:
  • Support for both Multi-drop or Point to Point communications protocols.
  • Protocol abstraction to facilitate multiple protocol implementations.
  • I/O Device specific façade to the application.
  • Simulation capability to enable automated testing of the full protocol stack.
  • Port abstraction allowing implementation of a protocol via different port types. e.g USB, TCP, or RS232.
This stack does not include support for:
  • Dynamic routing or path modelling.
  • Redundant paths.
  • Host level redundancy.
  • Use of multiple port channels (multi-link protocols).
The diagram has notes giving a short role description for each class.

Sunday 29 July 2007

Serial Protocol Driver States

Many applications require a serial communication protocol to communicate with PLCs, RTUs, instruments, weather station, etc. The implementation is often ad-hoc and often problematic, especially in recovering from fault conditions caused by bit error rates or just tripping over a cable. It seems to me that there is a common design pattern for protocol states which can be implemented in whole or part depending on the domain. I'm hoping that a generic driver can be developed from this to provide a common driver framework.

The advantage of understanding the pattern is to acquire the know how needed even in very reliable communication paths such as over USB.

The state chart above shows the full generic implementation. This state engine provides:
  • Support for control of exclusive system resources such as COM or USB ports independent of the communication channel state control. That is, the channel may be opened and closed without releasing resources.
  • Error recovery.
  • Transitional states for asynchronous state transitions which also allow for features such as 'back-off' time enforcement on channel shut down.
  • Unambiguous states to simplify client use.
  • Actions to control state available in every state for immediate execution, including the transitional states.
These are described more fully in the state descriptions below.

Stopped State

The stopped state is the initial state. In this state the protocol driver has been instantiated but has not acquired any resources. The driver should be placed in this state before disposing.

Transitions from this state:
  • On call to Start() transitions immediately (synchronously) to the Started state.
  • Re-entrant on a call to Reset().
  • A call to any other state interface method will cause a transition to the Error state.
Transitions to this state:
  • From any other state, including the Error state, by a call to Reset().
  • From the Started state by a call to Stop().

Started State

On entering the started state the protocol driver acquires all required resources. Typically this is opening exclusive resources such as a COM or USB port. High performance drivers may use configuration information to preallocate memory.

Transitions from this state:
  • On call to Open() transitions to the transitional Opening state. It is possible that the state may also transition to the Open or Failed state prior to Open() returning.
  • On call to Stop() transitions to the Stopped state. All resources are released prior to this transition.
  • A call to any other state interface method will cause a transition to the Error state.
Transitions to this state:
  • From any other state, including the Error state, by a call to Reset().
  • From the Stopped state by a call to Start().
  • Asynchronously from the Opening state by a call to Close().
  • Asynchronously from the Open state, via the Closing state, by a call to Close().
  • Synchronously from Failed state by a call to Close().

Opening State

The Opening state is a transitional state in which the driver establishes a communication channel with the remote device. This is protocol dependent and may be:
  • Protocol transactions to open a session
  • A simple poll to establish that the link exists
The time taken will vary dependent on the application from microseconds to minutes (for dial-up PSTN links). This state is beneficial even when using fast USB devices as it provides a clear validation prior to data transactions for diagnostics and channel control.

The Opening state is used when trying to open a channel for the first time (from the Started state) and when trying to reconnect a failed channel (from the Failed state).

Transitions from this state:
  • On success, transitions to the Open state.
  • On failure, transitions to the Failed state.
  • On call to Close() immediately transitions to the Closing state.
  • A call to any other state interface method will cause a transition to the Error state.
Transitions to this state:
  • From the Started state Open().
  • From the Failed state on a call to Open() or by a reconnect timer time out.

Open State

Data transfers may occur only in the Open state. The driver is in the Open state when communications with the remote device has been validated.

Transitions from this state:
  • On communication failure, transitions to the Failed state.
  • On call to Close() immediately transitions to the Closing state.
  • A call to any other state interface method will cause a transition to the Error state.
Transitions to this state:
  • From the Opening state on successful communications channel validation.

Failed State

The failed state provides:
  • Unambiguous indication of unexpected communications failure.
  • Optional implementation of a driver that can automatically reconnect.
Transitions from this state:
  • When conditions for attempting a reconnect (typically a time out) transitions to the Opening state.
  • On a call to Open() immediately transitions to the Opening state.
  • On a call to Close() immediately transitions to the Closing state.
  • A call to any other state interface method will cause a transition to the Error state.
Transitions to this state:
  • From the Open state on communication failure.
Closing State

The closing state provides orderly communication channel disconnection. Depending on the protocol and application this may include:
  • Session disconnection transaction with the remote device.
  • Flush pending transactions.
  • Allow timing for completion of transactions already commenced.
  • Implement 'back-off' timing to enforce an idle time between sessions to ensure time-out of any incomplete transactions.
Transitions from this state:
  • On completion of channel/session closure, transitions to the Started state.
  • On call to Close() immediately transitions to the Closing state.
  • A call to any other state interface method will cause a transition to the Error state.
Transitions to this state:
  • From the Opening, Open, or Failed state on a call to Close().
  • Re-entrant on calls to Close().

Wednesday 18 July 2007

Snow!

We got a real surprise this morning to wake up to snow. We had a few centimeters of snow on the ground. The place looked great. Driving to work the mountain looked something like a northern hemisphere Christmas card. Quiet a treat.

Sue stayed home and after a little initial hesitation the dogs loved the snow. Violet had great fun jumping in it.

We see snow flakes once or twice each year but it unusual to actually see snow on the ground.

The top left photo shows Violet and Golly running down the back path. The other photo shows the view across the road.

Wednesday 11 July 2007

A Metric To Measure Legacy Code Debt

It is not uncommon for a project to have 'legacy' code. That is, code that has poor health usually due to poor structure. This code makes it harder to add functionality. So if the team is to refactor this code as it goes to improve its health how does it measure its progress? How does the project manager measure the debt? If we cannot measure the benefits how do we justify the cost?

In the project I'm currently on we at least have the luxury of identifying this older code as code written without unit tests (using TDD). So we wonder if we can measure the debt by unit test (not User Acceptance Tests) coverage. This allows us to have a metric to say what % of our code is what we call 'legacy' code so we can then track this against our velocity. We expect our velocity to rise as the % falls. If it does not then we have an early indicator that perhaps our efforts to refactor the code is not productive.

This will be interesting.

Saturday 7 July 2007

Golly and Violet - The Play Team

Golly and Violet continue to really enjoy each other's company. This morning I took a short video of their playing in the lounge room and uploaded it to YouTube here.

Thursday 5 July 2007

User Acceptance Test Pattern

Automated User Acceptance Tests (UATs) compliment unit tests but are different. Today Nigel proposed a pattern for UATs. The benefit of the pattern is to give clear responsibilities of roles of classes within the UAT code. This is a great benefit.

I expect that he will post the full pattern but the roles were of Context, Tests, Jigs, and Testers. Where:

Context is the context of what is being tests and is implemented as base classes. A context provides actions suitable for the context of the test. e.g. If the UAT is on a UI page displaying a weather forecast then perhaps the base context class will offer methods to read temperature predicted from the page.

Tests are the tests that drive user actions and make assertions. e.g. Open page, get forcaset temperature, assert that forecast temperature displayed is XX.

Jigs are wrappers for user controls, typically UI pages. They encapsulate access to the controls (in a UAT manner) using the testers. e.g. A test jig for the forecast page may have a property to get a tester for the forecast temperature control.

Testers are underlying framework classes for testing UI controls. e.g. NUnitForms.

Sunday 1 July 2007

Storms Leave Us Without Power

On Wednesday a storm caused lots of damage here on Mount Dandenong. Many trees fell causing damage to half a dozen houses and the nearby school lost a building. Three or four large Mountain Ash trees (20-40 meters) fell on the tourist road between Olinda and Kalorama. We lost power from 9am on the Wednesday through to about Friday 1am.

Coming home on Wednesday night was a bit scary with roads closed. Two roads I tried were closed but I found a third dirt road which was clear. We were lucky with the only damage being from a very large Mountain Ash falling across our far rear fence. A monster of a tree that fell from the other side of the gully, has to be about 40m long. I'm getting quotes for insurance as it is going to be a lot of work to clear the fence and paths.

Next door was not so lucky with one tree falling across their driveway, over the fence, pulled down the street power lines, and blocked the road. But it only took 30 minutes to clear enough for cars to get by. Worse was a neighbor's tree falling and damaging a cottage behind their house.

Fortunately we had bought a generator a few months ago so that allowed us to at least run our gas heating and watch some TV. A good test as this area has been known to loose power for longer periods after bushfires etc. So now we know we need a bigger generator.

But hey, we live up here because we love the trees, so we cannot complain when a tree falls over the power lines.