|
@@ -1,61 +1,134 @@
|
|
|
#include "MyIec61850Server.h"
|
|
|
+#include <signal.h>
|
|
|
+#include <stdio.h>
|
|
|
|
|
|
static int running = 0;
|
|
|
|
|
|
void sigint_handler(int signalId) {
|
|
|
+ printf("Received SIGINT, stopping server...\n");
|
|
|
running = 0;
|
|
|
}
|
|
|
|
|
|
using namespace MyIec61850;
|
|
|
|
|
|
-MyIec61850Server::MyIec61850Server(int port) : port(port), iedServer(nullptr), model(nullptr),
|
|
|
- lDevice1(nullptr), lln0(nullptr), ttmp1(nullptr),
|
|
|
- temperatureValue(nullptr), temperatureTimestamp(nullptr),
|
|
|
- hhum1(nullptr), humidityValue(nullptr), humidityTimestamp(nullptr),
|
|
|
- dataSet(nullptr) {
|
|
|
- setupDataModel();
|
|
|
+MyIec61850Server::MyIec61850Server(const std::string& configFilePath) {
|
|
|
+ setupDataModelFromConfig(configFilePath);
|
|
|
+ port = 102;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
MyIec61850Server::~MyIec61850Server() {
|
|
|
+ printf("Destroying IEC 61850 Server\n");
|
|
|
stop();
|
|
|
if (model) {
|
|
|
IedModel_destroy(model);
|
|
|
+ model = nullptr;
|
|
|
}
|
|
|
}
|
|
|
+void MyIec61850Server::setupDataModelFromConfig(const std::string& configFilePath) {
|
|
|
+ // 加载并解析配置文件
|
|
|
+ std::ifstream configFile(configFilePath);
|
|
|
+ if (!configFile.is_open()) {
|
|
|
+ std::cerr << "Failed to open config file." << std::endl;
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
-void MyIec61850Server::setupDataModel() {
|
|
|
- model = IedModel_create("TemperatureHumiditySensor");
|
|
|
+ json config;
|
|
|
+ configFile >> config;
|
|
|
+
|
|
|
+ // 创建 IED 模型
|
|
|
+ model = IedModel_create("EnvironmentalSensors");
|
|
|
+
|
|
|
+ for (const auto& device : config["devices"]) {
|
|
|
+ std::string deviceType = device["type"];
|
|
|
+ std::string deviceId = device["id"];
|
|
|
+
|
|
|
+ // 根据设备类型创建逻辑设备
|
|
|
+ LogicalDevice* lDevice = LogicalDevice_create(deviceId.c_str(), model);
|
|
|
+
|
|
|
+ // 创建 LLN0 逻辑节点(标准逻辑节点)
|
|
|
+ LogicalNode* lln0 = LogicalNode_create("LLN0", lDevice);
|
|
|
+
|
|
|
+ if (deviceType == "sensor") {
|
|
|
+ // 创建温度传感器逻辑节点
|
|
|
+ std::string temperatureName = device["temperature"]["name"];
|
|
|
+ std::string temperatureDataObject = device["temperature"]["dataObject"];
|
|
|
+ LogicalNode* ttmp1 = LogicalNode_create(temperatureName.c_str(), lDevice);
|
|
|
+ DataObject* ttmp1_tmpsv = CDC_SAV_create(temperatureDataObject.c_str(), (ModelNode*) ttmp1, 0, false);
|
|
|
+ DataAttribute* temperatureValue = (DataAttribute*) ModelNode_getChild((ModelNode*) ttmp1_tmpsv, "instMag.f");
|
|
|
+ DataAttribute* temperatureTimestamp = (DataAttribute*) ModelNode_getChild((ModelNode*) ttmp1_tmpsv, "t");
|
|
|
+
|
|
|
+ // 创建湿度传感器逻辑节点
|
|
|
+ std::string humidityName = device["humidity"]["name"];
|
|
|
+ std::string humidityDataObject = device["humidity"]["dataObject"];
|
|
|
+ LogicalNode* hhum1 = LogicalNode_create(humidityName.c_str(), lDevice);
|
|
|
+ DataObject* hhum1_humsv = CDC_SAV_create(humidityDataObject.c_str(), (ModelNode*) hhum1, 0, false);
|
|
|
+ DataAttribute* humidityValue = (DataAttribute*) ModelNode_getChild((ModelNode*) hhum1_humsv, "instMag.f");
|
|
|
+ DataAttribute* humidityTimestamp = (DataAttribute*) ModelNode_getChild((ModelNode*) hhum1_humsv, "t");
|
|
|
+
|
|
|
+ // 创建数据集用于报告 - 温湿度传感器
|
|
|
+ DataSet* dataSet_sensors = DataSet_create("sensorData", lln0);
|
|
|
+ DataSetEntry_create(dataSet_sensors, (temperatureName + "$MX$" + temperatureDataObject + "$instMag$f").c_str(), -1, NULL);
|
|
|
+ DataSetEntry_create(dataSet_sensors, (humidityName + "$MX$" + humidityDataObject + "$instMag$f").c_str(), -1, NULL);
|
|
|
+
|
|
|
+ // 创建报告控制块 - 温湿度传感器
|
|
|
+ uint8_t rptOptions_sensors = RPT_OPT_SEQ_NUM | RPT_OPT_TIME_STAMP | RPT_OPT_REASON_FOR_INCLUSION;
|
|
|
+ ReportControlBlock_create("sensorReport", lln0, "sensorReport", false, NULL, 1, TRG_OPT_DATA_CHANGED, rptOptions_sensors, 50, 0);
|
|
|
+ } else if (deviceType == "smoke_detector") {
|
|
|
+ // 创建烟雾报警器逻辑节点
|
|
|
+ std::string smokeStatusName = device["status"]["name"];
|
|
|
+ std::string smokeStatusDataObject = device["status"]["dataObject"];
|
|
|
+ LogicalNode* ssmg1 = LogicalNode_create(smokeStatusName.c_str(), lDevice);
|
|
|
+ DataObject* ssmg1_smokeStatus = CDC_BSC_create(smokeStatusDataObject.c_str(), (ModelNode*) ssmg1, 0, 0, false);
|
|
|
+ DataAttribute* smokeStatus = (DataAttribute*) ModelNode_getChild((ModelNode*) ssmg1_smokeStatus, "stVal");
|
|
|
+
|
|
|
+ // 创建数据集用于报告 - 烟雾报警器
|
|
|
+ DataSet* dataSet_smoke = DataSet_create("smokeData", lln0);
|
|
|
+ DataSetEntry_create(dataSet_smoke, (smokeStatusName + "$MX$" + smokeStatusDataObject + "$stVal").c_str(), -1, NULL);
|
|
|
+
|
|
|
+ // 创建报告控制块 - 烟雾报警器
|
|
|
+ uint8_t rptOptions_smoke = RPT_OPT_SEQ_NUM | RPT_OPT_TIME_STAMP | RPT_OPT_REASON_FOR_INCLUSION;
|
|
|
+ ReportControlBlock_create("smokeReport", lln0, "smokeReport", false, NULL, 1, TRG_OPT_DATA_CHANGED, rptOptions_smoke, 50, 0);
|
|
|
+ }else if (deviceType == "flood_sensor") {
|
|
|
+ // 创建水浸传感器逻辑节点
|
|
|
+ std::string floodStatusName = device["status"]["name"];
|
|
|
+ std::string floodStatusDataObject = device["status"]["dataObject"];
|
|
|
+ LogicalNode* ffls1 = LogicalNode_create(floodStatusName.c_str(), lDevice);
|
|
|
+ DataObject* ffls1_floodStatus = CDC_BSC_create(floodStatusDataObject.c_str(), (ModelNode*) ffls1, 0, 0, false);
|
|
|
+ DataAttribute* floodStatus = (DataAttribute*) ModelNode_getChild((ModelNode*) ffls1_floodStatus, "stVal");
|
|
|
+
|
|
|
+ // 创建数据集用于报告 - 水浸传感器
|
|
|
+ DataSet* dataSet_flood = DataSet_create("floodData", lln0);
|
|
|
+ DataSetEntry_create(dataSet_flood, (floodStatusName + "$MX$" + floodStatusDataObject + "$stVal").c_str(), -1, NULL);
|
|
|
+
|
|
|
+ // 创建报告控制块 - 水浸传感器
|
|
|
+ uint8_t rptOptions_flood = RPT_OPT_SEQ_NUM | RPT_OPT_TIME_STAMP | RPT_OPT_REASON_FOR_INCLUSION;
|
|
|
+ ReportControlBlock_create("floodReport", lln0, "floodReport", false, NULL, 1, TRG_OPT_DATA_CHANGED, rptOptions_flood, 50, 0);
|
|
|
+ }
|
|
|
|
|
|
- lDevice1 = LogicalDevice_create("SENSORS", model);
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- lln0 = LogicalNode_create("LLN0", lDevice1);
|
|
|
+void onRCBEvent(void* parameter, ReportControlBlock* rcb, ClientConnection connection, IedServer_RCBEventType event, const char* parameterName, MmsDataAccessError serviceError) {
|
|
|
+ // 打印事件详情
|
|
|
+ printf("RCB Event: %d\n", event);
|
|
|
+ printf("RCB Name: %s\n", ReportControlBlock_getName(rcb));
|
|
|
+ printf("Client Address: %s\n", ClientConnection_getPeerAddress(connection));
|
|
|
|
|
|
- /* Create a Temperature Sensor LN */
|
|
|
- ttmp1 = LogicalNode_create("TTMP1", lDevice1);
|
|
|
- DataObject* ttmp1_tmpsv = CDC_SAV_create("TmpSv", (ModelNode*) ttmp1, 0, false);
|
|
|
|
|
|
- temperatureValue = (DataAttribute*) ModelNode_getChild((ModelNode*) ttmp1_tmpsv, "instMag.f");
|
|
|
- temperatureTimestamp = (DataAttribute*) ModelNode_getChild((ModelNode*) ttmp1_tmpsv, "t");
|
|
|
+ if (serviceError != DATA_ACCESS_ERROR_SUCCESS) {
|
|
|
+ printf("Service Error: %d\n", serviceError);
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- /* Create a Humidity Sensor LN */
|
|
|
- hhum1 = LogicalNode_create("HHUM1", lDevice1);
|
|
|
- DataObject* hhum1_humsv = CDC_SAV_create("HumSv", (ModelNode*) hhum1, 0, false);
|
|
|
|
|
|
- humidityValue = (DataAttribute*) ModelNode_getChild((ModelNode*) hhum1_humsv, "instMag.f");
|
|
|
- humidityTimestamp = (DataAttribute*) ModelNode_getChild((ModelNode*) hhum1_humsv, "t");
|
|
|
+void MyIec61850Server::start() {
|
|
|
+ printf("Starting IEC 61850 Server...\n");
|
|
|
|
|
|
- /* Create DataSet for reporting */
|
|
|
- dataSet = DataSet_create("sensorData", lln0);
|
|
|
- DataSetEntry_create(dataSet, "TTMP1$MX$TmpSv$instMag$f", -1, NULL);
|
|
|
- DataSetEntry_create(dataSet, "HHUM1$MX$HumSv$instMag$f", -1, NULL);
|
|
|
+ iedServer = IedServer_create(model); // 确保使用 sIedServer*
|
|
|
|
|
|
- /* Create Report Control Block */
|
|
|
- uint8_t rptOptions = RPT_OPT_SEQ_NUM | RPT_OPT_TIME_STAMP | RPT_OPT_REASON_FOR_INCLUSION;
|
|
|
- ReportControlBlock_create("sensorReport", lln0, "sensorReport", false, NULL, 1, TRG_OPT_DATA_CHANGED, rptOptions, 50, 0);
|
|
|
-}
|
|
|
+ IedServer_setRCBEventHandler(iedServer, onRCBEvent, NULL);
|
|
|
|
|
|
-void MyIec61850Server::start() {
|
|
|
- iedServer = IedServer_create(model); // 确保使用 sIedServer*
|
|
|
|
|
|
/* MMS server will be instructed to start listening to client connections. */
|
|
|
IedServer_start(iedServer, port);
|
|
@@ -69,9 +142,11 @@ void MyIec61850Server::start() {
|
|
|
|
|
|
void MyIec61850Server::stop() {
|
|
|
if (iedServer != nullptr) {
|
|
|
+ printf("Stopping IED Server...\n");
|
|
|
IedServer_stop(iedServer);
|
|
|
IedServer_destroy(iedServer); // 传递 sIedServer* 类型的参数
|
|
|
iedServer = nullptr; // 手动将指针置为 nullptr
|
|
|
+ printf("IED Server stopped.\n");
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -82,15 +157,18 @@ void MyIec61850Server::run() {
|
|
|
float temperature = 25.0f; // Initial temperature value
|
|
|
float humidity = 50.0f; // Initial humidity value
|
|
|
|
|
|
+ printf("Server is running and updating sensor values periodically.\n");
|
|
|
+
|
|
|
while (running) {
|
|
|
IedServer_lockDataModel(iedServer);
|
|
|
+ printf("Updating sensor values: Temperature=%.2f, Humidity=%.2f\n", temperature, humidity);
|
|
|
|
|
|
/* Update temperature and humidity values */
|
|
|
- IedServer_updateUTCTimeAttributeValue(iedServer, temperatureTimestamp, Hal_getTimeInMs());
|
|
|
- IedServer_updateFloatAttributeValue(iedServer, temperatureValue, temperature);
|
|
|
-
|
|
|
- IedServer_updateUTCTimeAttributeValue(iedServer, humidityTimestamp, Hal_getTimeInMs());
|
|
|
- IedServer_updateFloatAttributeValue(iedServer, humidityValue, humidity);
|
|
|
+ // IedServer_updateUTCTimeAttributeValue(iedServer, temperatureTimestamp, Hal_getTimeInMs());
|
|
|
+ // IedServer_updateFloatAttributeValue(iedServer, temperatureValue, temperature);
|
|
|
+ //
|
|
|
+ // IedServer_updateUTCTimeAttributeValue(iedServer, humidityTimestamp, Hal_getTimeInMs());
|
|
|
+ // IedServer_updateFloatAttributeValue(iedServer, humidityValue, humidity);
|
|
|
|
|
|
IedServer_unlockDataModel(iedServer);
|
|
|
|
|
@@ -100,4 +178,6 @@ void MyIec61850Server::run() {
|
|
|
|
|
|
Thread_sleep(1000); // Sleep for 1 second
|
|
|
}
|
|
|
-}
|
|
|
+
|
|
|
+ printf("Server stopped.\n");
|
|
|
+}
|