Commit d2bb7069 authored by Claes Sjofors's avatar Claes Sjofors

Conflicts merged

parents 62e4358f f7647de3
/*
* Proview $Id: opc_server.cpp,v 1.23 2008-10-31 12:51:29 claes Exp $
* Proview $Id: opc_server.cpp,v 1.23 2008-10-31 12:51:29 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <map>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <pthread.h>
#include <float.h>
#include "pwr.h"
#include "pwr_version.h"
#include "pwr_baseclasses.h"
#include "pwr_opcclasses.h"
#include "co_cdh.h"
#include "co_time.h"
#include "co_cnv.h"
#include "rt_gdh.h"
#include "opc_utl.h"
#include "opc_soap_H.h"
#include "Service.nsmap"
#include "rt_errh.h"
#include "rt_qcom.h"
#include "rt_ini_event.h"
#include "rt_aproc.h"
#include "rt_pwr_msg.h"
#include "rt_qcom_msg.h"
using namespace std;
typedef struct {
int address;
int access;
} opc_sClientAccess;
class opcsrv_sub {
public:
void *p;
int size;
opc_eDataType opc_type;
pwr_eType pwr_type;
pwr_tSubid subid;
float deadband;
std::string client_handle;
pwr_tInt64 old_value;
};
class opcsrv_client {
public:
opcsrv_client() : m_last_time(pwr_cNTime) {}
int access;
pwr_tTime m_last_time;
map< std::string, vector<opcsrv_sub> > m_sublist;
bool m_multi_threaded;
};
typedef map< std::string, vector<opcsrv_sub> >::iterator sublist_iterator;
typedef map< int, opcsrv_client>::iterator client_iterator;
class opc_server {
public:
opc_server() : m_client_access_cnt(0), m_grant_all(true), m_client(0),
qid(qcom_cNQid) {}
map< int, opcsrv_client> m_clientlist;
pwr_tTime m_start_time;
pwr_sClass_Opc_ServerConfig *m_config;
opc_sClientAccess m_client_access[20];
int m_client_access_cnt;
int m_current_access;
bool m_grant_all;
opcsrv_client *m_client;
qcom_sQid qid;
opcsrv_client *find_client( int sid);
opcsrv_client *new_client( int sid);
int fault( struct soap *soap, int code);
int get_access( int sid);
};
static opc_server *opcsrv;
static void *opcsrv_cyclic( void *arg);
static void *opcsrv_process_request( void *soap);
static int
opcsrv_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror)
{ *soap_faultcode(soap) = faultcode;
if (faultsubcode)
*soap_faultsubcode(soap) = faultsubcode;
*soap_faultstring(soap) = faultstring;
if (faultdetail && *faultdetail)
{ register const char **s = soap_faultdetail(soap);
if (s)
*s = faultdetail;
}
return soap->error = soaperror;
}
static int
opcsrv_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail)
{ char *r = NULL, *s = NULL, *t = NULL;
if (faultsubcode)
r = soap_strdup(soap, faultsubcode);
if (faultstring)
s = soap_strdup(soap, faultstring);
if (faultdetail)
t = soap_strdup(soap, faultdetail);
return opcsrv_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
}
int opc_server::fault( struct soap *soap, int code)
{
return opcsrv_fault( soap, opc_resultcode_to_string( code), 0, opc_resultcode_to_text( code), 0);
}
opcsrv_client *opc_server::find_client( int sid)
{
client_iterator it = opcsrv->m_clientlist.find( sid);
if ( it == opcsrv->m_clientlist.end())
return 0;
else {
time_GetTime( &it->second.m_last_time);
return &it->second;
}
}
opcsrv_client *opc_server::new_client( int sid)
{
opcsrv_client client;
m_clientlist[sid] = client;
m_clientlist[sid].access = get_access( sid);
m_clientlist[sid].m_multi_threaded = false;
time_GetTime( &m_clientlist[sid].m_last_time);
//fprintf( stderr, "New client IP=%d.%d.%d.%d\n",
// (sid>>24)&0xFF,(sid>>16)&0xFF,(sid>>8)&0xFF,sid&0xFF);
m_config->ClientCnt++;
return &m_clientlist[sid];
}
int main()
{
struct soap soap;
int m,s; // Master and slave sockets
pwr_tStatus sts;
pwr_tOid config_oid;
qcom_sQid qini;
qcom_sQattr qAttr;
qcom_sQid qid = qcom_cNQid;
int restarts = 10;
sts = gdh_Init("opc_server");
if ( EVEN(sts)) {
exit(sts);
}
errh_Init("opc_server", errh_eAnix_opc_server);
errh_SetStatus( PWR__SRVSTARTUP);
if (!qcom_Init(&sts, 0, "opc_server")) {
errh_Fatal("qcom_Init, %m", sts);
errh_SetStatus( PWR__SRVTERM);
exit(sts);
}
qAttr.type = qcom_eQtype_private;
qAttr.quota = 100;
if (!qcom_CreateQ(&sts, &qid, &qAttr, "events")) {
errh_Fatal("qcom_CreateQ, %m", sts);
errh_SetStatus( PWR__SRVTERM);
exit(sts);
}
qini = qcom_cQini;
if (!qcom_Bind(&sts, &qid, &qini)) {
errh_Fatal("qcom_Bind(Qini), %m", sts);
errh_SetStatus( PWR__SRVTERM);
exit(-1);
}
opcsrv = new opc_server();
opcsrv->qid = qid;
// Get OpcServerConfig object
sts = gdh_GetClassList( pwr_cClass_Opc_ServerConfig, &config_oid);
if ( EVEN(sts)) {
// Not configured
errh_SetStatus( 0);
exit(sts);
}
sts = gdh_ObjidToPointer( config_oid, (void **)&opcsrv->m_config);
if ( EVEN(sts)) {
errh_SetStatus( sts);
exit(sts);
}
aproc_RegisterObject( config_oid);
for ( int i = 0;
i < (int)(sizeof(opcsrv->m_config->ClientAccess)/sizeof(opcsrv->m_config->ClientAccess[0]));
i++) {
if ( strcmp( opcsrv->m_config->ClientAccess[i].Address, "") != 0) {
opcsrv->m_client_access[opcsrv->m_client_access_cnt].address =
inet_network( opcsrv->m_config->ClientAccess[i].Address);
if ( opcsrv->m_client_access[opcsrv->m_client_access_cnt].address != -1) {
opcsrv->m_client_access[opcsrv->m_client_access_cnt].access = opcsrv->m_config->ClientAccess[i].Access;
opcsrv->m_client_access_cnt++;
}
}
}
// Create a cyclic tread
pthread_t thread;
sts = pthread_create( &thread, NULL, opcsrv_cyclic, NULL);
time_GetTime( &opcsrv->m_start_time);
errh_SetStatus( PWR__SRUN);
soap_init( &soap);
for ( int k = 0; k < restarts + 1; k++) {
m = soap_bind( &soap, NULL, opcsrv->m_config->Port, 100);
if ( m < 0) {
if ( k == restarts) {
soap_print_fault( &soap, stderr);
break;
}
printf( "Soap bind failed, retrying...\n");
sleep( 10);
}
else {
fprintf( stderr, "Socket connection successfull: master socket = %d\n", m);
for ( int i = 1;; i++) {
s = soap_accept( &soap);
if ( s < 0) {
soap_print_fault( &soap, stderr);
break;
}
//fprintf( stderr, "%d: request from IP=%lu.%lu.%lu.%lu socket=%d\n", i,
// (soap.ip>>24)&0xFF,(soap.ip>>16)&0xFF,(soap.ip>>8)&0xFF,soap.ip&0xFF, s);
opcsrv->m_config->RequestCnt++;
opcsrv->m_client = opcsrv->find_client( soap.ip);
if ( !opcsrv->m_client)
opcsrv->m_client = opcsrv->new_client( soap.ip);
if ( !opcsrv->m_client->m_multi_threaded) {
if ( soap_serve( &soap) != SOAP_OK) // Process RPC request
soap_print_fault( &soap, stderr);
soap_destroy( &soap); // Clean up class instances
soap_end( &soap); // Clean up everything and close socket
}
else {
// Create a thread for every request
struct soap *tsoap;
pthread_t tid;
tsoap = soap_copy( &soap);
if ( !tsoap)
break;
pthread_create( &tid, NULL, opcsrv_process_request, (void *)tsoap);
}
}
}
}
soap_done( &soap); // Close master socket and detach environment
return SOAP_OK;
}
static void *opcsrv_process_request( void *soap)
{
pthread_detach( pthread_self());
soap_serve( (struct soap *) soap);
soap_destroy( (struct soap *) soap);
soap_end( (struct soap *) soap);
soap_done( (struct soap *) soap);
free( soap);
return 0;
}
static void *opcsrv_cyclic( void *arg)
{
pwr_tTime current_time;
pwr_tDeltaTime diff;
int tmo = 1000;
char mp[2000];
qcom_sGet get;
pwr_tStatus sts;
for (;;) {
time_GetTime( &current_time);
aproc_TimeStamp( ((float)tmo)/1000, 5);
get.maxSize = sizeof(mp);
get.data = mp;
qcom_Get( &sts, &opcsrv->qid, &get, tmo);
if (sts == QCOM__TMO || sts == QCOM__QEMPTY) {
// Check if any client can be removed
for ( client_iterator it = opcsrv->m_clientlist.begin(); it != opcsrv->m_clientlist.end(); it++) {
time_Adiff( &diff, &current_time, &it->second.m_last_time);
if ( diff.tv_sec > 600) {
//fprintf( stderr, "Client erased IP=%d.%d.%d.%d\n",
// (it->first>>24)&0xFF,(it->first>>16)&0xFF,(it->first>>8)&0xFF,it->first&0xFF);
opcsrv->m_clientlist.erase( it);
opcsrv->m_config->ClientCnt--;
}
}
}
else {
ini_mEvent new_event;
qcom_sEvent *ep = (qcom_sEvent*) get.data;
new_event.m = ep->mask;
if (new_event.b.oldPlcStop) {
errh_SetStatus( PWR__SRVRESTART);
} else if (new_event.b.swapDone) {
errh_SetStatus( PWR__SRUN);
} else if (new_event.b.terminate) {
exit(0);
}
}
}
}
SOAP_FMAC5 int SOAP_FMAC6 __s0__GetStatus(struct soap *soap,
_s0__GetStatus *s0__GetStatus,
_s0__GetStatusResponse *s0__GetStatusResponse)
{
pwr_tTime current_time;
// Check access for connection
opcsrv_client *client = opcsrv->find_client( soap->ip);
if ( !client)
client = opcsrv->new_client( soap->ip);
opcsrv->m_current_access = client->access;
switch ( opcsrv->m_current_access) {
case pwr_eOpc_AccessEnum_None:
return opcsrv->fault( soap, opc_eResultCode_E_ACCESS_DENIED);
default: ;
}
time_GetTime( &current_time);
s0__GetStatusResponse->GetStatusResult = soap_new_s0__ReplyBase( soap, -1);
s0__GetStatusResponse->GetStatusResult->RcvTime.assign( opc_datetime(0));
s0__GetStatusResponse->GetStatusResult->ReplyTime.assign( opc_datetime(0));
s0__GetStatusResponse->GetStatusResult->RevisedLocaleID = soap_new_std__string( soap, -1);
s0__GetStatusResponse->GetStatusResult->RevisedLocaleID->assign( "en");
s0__GetStatusResponse->GetStatusResult->ServerState = s0__serverState__running;
if ( s0__GetStatus->ClientRequestHandle) {
s0__GetStatusResponse->GetStatusResult->ClientRequestHandle =
soap_new_std__string( soap, -1);
s0__GetStatusResponse->GetStatusResult->ClientRequestHandle->assign( *s0__GetStatus->ClientRequestHandle);
}
s0__GetStatusResponse->Status = soap_new_s0__ServerStatus( soap, -1);
s0__GetStatusResponse->Status->VendorInfo = soap_new_std__string( soap, -1);
s0__GetStatusResponse->Status->VendorInfo->assign( "Proview - Open Source Process Control");
s0__GetStatusResponse->Status->SupportedInterfaceVersions.push_back( s0__interfaceVersion__XML_USCOREDA_USCOREVersion_USCORE1_USCORE0);
s0__GetStatusResponse->Status->SupportedLocaleIDs.push_back( std::string("en"));
s0__GetStatusResponse->Status->SupportedLocaleIDs.push_back( std::string("en-US"));
s0__GetStatusResponse->Status->StartTime.assign( opc_datetime( &opcsrv->m_start_time));
s0__GetStatusResponse->Status->ProductVersion = soap_new_std__string( soap, -1);
s0__GetStatusResponse->Status->ProductVersion->assign( pwrv_cPwrVersionStr);
return SOAP_OK;
}
SOAP_FMAC5 int SOAP_FMAC6 __s0__Read(struct soap *soap,
_s0__Read *s0__Read,
_s0__ReadResponse *s0__ReadResponse)
{
int ii;
class s0__ReadRequestItem *item;
pwr_sAttrRef ar;
pwr_tStatus sts;
pwr_tOName itemname;
pwr_tOName itempath;
pwr_tOName path;
int reqType = -1;
pwr_tTypeId tid;
unsigned int elem;
char buf[1024];
unsigned int options = 0;
// Check access for connection
opcsrv_client *client = opcsrv->find_client( soap->ip);
if ( !client)
client = opcsrv->new_client( soap->ip);
opcsrv->m_current_access = client->access;
switch ( opcsrv->m_current_access) {
case pwr_eOpc_AccessEnum_ReadOnly:
case pwr_eOpc_AccessEnum_ReadWrite:
break;
default:
return opcsrv->fault( soap, opc_eResultCode_E_ACCESS_DENIED);
}
s0__ReadResponse->ReadResult = soap_new_s0__ReplyBase( soap, -1);
s0__ReadResponse->ReadResult->RcvTime.assign( opc_datetime(0));
s0__ReadResponse->ReadResult->ReplyTime.assign( opc_datetime(0));
if (s0__Read->Options && s0__Read->Options->ClientRequestHandle) {
s0__ReadResponse->ReadResult->ClientRequestHandle = soap_new_std__string( soap, -1);
s0__ReadResponse->ReadResult->ClientRequestHandle->assign( *s0__Read->Options->ClientRequestHandle);
}
s0__ReadResponse->ReadResult->ServerState = s0__serverState__running;
if (!s0__Read->ItemList)
return SOAP_OK;
if (s0__Read->ItemList->Items.empty())
return SOAP_OK;
memset(path, 0, sizeof(path));
opc_requestoptions_to_mask(s0__Read->Options, &options);
if (s0__Read->ItemList->ItemPath && !s0__Read->ItemList->ItemPath->empty())
strncpy(path, s0__Read->ItemList->ItemPath->c_str(), sizeof(path));
for (ii = 0; ii < (int) s0__Read->ItemList->Items.size(); ii++) {
s0__ItemValue *iv = soap_new_s0__ItemValue( soap, -1);
if (!s0__ReadResponse->RItemList)
s0__ReadResponse->RItemList = soap_new_s0__ReplyItemList( soap, -1);
item = s0__Read->ItemList->Items[ii];
if (item->ItemPath && !item->ItemPath->empty())
strncpy(itempath, item->ItemPath->c_str(), sizeof(itempath));
else
strncpy(itempath, path, sizeof(itempath));
strncpy(itemname, itempath, sizeof(itemname));
strncat(itemname, item->ItemName->c_str(), sizeof(itemname));
if (options & opc_mRequestOption_ReturnItemPath) {
iv->ItemPath = soap_new_std__string( soap, -1);
iv->ItemPath->assign( itempath);
}
if (options & opc_mRequestOption_ReturnItemName) {
iv->ItemName = soap_new_std__string( soap, -1);
iv->ItemName->assign(itemname);
}
if (options & opc_mRequestOption_ReturnDiagnosticInfo) {
iv->DiagnosticInfo = soap_new_std__string( soap, -1);
iv->DiagnosticInfo->assign(""); // ToDo !!
}
if ( s0__Read->ItemList->Items[ii]->ClientItemHandle) {
iv->ClientItemHandle = soap_new_std__string( soap, -1);
iv->ClientItemHandle->assign( *s0__Read->ItemList->Items[ii]->ClientItemHandle);
}
sts = gdh_NameToAttrref(pwr_cNObjid, cnv_utf8_to_iso8859( itemname, strlen(itemname)+1), &ar);
if (EVEN(sts)) {
opcsrv_returnerror( soap, s0__ReadResponse->Errors, &iv->ResultID, opc_eResultCode_E_INVALIDITEMNAME, options);
s0__ReadResponse->RItemList->Items.push_back(iv);
continue;
}
if (!item->ReqType || item->ReqType->empty()) {
if (!s0__Read->ItemList->ReqType || s0__Read->ItemList->ReqType->empty()) {
reqType = -1;
} else {
opc_string_to_opctype(s0__Read->ItemList->ReqType->c_str(), &reqType);
}
} else {
opc_string_to_opctype(item->ReqType->c_str(), &reqType);
}
gdh_GetAttributeCharAttrref(&ar, &tid, NULL, NULL, &elem);
if (cdh_tidIsCid(tid) || elem > 1) {
opcsrv_returnerror( soap, s0__ReadResponse->Errors, &iv->ResultID, opc_eResultCode_E_BADTYPE, options);
s0__ReadResponse->RItemList->Items.push_back(iv);
continue;
}
sts = gdh_GetObjectInfoAttrref(&ar, buf, sizeof(buf));
if ( ODD(sts)) {
if (reqType < 0) opc_pwrtype_to_opctype(tid, &reqType);
if (opc_convert_pwrtype_to_opctype(buf, 0, sizeof(buf), reqType, tid)) {
iv->Value = opc_opctype_to_value( soap, buf, sizeof(buf), reqType);
if (options & opc_mRequestOption_ReturnItemTime) {
// ToDo !!!
}
s0__ReadResponse->RItemList->Items.push_back(iv);
} else {
opcsrv_returnerror( soap, s0__ReadResponse->Errors, &iv->ResultID, opc_eResultCode_E_BADTYPE, options);
s0__ReadResponse->RItemList->Items.push_back(iv);
continue;
}
} else {
opcsrv_returnerror( soap, s0__ReadResponse->Errors, &iv->ResultID, opc_eResultCode_E_BADTYPE, options);
s0__ReadResponse->RItemList->Items.push_back(iv);
continue;
}
}
return SOAP_OK;
}
SOAP_FMAC5 int SOAP_FMAC6 __s0__Write(struct soap* soap,
_s0__Write *s0__Write,
_s0__WriteResponse *s0__WriteResponse)
{
int ii;
s0__ItemValue *item;
pwr_sAttrRef ar;
pwr_tStatus sts;
pwr_tOName itemname;
pwr_tOName itempath;
pwr_tOName path;
pwr_tTypeId a_type;
unsigned int a_size, a_elem;
char buf[1024];
unsigned int options = 0;
// Check access for connection
opcsrv_client *client = opcsrv->find_client( soap->ip);
if ( !client)
client = opcsrv->new_client( soap->ip);
opcsrv->m_current_access = client->access;
switch ( opcsrv->m_current_access) {
case pwr_eOpc_AccessEnum_ReadWrite:
break;
default:
return opcsrv->fault( soap, opc_eResultCode_E_ACCESS_DENIED);
}
s0__WriteResponse->WriteResult = soap_new_s0__ReplyBase( soap, -1);
s0__WriteResponse->WriteResult->RcvTime.assign( opc_datetime(0));
s0__WriteResponse->WriteResult->ReplyTime.assign( opc_datetime(0));
if (s0__Write->Options && s0__Write->Options->ClientRequestHandle) {
s0__WriteResponse->WriteResult->ClientRequestHandle = soap_new_std__string( soap, -1);
s0__WriteResponse->WriteResult->ClientRequestHandle->assign( *s0__Write->Options->ClientRequestHandle);
}
s0__WriteResponse->WriteResult->ServerState = s0__serverState__running;
if (!s0__Write->ItemList)
return SOAP_OK;
if (s0__Write->ItemList->Items.empty())
return SOAP_OK;
strcpy(path, "");
opc_requestoptions_to_mask(s0__Write->Options, &options);
if (s0__Write->ItemList->ItemPath && !s0__Write->ItemList->ItemPath->empty())
strncpy(path, s0__Write->ItemList->ItemPath->c_str(), sizeof(path));
for (ii = 0; ii < (int) s0__Write->ItemList->Items.size(); ii++) {
s0__ItemValue *iv = new s0__ItemValue();
if (!s0__WriteResponse->RItemList)
s0__WriteResponse->RItemList = soap_new_s0__ReplyItemList( soap, -1);
item = s0__Write->ItemList->Items[ii];
if (item->ItemPath && !item->ItemPath->empty())
strncpy(itempath, item->ItemPath->c_str(), sizeof(itempath));
else
strncpy(itempath, path, sizeof(itempath));
strncpy(itemname, itempath, sizeof(itemname));
strncat(itemname, item->ItemName->c_str(), sizeof(itemname));
if (options & opc_mRequestOption_ReturnItemPath) {
iv->ItemPath = soap_new_std__string( soap, -1);
iv->ItemPath->assign( itempath);
}
if (options & opc_mRequestOption_ReturnItemName) {
iv->ItemName = soap_new_std__string( soap, -1);
iv->ItemName->assign(itemname);
}
if (options & opc_mRequestOption_ReturnDiagnosticInfo) {
iv->DiagnosticInfo = soap_new_std__string( soap, -1);
iv->DiagnosticInfo->assign(""); // ToDo !!
}
sts = gdh_NameToAttrref(pwr_cNObjid, cnv_utf8_to_iso8859(itemname, strlen(itemname)+1), &ar);
if (EVEN(sts)) {
opcsrv_returnerror( soap, s0__WriteResponse->Errors, &iv->ResultID, opc_eResultCode_E_INVALIDITEMNAME, options);
s0__WriteResponse->RItemList->Items.push_back(iv);
continue;
}
gdh_GetAttributeCharAttrref(&ar, &a_type, &a_size, NULL, &a_elem);
if (cdh_tidIsCid(a_type) || a_elem > 1) {
opcsrv_returnerror( soap, s0__WriteResponse->Errors, &iv->ResultID, opc_eResultCode_E_BADTYPE, options);
s0__WriteResponse->RItemList->Items.push_back(iv);
continue;
}
if ( !opc_convert_opctype_to_pwrtype( buf, a_size, item->Value, (pwr_eType) a_type)) {
opcsrv_returnerror( soap, s0__WriteResponse->Errors, &iv->ResultID, opc_eResultCode_E_BADTYPE, options);
s0__WriteResponse->RItemList->Items.push_back(iv);
continue;
}
sts = gdh_SetObjectInfoAttrref(&ar, buf, a_size);
if ( EVEN(sts)) {
opcsrv_returnerror( soap, s0__WriteResponse->Errors, &iv->ResultID, opc_eResultCode_E_BADTYPE, options);
s0__WriteResponse->RItemList->Items.push_back(iv);
}
}
return SOAP_OK;
}
SOAP_FMAC5 int SOAP_FMAC6 __s0__Subscribe(struct soap* soap,
_s0__Subscribe *s0__Subscribe,
_s0__SubscribeResponse *s0__SubscribeResponse)
{
pwr_tStatus sts;
pwr_tTypeId a_tid;
pwr_tUInt32 a_size, a_offs, a_elem;
pwr_tAName aname;
float list_deadband = 0;
float deadband;
// Check access for connection
opcsrv_client *client = opcsrv->find_client( soap->ip);
if ( !client)
client = opcsrv->new_client( soap->ip);
opcsrv->m_current_access = client->access;
s0__SubscribeResponse->SubscribeResult = soap_new_s0__ReplyBase( soap, -1);
s0__SubscribeResponse->SubscribeResult->RcvTime.assign( opc_datetime(0));
s0__SubscribeResponse->SubscribeResult->ReplyTime.assign( opc_datetime(0));
s0__SubscribeResponse->SubscribeResult->ServerState = s0__serverState__running;
if ( s0__Subscribe->Options && s0__Subscribe->Options->ClientRequestHandle) {
s0__SubscribeResponse->SubscribeResult->ClientRequestHandle =
soap_new_std__string( soap, -1);
s0__SubscribeResponse->SubscribeResult->ClientRequestHandle->assign(
*s0__Subscribe->Options->ClientRequestHandle);
}
switch ( opcsrv->m_current_access) {
case pwr_eOpc_AccessEnum_ReadOnly:
case pwr_eOpc_AccessEnum_ReadWrite:
break;
default:
return opcsrv->fault( soap, opc_eResultCode_E_ACCESS_DENIED);
}
if ( s0__Subscribe->ItemList) {
if ( s0__Subscribe->ItemList->Deadband)
list_deadband = *s0__Subscribe->ItemList->Deadband;
for ( int i = 0; i < (int) s0__Subscribe->ItemList->Items.size(); i++) {
opcsrv_sub sub;
int resultid = 0;
while (1) {
strcpy( aname,
cnv_utf8_to_iso8859( (char *)s0__Subscribe->ItemList->Items[i]->ItemName->c_str(),
s0__Subscribe->ItemList->Items[i]->ItemName->size()+1));
sts = gdh_GetAttributeCharacteristics( aname, &a_tid, &a_size, &a_offs, &a_elem);
if ( EVEN(sts)) {
resultid = opc_eResultCode_E_UNKNOWNITEMNAME;
break;
}
memset( &sub.old_value, 0, sizeof(sub.old_value));
sub.size = a_size;
sub.pwr_type = (pwr_eType) a_tid;
if ( cdh_tidIsCid( a_tid)) {
resultid = opc_eResultCode_E_BADTYPE;
break;
}
if ( !opc_pwrtype_to_opctype( sub.pwr_type, (int *)&sub.opc_type)) {
resultid = opc_eResultCode_E_BADTYPE;
break;
}
sts = gdh_RefObjectInfo( aname, &sub.p, &sub.subid, sub.size);
if ( EVEN(sts)) {
resultid = opc_eResultCode_E_FAIL;
break;
}
deadband = list_deadband;
if ( s0__Subscribe->ItemList->Items[i]->Deadband)
deadband = *s0__Subscribe->ItemList->Items[i]->Deadband;
sub.deadband = 0;
if ( deadband != 0) {
// Deadband in percentage of range, get range
pwr_tAName oname;
pwr_tAttrRef oaref;
pwr_tCid cid;
char *s;
strcpy( oname, aname);
if ( (s = strrchr( oname, '.')))
*s = 0;
sts = gdh_NameToAttrref( pwr_cNOid, oname, &oaref);
if ( EVEN(sts)) break;
sts = gdh_GetAttrRefTid( &oaref, &cid);
if ( EVEN(sts)) break;
switch ( cid) {
case pwr_cClass_Ai:
case pwr_cClass_Ao:
case pwr_cClass_Ii:
case pwr_cClass_Io: {
// Get range from channel
pwr_tAttrRef aaref;
pwr_tAttrRef sigchancon;
pwr_tFloat32 range_high = 0;
pwr_tFloat32 range_low = 0;
pwr_tStatus sts;
// Get Range from channel
sts = gdh_ArefANameToAref( &oaref, "SigChanCon", &aaref);
if ( ODD(sts))
sts = gdh_GetObjectInfoAttrref( &aaref, &sigchancon, sizeof(sigchancon));
if ( ODD(sts))
if ( cdh_ObjidIsNull( sigchancon.Objid))
sts = 0;
if ( ODD(sts))
sts = gdh_ArefANameToAref( &sigchancon, "ActValRangeHigh", &aaref);
if ( ODD(sts))
sts = gdh_GetObjectInfoAttrref( &aaref, &range_high, sizeof(range_high));
if ( ODD(sts))
sts = gdh_ArefANameToAref( &sigchancon, "ActValRangeLow", &aaref);
if ( ODD(sts))
sts = gdh_GetObjectInfoAttrref( &aaref, &range_low, sizeof(range_low));
if ( ODD(sts) && !(range_high == 0 && range_low == 0)) {
sub.deadband = (range_high - range_low) * deadband / 100;
break;
}
// Else continue and use PresMaxLimit and PresMinLimit
}
case pwr_cClass_Av:
case pwr_cClass_Iv: {
// Get range from Min/MaxShow
pwr_tAttrRef aaref;
pwr_tFloat32 range_high = 0;
pwr_tFloat32 range_low = 0;
pwr_tStatus sts;
sts = gdh_ArefANameToAref( &oaref, "PresMaxLimit", &aaref);
if ( ODD(sts))
sts = gdh_GetObjectInfoAttrref( &aaref, &range_high, sizeof(range_high));
if ( ODD(sts))
sts = gdh_ArefANameToAref( &oaref, "PresMinLimit", &aaref);
if ( ODD(sts))
sts = gdh_GetObjectInfoAttrref( &aaref, &range_low, sizeof(range_low));
if ( ODD(sts) && !(range_high == 0 && range_low == 0))
sub.deadband = (range_high - range_low) * deadband / 100;
break;
}
default:
// No range exist
;
}
}
if ( s0__Subscribe->ItemList->Items[i]->ClientItemHandle)
sub.client_handle.assign( *s0__Subscribe->ItemList->Items[i]->ClientItemHandle);
else
sub.client_handle.assign("");
if ( !s0__SubscribeResponse->ServerSubHandle) {
vector<opcsrv_sub> subv;
s0__SubscribeResponse->ServerSubHandle = soap_new_std__string( soap, -1);
s0__SubscribeResponse->ServerSubHandle->assign( cdh_SubidToString( 0, sub.subid, 0));
client->m_sublist[*s0__SubscribeResponse->ServerSubHandle] = subv;
}
client->m_sublist[*s0__SubscribeResponse->ServerSubHandle].push_back( sub);
break;
}
if ( resultid || s0__Subscribe->ReturnValuesOnReply) {
if ( !s0__SubscribeResponse->RItemList)
s0__SubscribeResponse->RItemList = new s0__SubscribeReplyItemList();
s0__SubscribeItemValue *iv = soap_new_s0__SubscribeItemValue( soap, -1);
iv->ItemValue = soap_new_s0__ItemValue( soap, -1);
iv->ItemValue->ItemName = soap_new_std__string( soap, -1);
iv->ItemValue->ItemName->assign(
cnv_utf8_to_iso8859( (char *)s0__Subscribe->ItemList->Items[i]->ItemName->c_str(),
s0__Subscribe->ItemList->Items[i]->ItemName->size()+1));
if ( s0__Subscribe->ItemList->Items[i]->ClientItemHandle) {
iv->ItemValue->ClientItemHandle = soap_new_std__string( soap, -1);
iv->ItemValue->ClientItemHandle->assign(
*s0__Subscribe->ItemList->Items[i]->ClientItemHandle);
}
if ( resultid) {
opcsrv_returnerror( soap, s0__SubscribeResponse->Errors,
&iv->ItemValue->ResultID, resultid, 0);
}
else if ( s0__Subscribe->ReturnValuesOnReply) {
int reqType;
char buf[1024];
opc_pwrtype_to_opctype( a_tid, &reqType);
if (opc_convert_pwrtype_to_opctype( sub.p, buf, sizeof(buf), reqType, a_tid)) {
iv->ItemValue->Value = opc_opctype_to_value( soap, buf, sizeof(buf), reqType);
}
else
opcsrv_returnerror( soap, s0__SubscribeResponse->Errors,
&iv->ItemValue->ResultID, opc_eResultCode_E_BADTYPE, 0);
}
s0__SubscribeResponse->RItemList->Items.push_back( iv);
}
}
}
return SOAP_OK;
}
SOAP_FMAC5 int SOAP_FMAC6 __s0__SubscriptionPolledRefresh(struct soap* soap,
_s0__SubscriptionPolledRefresh *s0__SubscriptionPolledRefresh,
_s0__SubscriptionPolledRefreshResponse *s0__SubscriptionPolledRefreshResponse)
{
// Check access for the connection
opcsrv_client *client = opcsrv->find_client( soap->ip);
if ( !client)
client = opcsrv->new_client( soap->ip);
opcsrv->m_current_access = client->access;
switch ( opcsrv->m_current_access) {
case pwr_eOpc_AccessEnum_ReadOnly:
case pwr_eOpc_AccessEnum_ReadWrite:
break;
default:
return opcsrv->fault( soap, opc_eResultCode_E_ACCESS_DENIED);
}
s0__SubscriptionPolledRefreshResponse->SubscriptionPolledRefreshResult =
soap_new_s0__ReplyBase( soap, -1);
s0__SubscriptionPolledRefreshResponse->SubscriptionPolledRefreshResult->RcvTime.assign( opc_datetime(0));
s0__SubscriptionPolledRefreshResponse->SubscriptionPolledRefreshResult->ReplyTime.assign( opc_datetime(0));
s0__SubscriptionPolledRefreshResponse->SubscriptionPolledRefreshResult->ServerState =
s0__serverState__running;
if ( s0__SubscriptionPolledRefresh->Options &&
s0__SubscriptionPolledRefresh->Options->ClientRequestHandle) {
s0__SubscriptionPolledRefreshResponse->SubscriptionPolledRefreshResult->ClientRequestHandle = soap_new_std__string( soap, -1);
s0__SubscriptionPolledRefreshResponse->SubscriptionPolledRefreshResult->ClientRequestHandle->assign( *s0__SubscriptionPolledRefresh->Options->ClientRequestHandle);
}
pwr_tTime hold_time;
int wait_time;
bool has_holdtime = false;
bool has_waittime = false;
int waited_time = 0;
pwr_tFloat32 wait_scan = 0.5;
pwr_tFloat32 min_hold = 0.5;
pwr_tDeltaTime dwait_scan, dmin_hold;
if ( s0__SubscriptionPolledRefresh->HoldTime) {
if ( !client->m_multi_threaded)
client->m_multi_threaded = true;
else {
has_holdtime = true;
time_FloatToD( &dmin_hold, min_hold);
opc_time_OPCAsciiToA( (char *)s0__SubscriptionPolledRefresh->HoldTime->c_str(),
&hold_time);
if ( s0__SubscriptionPolledRefresh->WaitTime) {
has_waittime = true;
wait_time = *s0__SubscriptionPolledRefresh->WaitTime;
time_FloatToD( &dwait_scan, wait_scan);
}
}
}
if ( has_holdtime) {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pwr_tTime current_time, next_time;
if ( min_hold > FLT_EPSILON) {
time_GetTime( &current_time);
time_Aadd( &next_time, &current_time, &dmin_hold);
if ( time_Acomp( &next_time, &hold_time) == -1)
next_time = hold_time;
struct timespec next_time_ts;
next_time_ts.tv_sec = next_time.tv_sec;
next_time_ts.tv_nsec = next_time.tv_nsec;
pthread_cond_timedwait( &cond, &mutex, &next_time_ts);
}
else {
struct timespec hold_time_ts;
hold_time_ts.tv_sec = hold_time.tv_sec;
hold_time_ts.tv_nsec = hold_time.tv_nsec;
pthread_cond_timedwait( &cond, &mutex, &hold_time_ts);
}
}
if ( has_waittime) {
// Check all values
bool change_found = false;
for ( waited_time = 0; waited_time < wait_time; waited_time += (int)(wait_scan * 1000)) {
for ( int i = 0; i < (int) s0__SubscriptionPolledRefresh->ServerSubHandles.size(); i++) {
sublist_iterator it =
client->m_sublist.find( s0__SubscriptionPolledRefresh->ServerSubHandles[i]);
if ( it != client->m_sublist.end()) {
for ( int j = 0; j < (int)it->second.size(); j++) {
if ( !opc_cmp_pwr( &it->second[j].old_value, it->second[j].p, it->second[j].size,
it->second[j].pwr_type, it->second[j].deadband)) {
change_found = true;
break;
}
}
}
if ( change_found)
break;
}
if ( change_found)
break;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pwr_tTime current_time, next_time;
time_GetTime( &current_time);
time_Aadd( &next_time, &current_time, &dwait_scan);
struct timespec next_time_ts;
next_time_ts.tv_sec = next_time.tv_sec;
next_time_ts.tv_nsec = next_time.tv_nsec;
pthread_cond_timedwait( &cond, &mutex, &next_time_ts);
}
}
for ( int i = 0; i < (int) s0__SubscriptionPolledRefresh->ServerSubHandles.size(); i++) {
sublist_iterator it =
client->m_sublist.find( s0__SubscriptionPolledRefresh->ServerSubHandles[i]);
if ( it != client->m_sublist.end()) {
// Test
for ( int jj = 0; jj < (int) it->second.size(); jj++) {
//printf( "%d sub: p %d size %d opc_type %d pwr_type %d subid %d,%d\n", jj, (int)it->second[jj].p,
// it->second[jj].size, it->second[jj].opc_type, it->second[jj].pwr_type, it->second[jj].subid.nid,
// it->second[jj].subid.rix);
jj++;
}
s0__SubscribePolledRefreshReplyItemList *rlist =
soap_new_s0__SubscribePolledRefreshReplyItemList( soap, -1);
rlist->SubscriptionHandle = soap_new_std__string( soap, -1);
rlist->SubscriptionHandle->assign( s0__SubscriptionPolledRefresh->ServerSubHandles[i]);
for ( int j = 0; j < (int)it->second.size(); j++) {
s0__ItemValue *ritem = soap_new_s0__ItemValue( soap, -1);
// TODO
ritem->Value = opc_opctype_to_value( soap, it->second[j].p, it->second[j].size,
it->second[j].opc_type);
if ( it->second[j].size <= (int)sizeof(it->second[j].old_value))
memcpy( &it->second[j].old_value, it->second[j].p, it->second[j].size);
ritem->Timestamp = soap_new_std__string( soap, -1);
ritem->Timestamp->assign( opc_datetime(0));
if ( !it->second[j].client_handle.empty()) {
ritem->ClientItemHandle = soap_new_std__string( soap, -1);
ritem->ClientItemHandle->assign( it->second[j].client_handle.c_str());
}
rlist->Items.push_back( ritem);
}
s0__SubscriptionPolledRefreshResponse->RItemList.push_back( rlist);
}
else {
// Subscription not found
s0__SubscribePolledRefreshReplyItemList *rlist = soap_new_s0__SubscribePolledRefreshReplyItemList( soap, -1);
rlist->SubscriptionHandle = soap_new_std__string( soap, -1);
rlist->SubscriptionHandle->assign( s0__SubscriptionPolledRefresh->ServerSubHandles[i]);
s0__ItemValue *ritem = soap_new_s0__ItemValue( soap, -1);
opcsrv_returnerror( soap, s0__SubscriptionPolledRefreshResponse->Errors, &ritem->ResultID,
opc_eResultCode_E_NOSUBSCRIPTION, 0);
rlist->Items.push_back( ritem);
s0__SubscriptionPolledRefreshResponse->RItemList.push_back( rlist);
}
}
return SOAP_OK;
}
SOAP_FMAC5 int SOAP_FMAC6 __s0__SubscriptionCancel(struct soap* soap,
_s0__SubscriptionCancel *s0__SubscriptionCancel,
_s0__SubscriptionCancelResponse *s0__SubscriptionCancelResponse)
{
opcsrv_client *client = opcsrv->find_client( soap->ip);
if ( !client)
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
// Check access for the connection
switch ( client->access) {
case pwr_eOpc_AccessEnum_ReadOnly:
case pwr_eOpc_AccessEnum_ReadWrite:
break;
default:
return opcsrv->fault( soap, opc_eResultCode_E_ACCESS_DENIED);
}
if ( !s0__SubscriptionCancel->ServerSubHandle)
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
time_GetTime( &client->m_last_time);
sublist_iterator it =
client->m_sublist.find( *s0__SubscriptionCancel->ServerSubHandle);
if ( it != client->m_sublist.end()) {
client->m_sublist.erase( it);
}
else {
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
}
if ( s0__SubscriptionCancel->ClientRequestHandle) {
s0__SubscriptionCancelResponse->ClientRequestHandle = soap_new_std__string( soap, -1);
s0__SubscriptionCancelResponse->ClientRequestHandle->assign(
*s0__SubscriptionCancel->ClientRequestHandle);
}
return SOAP_OK;
}
bool opcsrv_get_properties( struct soap *soap, bool is_item, pwr_tCid pcid, pwr_tAttrRef *parp,
pwr_tAttrRef *arp, unsigned int propmask, gdh_sAttrDef *bd,
std::vector<s0__ItemProperty *>& properties)
{
pwr_tStatus sts;
if ( !is_item) {
if ( propmask & opc_mProperty_Description) {
pwr_tAttrRef aaref;
pwr_tString80 desc;
sts = gdh_ArefANameToAref( arp, "Description", &aaref);
if ( ODD(sts)) {
sts = gdh_GetObjectInfoAttrref( &aaref, desc, sizeof(desc));
if ( ODD(sts)) {
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign("description");
ip->Value = soap_new_xsd__string( soap, -1);
((xsd__string *)ip->Value)->__item.assign(desc);
properties.push_back( ip);
}
}
if ( EVEN(sts)) {
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "description");
ip->Value = soap_new_xsd__string( soap, -1);
properties.push_back( ip);
}
}
}
else {
// IsItem
// Description
if ( propmask & opc_mProperty_Description) {
switch ( pcid) {
case pwr_cClass_Di:
case pwr_cClass_Do:
case pwr_cClass_Dv:
case pwr_cClass_Ai:
case pwr_cClass_Ao:
case pwr_cClass_Av:
case pwr_cClass_Ii:
case pwr_cClass_Io:
case pwr_cClass_Iv: {
if ( strcmp( bd->attrName, "ActualValue") != 0)
break;
pwr_tAttrRef aaref;
pwr_tString80 desc;
// Description from signal object
sts = gdh_ArefANameToAref( parp, "Description", &aaref);
if ( EVEN(sts)) break;
sts = gdh_GetObjectInfoAttrref( &aaref, desc, sizeof(desc));
if ( EVEN(sts)) break;
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "description");
ip->Value = soap_new_xsd__string( soap, -1);
((xsd__string *)ip->Value)->__item.assign( desc);
properties.push_back( ip);
break;
}
default: {
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "description");
ip->Value = soap_new_xsd__string( soap, -1);
properties.push_back( ip);
}
}
}
// DataType
if ( propmask & opc_mProperty_DataType) {
char *type_p;
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
if ( opc_pwrtype_to_string( bd->attr->Param.Info.Type, &type_p)) {
ip->Name.assign( "dataType");
ip->Value = soap_new_xsd__QName_( soap, -1);
((xsd__QName_ *)ip->Value)->__item.assign(type_p);
properties.push_back( ip);
}
else {
// Untranslatable type TODO
}
}
// Quality
if ( propmask & opc_mProperty_Quality) {
char *qual_p;
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
if ( opc_quality_to_string( s0__qualityBits__good, &qual_p)) {
ip->Name.assign( "quality");
ip->Value = soap_new_xsd__string( soap, -1);
((xsd__string *)ip->Value)->__item.assign( qual_p);
properties.push_back( ip);
}
}
// Timestamp
if ( propmask & opc_mProperty_Timestamp) {
// TODO ...
}
// Access Rights
if ( propmask & opc_mProperty_AccessRights) {
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "accessRights");
ip->Value = soap_new_xsd__string( soap, -1);
switch ( opcsrv->m_current_access) {
case pwr_eOpc_AccessEnum_ReadOnly:
((xsd__string *)ip->Value)->__item.assign( "readable");
break;
case pwr_eOpc_AccessEnum_ReadWrite:
if ( bd->attr->Param.Info.Flags & PWR_MASK_RTVIRTUAL ||
bd->attr->Param.Info.Flags & PWR_MASK_PRIVATE)
((xsd__string *)ip->Value)->__item.assign( "readable");
else
((xsd__string *)ip->Value)->__item.assign( "readWritable");
break;
default:
((xsd__string *)ip->Value)->__item.assign( "unknown");
break;
}
properties.push_back( ip);
}
// EngineeringUnits
if ( propmask & opc_mProperty_EngineeringUnits) {
if ( parp) {
switch ( pcid) {
case pwr_cClass_Ai:
case pwr_cClass_Ao:
case pwr_cClass_Av: {
if ( strcmp( bd->attrName, "ActualValue") != 0)
break;
pwr_tAttrRef aaref;
pwr_tString16 unit;
// Get Range from channel
sts = gdh_ArefANameToAref( parp, "Unit", &aaref);
if ( EVEN(sts)) break;
sts = gdh_GetObjectInfoAttrref( &aaref, &unit, sizeof(unit));
if ( EVEN(sts)) break;
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "engineeringUnits");
ip->Value = soap_new_xsd__string( soap, -1);
((xsd__string *)ip->Value)->__item.assign( unit);
properties.push_back( ip);
break;
}
default: ;
}
}
}
// EuType
if ( propmask & opc_mProperty_EuType) {
switch( bd->attr->Param.Info.Type) {
case pwr_eType_Float32: {
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "euType");
ip->Value = soap_new_xsd__string( soap, -1);
((xsd__string *)ip->Value)->__item.assign( "analog");
properties.push_back( ip);
break;
}
default: {
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "euType");
ip->Value = soap_new_xsd__string( soap, -1);
((xsd__string *)ip->Value)->__item.assign( "noEnum");
properties.push_back( ip);
break;
}
}
}
// HighEU
if ( propmask & opc_mProperty_HighEU) {
if ( parp) {
pwr_tAttrRef aaref;
pwr_tFloat32 fval;
switch ( pcid) {
case pwr_cClass_Av:
case pwr_cClass_Ai:
case pwr_cClass_Ao:
sts = gdh_ArefANameToAref( parp, "PresMaxLimit", &aaref);
if ( ODD(sts)) {
sts = gdh_GetObjectInfoAttrref( &aaref, &fval, sizeof(fval));
if ( ODD(sts)) {
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "highEU");
ip->Value = soap_new_xsd__double( soap, -1);
((xsd__double *)ip->Value)->__item = fval;
properties.push_back( ip);
}
}
break;
default: ;
}
}
}
// LowEU
if ( propmask & opc_mProperty_LowEU) {
if ( parp) {
pwr_tAttrRef aaref;
pwr_tFloat32 fval;
switch ( pcid) {
case pwr_cClass_Av:
case pwr_cClass_Ai:
case pwr_cClass_Ao:
sts = gdh_ArefANameToAref( parp, "PresMinLimit", &aaref);
if ( ODD(sts)) {
sts = gdh_GetObjectInfoAttrref( &aaref, &fval, sizeof(fval));
if ( ODD(sts)) {
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "lowEU");
ip->Value = soap_new_xsd__double( soap, -1);
((xsd__double *)ip->Value)->__item = fval;
properties.push_back( ip);
}
}
break;
default: ;
}
}
}
// HighIR
if ( propmask & opc_mProperty_HighIR) {
if ( parp) {
switch ( pcid) {
case pwr_cClass_Ai:
case pwr_cClass_Ii:
case pwr_cClass_Ao:
case pwr_cClass_Io: {
if ( strcmp( bd->attrName, "ActualValue") != 0)
break;
pwr_tAttrRef aaref;
pwr_tAttrRef sigchancon;
pwr_tFloat32 fval;
// Get Range from channel
sts = gdh_ArefANameToAref( parp, "SigChanCon", &aaref);
if ( EVEN(sts)) break;
sts = gdh_GetObjectInfoAttrref( &aaref, &sigchancon, sizeof(sigchancon));
if ( EVEN(sts)) break;
if ( cdh_ObjidIsNull( sigchancon.Objid))
break;
sts = gdh_ArefANameToAref( &sigchancon, "ActValRangeHigh", &aaref);
if ( EVEN(sts)) break;
sts = gdh_GetObjectInfoAttrref( &aaref, &fval, sizeof(fval));
if ( EVEN(sts)) break;
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "highIR");
ip->Value = soap_new_xsd__double( soap, -1);
((xsd__double *)ip->Value)->__item = fval;
properties.push_back( ip);
break;
}
default: ;
}
}
}
// LowIR
if ( propmask & opc_mProperty_LowIR) {
if ( parp) {
switch ( pcid) {
case pwr_cClass_Ai:
case pwr_cClass_Ii:
case pwr_cClass_Ao:
case pwr_cClass_Io: {
if ( strcmp( bd->attrName, "ActualValue") != 0)
break;
pwr_tAttrRef sigchancon;
pwr_tAttrRef aaref;
pwr_tFloat32 fval;
// Get Range from channel
sts = gdh_ArefANameToAref( parp, "SigChanCon", &aaref);
if ( EVEN(sts)) break;
sts = gdh_GetObjectInfoAttrref( &aaref, &sigchancon, sizeof(sigchancon));
if ( EVEN(sts)) break;
if ( cdh_ObjidIsNull( sigchancon.Objid))
break;
sts = gdh_ArefANameToAref( &sigchancon, "ActValRangeLow", &aaref);
if ( EVEN(sts)) break;
sts = gdh_GetObjectInfoAttrref( &aaref, &fval, sizeof(fval));
if ( EVEN(sts)) break;
s0__ItemProperty *ip = soap_new_s0__ItemProperty( soap, -1);
ip->Name.assign( "lowIR");
ip->Value = soap_new_xsd__double( soap, -1);
((xsd__double *)ip->Value)->__item = fval;
properties.push_back( ip);
break;
}
default: ;
}
}
}
}
return true;
}
int opc_server::get_access( int sid)
{
int access = pwr_eOpc_AccessEnum_None;
if ( m_grant_all)
access = pwr_eOpc_AccessEnum_ReadWrite;
else {
for ( int i = 0; i < m_client_access_cnt; i++) {
if ( m_client_access[i].address == (int)sid) {
access = m_client_access[i].access;
break;
}
}
}
return access;
}
SOAP_FMAC5 int SOAP_FMAC6 __s0__Browse(struct soap *soap, _s0__Browse *s0__Browse,
_s0__BrowseResponse *s0__BrowseResponse)
{
pwr_tStatus sts;
pwr_tOid oid, child, ch;
pwr_tOName name;
pwr_tCid cid;
unsigned int property_mask;
pwr_tTime current_time;
bool has_max_elem = false;
int max_elem = 0;
// Check access for connection
opcsrv_client *client = opcsrv->find_client( soap->ip);
if ( !client)
client = opcsrv->new_client( soap->ip);
opcsrv->m_current_access = client->access;
switch ( opcsrv->m_current_access) {
case pwr_eOpc_AccessEnum_ReadOnly:
case pwr_eOpc_AccessEnum_ReadWrite:
break;
default:
return opcsrv->fault( soap, opc_eResultCode_E_ACCESS_DENIED);
}
time_GetTime( &current_time);
if ( s0__Browse->MaxElementsReturned) {
has_max_elem = true;
max_elem = *s0__Browse->MaxElementsReturned;
}
s0__BrowseResponse->BrowseResult = soap_new_s0__ReplyBase( soap, -1);
s0__BrowseResponse->BrowseResult->RcvTime.assign( opc_datetime(0));
s0__BrowseResponse->BrowseResult->ReplyTime.assign( opc_datetime(0));
if ( s0__Browse->ClientRequestHandle) {
s0__BrowseResponse->BrowseResult->ClientRequestHandle = soap_new_std__string( soap, -1);
s0__BrowseResponse->BrowseResult->ClientRequestHandle->assign(
*s0__Browse->ClientRequestHandle);
}
s0__BrowseResponse->BrowseResult->ServerState = s0__serverState__running;
s0__BrowseResponse->MoreElements = (bool *) soap_malloc( soap, sizeof(bool));
*s0__BrowseResponse->MoreElements = false;
if ( s0__Browse->ContinuationPoint) {
// Continue with next siblings
pwr_tOName pname;
pwr_tOName itemname;
pwr_sAttrRef paref;
pwr_sAttrRef aref;
cdh_StringToObjid( s0__Browse->ContinuationPoint->c_str(), &child);
// Check continuationpoint
sts = gdh_GetObjectClass( child, &cid);
if ( EVEN(sts)) {
return opcsrv->fault( soap, opc_eResultCode_E_INVALIDCONTINUATIONPOINT);
}
for ( sts = 1;
ODD(sts);
sts = gdh_GetNextSibling( child, &child)) {
if ( has_max_elem && (int)s0__BrowseResponse->Elements.size() > max_elem) {
// Max elements reached, return current oid as continuation point
s0__BrowseResponse->ContinuationPoint = soap_new_std__string( soap, -1);
s0__BrowseResponse->ContinuationPoint->assign( cdh_ObjidToString( 0, child, 1));
*s0__BrowseResponse->MoreElements = true;
break;
}
sts = gdh_ObjidToName( child, name, sizeof(name), cdh_mName_object);
if ( EVEN(sts)) continue;
sts = gdh_GetObjectClass( child, &cid);
if ( EVEN(sts)) continue;
s0__BrowseElement *element = soap_new_s0__BrowseElement( soap, -1);
element->Name = soap_new_std__string( soap, -1);
element->Name->assign( name);
strcpy( itemname, pname);
strcat( itemname, "-");
strcat( itemname, name);
element->ItemName = soap_new_std__string( soap, -1);
element->ItemName->assign( itemname);
element->IsItem = false;
if ( cid == pwr_eClass_PlantHier || cid == pwr_eClass_NodeHier)
element->HasChildren = ODD( gdh_GetChild( child, &ch)) ? true : false;
else
element->HasChildren = true;
if ( s0__Browse->ReturnAllProperties)
property_mask = ~0;
else
opc_propertynames_to_mask( s0__Browse->PropertyNames, &property_mask);
if ( property_mask) {
aref = cdh_ObjidToAref( child);
opcsrv_get_properties( soap, element->IsItem, cid, &paref, &aref,
property_mask, 0,
element->Properties);
}
s0__BrowseResponse->Elements.push_back( element);
}
return SOAP_OK;
}
if ( (!s0__Browse->ItemName || s0__Browse->ItemName->empty()) &&
(!s0__Browse->ItemPath || s0__Browse->ItemPath->empty())) {
// Return rootlist
for ( sts = gdh_GetRootList( &oid); ODD(sts); sts = gdh_GetNextSibling( oid, &oid)) {
if ( has_max_elem && (int)s0__BrowseResponse->Elements.size() > max_elem) {
// Max elements reached, return current oid as continuation point
s0__BrowseResponse->ContinuationPoint = soap_new_std__string( soap, -1);
s0__BrowseResponse->ContinuationPoint->assign( cdh_ObjidToString( 0, oid, 1));
*s0__BrowseResponse->MoreElements = true;
break;
}
sts = gdh_ObjidToName( oid, name, sizeof(name), cdh_mName_object);
if ( EVEN(sts))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
sts = gdh_GetObjectClass( oid, &cid);
if ( EVEN(sts))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
s0__BrowseElement *element = new s0__BrowseElement();
element->Name = soap_new_std__string( soap, -1);
element->Name->assign( name);
element->ItemName = element->Name;
element->IsItem = false;
if ( cid == pwr_eClass_PlantHier || cid == pwr_eClass_NodeHier)
element->HasChildren = ODD( gdh_GetChild( child, &ch)) ? true : false;
else
element->HasChildren = true;
if ( s0__Browse->ReturnAllProperties)
property_mask = ~0;
else
opc_propertynames_to_mask( s0__Browse->PropertyNames, &property_mask);
pwr_tAttrRef aref = cdh_ObjidToAref( oid);
opcsrv_get_properties( soap, false, cid, 0, &aref,
property_mask, 0,
element->Properties);
s0__BrowseResponse->Elements.push_back( element);
}
}
else {
// Return attributes and children
pwr_tOName pname;
pwr_tOName itemname;
pwr_tObjName aname;
gdh_sAttrDef *bd;
int rows;
pwr_sAttrRef paref;
pwr_sAttrRef aref;
if ( s0__Browse->ItemPath && !s0__Browse->ItemPath->empty()) {
strncpy( pname, s0__Browse->ItemPath->c_str(), sizeof( pname));
if ( s0__Browse->ItemName && !s0__Browse->ItemName->empty()) {
strcat( pname, s0__Browse->ItemName->c_str());
}
}
else
strncpy( pname, s0__Browse->ItemName->c_str(), sizeof(pname));
strcpy( pname, cnv_utf8_to_iso8859( pname, strlen(pname)+1));
sts = gdh_NameToAttrref( pwr_cNOid, pname, &paref);
if ( EVEN(sts)) {
// return opcsrv->fault( soap, opc_eResultCode_E_UNKNOWNITEMNAME);
// Assume that this is an unmounted mount object and return OK
return SOAP_OK;
}
sts = gdh_GetAttrRefTid( &paref, &cid);
if ( EVEN(sts))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
if ( paref.Flags.b.Array) {
// Return all elements
pwr_tTypeId a_type;
unsigned int a_size, a_offs, a_dim;
pwr_tAttrRef oaref;
char *s;
char *attrname;
sts = gdh_AttrArefToObjectAref( &paref, &oaref);
if ( EVEN(sts))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
sts = gdh_GetAttrRefTid( &oaref, &cid);
if ( EVEN(sts))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
if ( !( attrname = strrchr( pname, '.')))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
attrname++;
// Get body definition
sts = gdh_GetObjectBodyDef( cid, &bd, &rows, pwr_cNOid);
if ( EVEN(sts))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
int bd_idx = -1;
for ( int i = 0; i < rows; i++) {
if ( cdh_NoCaseStrcmp( attrname, bd[i].attrName) == 0) {
bd_idx = i;
break;
}
}
if ( bd_idx == -1) {
// E_INVALIDITEMNAME
free( (char *)bd);
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
}
sts = gdh_GetAttributeCharAttrref( &paref, &a_type, &a_size, &a_offs, &a_dim);
if ( EVEN(sts)) {
free( (char *)bd);
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
}
for ( int i = 0; i < (int)a_dim; i++) {
s0__BrowseElement *element = soap_new_s0__BrowseElement( soap, -1);
sprintf( itemname, "%s[%d]", pname, i);
s = strrchr( itemname, '.');
if ( s)
strcpy( aname, s + 1);
else
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
element->Name = soap_new_std__string( soap, -1);
element->Name->assign( aname);
element->ItemName = soap_new_std__string( soap, -1);
element->ItemName->assign( itemname);
element->IsItem = true;
element->HasChildren = false;
if ( s0__Browse->ReturnAllProperties)
property_mask = ~0;
else
opc_propertynames_to_mask( s0__Browse->PropertyNames, &property_mask);
if ( property_mask) {
sts = gdh_NameToAttrref( pwr_cNOid, itemname, &aref);
if ( EVEN(sts))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
opcsrv_get_properties( soap, true, cid, &paref, &aref,
property_mask, &bd[bd_idx],
element->Properties);
}
s0__BrowseResponse->Elements.push_back( element);
}
free( (char *)bd);
return SOAP_OK;
}
if ( !cdh_tidIsCid( cid))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
sts = gdh_GetObjectBodyDef( cid, &bd, &rows, pwr_cNOid);
if ( ODD(sts)) {
for ( int i = 0; i < rows; i++) {
if ( bd[i].flags & gdh_mAttrDef_Shadowed)
continue;
if ( bd[i].attr->Param.Info.Flags & PWR_MASK_RTVIRTUAL ||
bd[i].attr->Param.Info.Flags & PWR_MASK_PRIVATE)
continue;
if ( bd[i].attr->Param.Info.Type == pwr_eType_CastId ||
bd[i].attr->Param.Info.Type == pwr_eType_DisableAttr)
continue;
if ( bd[i].attr->Param.Info.Flags & PWR_MASK_RTHIDE)
continue;
sts = gdh_ArefANameToAref( &paref, bd[i].attrName, &aref);
if ( EVEN(sts))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
if ( bd[i].attr->Param.Info.Flags & PWR_MASK_DISABLEATTR) {
pwr_tDisableAttr disabled;
sts = gdh_ArefDisabled( &aref, &disabled);
if ( EVEN(sts))
return opcsrv->fault( soap, opc_eResultCode_E_FAIL);
if ( disabled)
continue;
}
if ( bd[i].attr->Param.Info.Flags & PWR_MASK_ARRAY ||
bd[i].attr->Param.Info.Flags & PWR_MASK_CLASS ) {
s0__BrowseElement *element = soap_new_s0__BrowseElement( soap, -1);
cdh_SuppressSuper( aname, bd[i].attrName);
element->Name = soap_new_std__string( soap, -1);
element->Name->assign( aname);
strcpy( itemname, pname);
strcat( itemname, ".");
strcat( itemname, bd[i].attrName);
element->ItemName = soap_new_std__string( soap, -1);
element->ItemName->assign( itemname);
element->IsItem = false;
element->HasChildren = true;
if ( s0__Browse->ReturnAllProperties)
property_mask = ~0;
else
opc_propertynames_to_mask( s0__Browse->PropertyNames, &property_mask);
if ( property_mask)
opcsrv_get_properties( soap, element->IsItem, cid, &paref, &aref,
property_mask, &bd[i],
element->Properties);
s0__BrowseResponse->Elements.push_back( element);
}
else {
s0__BrowseElement *element = soap_new_s0__BrowseElement( soap, -1);
cdh_SuppressSuper( aname, bd[i].attrName);
element->Name = soap_new_std__string( soap, -1);
element->Name->assign( aname);
strcpy( itemname, pname);
strcat( itemname, ".");
strcat( itemname, bd[i].attrName);
element->ItemName = soap_new_std__string( soap, -1);
element->ItemName->assign( itemname);
element->IsItem = true;
element->HasChildren = false;
if ( s0__Browse->ReturnAllProperties)
property_mask = ~0;
else
opc_propertynames_to_mask( s0__Browse->PropertyNames, &property_mask);
if ( property_mask)
opcsrv_get_properties( soap, element->IsItem, cid, &paref, &aref,
property_mask, &bd[i],
element->Properties);
s0__BrowseResponse->Elements.push_back( element);
}
}
free( (char *)bd);
}
if ( paref.Flags.b.Object) {
for ( sts = gdh_GetChild( paref.Objid, &child);
ODD(sts);
sts = gdh_GetNextSibling( child, &child)) {
if ( has_max_elem && (int)s0__BrowseResponse->Elements.size() > max_elem) {
// Max elements reached, return current oid as continuation point
s0__BrowseResponse->ContinuationPoint = soap_new_std__string( soap, -1);
s0__BrowseResponse->ContinuationPoint->assign( cdh_ObjidToString( 0, child, 1));
*s0__BrowseResponse->MoreElements = true;
break;
}
sts = gdh_ObjidToName( child, name, sizeof(name), cdh_mName_object);
if ( EVEN(sts)) continue;
sts = gdh_GetObjectClass( child, &cid);
if ( EVEN(sts)) continue;
s0__BrowseElement *element = soap_new_s0__BrowseElement( soap, -1);
element->Name = soap_new_std__string( soap, -1);
element->Name->assign( name);
strcpy( itemname, pname);
strcat( itemname, "-");
strcat( itemname, name);
element->ItemName = soap_new_std__string( soap, -1);
element->ItemName->assign( itemname);
element->IsItem = false;
if ( cid == pwr_eClass_PlantHier || cid == pwr_eClass_NodeHier)
element->HasChildren = ODD( gdh_GetChild( child, &ch)) ? true : false;
else
element->HasChildren = true;
if ( s0__Browse->ReturnAllProperties)
property_mask = ~0;
else
opc_propertynames_to_mask( s0__Browse->PropertyNames, &property_mask);
if ( property_mask) {
aref = cdh_ObjidToAref( child);
opcsrv_get_properties( soap, element->IsItem, cid, &paref, &aref,
property_mask, 0,
element->Properties);
}
s0__BrowseResponse->Elements.push_back( element);
}
}
}
return SOAP_OK;
}
SOAP_FMAC5 int SOAP_FMAC6 __s0__GetProperties(struct soap *soap,
_s0__GetProperties *s0__GetProperties,
_s0__GetPropertiesResponse *s0__GetPropertiesResponse)
{
unsigned int property_mask;
pwr_tCid cid;
pwr_tAName iname;
char *aname;
pwr_tStatus sts;
pwr_tAttrRef aref;
pwr_tAttrRef paref;
gdh_sAttrDef *bd;
int rows;
// Check access for connection
opcsrv_client *client = opcsrv->find_client( soap->ip);
if ( !client)
client = opcsrv->new_client( soap->ip);
opcsrv->m_current_access = client->access;
switch ( opcsrv->m_current_access) {
case pwr_eOpc_AccessEnum_ReadOnly:
case pwr_eOpc_AccessEnum_ReadWrite:
break;
default:
return opcsrv->fault( soap, opc_eResultCode_E_ACCESS_DENIED);
}
s0__GetPropertiesResponse->GetPropertiesResult = soap_new_s0__ReplyBase( soap, -1);
s0__GetPropertiesResponse->GetPropertiesResult->RcvTime.assign( opc_datetime(0));
s0__GetPropertiesResponse->GetPropertiesResult->ReplyTime.assign( opc_datetime(0));
if ( s0__GetProperties->ClientRequestHandle) {
s0__GetPropertiesResponse->GetPropertiesResult->ClientRequestHandle =
soap_new_std__string( soap, -1);
s0__GetPropertiesResponse->GetPropertiesResult->ClientRequestHandle->assign(
*s0__GetProperties->ClientRequestHandle);
}
s0__GetPropertiesResponse->GetPropertiesResult->ServerState = s0__serverState__running;
if ( s0__GetProperties->ReturnAllProperties && *s0__GetProperties->ReturnAllProperties)
property_mask = ~0;
else
opc_propertynames_to_mask( s0__GetProperties->PropertyNames, &property_mask);
for ( int i = 0; i < (int)s0__GetProperties->ItemIDs.size(); i++) {
s0__PropertyReplyList *plist = soap_new_s0__PropertyReplyList( soap, -1);
std::string *path;
if ( s0__GetProperties->ItemIDs[i]->ItemPath)
path = s0__GetProperties->ItemIDs[i]->ItemPath;
else
path = s0__GetProperties->ItemPath;
if ( path) {
plist->ItemPath = soap_new_std__string( soap, -1);
plist->ItemPath->assign( cnv_utf8_to_iso8859( (char *)path, path->size()+1));
}
plist->ItemName = soap_new_std__string( soap, -1);
plist->ItemName->assign(
cnv_utf8_to_iso8859( (char *)s0__GetProperties->ItemIDs[i]->ItemName->c_str(),
s0__GetProperties->ItemIDs[i]->ItemName->size()+1));
if ( path) {
strcpy( iname, path->c_str());
strcat( iname, s0__GetProperties->ItemIDs[i]->ItemName->c_str());
}
else
strcpy( iname, s0__GetProperties->ItemIDs[i]->ItemName->c_str());
sts = gdh_NameToAttrref( pwr_cNOid, cnv_utf8_to_iso8859( iname, strlen(iname)+1), &aref);
if ( EVEN(sts)) {
opcsrv_returnerror( soap, s0__GetPropertiesResponse->Errors, &plist->ResultID,
opc_eResultCode_E_UNKNOWNITEMNAME, 0);
s0__GetPropertiesResponse->PropertyLists.push_back( plist);
continue;
}
if ( aref.Flags.b.Object || aref.Flags.b.ObjectAttr) {
// This is an object
sts = gdh_GetAttrRefTid( &aref, &cid);
if ( EVEN(sts)) {
opcsrv_returnerror( soap, s0__GetPropertiesResponse->Errors, &plist->ResultID,
opc_eResultCode_E_FAIL, 0);
s0__GetPropertiesResponse->PropertyLists.push_back( plist);
continue;
}
if ( !cdh_tidIsCid( cid)) {
opcsrv_returnerror( soap, s0__GetPropertiesResponse->Errors, &plist->ResultID,
opc_eResultCode_E_FAIL, 0);
s0__GetPropertiesResponse->PropertyLists.push_back( plist);
continue;
}
opcsrv_get_properties( soap, false, cid, 0, &aref,
property_mask, 0,
plist->Properties);
}
else {
// Get the object attrref and class for this attribute
if ( !( aname = strrchr( iname, '.'))) {
opcsrv_returnerror( soap, s0__GetPropertiesResponse->Errors, &plist->ResultID,
opc_eResultCode_E_INVALIDITEMNAME, 0);
s0__GetPropertiesResponse->PropertyLists.push_back( plist);
continue;
}
aname++;
sts = gdh_AttrArefToObjectAref( &aref, &paref);
if ( EVEN(sts)) {
opcsrv_returnerror( soap, s0__GetPropertiesResponse->Errors, &plist->ResultID,
opc_eResultCode_E_FAIL, 0);
s0__GetPropertiesResponse->PropertyLists.push_back( plist);
continue;
}
sts = gdh_GetAttrRefTid( &paref, &cid);
if ( EVEN(sts)) {
opcsrv_returnerror( soap, s0__GetPropertiesResponse->Errors, &plist->ResultID,
opc_eResultCode_E_FAIL, 0);
s0__GetPropertiesResponse->PropertyLists.push_back( plist);
continue;
}
// Get body definition
sts = gdh_GetObjectBodyDef( cid, &bd, &rows, pwr_cNOid);
if ( EVEN(sts)) {
opcsrv_returnerror( soap, s0__GetPropertiesResponse->Errors, &plist->ResultID,
opc_eResultCode_E_FAIL, 0);
s0__GetPropertiesResponse->PropertyLists.push_back( plist);
continue;
}
int bd_idx = -1;
for ( int i = 0; i < rows; i++) {
if ( cdh_NoCaseStrcmp( aname, bd[i].attrName) == 0) {
bd_idx = i;
break;
}
}
if ( bd_idx == -1) {
free( (char *)bd);
opcsrv_returnerror( soap, s0__GetPropertiesResponse->Errors, &plist->ResultID,
opc_eResultCode_E_FAIL, 0);
s0__GetPropertiesResponse->PropertyLists.push_back( plist);
continue;
}
opcsrv_get_properties( soap, true, cid, &paref, &aref,
property_mask, &bd[bd_idx],
plist->Properties);
free( (char *)bd);
}
s0__GetPropertiesResponse->PropertyLists.push_back( plist);
}
return SOAP_OK;
}
......@@ -70,8 +70,8 @@ static pwr_tStatus IoAgentClose( io_tCtx ctx,
}
#else
static pwr_tStatus IoAgentInit( io_tCtx ctx, io_sAgent *ap) { return 0;}
static pwr_tStatus IoAgentClose( io_tCtx ctx, io_sAgent *ap) { return 0;}
static pwr_tStatus IoAgentInit( io_tCtx ctx, io_sAgent *ap) { return IO__RELEASEBUILD;}
static pwr_tStatus IoAgentClose( io_tCtx ctx, io_sAgent *ap) { return IO__RELEASEBUILD;}
#endif
/* Every method should be registred here. */
......
......@@ -298,10 +298,10 @@ static pwr_tStatus IoCardWrite( io_tCtx ctx,
}
#else
static pwr_tStatus IoCardInit( io_tCtx ctx,io_sAgent *ap,io_sRack *rp,io_sCard *cp) {return 0;}
static pwr_tStatus IoCardClose( io_tCtx ctx,io_sAgent *ap,io_sRack *rp,io_sCard *cp) {return 0;}
static pwr_tStatus IoCardRead( io_tCtx ctx,io_sAgent *ap,io_sRack *rp,io_sCard *cp) {return 0;}
static pwr_tStatus IoCardWrite( io_tCtx ctx,io_sAgent *ap,io_sRack *rp,io_sCard *cp) {return 0;}
static pwr_tStatus IoCardInit( io_tCtx ctx,io_sAgent *ap,io_sRack *rp,io_sCard *cp) {return IO__RELEASEBUILD;}
static pwr_tStatus IoCardClose( io_tCtx ctx,io_sAgent *ap,io_sRack *rp,io_sCard *cp) {return IO__RELEASEBUILD;}
static pwr_tStatus IoCardRead( io_tCtx ctx,io_sAgent *ap,io_sRack *rp,io_sCard *cp) {return IO__RELEASEBUILD;}
static pwr_tStatus IoCardWrite( io_tCtx ctx,io_sAgent *ap,io_sRack *rp,io_sCard *cp) {return IO__RELEASEBUILD;}
#endif
/* Every method should be registred here. */
......
#060227 cs - Changelog created.
070528 cs logg Env variable allowed in remotelogg filename.
071115 rk tcpip Fixed several bugs when acting as server.
101216 rk wmq Added functionality for handling Websphere MQ as remote node.
......@@ -4,7 +4,8 @@ link_rule_mk := 1
ifeq ($(pwre_conf_mq),1)
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) \
$(pwre_conf_libdir) $(pwre_conf_libpwrremote) $(pwre_conf_libpwrrt) $(pwre_conf_lib)
$(pwre_conf_libdir) $(pwre_conf_libpwrremote) $(pwre_conf_libpwrrt) \
$(pwre_conf_libmq) $(pwre_conf_lib)
else
link = echo "Mq not installed"
endif
......
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
ifndef link_rule_mk
link_rule_mk := 1
ifeq ($(PWRE_CONF_WMQ),1)
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) \
$(pwre_conf_libdir) $(pwre_conf_libpwrremote) $(pwre_conf_libpwrrt) \
$(pwre_conf_libwmq) $(pwre_conf_lib)
else
link = echo "WMQ not installed"
endif
endif
/*
* Proview $Id: rs_remote_mq.c,v 1.3 2006-04-24 13:22:23 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
* ===============
* P r o v i e w
* ===============
**************************************************************************
*
* Filename: rs_remote_wmq.c
*
* Description: Remote transport process for Websphere Message Queue
* as a client
* For further information, please refer to Webspherer MQ
* documentation.
*
* Change log: 2010-12-08, Robert Karlsson
* First version introduced in 4.8.0-2
*
*
**************************************************************************
**************************************************************************/
/*_Include files_________________________________________________________*/
#if defined PWRE_CONF_WMQ
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "pwr_class.h"
#include "pwr_systemclasses.h"
#include "rt_gdh.h"
#include "co_time.h"
#include "co_cdh.h"
#include "rt_errh.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "rt_pwr_msg.h"
#include "rt_aproc.h"
#include "remote.h"
#include "remote_remtrans_utils.h"
// Message Q include files
#include <cmqc.h>
#define TIME_INCR 0.02
#define debug 0
remnode_item rn;
pwr_sClass_RemnodeWMQ *rn_wmq;
char mgr_name[MQ_Q_MGR_NAME_LENGTH];
MQHCONN Hconn;
MQOD RcvObjDesc = {MQOD_DEFAULT};
MQLONG RcvOpenOptions; // options that control the open-call
MQOD SndObjDesc = {MQOD_DEFAULT};
MQLONG SndOpenOptions; // options that control the open-call
char rcv_que_name[MQ_Q_NAME_LENGTH];
char snd_que_name[MQ_Q_NAME_LENGTH];
MQHOBJ RcvHobj; // object handle
MQHOBJ SndHobj; // object handle
/*************************************************************************
**************************************************************************
*
* RemoteSleep
*
**************************************************************************
**************************************************************************/
void RemoteSleep(float time)
{
struct timespec rqtp, rmtp;
rqtp.tv_sec = 0;
rqtp.tv_nsec = (long int) (time * 1000000000);
nanosleep(&rqtp, &rmtp);
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : wmq_receive
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Invoked when a MQ message is received.
*
**************************************************************************
**************************************************************************/
unsigned int wmq_receive()
{
MQLONG CompCode;
MQLONG Reason;
MQMD MsgDesc = {MQMD_DEFAULT};
MQLONG DataLength;
MQCHAR Buffer[16384];
MQGMO GetMsgOpts = {MQGMO_DEFAULT};
MQLONG BufferLength = sizeof(Buffer);
unsigned int sts;
char search_remtrans;
remtrans_item *remtrans;
/* Set options */
GetMsgOpts.Options = MQGMO_NO_WAIT + MQGMO_ACCEPT_TRUNCATED_MSG;
MsgDesc.Encoding = MQENC_NATIVE;
MsgDesc.CodedCharSetId = MQCCSI_Q_MGR;
/* Get message */
MQGET(Hconn, RcvHobj, &MsgDesc, &GetMsgOpts, BufferLength, Buffer, &DataLength, &CompCode, &Reason);
if (CompCode != MQCC_FAILED) {
if (debug) printf("Received message %d\n", (int) DataLength);
search_remtrans = true;
remtrans = rn.remtrans;
while(remtrans && search_remtrans) {
if ((strncmp(remtrans->objp->TransName, (char *) MsgDesc.MsgId, MQ_MSG_ID_LENGTH) == 0) &&
(remtrans->objp->Direction == REMTRANS_IN)) {
search_remtrans = false;
sts = RemTrans_Receive(remtrans, (char *) &Buffer, DataLength);
if (sts != STATUS_OK && sts != STATUS_BUFF)
errh_Error("Error from RemTrans_Receive, status %d", sts, 0);
break;
}
remtrans = (remtrans_item *) remtrans->next;
}
if (search_remtrans) {
rn_wmq->ErrCount++;
errh_Info("No remtrans for received message, msgid %s", MsgDesc.MsgId, 0);
}
}
else if (Reason != MQRC_NO_MSG_AVAILABLE) {
rn_wmq->ErrCount++;
errh_Error("Receive failed, reason %d", Reason, 0);
}
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : wmq_send
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a MQ message to Remote node
*
**************************************************************************
**************************************************************************/
unsigned int wmq_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size)
{
MQLONG CompCode;
MQLONG Reason;
MQPMO pmo = {MQPMO_DEFAULT}; /* put message options */
// MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */
MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */
MQLONG messlen; /* message length */
pmo.Options = MQPMO_NO_SYNCPOINT | MQPMO_FAIL_IF_QUIESCING;
// pmo.Options |= MQPMO_NEW_MSG_ID;
// pmo.Options |= MQPMO_NEW_CORREL_ID;
strncpy((char *) md.MsgId, remtrans->TransName, MQ_MSG_ID_LENGTH) ;
memcpy(md.CorrelId, MQCI_NONE, sizeof(md.CorrelId));
if ((remtrans->Address[0] <= MQPER_PERSISTENCE_AS_Q_DEF) &&
(remtrans->Address[0] >= MQPER_NOT_PERSISTENT))
md.Persistence = remtrans->Address[0];
else
md.Persistence = MQPER_NOT_PERSISTENT; // | MQPRE_NOT_PERSISTENT
messlen = buf_size;
MQPUT(Hconn, /* connection handle */
SndHobj, /* object handle */
&md, /* message descriptor */
&pmo, /* default options (datagram) */
messlen, /* message length */
buf, /* message buffer */
&CompCode, /* completion code */
&Reason); /* reason code */
/* report reason, if any */
if (Reason != MQRC_NONE) {
remtrans->ErrCount++;
errh_Error("Send failed, msgid %s, Reason %d", md.MsgId, Reason, 0);
printf("MQPUT ended with reason code %d\n", (int) Reason);
}
// if (debug) printf("Sent message %d\n", (int) mq_sts);
return( STATUS_OK );
}
/*************************************************************************
**************************************************************************
*
* Main
*
**************************************************************************
**************************************************************************/
int main(int argc, char *argv[])
{
remtrans_item *remtrans;
unsigned char id[32];
unsigned char pname[32];
pwr_tStatus sts;
int i;
float time_since_scan = 0.0;
MQLONG CompCode;
MQLONG Reason;
/* Read arg number 2, should be id for this instance and id is our queue number */
if (argc >= 2)
strcpy((char *)id, argv[1]);
else
strcpy((char *)id, "0");
/* Build process name with id */
sprintf((char *) pname, "rs_remwmq_%s", id);
/* Init of errh */
errh_Init((char *) pname, errh_eAnix_remote);
errh_SetStatus(PWR__SRVSTARTUP);
/* Init of gdh */
if (debug) printf("Before gdh_init\n");
sts = gdh_Init((char *) pname);
if ( EVEN(sts)) {
errh_Fatal("gdh_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Arg number 3 should be my remnodes objid in string representation,
read it, convert to real objid and store in remnode_item */
sts = 0;
if (argc >= 3) sts = cdh_StringToObjid(argv[2], &rn.objid);
if ( EVEN(sts)) {
errh_Fatal("cdh_StringToObjid, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Get pointer to RemnodeWMQ object and store locally */
sts = gdh_ObjidToPointer(rn.objid, (pwr_tAddress *) &rn_wmq);
if ( EVEN(sts)) {
errh_Fatal("cdh_ObjidToPointer, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Initialize some internal data and make standard remtrans init */
rn.next = NULL;
rn.local = NULL; // We dont use local structure since we only have one remnode
rn_wmq->ErrCount = 0;
if (debug) printf("Before remtrans_init\n");
sts = RemTrans_Init(&rn);
if ( EVEN(sts)) {
errh_Fatal("RemTrans_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Store remtrans objects objid in remnode_mq object */
remtrans = rn.remtrans;
i = 0;
while(remtrans) {
rn_wmq->RemTransObjects[i++] = remtrans->objid;
if ( i >= (int)(sizeof(rn_wmq->RemTransObjects) / sizeof(rn_wmq->RemTransObjects[0])))
break;
remtrans = (remtrans_item *) remtrans->next;
}
/* Variables for MQ calls */
strncpy(mgr_name, rn_wmq->QueueManager, MQ_Q_MGR_NAME_LENGTH);
// strncpy(mgr_name, "hejsanqqq", sizeof(MQ_Q_MGR_NAME_LENGTH));
/* Connect to specified queue manager */
MQCONN(mgr_name, &Hconn, &CompCode, &Reason);
if ((CompCode != MQCC_OK) | (Reason != MQRC_NONE)) {
errh_Fatal("MQCONN failed, queue mgr: %s, Code: %d, Reason: %d", mgr_name, CompCode, Reason);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
/* Open queue for receiving messages */
strncpy(rcv_que_name, rn_wmq->RcvQueue, MQ_Q_NAME_LENGTH);
// strncpy(rcv_que_name, "hejsanqqq", sizeof(MQ_Q_NAME_LENGTH));
/* Initialize object descriptor control block */
strncpy(RcvObjDesc.ObjectName, rcv_que_name, MQ_Q_NAME_LENGTH);
/* open queue for input but not if MQM stopping */
RcvOpenOptions = MQOO_INPUT_AS_Q_DEF | MQOO_FAIL_IF_QUIESCING;
/* Open queue */
MQOPEN(Hconn, &RcvObjDesc, RcvOpenOptions, &RcvHobj, &CompCode, &Reason);
if ((CompCode != MQCC_OK) | (Reason != MQRC_NONE)) {
errh_Fatal("MQOPEN failed, queue: %s, Code: %d, Reason: %d", rcv_que_name, CompCode, Reason);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
/* Open queue for sending messages */
strncpy(snd_que_name, rn_wmq->SndQueue, MQ_Q_NAME_LENGTH);
// strncpy(snd_que_name, "hejsanqqq", sizeof(MQ_Q_NAME_LENGTH));
/* Initialize object descriptor control block */
strncpy(SndObjDesc.ObjectName, snd_que_name, MQ_Q_NAME_LENGTH);
/* open queue for output but not if MQM stopping */
SndOpenOptions = MQOO_OUTPUT | MQOO_FAIL_IF_QUIESCING;
MQOPEN(Hconn, &SndObjDesc, SndOpenOptions, &SndHobj, &CompCode, &Reason);
if ((CompCode != MQCC_OK) | (Reason != MQRC_NONE)) {
errh_Fatal("MQOPEN failed, queue: %s, Code: %d, Reason: %d", snd_que_name, CompCode, Reason);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
errh_SetStatus(PWR__SRUN);
/* Set (re)start time in remnode object */
time_GetTime(&rn_wmq->RestartTime);
/* Loop forever */
while (!doomsday) {
if (rn_wmq->Disable == 1) {
errh_Fatal("Disabled, exiting");
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
aproc_TimeStamp(TIME_INCR, 5);
RemoteSleep(TIME_INCR);
time_since_scan += TIME_INCR;
sts = wmq_receive();
if (time_since_scan >= rn_wmq->ScanTime) {
sts = RemTrans_Cyclic(&rn, &wmq_send);
time_since_scan = 0.0;
}
}
}
#else
#include <stdio.h>
int main()
{
printf( "Remote WMQ not built for this release\n");
return 0;
}
#endif
......@@ -43,6 +43,7 @@
* 040303 J Nylund ndrat till omgivningsvariabel
* i skvgarna till exe-filerna
* 040422 C Jurstrand 4.0.0
* 101209 R Karlsson Adderat std fr Websphere MQ
*
* Description:
* Start and control of transportprocesses for remote communication
......@@ -111,6 +112,7 @@ static void AddTransports()
pwr_tObjid objid;
pwr_tAddress objref;
pwr_tStatus sts;
pwr_tUInt32 id = 1;
/* Init transport (process) counter */
tpcount = 0;
......@@ -118,6 +120,30 @@ static void AddTransports()
/* Initialize transport vector with 0's */
memset(&tp, 0, sizeof(tp));
/* Get and configure all WMQ remnodes, one process for each remnode */
sts = gdh_GetClassList (pwr_cClass_RemnodeWMQ, &objid);
while ( ODD(sts))
{
sts = gdh_ObjidToPointer(objid, &objref);
sprintf(tp[tpcount].path, "rs_remote_wmq");
tp[tpcount].id = id++;
tp[tpcount].disable = &((pwr_sClass_RemnodeWMQ *) objref)->Disable;
tp[tpcount].restart_limit = &((pwr_sClass_RemnodeWMQ *) objref)->RestartLimit;
tp[tpcount].restarts = &((pwr_sClass_RemnodeWMQ *) objref)->RestartCount;
((pwr_sClass_RemnodeWMQ *) objref)->RestartCount = 0;
tp[tpcount].objid = objid;
tp[tpcount].objref = objref;
tp[tpcount].classid = pwr_cClass_RemnodeWMQ;
tp[tpcount].cpid = -1;
tp[tpcount].first = true;
remcfgp->RemNodeObjects[tpcount] = objid;
tpcount++;
sts = gdh_GetNextObject (objid, &objid);
}
/* Get and configure all MQ remnodes, one process for each remnode */
sts = gdh_GetClassList (pwr_cClass_RemnodeMQ, &objid);
......
!
! Proview $Id: remote_c_remnodemq.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remnodewmq.wb_load -- Defines the class RemnodeWMQ.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures communication through a message queue using Webspere MQ.
! Configures communication through a message queue using Websphere MQ as a client.
! All regarding Server, channel, queue manager and queues to connect to is configured
! in the RemonodeWMQ-object.
! Configurations for the different messages is configured in the RemtTrans-object that define
! each in- and outgoing message. For each RemTrans-message the following can be configured:
!
! TransName - a string that defines the MsgId (message identity of the message).
! Address[0] - defines whether the message should be sent as a persistent message or not.
! 1 means that the message will be sent as a persistent message. 0 not.
!
! @b Object graph
! @image orm_remnodewmq_og.gif
!
! @b See also
! @classlink RemoteConfig pwrp_remoteconfig.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object RemnodeWMQ $ClassDef 33
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemnodeWMQ"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Process priority for the transport process. For future use.
!*/
Object Prio $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! Name of Queue Manager to connect to.
! Server to connect to is defined by enviroment variable MQSERVER.
! export MQSERVER=<ChannelName>/<TransportType>/<ConnectionName>[(port)]
! For example:
! export MQSERVER=CHANNEL1/TCP/192.168.40.20(2020)
! The port is by default 1414 and will be used if no port is given.
!*/
Object QueueManager $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Name of WMQ queue for all incoming messages.
!*/
Object RcvQueue $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Name of WMQ queue for all outgoing messages.
!*/
Object SndQueue $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Scantime in seconds for outgoing RemTrans messages.
! Dynamic change is possible.
!*/
Object ScanTime $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute tells the remote handler not to start
! or restart the process that handles this remote node. If the transport process
! is running while the attribute is set it will terminate. This can be used to force
! a restart of the process.
!*/
Object Disable $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! This attribute shows how many times the remote handler has restarted the
! transport process that handles this remnode.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartCount $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! The restart limit tells the remote handler how many times the transport process
! that handle this remnode can be restarted.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartLimit $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! The restart time is set by the transport process at startup and therefore
! shows the latest (re)starttime.
!*/
Object RestartTime $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$Time"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Error counter.
!*/
Object ErrCount $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Type of remnode. Used in the RemoteConfig classgraph.
!*/
Object Id $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$String8"
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Contains the objid for the RemTrans objects for this remnode.
! The objid's are inserted by the remote process.
!*/
Object RemTransObjects $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 25
EndBody
EndObject
EndObject
Object Template RemnodeWMQ
Body RtBody
Attr Prio = 15
Attr Disable = 0
Attr RestartCount = 0
Attr RestartLimit = 100
Attr ScanTime = 0.1
Attr Id = "WMQ"
EndBody
EndObject
EndObject
EndSObject
......@@ -1730,7 +1730,7 @@ This file (if it exists) will be used as the link options when I build the plc-p
Proview by default links against some libraries and object-files. If you have your own
opt-file you need to include these. A default opt-file would look like:
<c>$pwr_obj/rt_io_user.o -lpwr_rt -lpwr_usbio_dummy
<c>$pwr_obj/rt_io_user.o -lpwr_rt -lpwr_usbio_dummy -lpwr_usb_dummy -lpwr_pnak_dummy
Add your own libraries at will. The syntax to use is the sytax for ld (The GNU linker). Proview
will create a template option file .opt_template that can be renamed to .opt and used as a template.
......@@ -2196,7 +2196,8 @@ plc_'nodename'_'qbus'.opt, for example
The following line is inserted into this file
<c>$pwr_obj/rt_io_user.o $pwrp_obj/ra_myfunction.o -lpwr_rt -lpwr_usbio_dummy
<c>$pwr_obj/rt_io_user.o $pwrp_obj/ra_myfunction.o -lpwr_rt -lpwr_usbio_dummy \
<c>-lpwr_usb_dummy -lpwr_pnak_dummmy
We kan now build the node and startup Proview runtime.
......@@ -6830,7 +6831,7 @@ e.g. plc_mynode_0999.opt. The content of the file is input to the linker, ld, an
add the modules of the plc-code. In the example below these modules are placed in the archive
$pwrp_lib/libpwrp.a
<c>$pwr_obj/rt_io_user.o -lpwrp
<c>$pwr_obj/rt_io_user.o -lpwrp -lpwr_rt -lpwr_usbio_dummy -lpwr_usb_dummy -lpwr_pnak_dummy
......
......@@ -1718,7 +1718,7 @@ Den
länkningen av plc-programmet. Några bibliotek och objektsmoduler måste finnas med, och
en default option-fil ska se ut så här:
<c>$pwr_obj/rt_io_user.o -lpwr_rt -lpwr_usbio_dummy
<c>$pwr_obj/rt_io_user.o -lpwr_rt -lpwr_usbio_dummy -lpwr_usb_dummy -lpwr_pnak_dummy
Till detta adderas de bibliotek och moduler som behövs. Syntaxen är den som gäller för ld
(The GNU linker). Proview genererar en template option-fil .opt_template som kan användas som
......@@ -2176,7 +2176,8 @@ plc_'nodename'_'qbus'.opt, t ex
I denna läggs följande rad in
<c>$pwr_obj/rt_io_user.o $pwrp_obj/ra_myfunction.o -lpwr_rt -lpwr_usbio_dummy
<c>$pwr_obj/rt_io_user.o $pwrp_obj/ra_myfunction.o -lpwr_rt -lpwr_usbio_dummy -lpwr_usb_dummy \
<c> -lpwr_pnak_dummy
Vi kan nu bygga noden och starta Proview runtime.
......@@ -6744,7 +6745,7 @@ plc_mynode_0999.opt. Inneh
lägger även in modulerna för plc-koden. I exemplet nedan antas att dessa moduler ligger i
arkivet $pwrp_lib/libpwrp.a.
<c>$pwr_obj/rt_io_user.o -lpwrp
<c>$pwr_obj/rt_io_user.o -lpwrp -lpwr_rt -lpwr_usbio_dummy -lpwr_usb_dummy -lpwr_pnak_dummy
</topic>
......
......@@ -2621,6 +2621,7 @@ gdh_SetObjectInfoAttrref (
}
/* Try remote. */
sts = GDH__SUCCESS;
vp = pool_Address(NULL, gdbroot->pool, ap->op->l.vr);
np = pool_Address(NULL, gdbroot->pool, vp->l.nr);
......@@ -2656,6 +2657,8 @@ gdh_SetObjectInfoAttrref (
rarp = ndc_NarefToRaref(&sts, ap, arp, ccp, &ridx, &raref, &equal, NULL, ccpLocked, vp, np);
}
else
equal = ap->op->u.c.flags.b.classEqual;
break;
......
......@@ -101,6 +101,8 @@ replaced <Symbol is replaced> /info
normal <Normal operating state> /succ
initfail <Initialization failed> /error
nodevice <Device not found> /error
releasebuild <I/O system is not built with this release> /error
dummybuild <Archive for I/O system is not linked with this executable> /error
.end
......@@ -111,6 +111,10 @@ pwre_config_check_lib()
conf_libmotif=$conf_libmotif" -l${lib%.*}"
elif test $4 == "wb"; then
conf_libwb=$conf_libwb" -l${lib%.*}"
elif test $4 == "mq"; then
conf_libmq=$conf_libmq" -l${lib%.*}"
elif test $4 == "wmq"; then
conf_libwmq=$conf_libwmq" -l${lib%.*}"
else
conf_lib=$conf_lib" -l${lib%.*}"
fi
......@@ -200,6 +204,8 @@ dhw=`eval echo ${pwre_hw} | tr [:lower:] [:upper:]`
conf_cc_define="-D$dos=1 -D$dhw=1 -DOS=${pwre_os:3} -DHW=${pwre_hw:3} -D_${dos:3}"
conf_lib=""
conf_libwb=""
conf_libmq=""
conf_libwmq=""
conf_libgtk=""
conf_libmotif=""
conf_libdir=""
......@@ -284,6 +290,8 @@ if test $pwre_hw == "hw_arm"; then
echo "export pwre_conf_libpwrsev=\"-lpwr_sev\"" >> $cfile
echo "export pwre_conf_lib=\"-lpthread -lm -lrt -lcrypt\"" >> $cfile
echo "export pwre_conf_libwb=\"$conf_libwb\"" >> $cfile
echo "export pwre_conf_libmq=\"$conf_libmq\"" >> $cfile
echo "export pwre_conf_libwmq=\"$conf_libwmq\"" >> $cfile
echo "export pwre_conf_libgtk=\"$conf_libgtk\"" >> $cfile
echo "export pwre_conf_libmotif=\"$conf_libmotif\"" >> $cfile
echo "export pwre_conf_libdir=\"$conf_libdir\"" >> $cfile
......@@ -306,7 +314,8 @@ else
pwre_config_check_lib libz LIBZ lib lib 0 /usr/lib/libz.so:/usr/lib/libz.a
pwre_config_check_lib libcrypt LIBCRYPT lib lib 0 /usr/lib/libcrypt.so:/usr/lib/libcrypt.a
pwre_config_check_lib mysql MYSQL lib lib 1 /usr/lib/libmysqlclient.so:/usr/lib/mysql/libmysqlclient.so
pwre_config_check_lib mq MQ lib lib 1 /usr/lib/libdmq.so
pwre_config_check_lib mq MQ lib mq 1 /usr/lib/libdmq.so
pwre_config_check_lib wmq WMQ lib wmq 1 /usr/lib/libmqic.so
pwre_config_check_lib libpnioif PNAK lib lib 1 /usr/lib/libpnioif.a:/usr/local/lib/libpnioif.a
pwre_config_check_lib libusb LIBUSB lib lib 1 /usr/lib/libusb-1.0.so
pwre_config_check_lib librt LIBRT lib lib 0 /usr/lib/librt.so:/usr/lib/librt.a
......@@ -319,6 +328,7 @@ else
pwre_config_check_include gtk GTK 1 /usr/local/include/gtk-2.0/gtk.h:/usr/local/include/gtk-2.0/gtk/gtk.h:/usr/include/gtk-2.0/gtk/gtk.h
pwre_config_check_include jni JNI 1 $jdk/include/jni.h
pwre_config_check_include jni JNI 0 $jdk/include/linux/jni_md.h
pwre_config_check_include wmq WMQ 1 /opt/mqm/inc/cmqc.h
export pwre_conf_alsa=1
......@@ -355,6 +365,8 @@ else
echo "export pwre_conf_libpwrsev=\"-lpwr_sev\"" >> $cfile
echo "export pwre_conf_lib=\"$conf_lib\"" >> $cfile
echo "export pwre_conf_libwb=\"$conf_libwb\"" >> $cfile
echo "export pwre_conf_libmq=\"$conf_libmq\"" >> $cfile
echo "export pwre_conf_libwmq=\"$conf_libwmq\"" >> $cfile
echo "export pwre_conf_libgtk=\"$conf_libgtk\"" >> $cfile
echo "export pwre_conf_libmotif=\"$conf_libmotif\"" >> $cfile
echo "export pwre_conf_libdir=\"$conf_libdir\"" >> $cfile
......
......@@ -182,7 +182,7 @@ palette NavigatorPalette
menu Siemens
{
class Siemens_Motor_1LA
class Siemens_G120_Tgm1
class Sinamics_G120_Tgm1
}
menu Suco
{
......@@ -338,6 +338,7 @@ palette NavigatorPalette
class RemnodeALCM
class RemnodeModbus
class RemnodeMQ
class RemnodeWMQ
class RemnodeSerial
class RemnodeTCP
class RemnodeUDP
......
#define ge_bitmap_limitswitch248_width 16
#define ge_bitmap_limitswitch248_height 13
static unsigned char ge_bitmap_limitswitch248_bits[] = {
0xe0, 0x03, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02,
0x20, 0x02, 0xe0, 0x03, 0x80, 0x00, 0x40, 0x00, 0x30, 0x00, 0x30, 0x00,
0x00, 0x00};
0! DefaultWidth 144
0! DefaultHeight 288
1
100 144.012
135 144.012
101 20
102 -232
103 -271
104 28.0481
136 28.0481
105 100
106 -45
107 -52
108 0.9
109 0
110 2
111 0
116 0
117 0
118 131
119 118
120 1
121 Claes context
122 0
126 0.1
127 0.1
128 0
129 0.3
130 1.5
131 0.8
132 3
133 2
137 4510
138 3
139 2
134
22
2200 1
2201 15
2202 pwr_limitswitch
2203 300
2205 0
2204
2206 0
2207
2208
2209 0
2210 0
2211 1
2212 2
2213 4
2214
pwrp_pop:
pwrp_exe:
ssab_exe:
pwr_exe:
2215 32768
2236 0
2216 0
2221 0
2237 0
2238 0
2239 0
2240 0
2241 0
2242 0
2217 0
2218 0
2219 1
2220
2230 0
2231 0
2222 pwr_limitswitch__p2
2223 1
2224 0.5
2232 0.5
2225 0.5
2226 0
2227
2228 0
2229 0
2233 1
2234 1
2235 0
2243 0
2245 0
2244
1
100 1
101 1
102 33619964
103 0
99
99
123
2
99
124
2
99
125
2
26
2604 O6
2600 0.525089
2601 0.191637
2602 1.76237
2603 1.28328
2605
25
2500 0
2501 1
2503 1
2504 0
2502
2
7
700 0.533452
701 1.82091
99
7
700 0.3
701 2.3
99
7
700 0.2
701 2.2
99
7
700 0.333452
701 1.82091
99
7
700 0.533452
701 1.82091
99
99
99
2608 0
2609 36
2610 36
2611 1
2616 1
2614 5
2617 2
2615 0
2618 1
2607 0
2606
2612
28
2800 1
2801 0
2802 -0.00836311
2803 0
2804 1
2805 -0.537634
2806 0
99
2613 0
2619 0
2620 0
2621 1
2622 0
2623 0
2624 4
2625 0
99
19
1904 O11
1900 0.9
1901 0.1
1902 1.3
1903 0
1908 0
1909 38
1910 38
1911 1
1915 0
1913 17
1916 2
1914 0
1918 0
1919 0
1920 0
1917 0
1921 0
1922 4
1923 0
1907 0
1906
1905
5
500 0
501 1
504 1
505 1
502
7
700 0.1
701 0.5
99
503
7
700 0.9
701 1.8
99
99
1912
28
2800 1
2801 0
2802 0
2803 0
2804 1
2805 -0.5
2806 0
99
99
24
2404 O13
2400 0.4
2401 0
2402 2
2403 1.6
2408 0
2409 0
2410 0
2411 1
2415 0
2413 5
2416 2
2414 0
2417 1
2421 1
2418 0
2419 4
2420 1
2422 0
2407 0
2406
2405
8
802 0
803 1
800 0
801 360
806 1
804
7
700 0
701 2.1
99
805
7
700 0.4
701 2.5
99
99
2412
28
2800 1
2801 0
2802 0
2803 0
2804 1
2805 -0.5
2806 0
99
99
21
2104 O14
2100 0.8
2101 0.2
2102 0.3
2103 -0.3
2105
8
802 0
803 2
800 0
801 360
806 0
804
7
700 -0.3
701 -0.3
99
805
7
700 0.3
701 0.3
99
99
2106
12
1200 0
1201 4
1202
7
700 0.5
701 0
99
1203
1204 0
1205
28
2800 1
2801 0
2802 0
2803 0
2804 1
2805 0
2806 0
99
99
99
99
99
123
2
3
300 pwr_limitswitch
301
2
26
2604 O6
2600 0.525089
2601 0.191637
2602 1.76237
2603 1.28328
2605
25
2500 0
2501 1
2503 1
2504 0
2502
2
7
700 0.533452
701 1.82091
99
7
700 0.3
701 2.3
99
7
700 0.2
701 2.2
99
7
700 0.333452
701 1.82091
99
7
700 0.533452
701 1.82091
99
99
99
2608 0
2609 36
2610 36
2611 1
2616 1
2614 5
2617 2
2615 0
2618 1
2607 0
2606
2612
28
2800 1
2801 0
2802 -0.00836311
2803 0
2804 1
2805 -0.537634
2806 0
99
2613 0
2619 0
2620 0
2621 1
2622 0
2623 0
2624 4
2625 0
99
19
1904 O11
1900 0.9
1901 0.1
1902 1.3
1903 0
1908 0
1909 38
1910 38
1911 1
1915 0
1913 17
1916 2
1914 0
1918 0
1919 0
1920 0
1917 0
1921 0
1922 4
1923 0
1907 0
1906
1905
5
500 0
501 1
504 1
505 1
502
7
700 0.1
701 0.5
99
503
7
700 0.9
701 1.8
99
99
1912
28
2800 1
2801 0
2802 0
2803 0
2804 1
2805 -0.5
2806 0
99
99
24
2404 O13
2400 0.4
2401 0
2402 2
2403 1.6
2408 0
2409 0
2410 0
2411 1
2415 0
2413 5
2416 2
2414 0
2417 1
2421 1
2418 0
2419 4
2420 1
2422 0
2407 0
2406
2405
8
802 0
803 1
800 0
801 360
806 1
804
7
700 0
701 2.1
99
805
7
700 0.4
701 2.5
99
99
2412
28
2800 1
2801 0
2802 0
2803 0
2804 1
2805 -0.5
2806 0
99
99
12
1200 0
1201 4
1202
7
700 0.5
701 0
99
1203
1204 0
1205
28
2800 1
2801 0
2802 0
2803 0
2804 1
2805 0
2806 0
99
99
99
302 0
305 0
306
307
304 0
303
308 32768
321 0
309 0
313 0
322 0
323 0
324 0
325 0
326 0
327 0
310 0
311 0
312
314 pwr_limitswitch__p2
315 1
316 1
317 0
318 2
319 0
320 1
328 0
329
1
100 1
101 1
102 33619964
103 0
99
99
99
99
0! DefaultWidth 144
0! DefaultHeight 288
1
100 144.012
135 144.012
101 20
102 -232
103 -271
104 28.0481
136 28.0481
105 100
106 -45
107 -52
108 1
109 0.1
110 2
111 -1.66533e-15
116 0
117 0
118 131
119 118
120 1
121 Claes context
122 0
126 0.1
127 0.1
128 0
129 0.3
130 1.5
131 0.8
132 3
133 2
137 4510
138 3
139 2
134
22
2200 0
2201 13
2202 pwr_limitswitch__p2
2203 300
2205 0
2204
2206 0
2207
2208
2209 0
2210 0
2211 1
2212 2
2213 4
2214
pwrp_pop:
pwrp_exe:
ssab_exe:
pwr_exe:
2215 32768
2236 0
2216 0
2221 0
2237 0
2238 0
2239 0
2240 0
2241 0
2242 0
2217 0
2218 0
2219 1
2220
2230 0
2231 0
2222
2223 1
2224 0.5
2232 0.5
2225 0.5
2226 0
2227
2228 0
2229 0
2233 1
2234 1
2235 0
2243 0
2245 0
2244
1
100 1
101 1
102 33619964
103 0
99
99
123
2
99
124
2
99
125
2
26
2604 O6
2600 0.764011
2601 0.430559
2602 1.73747
2603 1.25838
2605
25
2500 0
2501 1
2503 1
2504 0
2502
2
7
700 0.533452
701 1.82091
99
7
700 0.3
701 2.3
99
7
700 0.2
701 2.2
99
7
700 0.333452
701 1.82091
99
7
700 0.533452
701 1.82091
99
99
99
2608 0
2609 36
2610 36
2611 1
2616 1
2614 5
2617 2
2615 0
2618 1
2607 0
2606
2612
28
2800 -1
2801 -0
2802 0.964011
2803 0
2804 1
2805 -0.56253
2806 0
99
2613 0
2619 0
2620 0
2621 1
2622 0
2623 0
2624 4
2625 0
99
19
1904 O10
1900 0.9
1901 0.1
1902 1.3
1903 -1.66533e-15
1908 0
1909 38
1910 38
1911 1
1915 0
1913 17
1916 2
1914 0
1918 0
1919 0
1920 0
1917 0
1921 0
1922 4
1923 0
1907 0
1906
1905
5
500 0
501 1
504 1
505 1
502
7
700 0.1
701 0.5
99
503
7
700 0.9
701 1.8
99
99
1912
28
2800 1
2801 0
2802 -1.49533e-15
2803 0
2804 1
2805 -0.5
2806 0
99
99
24
2404 O11
2400 1
2401 0.6
2402 2
2403 1.6
2408 0
2409 0
2410 0
2411 1
2415 0
2413 5
2416 2
2414 0
2417 1
2421 1
2418 0
2419 4
2420 1
2422 0
2407 0
2406
2405
8
802 0
803 1
800 0
801 360
806 1
804
7
700 0
701 2.1
99
805
7
700 0.4
701 2.5
99
99
2412
28
2800 1
2801 0
2802 0.6
2803 0
2804 1
2805 -0.5
2806 0
99
99
21
2104 O12
2100 0.8
2101 0.2
2102 0.3
2103 -0.3
2105
8
802 0
803 2
800 0
801 360
806 0
804
7
700 -0.3
701 -0.3
99
805
7
700 0.3
701 0.3
99
99
2106
12
1200 0
1201 4
1202
7
700 0.5
701 0
99
1203
1204 0
1205
28
2800 1
2801 0
2802 -3.43215e-15
2803 0
2804 1
2805 1.32533e-15
2806 0
99
99
99
99
99
123
2
3
300 pwr_limitswitch__p2
301
2
26
2604 O6
2600 0.764011
2601 0.430559
2602 1.73747
2603 1.25838
2605
25
2500 0
2501 1
2503 1
2504 0
2502
2
7
700 0.533452
701 1.82091
99
7
700 0.3
701 2.3
99
7
700 0.2
701 2.2
99
7
700 0.333452
701 1.82091
99
7
700 0.533452
701 1.82091
99
99
99
2608 0
2609 36
2610 36
2611 1
2616 1
2614 5
2617 2
2615 0
2618 1
2607 0
2606
2612
28
2800 -1
2801 -0
2802 0.964011
2803 0
2804 1
2805 -0.56253
2806 0
99
2613 0
2619 0
2620 0
2621 1
2622 0
2623 0
2624 4
2625 0
99
19
1904 O10
1900 0.9
1901 0.1
1902 1.3
1903 -1.66533e-15
1908 0
1909 38
1910 38
1911 1
1915 0
1913 17
1916 2
1914 0
1918 0
1919 0
1920 0
1917 0
1921 0
1922 4
1923 0
1907 0
1906
1905
5
500 0
501 1
504 1
505 1
502
7
700 0.1
701 0.5
99
503
7
700 0.9
701 1.8
99
99
1912
28
2800 1
2801 0
2802 -1.49533e-15
2803 0
2804 1
2805 -0.5
2806 0
99
99
24
2404 O11
2400 1
2401 0.6
2402 2
2403 1.6
2408 0
2409 0
2410 0
2411 1
2415 0
2413 5
2416 2
2414 0
2417 1
2421 1
2418 0
2419 4
2420 1
2422 0
2407 0
2406
2405
8
802 0
803 1
800 0
801 360
806 1
804
7
700 0
701 2.1
99
805
7
700 0.4
701 2.5
99
99
2412
28
2800 1
2801 0
2802 0.6
2803 0
2804 1
2805 -0.5
2806 0
99
99
12
1200 0
1201 4
1202
7
700 0.5
701 0
99
1203
1204 0
1205
28
2800 1
2801 0
2802 -3.43215e-15
2803 0
2804 1
2805 1.32533e-15
2806 0
99
99
99
302 0
305 0
306
307
304 0
303
308 32768
321 0
309 0
313 0
322 0
323 0
324 0
325 0
326 0
327 0
310 0
311 0
312
314
315 1
316 1
317 0
318 2
319 0
320 1
328 0
329
1
100 1
101 1
102 33619964
103 0
99
99
99
99
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment