In various posts on this forum I've seen this statment;
Casting usually is considered as bad software design.
Here is somewhat generic example that I've considered but leads to alot of casting. I'm curious what would be a better design.

Consider a network that contains pc's and micro-controllers. The pc's can have printers attached to them and the mc can have sensors attached to them. In the business layer of an application these hardware units are read and stored in 'efficient' manner. Then through several events (callbacks) I'd like to pass information for all the module to the gui layer of the application.

The problem is that these module types have different features and require different information to be stored.

What I considered is defining the various hardware modules;
Code:
enum ModuleType { pc, mc, printer, sensor };
Then create a few interfaces (abstract classes);
Code:
class IHWModule // interface
{
    int GetID() = 0;
    ModuleType GetType() = 0;
    // more methods
};

class IPC : IHWModule // interface
{
    // specific methods for this class
};

class IMC : IHWModule // interface
{
    // specific methods for this class
};

class IPrinter : IHWModule // interface
{
    // specific methods for this class
};

class ISensor : IHWModule // interface
{
    // specific methods for this class
};
I could then pass the IHWModule to the gui layer and using the ModuleType to cast the object to the appropriate object type and use it accordingly.

What would be a 'smarter' solution to this generic problem. hoping for some input \ advice. Apologies for being so generic.