Sample code for using IChannel.GetDBAddress()

  • Developers
  • Sample code for using IChannel.GetDBAddress()
Denis Desourdy

Posted on 30.07.2018 21:14

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

Denis Desourdy

Posted on 30.07.2018 21:16

I forgot to mention that I need to read those samples at 100 Hz.

Thanks!

Denis

Eva Kalšek
Customer Support Engineer
Posted on 01.08.2018 15:37

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



Denis Desourdy

Posted on 01.08.2018 16:00

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

DEWESoft Support
Technical support
Posted on 02.08.2018 10:10

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!


Denis Desourdy

Posted on 03.08.2018 18:55

Is the pointer returned from GetDBAddress() usable in a .Net plugin? Or do I have to write my plugin in C++/Win32?


Thanks!

Denis Desourdy

Posted on 03.08.2018 21:57

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

DEWESoft Support
Technical support
Posted on 06.08.2018 13:09

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).

Denis Desourdy

Posted on 06.08.2018 20:58

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:
DEWESoft Support
Technical support
Posted on 07.08.2018 13:49

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

Denis Desourdy

Posted on 07.08.2018 16:21

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.

Login to reply to this topic. If you don't have account yet, you can signup for free account .