The application must to have at least 3 levels of abstraction.
The error handling should be of 2 types : for users, for debugging
The maximum of the code must be hardware-independent.
You should provide two interfaces with your program : for usual use, and for testing.
"Test Center" class implements the testing interface. It should "know" about every device in the system. Thus the device on initialization / creation should register at the "Test Center". Test Center gives us opportunity to accumulate different statuses of the system ( for example : time of last
Make sure your software runs in simulation mode. It lets you to develop first versions without the needed hardware. It it useful in debugging upper layers of software.
It is very important to have information about the system configuration. All paths, all parameters should held in one place to be shared by all applications that need it. So the repository should be external or accessible from the outside of the application.
The error handling should be of 2 types : for users and for debugging.