#pragma once

/** @mainpage Inertia library
 *  The Inertia library can be used to configure, capture and log (wireless)
 *  monitoring of vibration and motion sensors.
 */

#include "dll/InertiaExport.h"
#include "platform.h"
#include "version.h"
#include "dll/DebugLog.h"
#include "dll/Quaternion.h"

#include "dll/StreamListener.h"
#include "dll/LogColumns.h"
#include "dll/ConnectionSettings.h"
#include "dll/LogSettings.h"
#include "dll/SocketSettings.h"
#include "dll/CalibrationSettings.h"
#include "dll/ConvertSettings.h"
#include "dll/ChannelSpec.h"
#include "dll/OrientationSettings.h"
#include "dll/FirmwareSettings.h"

#include "data/InertiaConfig.h"
#include "data/InertiaCommands.h"
#include "data/InertiaService.h"
#include "data/Sample.h"
#include "data/DeviceInfo.h"


 /** Namespace for all Inertia SDK related functions and classes. */
namespace inertia
{
	/** Get the library version, format 'x.x.x'.
	 *  @return the version
	 */
	INERTIA_API std::wstring GetLibraryVersion();

	/** Get the full library version, format 'x.x.x.x (rev)'.
	 *  @return the full version
	 */
	INERTIA_API std::wstring GetLibraryVersionFull();

	/** Split a command line string into separate arguments, separated by spaces.
	 *  @param cmdLine the command line
	 *  @return a vector with command strings
	 */
	INERTIA_API std::vector<std::wstring> SplitCommandLine(std::wstring const& cmdLine);

	/** Get a map with available serial ports and the name of the connected device (if available).
	 *  @return a map with connectionName - deviceName
	 */
	INERTIA_API const std::map<std::wstring, std::wstring> GetSerialPortList();

	/** Get a map with available bluetooth ports and the name of the connected device (if available).
	 *  For BLE devices the port is the MAC address of the device.
	 *  @return a map with connectionName - deviceName
	 */
	INERTIA_API const std::map<std::wstring, std::wstring> GetBluetoothPortList();

	/** Get a map with available network adapters and the MAC address of the adapter.
	 *  @return a map with adapterName - MAC address
	 */
	INERTIA_API const std::map<std::wstring, std::wstring> GetNetworkAdapterList();

	/** Get the version of the Inertia Driver (Windows only).
	 *  An Inertia device must have been connected at least once, otherwise 0 will be returned.
	 *  If a device is connected and the driver is not installed, -1 will be returned.
	 *  @return the driver version
	 */
	INERTIA_API unsigned GetSerialDriverVersion();

	/** Check if connecting to network adapters is supported.
	 *  Requires Npcap or WinPcap on Windows, libpcap on Linux and macOS.
	 *  @param installed set to true when the library is detected
	 *  @param enabled set to true when the pcap is able to detect network interfaces
	 */
	INERTIA_API void GetPcapAvailable(bool& installed, bool& enabled);

	/** Get the supported LogWriter and export file types.
	 *  @return a vector with supported LogFileTypes
	 */
	INERTIA_API std::vector<LogFileType> GetSupportedFileTypes();



	/** Add/update and open a connection (serial, ethernet) with the given properties.
	 *  @param settings settings for connection
	 *  @return true on success
	 */
	INERTIA_API bool ConnectionUpdate(ConnectionSettings const& settings);

	/** Try to remove the connection with the given name.
	 *  @param connection the name of the connection
	 *  @return false when it could not be removed
	 */
	INERTIA_API bool ConnectionRemove(std::wstring const& connection);

	/** Add a listener for stream events to a connection.
	 *  Use an empty name to add the listener as default listener, it will be used for all existing and new connections.
	 *  If a name of a connection is provided that is not (yet) opened, the pointer to the listener is stored until the connection
	 *  is opened, or until the listener is removed.
	 *  @param listener the class that receives stream events
	 *  @param connection the name of the connection used in ConnectionUpdate, empty for default listener
	 */
	INERTIA_API void ConnectionAddListener(StreamListenerPtr const& listener, std::wstring const& connection = std::wstring());

	/** Remove a listener for stream events from a connection.
	 *  @param listener the class that receives stream events
	 *  @param connection the name of the connection used in ConnectionUpdates, empty for default listener
	 */
	INERTIA_API void ConnectionRemoveListener(StreamListenerPtr const& listener, std::wstring const& connection = std::wstring());

	/** Check if a connection is handled.
	 *  @param connection the name of the connection
	 *  @return true if the connection has a handler
	 */
	INERTIA_API bool ConnectionFind(std::wstring const& connection);



	/** Update logging settings for a connection.
	 *  @param connection the name of the connection
	 *  @param logSettings logging settings
	 *  @return false if updating failed
	 */
	INERTIA_API bool LoggingUpdate(std::wstring const& connection, LogWriterSettings const& logSettings);

	/** Check which filename will be used when starting a log file. When already logging, return the file that is created.
	 *  @param connection the (optional) connection name (to get the filename when already logging)
	 *  @param settings the settings used for logging
	 *  @return the filename that will be created or is being used
	 */
	INERTIA_API std::wstring LoggingCheckFileName(std::wstring const& connection, LogWriterSettings const& settings);



	/** Read samples from given log reader settings.
	 *  @param settings log reader settings
	 *  @return false if updating failed
	 */
	INERTIA_API bool ReplayUpdate(LogReaderSettings const& settings);

	/** Stop reading from given log file.
	 *  @param filename name of file to stop reading
	 */
	INERTIA_API void ReplayRemove(std::wstring const& filename);

	/** Add a listener for stream events to a replay.
	 *  Use an empty name to add the listener as default listener, it will be used for all existing and new replays.
	 *  If a filename of a replay is provided that is not (yet) started, the pointer to the listener is stored until the replay
	 *  is started, or until the listener is removed.
	 *  @param listener the class that receives stream events
	 *  @param filename the name of the replay file used in ReplayUpdate, empty for default listener
	 */
	INERTIA_API void ReplayAddListener(StreamListenerPtr const& listener, std::wstring const& filename = std::wstring());

	/** Remove a listener for stream events from a replay.
	 *  @param listener the class that receives stream events
	 *  @param filename the name of the replay file used in ReplayUpdate, empty for default listener
	 */
	INERTIA_API void ReplayRemoveListener(StreamListenerPtr const& listener, std::wstring const& filename = std::wstring());

	/** Check if a file is being read.
	 *  @param filename name of file to check
	 *  @return true when file is being read, false when file has not been read or has finished
	 */
	INERTIA_API bool ReplayIsActive(std::wstring const& filename);

	/** The percentage of the file that has been read.
	 *  @param filename name of file to check
	 *  @return the percentage
	 */
	INERTIA_API unsigned ReplayGetProgress(std::wstring const& filename);

	/** Get samples from a replay, when reading the file synchronous.
	 *  @param filename to log file to read samples from
	 *  @param maxItems maximum number of samples to fetch
	 *  @return map with addrID and vector of samples
	 */
	INERTIA_API std::map<unsigned, std::vector<Sample> > const ReplayGetSamples(std::wstring const& filename, const unsigned maxItems);

	/** Get source file information encoded in the logfile. Requires at least 1 call to ReplayGetSamples() before info is available.
	 *  @param filename to log file to get info from
	 *  @return source info
	 */
	INERTIA_API LogWriterSourceInfo const ReplayGetSourceInfo(std::wstring const& filename);



	/** Get samples from the specified connection and addrID.
	 *  @param connection the name of the connection (or file)
	 *  @param addrID the applicable node
	 *  @param maxItems the maximum number of items to fetch
	 *  @param newest only get the newest samples, dropping any previously received samples
	 *  @return a vector of samples
	 */
	INERTIA_API std::vector<Sample> const DataGetSamples(std::wstring const& connection, const unsigned addrID, const unsigned maxItems, const bool newest = false);

	/** Get lost and total sample statistics.
	 *  @param connection the name of the connection (or file)
	 *  @param addrID the applicable node
	 *  @param lost the lost samples
	 *  @param received the received samples
	 */
	INERTIA_API void DataGetStats(std::wstring const& connection, const unsigned addrID, unsigned long& lost, unsigned long& received);

	/** Clear sample statistics.
	 *  @param connection the name of the connection (or file)
	 *  @param addrID the applicable node, 0 for all
	 */
	INERTIA_API void DataClearStats(std::wstring const& connection, const unsigned addrID = 0);

	/** Get the value based on the provided channel specification.
	 *  @param sample a sample including measurements taken at a certain time
	 *  @param spec the channel specification
	 *  @param value the sample value, NaN when invalid
	 *  @return true when a valid sample is returned
	 */
	INERTIA_API bool DataGetValue(Sample const& sample, ChannelSpec const& spec, double& value);



	/** Get all the addrIDs that are detected on the specified connection.
	 *  @param connection the name of the connection or file
	 *  @return a vector with the addrIDs
	 */
	INERTIA_API const std::vector<unsigned> GetNodeIDs(std::wstring const& connection);

	/** Clear all information (configurations, node info) of the specified addrIDs.
	 *  @param connection the name of the connection or file
	 *  @param addrIDs a vector with addrIDs to clear
	 *  @param onlyInvalidate keep info but request it again from the node
	 */
	INERTIA_API void ClearNodeIDs(std::wstring const& connection, std::vector<unsigned>& addrIDs, const bool onlyInvalidate);

	/** Get the sampling frequency of specified node and config type.
	 *  @param connection the name of the connection or file
	 *  @param addrID the applicable node
	 *  @param type the optional configuration type (e.g accelerometer, ADC)
	 *  @param index the optional group (for ADC2 configs) or sensorID (for xAxisConfigs)
	 *  @param instance the optional instance of a sensorID (for xAxisConfigs)
	 *  @return the sampling frequency in Hz, -1 when the addrID has no configuration,
	 *          or the global sampling frequency when the specific configuration is not available
	 */
	INERTIA_API double GetSamplingFrequency(std::wstring const& connection, const unsigned addrID, const ConfigType type = CONFIG_GLOBAL_SAMPLING, const unsigned index = 0, const int instance = -1);

	/** Get the configuration of a node.
	 *  @param connection the name of the connection or file
	 *  @param addrID the applicable node
	 *  @return the configuration of the node
	 */
	INERTIA_API const InertiaConfig GetConfiguration(std::wstring const& connection, const unsigned addrID);

	/** Get the device info of a node.
	 *  @param connection the name of the connection or file
	 *  @param addrID the applicable node
	 *  @return the device info of the node
	 */
	INERTIA_API const DeviceInfo GetDeviceInfo(std::wstring const& connection, const unsigned addrID);

	/** Send a configuration to a device.
	 *  @param connection the name of the connection
	 *  @param config the configuration to send
	 *  @param addrID the applicable node, default is ADDRESS_BROADCAST for broadcast
	 *  @return true when the configuration is successfully scheduled
	 */
	INERTIA_API bool SendConfiguration(std::wstring const& connection, InertiaConfig const& config, const unsigned addrID = ADDRESS_BROADCAST);

	/** Send a command to a device.
	 *  @param connection the name of the connection
	 *  @param command the command to send
	 *  @param addrID the applicable node, default is ADDRESS_BROADCAST for broadcast
	 *  @return true when the command is successfully scheduled
	 */
	INERTIA_API bool SendCommand(std::wstring const& connection, InertiaCommands const& command, const unsigned addrID = ADDRESS_BROADCAST);

	/** Send a service request to a device.
	 *  @param connection the name of the connection
	 *  @param service the service request to send
	 *  @param addrID the applicable node, default is ADDRESS_BROADCAST for broadcast
	 *  @return true when the service message is successfully scheduled
	 */
	INERTIA_API bool SendServiceRequest(std::wstring const& connection, ServiceRequest const& service, const unsigned addrID = ADDRESS_BROADCAST);

	/** Enable automatically modifying an individual sensors sampling rate when the global sampling rate changes,
	 *  so the sensors keep sampling at allowed sampling rates.
	 *  @param enable true to automatically update the sampling rates
	 */
	INERTIA_API void SetAutoUpdateSensorSamplingRate(const bool enable);

	/** Set to use raw or converted ADC samples.
	*  By default, the ADC samples are converted to Voltage. Use this to enable or disable this conversion.
	*  @param enable Enable raw ADC Samples
	*/
	INERTIA_API void SetUseRawADCSamples(const bool enable);


	/** Update calibration settings, and parse the file when applicable.
	 *  Note: this function will not return until the calibration file is read.
	 *  @param settings the calibration settings
	 *  @return a set with detected nodes
	 */
	INERTIA_API std::set<unsigned> CalibrateUpdate(CalibrationSettings const& settings);

	/** Remove calibration data of the given file.
	 *  @param filename the file for which calibration needs to be removed
	 *  @return true if successful, else false
	 */
	INERTIA_API bool CalibrateRemove(std::wstring const& filename);

	/** Get the calibration results.
	 *  @param filename the file used
	 *  @param addrID the applicable node
	 *  @param valueType the type of data
	 *  @return CalibrationResults
	 */
	INERTIA_API const CalibrationResults CalibrateGetResults(std::wstring const& filename, unsigned const addrID, ValueType const valueType);

	/** Get detailed calibration data.
	 *  @param filename the file to use
	 *  @param addrID the applicable node
	 *  @param calibration the calibration results to apply
	 *  @param timestamp the timestamps
	 *  @param norm the normalized sensor data
	 *  @param appliedNorm the normalized sensor data with applied calibration
	 */
	INERTIA_API void CalibrateGetData(std::wstring const& filename, unsigned const addrID, CalibrationResults const& calibration,
		std::vector<double>& timestamp, std::vector<double>& norm, std::vector<double>& appliedNorm);



	/** @brief Available FFT window function */
	enum FFTWindowFunction : unsigned
	{
		FFT_RECTANGULAR = 0, ///< Rectangular window.
		FFT_TRIANGULAR,      ///< Triangular window.
		FFT_HAMMING,         ///< Hamming window.
		FFT_HANNING,         ///< Hanning window.
		FFT_BLACKMAN,        ///< Blackman window.
		FFT_END
	};

	/** Initialize the number of FFT samples and FFT window method, and start listening to samples.
	 *  @param points use 2^p points for the FFT calculation
	 *  @param interval number of milliseconds between FFT calculations
	 *  @param window the #FFTWindowFunction method to use
	 *  @param removeDC remove the mean DC signal to reduce the 0-component
	 */
	INERTIA_API void FFTInit(const unsigned points, const unsigned interval, const FFTWindowFunction window, const bool removeDC);

	/** Start FFT capturing for the specified channel.
	 *  @param channel the channel to capture
	 */
	INERTIA_API void FFTStart(ChannelSpec const& channel);

	/** Stop FFT capturing for all channels.
	 */
	INERTIA_API void FFTStop();

	/** Get the FFT listener.
	 *  @return the FFT StreamListener
	 */
	INERTIA_API StreamListenerPtr FFTGetListener();

	/** Get the last calculated FFTs of the given connection and channel.
	 *  @param connection the name of the connection (or file)
	 *  @param channel the channel specification
	 *  @param erase remove the existing FFT so the next call will return either a new FFT or an empty map
	 *  @return a map with values for each addrID
	 */
	INERTIA_API std::map<unsigned, std::vector<double> > const FFTGet(std::wstring const& connection, ChannelSpec const& channel, const bool erase = false);



	/** Start downloading a new file, or add it to the queue.
	 *  @param connection the name of the connection
	 *  @param addrID the applicable node
	 *  @param flashname the file to download
	 *  @param logSettings the settings used for writing the file
	 *  @return true when successfully added
	 */
	INERTIA_API bool DownloadFlashStart(std::wstring const& connection, const unsigned addrID, std::wstring const& flashname, LogWriterSettings const& logSettings);

	/** Cancel downloading a file, or remove it from the queue.
	 *  @param connection the name of the connection
	 *  @param addrID the applicable node
	 *  @param flashname the file to cancel
	 *  @return true when successfully canceled
	 */
	INERTIA_API bool DownloadFlashStop(std::wstring const& connection, const unsigned addrID, std::wstring const& flashname);

	/** Get a list of files being downloaded or queued. Use an empty connection name to get all files of all connections and nodes.
	 *  @param connection the name of the connection
	 *  @param addrID the applicable node
	 *  @return a vector with pending downloads
	 */
	INERTIA_API std::vector<std::wstring> DownloadFlashGetActive(std::wstring const& connection, const unsigned addrID);

	/** Start uploading a file, or add it to the queue.
	 *  @param connection the name of the connection
	 *  @param addrID the applicable node
	 *  @param flashname the filename in the flash on the node
	 *  @param filename the file to upload
	 *  @return true when successfully added
	 */
	INERTIA_API bool UploadFlashStart(std::wstring const& connection, const unsigned addrID, std::wstring const& flashname, std::wstring const& filename);

	/** Cancel uploading a file, or remove it from the queue.
	 *  @param connection the name of the connection
	 *  @param addrID the applicable node
	 *  @param flashname the file to cancel
	 *  @return true when successfully canceled
	 */
	INERTIA_API bool UploadFlashStop(std::wstring const& connection, const unsigned addrID, std::wstring const& flashname);

	/** Get a list of files being uploaded or queued. Use an empty connection name to get all files of all connections and nodes.
	 *  @param connection the name of the connection
	 *  @param addrID the applicable node
	 *  @return a vector with pending uploads
	 */
	INERTIA_API std::vector<std::wstring> UploadFlashGetActive(std::wstring const& connection, const unsigned addrID);



	/** Convert a binary file to a different format.
	 *  @param filename the binary source file
	 *  @param convertSettings settings for converting a log file
	 *  @param createdFile the actual filename that will be converted in to
	 *  @return true when successfully started
	 */
	INERTIA_API bool ConvertFileStart(std::wstring const& filename, ConvertFileSettings const& convertSettings, std::wstring& createdFile);

	/** Stop conversion if it is still running.
	 *  @param filename the binary source file
	 */
	INERTIA_API void ConvertFileStop(std::wstring const& filename);

	/** Check if a file is being converted.
	 *  @param filename the source filename to check
	 *  @return true if active
	 */
	INERTIA_API bool ConvertFileIsActive(std::wstring const& filename);



	/** Set the number of retries to use when filling lost samples misses some samples.
	 *  @param retries the number of retries
	 *  @param keepBackup create a copy of the unfilled file
	 *  @param slots change number of slots during fill-loss (0 = don't change)
	 *  @param maxFlashDiff the maximum time difference (in seconds) allowed between
	 *                      the file to fill and the timestamp of the flash logs
	 *  @param speedStatistics add messages to fill-loss callbacks with estimated
	 *                         speed statistics
	 */
	INERTIA_API void FillLossUpdateSettings(const unsigned retries, const bool keepBackup,
		const unsigned slots = 0, const unsigned maxFlashDiff = 60, const bool speedStatistics = true);

	/** Fill lost samples in a binary file.
	 *  @param filename the binary source file
	 *  @param connection the name of the connection
	 *  @return true when successfully started
	 */
	INERTIA_API bool FillLossStart(std::wstring const& filename, std::wstring const& connection);

	/** Stop filling in lost samples.
	 *  @param filename the binary source file
	 */
	INERTIA_API void FillLossStop(std::wstring const& filename);

	/** Check if a file is being filled in.
	 *  @param filename filename to check
	 *  @return true if active
	 */
	INERTIA_API bool FillLossIsActive(std::wstring const& filename);



	/** Merge multiple itlog files into one file.
	 *  @param logSettings settings for creating a log file
	 *  @param filenames the binary source files
	 *  @param createdFile the actual filename that will be merged in to
	 *  @return true when successfully started
	 */
	INERTIA_API bool MergeFilesStart(LogWriterSettings const& logSettings, std::vector<std::wstring> const& filenames, std::wstring& createdFile);

	/** Stop merging files.
	 *  @param filename the file that is being created (filename from MergeFilesStart logSettings.fileSettings.logfile)
	 */
	INERTIA_API void MergeFilesStop(std::wstring const& filename);

	/** Check if a file is being merged.
	 *  @param filename the file to check
	 *  @return true if active
	 */
	INERTIA_API bool MergeFilesIsActive(std::wstring const& filename);



	/** Create a new orientation algorithm, or reset an existing algorithm.
	 *  @param connection the name of the connection
	 *  @param addrID the applicable node
	 */
	INERTIA_API void OrientationUpdate(std::wstring const& connection, const unsigned addrID);

	/** Remove an orientation algorithm.
	 *  @param connection the name of the connection, empty to remove all
	 *  @param addrID the applicable node, 0 to remove all
	 */
	INERTIA_API void OrientationRemove(std::wstring const& connection = std::wstring(), const unsigned addrID = 0);

	/** Enable or disable using orientation algorithms.
	 *  @param enable true to enable
	 */
	INERTIA_API void OrientationEnable(const bool enable);

	/** Check if using orientation algorithms are enabled.
	 *  @return true when enabled
	 */
	INERTIA_API bool OrientationIsEnabled();

	/** Get the Orientation Algorithm settings.
	 *  @param connection the name of the connection, empty for default settings
	 *  @param addrID the applicable node, 0 for default settings
	 *  @return the settings
	 */
	INERTIA_API OrientationSettings OrientationGetSettings(std::wstring const& connection = std::wstring(), const unsigned addrID = 0);

	/** Update the Orientation Algorithm settings.
	 *  If the OrientationAlgorithm is changed, all algorithms are reset.
	 *  @param settings the settings to use
	 *  @param connection the name of the connection, empty for all connections
	 *  @param addrID the applicable node, 0 for all nodes
	 *  @param reset this will reset the Orientation Algorithm, setting a different algorithm will always reset it
	 */
	INERTIA_API void OrientationUpdateSettings(OrientationSettings const& settings, std::wstring const& connection = std::wstring(), const unsigned addrID = 0, const bool reset = true);

	/** Set the orientation algorithm to a specific orientation.
	 *  @param connection the name of the connection
	 *  @param addrID the applicable node
	 *  @param quat the orientation to appy
	 */
	INERTIA_API void OrientationSet(std::wstring const& connection, const unsigned addrID, inertia::Quaternion const& quat);

	/** Calculate orientation directly from sensor data.
	 *  @param connection the name of the connection
	 *  @param addrID the applicable node
	 *  @param sample the sample with the sensor data that will get the quaternion
	 */
	INERTIA_API void OrientationCalculate(std::wstring const& connection, const unsigned addrID, inertia::Sample& sample);



	/** Add or update a TCP connection with given properties, return true upon success.
	 *  The TCP connection can be used to control the InertiaSDK (as server) or to let the InertiaSDK send data to a remote connection (as client).
	 *  @param settings new or updated socket settings
	 *  @param filter new or updated stream filter settings
	 *  @return callback class for receiving stream status updates from a connection, nullptr on failure
	 */
	INERTIA_API StreamListenerPtr NetworkUpdateConnection(SocketSettings const& settings, StreamFilter const& filter);

	/** Check if a TCP socket is handled.
	 *  @param hostname hostname when using TCP client, for TCP server use an empty string
	 *  @param port port of TCP server to listen on or TCP client to connect to
	 *  @return true if the port has a handler
	 */
	INERTIA_API bool NetworkFindConnection(std::wstring const& hostname, const unsigned port);

	/** Try to remove TCP socket with given parameters.
	 *  @param hostname hostname when using TCP client, for TCP server use an empty string
	 *  @param port port of TCP server to listen on or TCP client to connect to
	 *  @return false when it could not be removed
	 */
	INERTIA_API bool NetworkRemoveConnection(std::wstring const& hostname, const unsigned port);



	/** Validate the given parameters. Results are forwarded via the asynchronous RRPProgress service response.
	 *  @param connection the name of the connection the device is connected to. Leave empty to validate only filename
	 *  @param addrID the ID of the node
	 *  @param settings firmware update settings
	 */
	INERTIA_API void FirmwareValidate(std::wstring const& connection, unsigned const addrID, FirmwareSettings const& settings);

	/** Validate and reprogram with the given parameters. Results are forwarded via the asynchronous RRPProgress service response.
	 *  @param connection the name of the connection the device is connected to
	 *  @param addrID the ID of the node
	 *  @param settings firmware update settings
	 */
	INERTIA_API void FirmwareReprogram(std::wstring const& connection, unsigned const addrID, FirmwareSettings const& settings);



	/** Add a custom sampling channel.
	 *  @param serialNr the serial number of the applicable device
	 *  @param samplingChannel the sampling channel to add, value from 0 to 255
	 *  @param customChannel channel information
	 */
	INERTIA_API void CustomChannelAdd(uint64_t const serialNr, const int samplingChannel, Channel const& customChannel);

	/** Remove a custom sampling channel.
	 *  @param serialNr the serial number of the applicable device
	 *  @param samplingChannel the sampling channel to remove, -1 to clear all channels
	 */
	INERTIA_API void CustomChannelRemove(uint64_t const serialNr, const int samplingChannel = -1);

	/** Get the custom sampling channels.
	 *  @param serialNr the serial number of the applicable device
	 *  @return a map of channels
	 */
	INERTIA_API ChannelMap CustomChannelGet(uint64_t const serialNr);



	/** Stop and destruct all asynchronous threads used in the Library
	 *  Should only be called at end of program.
	 */
	INERTIA_API void Destruct();

} // namespace inertia
