Custom driver
A driver is a .NET library (DLL). QInsight discovers it automatically — the
class just has to implement the IDriverBase interface (be public,
non-abstract, with a parameterless constructor) and the DLL must sit in the
Drivers folder next to QInsight.exe. No other registration is needed.
Driver skeleton
In practice you inherit from the ready-made DriverBase base class, which
handles the common parts (protocols, states, settings):
public class MyDeviceDriver : DriverBase, ITransportSource<byte[]>
{
public MyDeviceDriver() // a parameterless constructor is mandatory
{
Specification = new SpecificationBase
{
Name = "MyDeviceDriver", // stable technical id
Label = "My Device", // text in Project Configuration
Version = new Version(1, 0, 0), // mandatory
};
}
public override void SetConfiguration()
{
// parse RawSettings ("key=value;...") into your own fields
}
public override async Task StartAsync(CancellationToken ct)
{
// open the connection, start the read loop,
// pass the received data to the protocols
}
public override async Task StopAsync(CancellationToken ct)
{
// stop the communication and release the connection
}
public override void Send<T>(T data) { /* send data to the device */ }
public override Task SendAsync<T>(T data, CancellationToken ct)
=> Task.Run(() => Send(data), ct);
public override void Dispose() { /* cleanup */ }
}
Specification.Version is mandatory: a plugin without it is skipped when
the folder is scanned (with a warning in the log). The shipped examples
take it from the assembly
(Assembly.GetExecutingAssembly().GetName().Version).
ITransportSource<T> declares the type of data the driver hands to its
protocols (byte[] for byte streams, CanFrame for CAN frames, …). It has
no members — it only lets Project Configuration offer the driver just the
protocols built for the same T (incompatible ones are greyed out). A
driver without the declaration is treated as unrestricted.
The driver reports its status by calling SetState(...) — the state shows
up in the Logs window and in the UI.
Before calling SetConfiguration(), QInsight fills in Label,
IsEnabled, RawSettings and — for drivers derived from DriverBase —
Logger. The driver passes its Logger on to the protocols added to it.
Settings, reconnection and keepalive
The driver carries its own settings template: override the
DefaultRawSettings property and return a string listing every parameter
with a representative value — it is pre-filled for the user when the
driver is added in Project Configuration.
Read the settings with the shared SettingsParser.Parse(RawSettings, knownKeys, Logger, "My driver") from Qenex.QSuite.Protocols.Protocol: it
returns a key → value dictionary (case-insensitive keys, quotes
stripped) and reports every key outside knownKeys with a warning in the
log that also lists the known keys — the same as the shipped drivers, so
the user learns about a typo.
Reconnection is handled by the ReconnectPolicy class from
Qenex.QSuite.Drivers.Driver: ReconnectPolicy.Parse(settings, defaultDelayMs, Logger, "My driver") reads reconnectDelayMs and
reconnectAttempts (-1 forever, 0 never, N attempts),
SettingsTemplate(defaultDelayMs) returns their part of the template. In
the driver loop call ResetAfterSuccess() after a successful connection
and RegisterFailure() after a failure — false means give up: log
GiveUpMessage(error) as Error, stop the protocols and set Stopped with
that message; otherwise log the attempt at FailureLogLevel() with
AttemptText, set Faulted and wait ReconnectDelayMs. Call
NotifyProtocolsTransportConnectionChanged(false/true) when the transport
is lost and back so the protocols can react (XCP drops and re-establishes
its session this way). A driver built on TCP can enable keepalive on the
connection with the TcpKeepAlive class (Parse, Apply(socket, keepAliveMs), SettingsTemplate()) to detect a dead peer within seconds.
Your driver then behaves in Project Configuration and at runtime like the
shipped ones — see Reconnection.
Optional capabilities
Depending on its purpose, a driver implements additional interfaces:
ITransportSource<T>— declares the transport data type for protocol compatibility (see the skeleton above),IReplayDriver— the driver can replay a record (pause, seek, speed…),IProtocolVariableSinkDriver— the driver consumes values (e.g. a logger),IProtocolVariableCommandDriver— the driver carries operator commands to its protocols: an operator write (CanSendCommand,OnProtocolVariableCommandAsync→ the protocol'sIProtocolVariableWriteProtocol) and a one-shot read of a variable bound to an On Request event (CanRequestRead,OnProtocolVariableReadRequestAsync→ the protocol'sIProtocolVariableReadProtocol). The driver only delegates to the owning protocol — see Example temp sensor.
Deployment
Copy the compiled DLL into the Drivers folder (for a default
installation C:\Program Files\Qenex\QInsight\Drivers — writing there
needs administrator rights). Only your own DLL is needed: the QSuite base
libraries (Driver, Protocol, …) are already next to QInsight.exe.
After restarting QInsight, the driver appears in the
Home → Project Configuration → Drivers list. Only a reference (Name
- version) is stored in the project; when a project is opened, the driver
is looked up by
Nameand the same major.minor version, so the project can be moved to another computer with the same driver set.
Next
Custom protocol — working driver + protocol pairs are in two chapters: the smallest possible one in Example ISS and the full pattern including writes in Example temp sensor.

