Skip to content

Base Device

Yağızhan Dinçkurt edited this page Nov 2, 2025 · 4 revisions

🧩 BaseDevice Overview

BaseDevice is the core class that every device in RadCat must inherit from. It provides a component-based structure and integrates directly with the RadCat systems.

🧱 Inheriting from BaseDevice

Every device must inherit from the BaseDevice template and specify its components. Component creation and assignment are handled automatically by the RadCat system. Base Class inheritance can be done with:

Class YourDevice : public BaseDevice<Component1,Component2,...> {}

🚧 Also you need to add base constructor into your own constructor with:

YourDevice() : BaseDevice() { }

This will make sure that every component you used in your device will know which device is using them and thus will have access to some of its properties.

🔧 Component Access

Component access from a device is fairly easy with getComponent function. You can assign your component to a variable in your header to use it later on with:

componentType& VariableName = getComponent<ComponentType>()

👍🏻 We recommend assigning components to variables if you will be using those components in your code.

You should never fetch components inside update loops.

⚙️ BaseDevice Properties

BaseDevice gives you few handy functions that you can implement and use to make your life easier. It has some pure/normal virtual functions that you need to implement in your class. If you dont your class WONT compile. These functions are:

  • bool connect() -> Pure virtual
  • bool disconnect() -> Pure virtual
  • void update() -> virtual
  • double readValue(const std::string& parameter) -> virtual
  • bool setValue(const std::string& parameter, double value) -> virtual
  • void setupTasks() -> virtual

These functions are implemented by RadCat system automaticly thus its inportant to understand what each one does and when each one is called.

Lets start with connect() and disconnect(). these functions are called whenever device tries to connect and disconnect from the program. You need to implement FTDI or other communication components inside these functions in order to connect and disconnect from the program. These two functions are pure virtual so you need to override them in your device class or it wont compile.

You may not want other people to see / change variables you implement under the hood. Thus its a good idea to make them private and use double readValue(const std::string& parameter) and bool setValue(const std::string& parameter, double value) to expose only the values you want.

update() function run once per CPU cycle to check anything you need. You want to check temperature every cycle? You can implement a function inside update() to do so. But there is an important caveat here. Doing heavy stuff inside update() every CPU cycle can slow down program alot. Thus we recommend implementing a time based system where it check the time passed every cycle and fires the check function when enough time passes.

Thats where setupTasks() and addTask() comes into the place. BaseDevice has a task system that you can use to make time-driven function calls. addTask() function takes two values, first a function and then a milisecond timer. You can use lambda functions inside addTask() to return the value of the function you call to a variable.

You can predefine tasks by overriding setupTasks() as:

void MiniXDevice::setupTasks() { 
    addTask(function(), miliseconds);
    addTask([]lambdaFunction{}, miliseconds);
}

and these functions will be called automaticly by the system when the time comes as long as the tasksActive bool in your device class is True. If you set it to false all automatic tasks will stop. If you want to controll spesific tasks you can set up a task bool.

📦 Simple Device Example

Class BasicFTDI : public BaseDevice<FTDIConnection> {

static inline const DeviceRegistry::RegistryEntry::DeviceInfo deviceInfo = {
"Basic Device", 
"1.0",
"Manufacturer",
"Description"
};

BasicFTDI() : BaseDevice() {  }

virtual bool connect() override;
virtual bool disconnect() override;
virtual void update() override;
virtual void setupTasks() override;
virtual double readValue(const std::string& parameter) override;
virtual bool setValue(const std::string& parameter, double value) override;

}

Thats it for the Base Device. Happy device creation.

Clone this wiki locally