OptoControlSDK with .Net

I realize that Opto22 does not recommend new development with OptoControlSDK for FactoryFloor systems, but I recently found myself having to do just that. One area that was easy to fix but gave me a bit of trouble at first was the data type for information transmitted from the FactoryFloor controller to the PC.

The header files included in the SDK that provide access to the OptoCOM DLL’s have the controller response declared as a string. This may not have caused any issues in VB6, but it does in .Net. Strings in .Net are stored in 16 bit unicode. When .Net loads the incoming data into the string it interprets the 8 bit value as a Windows codepage 1252 character and converts that to the matching Unicode character. There are around 30 characters in the 8 bit extended ASCII (or any other 8 bit encoding) that do not have the same binary value as Unicode. So .Net will return the wrong value for that string character if it happens to be one that does not match.

So for example, if the FactoryFloor controller sends a byte with decimal value 154 .net will see this 8 bit data as representing the character “s” with caron in codepage 1252. The “s” with caron has a Unicode decimal value of 353. Which is way off!

The fix is simple (though it took me some time and I needed help from the msdn forums). Just declare the response on any function you plan to use as a byte array and your data will be preserved.

For example I changed:

Declare Function O22MdsSendReceSz Lib "OptoCom.DLL" (ByVal hControllerArg As Integer, ByVal pCommandArg As String, ByVal pResponseArg As String, _      ByVal cbRespMaxLen0Arg As Integer) As Short     
'
'C type: STDAPI_( O22_ERROR_CODE ) 
    'C params: ( O22HCONT   hControllerArg, LPCSTR    pCommandArg, LPSTR    pResponseArg, DWORD    cbRespMaxLen0Arg )

to:

Declare Function O22MdsSendReceSz Lib "OptoCom.DLL" (ByVal hControllerArg As Integer, ByVal pCommandArg As String, ByVal pResponseArg() As Byte, _      ByVal cbRespMaxLen0Arg As Integer) As Short     
'     
'C type: STDAPI_( O22_ERROR_CODE ) 
    'C params: ( O22HCONT   hControllerArg, LPCSTR    pCommandArg, LPSTR    pResponseArg, DWORD    cbRespMaxLen0Arg )

Not sure how many will need this info but thought I would toss it out there…

It appears the Forth commands “T Range Print” and “T Range Store” are the only commands that send/receive data as four binary bytes. All others appear to be ASCII. I suppose you could leave the response declared as a string if you do not plan to use “T Range Print” or “T Range Store”. In my case I left it declared as a byte array and converted as needed.

Chrismec,

Thanks a whole bunch for writing this up… exactly the sort of info we are looking for here… hard won tips that can save others a whole bunch of time.

Thanks.

Ben.

Here’s a little more info for would-be OptoControlSDK users… a link to the SDK download [click here].

Also, I should share that the first and primary problem developers run into when trying to use optocom.dll is an error that looks like the program can’t find optocom.dll. It’s a path/dependency issue.

While optocom.dll might be found by the exe in question, that dll has a few not-so-obvious dependencies (OptoErr.dll, OptoMwd.dll, and Optosnif.dll), as shown here in Microsoft’s Dependency Walker:


If you put ALL these dlls in the same folder as your exe, that usually does the trick.

Another point of confusion is how the program might behave differently (in terms of getting or not getting the error mention above) when run in the programming environment’s debugger vs. as a compiled exe. That’s because the compiler itself is the exe looking for the dll when you’re debugging (not the compiled program).

For example, say you’re using Visual Basic, and you right-click on wherever you start Visual Basic from, select Properties to see where the “Target” is on your hard drive. If you copy these opto dlls there (or set your windows path appropriately) your debugger should be happy too.

-OptoMary

Hi Chrismec,

Hats off to you - you got a lot further down the road than I managed to do. Like you, I need to do an upgrade to the app in VB6 or figure out how to do it in dotNet, and I’d far prefer the latter - I can’t even establish a connection to the controller.

Any chance you could share your converted Opto22 header files? I converted the .BAS files in the SDK to modules, but got nowhere.

Tia,

SamG

I will not be able to post the header files until next week (they are at work). But I would be happy to share the migration path I used. Visual Studio will take care of most of the conversion, but it can not do it all at once. You will have to convert to VS 2008 and then to 2010. I picked the example “OpenCont” from the OptoControlSDK. Open with VS express 2008 and it will convert the project for you. Save and then open with VS 2010, again it will take care of the conversion. There are a couple hiccups (cant remember all of them) that you must modify yourself, but from memory they are pretty straight forward. One that stands out is a declaration of type “Any”. This is no longer allowed in VB, I believe I set them as type integer. Hope this helps in some way. I will post the headers when I can get to them.

Hi Chris,

Don’t I feel silly. I had attempted to convert the .BAS files by hand, and ended up with a number of errors when I tried to compile. Just using the conversion wizard and produced the necessary modules without issue.

That and your tips on O22MdsSendReceSz conversion should get me on the way; I only need to poke a few values into the controller, and extract a few others. Again, thanks for the assist.

Cheers,

Sam