Skip to content
Snippets Groups Projects
Commit 9db582a3 authored by Tim Übelhör's avatar Tim Übelhör
Browse files

Lots of fixes

parent b3c94eb6
No related branches found
No related tags found
No related merge requests found
...@@ -11,14 +11,28 @@ ADIDatCli::AdiDatWriter::AdiDatWriter(String ^ path, IEnumerable<String^>^ chann ...@@ -11,14 +11,28 @@ ADIDatCli::AdiDatWriter::AdiDatWriter(String ^ path, IEnumerable<String^>^ chann
// Create the native vectors // Create the native vectors
std::vector<std::string> vecChannelNames; std::vector<std::string> vecChannelNames;
for each(auto name in channelNames) for each(auto name in channelNames)
{
if (name == nullptr)
{
vecChannelNames.push_back("no name");
}
else
{ {
vecChannelNames.push_back(marshal_as<std::string>(name)); vecChannelNames.push_back(marshal_as<std::string>(name));
} }
}
std::vector<std::string> vecChannelUnits; std::vector<std::string> vecChannelUnits;
for each(auto unit in channelUnits) for each(auto unit in channelUnits)
{
if (unit == nullptr)
{
vecChannelUnits.push_back("no unit");
}
else
{ {
vecChannelUnits.push_back(marshal_as<std::string>(unit)); vecChannelUnits.push_back(marshal_as<std::string>(unit));
} }
}
// Check conistency // Check conistency
if (vecChannelNames.size() != vecChannelUnits.size()) if (vecChannelNames.size() != vecChannelUnits.size())
{ {
...@@ -34,8 +48,19 @@ ADIDatCli::AdiDatWriter::~AdiDatWriter() ...@@ -34,8 +48,19 @@ ADIDatCli::AdiDatWriter::~AdiDatWriter()
delete(_writer); delete(_writer);
} }
void ADIDatCli::AdiDatWriter::AppendData(IEnumerable<IEnumerable<float>^>^ data) void ADIDatCli::AdiDatWriter::AddRecord(IEnumerable<IEnumerable<float>^>^ data)
{
std::vector<std::vector<float>> dataVector;
// Copy the data into c++ vecors
for each(auto channel in data)
{ {
throw gcnew System::NotImplementedException(); std::vector<float> samples;
for each(float sample in channel)
{
samples.push_back(sample);
}
dataVector.push_back(samples);
}
_writer->AddRecord(dataVector);
} }
...@@ -15,7 +15,10 @@ namespace ADIDatCli ...@@ -15,7 +15,10 @@ namespace ADIDatCli
/// Creates the file in the path. Also set up the /// Creates the file in the path. Also set up the
AdiDatWriter(String^ path, IEnumerable<String^>^ channelNames, IEnumerable<String^>^ channelUnits, double secondsPerSample); AdiDatWriter(String^ path, IEnumerable<String^>^ channelNames, IEnumerable<String^>^ channelUnits, double secondsPerSample);
~AdiDatWriter(); ~AdiDatWriter();
void AppendData( IEnumerable<IEnumerable<float>^>^ data); /// Adds a new record to the file
void AddRecord(
IEnumerable<IEnumerable<float>^>^ data // An enumerable of channel data. Each inner enumerable must have the same size.
);
private: private:
// The native class does the actual work // The native class does the actual work
NativeWriter* _writer; NativeWriter* _writer;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion> <VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{080112AF-3D1C-4269-BA88-3AD5E0C5F587}</ProjectGuid> <ProjectGuid>{080112AF-3D1C-4269-BA88-3AD5E0C5F587}</ProjectGuid>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword> <Keyword>ManagedCProj</Keyword>
<RootNamespace>AdidatCLI</RootNamespace> <RootNamespace>AdidatCLI</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
......
#include "stdafx.h" #include "stdafx.h"
#include "NativeWriter.h" #include "NativeWriter.h"
#include <ctime> #include <ctime>
#include "ADIDatCAPI.h"
NativeWriter::NativeWriter(std::string path, std::vector<std::string> channelNames, std::vector<std::string> channelUnits, double secondsPerSample) NativeWriter::NativeWriter(std::string path, std::vector<std::string> channelNames, std::vector<std::string> channelUnits, double secondsPerSample) :
_fileHandle(0), _writerHandle(0)
{ {
_channelCount = channelNames.size(); _channelCount = channelNames.size();
if (_channelCount > 32)
{
throw new std::invalid_argument("Only a maximum of 32 channels is supported by the LabView data export.");
}
// Create the file // Create the file
_path = std::wstring(path.length(), L'\0'); std::wstring wPath(path.begin(), path.end());
size_t pathCharsConverted = 0; checkResult(ADI_CreateFile(wPath.c_str(), &_fileHandle));
mbstowcs_s(&pathCharsConverted, &_path[0], path.length(), path.c_str(), _path.length());
ADI_FileHandle fileHandle(0);
checkResult(ADI_CreateFile(_path.c_str(), &fileHandle));
// Start writing // Start writing
ADI_WriterHandle writerHandle(0); checkResult(ADI_CreateWriter(_fileHandle, &_writerHandle));
checkResult(ADI_CreateWriter(fileHandle, &writerHandle));
// Set the channels names and indo // Set the channels names and indo
for (int channel = 0; channel < static_cast<int>(channelNames.size()); channel++) for (size_t channel = 0; channel < channelNames.size(); channel++)
{ {
std::wstring wName(channelNames[channel].size(), L'\0'); std::wstring wName(channelNames[channel].begin(), channelNames[channel].end());
size_t channelCharsConverted = 0; checkResult(ADI_SetChannelName(_fileHandle, static_cast<long>(channel), wName.c_str()));
mbstowcs_s(&channelCharsConverted, &wName[0], channelNames[channel].length(), channelNames[channel].c_str(), wName.length()); std::wstring wUnit(channelUnits[channel].begin(), channelUnits[channel].end());
ADI_SetChannelName(fileHandle, channel, wName.c_str()); checkResult(ADI_SetChannelInfo(_writerHandle, static_cast<long>(channel), true, secondsPerSample, wUnit.c_str(), NULL));
std::wstring wUnit(channelUnits[channel].size(), L'\0');
size_t unitCharsConverted = 0;
mbstowcs_s(&unitCharsConverted, &wUnit[0], channelUnits[channel].length(), channelUnits[channel].c_str(), wUnit.length());
checkResult(ADI_SetChannelInfo(writerHandle, channel, true, secondsPerSample, wUnit.c_str(), NULL));
} }
// Commit the changes
checkResult(ADI_CommitFile(writerHandle, 0));
checkResult(ADI_CloseWriter(&writerHandle));
checkResult(ADI_CloseFile(&fileHandle));
} }
NativeWriter::~NativeWriter() NativeWriter::~NativeWriter()
{ {
// Close the file
checkResult(ADI_CloseWriter(&_writerHandle));
checkResult(ADI_CloseFile(&_fileHandle));
} }
void NativeWriter::checkResult(int code) void NativeWriter::checkResult(int code)
...@@ -57,34 +52,22 @@ void NativeWriter::checkResult(int code) ...@@ -57,34 +52,22 @@ void NativeWriter::checkResult(int code)
// If it is kResultsuccess we are all fine :) // If it is kResultsuccess we are all fine :)
} }
void NativeWriter::AppendData(std::vector<std::vector<float>> data) void NativeWriter::AddRecord(std::vector<std::vector<float>> data)
{
// Check if the data is consistent
if (data.empty())
{ {
return; // Determine how many samples we can add
} size_t samplesToAdd = SIZE_MAX;
size_t samplesToAdd = data[0].size();
for (auto channel : data) for (auto channel : data)
{ {
if (channel.size() != samplesToAdd) if (channel.size() < samplesToAdd)
{ {
throw new std::invalid_argument("The channels do no contain an equal number of samples."); samplesToAdd = channel.size();
} }
} }
// Open the file
ADI_FileHandle fileHandle(0);
checkResult(ADI_OpenFile(_path.c_str(), &fileHandle, ADIFileOpenMode::kOpenFileForReadAndWrite));
// Create the write handler
ADI_WriterHandle writerHandle(0);
checkResult(ADI_CreateWriter(fileHandle, &writerHandle));
// Start a new record // Start a new record
time_t currentTime; time_t currentTime;
time(&currentTime); time(&currentTime);
checkResult(ADI_StartRecord(writerHandle, currentTime, 0, 0)); checkResult(ADI_StartRecord(_writerHandle, currentTime, 0, 0));
// Add chunks of samples parallel for all channels
// Add the data to the record // Add the data to the record
size_t samplesAdded = 0; size_t samplesAdded = 0;
while (samplesAdded < samplesToAdd) while (samplesAdded < samplesToAdd)
...@@ -95,18 +78,18 @@ void NativeWriter::AppendData(std::vector<std::vector<float>> data) ...@@ -95,18 +78,18 @@ void NativeWriter::AppendData(std::vector<std::vector<float>> data)
{ {
chunkSize = OPTIMAL_CHUNK_SIZE; chunkSize = OPTIMAL_CHUNK_SIZE;
} }
long samplesAdded = 0; for (size_t channel = 0; channel < data.size(); channel++)
for (int i = 0; i < static_cast<int>(data.size()); i++)
{ {
// Add the data directly from the matrix // Write it
checkResult(ADI_AddChannelSamples(writerHandle, i, &data[i][samplesAdded], chunkSize, &samplesAdded)); long writtenSamples = 0;
checkResult(ADI_AddChannelSamples(_writerHandle, static_cast<long>(channel), data[channel].data() + samplesAdded, chunkSize, &writtenSamples));
// Weird but once the chunk is written to the first channel, all other channels will retunr writtenSamples = 0 :(
samplesAdded += writtenSamples;
} }
} }
// Close the record // Close the record
checkResult(ADI_FinishRecord(writerHandle)); checkResult(ADI_FinishRecord(_writerHandle));
// Commit the changes // Commit the changes
checkResult(ADI_CommitFile(writerHandle, 0)); checkResult(ADI_CommitFile(_writerHandle, 0));
checkResult(ADI_CloseWriter(&writerHandle));
checkResult(ADI_CloseFile(&fileHandle));
} }
\ No newline at end of file
#pragma once #pragma once
#include <string> #include <string>
#include <vector> #include <vector>
#include "ADIDatCAPI.h"
// For best display in labchart medium size chunks
// For best display in labchart const long OPTIMAL_CHUNK_SIZE = 1024;
const size_t OPTIMAL_CHUNK_SIZE = 16000;
// The maximal count of characters when getting the error message // The maximal count of characters when getting the error message
const size_t MAX_ERROR_MESSAGE_SIZE = 1024; const size_t MAX_ERROR_MESSAGE_SIZE = 1024;
class NativeWriter class NativeWriter
{ {
private: private:
// Where we created the file // Handles for the file and writer
std::wstring _path; // Must stay open otherwise writing fails ?!
ADI_FileHandle _fileHandle;
ADI_WriterHandle _writerHandle;
// Rememebr how many channels we use // Rememebr how many channels we use
size_t _channelCount; size_t _channelCount;
/// Throws an exception if any error occured /// Throws an exception if any error occured
void checkResult(int code); void checkResult(int code);
public: public:
NativeWriter(std::string path, std::vector<std::string> channelNames, std::vector<std::string> channelUnits, double secondsPerSample); NativeWriter(std::string path, std::vector<std::string> channelNames, std::vector<std::string> channelUnits, double secondsPerSample);
void AppendData(std::vector<std::vector<float>> data); void AddRecord(std::vector<std::vector<float>> data);
~NativeWriter(); ~NativeWriter();
}; };
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment