-1

I am looking for alternative ideas of how to implement the following situation (.NET Core, C#)

Having multiple sensors that communicate over a RS485 interface with the host. Each sensor is implemented using an generic ISensor interface (All sensor types have a certain function which must be implemented over the ISensor interface) There are all kinds of sensors that communicate over varying channels with the host, TCP, Serial, USB, custom hardware, etc. This class of sensors is somehow special in that they share the same communication channel, which can be opened only once.

This special group of sensors use the RS485 serial port to communicate, each sensor has an id which is included in every data packet sent or received. So when I send a data packet with an address of "1" all sensors on this port will receive it but only the one with address "1" will react and possibly respond.

Only one logical connection over the serial port can be opened to talk to all sensors and receive data from all. Therefore I must have a central point of distribution from where all inputs are dispatched and to which all output is sent. From the point of the using app, it only talks to the ISensor interface and doesn't care how the sensor communicates, if anyhow. (many other sensors already implemented are simple in that they own their connection)

Every interaction with a sensor contains a data structure with an corresponding answer data structure (or in case of failure an error data structure identical for all errors)

I am wondering in what OO pattern to implement this scenario, a few come to my mind but none satisfies me too much.

The app creates, lets say 3 instances of the same sensor (configuration tells that 3 are connected), configures them by using something like ISensor.Setup() and then ISensor.Start() after that, each of the sensors starts to send in data periodically.

Now I have already an protocol class which does the parsing of all communication data, independent of sensor ID or underlying communication channel.

My idea was to have an queue where all incoming data is arranged and the sensors subscribe to it and pick out the data for them ( the subscription may already filter them ). Outgoing data should be also queued from all sensors. Not sure now where to plug in the protocol parser and the communication class.

Its kinda related to Controlling a sensor network which didnt get any useful answers though. Bandwidth is not so much a problem as there are packets only every 100ms incoming, from up to 8 sensors per serial port.

  • 3
    What is your specific question? – Robert Harvey Dec 30 '20 at 19:13
  • As I said, Ideas on which OO pattern to use. What can you recommend, based on the fact that I already have a protocol parser that must be used. – Hefaistos68 Dec 31 '20 at 11:52
  • The best approach for you is to search online for the source code for a complete working example project. There needs to be some kind of manager object (e.g. a Singleton) dedicated to the arbitration of RS485 operations. Based on similar questions about RS485 on C# (using SerialPort class), this class also needs to be launched into its own thread, in order to have timing (e.g. a waiting time after sending each message before enabling receive) proportional to the length of the message sent, the expected delay of the recipient device, and the baud rate. – rwong Dec 31 '20 at 17:44
2

I would create a separate class (e.g. RS485Channel) that represents the RS485 communication channel. This class would be responsible for multiplexing multiple sensors on the RS485 bus.

The ISensor classes that represent/communicate with the sensors on RS485 would be constructed with an RS485Channel instance and the ID of the sensor on the RS485 bus.

The ISensor interface itself would not expose information if the sensor is on a shared bus or if the class manages the connection itself. Onle the code constructing the actual instances would need to have that knowledge.

1

The pattern I would use would not be far removed from the service + repository pattern common in ASP.NET. Except instead of exposing web functionality, you are exposing an API for other programs to work with, and instead of accessing a database, you are accessing a hardware device.

Repository layer

  • Provides data access to the hardware
  • Its single reason to change is if the hardware itself changes.
  • Wraps unmanaged resources required to access the hardware (e.g. serial ports)
  • Should probably expose at least one class that implements IDisposable, e.g. ComPortSession.
  • Private

Service layer

  • Exposes public classes and methods that want your end users to reason about and work with, e.g. Sensor
  • Calls the repository layer to do things; knows nothing of how the hardware works
  • Exposes a factory that allows the caller to obtain instances of the public classes.
    • The factory coordinates with the repository layer to ensure any sort of mutual exclusivity is enforced, e.g. if there is a constraint on how many Sensor instances can be opened at once.
    • This is probably where you would persist repository objects that represent unmanaged resources (as private member fields).
    • Probably needs to implement IDisposable to give the caller the ability to release resources.
  • Uses interfaces liberally (e.g. ISensor) to make it easier for your customers to unit test their code. That way they can stub out your classes.
  • In your scenario, where would you plug in the protocol parser? – Hefaistos68 Jan 12 at 9:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.