feat:
--READ smash_read_this.txt
This commit is contained in:
commit
1ddf693260
181 files changed
+66527
No files matched your search
@@ -0,0 +1,20 @@
|
||||
include_directories(
|
||||
.
|
||||
)
|
||||
|
||||
set(example_SRCS
|
||||
simple_client.c
|
||||
)
|
||||
|
||||
IF(WIN32)
|
||||
set_source_files_properties(${example_SRCS}
|
||||
PROPERTIES LANGUAGE CXX)
|
||||
ENDIF(WIN32)
|
||||
|
||||
add_executable(simple_client
|
||||
${example_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries(simple_client
|
||||
lib60870
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
LIB60870_HOME=../..
|
||||
|
||||
PROJECT_BINARY_NAME = simple_client
|
||||
PROJECT_SOURCES = simple_client.c
|
||||
|
||||
include $(LIB60870_HOME)/make/target_system.mk
|
||||
include $(LIB60870_HOME)/make/stack_includes.mk
|
||||
|
||||
all: $(PROJECT_BINARY_NAME)
|
||||
|
||||
include $(LIB60870_HOME)/make/common_targets.mk
|
||||
|
||||
|
||||
$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -g -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
|
||||
|
||||
clean:
|
||||
rm -f $(PROJECT_BINARY_NAME)
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/* scada.c — simulates a SCADA control center */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cs104_connection.h"
|
||||
#include "hal_thread.h"
|
||||
#include "hal_time.h"
|
||||
|
||||
static bool running = true;
|
||||
|
||||
void sigint_handler(int s) { running = false; }
|
||||
|
||||
/* ── called for every ASDU received from RTU ───────────────── */
|
||||
static bool asduReceivedHandler(void* p, int address, CS101_ASDU asdu) {
|
||||
int typeId = CS101_ASDU_getTypeID(asdu);
|
||||
int cot = CS101_ASDU_getCOT(asdu);
|
||||
|
||||
/* measured float value M_ME_NC_1 */
|
||||
if (typeId == M_ME_NC_1) {
|
||||
int i;
|
||||
for (i = 0; i < CS101_ASDU_getNumberOfElements(asdu); i++) {
|
||||
MeasuredValueShort mv = (MeasuredValueShort)
|
||||
CS101_ASDU_getElement(asdu, i);
|
||||
int ioa = InformationObject_getObjectAddress((InformationObject)mv);
|
||||
float value = MeasuredValueShort_getValue(mv);
|
||||
InformationObject_destroy((InformationObject)mv);
|
||||
|
||||
if (ioa == 100)
|
||||
printf("[SCADA ←] Voltage IOA=100 %.2f kV\n", value);
|
||||
else if (ioa == 101)
|
||||
printf("[SCADA ←] Current IOA=101 %.1f A\n", value);
|
||||
else
|
||||
printf("[SCADA ←] Float IOA=%d %.2f\n", ioa, value);
|
||||
}
|
||||
}
|
||||
|
||||
/* single point M_SP_NA_1 */
|
||||
else if (typeId == M_SP_NA_1) {
|
||||
int i;
|
||||
for (i = 0; i < CS101_ASDU_getNumberOfElements(asdu); i++) {
|
||||
SinglePointInformation sp = (SinglePointInformation)
|
||||
CS101_ASDU_getElement(asdu, i);
|
||||
int ioa = InformationObject_getObjectAddress((InformationObject)sp);
|
||||
bool state = SinglePointInformation_getValue(sp);
|
||||
InformationObject_destroy((InformationObject)sp);
|
||||
|
||||
if (ioa == 200)
|
||||
printf("[SCADA ←] Breaker1 IOA=200 %s\n", state ? "ON" : "OFF");
|
||||
else if (ioa == 201)
|
||||
printf("[SCADA ←] Breaker2 IOA=201 %s\n", state ? "ON" : "OFF");
|
||||
else
|
||||
printf("[SCADA ←] Point IOA=%d %s\n", ioa, state ? "ON" : "OFF");
|
||||
}
|
||||
}
|
||||
|
||||
/* command confirmation */
|
||||
else if (typeId == C_SC_NA_1) {
|
||||
if (cot == CS101_COT_ACTIVATION_CON)
|
||||
printf("[SCADA ←] Command confirmed by RTU\n");
|
||||
else if (cot == CS101_COT_UNKNOWN_IOA)
|
||||
printf("[SCADA ←] Command rejected — unknown IOA\n");
|
||||
}
|
||||
|
||||
else {
|
||||
printf("[SCADA ←] TypeID=%d COT=%d\n", typeId, cot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ── connection state ───────────────────────────────────────── */
|
||||
static void connectionHandler(void* p, CS104_Connection con, CS104_ConnectionEvent event) {
|
||||
if (event == CS104_CONNECTION_OPENED)
|
||||
printf("[SCADA] Connected to RTU\n");
|
||||
else if (event == CS104_CONNECTION_CLOSED)
|
||||
printf("[SCADA] Disconnected from RTU\n");
|
||||
else if (event == CS104_CONNECTION_STARTDT_CON_RECEIVED)
|
||||
printf("[SCADA] STARTDT confirmed — data transfer active\n");
|
||||
else if (event == CS104_CONNECTION_STOPDT_CON_RECEIVED)
|
||||
printf("[SCADA] STOPDT confirmed\n");
|
||||
}
|
||||
|
||||
/* ── send a single command to RTU ───────────────────────────── */
|
||||
void send_command(CS104_Connection con, int ioa, bool state) {
|
||||
CS101_AppLayerParameters alParams =
|
||||
CS104_Connection_getAppLayerParameters(con);
|
||||
|
||||
CS101_ASDU asdu = CS101_ASDU_create(alParams, false,
|
||||
CS101_COT_ACTIVATION, 0, 1, false, false);
|
||||
|
||||
InformationObject io = (InformationObject)
|
||||
SingleCommand_create(NULL, ioa, state, false, 0);
|
||||
|
||||
CS101_ASDU_addInformationObject(asdu, io);
|
||||
InformationObject_destroy(io);
|
||||
|
||||
CS104_Connection_sendASDU(con, asdu);
|
||||
CS101_ASDU_destroy(asdu);
|
||||
|
||||
printf("[SCADA →] Command sent — IOA=%d state=%s\n",
|
||||
ioa, state ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
/* ── send general interrogation ─────────────────────────────── */
|
||||
void send_gi(CS104_Connection con) {
|
||||
CS104_Connection_sendInterrogationCommand(con,
|
||||
CS101_COT_ACTIVATION, 1, IEC60870_QOI_STATION);
|
||||
printf("[SCADA →] General Interrogation sent\n");
|
||||
}
|
||||
|
||||
/* ── main ───────────────────────────────────────────────────── */
|
||||
int main(int argc, char** argv) {
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
const char* ip = (argc > 1) ? argv[1] : "127.0.0.1";
|
||||
|
||||
printf("[SCADA] Connecting to RTU at %s:2404\n\n", ip);
|
||||
|
||||
CS104_Connection con = CS104_Connection_create(ip, 2404);
|
||||
|
||||
CS104_Connection_setConnectionHandler(con, connectionHandler, NULL);
|
||||
CS104_Connection_setASDUReceivedHandler(con, asduReceivedHandler, NULL);
|
||||
|
||||
CS104_Connection_connect(con);
|
||||
Thread_sleep(1000);
|
||||
|
||||
/* start data transfer */
|
||||
CS104_Connection_sendStartDT(con);
|
||||
Thread_sleep(500);
|
||||
|
||||
/* request all current values */
|
||||
send_gi(con);
|
||||
Thread_sleep(2000);
|
||||
|
||||
/* main loop — send commands periodically */
|
||||
uint64_t lastCmd = 0;
|
||||
bool b1_state = false;
|
||||
bool b2_state = false;
|
||||
|
||||
printf("\n[SCADA] Running — commands every 5s, Ctrl+C to stop\n\n");
|
||||
|
||||
while (running) {
|
||||
uint64_t now = Hal_getMonotonicTimeInMs();
|
||||
|
||||
/* every 5s — toggle breaker1 then breaker2 alternately */
|
||||
if (now >= lastCmd + 5000) {
|
||||
lastCmd = now;
|
||||
|
||||
static int cmd_count = 0;
|
||||
cmd_count++;
|
||||
|
||||
if (cmd_count % 2 == 0) {
|
||||
b1_state = !b1_state;
|
||||
send_command(con, 200, b1_state); /* toggle breaker1 */
|
||||
} else {
|
||||
b2_state = !b2_state;
|
||||
send_command(con, 201, b2_state); /* toggle breaker2 */
|
||||
}
|
||||
}
|
||||
|
||||
Thread_sleep(10);
|
||||
}
|
||||
|
||||
printf("\n[SCADA] Shutting down\n");
|
||||
CS104_Connection_sendStopDT(con);
|
||||
Thread_sleep(500);
|
||||
CS104_Connection_destroy(con);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user