Sample code for using IChannel.GetDBAddress()
Hi,
I need to read the last value of let say 200 channels and return them to a client via a socket.
Is it possible to have a code sample that use IChannel.GetDBAddress() to do this?
Thanks!
Denis Desourdy
I forgot to mention that I need to read those samples at 100 Hz.
Thanks!
Denis
Customer Support Engineer
Hi Denis,
are you writing a Dewesoft plugin? It is only possible to access the data via IChannel.GetDBAddress() in custom plugins that run in the same address space as the Dewesoft application. If not you will have to use other methods (e.g. Read data via IChannelConnection - GetDataValues or GetDataBlocks, Read data from direct buffer - DBValues, Read block from direct buffer - GetScaledDataEx/GetUnscaledDataEx). You can also find examples on our web page on the following link https://download.dewesoft.com/list/2/3. Given that the sample rate is very low, all the methods should be acceptable.
Regards
Hi Eva,
Yes, I am writing a Dewesoft plugin. I would like to know how to read the last sample for a set of channels with GetDBAddress.
I already know how to use DBValues but as I read in the DCOM documentation, this is slow.
Just a small sample in any language would be very useful.
Best regards!
Denis
Technical support
Hi Denis,
GetDBAddress() only returns the pointer to the beginning of DBAvalues array, so you can access it the same as DBValues, you just have to cast it to the right type.
Here is an example from our developer:
int DewesoftBridge::getLastValueIndex(IChannelPtr channel)
{
return (channel->DBPos - 1 + channel->DBBufSize) % channel->DBBufSize;
}
...
if (channel->DBDataSize > 0)
{
int lastValueIndex = getLastValueIndex(channel);
float* addr = (float*) channel ->GetDBAddress64()
float value = addr[lastValueIndex];
}
Regards!
Is the pointer returned from GetDBAddress() usable in a .Net plugin? Or do I have to write my plugin in C++/Win32?
Thanks!
Hi,
I tried your sample with the C++ sample plugin but I always get a 0 value with GetDBAddress(). When I use DBValues the value is good. Do you know what could cause this?
int lastIndex = getLastValueIndex(pChannel);
float* addr = (float*)pChannel->GetDBAddress();
float theValue = addr[lastIndex]; // always 0
float theValue2 = pChannel->DBValues[lastIndex]; // value is good
Thanks!
Denis
Technical support
Hi Denis,
Looks like the channel type is not Single but something else. If you access the value via DBValues, it automatically turns into float. But if you access the value via pointer, you have to cast it to the right type.
e.g. if the channel type is Integer:
int* addr = (int*)channel->GetDBAddress();
int valuePtr = addr[lastValueIndex];
With C# you can access the pointer with "unsafe" block. Otherwise you can use IntPtr class (https://docs.microsoft.com/en-us/dotnet/api/system.intptr?view=netframework-4.7.1) or Marshall class (https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal?view=netframework-4.7.1).
Hi,
The channel is indeed a SmallInt. How do you make the conversion from a 2 bytes integer value to a 4 bytes float? Could you provide an algorithm for doing it?
I have attached a screenshot of DEWESoft 7.1 Event Viewer.
Thanks!
Denis
Attached files:
Technical support
Hi Denis,
You can use formula ActualValue = Scale * Value * Offset
There is also an IChannel method float ScaleValue(float unscaled) which does exactly this.
Regards
Hi,
Do you mean : ActualValue = Scale * Value + Offset ?
Anyway I tried both and it does not work.
IChannel::ScaleValue() works but I am trying to remove as much DCOM calls as is possible.