Skip to content

Commit

Permalink
OPC DA: Parse OPC data item with lower overhead
Browse files Browse the repository at this point in the history
Upstream WS2LPCTSTR is buggy because on the initial 64bit port I
can write but cannot read the OPC data values until I fix it.

This local WS2LPCTSTR method is safe as it will always allocate the
exact ammount of space needed for the conversion, resulting parsing
OPC data item faster.
  • Loading branch information
kumajaya committed Mar 4, 2024
1 parent 2814412 commit d68f348
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 25 deletions.
36 changes: 11 additions & 25 deletions src/com/opc/opcconnectionimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ bool COpcConnectionImpl::connect(const char* paGroupName){

mOpcServer = mOpcHost->connectDAServer(COPCHost::LPCSTR2WS(mServerName));
} catch (OPCException &e){
DEVLOG_ERROR("connect OPC server failed:%s[%s]\n",COPCHost::WS2LPCTSTR(e.reasonString()),paGroupName);
DEVLOG_ERROR("connect OPC server failed:%s[%s]\n",WS2LPCTSTR(e.reasonString()),paGroupName);
return false;
}
DEVLOG_INFO("successfully connect OPC server in COpcConnectionImpl[%s]\n",paGroupName);
Expand Down Expand Up @@ -109,9 +109,9 @@ void COpcConnectionImpl::addItemList(const char* paGroupName, std::vector<std::s
}
catch (OPCException &e)
{
DEVLOG_ERROR("addItem failed with exception:%s[%s:%s]\n", COPCHost::WS2LPCTSTR(e.reasonString()),
DEVLOG_ERROR("addItem failed with exception:%s[%s:%s]\n", WS2LPCTSTR(e.reasonString()),
groupName,paReadItems[i].c_str());
if(strcmp(COPCHost::WS2LPCTSTR(e.reasonString()),"Failed to add item") != 0){
if(strcmp(WS2LPCTSTR(e.reasonString()),"Failed to add item") != 0){
//pa_pNewItem->setIsActive(false);
this->disconnect();
mConnected = false;
Expand Down Expand Up @@ -201,12 +201,12 @@ int COpcConnectionImpl::sendItemData(const char *paGroupName, const char *paItem
if(it != mOpcItems.end()){
lItems = it->second;
for(size_t i = 0; i < lItems.size(); i++){
if(0 == strcmp(COPCHost::WS2LPCTSTR(lItems[i]->getName()), paItemName)){
if(0 == strcmp(WS2LPCTSTR(lItems[i]->getName()), paItemName)){
try{
lItems[i]->writeSync(paVar);
}
catch (OPCException &e){
DEVLOG_ERROR("opcitem writesync failed with exception:%s[%s:%s]\n", COPCHost::WS2LPCTSTR(e.reasonString()), writeGrpName, paItemName);
DEVLOG_ERROR("opcitem writesync failed with exception:%s[%s:%s]\n", WS2LPCTSTR(e.reasonString()), writeGrpName, paItemName);
rtn = -1;
break;
}
Expand All @@ -226,31 +226,17 @@ int COpcConnectionImpl::sendItemData(const char *paGroupName, const char *paItem

void COpcConnectionImpl::OnDataChange(COPCGroup & paGroup, COPCItemDataMap & paChanges){
TItemDataList itemList;
for(POSITION pos = paChanges.GetStartPosition(); pos != nullptr;){
POSITION pos = paChanges.GetStartPosition();
while(pos){
OPCHANDLE handle = paChanges.GetKeyAt(pos);
OPCItemData *data = paChanges.GetNextValue(pos);
if (data) {
const COPCItem *item = data->item();
if (item) {
itemList.push_back(new SOpcItemData(COPCHost::WS2LPCTSTR(item->getName()), (Variant) data->vDataValue));
}
itemList.push_back(new SOpcItemData(WS2LPCTSTR(item->getName()), (Variant) data->vDataValue));
}
}

const wchar_t *input = paGroup.getName().c_str();
// Count required buffer size (plus one for null-terminator).
size_t size = (wcslen(input) + 1) * sizeof(wchar_t);
char *buffer = new char[size];
#ifdef __STDC_LIB_EXT1__
// wcstombs_s is only guaranteed to be available if __STDC_LIB_EXT1__ is defined
size_t convertedSize;
std::wcstombs_s(&convertedSize, buffer, size, input, size);
#else
std::wcstombs(buffer, input, size);
#endif
const char *c_groupName = (const char*) buffer;
// Free allocated memory:
delete buffer;
const char *c_groupName = WS2LPCTSTR(paGroup.getName());

int position = 0;
const char * subStrRead = strstr(c_groupName, "_read");
Expand Down Expand Up @@ -287,7 +273,7 @@ COPCGroup* COpcConnectionImpl::getOpcGroup(const char* paGroupName, bool paIfRea
(*it)->mReadGroupAdded = true;
} catch (OPCException &e){
// TODO
DEVLOG_ERROR("exception in make opc group[%s]:%s\n",groupName,COPCHost::WS2LPCTSTR(e.reasonString()));
DEVLOG_ERROR("exception in make opc group[%s]:%s\n",groupName,WS2LPCTSTR(e.reasonString()));
(*it)->mOpcGroupRead = nullptr;
retGroup = nullptr;
}
Expand All @@ -305,7 +291,7 @@ COPCGroup* COpcConnectionImpl::getOpcGroup(const char* paGroupName, bool paIfRea
(*it)->mWriteGroupAdded = true;
} catch (OPCException &e){
// TODO
DEVLOG_ERROR("exception in make opc group[%s]:%s\n",groupName,COPCHost::WS2LPCTSTR(e.reasonString()));
DEVLOG_ERROR("exception in make opc group[%s]:%s\n",groupName,WS2LPCTSTR(e.reasonString()));
(*it)->mOpcGroupWrite = nullptr;
(*it)->mOpcGroupWrite = nullptr;
retGroup = nullptr;
Expand Down
18 changes: 18 additions & 0 deletions src/com/opc/opcconnectionimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,24 @@ class COpcConnectionImpl : public IAsyncDataCallback{

private:

static const char* WS2LPCTSTR(const std::wstring &wstr) {
const wchar_t *input = wstr.c_str();
// Count required buffer size (plus one for null-terminator).
size_t size = (wcslen(input) + 1) * sizeof(wchar_t);
char *buffer = new char[size];
#ifdef __STDC_LIB_EXT1__
// wcstombs_s is only guaranteed to be available if __STDC_LIB_EXT1__ is defined
size_t convertedSize;
std::wcstombs_s(&convertedSize, buffer, size, input, size);
#else
std::wcstombs(buffer, input, size);
#endif
const char *ret = (const char*) buffer;
// Free allocated memory:
delete buffer;
return ret;
}

COPCGroup* getOpcGroup(const char* paGroupName, bool paIfRead);
void clearGroup();

Expand Down

0 comments on commit d68f348

Please sign in to comment.