Merge branch 'master' of mz-automation.de:libiec61850
This commit is contained in:
commit
1e018287b2
20 changed files with 217 additions and 77 deletions
|
@ -111,7 +111,10 @@ namespace IEC61850
|
|||
static extern IntPtr IedConnection_getLogicalNodeDirectory (IntPtr self, out int error, string logicalNodeReference, int acsiClass);
|
||||
|
||||
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
|
||||
static extern IntPtr IedConnection_getServerDirectory (IntPtr self, out int error, bool getFileNames);
|
||||
static extern IntPtr IedConnection_getServerDirectory (IntPtr self, out int error, bool getFileNames);
|
||||
|
||||
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern void IedConnection_getDeviceModelFromServer(IntPtr self, out int error);
|
||||
|
||||
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
|
||||
static extern IntPtr IedConnection_getLogicalDeviceDirectory (IntPtr self, out int error, string logicalDeviceName);
|
||||
|
@ -253,7 +256,17 @@ namespace IEC61850
|
|||
ControlObject controlObject = new ControlObject (objectReference, connection, this);
|
||||
|
||||
return controlObject;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateDeviceModel()
|
||||
{
|
||||
int error;
|
||||
|
||||
IedConnection_getDeviceModelFromServer(connection, out error);
|
||||
|
||||
if (error != 0)
|
||||
throw new IedConnectionException("UpdateDeviceModel failed", error);
|
||||
}
|
||||
|
||||
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
|
||||
public List<string> GetServerDirectory (bool fileDirectory = false)
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
|
|
|
@ -85,10 +85,10 @@ editSgConfirmedHandler(void* parameter, SettingGroupControlBlock* sgcb,
|
|||
{
|
||||
printf("Received edit sg confirm for sg %i\n", editSg);
|
||||
|
||||
ptoc1Settings[editSg - 1].strVal = MmsValue_toFloat(IEDMODEL_PROT_PTOC1_StrVal_setMag_f->mmsValue);
|
||||
ptoc1Settings[editSg - 1].opDlTmms = MmsValue_toInt32(IEDMODEL_PROT_PTOC1_OpDlTmms_setVal->mmsValue);
|
||||
ptoc1Settings[editSg - 1].rsDlTmms = MmsValue_toInt32(IEDMODEL_PROT_PTOC1_RsDlTmms_setVal->mmsValue);
|
||||
ptoc1Settings[editSg - 1].rstTms = MmsValue_toInt32(IEDMODEL_PROT_PTOC1_RstTms_setVal->mmsValue);
|
||||
ptoc1Settings[editSg - 1].strVal = MmsValue_toFloat(IEDMODEL_SE_PROT_PTOC1_StrVal_setMag_f->mmsValue);
|
||||
ptoc1Settings[editSg - 1].opDlTmms = MmsValue_toInt32(IEDMODEL_SE_PROT_PTOC1_OpDlTmms_setVal->mmsValue);
|
||||
ptoc1Settings[editSg - 1].rsDlTmms = MmsValue_toInt32(IEDMODEL_SE_PROT_PTOC1_RsDlTmms_setVal->mmsValue);
|
||||
ptoc1Settings[editSg - 1].rstTms = MmsValue_toInt32(IEDMODEL_SE_PROT_PTOC1_RstTms_setVal->mmsValue);
|
||||
|
||||
if (IedServer_getActiveSettingGroup(iedServer, sgcb) == editSg) {
|
||||
loadActiveSgValues(editSg);
|
||||
|
|
|
@ -231,4 +231,3 @@ StringUtils_startsWith(char* string, char* prefix)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -54,15 +54,44 @@ typedef struct sSocket* Socket;
|
|||
/** Opaque reference for a set of server and socket handles */
|
||||
typedef struct sHandleSet* HandleSet;
|
||||
|
||||
/**
|
||||
* \brief Create a new connection handle set (HandleSet)
|
||||
*
|
||||
* \return new HandleSet instance
|
||||
*/
|
||||
HandleSet
|
||||
Handleset_new(void);
|
||||
|
||||
/**
|
||||
* \brief add a soecket to an existing handle set
|
||||
*
|
||||
* \param self the HandleSet instance
|
||||
* \param sock the socket to add
|
||||
*/
|
||||
void
|
||||
Handleset_addSocket(HandleSet self, const Socket sock);
|
||||
|
||||
|
||||
/**
|
||||
* \brief wait for a socket to become ready
|
||||
*
|
||||
* This function is corresponding to the BSD socket select function.
|
||||
* It returns the number of sockets on which data is pending or 0 if no data is pending
|
||||
* on any of the monitored connections. The function will return after "timeout" ms if no
|
||||
* data is pending.
|
||||
* The function shall return -1 if a socket error occures.
|
||||
*
|
||||
* \param self the HandleSet instance
|
||||
* \param timeout in milliseconds (ms)
|
||||
*/
|
||||
int
|
||||
Handleset_waitReady(HandleSet self, unsigned int timeoutMs);
|
||||
|
||||
/**
|
||||
* \brief destroy the HandleSet instance
|
||||
*
|
||||
* \param self the HandleSet instance to destroy
|
||||
*/
|
||||
void
|
||||
Handleset_destroy(HandleSet self);
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
|
|||
{
|
||||
int result;
|
||||
|
||||
if (self != NULL && self->maxHandle >= 0) {
|
||||
if ((self != NULL) && (self->maxHandle >= 0)) {
|
||||
struct timeval timeout;
|
||||
|
||||
timeout.tv_sec = timeoutMs / 1000;
|
||||
|
|
|
@ -56,7 +56,7 @@ struct sServerSocket {
|
|||
|
||||
struct sHandleSet {
|
||||
fd_set handles;
|
||||
int maxHandle;
|
||||
SOCKET maxHandle;
|
||||
};
|
||||
|
||||
HandleSet
|
||||
|
@ -66,7 +66,7 @@ Handleset_new(void)
|
|||
|
||||
if (result != NULL) {
|
||||
FD_ZERO(&result->handles);
|
||||
result->maxHandle = -1;
|
||||
result->maxHandle = INVALID_SOCKET;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -74,11 +74,11 @@ Handleset_new(void)
|
|||
void
|
||||
Handleset_addSocket(HandleSet self, const Socket sock)
|
||||
{
|
||||
if (self != NULL && sock != NULL && sock->fd != -1) {
|
||||
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET) {
|
||||
FD_SET(sock->fd, &self->handles);
|
||||
if (sock->fd > self->maxHandle) {
|
||||
|
||||
if ((sock->fd > self->maxHandle) || (self->maxHandle == INVALID_SOCKET))
|
||||
self->maxHandle = sock->fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,16 +302,6 @@ Socket_connect(Socket self, const char* address, int port)
|
|||
FD_ZERO(&fdSet);
|
||||
FD_SET(self->fd, &fdSet);
|
||||
|
||||
// if (connect(self->fd, (struct sockaddr *) &serverAddress,sizeof(serverAddress)) < 0) {
|
||||
// if (DEBUG_SOCKET)
|
||||
// printf("WIN32_SOCKET: Socket failed connecting!\n");
|
||||
// return false;
|
||||
// }
|
||||
// else {
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
|
||||
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) {
|
||||
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
return false;
|
||||
|
@ -321,7 +311,7 @@ Socket_connect(Socket self, const char* address, int port)
|
|||
timeout.tv_sec = self->connectTimeout / 1000;
|
||||
timeout.tv_usec = (self->connectTimeout % 1000) * 1000;
|
||||
|
||||
if (select(self->fd + 1, NULL, &fdSet, NULL, &timeout) == SOCKET_ERROR)
|
||||
if (select(self->fd + 1, NULL, &fdSet, NULL, &timeout) < 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
|
|
@ -237,7 +237,7 @@ ClientGooseControlBlock_setDstAddress_vid(ClientGooseControlBlock self, uint16_t
|
|||
self->dstAddress = newEmptyPhyCommAddress();
|
||||
|
||||
MmsValue* vid = MmsValue_getElement(self->dstAddress, 2);
|
||||
MmsValue_setUint8(vid, vidValue);
|
||||
MmsValue_setUint16(vid, vidValue);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
|
@ -256,7 +256,7 @@ ClientGooseControlBlock_setDstAddress_appid(ClientGooseControlBlock self, uint16
|
|||
self->dstAddress = newEmptyPhyCommAddress();
|
||||
|
||||
MmsValue* appid = MmsValue_getElement(self->dstAddress, 3);
|
||||
MmsValue_setUint8(appid, appidValue);
|
||||
MmsValue_setUint16(appid, appidValue);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -328,6 +328,8 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
|
|||
|
||||
char* rptId = report->rptId;
|
||||
|
||||
printf("Report ID is null!\n");
|
||||
|
||||
if (rptId == NULL)
|
||||
rptId = report->rcbReference;
|
||||
|
||||
|
|
|
@ -195,47 +195,70 @@ ClientDataSet_getDataSetSize(ClientDataSet self)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
doesControlObjectMatch(char* objRef, char* cntrlObj)
|
||||
bool
|
||||
private_IedConnection_doesControlObjectMatch(char* objRef, char* cntrlObj)
|
||||
{
|
||||
int objRefLen = strlen(objRef);
|
||||
int i = 0;
|
||||
|
||||
char* separator = strchr(cntrlObj, '$');
|
||||
while (objRef[i] != '/') {
|
||||
if (objRef[i] != cntrlObj[i])
|
||||
return false;
|
||||
|
||||
if (separator == NULL)
|
||||
i++;
|
||||
}
|
||||
|
||||
if (cntrlObj[i] != '/')
|
||||
return false;
|
||||
|
||||
int sepLen = separator - cntrlObj;
|
||||
// --> LD is equal
|
||||
|
||||
if (sepLen >= objRefLen)
|
||||
i++;
|
||||
|
||||
while (objRef[i] != '.') {
|
||||
if (objRef[i] != cntrlObj[i])
|
||||
return false;
|
||||
i++;
|
||||
}
|
||||
|
||||
int j = i;
|
||||
|
||||
if (cntrlObj[j++] != '$')
|
||||
return false;
|
||||
|
||||
if (memcmp(objRef, cntrlObj, sepLen) != 0)
|
||||
// --> LN is equal
|
||||
|
||||
if (cntrlObj[j++] != 'C')
|
||||
return false;
|
||||
if (cntrlObj[j++] != 'O')
|
||||
return false;
|
||||
if (cntrlObj[j++] != '$')
|
||||
return false;
|
||||
|
||||
char* cntrlObjName = objRef + sepLen + 1;
|
||||
// --> FC is ok
|
||||
|
||||
if (separator[1] != 'C')
|
||||
return false;
|
||||
if (separator[2] != 'O')
|
||||
return false;
|
||||
if (separator[3] != '$')
|
||||
return false;
|
||||
i++;
|
||||
|
||||
char* nextSeparator = strchr(separator + 4, '$');
|
||||
while (objRef[i] != 0) {
|
||||
if (cntrlObj[j] == 0)
|
||||
return false;
|
||||
|
||||
if (nextSeparator == NULL)
|
||||
return false;
|
||||
if (objRef[i] == '.') {
|
||||
if (cntrlObj[j] != '$')
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (objRef[i] != cntrlObj[j])
|
||||
return false;
|
||||
}
|
||||
|
||||
int cntrlObjNameLen = strlen(cntrlObjName);
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
if (cntrlObjNameLen != nextSeparator - (separator + 4))
|
||||
return false;
|
||||
|
||||
if (memcmp(cntrlObjName, separator + 4, cntrlObjNameLen) == 0)
|
||||
if ((cntrlObj[j] == 0) || (cntrlObj[j] == '$'))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -357,7 +380,7 @@ handleLastApplErrorMessage(IedConnection self, MmsValue* lastApplError)
|
|||
|
||||
char* objectRef = ControlObjectClient_getObjectReference(object);
|
||||
|
||||
if (doesControlObjectMatch(objectRef, MmsValue_toString(cntrlObj))) {
|
||||
if (private_IedConnection_doesControlObjectMatch(objectRef, MmsValue_toString(cntrlObj))) {
|
||||
ControlObjectClient_setLastApplError(object, self->lastApplError);
|
||||
}
|
||||
|
||||
|
@ -966,9 +989,8 @@ IedConnection_getDeviceModelFromServer(IedConnection self, IedClientError* error
|
|||
|
||||
LinkedList_destroy(logicalDeviceNames);
|
||||
}
|
||||
else {
|
||||
else
|
||||
*error = iedConnection_mapMmsErrorToIedError(mmsError);
|
||||
}
|
||||
}
|
||||
|
||||
LinkedList /*<char*>*/
|
||||
|
|
|
@ -607,13 +607,16 @@ typedef void (*ReportCallbackFunction) (void* parameter, ClientReport report);
|
|||
/**
|
||||
* \brief Install a report handler function for the specified report control block (RCB)
|
||||
*
|
||||
* It is important that you provide a ClientDataSet instance that is already populated with an MmsValue object
|
||||
* of type MMS_STRUCTURE that contains the data set entries as structure elements. This is required because otherwise
|
||||
* the report handler is not able to correctly parse the report message from the server.
|
||||
* This function will replace a report handler set earlier for the specified RCB. The report handler
|
||||
* will be called whenever a report for the specified RCB is received.
|
||||
* Please note that this function should be called whenever the RCB data set is changed or updated.
|
||||
* Otherwise the internal data structures storing the received data set values will not be updated
|
||||
* correctly.
|
||||
*
|
||||
* This function will replace a formerly set report handler function for the specified RCB.
|
||||
* When replacing a report handler you only have to call this function. There is no separate call to
|
||||
* IedConnection_uninstallReportHandler() required.
|
||||
*
|
||||
* \param connection the connection object
|
||||
* \param self the connection object
|
||||
* \param rcbReference object reference of the report control block
|
||||
* \param rptId a string that identifies the report. If the rptId is not available then the
|
||||
* rcbReference is used to identify the report.
|
||||
|
@ -626,6 +629,9 @@ IedConnection_installReportHandler(IedConnection self, char* rcbReference, char*
|
|||
|
||||
/**
|
||||
* \brief uninstall a report handler function for the specified report control block (RCB)
|
||||
*
|
||||
* \param self the connection object
|
||||
* \param rcbReference object reference of the report control block
|
||||
*/
|
||||
void
|
||||
IedConnection_uninstallReportHandler(IedConnection self, char* rcbReference);
|
||||
|
|
|
@ -253,36 +253,52 @@ struct sGSEControlBlock {
|
|||
/**
|
||||
* \brief get the number of direct children of a model node
|
||||
*
|
||||
* \param node the model node instance
|
||||
* \param self the model node instance
|
||||
*
|
||||
* \return the number of children of the model node
|
||||
* ¸
|
||||
*/
|
||||
int
|
||||
ModelNode_getChildCount(ModelNode* modelNode);
|
||||
ModelNode_getChildCount(ModelNode* self);
|
||||
|
||||
/**
|
||||
* \brief return a child model node
|
||||
*
|
||||
* \param node the model node instance
|
||||
* \param the name of the child model node
|
||||
* \param self the model node instance
|
||||
* \param name the name of the child model node
|
||||
*
|
||||
* \return the model node instance or NULL if model node does not exist.
|
||||
*/
|
||||
ModelNode*
|
||||
ModelNode_getChild(ModelNode* modelNode, const char* name);
|
||||
ModelNode_getChild(ModelNode* self, const char* name);
|
||||
|
||||
/**
|
||||
* \brief return a child model node with a given functional constraint
|
||||
*
|
||||
* Sometimes the name is not enough to identify a model node. This is the case when
|
||||
* editable setting groups are used. In this case the setting group members have two different
|
||||
* model nodes associated that differ in their FC (SG and SE).
|
||||
*
|
||||
* \param self the model node instance
|
||||
* \param name the name of the child model node
|
||||
* \param fc the functional constraint of the model node
|
||||
*
|
||||
* \return the model node instance or NULL if model node does not exist.
|
||||
*/
|
||||
ModelNode*
|
||||
ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint fc);
|
||||
|
||||
/**
|
||||
* \brief Return the IEC 61850 object reference of a model node
|
||||
*
|
||||
* \param node the model node instance
|
||||
* \param self the model node instance
|
||||
* \param objectReference pointer to a buffer where to write the object reference string. If NULL
|
||||
* is given the buffer is allocated by the function.
|
||||
*
|
||||
* \return the object reference string
|
||||
*/
|
||||
char*
|
||||
ModelNode_getObjectReference(ModelNode* node, char* objectReference);
|
||||
ModelNode_getObjectReference(ModelNode* self, char* objectReference);
|
||||
|
||||
/**
|
||||
* \brief Set the name of the IED
|
||||
|
|
|
@ -71,6 +71,9 @@ struct sClientReportControlBlock {
|
|||
IedClientError
|
||||
private_IedConnection_mapMmsErrorToIedError(MmsError mmsError);
|
||||
|
||||
bool
|
||||
private_IedConnection_doesControlObjectMatch(char* objRef, char* cntrlObj);
|
||||
|
||||
void
|
||||
private_IedConnection_addControlClient(IedConnection self, ControlObjectClient control);
|
||||
|
||||
|
|
|
@ -1602,6 +1602,7 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
|
|||
if ((val > 0) && (val <= sg->sgcb->numOfSGs)) {
|
||||
|
||||
if (sg->editSgChangedHandler != NULL) {
|
||||
|
||||
if (sg->editSgChangedHandler(sg->editSgChangedHandlerParameter, sg->sgcb,
|
||||
(uint8_t) val, (ClientConnection) connection))
|
||||
{
|
||||
|
|
|
@ -328,7 +328,6 @@ sendReport(ReportControl* self, bool isIntegrity, bool isGI)
|
|||
if (self->inclusionFlags[i] != REPORT_CONTROL_NONE)
|
||||
addReferenceForEntry = true;
|
||||
|
||||
|
||||
if (addReferenceForEntry) {
|
||||
|
||||
char dataReference[130];
|
||||
|
|
|
@ -58,7 +58,6 @@ readLine(FileHandle fileHandle, uint8_t* buffer, int maxSize)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (fileReadResult > 0) {
|
||||
while (fileReadResult > 0) {
|
||||
fileReadResult = FileSystem_readFile(fileHandle, buffer + bufPos, 1);
|
||||
|
@ -238,8 +237,12 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
|
|||
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
|
||||
else if (StringUtils_startsWith((char*) lineBuffer, "SG")) {
|
||||
|
||||
if (strcmp(currentLN->name, "LLN0") != 0)
|
||||
if (strcmp(currentLN->name, "LLN0") != 0) {
|
||||
if (DEBUG_IED_SERVER)
|
||||
printf("Setting group control is not defined in LLN0\n");
|
||||
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
int actSG;
|
||||
int numOfSGs;
|
||||
|
@ -253,8 +256,12 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
|
|||
}
|
||||
#endif /* (CONFIG_IEC61850_SETTING_GROUPS == 1) */
|
||||
|
||||
else
|
||||
else {
|
||||
// if (DEBUG_IED_SERVER)
|
||||
printf("IED_SERVER: Unknown identifier (%s)\n", lineBuffer);
|
||||
|
||||
goto exit_error;
|
||||
}
|
||||
|
||||
}
|
||||
else if (indendation > 3) {
|
||||
|
@ -423,8 +430,8 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
|
|||
return model;
|
||||
|
||||
exit_error:
|
||||
if (DEBUG_IED_SERVER)
|
||||
printf("error parsing line %i\n", currentLine);
|
||||
// if (DEBUG_IED_SERVER)
|
||||
printf("IED_SERVER: error parsing line %i (indendation level = %i)\n", currentLine, indendation);
|
||||
IedModel_destroy(model);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -457,6 +457,56 @@ ModelNode_getChild(ModelNode* self, const char* name)
|
|||
return matchingNode;
|
||||
}
|
||||
|
||||
ModelNode*
|
||||
ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint fc)
|
||||
{
|
||||
// check for separator
|
||||
const char* separator = strchr(name, '.');
|
||||
|
||||
int nameElementLength = 0;
|
||||
|
||||
if (separator != NULL)
|
||||
nameElementLength = (separator - name);
|
||||
else
|
||||
nameElementLength = strlen(name);
|
||||
|
||||
ModelNode* nextNode = self->firstChild;
|
||||
|
||||
ModelNode* matchingNode = NULL;
|
||||
|
||||
while (nextNode != NULL) {
|
||||
int nodeNameLen = strlen(nextNode->name);
|
||||
|
||||
if (nodeNameLen == nameElementLength) {
|
||||
if (memcmp(nextNode->name, name, nodeNameLen) == 0) {
|
||||
|
||||
if (separator == NULL) {
|
||||
if (nextNode->modelType == DataAttributeModelType) {
|
||||
DataAttribute* da = (DataAttribute*) nextNode;
|
||||
|
||||
if (da->fc == fc) {
|
||||
matchingNode = nextNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
matchingNode = nextNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nextNode = nextNode->sibling;
|
||||
}
|
||||
|
||||
if ((separator != NULL) && (matchingNode != NULL)) {
|
||||
return ModelNode_getChildWithFc(matchingNode, separator + 1, fc);
|
||||
}
|
||||
else
|
||||
return matchingNode;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
LogicalNode*
|
||||
|
|
|
@ -338,10 +338,7 @@ IsoSession_createFinishSpdu(IsoSession* self, BufferChain buffer, BufferChain pa
|
|||
|
||||
buf[offset++] = 9; /* FINISH-SPDU code */
|
||||
|
||||
buf[offset++] = 5 + payload->length; /* LI */
|
||||
buf[offset++] = 17; /* PI-Code transport-disconnect */
|
||||
buf[offset++] = 1; /* LI = 1 */
|
||||
buf[offset++] = 2; /* transport-connection-released */
|
||||
buf[offset++] = 2 + payload->length; /* LI */
|
||||
buf[offset++] = 193; /* PGI-Code user data */
|
||||
buf[offset++] = payload->length; /* LI of user data */
|
||||
|
||||
|
|
|
@ -481,4 +481,5 @@ EXPORTS
|
|||
IedServer_getUTCTimeAttributeValue
|
||||
IedServer_getBitStringAttributeValue
|
||||
IedServer_getStringAttributeValue
|
||||
ModelNode_getChildWithFc
|
||||
|
||||
|
|
|
@ -505,4 +505,5 @@ EXPORTS
|
|||
IedServer_getUTCTimeAttributeValue
|
||||
IedServer_getBitStringAttributeValue
|
||||
IedServer_getStringAttributeValue
|
||||
|
||||
ModelNode_getChildWithFc
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue