Click here to Skip to main content
15,887,917 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi,

I'm designing some C# .NET drivers for communicating with industrial equipments, mainly for testing purposes.

The communication is based on text messages (a start(@/#) and stop(;) flags).

The start flag is different when receiving(#) and sending(@) data.

I started to create a hierarchy of classes, each of them inherits a Byte[] and String Representations that allow them (depending on the properties) to have the proper set of bytes to send through a communication channel (SerialPort UART or Ethernet UDP).

This works pretty well, but I'm wondering is there any other better design approach, cause I have basically one more classes for one specific keyword (i.e. to request the equipment to perform a certain operation and also depending on some other parameters).

I was thinking using some factories but dunno really if it would be a much better approach than instantiate classes that gather the parameters of command / acknowledgment with a proper understanding.
Posted
Updated 16-Jun-14 16:20pm
v2
Comments
Sergey Alexandrovich Kryukov 16-Jun-14 23:12pm    
I appreciate you desire to improve things. However, think at the following: first impression of your request is developing architecture for architecture and using patterns for the sake of using patterns. Please tell us: how "factories" are related to messages?

Of course, this can only be impression, but still, your question does not provide any motivation for proposing better architecture. Such motivation should be based on some concerns of maintainability (including fuzzy requirements for elegance, clarity and smaller size of code), performance, reliability, and so on. Anything?

By the way, do you mean that '@' '#' or ';' are magic characters used as the tokens of some actions? If so, it does not seem well maintainable of elegant... :-)

—SA
_Asif_ 17-Jun-14 1:20am    
If you have had shared your class hierarchy, we could have suggested approaches towards generalizing your approach to more maintainable and elegant solutions.
Ehouarn Perret 17-Jun-14 4:03am    
Well thanks your feedback, it's hard to tell more about the topic as it involves plenty of details...
But let's give a try:

Basically, we have different product:
- A Controller to perform measurement channel inputs (e.g. Current, Voltage, Frequency, Digital, Relay, etc.) and generate some signals on its outputs (AWG, Voltage, Frequency, Digital, etc.) and some typical automotive buses: CAN, LIN and K-LINE.
- A Unit, able to deal with the power supply and to embed several controllers.
- An Extension to perform some temperature measurements and bring, it's connected to the Unit.

The fact is the embedded team who (is charge of designing all the dirty stuff over the hardware) gave me the commands and acknowledgments are not really clear, neither user-friendly, and for some legacy reasons they're not gonna change that...
Mainly cause prior to that situation we used to have a software dealing directly with the commands and it was a huge huge huge mess. Since I decided to gather all the communication stuff in assembly dedicated to that. It allows btw to make instrument drivers (for NI LabVIEW) by wrapping the objects and methods of the assembly. I'm pretty proud of that cause it allows our systems to be used in many many different Software platforms (e.g. Matlab) and in our own software platforms as well. I also manage myself to make our assembly Mono compliant.

The protocol as it has been defined it not that extensible (not necessarily there is a need to make it extensible but I feel sometimes that it could be better).
Unit Command: {@}{UnitId}{XX}{_}{UnitMessageKeyword}{=Parameters}(if any){;}
Unit Acknowledgment: {#}{UnitId}{XX}{_}{UnitMessageKeyword}{=Answer}(if any){;}

Controller Command: {@}{ParentUnitId}{ControllerId}{_}{ControllerMessageKeyword}{=Parameters}(if any){;}
Controller Acknowledgment: {#}{ParentUnitId}{ControllerId}{_}{ControllerMessageKeyword}{=Answers}(if any){;}

Extension Command: {@}{ExtensionId}{XX}{_}{ExtensionMessageKeyword}{=Parameters}(if any){;}
Extension Acknowledgment: {@}{ExtensionId}{XX}{_}{ExtensionMessageKeyword}{=Parameters}(if any){;}

Controller Instead to provide a dummy interface with the command to the end users, I decided to gather messages and acknowledgment into things what really the user needs through properties, it's more natural as it really represents the Unit:
- Property (Category) Power Supply => Enabled { get; set; } / CurrentMax { set; get; } / Current { get; } / Voltage { get; set; }
- Property (category) Information => SubCategory Identifiers { get; } / SubCategory OperatingTimes { get; } / etc.
- Method On() // Turn On...
- Method Off() // Turn Off...
- Method Lock() // Remote Control Only
- Method Unlock() // Allow Manual Mode
- ReadOnlyKeyedCollection<controller,>
- Etc.

Lock() / Unlock() methods could be gathered as a Boolean Property Locked { get; set; }
The same for On() / Off() methods into Powered / On { get; set; } or whatsoever.

The fact is that we are making new products, some of them are based on the previous one: like a Controller which is out of the unit for the customers who do not need a big power supply.

I was just suggesting factories for better re-usability matters, the fact is my solution now is a bit boring to implement and I'd like to make things easier. The core of the troubles are that there is an underlying implementation of the messages. For some reasons a Message Keyword does not necessarily match a Command Implementation in the assembly, sometimes the possibilities for one keywords are simply too much (and can lead to have a lot of Nullable as properties of the message), therefore when it's possible a keyword can be used in different command implementations when the concerns are properly separated.

Message
^- Acknowledgment (Token Reception: Start / Stop)
^- AcknowledgmentUnit
^- AcknowledgmentController
^- AcknowledgmentExtension

^- Command (Token Transmission: Start / Stop)
^- CommandUnit
^- CommandController
^- CommandExtensi

1 solution

Please see my comment to the question. In essence, you did not provide enough material for thinking and giving you some serious ideas.

So, I can give you only some rather trivial idea: use either WCF or "classical" remoting (some says it's deprecated, but there are cases when it's better). This way, you can benefit from abstracting out transport "logistics" of your messages from some detail. In principle, you can abstract out content of your messages. If you use service contract or data contract, you can hinde concrete presentation of data in the stream behind contract methods (1st case) or some object (or object graph) representing a contract (second case). Both technologies will allow you to abstract communication channels and their nature (IPC (actually, named pipes), sockets or anything else) from messages and make the channels replaceable.

Again, you could use some other approaches and ideas. I cannot discuss it more serious based on the detail you provided in your question. Just think about it.

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900