ABS SCPI Driver 0.2.0
ABS SCPI driver library
Loading...
Searching...
No Matches
ABS SCPI Driver

C/C++ driver for communicating with a Bloomy Controls Advanced Battery Simulator (ABS) via SCPI over TCP, UDP, and RS-485.

Features

  • TCP, UDP, RS-485, and UDP multicast
  • Modern, native C++20 library
  • Supports Windows and Linux
  • Implements all SCPI commands and queries supported by the ABS
  • Automatic device discovery over UDP multicast and RS-485 to quickly find and identify devices
  • Exception-less error handling (see below)
  • C wrapper (include/bci/abs/CInterface.h) for use in C and other languages
  • Easy inclusion in CMake projects
  • Python bindings

‍[!NOTE] Exceptions are not handled internally unless it is necessary to do so. Any exceptions thrown by this library are considered critical exceptional situations, such as a failure to allocate memory.

Example Usage (C++)

This example uses a UDP driver to query the device's information (equivalent to a *IDN? over SCPI). This library makes use of Sy Brand's excellent expected library to provide exception-less error handling. If this library throws an exception, it is considered an exceptional event, and is generally expected to be unrecoverable.

Note that the UDP driver's Open() function also has an overload which takes the local IP address to bind to. If you have multiple NICs, you probably want to use this option.

#include <iostream>
int main(void) {
using ec = bci::abs::ErrorCode;
auto driver{std::make_shared<bci::abs::drivers::UdpDriver>()};
bci::abs::ScpiClient client{driver};
auto ret = driver->Open("192.168.1.100");
if (ret != ec::kSuccess) {
std::cerr << "Failed to open device: " << bci::abs::ErrorMessage(ret)
<< '\n';
return 1;
}
if (auto idn = client.GetDeviceInfo()) {
std::cout << "Part number: " << idn->part_number << '\n';
std::cout << "Serial number: " << idn->serial << '\n';
std::cout << "Version: " << idn->version << '\n';
} else {
std::cerr << "Failed to get device info: "
<< bci::abs::ErrorMessage(idn.error()) << '\n';
return 1;
}
}
Primary SCPI client declaration.
Generic SCPI client for communicating with the Bloomy Controls ABS.
Definition ScpiClient.h:54
ErrorCode
Error codes returned by driver functions.
Definition CommonTypes.h:137
const char * ErrorMessage(ErrorCode ec) noexcept
Get an error message string for a given error code.

Example Usage (C)

This example implements the same logic as the C++ example above using the C interface.

#include <stdio.h>
static void FormatErr(const char* msg, int ec) {
fprintf(stderr, "%s: %s (%d)\n", msg, AbsScpiClient_ErrorMessage(ec), ec);
}
int main(void) {
int ret = 1;
int ec;
AbsScpiClientHandle handle = NULL;
ec = AbsScpiClient_Init(&handle);
if (ec < 0) {
FormatErr("failed to initialize client", ec);
goto cleanup;
}
ec = AbsScpiClient_OpenUdp(handle, "192.168.1.100", NULL);
if (ec < 0) {
FormatErr("failed to open device", ec);
goto cleanup;
}
ec = AbsScpiClient_GetDeviceInfo(handle, &idn);
if (ec < 0) {
FormatErr("failed to get device info", ec);
goto cleanup;
}
printf("Part number: %s\n", idn.part_number);
printf("Serial number: %s\n", idn.serial);
printf("Version: %s\n", idn.version);
ret = 0;
cleanup:
return ret;
}
C-style interface to the library.
void * AbsScpiClientHandle
ABS SCPI client handle.
Definition CInterface.h:133
int AbsScpiClient_Init(AbsScpiClientHandle *handle_out)
Initialize a SCPI client.
void AbsScpiClient_Destroy(AbsScpiClientHandle *handle)
Destroy a SCPI client.
const char * AbsScpiClient_ErrorMessage(int error)
Get an error message to describe an error code returned by the driver.
int AbsScpiClient_OpenUdp(AbsScpiClientHandle handle, const char *target_ip, const char *interface_ip)
Open a UDP connection to the ABS.
int AbsScpiClient_GetDeviceInfo(AbsScpiClientHandle handle, AbsDeviceInfo *info_out)
Query basic information about the unit.
ABS device information structure. All strings are guaranteed to be null-terminated.
Definition CInterface.h:141
char version[128]
Version number.
Definition CInterface.h:144
char serial[128]
Serial number.
Definition CInterface.h:143
char part_number[128]
Part number.
Definition CInterface.h:142

Building

To build the driver as a shared library (.DLL or .so), first configure CMake, then execute the build system. This project can also be built with Visual Studio.

cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON
cmake --build build

Adding to a CMake Project

In your CMakeLists.txt, fetch and link with the driver:

FetchContent_Declare(abs-driver
GIT_REPOSITORY https://github.com/BloomyControls/abs-scpi-driver.git
GIT_TAG v1.0.0
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(abs-driver)
target_link_libraries(my_program PRIVATE bci::absscpi)

If you have already installed the driver to a standard location on your system, you can use find_package instead:

find_package(absscpi 1.0.0 REQUIRED)
target_link_libraries(my_program PRIVATE bci::absscpi)

‍[!TIP] On Windows, the MSI installer will register the CMake package in the Windows registry, so the above example will build and link successfully. However, because the DLL is not located in the PATH environment variable, the DLL will fail to be found at runtime. To fix this, you can add a CMake command to copy the DLL to the build directory and you can add an install target to copy the DLL when installing your target.

Dependencies

This library does not have any runtime dependencies aside from the standard C/C++ runtime libraries on your system. However, it does have some build dependencies. If these are installed on your system, CMake will find and use them if your installed versions are compatible. Otherwise, it will automatically fetch and build them as part of the build. The build dependencies are:

  • fmt v10.2.1
  • Boost v1.81.0
  • FastFloat v6.1.1

These are all linked statically, regardless of the build configuration.

License

Copyright (c) 2024, Bloomy Controls, Inc. All rights reserved.

This software is distributed under the BSD-3-clause license. See the LICENSE file or https://opensource.org/license/BSD-3-Clause for details.