IRecorder Interface Definition

Introduction

The IRecorder Interface shall inherit from the IFunctionBlock interface.
The IRecorder Interface shall specify the start and stop methods.
The IRecorder Interface shall at the minimum specify the start and stop methods.

Example code:

// case 1
struct IRecorder : public IFunctionBlock
struct IHBKRecorder : public IRecorder

class HBKRecorderImpl : public ImplementationOf<IHBKRecorder> {
  HBKRecorderImpl(ListPtr<> args)
}

// case 2 -> do not inherit
class HBKRecorderImpl : public ImplementationOf<IFunctionBlock, IRecorder, IHBKRecorder> {
  HBKRecorderImpl(ListPtr<> args)
}


FunctionBlockPtr fb = createWithImplementation<IFunctionBlock, HBKRecorderImpl>(args);

auto rec = fb.asPtr<IRecorder>();
auto hbkrec = fb.asPtr<IHBKRecorder>();

// actual implementation
struct IRecorder : public IFunctionBlock {
  virtual INTERFACE_FUNC ErrCode start() = 0;
}

template <typename T>
class GenericRecorderImpl<T> : public GenericFunctionBlockImpl<IRecorder, T> {
  ErrCode start() override;
}

class HBKRecorderImpl : public GenericRecorderImpl<IHBKRecorder> {
  HBKRecorderImpl(ListPtr<> args): public GenericRecorderImpl<IHBKRecorder>() {
  }
}

// You can get all recorders available on a device or openDAQ instance via: 
auto recorderListList = instance.getAvailableFunctionBlocks<IRecorder>();

auto recorderList = device.getAvailableFunctionBlocks<IRecorder>();

openDAQ architectural concerns

This section highlights some considerations about the IRecorder::start/stop() methods in regard to the current state of the SDK design.

When considering the currently available feature + those already being implemented (not counting the IRecorder interface), we already have 2 complementary ways of enabling/disabling recording:

setActive(true/false)
  • Sets the active state of a component (function block) and all of its child components.
  • Signals that are inactive don’t send data packets.
  • Input ports that are inactive don’t receive data packets.
  • As such, an inactive function block does not process data. By extension, an inactive recorder does not store data
setOperationMode()
  • openDAQ currently defines three operation modes
    • Idle → Configuration, no data processing
    • Safe Operation → Configuration, full rate data, no physical sinks are online
    • Operation → Configuration, full rate, all sinks active; default state unless specified otherwise
  • All states except for “Operation” are opt-in, meaning that a device is allowed to only support the “Operation” state.
  • When considering the above states, a device that is not in “Operation” should not record data

Considering “Active” and “Operation Modes” together, we have:

  • A way of enabling/disabling (stopping/starting) any function block, even when in “Operation” mode via setActive.
  • A way of triggering storing based on a common device state shared across the entire device via setOperationMode

IRecorder::start/stop()

The question that remains is how IRecorder::start()and IRecorder::stop() can be slotted into the above behaviour without duplication that confuses end-users with multiple ways of achieving the same thing.

My (Jaka) proposal is to overload start/stop and have them be equivalent to setActive(true) and setActive(false), while also being integrated with operation modes:

  • start can only be called if the device is in “Operation” mode. When called, it sets activeto true.
  • Similarly, stop can only be called if the device is in “Operation” mode. When called, it sets active to false.

Who shall implement the Feature

openDAQ
Contribution

Status
Feature Planned on Roadmap
Feature Request is discussed in Working Group
Feature declined.