I ended up generating some specific structs for each type of variable that I needed, because to generate the HDF5 file it was necessary to allocate a specific space for each type, so I chose to make a generic class (a helper) and from there instantiate the flow I needed based on the data type I read:
public class OpcToHdfHelper
{
public dynamic opcToRun;
public void SetTypeAndWriteHdf(string bvtag, IOpcUaSession uaSession, Opc.Ua.ReadRawModifiedDetails readDetails,
Opc.Ua.NodeId sourceId, H5GroupId group)
{
var data = HistoryReadEnu(uaSession, readDetails, sourceId);
int i = 0;
var p = data.ToArray()[i].Value;
i = 1;
while (p == null && i < 10)
{
p = data.ToArray()[i].Value;
i++;
} ;
if (p.GetType() == typeof(int))
{
opcToRun = new OpcInt32(data, bvtag, group);
}
if (p.GetType() == typeof(Int64))
{
opcToRun = new OpcInt64();
}
if (p.GetType() == typeof(float))
{
opcToRun = new OpcFloat();
}
if (p.GetType() == typeof(double))
{
opcToRun = new OpcDouble(data, bvtag, group);
}
if(p.GetType() == typeof(string))
{
opcToRun = new OpcString(data, bvtag, group);
}
if(p.GetType() == typeof(bool))
{
opcToRun = new OpcBoolean(data, bvtag, group);
}
}
Edit to clarify why different structs were needed:
struct OpcString
{
public Int64 dt;
public Int64 qlt;
public IntPtr vl;
public OpcString(Int64 timestamp = 0, Int64 quality = 0, string value="0")
{
dt = timestamp;
qlt = quality;
vl = new IntPtr();
vl = ConvertTo(value);
}
IntPtr ConvertTo(string s)
{
var x = Marshal.StringToHGlobalAnsi(s);
return x;
}
public OpcString(IEnumerable<Opc.Ua.DataValue> dados, string bvTag, H5GroupId groupId)
{
dt = 0;
qlt = 0;
vl = new IntPtr();
GenerateHdf5(dados, bvTag, groupId);
}
public void GenerateHdf5(IEnumerable<Opc.Ua.DataValue> dados, string bvTag, H5GroupId groupId)
{
long[] dims = new long[1];
dims[0] = dados.Count<Opc.Ua.DataValue>();
H5DataSpaceId dataSpaceId = H5S.create_simple(1, dims);
string auxLen = "";
foreach(Opc.Ua.DataValue vc in dados)
{
if (vc.Value != null) {
if(vc.Value.ToString().Length > auxLen.Length)
{
auxLen = vc.Value.ToString();
}
}
}
H5DataTypeId stringTypeId = H5T.create(H5T.CreateClass.STRING, -1);
OpcString opcHelper = new OpcString();
H5DataTypeId dataTypeId = H5T.create(H5T.CreateClass.COMPOUND, Marshal.SizeOf(opcHelper));
H5T.insert(dataTypeId, "Timestamp", 0, new H5DataTypeId(H5T.H5Type.NATIVE_LONG));
H5T.insert(dataTypeId, "Quality", 8, new H5DataTypeId(H5T.H5Type.NATIVE_LONG));
H5T.insert(dataTypeId, "Value", 16, stringTypeId);
var list = new List<OpcString>();
foreach (Opc.Ua.DataValue dv in dados)
{
string t = "NullValue";
if(dv.Value != null)
{
t = dv.Value.ToString();
}
OpcString aux = new OpcString((Int64)dv.SourceTimestamp.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds, dv.StatusCode.Code, t);
list.Add(aux);
}
H5DataSetId bvDset = H5D.create(groupId, bvTag, dataTypeId, dataSpaceId);
H5D.write(bvDset, dataTypeId, new H5Array<OpcString>(list.ToArray()));
H5D.close(bvDset);
H5S.close(dataSpaceId);
}
}
struct OpcBoolean
{
public Int64 dt;
public Int64 qlt;
public bool vl;
public OpcBoolean(Int64 timestamp = 0, Int64 quality = 0, bool value = false)
{
dt = timestamp;
qlt = quality;
vl = value;
}
public OpcBoolean(IEnumerable<Opc.Ua.DataValue> dados, string bvTag, H5GroupId groupId)
{
dt = 0;
qlt = 0;
vl = false;
GenerateHdf5(dados, bvTag, groupId);
}
public void GenerateHdf5(IEnumerable<Opc.Ua.DataValue> dados, string bvTag, H5GroupId groupId)
{
long[] dims = new long[1];
dims[0] = dados.Count<Opc.Ua.DataValue>();
H5DataSpaceId dataSpaceId = H5S.create_simple(1, dims);
OpcBoolean opcHelper = new OpcBoolean();
H5DataTypeId dataTypeId = H5T.create(H5T.CreateClass.COMPOUND, Marshal.SizeOf(opcHelper));
H5T.insert(dataTypeId, "Timestamp", 0, new H5DataTypeId(H5T.H5Type.NATIVE_LONG));
H5T.insert(dataTypeId, "Quality", 8, new H5DataTypeId(H5T.H5Type.NATIVE_LONG));
H5T.insert(dataTypeId, "Value", 16, new H5DataTypeId(H5T.H5Type.NATIVE_HBOOL));
var list = new List<OpcBoolean>();
foreach (Opc.Ua.DataValue dv in dados)
{
OpcBoolean aux = new OpcBoolean((Int64)dv.SourceTimestamp.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds, dv.StatusCode.Code, Convert.ToBoolean(dv.Value));
list.Add(aux);
}
H5DataSetId bvDset = H5D.create(groupId, bvTag, dataTypeId, dataSpaceId);
H5D.write(bvDset, dataTypeId, new H5Array<OpcBoolean>(list.ToArray()));
H5D.close(bvDset);
H5S.close(dataSpaceId);
}
}