123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- #include "iec_include.h"
- #include "simple_server.h"
- static bool running = true;
- static void printCP56Time2a(CP56Time2a time)
- {
- printf("%02i:%02i:%02i %02i/%02i/%04i", CP56Time2a_getHour(time),
- CP56Time2a_getMinute(time),
- CP56Time2a_getSecond(time),
- CP56Time2a_getDayOfMonth(time),
- CP56Time2a_getMonth(time),
- CP56Time2a_getYear(time) + 2000);
- }
- /* Callback handler to log sent or received messages (optional) */
- static void
- rawMessageHandler(void* parameter, IMasterConnection conneciton, uint8_t* msg, int msgSize, bool sent)
- {
- if (sent)
- printf("SEND: ");
- else
- printf("RCVD: ");
- int i;
- for (i = 0; i < msgSize; i++) {
- printf("%02x ", msg[i]);
- }
- printf("\n");
- }
- static bool
- cs104ClockSyncHandler (void* parameter, IMasterConnection connection, CS101_ASDU asdu, CP56Time2a newTime)
- {
- printf("Process time sync command with time "); printCP56Time2a(newTime); printf("\n");
- uint64_t newSystemTimeInMs = CP56Time2a_toMsTimestamp(newTime);
- /* Set time for ACT_CON message */
- CP56Time2a_setFromMsTimestamp(newTime, Hal_getTimeInMs());
- /* update system time here */
- return true;
- }
- static bool
- cs104InterrogationHandler(void* parameter, IMasterConnection connection, CS101_ASDU asdu, uint8_t qoi)
- {
- printf("Received interrogation for group %i\n", qoi);
- if (qoi == 20) { /* only handle station interrogation */
- CS101_AppLayerParameters alParams = IMasterConnection_getApplicationLayerParameters(connection);
- IMasterConnection_sendACT_CON(connection, asdu, false);
- /* The CS101 specification only allows information objects without timestamp in GI responses */
- CS101_ASDU newAsdu = CS101_ASDU_create(alParams, false, CS101_COT_INTERROGATED_BY_STATION,
- 0, 1, false, false);
- InformationObject io = (InformationObject) MeasuredValueScaled_create(NULL, 100, -1, IEC60870_QUALITY_GOOD);
- CS101_ASDU_addInformationObject(newAsdu, io);
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject)
- MeasuredValueScaled_create((MeasuredValueScaled) io, 101, 23, IEC60870_QUALITY_GOOD));
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject)
- MeasuredValueScaled_create((MeasuredValueScaled) io, 102, 2300, IEC60870_QUALITY_GOOD));
- InformationObject_destroy(io);
- IMasterConnection_sendASDU(connection, newAsdu);
- CS101_ASDU_destroy(newAsdu);
- newAsdu = CS101_ASDU_create(alParams, false, CS101_COT_INTERROGATED_BY_STATION,
- 0, 1, false, false);
- io = (InformationObject) SinglePointInformation_create(NULL, 104, true, IEC60870_QUALITY_GOOD);
- CS101_ASDU_addInformationObject(newAsdu, io);
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject)
- SinglePointInformation_create((SinglePointInformation) io, 105, false, IEC60870_QUALITY_GOOD));
- InformationObject_destroy(io);
- IMasterConnection_sendASDU(connection, newAsdu);
- CS101_ASDU_destroy(newAsdu);
- newAsdu = CS101_ASDU_create(alParams, true, CS101_COT_INTERROGATED_BY_STATION,
- 0, 1, false, false);
- CS101_ASDU_addInformationObject(newAsdu, io = (InformationObject) SinglePointInformation_create(NULL, 300, true, IEC60870_QUALITY_GOOD));
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject) SinglePointInformation_create((SinglePointInformation) io, 301, false, IEC60870_QUALITY_GOOD));
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject) SinglePointInformation_create((SinglePointInformation) io, 302, true, IEC60870_QUALITY_GOOD));
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject) SinglePointInformation_create((SinglePointInformation) io, 303, false, IEC60870_QUALITY_GOOD));
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject) SinglePointInformation_create((SinglePointInformation) io, 304, true, IEC60870_QUALITY_GOOD));
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject) SinglePointInformation_create((SinglePointInformation) io, 305, false, IEC60870_QUALITY_GOOD));
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject) SinglePointInformation_create((SinglePointInformation) io, 306, true, IEC60870_QUALITY_GOOD));
- CS101_ASDU_addInformationObject(newAsdu, (InformationObject) SinglePointInformation_create((SinglePointInformation) io, 307, false, IEC60870_QUALITY_GOOD));
- InformationObject_destroy(io);
- IMasterConnection_sendASDU(connection, newAsdu);
- CS101_ASDU_destroy(newAsdu);
- newAsdu = CS101_ASDU_create(alParams, false, CS101_COT_INTERROGATED_BY_STATION,
- 0, 1, false, false);
- io = (InformationObject) BitString32_create(NULL, 500, 0xaaaa);
- CS101_ASDU_addInformationObject(newAsdu, io);
- InformationObject_destroy(io);
- IMasterConnection_sendASDU(connection, newAsdu);
- CS101_ASDU_destroy(newAsdu);
- IMasterConnection_sendACT_TERM(connection, asdu);
- }
- else {
- IMasterConnection_sendACT_CON(connection, asdu, true);
- }
- return true;
- }
- static bool
- cs104AsduHandler(void* parameter, IMasterConnection connection, CS101_ASDU asdu)
- {
- if (CS101_ASDU_getTypeID(asdu) == C_SC_NA_1) {
- printf("received single command\n");
- if (CS101_ASDU_getCOT(asdu) == CS101_COT_ACTIVATION) {
- InformationObject io = CS101_ASDU_getElement(asdu, 0);
- if (io) {
- if (InformationObject_getObjectAddress(io) == 5000) {
- SingleCommand sc = (SingleCommand) io;
- printf("IOA: %i switch to %i\n", InformationObject_getObjectAddress(io),
- SingleCommand_getState(sc));
- CS101_ASDU_setCOT(asdu, CS101_COT_ACTIVATION_CON);
- }
- else
- CS101_ASDU_setCOT(asdu, CS101_COT_UNKNOWN_IOA);
- InformationObject_destroy(io);
- }
- else {
- printf("ERROR: message has no valid information object\n");
- return true;
- }
- }
- else
- CS101_ASDU_setCOT(asdu, CS101_COT_UNKNOWN_COT);
- IMasterConnection_sendASDU(connection, asdu);
- return true;
- }
- return false;
- }
- static bool
- cs104ConnectionRequestHandler(void* parameter, const char* ipAddress)
- {
- printf("New connection request from %s\n", ipAddress);
- #if 0
- if (strcmp(ipAddress, "127.0.0.1") == 0) {
- printf("Accept connection\n");
- return true;
- }
- else {
- printf("Deny connection\n");
- return false;
- }
- #else
- return true;
- #endif
- }
- static void
- cs104ConnectionEventHandler(void* parameter, IMasterConnection con, CS104_PeerConnectionEvent event)
- {
- if (event == CS104_CON_EVENT_CONNECTION_OPENED) {
- printf("Connection opened (%p)\n", con);
- }
- else if (event == CS104_CON_EVENT_CONNECTION_CLOSED) {
- printf("Connection closed (%p)\n", con);
- }
- else if (event == CS104_CON_EVENT_ACTIVATED) {
- printf("Connection activated (%p)\n", con);
- }
- else if (event == CS104_CON_EVENT_DEACTIVATED) {
- printf("Connection deactivated (%p)\n", con);
- }
- }
- void cs104_server(void const* arg)
- {
- /* create a new slave/server instance with default connection parameters and
- * default message queue size */
- CS104_Slave slave = CS104_Slave_create(10, 10);
- CS104_Slave_setLocalAddress(slave, "0.0.0.0");
- /* Set mode to a single redundancy group
- * NOTE: library has to be compiled with CONFIG_CS104_SUPPORT_SERVER_MODE_SINGLE_REDUNDANCY_GROUP enabled (=1)
- */
- CS104_Slave_setServerMode(slave, CS104_MODE_SINGLE_REDUNDANCY_GROUP);
- /* get the connection parameters - we need them to create correct ASDUs -
- * you can also modify the parameters here when default parameters are not to be used */
- CS101_AppLayerParameters alParams = CS104_Slave_getAppLayerParameters(slave);
- /* when you have to tweak the APCI parameters (t0-t3, k, w) you can access them here */
- CS104_APCIParameters apciParams = CS104_Slave_getConnectionParameters(slave);
- printf("APCI parameters:\n");
- printf(" t0: %i\n", apciParams->t0);
- printf(" t1: %i\n", apciParams->t1);
- printf(" t2: %i\n", apciParams->t2);
- printf(" t3: %i\n", apciParams->t3);
- printf(" k: %i\n", apciParams->k);
- printf(" w: %i\n", apciParams->w);
- /* set the callback handler for the clock synchronization command */
- CS104_Slave_setClockSyncHandler(slave, cs104ClockSyncHandler, NULL);
- /* set the callback handler for the interrogation command */
- CS104_Slave_setInterrogationHandler(slave, cs104InterrogationHandler, NULL);
- /* set handler for other message types */
- CS104_Slave_setASDUHandler(slave, cs104AsduHandler, NULL);
- /* set handler to handle connection requests (optional) */
- CS104_Slave_setConnectionRequestHandler(slave, cs104ConnectionRequestHandler, NULL);
- /* set handler to track connection events (optional) */
- CS104_Slave_setConnectionEventHandler(slave, cs104ConnectionEventHandler, NULL);
- /* uncomment to log messages */
- //CS104_Slave_setRawMessageHandler(slave, rawMessageHandler, NULL);
- CS104_Slave_start(slave);
- if (CS104_Slave_isRunning(slave) == false) {
- printf("Starting server failed!\n");
- goto exit_program;
- }
- int16_t scaledValue = 0;
- while (running) {
- delay_ms(1000);
- CS101_ASDU newAsdu = CS101_ASDU_create(alParams, false, CS101_COT_PERIODIC, 0, 1, false, false);
- InformationObject io = (InformationObject) MeasuredValueScaled_create(NULL, 110, scaledValue, IEC60870_QUALITY_GOOD);
- scaledValue++;
- CS101_ASDU_addInformationObject(newAsdu, io);
- InformationObject_destroy(io);
- /* Add ASDU to slave event queue */
- CS104_Slave_enqueueASDU(slave, newAsdu);
- CS101_ASDU_destroy(newAsdu);
- }
- CS104_Slave_stop(slave);
- exit_program:
- CS104_Slave_destroy(slave);
- delay_ms(500);
- }
|