- Posts: 34
- Thank you received: 1
Online Forums
Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.
Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.
Do not use the Contact page for technical issues.
Writing ByteString
I solved my problem with the following cast:
variant_t vArray;
vArray.ChangeType(VT_ARRAY | VT_UI1, &output);
Please Log in or Create an account to join the conversation.
You can read the DataType attribute of the node to obtain its data type. What you get a back is a node ID of the data type; this need to be compared with the "standard" node IDS for various types, as defined in the OPC UA specification. An example of reading the data type attibute (unfortunately for .NET only) is here: opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...%20of%20a%20single%20node.html .
I do not quite understand the part about ChangeType. First of all, I think that changing type to VT_CARRAY or VT_SAFEARRAY is pointless, they are special values not meant for user code. And, VT_ARRAY is a bit that needs to OR-ed with some other scalar VT_xxxx in order to make sense. Second, in your two-line example, the contents of vString is an empty variant (VT_EMPTY), so no wonder that its type cannot be changed. You can use ChangeType on variants for e.g. converting numbers to string or converting between integer types (if the value fits into the target range) etc., but do not expect it to convert between strings and arrays and similar things.
Regards
Please Log in or Create an account to join the conversation.
void WriteValue::ByteString() {
CoInitializeEx(NULL, COINIT_MULTITHREADED);
_bstr_t serverParam(_T("opc.tcp://localhost:4840"));
_bstr_t valueParam(_T("ns=2;s=VARIABLE"));
_EasyUAClientPtr ClientPtr(__uuidof(EasyUAClient));
// Obtain attribute data. By default, the Value attribute of a node will be read.
try{
// Insert Content into the array: saByteArray
CString writeValue (_T("TEST"));
CComSafeArray <BYTE> saByteArray(256);
int nRealLength = writeValue.GetLength();
saByteArray.Resize(nRealLength);
for(int i = 0; i < min(nRealLength, 256); i++) {
saByteArray.SetAt(i, writeValue.GetAt(i));
}
CComVariant varArrayWrapper (saByteArray);
_UAWriteValueArgumentsPtr WriteValueArguments1Ptr(_uuidof(UAWriteValueArguments));
WriteValueArguments1Ptr->EndpointDescriptor->UrlString = serverParam;
WriteValueArguments1Ptr->NodeDescriptor->NodeId->ExpandedText = valueParam;
WriteValueArguments1Ptr->Value = varArrayWrapper;
CComSafeArray<VARIANT> arguments(1);
arguments.SetAt(0, _variant_t((IDispatch*)WriteValueArguments1Ptr));
// Obtain values. By default, the Value attributes of the nodes will be Write.
LPSAFEARRAY pArguments = arguments.Detach();
CComSafeArray<VARIANT> results;
results.Attach(ClientPtr->WriteMultipleValues(&pArguments));
arguments.Attach(pArguments);
// Display results
for (int i = results.GetLowerBound(); i <= results.GetUpperBound(); i++) {
_UAWriteResultPtr ResultPtr = results[i];
if (ResultPtr->Succeeded)
_tprintf(_T("Result %d success\n"), i);
else {
CString msg;
msg.Format(_T("Result %d: %s\n"), i, CW2T(ResultPtr->Exception->GetBaseException()->Message));
AfxMessageBox(msg);
}
}
SAFEARRAY* pResults = results.Detach();
pArguments = arguments.Detach();
SafeArrayDestroyData(pArguments);
SafeArrayDestroyData(pResults);
SafeArrayDestroy(pArguments);
SafeArrayDestroy(pResults);
arguments.Destroy();
results.Destroy();
pArguments = NULL;
pResults = NULL;
}
catch (const _com_error& e){
CString desc( (LPCTSTR) e.Description());
CString errorMessage(e.ErrorMessage());
}
// Release all interface pointers BEFORE calling CoUninitialize()
CoUninitialize();
}
Now I have some problem reading the variables…
Casting the variable to VT_BSTR, VT_SAFEARRAY, VT_CARRAY or VT_ARRAY always fails.
_variant_t vString;
vString.ChangeType(VT_BSTR, &output);
Thank you!
Best regards,
Federica
Please Log in or Create an account to join the conversation.
void WriteValue::ByteString()
{
// Initialize the COM library
CoInitializeEx(NULL, COINIT_MULTITHREADED);
{
// Instantiate the client object
_EasyUAClientPtr ClientPtr(__uuidof(EasyUAClient));
// Prepare the value to be written
CComSafeArray<BYTE> array(5);
array.SetAt(0, 11);
array.SetAt(1, 22);
array.SetAt(2, 33);
array.SetAt(3, 44);
array.SetAt(4, 55);
const CComVariant value(array);
// Perform the operation
ClientPtr->WriteValue(
L"http://opcua.demo-this.com:51211/UA/SampleServer", // or "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
L"nsu=http://test.org/UA/Data/;i=10230",
value);
}
// Release all interface pointers BEFORE calling CoUninitialize()
CoUninitialize();
}
Please Log in or Create an account to join the conversation.
Please Log in or Create an account to join the conversation.
what type of value are you passing to be written? Are you passing in a string? If so, that would be wrong. It should be an array of bytes.
Best regards
Please Log in or Create an account to join the conversation.
I'm using your SDK (QuickOPC 2018.1, in particular OPC-UA under COM with C++) since last year.
We usually write data through WriteValue method.
I'm connected to a Fanuc OPC-UA server and I need to write a ByteString tag.
How can I do this?
I continue to receive casting error: "Cast da 'System.String' a 'System.Byte[]' non valido."
Do you know a way for detecting the type of the tag in order to handle different data type in my source code?
Thank you
Best regards,
Federica
Please Log in or Create an account to join the conversation.