
#include "UA_PLC.h"
#include <string.h>
static UA_StatusCode
nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle);
void saveUA_ReferenceDescriptionToUAReferenceDescription(int j,UA_ReferenceDescription *ref,UAReferenceDescription *BrowseResult);
UA_Client *client;
u32 UA_Connect(STRING endpointUrl,UASessionConnectInfo SessionConnectInfo,long *ConnectionHdl){
	UA_Client *c = UA_Client_new();
	UA_StatusCode flag = UA_ClientConfig_setDefault(UA_Client_getConfig(c));
	UA_ClientConfig *config=UA_Client_getConfig(c);

	config->securityMode=SessionConnectInfo.SecurityMsgMode;
	config->timeout=SessionConnectInfo.SessionTimeout;
	if (flag == UA_STATUSCODE_GOOD) {
		flag=UA_Client_connect(c, endpointUrl.data);

	}else
	{
		UA_Client_delete(c);
		//memset(c,0,100);
		return flag;
	}
	client = c;
	*ConnectionHdl = (long *)c;
	printf("ConnectionHdl %lld \n",*ConnectionHdl);
	return flag;
}



u32 UA_Disconnect(long ConnectionHdl){
	UA_Client *c =(UA_Client*)ConnectionHdl;
	UA_Client_delete(ConnectionHdl);
	return 0;
}

u32 UA_NamespaceGetIndexList(long ConnectionHdl,u16 NamespaceUrisCount,STRING *NamespaceUris,u16 *NamespaceIndexes){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	int i;
	u32 retval=0;
	if(NamespaceUrisCount>MAX_ELEMENTS_NAMESPACES){
		retval=0xA0000002;
		return retval;
	}
	for(i=0;i<NamespaceUrisCount;i++){
		UA_String NamespaceUri;
		NamespaceUri.length = NamespaceUris[i].length;
		NamespaceUri.data = NamespaceUris[i].data;
		retval=UA_Client_NamespaceGetIndex(c,&NamespaceUri,&NamespaceIndexes[i]);
	}
	return retval;
}

u32 UA_ServerGetUriByIndex(long ConnectionHdl,u32 ServerIndex,STRING *ServerUri){
	UA_Client *client = (UA_Client*)ConnectionHdl;
	UA_ReadRequest request;
    UA_ReadRequest_init(&request);
    UA_ReadValueId id;
    UA_ReadValueId_init(&id);
    id.attributeId = UA_ATTRIBUTEID_VALUE;
    id.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY);
    request.nodesToRead = &id;
    request.nodesToReadSize = 1;

    UA_ReadResponse response = UA_Client_Service_read(client, request);

    UA_StatusCode retval = UA_STATUSCODE_GOOD;
    if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
        retval = response.responseHeader.serviceResult;
    else if(response.resultsSize != 1 || !response.results[0].hasValue)
        retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
    else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_STRING])
        retval = UA_STATUSCODE_BADTYPEMISMATCH;

    if(retval != UA_STATUSCODE_GOOD) {
        UA_ReadResponse_clear(&response);
        return retval;
    }


    UA_String *ns = (UA_String *)response.results[0].value.data;
	if(ServerIndex<=response.resultsSize&&ServerIndex>=0){
		ServerUri->length=ns[ServerIndex].length;
		ServerUri->data=ns[ServerIndex].data;
	}else{
		retval = 0xA0000200;
	}

	return retval;
}

u32 UA_ServerGetIndexByUriList(long ConnectionHdl,u16 ServerUrisCount,STRING ServerUris[],u16 *ServerIndexes){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	int i;
	u32 retval;
	if(ServerUrisCount>MAX_ELEMENTS_NAMESPACES){
		retval=0xA0000002;
		return retval;
	}
	for(i=0;i<ServerUrisCount;i++){
		UA_String NamespaceUri;
		NamespaceUri.length = ServerUris[i].length;
		NamespaceUri.data = ServerUris[i].data;
		retval=UA_Client_NamespaceGetIndex(c,&NamespaceUri,&ServerIndexes[i]);
	}
	return retval;
}
int IdentifierTypeChange[4]={0,0,0,1,2,3};

int my_strcmp(const char *s1,const char *s2){
	assert(s1 !=NULL&&s2!=NULL);
	while((*s1==*s2)&& *s1){
		s1++;
		s2++;
	}
	return *s1-*s2;
}

u32 UA_TranslatePathList(long ConnectionHdl,u16 BrowsePathsCount,UABrowsePath *BrowsePaths,UANodeID *TargetNodeIDs){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	UA_StatusCode retval;
	UA_BrowseRequest bReq;
	UA_BrowseRequest_init(&bReq);
	if(BrowsePathsCount>MAX_ELEMENTS_RELATIVEPATH){
		retval=0xA0000002;
		return retval;
	}
	for(int i=0;i<BrowsePathsCount;i++){
		bReq.requestedMaxReferencesPerNode = 0;
		bReq.nodesToBrowse = UA_BrowseDescription_new();

		switch(BrowsePaths[i].StartingNode.IdentifierType){
				case 0:bReq.nodesToBrowse[0].nodeId=UA_NODEID_NUMERIC(BrowsePaths[i].StartingNode.NamespaceIndex,BrowsePaths[i].StartingNode.Identifier.length);break;
				case 1:bReq.nodesToBrowse[0].nodeId=UA_NODEID_STRING(BrowsePaths[i].StartingNode.NamespaceIndex,BrowsePaths[i].StartingNode.Identifier.data);break;
				case 2:bReq.nodesToBrowse[0].nodeId.identifierType=4;
						bReq.nodesToBrowse[0].nodeId.identifier.string.data=BrowsePaths[i].StartingNode.Identifier.data;
						bReq.nodesToBrowse[0].nodeId.identifier.string.length=BrowsePaths[i].StartingNode.Identifier.length;
						bReq.nodesToBrowse[0].nodeId.namespaceIndex=BrowsePaths[i].StartingNode.NamespaceIndex;break;
				case 3:bReq.nodesToBrowse[0].nodeId=UA_NODEID_BYTESTRING(BrowsePaths[i].StartingNode.NamespaceIndex,BrowsePaths[i].StartingNode.Identifier.data);break;
		}
		switch(BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.IdentifierType){
				case 0:bReq.nodesToBrowse[0].referenceTypeId=UA_NODEID_NUMERIC(BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.NamespaceIndex,BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.Identifier.length);break;
				case 1:bReq.nodesToBrowse[0].referenceTypeId=UA_NODEID_STRING(BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.NamespaceIndex,BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.Identifier.data);break;
				case 2:bReq.nodesToBrowse[0].referenceTypeId.identifierType=4;
						bReq.nodesToBrowse[0].referenceTypeId.identifier.string.data=BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.Identifier.data;
						bReq.nodesToBrowse[0].referenceTypeId.identifier.string.length=BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.Identifier.length;
						bReq.nodesToBrowse[0].referenceTypeId.namespaceIndex=BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.NamespaceIndex;break;
				case 3:bReq.nodesToBrowse[0].referenceTypeId=UA_NODEID_BYTESTRING(BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.NamespaceIndex,BrowsePaths[i].RelativePath.Elements[0].ReferenceTypeId.Identifier.data);break;
		}
		if(BrowsePaths[i].RelativePath.Elements[0].IsInverse==1){
			bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ISFORWARD;
		}else{
			bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL;
		}
		if(BrowsePaths[i].RelativePath.Elements[0].IncludeSubtypes==1)
			bReq.nodesToBrowse[0].includeSubtypes = BrowsePaths[i].RelativePath.Elements[0].IncludeSubtypes;
		bReq.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_BOTH;
	}
	bReq.nodesToBrowseSize = BrowsePathsCount;
	UA_BrowseResponse bResp = UA_Client_Service_browse(c, bReq);
	int flag = 0;
	retval = bResp.responseHeader.serviceResult;
	if(retval == UA_STATUSCODE_GOOD) {
        for(size_t i = 0; i < bResp.resultsSize; ++i) {
            for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) {
                UA_ReferenceDescription *ref = &bResp.results[i].references[j];
				if(ref->nodeId.nodeId.namespaceIndex==BrowsePaths[i].RelativePath.Elements[0].TargetName.NamespaceIndex){
					//printf("%d\n",ref->nodeId.nodeId.identifier.string.data);
					//printf("%d\n",BrowsePaths[0].RelativePath.Elements[i].TargetName.Name.data);
					if(my_strcmp(ref->nodeId.nodeId.identifier.string.data,BrowsePaths[i].RelativePath.Elements[0].TargetName.Name.data)==0){
						TargetNodeIDs[i].NamespaceIndex=ref->nodeId.nodeId.namespaceIndex;
						TargetNodeIDs[i].IdentifierType=IdentifierTypeChange[ref->nodeId.nodeId.identifierType];
						TargetNodeIDs[i].Identifier.data=ref->nodeId.nodeId.identifier.string.data;
						TargetNodeIDs[i].Identifier.length=ref->nodeId.nodeId.identifier.string.length;
						flag = 1;
					}
				}
            }
        }
    }
	if(flag == 0){
		retval = 0xA0000200;
	}
	return retval;
}

u32 UA_NodeGetHandleList(long ConnectionHdl,u16 NodeIDCount,UANodeID *NodeIDs,long *NodeHdls,u32 ErrorIDs[]){
	int i;
	u32 retval=0;
	UA_NodeId *NodeID=malloc(sizeof(UA_NodeId)*NodeIDCount);
	if(NodeIDCount>MAX_ELEMENTS_NODELIST){
		retval=0xA0000002;
		return retval;
	}

	for(i=0;i<NodeIDCount;i++){
        printf("\nNdeIDs[i].IdentifierType=%d,NodeIDs[i].NamespaceIndex=%d,NodeIDs[i].Identifier.length=%d, NodeIDs[i].Identifier.data=%s\n",
            NodeIDs[i].IdentifierType,   NodeIDs[i].NamespaceIndex,  NodeIDs[i].Identifier.length ,NodeIDs[i].Identifier.data );

		if(NodeIDs[i].IdentifierType>=0&&NodeIDs[i].IdentifierType<4){
			switch(NodeIDs[i].IdentifierType){
				case 0:NodeID[i]=UA_NODEID_NUMERIC(NodeIDs[i].NamespaceIndex,NodeIDs[i].Identifier.data);break;
				case 1:NodeID[i]=UA_NODEID_STRING(NodeIDs[i].NamespaceIndex,NodeIDs[i].Identifier.data);break;
				case 2:NodeID[i].identifierType=4;
						NodeID[i].identifier.string.data=NodeIDs[i].Identifier.data;
						NodeID[i].identifier.string.length=NodeIDs[i].Identifier.length;
						NodeID[i].namespaceIndex=NodeIDs[i].NamespaceIndex;break;
				case 3:NodeID[i]=UA_NODEID_BYTESTRING(NodeIDs[i].NamespaceIndex,NodeIDs[i].Identifier.data);break;
			}
			ErrorIDs[i]=0;
		}else{
			ErrorIDs[i]=0xA0000301;
			retval=ErrorIDs[i];
		}
		// NodeID[i].identifier.string.data=NodeIDs[i].Identifier.data;
		// NodeID[i].identifier.string.length=NodeIDs[i].Identifier.length;
		// NodeID[i].namespaceIndex=NodeIDs[i].NamespaceIndex;
		NodeHdls[i]=&NodeID[i];
		//UA_NodeId *NodeID1=malloc(sizeof(UA_NodeId)*NodeIDCount);
		//UA_NodeId_delete(&NodeID[i]);
	}

	return retval;

}

u32 UA_NodeReleaseHandleList(long ConnectionHdl,u16 NodeHdlCount,long *NodeHdls,u32 ErrorIDs[]){
	int i;
	u32 retval=0;
	if(NodeHdlCount>MAX_ELEMENTS_NODELIST){
		retval=0xA0000002;
		return retval;
	}
	for(i=0;i<NodeHdlCount;i++){
		UA_NodeId nodeId = *(UA_NodeId*)NodeHdls[i];
		NodeHdls[i]=0;
		//UA_NodeId_delete(&nodeId);
		ErrorIDs[i]=0;
	}
	return retval;
}

u32 UA_NodeGetInformation(long ConnectionHdl,UANodeID NodeID,UANodeInformation *NodeInfo,u32 ErrorIDs[]){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	u32 retval,ret=0;
	UA_NodeId NODEID=UA_NODEID_STRING(NodeID.NamespaceIndex,NodeID.Identifier.data);
	// NODEID.namespaceIndex = NodeID.NamespaceIndex;
	// if(NodeID.IdentifierType>=0&&NodeID.IdentifierType<4){
	// 		switch(NodeID.IdentifierType){
	// 			case 0:NODEID.identifierType=0;
	// 			case 1:NODEID.identifierType=3;
	// 			case 2:NODEID.identifierType=4;
	// 			case 3:NODEID.identifierType=5;
	// 		}
	// 		ret=0;
	// 	}else{
	// 		ret=0xA0000301;
	// 	}
	// NODEID.identifier.string = UA_STRING(NodeID.Identifier.data);
	UA_NodeClass outNodeClass;
	UA_NodeClass_init(&outNodeClass);
	retval=UA_Client_readNodeClassAttribute(c,NODEID,&outNodeClass);
	if(retval!=0){
		ErrorIDs[0]=retval;
		ret=retval;
	}
	u32 temp =outNodeClass;
	NodeInfo->NodeClass=temp;
	UA_NodeClass_clear(&outNodeClass);

	UA_QualifiedName outBrowseName;
	UA_QualifiedName_init(&outBrowseName);
	retval=UA_Client_readBrowseNameAttribute(c,NODEID,&outBrowseName);
	if(retval!=0){
		ErrorIDs[1]=retval;
		ret=retval;
	}
	NodeInfo->BrowseName.NamespaceIndex=outBrowseName.namespaceIndex;
	NodeInfo->BrowseName.Name.length=outBrowseName.name.length;
	NodeInfo->BrowseName.Name.data=outBrowseName.name.data;
	UA_QualifiedName_clear(&outBrowseName);

	UA_LocalizedText outDisplayName;
	UA_LocalizedText_init(&outDisplayName);
	retval=UA_Client_readDisplayNameAttribute(c,NODEID,&outDisplayName);
	if(retval!=0){
		ErrorIDs[2]=retval;
		ret=retval;
	}
	NodeInfo->DisplayName.Locale=outDisplayName.locale.data;
	NodeInfo->DisplayName.Text.length=outDisplayName.text.length;
	NodeInfo->DisplayName.Text.data=outDisplayName.text.data;
	UA_LocalizedText_clear(&outDisplayName);

	UA_LocalizedText outDescription;
	UA_LocalizedText_init(&outDescription);
	retval=UA_Client_readDescriptionAttribute(c,NODEID,&outDescription);
	if(retval!=0){
		ErrorIDs[3]=retval;
		ret=retval;
	}
	NodeInfo->Description.Locale=outDescription.locale.data;
	NodeInfo->Description.Text.length=outDescription.text.length;
	NodeInfo->Description.Text.data=outDescription.text.data;
	UA_LocalizedText_clear(&outDescription);

	UA_UInt32 outWriteMask;
	UA_UInt32_init(&outWriteMask);
	retval=UA_Client_readWriteMaskAttribute(c,NODEID,&outWriteMask);
	if(retval!=0){
		ErrorIDs[4]=retval;
		ret=retval;
	}
	NodeInfo->WriteMask=outWriteMask;
	UA_UInt32_clear(&outWriteMask);

	UA_UInt32 outUserWriteMask;
	UA_UInt32_init(&outUserWriteMask);
	retval=UA_Client_readUserWriteMaskAttribute(c,NODEID,&outUserWriteMask);
	if(retval!=0){
		ErrorIDs[5]=retval;
		ret=retval;
	}
	NodeInfo->UserWriteMask=outUserWriteMask;
	UA_UInt32_clear(&outUserWriteMask);

	UA_Boolean outIsAbstract;
	UA_Boolean_init(&outIsAbstract);
	retval=UA_Client_readIsAbstractAttribute(c,NODEID,&outIsAbstract);
	if(retval!=0){
		ErrorIDs[6]=retval;
		//ret=retval;
	}
	NodeInfo->IsAbstract=outIsAbstract;
	UA_Boolean_clear(&outIsAbstract);

	UA_Boolean outSymmetric;
	UA_Boolean_init(&outSymmetric);
	retval=UA_Client_readSymmetricAttribute(c,NODEID,&outSymmetric);
	if(retval!=0){
		ErrorIDs[7]=retval;
		//ret=retval;
	}
	NodeInfo->Symmetric=outSymmetric;
	UA_Boolean_clear(&outSymmetric);

	UA_LocalizedText outInverseName;
	UA_LocalizedText_init(&outInverseName);
	retval=UA_Client_readInverseNameAttribute(c,NODEID,&outInverseName);
	if(retval!=0){
		ErrorIDs[8]=retval;
		//ret=retval;
	}
	NodeInfo->InverseName.length=outInverseName.text.length;
	NodeInfo->InverseName.data=outInverseName.text.data;
	UA_LocalizedText_clear(&outInverseName);

	UA_Boolean outContainsNoLoops;
	UA_Boolean_init(&outContainsNoLoops);
	retval=UA_Client_readContainsNoLoopsAttribute(c,NODEID,&outContainsNoLoops);
	if(retval!=0){
		ErrorIDs[9]=retval;
		//ret=retval;
	}
	NodeInfo->ContainsNoLoops=outContainsNoLoops;
	UA_Boolean_clear(&outContainsNoLoops);

	UA_Byte outEventNotifier;
	UA_Byte_init(&outEventNotifier);
	retval=UA_Client_readEventNotifierAttribute(c,NODEID,&outEventNotifier);
	if(retval!=0){
		ErrorIDs[10]=retval;
		//ret=retval;
	}
	NodeInfo->EventNotifier=outEventNotifier;
	UA_Byte_clear(&outEventNotifier);

	UA_NodeId outDataType;
	UA_NodeId_init(&outDataType);
	retval=UA_Client_readDataTypeAttribute(c,NODEID,&outDataType);
	if(retval!=0){
		ErrorIDs[11]=retval;
		ret=retval;
	}
	NodeInfo->DataType.NamespaceIndex=outDataType.namespaceIndex;
	NodeInfo->DataType.IdentifierType=outDataType.identifierType;
	NodeInfo->DataType.Identifier.length=outDataType.identifier.string.length;
	NodeInfo->DataType.Identifier.data=outDataType.identifier.string.data;
	UA_NodeId_clear(&outDataType);

	UA_Int32 outValueRank;
	UA_Int32_init(&outValueRank);
	retval=UA_Client_readValueRankAttribute(c,NODEID,&outValueRank);
	if(retval!=0){
		ErrorIDs[12]=retval;
		ret=retval;
	}
	NodeInfo->ValueRank=outValueRank;
	UA_Int32_clear(&outValueRank);

	UA_UInt32 outArrayDimensions[MAX_ELEMENTS_ARRAYDIMENSION];
	//UA_UInt32_init(*outArrayDimensions);
	int size;
	retval=UA_Client_readArrayDimensionsAttribute(c,NODEID,&size,outArrayDimensions);
	if(retval!=0){
		ErrorIDs[13]=retval;
		ret=retval;
	}
	for(int i=0;i<MAX_ELEMENTS_ARRAYDIMENSION;i++){
		NodeInfo->ArrayDimension[i]=outArrayDimensions[i];
	}


	UA_Byte outAccessLevel;
	UA_Byte_init(&outAccessLevel);
	retval=UA_Client_readAccessLevelAttribute(c,NODEID,&outAccessLevel);
	if(retval!=0){
		ErrorIDs[14]=retval;
		ret=retval;
	}
	NodeInfo->AccessLevel=outAccessLevel;

	UA_Byte outUserAccessLevel;
	UA_Byte_init(&outUserAccessLevel);
	retval=UA_Client_readUserAccessLevelAttribute(c,NODEID,&outUserAccessLevel);
	if(retval!=0){
		ErrorIDs[15]=retval;
		ret=retval;
	}
	NodeInfo->UserAccessLevel=outUserAccessLevel;

	UA_Double outMinSamplingInterval;
	UA_Double_init(&outMinSamplingInterval);
	retval=UA_Client_readMinimumSamplingIntervalAttribute(c,NODEID,&outMinSamplingInterval);
	if(retval!=0){
		ErrorIDs[16]=retval;
		ret=retval;
	}
	NodeInfo->MinimumSamplingInterval=outMinSamplingInterval;

	UA_Boolean outHistorizing;
	UA_Boolean_init(&outHistorizing);
	retval=UA_Client_readHistorizingAttribute(c,NODEID,&outHistorizing);
	if(retval!=0){
		ErrorIDs[17]=retval;
		ret=retval;
	}
	NodeInfo->Historizing=outHistorizing;

	UA_Boolean outExecutable;
	UA_Boolean_init(&outExecutable);
	retval=UA_Client_readExecutableAttribute(c,NODEID,&outExecutable);
	if(retval!=0){
		ErrorIDs[18]=retval;
		//ret=retval;
	}
	NodeInfo->Executable=outExecutable;

	UA_Boolean outUserExecutable;
	UA_Boolean_init(&outUserExecutable);
	retval=UA_Client_readUserExecutableAttribute(c,NODEID,&outUserExecutable);
	if(retval!=0){
		ErrorIDs[19]=retval;
		//ret=retval;
	}
	NodeInfo->UserExecutable=outUserExecutable;

	return ret;
}

u32 UA_SubscriptionCreate(long ConnectionHdl,bool PublishingEnable,u16 Priority,long *SubscriptionHdl,TIME *PublishingInterval){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default();
	request.requestedPublishingInterval=*PublishingInterval;
	request.publishingEnabled=PublishingEnable;
	request.priority=Priority;
	UA_CreateSubscriptionResponse *response=malloc(sizeof(UA_CreateSubscriptionResponse));
	*response = UA_Client_Subscriptions_create(c,request,NULL,NULL,NULL);
	u32 retval=response[0].responseHeader.serviceResult;
	if(retval!=UA_STATUSCODE_GOOD){
		UA_CreateSubscriptionResponse_clear(&response[0]);
		return retval;
	}
	printf("response[0].subscripstionId is %x\n",response[0].subscriptionId);
	*SubscriptionHdl=(long *)response[0].subscriptionId;
	UA_CreateSubscriptionResponse_clear(&response[0]);
	return retval;
}

u32 UA_SubscriptionDelete(long ConnectionHdl,long SubscriptionHdl){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	u32 retval=UA_Client_Subscriptions_deleteSingle(c,SubscriptionHdl);
	return retval;
}

u32 UA_SubscriptionModify(long ConnectionHdl,long SubscriptionHdl,bool PublishingEnable,u16 Priority,TIME *PublishingInterval){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	//UA_CreateSubscriptionRequest *request =(UA_CreateSubscriptionRequest *)SubscriptionHdl;
	UA_ModifySubscriptionRequest request;
	UA_ModifySubscriptionRequest_init(&request);
	request.subscriptionId=SubscriptionHdl;
	request.requestedPublishingInterval=*PublishingInterval;
	//request.requestHeader.publishingEnabled=PublishingEnable;
	request.priority=Priority;
	UA_ModifySubscriptionResponse response=UA_Client_Subscriptions_modify(c,request);
	u32 retval = response.responseHeader.serviceResult;
	//SubscriptionHdl=(u32 *)&request;

	return retval;
}

u32 UA_SubscriptionProcessed(long SubscriptionHdl){

}

u32 SubscriptionHdlzu2[100];
u32 MonItemHdlzu[100];
UAMonitoredVariables MonVlaue[100];
int MontNum=0;
static void handler_DataChanged(UA_Client *client, UA_UInt32 subId,
                                    void *subContext, UA_UInt32 monId,
                                    void *monContext, UA_DataValue *value)
{
    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT, "Received Notification");

    UA_NodeId *ptr = (UA_NodeId*)monContext;
	SubscriptionHdlzu2[MontNum]=subId;
	MonItemHdlzu[MontNum]=monId;
	MonVlaue[MontNum].Values.data=value->value.data;
	MonVlaue[MontNum].Values.type=value->value.type->typeId.identifier.numeric;
	UA_DateTime now = UA_DateTime_nowMonotonic();
	MonVlaue[MontNum].TimeStamps=now;
	MonVlaue[MontNum].NewValuesCount=1;
	//MonVlaue[MontNum].NodeQualityIDs[0]=0;
    //UA_Int32 currentValue = *(UA_Int32*)(value->value.data);

	MontNum++;
}

u32 UA_MonitoredItemAddList(long ConnectionHdl,long SubscriptionHdl,u16 NodeHdlCount,
							long *NodeHdls,UAMonitoringSyncMode SyncMode,
							UANodeAdditionalInfo *NodeAddInfos,u32 *MonitoredItemHdls,u32 ErrorIDs[]){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	u32 retval=0;
	if(NodeHdlCount>MAX_ELEMENTS_MONITORLIST){
		retval=0xA0000002;
		return retval;
	}
	if(SyncMode==UAMS_ControllerSync){
		for(int i=0;i<NodeHdlCount;i++){
			UA_NodeId *NodeID=(UA_NodeId*)NodeHdls[i];
			UA_MonitoredItemCreateRequest monRequest=UA_MonitoredItemCreateRequest_default(*NodeID);
			monRequest.itemToMonitor.attributeId = NodeAddInfos[i].AttributeID;
			UA_MonitoredItemCreateResult monResponse=
			UA_Client_MonitoredItems_createDataChange(c,SubscriptionHdl,UA_TIMESTAMPSTORETURN_BOTH,
														monRequest,NodeID,handler_DataChanged,NULL);
		if(monResponse.statusCode!=UA_STATUSCODE_GOOD){
			retval=monResponse.statusCode;
		}
		ErrorIDs[i]=monResponse.statusCode;
		MonitoredItemHdls[i]=monResponse.monitoredItemId;
		}

	}
	return retval;

}

u32 UA_MonitoredItemRemoveList(long ConnectionHdl,long SubscriptionHdl,u16 MonitoredItemHdlCount,long *MonitoredItemHdls,u32 ErrorIDs[]){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	u32 retval=0;
	for(int i=0;i<MonitoredItemHdlCount;i++){
		MonitoredItemHdls[i]=0;
		ErrorIDs[i]=0;
	}
	return retval;
}

u32 UA_MonitoredItemModifyList(long ConnectionHdl,long SubscriptionHdl,u16 MonitoredItemHdlCount,
								long *MonitoredItemHdls,UAMonitoringParameter MonitoringParameter[],
								u32 ErrorIDs[]){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	UA_ModifyMonitoredItemsRequest request;
	request.subscriptionId=SubscriptionHdl;
	request.itemsToModifySize=MonitoredItemHdlCount;
	u32 retval=0;
	for(int i=0;i<MonitoredItemHdlCount;i++){
		request.itemsToModify[i].monitoredItemId=MonitoredItemHdls[i];
		request.itemsToModify[i].requestedParameters.samplingInterval=MonitoringParameter[i].SamplingInterval;
		request.itemsToModify[i].requestedParameters.queueSize=MonitoringParameter[i].QueueSize;
		request.itemsToModify[i].requestedParameters.discardOldest=MonitoringParameter[i].DiscardOldest;
	}
	UA_ModifyMonitoredItemsResponse Response=UA_Client_MonitoredItems_modify(c,request);
	for(int i=0;i<MonitoredItemHdlCount;i++){
		ErrorIDs[i]=Response.results[i].statusCode;
		if(ErrorIDs[i]!=UA_STATUSCODE_GOOD){
			retval=ErrorIDs[i];
		}
	}

	return retval;
}

u32 UA_MonitoredItemOperateList(long ConnectionHdl,long SubscriptionHdl,u16 MonitoredItemHdlCount,long *MonitoredItemHdls,
								UAMonitoredVariables *Variables,
								bool *ValuesChanged,u16 *MinLostValueCount,u32 *NodeErrorIDs){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	u32 retval=0;
	UA_Client_run_iterate(c, 1000);
	int i,j,flag=0;
	for(i=0;i<MontNum;i++){
		if(SubscriptionHdlzu2[i]!=NULL&&SubscriptionHdl==SubscriptionHdlzu2[i]){
			for(j=0;j<MonitoredItemHdlCount;j++){
				if(MonitoredItemHdls[j]==MonItemHdlzu[i]){
					Variables[j]=MonVlaue[i];
					NodeErrorIDs[j]=0;
					if(NodeErrorIDs[j]!=0){
						retval=NodeErrorIDs[j];
					}
					// UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT, "SubId:%u, MonId:%u, Current Value: %d\n",
                    //                                         SubscriptionHdl, MonitoredItemHdls[i], MonVlaue[i].data);
					*ValuesChanged|=1;
					flag++;

				}
			}
		}
	}
	*MinLostValueCount=MontNum-flag;
	return retval;

}
/*
u32 UA_ReadList(long ConnectionHdl,u16 NodeHdlCount,long *NodeHdls,UANodeAdditionalInfo *NodeAddInfos,UA_Value *variables,u32 ErrorIDs[]){
	//UA_Client *c = (UA_Client*)ConnectionHdl;
	UA_Client *c=client;
	int i;
	u32 retval;
 	UA_ReadValueId item[NodeHdlCount];
	if(NodeHdlCount>MAX_ELEMENTS_NODELIST){
		retval=0xA0000002;
	}
	else
    {
        for(i=0;i<NodeHdlCount;i++){
            UA_ReadValueId_init(&item[i]);
            item[i].nodeId = *(UA_NodeId*)NodeHdls[i];
            item[i].attributeId = NodeAddInfos[i].AttributeID;
        }

        UA_ReadRequest request;
        UA_ReadRequest_init(&request);
        request.nodesToRead = &item[0];
        request.nodesToReadSize = 1;
        UA_ReadResponse response = UA_Client_Service_read(c, request);
        retval = response.responseHeader.serviceResult;
        if(retval == UA_STATUSCODE_GOOD)
        {
            if(response.resultsSize==NodeHdlCount)
            {
                for (i = 0; i < NodeHdlCount; i++)
                {
                    ErrorIDs[i]=response.results[i].status;
                }
                UA_Variant *out=malloc(sizeof(UA_Variant));
                for(i=0;i<NodeHdlCount;i++)
                {
                    if(ErrorIDs[i]==UA_STATUSCODE_GOOD)
                    {
                        UA_DataValue res = response.results[i];
                        if(!res.hasValue)
                        {
                            UA_ReadResponse_clear(&response);
                            return UA_STATUSCODE_BADUNEXPECTEDERROR;
                        }
                    }
                    else
                    {
                        if(NodeAddInfos[i].AttributeID == UA_ATTRIBUTEID_VALUE)
                        {
                            memcpy(out, &res.value, sizeof(UA_Variant));
                            UA_Variant_init(&res.value);
                            variables[i].data=(void *)*res.value.data;//out->data;
                            variables[i].type=out->type->typeId.identifier.numeric;
                        }
                        else if(NodeAddInfos[i].AttributeID == UA_ATTRIBUTEID_NODECLASS)
                        {
                            UA_NodeClass *out1;
                            memcpy(out1, (UA_NodeClass*)res.value.data, sizeof(UA_NodeClass));
                            variables[i].data=out1;
                            variables[i].type=UA_TYPES_NODECLASS;
                        }
                        else if(UA_Variant_isScalar(&res.value))
                        {
                            memcpy(&variables[i].data, &res.value.data, res.value.type->memSize);
                            UA_free(res.value.data);
                            res.value.data = NULL;
                            variables[i].type=res.value.type->typeId.identifier.numeric;
                        }
                        else
                        {
                            retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
                        }

                    }
                }  //end for
            }
            else
            {

                retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
            }
        }//end if(retval == UA_STATUSCODE_GOOD)

        UA_ReadResponse_clear(&response);
    }

}

*/
u32 UA_ReadList(long ConnectionHdl,u16 NodeHdlCount,long *NodeHdls,UANodeAdditionalInfo *NodeAddInfos,UA_Value *variables,u32 ErrorIDs[]){
	//UA_Client *c = (UA_Client*)ConnectionHdl;
	UA_Client *c=client;
	int i;
	u32 retval;
 	UA_ReadValueId item[NodeHdlCount];
	if(NodeHdlCount>MAX_ELEMENTS_NODELIST){
		retval=0xA0000002;
	}
	else
    {
        for(i=0;i<NodeHdlCount;i++){
            UA_ReadValueId_init(&item[i]);
            item[i].nodeId = *(UA_NodeId*)NodeHdls[i];
            //item[i].nodeId.identifier.numeric = NodeHdls[i];//zjy 20240910
            item[i].attributeId = NodeAddInfos[i].AttributeID;
            //item[i].nodeId.namespaceIndex = 1;
            console_printf("------------#2------NodeHdls[i] = %ld ,item[i].nodeId = %d,item[i].attributeId=%d,item[i].nodeId.namespaceIndex=%d-\n",
               NodeHdls[i],item[i].nodeId.identifier.string.length,item[i].attributeId,item[i].nodeId.namespaceIndex);
        }
        UA_ReadRequest request;
        UA_ReadRequest_init(&request);
        request.nodesToRead = &item[0];
        request.nodesToReadSize = 1;
        UA_ReadResponse response = UA_Client_Service_read(c, request);
        retval = response.responseHeader.serviceResult;
        if(retval == UA_STATUSCODE_GOOD)
        {
            console_printf("------------#3---------------\n");
            if(response.resultsSize==NodeHdlCount)
            {
                console_printf("------------#4---------------\n");
                for (i = 0; i < NodeHdlCount; i++)
                {
                    ErrorIDs[i]=response.results[i].status;
                }
                retval = 0 ;
                for(i=0;i<NodeHdlCount;i++)
                {
                    if(ErrorIDs[i]==UA_STATUSCODE_GOOD)
                    {
                        console_printf("------------#5---------------\n");
                        UA_DataValue res = response.results[i];
                        if(!res.hasValue)
                        {
                            console_printf("------------#6---------------\n");
                            UA_ReadResponse_clear(&response);
                            retval =  UA_STATUSCODE_BADUNEXPECTEDERROR;
                        }
						else
						{
  							if(NodeAddInfos[i].AttributeID == UA_ATTRIBUTEID_VALUE)
							{
  								//UA_Variant *out=malloc(sizeof(UA_Variant));
								UA_Variant out;
								//memcpy(&out, &res.value, sizeof(UA_Variant));
								//UA_Variant_init(&res.value);
								//variables[i].data =res.value.data;
								long temp ;
								memcpy(&temp,res.value.data,8);
								variables[i].data = (void *)temp;

								variables[i].type=res.value.type->typeId.identifier.numeric;

							}
							else if(NodeAddInfos[i].AttributeID == UA_ATTRIBUTEID_NODECLASS)
							{
								//UA_NodeClass *out1;
								//memcpy(out1, (UA_NodeClass*)res.value.data, sizeof(UA_NodeClass));
								memcpy(variables[i].data,res.value.data,8);
								variables[i].type=UA_TYPES_NODECLASS;
							}
							else if(UA_Variant_isScalar(&res.value))
							{
								//memcpy(&variables[i].data, &res.value.data, res.value.type->memSize);
								//UA_free(res.value.data);
								//res.value.data = 0;
								variables[i].type=res.value.type->typeId.identifier.numeric;
							}
							else
							{
								retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
							}

						}
						UA_free(res.value.data);   //?????   need or not
					}
                }  //end for
            }
            else
            {

                retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
            }
        }//end if(retval == UA_STATUSCODE_GOOD)
      //  console_printf("------------#f8 --------------\n");
        // UA_ReadResponse_clear(&response);
    }

    return retval;
}

u32 UA_WriteList(long ConnectionHdl,u16 NodeHdlCount,long *NodeHdls,UANodeAdditionalInfo *NodeAddInfos,UA_Value *variables,u32 ErrorIDs[]){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	int i;
	UA_StatusCode retval=0;
	if(NodeHdlCount>MAX_ELEMENTS_NODELIST){
		retval=0xA0000002;
		return retval;
	}
	//UA_NodeId NODEid= UA_NODEID_STRING(1, "A1.the anwser2");
	//UA_Client_writeValueAttribute(c,NODEid,&in);
	UA_WriteValue wValue[NodeHdlCount];
	for(i=0;i<NodeHdlCount;i++){
		UA_WriteValue_init(&wValue[i]);
	 	wValue[i].nodeId = *(UA_NodeId*)NodeHdls[i];
	 	//wValue[i].nodeId = NODEid;
	 	wValue[i].attributeId = NodeAddInfos[i].AttributeID;
	 	if(NodeAddInfos[i].AttributeID == UA_ATTRIBUTEID_VALUE){
	 		UA_Variant in;
			UA_Variant_init(&in);
			UA_Variant_setScalar(&in,variables[i].data,&UA_TYPES[variables[i].type-1]);
         	wValue[i].value.value = in;
			wValue[i].value.hasValue = true;
	 	}
	 	else{
	 		UA_Variant_setScalar(&wValue[i].value.value, (void*)(uintptr_t)variables[i].data, &UA_TYPES[variables[i].type-1]);
		}
	}
	UA_WriteRequest wReq;
	UA_WriteRequest_init(&wReq);
	wReq.nodesToWrite = &wValue[0];
	wReq.nodesToWriteSize = NodeHdlCount;

	UA_WriteResponse wResp = UA_Client_Service_write(c, wReq);

	retval = wResp.responseHeader.serviceResult;
	if(retval==UA_STATUSCODE_GOOD){
		if(wResp.resultsSize==NodeHdlCount){
			for(i=0;i<NodeHdlCount;i++){
				ErrorIDs[i]=wResp.results[i];
			}
		}else{
			retval=UA_STATUSCODE_BADUNEXPECTEDERROR;
		}
	}
	UA_WriteRequest_clear(&wResp);
	return retval;
}

u32 UA_MethodGetHandleList(long ConnectionHdl,u16 NodeIDCount,UANodeID *ObjectNodeIDs,UANodeID *MethodNodeIDs,long *MethodHdls,u32 ErrorIDs[]){
	UA_Client *c = (UA_Client*)ConnectionHdl;

	u32 retval=0;
	if(NodeIDCount>MAX_ELEMENTS_METHOD){
		retval=0xA0000002;
		return retval;
	}

	for(int i = 0;i<NodeIDCount;i++){
		UA_CallRequest *request=malloc(sizeof(UA_CallRequest));

    	UA_CallMethodRequest item;
		UA_CallMethodRequest_init(&item);
		UA_CallRequest_init(request);

		switch(ObjectNodeIDs[i].IdentifierType){
			case 0:item.objectId=UA_NODEID_NUMERIC(ObjectNodeIDs[i].NamespaceIndex,ObjectNodeIDs[i].Identifier.data);break;
			case 1:item.objectId=UA_NODEID_STRING(ObjectNodeIDs[i].NamespaceIndex,ObjectNodeIDs[i].Identifier.data);break;
			case 2:item.objectId.identifierType=4;
					item.objectId.identifier.string.data=ObjectNodeIDs[i].Identifier.data;
					item.objectId.identifier.string.length=ObjectNodeIDs[i].Identifier.length;
					item.objectId.namespaceIndex=ObjectNodeIDs[i].NamespaceIndex;break;
			case 3:item.objectId=UA_NODEID_BYTESTRING(ObjectNodeIDs[i].NamespaceIndex,ObjectNodeIDs[i].Identifier.data);break;
			default:ErrorIDs[i]==0xA0000301;retval=ErrorIDs[i];break;
		}
		switch(MethodNodeIDs[i].IdentifierType){
			case 0:item.methodId=UA_NODEID_NUMERIC(MethodNodeIDs[i].NamespaceIndex,MethodNodeIDs[i].Identifier.data);break;
			case 1:item.methodId=UA_NODEID_STRING(MethodNodeIDs[i].NamespaceIndex,MethodNodeIDs[i].Identifier.data);break;
			case 2:item.methodId.identifierType=4;
					item.methodId.identifier.string.data=MethodNodeIDs[i].Identifier.data;
					item.methodId.identifier.string.length=MethodNodeIDs[i].Identifier.length;
					item.methodId.namespaceIndex=MethodNodeIDs[i].NamespaceIndex;break;
			case 3:item.methodId=UA_NODEID_BYTESTRING(MethodNodeIDs[i].NamespaceIndex,MethodNodeIDs[i].Identifier.data);break;
			default:ErrorIDs[i]==0xA0000301;retval=ErrorIDs[i];break;
		}
		//UA_CallMethodRequest_clear(&item);
		request[i].methodsToCall = &item;

		//UA_CallRequest_clear(request);
		request[i].methodsToCallSize = 1;
		MethodHdls[i]=(long *)request;
		ErrorIDs[i]=0;
	}

	return retval;
}

u32 UA_MethodReleaseHandleList(long ConnectionHdl,u16 MethodHdlCount,long *MethodHdls,u32 *ErrorIDs){
	int i;
	u32 retval=0;
	if(MethodHdlCount>MAX_ELEMENTS_METHOD){
		retval=0xA0000002;
		return retval;
	}
	for(i=0;i<MethodHdlCount;i++){
		UA_CallRequest *request=MethodHdls[i];
		MethodHdls[i]=0;
		//UA_CallRequest_clear(&MethodHdls[i]);
		ErrorIDs[i]=0;
	}
	return retval;
}

u32 UA_MethodCall(long ConnectionHdl,long MethodHdl,UA_Arguments *InputArguments, UA_Arguments *OutputArguments){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	UA_CallRequest request=*(UA_CallRequest *)MethodHdl;
	UA_Variant newValue[InputArguments->ArgumentSize];
	for(int i=0;i<InputArguments->ArgumentSize;i++){
		UA_Variant_init(&newValue[i]);
		UA_Variant_setScalar(&newValue[i],InputArguments->value[i].data,&UA_TYPES[InputArguments->value[i].type-1]);
	}
	request.methodsToCall->inputArguments = &newValue; // cast const...(UA_Variant *)(void*)(uintptr_t)
    request.methodsToCall->inputArgumentsSize = InputArguments->ArgumentSize;
	size_t outputSzie;
	UA_Variant *outputValue;
	// UA_Variant inValue[2];
	// UA_Variant_init(&inValue[0]);
	// UA_Variant_init(&inValue[1]);
	// UA_UInt16 a1=1;
	// UA_UInt16 a2=2;
	// UA_Variant_setScalar(&inValue[0],&a1,&UA_TYPES[UA_TYPES_INT16]);
	// UA_Variant_setScalar(&inValue[1],&a2,&UA_TYPES[UA_TYPES_INT16]);
	// UA_Client_call(c,UA_NODEID_STRING(0,"A1"),UA_NODEID_STRING(1,"test"),2,inValue,&outputSzie,&outputValue);
    /* Call the service */
	UA_CallResponse response = UA_Client_Service_call(c, request);
	UA_StatusCode retval = response.responseHeader.serviceResult;
	if(retval == UA_STATUSCODE_GOOD) {
        if(response.resultsSize == 1)
            retval = response.results[0].statusCode;
        else
            retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
    }
	 if(retval != UA_STATUSCODE_GOOD) {
        UA_CallResponse_clear(&response);
        return retval;
    }

	/* Move the output arguments */
    if(&OutputArguments->value != NULL && &OutputArguments->ArgumentSize != NULL) {
		OutputArguments->ArgumentSize==response.results[0].outputArgumentsSize;
		for(int i=0;i<OutputArguments->ArgumentSize;i++){
			UA_Variant output;
			UA_Variant_init(&output);
			output = response.results[0].outputArguments[i];
			OutputArguments->value[i].data=output.data;
			OutputArguments->value[i].type=output.type->typeId.identifier.numeric;
		}
	}
	//UA_CallResponse_clear(&response);
    return retval;
}



u32 UA_Browse(long ConnectionHdl,UABrowseDescription BrowseDescription,u32 ContinuationPointIn,u16 *BrowseResultCount,UAReferenceDescription *BrowseResult,u32 ContinuationPointOut){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	UA_StatusCode retval;
	if(ContinuationPointIn==0){
		UA_BrowseRequest bReq;
		UA_BrowseRequest_init(&bReq);
		bReq.requestedMaxReferencesPerNode = 0;
		bReq.nodesToBrowse = UA_BrowseDescription_new();
		bReq.nodesToBrowseSize = 1;
		switch(BrowseDescription.StartingNodeID.IdentifierType){
			case 0:bReq.nodesToBrowse[0].nodeId=UA_NODEID_NUMERIC(BrowseDescription.StartingNodeID.NamespaceIndex,BrowseDescription.StartingNodeID.Identifier.data);break;
			case 1:bReq.nodesToBrowse[0].nodeId=UA_NODEID_STRING(BrowseDescription.StartingNodeID.NamespaceIndex,BrowseDescription.StartingNodeID.Identifier.data);break;
			case 2:bReq.nodesToBrowse[0].nodeId.identifierType=4;
					bReq.nodesToBrowse[0].nodeId.identifier.string.data=BrowseDescription.StartingNodeID.Identifier.data;
					bReq.nodesToBrowse[0].nodeId.identifier.string.length=BrowseDescription.StartingNodeID.Identifier.length;
					bReq.nodesToBrowse[0].nodeId.namespaceIndex=BrowseDescription.StartingNodeID.NamespaceIndex;break;
			case 3:bReq.nodesToBrowse[0].nodeId=UA_NODEID_BYTESTRING(BrowseDescription.StartingNodeID.NamespaceIndex,BrowseDescription.StartingNodeID.Identifier.data);break;
			default:retval=UA_STATUSCODE_BADUNEXPECTEDERROR;
		}
		if(BrowseDescription.ReferenceTypeID.Identifier.length!=NULL)
			bReq.nodesToBrowse[0].referenceTypeId=UA_NODEID_NUMERIC(0,BrowseDescription.ReferenceTypeID.Identifier.length);
		if(BrowseDescription.ResultMask==1||BrowseDescription.ResultMask==2||BrowseDescription.ResultMask==4||BrowseDescription.ResultMask==8||BrowseDescription.ResultMask==16)
		 	bReq.nodesToBrowse[0].resultMask = BrowseDescription.ResultMask;
		if(BrowseDescription.Direction==2||BrowseDescription.Direction==1||BrowseDescription.Direction==0)
		 	bReq.nodesToBrowse[0].browseDirection = BrowseDescription.Direction;
		if(BrowseDescription.IncludeSubtypes==0||BrowseDescription.IncludeSubtypes==1)
		 	bReq.nodesToBrowse[0].includeSubtypes = BrowseDescription.IncludeSubtypes;
		if(BrowseDescription.NodeClass!=NULL)
		 	bReq.nodesToBrowse[0].nodeClassMask = BrowseDescription.NodeClass;

		UA_BrowseResponse bResp = UA_Client_Service_browse(c, bReq);
		retval = bResp.responseHeader.serviceResult;
		if(retval == UA_STATUSCODE_GOOD) {
			if(bResp.results[0].referencesSize<=MAX_ELEMENTS_NODELIST){
				*BrowseResultCount=bResp.results[0].referencesSize;
				for(size_t j = 0; j < bResp.results[0].referencesSize; ++j){
					UA_ReferenceDescription *ref = &bResp.results[0].references[j];
					saveUA_ReferenceDescriptionToUAReferenceDescription(j,ref,BrowseResult);
				}
				ContinuationPointOut=0;
			}else if(bResp.results[0].referencesSize>MAX_ELEMENTS_NODELIST){
				*BrowseResultCount=MAX_ELEMENTS_NODELIST;
				UA_ReferenceDescription *ref1=malloc(sizeof(UA_ReferenceDescription)*(bResp.results[0].referencesSize-MAX_ELEMENTS_NODELIST+1));
				for(size_t j = 0; j < MAX_ELEMENTS_NODELIST; ++j){
					UA_ReferenceDescription *ref = &bResp.results[0].references[j];
					saveUA_ReferenceDescriptionToUAReferenceDescription(j,ref,BrowseResult);
				}
				for(size_t j=MAX_ELEMENTS_NODELIST+1;j<=bResp.results[0].referencesSize;j++){
					ref1[j-MAX_ELEMENTS_NODELIST]=bResp.results[0].references[j];
				}
				ref1[0].browseName.namespaceIndex=bResp.results[0].referencesSize-MAX_ELEMENTS_NODELIST;
				ContinuationPointOut=(u32 *)ref1;
			}

		}
		//UA_BrowseRequest_clear(&bReq);
    	//UA_BrowseResponse_clear(&bResp);
	}else{
		UA_ReferenceDescription *ref=(UA_ReferenceDescription *)ContinuationPointOut;
		if(ref[0].browseName.namespaceIndex<=MAX_ELEMENTS_NODELIST){
			for(size_t j = 1; j < ref[0].browseName.namespaceIndex+1; ++j){
				saveUA_ReferenceDescriptionToUAReferenceDescription(j,ref,BrowseResult);
			}
			ContinuationPointOut=0;
		}else if(ref[0].browseName.namespaceIndex>MAX_ELEMENTS_NODELIST){
			UA_ReferenceDescription *ref1=malloc(sizeof(UA_ReferenceDescription)*(ref[0].browseName.namespaceIndex-MAX_ELEMENTS_NODELIST+1));
			for(size_t j = 1; j < MAX_ELEMENTS_NODELIST+1; ++j){
				saveUA_ReferenceDescriptionToUAReferenceDescription(j,ref,BrowseResult);
			}
			for(size_t j=MAX_ELEMENTS_NODELIST+1;j<=ref[0].browseName.namespaceIndex;j++){
				ref1[j-MAX_ELEMENTS_NODELIST]=ref[j];
			}
			ref1[0].browseName.namespaceIndex=ref[0].browseName.namespaceIndex-MAX_ELEMENTS_NODELIST;
			ContinuationPointOut=(u32 *)ref1;
		}

	}

	return retval;
}

u32 SubscriptionHdlzu[100];
u32 EventItemHdlzu[100];
UAEventField EventFields[100];
int EventNum=0;
static void events_callback(UA_Client *client,UA_UInt32 subId,void *subContext,UA_UInt32 monId,
							void *monContext, size_t nEventFields,UA_Variant *eventFields){
	UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"Notification");

	//UA_assert(*(UA_UInt32*)monContext == monId);
	SubscriptionHdlzu[EventNum]=subId;
	EventItemHdlzu[EventNum]=monId;

	int j=0;
	STRING *context = (STRING *)monContext;
	for(size_t i = 0;i<nEventFields;++i){
		if(UA_Variant_hasScalarType(&eventFields[i],&UA_TYPES[UA_TYPES_UINT16])){
			UA_UInt16 severity = *(UA_UInt16 *)eventFields[i].data;
			EventFields[EventNum].Severity=severity;
			//UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"Severity:%u",severity);
		}
		else if(UA_Variant_hasScalarType(&eventFields[i],&UA_TYPES[UA_TYPES_LOCALIZEDTEXT])){
			UA_LocalizedText *lt = (UA_LocalizedText *)eventFields[i].data;
			//UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"Message:'%.*s'",(int)lt->text.length,lt->text.data);
			EventFields[EventNum].Message.data=lt->text.length;
			EventFields[EventNum].Message.length=lt->text.data;
		}else if(UA_Variant_hasScalarType(&eventFields[i],&UA_TYPES[UA_TYPES_NODEID])){
			int flag=1;
			while(flag){
				if(!strcmp(context[j].data,"EventType")){
					//UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"EventType");
					UA_NodeId nodeid;
					UA_NodeId_copy((UA_NodeId *)eventFields[i].data,&nodeid);
					EventFields[EventNum].EventType.NamespaceIndex=nodeid.namespaceIndex;
					switch (nodeid.identifierType)
					{
						case 0:	EventFields[EventNum].EventType.IdentifierType=0;
								EventFields[EventNum].EventType.Identifier.length=nodeid.identifier.numeric;
								break;
						case 3:	EventFields[EventNum].EventType.IdentifierType=1;
								EventFields[EventNum].EventType.Identifier.data=nodeid.identifier.string.data;
								EventFields[EventNum].EventType.Identifier.length=nodeid.identifier.string.length;
								break;
						case 4:	EventFields[EventNum].EventType.IdentifierType=2;break;
								//EventFields[EventNum].EventType.Identifier.data=nodeid.identifier.guid.;
						case 5:	EventFields[EventNum].EventType.IdentifierType=3;
								EventFields[EventNum].EventType.Identifier.data=nodeid.identifier.byteString.data;
								EventFields[EventNum].EventType.Identifier.length=nodeid.identifier.byteString.length;
								break;
						default:
							break;
					}
					j++;
					flag=0;
				}else if(!strcmp(context[j].data,"SourceNode")){
					UA_NodeId nodeid;
					UA_NodeId_copy((UA_NodeId *)eventFields[i].data,&nodeid);
					EventFields[EventNum].SourceNode.NamespaceIndex=nodeid.namespaceIndex;
					switch (nodeid.identifierType)
					{
						case 0:	EventFields[EventNum].SourceNode.IdentifierType=0;
								EventFields[EventNum].SourceNode.Identifier.length=nodeid.identifier.numeric;
								break;
						case 3:	EventFields[EventNum].SourceNode.IdentifierType=1;
								EventFields[EventNum].SourceNode.Identifier.data=nodeid.identifier.string.data;
								EventFields[EventNum].SourceNode.Identifier.length=nodeid.identifier.string.length;
								break;
						case 4:	EventFields[EventNum].SourceNode.IdentifierType=2;break;
								//EventFields[EventNum].SourceNode.Identifier.data=nodeid.identifier.guid.;
						case 5:	EventFields[EventNum].SourceNode.IdentifierType=3;
								EventFields[EventNum].SourceNode.Identifier.data=nodeid.identifier.byteString.data;
								EventFields[EventNum].SourceNode.Identifier.length=nodeid.identifier.byteString.length;
								break;
						default:
							break;
					}
					j++;
					flag=0;
				}else{
					j++;
				}
			}
			//UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"UA_TYPES_NODEID");
		}else if(UA_Variant_hasScalarType(&eventFields[i],&UA_TYPES[UA_TYPES_DATETIME])){
			//UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"UA_TYPES_DATETIME");
			int flag=1;
			while(flag){
				if(!strcmp(context[j].data,"Time")){
					UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"Time");
					TIME time =*(UA_DateTime *)eventFields[i].data;
					EventFields[EventNum].Time=time;
					j++;
					flag=0;
				}else if(!strcmp(context[j].data,"ReceiveTime")){
					UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"ReceiveTime");
					TIME time =*(UA_DateTime *)eventFields[i].data;
					EventFields[EventNum].ReceiveTime=time;
					j++;
					flag=0;
				}else{
					j++;
				}
			}

		}
		else{
			//UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"Don't know how to handle type:'%s'",eventFields[i].type->typeName);
		}
	}
	EventNum=EventNum+1;
}


u32 UA_EventItemAdd(long ConnectionHdl,long SubscriptionHdl,long NodeHdl,
					UANodeID EventType,u16 EventFieldSelectionCount,
					UARelativePath *EventFieldSelections,long *EventItemHdl){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	u32 retval;
	if(EventFieldSelectionCount>MAX_ELEMENTS_SELECTIONS){
		retval=0xA0000002;
		return retval;
	}
	UA_MonitoredItemCreateRequest item;
	UA_MonitoredItemCreateRequest_init(&item);
	item.itemToMonitor.nodeId = UA_NODEID_NUMERIC(0,2253);
	item.itemToMonitor.attributeId = UA_ATTRIBUTEID_EVENTNOTIFIER;
	item.monitoringMode = UA_MONITORINGMODE_REPORTING;

	UA_EventFilter fielter;
	UA_EventFilter_init(&fielter);

	UA_SimpleAttributeOperand *selectClauses = (UA_SimpleAttributeOperand*)
		UA_Array_new(2,&UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]);
	STRING *contex=malloc(sizeof(STRING)*EventFieldSelectionCount);
	if(!selectClauses){
		retval=UA_STATUSCODE_BADUNEXPECTEDERROR;
		return retval;
	}
	for(size_t i=0;i<EventFieldSelectionCount;i++){
		UA_SimpleAttributeOperand_init(&selectClauses[i]);
		selectClauses[i].typeDefinitionId = UA_NODEID_NUMERIC(0,UA_NS0ID_BASEEVENTTYPE);
		selectClauses[i].browsePathSize = (size_t *)EventFieldSelections[i].NoOfElements;
		selectClauses[i].browsePath = malloc(sizeof(UA_QualifiedName)*selectClauses[i].browsePathSize);
		if(!selectClauses[i].browsePath){
			UA_SimpleAttributeOperand_delete(selectClauses);
			retval=UA_STATUSCODE_BADUNEXPECTEDERROR;
			return retval;
		}
		selectClauses[i].attributeId = UA_ATTRIBUTEID_VALUE;
		for(int j=0;j<selectClauses[i].browsePathSize;j++){
			selectClauses[i].browsePath[j] = UA_QUALIFIEDNAME_ALLOC(0,EventFieldSelections[i].Elements[j].TargetName.Name.data);
			contex[i].data=EventFieldSelections[i].Elements[j].TargetName.Name.data;
		}
	}


	fielter.selectClauses = selectClauses;
	fielter.selectClausesSize = EventFieldSelectionCount;

	item.requestedParameters.filter.encoding = UA_EXTENSIONOBJECT_DECODED;
	item.requestedParameters.filter.content.decoded.data = &fielter;
	item.requestedParameters.filter.content.decoded.type = &UA_TYPES[UA_TYPES_EVENTFILTER];



	UA_MonitoredItemCreateResult result = UA_Client_MonitoredItems_createEvent(c,SubscriptionHdl,UA_TIMESTAMPSTORETURN_BOTH,item,contex,events_callback,NULL);
	retval=result.statusCode;
	if(result.statusCode != UA_STATUSCODE_GOOD){

		UA_MonitoredItemCreateResult_clear(&result);
		UA_Array_delete(fielter.selectClauses,EventFieldSelectionCount,&UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]);
		return retval;
	}

	*EventItemHdl = (long *)result.monitoredItemId;

	return retval;
}

u32 UA_EventItemOperateList(long ConnectionHdl,long SubscriptionHdl,u16 EventItemHdlCount,long *EventItemHdls,
							UAEventField *Fields,bool EventProcessed,
							u16 *RemainingEventCount,u32 *FieldErrorIDs){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	u32 retval=0;
	if(EventItemHdlCount>MAX_ELEMENTS_EVENTITEMLIST){
		retval=0xA0000002;
		return retval;
	}
	UA_Client_run_iterate(c, 1000);
	int i,j,flag=0;
	for(i=0;i<EventNum;i++){
		if(SubscriptionHdlzu[i]!=NULL&&SubscriptionHdl==SubscriptionHdlzu[i]){
			for(j=0;j<EventItemHdlCount;j++){
				if(EventItemHdls[j]==EventItemHdlzu[i]){
					Fields[j]=EventFields[i];
					FieldErrorIDs[j]=0;
					EventProcessed|=1;
					if(FieldErrorIDs[j]!=0){
						retval=FieldErrorIDs[j];
					}
					flag++;

				}
			}
		}
	}
	*RemainingEventCount=EventNum-flag;
	return retval;
}

u32 UA_EventItemRemoveList(long ConnectionHdl,long SubscriptionHdl,u16 EventItemHdlCount,long EventItemHdls,u32 ErrorIDs[]){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	u32 retval=0;
	if(EventItemHdlCount>MAX_ELEMENTS_EVENTITEMLIST){
		retval=0xA0000002;
		return retval;
	}
	for(int i=0;i<EventItemHdlCount;i++){
		//ErrorIDs[i]=UA_Client_Subscriptions_deleteSingle(c,SubscriptionHdl);
		EventItemHdls=0;
		ErrorIDs[i]=0;

	}
	return retval;
}
u32 UA_HistoryUpdate(long ConnectionHdl,long NodeHdl,bool PerformInsert,bool PerformReplace,u16 DataValueCount,UAHADataValue *DataValues){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	UA_NodeId *NodeID=(UA_NodeId*)NodeHdl;
	u32 retval=0;
	for(int i=0;i<DataValueCount;i++){
		UA_DataValue value;
		UA_DataValue_init(&value);
		if(value.status==NULL){
			value.status=0;
		}
		UA_Variant_setScalar(&value,DataValues[i].Values.data,&UA_TYPES[DataValues[i].Values.type-1]);
		value.sourceTimestamp=DataValues[i].SourceTimeStamp;
		value.serverTimestamp=DataValues[i].ServerTimeStamp;
		if(PerformInsert==1&&PerformReplace==0){
			retval=UA_Client_HistoryUpdate_insert(c,NodeID,&value);
		}else if(PerformInsert==0&&PerformReplace==1){
			retval=UA_Client_HistoryUpdate_replace(c,NodeID,&value);
		}else if(PerformInsert==1&&PerformReplace==1){
			retval=UA_Client_HistoryUpdate_update(c,NodeID,&value);
		}else{
			retval=UA_STATUSCODE_BADUNEXPECTEDERROR;
		}
	}
	return retval;
}

u32 UA_ConnectionGetStatus(long ConnectionHdl,UAConnectionStatus *ConnectionStatus,UAServerState *ServerState,u8 *ServiceLevel){
	UA_Client *c = (UA_Client*)ConnectionHdl;
	UA_SecureChannelState channelState;
	UA_SessionState sessionState;
	UA_StatusCode connectStatus;
	UA_Client_getState(c,&channelState,&sessionState,&connectStatus);
	switch(channelState){
		case UA_SECURECHANNELSTATE_OPEN:*ConnectionStatus=UACS_Connected;break;
		case UA_SECURECHANNELSTATE_CLOSED:*ConnectionStatus=UACS_Shutdown;break;
		case UA_SECURECHANNELSTATE_CLOSING:*ConnectionStatus=UACS_ConnectionError;break;
		default:*ConnectionStatus=UACS_Connected;break;
	}
	switch(sessionState){
		case UA_SESSIONSTATE_ACTIVATED:*ServerState=UASS_Running;break;
		case UA_SESSIONSTATE_CLOSED:*ServerState=UASS_Shutdown;break;
		case UA_SESSIONSTATE_CLOSING:*ServerState=UASS_Suspended;break;
		default:*ServerState=UASS_Unknown;break;
	}
	*ServiceLevel=127;
	return connectStatus;
}

void UA_Value_init(UA_Value *p) {
	memset(p, 0, sizeof(UA_Value));
}

struct mytm {
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon;
    int tm_year;
};

TIME UA_DateTimeFromStruct(UADateTimeStruct ts){
	 /* Seconds since the Unix epoch */
    struct mytm tm;
    memset(&tm, 0, sizeof(struct mytm));
    tm.tm_year = ts.year - 1900;
    tm.tm_mon = ts.month - 1;
    tm.tm_mday = ts.day;
    tm.tm_hour = ts.hour;
    tm.tm_min = ts.min;
    tm.tm_sec = ts.sec;
    long long sec_epoch = __tm_to_secs(&tm);

    UA_DateTime t = UA_DATETIME_UNIX_EPOCH;
    t += sec_epoch * UA_DATETIME_SEC;
    t += ts.milliSec * UA_DATETIME_MSEC;
    t += ts.microSec * UA_DATETIME_USEC;
    t += ts.nanoSec / 100;
    return t;
}

unsigned int UA_Client_readNode(long client, char *NodeName, UA_Value *outValue) {
	UA_Client *c = (UA_Client*)client;
	const UA_NodeId nodeId = UA_NODEID_STRING(1, NodeName);
	UA_Variant value;
	UA_StatusCode retval;
	UA_Variant_init(&value);
	retval=UA_Client_readValueAttribute(c, nodeId,&value);
	int i;
	if (retval == UA_STATUSCODE_GOOD) {
		for (i = 0; i < 24; i++) {
			UA_Boolean flag = UA_Variant_hasScalarType(&value, &UA_TYPES[i]);
			if (flag == 1) break;
		}
		outValue->type = i;
		outValue->data = value.data;
	}
	return retval;
}

unsigned int UA_printValue(UA_Value *value) {
	if (value->data != NULL&&value->type != NULL) {
		switch (value->type)
		{
			case UA_TYPES_BOOLEAN:{
				UA_Boolean variableValue = *(UA_Boolean*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %d\n", variableValue);
				break;
			}
			case UA_TYPES_SBYTE:{
				UA_SByte variableValue = *(UA_SByte*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: 0x%x\n", (unsigned char)variableValue);
				break;
			}
			case UA_TYPES_BYTE:{
				UA_Byte variableValue = *(UA_Byte*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: 0x%x\n", variableValue);
				break;
			}
			case UA_TYPES_INT16:{
				UA_Int16 variableValue = *(UA_Int16*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %hd\n", variableValue);
				break;
			}
			case UA_TYPES_UINT16:{
				UA_UInt16 variableValue = *(UA_UInt16*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %hu\n", variableValue);
				break;
			}
			case UA_TYPES_INT32: {
				UA_Int32 variableValue = *(UA_Int32*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %d\n", variableValue);
				break;
			}
			case UA_TYPES_UINT32: {
				UA_UInt32 variableValue = *(UA_UInt32*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %u\n", variableValue);
				break;
			}
			case UA_TYPES_INT64: {
				UA_Int64 variableValue = *(UA_Int64*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %lld\n", variableValue);
				break;
			}
			case UA_TYPES_UINT64: {
				UA_UInt64 variableValue = *(UA_UInt64*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %llu\n", variableValue);
				break;
			}
			case UA_TYPES_FLOAT:{
				UA_Float variableValue = *(UA_Float*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %f\n", variableValue);
				break;
			}
			case UA_TYPES_DOUBLE: {
				UA_Double variableValue = *(UA_Double*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %f\n", variableValue);
				break;
			}
			case UA_TYPES_STRING: {
				UA_String variableValue = *(UA_String*)value->data;
				UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Variable Value is: %s\n", variableValue.data);
				break;
			}
		default:
			return 1;
		}
		return UA_STATUSCODE_GOOD;
	}
	return 1;

}

static void printTimestamp(char *name, UA_DateTime date)
{
    UA_DateTimeStruct dts = UA_DateTime_toStruct(date);
    if (name){
        printf("%s: %02u-%02u-%04u %02u:%02u:%02u.%03u, ", name,
               dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
	}
    else
        printf("%02u-%02u-%04u %02u:%02u:%02u.%03u, ",
               dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
}

static void printDataValue(UA_DataValue *value)
{
    // Print status and timestamps
    if (value->hasServerTimestamp){
		printTimestamp("ServerTime", value->serverTimestamp);
	}
    if (value->hasSourceTimestamp)
        printTimestamp("SourceTime", value->sourceTimestamp);

    if (value->hasStatus)
        printf("Status 0x%08x, ", value->status);

    if (value->value.type == &UA_TYPES[UA_TYPES_INT32]) {
        UA_UInt32 hrValue = *(UA_UInt32 *)value->value.data;
        printf("Uint32Value %u\n", hrValue);
    }

    if (value->value.type == &UA_TYPES[UA_TYPES_DOUBLE]) {
        UA_Double hrValue = *(UA_Double *)value->value.data;
        printf("DoubleValue %f\n", hrValue);
    }
}

static UA_Boolean readRaw(const UA_HistoryData *data)
{
    printf("readRaw Value count: %lu\n", (long unsigned)data->dataValuesSize);

    // Iterate over all values
    for (UA_UInt32 i = 0; i < data->dataValuesSize; ++i)
    {
        printDataValue(&data->dataValues[i]);
    }

    // We want more data!
    return true;
}



UA_Boolean readHist(UA_Client *client, const UA_NodeId *nodeId,
                        UA_Boolean moreDataAvailable,
                        const UA_ExtensionObject *data, void *unused)
{
    printf("\nRead historical callback:\n");
    printf("\tHas more data:\t%d\n\n", moreDataAvailable);
    if (data->content.decoded.type == &UA_TYPES[UA_TYPES_HISTORYDATA])
    {
        return readRaw((UA_HistoryData*)data->content.decoded.data);
    }

    return true;
}


unsigned int UA_Client_writeValue(long client,char *NodeName,void *value,int type) {
	UA_Client *c = (UA_Client*)client;
	const UA_NodeId nodeId = UA_NODEID_STRING(1, NodeName);
	UA_Variant newValue;
	UA_Variant_init(&newValue);
	UA_Variant_setScalar(&newValue,value,&UA_TYPES[type]);
	UA_StatusCode retval;
	retval = UA_Client_writeValueAttribute(c, nodeId, &newValue);
	return retval;
}

unsigned int
UA_Client_HistoryRead(long client, char *NodeName) {
	UA_Client *c = (UA_Client*)client;
	const UA_NodeId nodeId = UA_NODEID_STRING(1, NodeName);
	return UA_Client_HistoryRead_raw(c,&nodeId,readHist,
										UA_DateTime_fromUnixTime(0), UA_DateTime_now(),
										UA_STRING_NULL, false, 10,
										UA_TIMESTAMPSTORETURN_BOTH, NULL);
}

const char * emptyStatusCodeName = "";
const char * UA_StatusCodeName(UA_StatusCode code) {
    return emptyStatusCodeName;
}

void UA_Value_Clear(UA_Value *p) {
	free(p);
}
void Browse(long client){
	UA_Client *c = (UA_Client*)client;
	UA_NodeId parent = UA_NODEID_STRING(0, "A1");
	UA_Client_forEachChildNodeCall(c,parent,nodeIter, &parent);
}

static UA_StatusCode
nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle) {
	if (isInverse)
		return UA_STATUSCODE_GOOD;
	UA_NodeId *parent = (UA_NodeId *)handle;
	switch (childId.identifierType)
	{
		case UA_NODEIDTYPE_NUMERIC:
		printf("%d, %d --- %d ---> NodeId %d, %d\n",
			parent->namespaceIndex, parent->identifier.numeric,
			referenceTypeId.identifier.numeric, childId.namespaceIndex,
			childId.identifier.numeric);
		break;
		case UA_NODEIDTYPE_STRING:
		printf("%d, %d --- %d ---> NodeId %d, %s\n",
			parent->namespaceIndex, parent->identifier.numeric,
			referenceTypeId.identifier.numeric, childId.namespaceIndex,
			childId.identifier.string.data);
		break;
		case UA_NODEIDTYPE_GUID:
		break;
		case UA_NODEIDTYPE_BYTESTRING:
		break;
	default:
		break;
	}

	return UA_STATUSCODE_GOOD;
}






// unsigned int UA_SubscriptionCreate1(UA_Client *client,bool PublishingEnable,UA_Byte Priority)
// {
//     /* Create a subscription */
//     UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default();
//     UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(client, request,
//                                                                             NULL, NULL, NULL);

//     UA_UInt32 subId = response.subscriptionId;
//     if(response.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
//     {
//         UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT, "Create subscription succeeded, id %u\n", subId);
//     }
// 	unsigned int retval=response.responseHeader.serviceResult;
// 	return retval;

// }



void UA_readNodeList(u32 client){
	UA_Client *c = (UA_Client*)client;
	UA_String *namespaceUri;
	//UA_String_init(namespaceUri);
	UA_UInt16 *namespaceIndex;
	UA_Client_NamespaceGetIndex(c,namespaceUri,namespaceIndex);
}

// unsigned int UA_MethodCall(long client){

// }

// unsigned int UA_ReadList(bool Execute,long client,u16 NodeHdlCount,u32 *NodeHdls,UANodeAdditionalInfo *NodeAddInfos,
// 							TIME Timeout,UA_ReadListOutput *output,Variable_Identification *Variables){
// 	UA_Client *c = (UA_Client*)client;
// 	int i;
// 	UA_Value value;
// 	UA_Value_init(&value);
// 	for(i=0;i<NodeHdlCount;i++){
// 		UA_Client_readNode(c,NodeHdls,&value);

// 	}
// }

long UA_NodeID_STRING(int NS,char *NodeName){
	UA_NodeId *targetNodeId=malloc(sizeof(UA_NodeId));
	*targetNodeId = UA_NODEID_STRING(NS, NodeName);
	long *output = (long *)targetNodeId;
	return *output;
}

void UA_Client_Delete(long client) {
	UA_Client *c = (UA_Client*)client;
	UA_Client_delete(c);
}

void saveUA_ReferenceDescriptionToUAReferenceDescription(int j,UA_ReferenceDescription *ref,UAReferenceDescription *BrowseResult){
	memcpy(BrowseResult[j].BrowseName.data,ref->browseName.name.data,ref->browseName.name.length);
	BrowseResult[j].BrowseName.length=ref->browseName.name.length;
	memcpy(BrowseResult[j].DisplayName.Locale,ref->displayName.locale.data,ref->displayName.locale.length);
	memcpy(BrowseResult[j].DisplayName.Text.data,ref->displayName.text.data,ref->displayName.text.length);
	BrowseResult[j].IsForward=ref->isForward;
	BrowseResult[j].NodeClass=ref->nodeClass;
	BrowseResult[j].NodeID.ID.NamespaceIndex=ref->nodeId.nodeId.namespaceIndex;
	BrowseResult[j].NodeID.ID.IdentifierType=ref->nodeId.nodeId.identifierType;
	BrowseResult[j].NodeID.ID.Identifier.length=ref->nodeId.nodeId.identifier.string.length;
	BrowseResult[j].NodeID.ID.Identifier.data=ref->nodeId.nodeId.identifier.string.data;
	BrowseResult[j].NodeID.NamespaceURI.length=ref->nodeId.namespaceUri.length;
	memcpy(BrowseResult[j].NodeID.NamespaceURI.data,ref->nodeId.namespaceUri.data,ref->nodeId.namespaceUri.length);
	BrowseResult[j].NodeID.ServerIndex=ref->nodeId.serverIndex;
	BrowseResult[j].ReferenceTypeID.NamespaceIndex=ref->referenceTypeId.namespaceIndex;
	BrowseResult[j].ReferenceTypeID.IdentifierType=ref->referenceTypeId.identifierType;
	BrowseResult[j].ReferenceTypeID.Identifier.length=ref->referenceTypeId.identifier.string.length;
	//memcpy(BrowseResult[j].ReferenceTypeID.Identifier.data,ref->referenceTypeId.identifier.string.data,ref->referenceTypeId.identifier.string.length);
	BrowseResult[j].TypeDefinition.ID.NamespaceIndex=ref->typeDefinition.nodeId.namespaceIndex;
	BrowseResult[j].TypeDefinition.ID.IdentifierType=ref->typeDefinition.nodeId.identifierType;
	BrowseResult[j].TypeDefinition.ID.Identifier.length=ref->typeDefinition.nodeId.identifier.string.length;
	memcpy(BrowseResult[j].TypeDefinition.ID.Identifier.data,ref->typeDefinition.nodeId.identifier.string.data,ref->typeDefinition.nodeId.identifier.string.length);
	BrowseResult[j].TypeDefinition.NamespaceURI.length=ref->typeDefinition.namespaceUri.length;
	memcpy(BrowseResult[j].TypeDefinition.NamespaceURI.data,ref->typeDefinition.namespaceUri.data,ref->typeDefinition.namespaceUri.length);
	BrowseResult[j].TypeDefinition.ServerIndex=ref->typeDefinition.serverIndex;
}
