BPNGClientLib
Library for accessing the Telemotive data logger devices
User's manual - BLUEPIRAT Client Library 5.0.1

General

This is the documentation for the C++ BLUEPIRAT Client library which is compatible with all Microsoft compilers. The library's interface class IBPNGClient uses only base data type parameters like int, long and char, pointers to those types and pointers to complex proprietary data objects that are entirely defined within the library. To access the data of such objects the library comes with own interface definitions for all of those complex data types (like e.g. IConversionSet, see BPNGDefines.h). All library functions are blocking functions. Status and progress information is processed via listener callbacks (see IBPNGClientListener). Errors are processed by the functions' return values (see section Error handling for more details).

Functionality

The BLUEPIRAT Client Library provides methods for base functionality like:

Besides that there are several more functions for deleting data, setting the logger's/TSL time and marker, scanning the network for available loggers/TSL, etc.

Error handling and listener mechanism

All errors are processed by the functions' return values. If the return value states an error a call to getLastError() provides details about the error(s) occurred. Warnings are not intended to abort a process. That's why they are reported via the function IBPNGClientListener::onWarning(). It's up to the user to handle them or not.

Progress and status information is also processed via listener callbacks. You have to derive your own class from IBPNGClientListener and implement all functions you need. Register an object of your listener class at the executing IBPNGClient with IBPNGClient::addListener().

Compiler/Linker

The library is build with Microsoft Visual C++ and is linked to the C-Runtime Library with the Multi-threaded resp. Multi-threaded Debug compiler switch (/MT resp. /MTd). The user's project must have the same settings. Applications with mixed runtime library linkage may cause errors that are difficult to diagnose and to handle. The debug version of the library is named with a "_d" suffix.

Thread safety

The library is thread safe when using different objects of IBPNGClient resp. the objects' pointers in different threads. It is NOT thread safe for one IBPNGClient instance in several threads!

Demo project

The "sample" directory contains a demo project for the BLUEPIRAT Client Library.

Exampe for lib unsage:

//************************************************************
//
// main.cc
//
//************************************************************
// sys
#include <sys/stat.h>
#include <cerrno>
#include <ctime>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
// tmlib
#ifndef _MSC_VER
#include <fileutils.hh>
#endif
// atom
#include "BPNGDefines.h"
// client
#include "windirent.h"
#include <IBPNGClient.h>
#include "RdbEventList.hh"
#ifndef _MSC_VER
#include <sys/stat.h>
#else
#include <direct.h>
#define mkdir(a, b) _mkdir(a)
#endif
using namespace std;
/********************************************************************ONLINE*DOWNLOAD***********************************************************/
static void sampleFunctionDownload(OnlineLoggerInfo device);
static void sampleFunctionTSLDownload(TSLClusterImpl tsl);
/********************************************************************ONLINE*CONVERSION*********************************************************/
static void sampleFunctionOnlineConversion(OnlineLoggerInfo device);
static void sampleFunctionTSLOnlineConversion(TSLClusterImpl tsl);
/********************************************************************CONFIG********************************************************************/
static void sampleFunctionConfiguration(OnlineLoggerInfo device);
static void sampleFunctionTSLConfiguration(TSLClusterImpl tsl);
/********************************************************************OFFLINE*CONVERSION********************************************************/
static void sampleFunctionOfflineConversion();
static void sampleFunctionOfflineTSLConversion();
/********************************************************************HELPERS*******************************************************************/
static string getLocalDateString();
static vector<string> readZipsFromDirectory(string dir);
int main()
{
// Get list of all currently available blue PiraT 2 devices
vector<OnlineLoggerInfo> devices = detector.getLoggerList(0);
vector<TSLClusterImpl> tsls = detector.getTSLs(devices);
// select the device you want to work with
TSLClusterImpl targetTsl;
bool found = false;
bool tslFound = false;
//map for tsl's
for (size_t i = 0; i < devices.size(); ++i)
{
if (strcmp(devices[i].ip, "192.168.0.233") == 0)
{
device = devices[i];
found = true;
break;
}
}
for (size_t i = 0; i < tsls.size(); ++i)
{
TSLClusterImpl tsl = tsls[i];
cout << "Found TSL [" << tsl.getTSLName() << "] with devices\n";
tsl.print();
cout << "\n";
/* insert target tsl name here*/
if (tsl.getTSLName() == "NoTSLName")
{
targetTsl = tsl;
tslFound = true;
}
}
/* activate one of the sample functions */
if (found)
{
//sampleFunctionDownload(device);
//sampleFunctionOnlineConversion(device);
//sampleFunctionConfiguration(device);
}
if (tslFound)
{
//sampleFunctionTSLConfiguration(targetTsl);
//sampleFunctionTSLDownload(targetTsl);
//sampleFunctionTSLOnlineConversion(targetTsl);
}
/* offline samples*/
//sampleFunctionOfflineConversion();
//sampleFunctionOfflineTSLConversion();
int ret = system("pause");
if (ret == -1)
cerr << "error in system(\"pause\"): " << strerror(errno) << endl;
}
/********************************************************************ONLINE*DOWNLOAD***********************************************************/
// We want to download all traces since last startup to an offline data set
#ifndef _MSC_VER
static void sampleFunctionDownload(OnlineLoggerInfo device) __attribute__((unused));
#endif
static void sampleFunctionDownload(OnlineLoggerInfo device)
{
// connect logger
BOOL ret = client->connectLogger(1 , &device);
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to connect logger. " << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
ret = client->initialize();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to init online." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
IRdbEventList *list = client->getEventList();
RdbEventList eventList(list);
if (eventList.size() == 0)
{
cout << "Empty event list" << endl;
client->disconnectLogger();
client->release();
return;
}
uint64_t startupId = 0;
uint64_t endId = -1; //max value for uint64 to include everything in the id range
// search last startup
for (int i = eventList.size() - 1; i >= 0; --i)
{
if (eventList[i].type == STARTUP)
{
startupId = eventList[i].uniqueID;
break;
}
}
DataSpan span;
span.type = DST_IDSPAN;
span.start = startupId;
span.end = endId;
// if you want to download several spans, put them in a vector
vector<DataSpan> spanVec;
spanVec.push_back(span);
ret = mkdir("..\\testoutdir", 0x777);
if (ret != 0 && errno != EEXIST)
{
cout << "Failed to create output directory" << endl;
client->disconnectLogger();
client->release();
return;
}
ret = client->downloadDataSpans(spanVec.size(), &spanVec[0], "..\\testoutdir\\BP2_Offline.zip", 0);
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to dowload data." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
// disconnect
client->disconnectLogger();
// free memory
client->release();
}
// We want to download all traces since last startup to an offline data set
#ifndef _MSC_VER
static void sampleFunctionTSLDownload(TSLClusterImpl tsl) __attribute__((unused));
#endif
static void sampleFunctionTSLDownload(TSLClusterImpl tsl)
{
client->setTSLCluster(tsl.getTSLCluster());
// connect logger
BOOL ret = client->connect();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to connect tsl. " << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
ret = client->initialize();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to init online." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
IRdbEventList *list = client->getEventList();
RdbEventList eventList(list);
if (eventList.size() == 0)
{
cout << "Empty event list" << endl;
client->disconnectLogger();
client->release();
return;
}
uint64_t startupId = 0;
uint64_t endId = -1; //max value for uint64 to include everything in the id range
// search last startup
for (int i = eventList.size() - 1; i >= 0; --i)
{
if (eventList[i].type == STARTUP)
{
startupId = eventList[i].uniqueID;
break;
}
}
DataSpan span;
span.type = DST_IDSPAN;
span.start = startupId;
span.end = endId;
// if you want to download several spans, put them in a vector
vector<DataSpan> spanVec;
spanVec.push_back(span);
ret = mkdir("..\\testoutdir", 0x777);
if (ret != 0 && errno != EEXIST)
{
cout << "Failed to create output directory" << endl;
client->disconnectLogger();
client->release();
return;
}
ret = client->downloadDataSpans(spanVec.size(), &spanVec[0], "..\\testoutdir\\TSL_Offline.zip", 0);
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to dowload data." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
// disconnect
client->disconnectLogger();
// free memory
client->release();
}
/********************************************************************ONLINE*CONVERSION*********************************************************/
// We want to convert all CAN traces from the logger
// around the last Marker to CANoe asc and BLF format.
#ifndef _MSC_VER
static void sampleFunctionOnlineConversion(OnlineLoggerInfo device) __attribute__((unused));
#endif
static void sampleFunctionOnlineConversion(OnlineLoggerInfo device)
{
// connect logger
BOOL ret = client->connectLogger(1, &device);
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to connect logger." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
ret = client->initialize();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to init online." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
IRdbEventList* list = client->getEventList();
RdbEventList eventList(list);
if (eventList.size() == 0)
{
cout << "Empty event list" << endl;
client->disconnectLogger();
client->release();
return;
}
uint64_t markerTimeStamp = 0;
// search last marker
for (int i = eventList.size() - 1; i >= 0; --i)
{
if (eventList[i].type == MARKER)
{
markerTimeStamp = eventList[i].timeStamp;
break;
}
}
if (markerTimeStamp == 0)
{
cout << "No marker found." << endl;
client->disconnectLogger();
client->release();
return;
}
// Ensure the out directory exists
ret = mkdir("..\\testoutdir", 0x777);
if (ret != 0 && errno != EEXIST)
{
cout << "Failed to create output directory" << endl;
client->disconnectLogger();
client->release();
return;
}
// Get a conversion set
IConversionSet* conversionSet = client->createNewConversionSet();
// The time span has to be 60s before and 60s after the marker
uint64_t startTime = markerTimeStamp - 60 * 1000000; // in usec
uint64_t endTime = markerTimeStamp + 60 * 1000000; // in usec
// If you want to convert more than one span,
// call this function several times
conversionSet->addTimeSpan(startTime, endTime);
// CAN #1 and CAN #2 are supposed to be written to one asc output file each.
// CAN #3 and CAN #4 are supposed to be written together in another asc file.
// All other CAN channels are supposed to be written together in one BLF file.
const IChannelList* channels = client->getLoggerChannels();
for (int i = 0; i < channels->getSize(); ++i)
{
ChannelType type = channels->getChannel(i)->getType();
if (type != CH_CAN)
continue;
// Note: channel indices are zero based
int index = channels->getChannel(i)->getIndex();
if (index == 0 || index == 1)
{
// CAN #1 and #2 in separate files
// -1 as fileId parameter creates a separate file for this channel
conversionSet->addChannel(type,
index,
CANOE,
-1,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
else if (index == 2 || index == 3)
{
// CAN #3 and #4 in the same file.
// fileId != -1 will write all channels with the same format and same
// file Id to the same output file (if procurable in accordance with
// the format specification.
conversionSet->addChannel(type,
index,
CANOE,
10,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
else
{
// All other CAN channels to one BLF file.
conversionSet->addChannel(type,
index,
BLF,
20,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
}
ret = client->convertData(conversionSet, "..\\testoutdir");
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to convert data." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
// disconnect
client->disconnectLogger();
// free memory
client->release();
}
#ifndef _MSC_VER
static void sampleFunctionTSLOnlineConversion(TSLClusterImpl tsl) __attribute__((unused));
#endif
static void sampleFunctionTSLOnlineConversion(TSLClusterImpl tsl)
{
client->setTSLCluster(tsl.getTSLCluster());
// connect logger
BOOL ret = client->connect();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to connect tsl." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
ret = client->initialize();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to init online." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
IRdbEventList* list = client->getEventList();
RdbEventList eventList(list);
if (eventList.size() == 0)
{
cout << "Empty event list" << endl;
client->disconnectLogger();
client->release();
return;
}
uint64_t markerTimeStamp = 0;
// search last marker
for (int i = eventList.size() - 1; i >= 0; --i)
{
if (eventList[i].type == MARKER)
{
markerTimeStamp = eventList[i].timeStamp;
break;
}
}
if (markerTimeStamp == 0)
{
cout << "No marker found." << endl;
client->disconnectLogger();
client->release();
return;
}
// Ensure the out directory exists
ret = mkdir("..\\testoutdir", 0x777);
if (ret != 0 && errno != EEXIST)
{
cout << "Failed to create output directory" << endl;
client->disconnectLogger();
client->release();
return;
}
// Get a conversion set
IConversionSet* conversionSet = client->createNewConversionSet();
// The time span has to be 60s before and 60s after the marker
uint64_t startTime = markerTimeStamp - 60 * 1000000; // in usec
uint64_t endTime = markerTimeStamp + 60 * 1000000; // in usec
// If you want to convert more than one span,
// call this function several times
conversionSet->addTimeSpan(startTime, endTime);
// CAN #1 and CAN #2 are supposed to be written to one asc output file each.
// CAN #3 and CAN #4 are supposed to be written together in another asc file.
// All other CAN channels are supposed to be written together in one BLF file.
// On TSL we have to add offset and mainboardnumber for channel identification.
const IChannelList* channels = client->getLoggerChannels();
for (int i = 0; i < channels->getSize(); ++i)
{
ChannelType type = channels->getChannel(i)->getType();
if (type != CH_CAN)
continue;
// Note: channel indices are zero based
int index = channels->getChannel(i)->getIndex();
if (index == 0 || index == 1)
{
// CAN #1 and #2 in separate files
// -1 as fileId parameter creates a separate file for this channel
conversionSet->addChannel(type,
index,
CANOE,
-1,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
else if (index == 2 || index == 3)
{
// CAN #3 and #4 in the same file.
// fileId != -1 will write all channels with the same format and same
// file Id to the same output file (if procurable in accordance with
// the format specification.
conversionSet->addChannel(type,
index,
CANOE,
10,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
else
{
// All other CAN channels to one BLF file.
conversionSet->addChannel(type,
index,
BLF,
20,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
}
ret = client->convertData(conversionSet, "..\\testoutdir");
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to convert data." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
// disconnect
client->disconnectLogger();
// free memory
client->release();
}
/********************************************************************CONFIG********************************************************************/
// This function shows how to:
// - download the configuration
// - reconfigurate the logger device
// - set the default config
#ifndef _MSC_VER
static void sampleFunctionConfiguration(OnlineLoggerInfo device) __attribute__((unused));
#endif
static void sampleFunctionConfiguration(OnlineLoggerInfo device)
{
client->setDevice(device);
BOOL ret = client->connect();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to connect logger." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
// save current config
stringstream targetPath;
targetPath << "..\\testoutdir\\bpng_[" << device.mbnr << "]_[" << getLocalDateString() << "].zip";
ret = client->getConfig(targetPath.str().c_str());
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to download configuration." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
// here you could change the downloaded configuration
// by extracting it and modifying the xml files
// see documentation of IBPNGClient::getConfig()
// or IBPNGClient::reconfigLogger().
// the new config archive needs a date in its filename in this form: YYYY-MM-DD_HH-MM-SS
// We use the same config that we downloaded
string newConfigPath = targetPath.str();
pair.key = device;
pair.value = newConfigPath.c_str();
ret = client->reconfigLogger(1, &pair);
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to reconfigurate the logger." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
// Setting the default config
ret = client->setDefaultConfig();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to set default config to the logger." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
// disconnect
client->disconnectLogger();
// free memory
client->release();
}
// This function shows how to:
// - download the configuration
// - reconfigurate the logger device
// - set the default config
#ifndef _MSC_VER
static void sampleFunctionTSLConfiguration(TSLClusterImpl tsl) __attribute__((unused));
#endif
static void sampleFunctionTSLConfiguration(TSLClusterImpl tsl)
{
//get the tsl client instance
client->setTSLCluster(tsl.getTSLCluster());
BOOL ret = client->connect();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to connect TSL." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
// save current config
string targetPath = "..\\testoutdir\\tsl_[" + tsl.getTSLName() + "]_[" + getLocalDateString() + "]";
ret = client->getConfig(targetPath.c_str());
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to download configurations." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
// here you could change the downloaded configuration
// by extracting it and modifying the xml files
// see documentation of IBPNGClient::getConfig()
// or IBPNGClient::reconfigLogger().
// the new config archive needs a date in its filename in this form: YYYY-MM-DD_HH-MM-SS
// We use the same config that we downloaded
// for tsl we have to create one string which includes all config-ip pairs
vector<string> configZips = readZipsFromDirectory(targetPath);
vector<string> paths;
vector<OnlineLoggerInfoStringPair> pairs;
for (vector<OnlineLoggerInfo>::iterator iter = tsl.begin(); iter != tsl.end(); ++iter)
{
OnlineLoggerInfo device = *iter;
for (size_t i = 0; i != configZips.size(); ++i)
{
string configZip = configZips[i];
if (configZip.find(device.mbnr) != string::npos)
{
pair.key = device;
paths.push_back(targetPath + "\\" + configZip);
pair.value = paths.back().c_str();
pairs.push_back(pair);
break;
}
}
}
ret = client->reconfigLogger(pairs.size(), &pairs[0]);
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to reconfigurate the logger." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
ret = client->setDefaultConfig();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to set default config to the logger." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->disconnectLogger();
client->release();
return;
}
// disconnect
client->disconnectLogger();
// free memory
client->release();
}
/********************************************************************OFFLINE*CONVERSION********************************************************/
// We want to convert all CAN traces from an Offline data set
// around the last Marker to CANoe asc and BLF format.
#ifndef _MSC_VER
static void sampleFunctionOfflineConversion() __attribute__((unused));
#endif
static void sampleFunctionOfflineConversion()
{
// We use the sample Offline Data Set that was downloaded
// with sampleFunctionDownload().
// Its up to you to ensure an existing file.
client->setOfflineData("..\\testoutdir\\BP2_Offline.zip");
BOOL ret = client->initialize();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to init offline." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
IRdbEventList* list = client->getEventList();
RdbEventList eventList(list);
if (eventList.size() == 0)
{
cout << "Empty event list" << endl;
client->release();
return;
}
uint64_t markerTimeStamp = 0;
// search last marker
for (int i = eventList.size() - 1; i >= 0; --i)
{
if (eventList[i].type == MARKER)
{
markerTimeStamp = eventList[i].timeStamp;
break;
}
}
if (markerTimeStamp == 0)
{
cout << "No marker found." << endl;
client->release();
return;
}
// Ensure the out directory exists
ret = mkdir("..\\testoutdir", 0x777);
if (ret != 0 && errno != EEXIST)
{
cout << "Failed to create output directory" << endl;
client->release();
return;
}
// Get a conversion set
IConversionSet* conversionSet = client->createNewConversionSet();
// The time span has to be 60s before and 60s after the marker
uint64_t startTime = markerTimeStamp - 60 * 1000000; // in usec
uint64_t endTime = markerTimeStamp + 60 * 1000000; // in usec
// If you want to convert more than one span,
// call this function several times
conversionSet->addTimeSpan(startTime, endTime);
// CAN #1 and CAN #2 are supposed to be written to one asc output file each.
// CAN #3 and CAN #4 are supposed to be written together in another asc file.
// All other CAN channels are supposed to be written together in one BLF file.
const IChannelList* channels = client->getLoggerChannels();
for (int i = 0; i < channels->getSize(); ++i)
{
ChannelType type = channels->getChannel(i)->getType();
if (type != CH_CAN)
continue;
// Note: channel indices are zero based
int index = channels->getChannel(i)->getIndex();
if (index == 0 || index == 1)
{
// CAN #1 and #2 in separate files
// -1 as fileId parameter creates a separate file for this channel
conversionSet->addChannel(type,
index,
CANOE,
-1,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
else if (index == 2 || index == 3)
{
// CAN #3 and #4 in the same file.
// fileId != -1 will write all channels with the same format and same
// file Id to the same output file (if procurable in accordance with
// the format specification.
conversionSet->addChannel(type,
index,
CANOE,
10,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
else
{
// All other CAN channels to one BLF file.
conversionSet->addChannel(type,
index,
BLF,
20,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
}
ret = client->convertData(conversionSet, "..\\testoutdir");
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to convert data." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
// free memory
client->release();
}
// We want to convert all A/I, D/I traces from an Offline TSL data set
// to XTMT
#ifndef _MSC_VER
static void sampleFunctionOfflineTSLConversion() __attribute__((unused));
#endif
static void sampleFunctionOfflineTSLConversion()
{
// We use the sample Offline Data Set that was downloaded
// with sampleFunctionTSLDownload().
string offlineDataSetPath = "..\\testoutdir\\TSL_Offline.zip";
// Its up to you to ensure an existing file.
client->setOfflineData(offlineDataSetPath.c_str());
BOOL ret = client->initialize();
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to init offline." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
// Ensure the out directory exists
#ifdef _MSC_VER
ret = _mkdir("..\\testoutdir");
#else
ret = mkdirPath("..\\testoutdir");
#endif
if (ret != 0 && errno != EEXIST)
{
cout << "Failed to create output directory" << endl;
client->release();
return;
}
// Get a conversion set
IConversionSet* conversionSet = client->createNewConversionSet();
//select all spans
conversionSet->addTimeSpan(0, 0xFFFFFFFFFFFFFFFFUL);
// All A/I, D/I channels are supposed to be written in separated XTMT files.
const IChannelList* channels = client->getLoggerChannels();
for (int i = 0; i < channels->getSize(); ++i)
{
ChannelType type = channels->getChannel(i)->getType();
if (type == CH_DIGITAL_IN || type == CH_ANALOG_IN)
{
// -1 as fileId parameter creates a separate file for this channel
// for tsl the offset and mainboardnumber fields are needed
conversionSet->addChannel(type,
channels->getChannel(i)->getIndex(),
XTMT,
-1,
channels->getChannel(i)->getOffset(),
channels->getChannel(i)->getMainboardNumber(),
channels->getChannel(i)->isMappingActive(),
}
}
ret = client->convertData(conversionSet, "..\\testoutdir");
if (ret == 0)
{
BPNGError err = client->getLastError();
cout << "Failed to convert data." << endl;
cout << "BPNGErrCode: " << err.code << ", " << err.msg << endl;
client->release();
return;
}
// free memory
client->release();
}
/********************************************************************HELPERS*******************************************************************/
static string getLocalDateString()
{
time_t timeObj;
time(&timeObj);
tm *pTime = localtime(&timeObj);
char buffer[100];
sprintf(buffer, "%d-%02d-%02d_%02d-%02d-%02d", pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday, pTime->tm_hour, pTime->tm_min, pTime->tm_sec);
return buffer;
}
static vector<string> readZipsFromDirectory(string dir)
{
vector<string> output;
DIR* directory = NULL;
directory = opendir(dir.c_str());
struct dirent* entry = readdir(directory);
string file;
while (entry != NULL)
{
file = entry->d_name;
if (file.find(".zip") != string::npos)
{
output.push_back(file);
}
entry = readdir(directory);
}
closedir(directory);
return output;
}