First, as they say, "Do not confuse the map and the terrain". In other words, the map is just a picture of the problem, it isn't the problem itself. So, you have two different issues here:
1 - How to create an architecture that will allow you to monitor (and maybe control?) all the devices in your process, independently of how that information is displayed on screen and
2 - How to display the status of the system and react to problems independently of how the system status is recorded.
I assume you have some kind of low-level control library that lets you identify and monitor specific devices. I would start by creating a QObject subclasses (maybe "MonitoredObject", "MonitoredDevice", "MonitoredSubsystem") which you can use to wrap the low-level devices and systems and convert the low-level monitoring information into Qt signals. If you make this class general enough, it can encapsulate the behavior of most of the devices, even if the details are slightly different. You can then derive more subclasses from this to model specific devices.
I would also develop another class hierarchy, something like QEvent, where you can have a generic "MonitoredEvent", which maybe gets further refined into "TemperatureEvent", "PressureEvent", etc. with data members specific for that kind of measurement. Your MonitoredDevice classes can emit signals with the appropriate event types: "deviceAlarmEvent( MonitoredEvent * )", "deviceStatusEvent( MonitoredEvent * )" to communicate with the outside world.
MonitoredDevice instances can be combined in "MonitoredSubsystem" collections. Here, you can establish relationships between devices which occur in the same subsystem. If the temperature of process A goes too high, the deviceAlarmEvent() from temperature monitor A can be connected to a slot in the TemperatureController instance for A which will turn the heat down. Other subsystems do not need to know about this, since it is handled internally. However, if a problem in one subsystem can cause a problem in another subsystem (a pressure surge in subsystem A can cause problems in other subsystems in the same pipe network), then subsystems can emit signals that can be monitored by others: "subsystemAlarmEvent( MonitoredEvent * )" where the detailed event information includes the ID for the device that raised the alarm.
Notice that none of this discussion says anything (so far) about the display of the information. All of the activity around monitoring and controlling the system is completely encapsulated, totally independent of the display.
So, now you need to display the status on screen. Here, I would use the Qt Graphics/View architecture. I would create a QGraphicsObject subclass that mirrors each of the MonitoredObject subclasses in the monitoring hierarchy. These QGraphicsObject classes provide the visual display of the device status, and can have a different appearance depending on the device type (a temperature monitor looks like a thermometer, maybe) and can change their display depending on the device status.
You also make a QGraphicsObject subclass that represents MonitoredSubsystem instances. These contain child graphics objects that represent the monitored devices and the connections between them. This is where you can make use of the "level of detail" feature of the Graphics/View architecture. At a very high level, you can display a rectangle for each subsystem with lines that connect the subsystems that are wired or plumbed together. The rectangle has a color or other display that indicates its status - green for normal, yellow for warning, flashing red for emergency. Zooming in can display the subsystems inside a bigger one, zooming in more can display individual devices with their status and connections. (See the 40,000 chips demo in Qt to see what I mean).
Since each QGraphicsObject is responsible for a single actual MonitoredObject, you can connect slots in the graphics object with the same signals used by the monitoring hierarchy; these slots will cause changes in the display of the object's status, but nothing else. The monitoring hierarchy controls the devices themselves. If the user can control and change process settings through an interaction with the GUI (say, clicking on a temperature controller icon allows changes in the setpoint), then the graphics object should emit signals (with a "ControlEvent" pointer that the MonitoredDevice can be connected to.
I'll let you think about it. The basic idea is that Qt provide you with some great programming tools that can allow you to completely encapsulate different parts of your architecture in a way that allows you to implement and test the parts independently. The connections between the parts are realized using the signals and slots mechanism. If you keep the separation between the monitoring subsystem and the display subsystem clear in your head as you design and implement the system, you will end up with something that is very flexible and easy to change as the physical system changes - a Model 123 temperature sensor breaks and is replaced by an improved Model 124 temperature sensor, but except for replacing some small bit of code for that specific device code (or better yet, a configuration database that is read in at runtime to define the in-silico model of the system - similar to the XML used in .ui files to define the GUI), nothing else changes anywhere.




Reply With Quote
Bookmarks