mz-automation / libiec61850

Official repository for libIEC61850, the open-source library for the IEC 61850 protocols
http://libiec61850.com/libiec61850
GNU General Public License v3.0
857 stars 459 forks source link

How to deal with EntryID of ClientReportControlBlock? #47

Open codebuks opened 6 years ago

codebuks commented 6 years ago

I created a client and wanted to receive reports form an IED(I use IEDSCout as my Simulator). but everytime i restart my client, I will receviced the whole reports buffered by the server. I followed the method search from internet which says writing the entryId , but it does not work, my code is as follows, can you help me?

here are the tissues from http://iec61850.tissue-db.com: BRCB entryID EntryID needs clarification

/*
 * client_example1.c
 *
 * This example is intended to be used with server_example3 or server_example_goose.
 */

#include "iec61850_client.h"

#include "stack_config.h"

#include "ied_connection_private.h"

#include "libiec61850_platform_includes.h"
#include <stdlib.h>
#include <stdio.h>

#include "hal_thread.h"
void
ClientReportControlBlock_setEntryId_ex(ClientReportControlBlock self, MmsValue* entryId)
{
    if (self->entryId != NULL) {
        bool r = MmsValue_update(self->entryId, entryId);
        printf("ClientReportControlBlock_setEntryId_ex MmsValue_update:%d\n",r);
    }
    else {
        if (MmsValue_getType(entryId) != MMS_OCTET_STRING) {
            if (DEBUG_IED_CLIENT)
                printf("IED_CLIENT: ClientReportControlBlock_setEntryId invalid argument type\n");
        }
        else
            self->entryId = MmsValue_clone(entryId);
    }
}
void
reportCallbackFunction(void* parameter, ClientReport report)
{
    MmsValue* dataSetValues = ClientReport_getDataSetValues(report);
    char* reportId = ClientReport_getRptId(report);
    uint16_t reportSeqNum = ClientReport_getSeqNum(report);
    printf("reportId %s,reportSeqNum %d\n",reportId,reportSeqNum);
    //printf("received report for %s\n", ClientReport_getRcbReference(report));
    MmsValue * entryId = ClientReport_getEntryId(report);   
    if (entryId) {
        char * buf = (char*)MmsValue_getOctetStringBuffer(entryId);
        printf("Entry ID: %02hhX-%02hhX-%02hhX %02hhX-%02hhX-%02hhX-%02hhX-%02hhX\n", buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]);
    }
    /*int i;
    for (i = 0; i < 4; i++) {
        ReasonForInclusion reason = ClientReport_getReasonForInclusion(report, i);

        if (reason != IEC61850_REASON_NOT_INCLUDED) {
            printf("  GGIO1.SPCSO%i.stVal: %i (included for reason %i)\n", i,
                    MmsValue_getBoolean(MmsValue_getElement(dataSetValues, i)), reason);
        }
    }*/
}

int main(int argc, char** argv) {

    char* hostname;
    int tcpPort = 102;

    if (argc > 1)
        hostname = argv[1];
    else
        hostname = "192.168.25.25";

    if (argc > 2)
        tcpPort = atoi(argv[2]);

    IedClientError error;

    IedConnection con = IedConnection_create();

    IedConnection_connect(con, &error, hostname, tcpPort);

    if (error == IED_ERROR_OK) {

        IedConnection_getServerDirectory(con, &error, false);

        /* read an analog measurement value from server */
        MmsValue* value = IedConnection_readObject(con, &error, "TEMPLATELD0/LLN0.ActSG.mag.i", IEC61850_FC_MX);

        if (value != NULL) {
            int32_t fval = MmsValue_toInt32(value);
            printf("read int32 value: %d\n", fval);
            MmsValue_delete(value);
        }

        /* write a variable to the server */
        value = MmsValue_newVisibleString("test");
        IedConnection_writeObject(con, &error, "TEMPLATELD0/LPHD1.PhyNam.vendor", IEC61850_FC_DC, value);

        if (error != IED_ERROR_OK)
            printf("failed to write TEMPLATELD0/LPHD1.PhyName.vendor!\n");
        else
            printf("succeed to write TEMPLATELD0/LPHD1.PhyName.vendor test!\n");

        MmsValue_delete(value);

        /* read data set */
        ClientDataSet clientDataSet = IedConnection_readDataSetValues(con, &error, "TEMPLATELD0/LLN0.dsWarning", NULL);

        if (clientDataSet == NULL)
            printf("failed to read dataset TEMPLATELD0/LLN0.dsWarning\n");
        else
            printf("succeed to read dataset TEMPLATELD0/LLN0.dsWarning\n");

        /* Read RCB values */
        ClientReportControlBlock rcb =
                IedConnection_getRCBValues(con, &error, "TEMPLATELD0/LLN0.BR.brcbAlarm01", NULL);

        bool rptEna = ClientReportControlBlock_getRptEna(rcb);
        printf("RptEna = %i\n", rptEna);

        /* setEntryId */
        char buf[8] = {00,00,00,00,00,00,0x00,0x16};
        MmsValue *entryId = MmsValue_newOctetString(8, 8); 
        MmsValue_setOctetString(entryId, (uint8_t*)buf, 8);
        ClientReportControlBlock_setEntryId_ex(rcb, entryId);

        /* Install handler for reports */
        IedConnection_installReportHandler(con, "TEMPLATELD0/LLN0.BR.brcbAlarm01", ClientReportControlBlock_getRptId(rcb), reportCallbackFunction, rcb);

        /* Set trigger options and enable report */
        ClientReportControlBlock_setTrgOps(rcb, TRG_OPT_DATA_UPDATE | TRG_OPT_INTEGRITY | TRG_OPT_GI);
        ClientReportControlBlock_setRptEna(rcb, true);
        ClientReportControlBlock_setIntgPd(rcb, 30000);
        IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA | RCB_ELEMENT_TRG_OPS | RCB_ELEMENT_INTG_PD, true);

        if (error != IED_ERROR_OK)
            printf("report activation failed (code: %i)\n", error);
        else
            printf("report activation succeed (code: %i)\n", error);    

        //Thread_sleep(1000);

        /* trigger GI report */
        ClientReportControlBlock_setGI(rcb, true);
        IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_GI, true);

        if (error != IED_ERROR_OK)
            printf("Error triggering a GI report (code: %i)\n", error);

        Thread_sleep(1000000);

        /* disable reporting */
        ClientReportControlBlock_setRptEna(rcb, false);
        IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA, true);

        if (error != IED_ERROR_OK)
            printf("disable reporting failed (code: %i)\n", error);
        else
            printf("disable reporting succeed (code: %i)\n", error);

        ClientDataSet_destroy(clientDataSet);

        ClientReportControlBlock_destroy(rcb);

        close_connection:

        IedConnection_close(con);
    }
    else {
        printf("Failed to connect to %s:%i\n", hostname, tcpPort);
    }

    IedConnection_destroy(con);
}
codebuks commented 6 years ago

sorry, my problem is solved, i forget to call IedConnection_setRCBValues IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_TRG_OPS | RCB_ELEMENT_OPT_FLDS | RCB_ELEMENT_ENTRY_ID, true);

mzillgith commented 6 years ago

Hi. I will keep it as a question because it might help other users.