From 48112eb3439ebfb9efd12529bf3ec3aa8437e160 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 14 Feb 2024 11:48:59 +0000 Subject: [PATCH 1/3] villas: Use Python dictionaries for defining VILLASconfig files Signed-off-by: Steffen Vogel --- examples/villas/dpsim-file.py | 20 +++++++------ .../villas/dpsim-mqtt-cigre-mv-pf-profiles.py | 19 +++++++------ .../villas/dpsim-mqtt-import-export-MIMO.py | 28 +++++++++---------- examples/villas/dpsim-mqtt-import-export.py | 16 +++++------ examples/villas/dpsim-mqtt.py | 28 ++++++++++--------- 5 files changed, 59 insertions(+), 52 deletions(-) diff --git a/examples/villas/dpsim-file.py b/examples/villas/dpsim-file.py index cf7b157d6e..dbab6bf162 100644 --- a/examples/villas/dpsim-file.py +++ b/examples/villas/dpsim-file.py @@ -1,5 +1,7 @@ # This example demonstrates the export of values calculated by dpsim to a file using the VILLASnode interface +import json + import dpsimpy import dpsimpyvillas @@ -39,16 +41,16 @@ sim.set_time_step(time_step) sim.set_final_time(final_time) -file_config = '''{ - "type": "file", - "format": "csv", - "uri": "logs/output.csv", - "out": { - "flush": true - } -}''' +intf_config = { + 'type': 'file', + 'format': 'csv', + 'uri': 'logs/output.csv', + 'out': { + 'flush': True + } +} -intf = dpsimpyvillas.InterfaceVillas(file_config, name='dpsim-file') +intf = dpsimpyvillas.InterfaceVillas(name='dpsim-file', config=json.dumps(intf_config)) intf.export_attribute(evs.attr('i_intf').derive_coeff(0, 0), 0) sim.add_interface(intf) diff --git a/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py b/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py index 8b5ef2c850..3bc4e531b3 100644 --- a/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py +++ b/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py @@ -4,6 +4,7 @@ import logging import os import sys +import json import dpsimpy import dpsimpyvillas @@ -55,16 +56,18 @@ logger = dpsimpy.Logger(name) # setup VILLASnode -intf_mqtt = dpsimpyvillas.InterfaceVillas(name='MQTT', config='''{ - "type": "mqtt", - "host": "mqtt", - "in": { - "subscribe": "mqtt-dpsim" +intf_mqtt_config = { + 'type': 'mqtt', + 'host': 'mqtt', + 'in': { + 'subscribe': 'mqtt-dpsim' }, - "out": { - "publish": "dpsim-mqtt" + 'out': { + 'publish': 'dpsim-mqtt' } -}''') +} + +intf_mqtt = dpsimpyvillas.InterfaceVillas(name='MQTT', config=json.dumps(intf_mqtt_config)) # setup simulation sim = dpsimpy.RealTimeSimulation(name) diff --git a/examples/villas/dpsim-mqtt-import-export-MIMO.py b/examples/villas/dpsim-mqtt-import-export-MIMO.py index 1e37e46b86..f11efa8606 100644 --- a/examples/villas/dpsim-mqtt-import-export-MIMO.py +++ b/examples/villas/dpsim-mqtt-import-export-MIMO.py @@ -155,31 +155,31 @@ def dpsim(): sim.log_attribute('n2.v', n1.attr('v')) intf_config = { - "type": "mqtt", - "format": "json", - "host": "mqtt", - "in": { - "subscribe": "/mqtt-dpsim" + 'type': 'mqtt', + 'format': 'json', + 'host': 'mqtt', + 'in': { + 'subscribe': '/mqtt-dpsim' }, - "out": { - "publish": "/dpsim-mqtt" + 'out': { + 'publish': '/dpsim-mqtt' } } intf_config_2 = { - "type": "shmem", - "in": { - "name": "/shmem-dpsim" + 'type': 'shmem', + 'in': { + 'name': '/shmem-dpsim' }, - "out": { - "name": "/dpsim-shmem" + 'out': { + 'name': '/dpsim-shmem' } } - intf = dpsimpyvillas.InterfaceVillas(name="dpsim-mqtt", config=intf_config) + intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=json.dumps(intf_config)) sim.add_interface(intf) - intf2 = dpsimpyvillas.InterfaceVillas(name="dpsim-shmem", config=intf_config_2) + intf2 = dpsimpyvillas.InterfaceVillas(name='dpsim-shmem', config=json.dumps(intf_config_2)) sim.add_interface(intf2) intf.import_attribute(load.attr('P'), 0) intf.export_attribute(n1.attr('v').derive_coeff(0,0), 0) diff --git a/examples/villas/dpsim-mqtt-import-export.py b/examples/villas/dpsim-mqtt-import-export.py index 8367852c33..9d30034666 100644 --- a/examples/villas/dpsim-mqtt-import-export.py +++ b/examples/villas/dpsim-mqtt-import-export.py @@ -125,18 +125,18 @@ def dpsim(): sim.log_attribute('n2.v', n2.attr('v')) intf_config = { - "type": "mqtt", - "format": "json", - "host": "mqtt", - "in": { - "subscribe": "/mqtt-dpsim" + 'type': 'mqtt', + 'format': 'json', + 'host': 'mqtt', + 'in': { + 'subscribe': '/mqtt-dpsim' }, - "out": { - "publish": "/dpsim-mqtt" + 'out': { + 'publish': '/dpsim-mqtt' } } - intf = dpsimpyvillas.InterfaceVillas(name="dpsim-mqtt", config=intf_config) + intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=json.dumps(intf_config)) intf.import_attribute(load.attr('P'), 0) intf.export_attribute(n1.attr('v').derive_coeff(0,0), 0) intf.export_attribute(n2.attr('v').derive_coeff(0,0).derive_mag(), 1) diff --git a/examples/villas/dpsim-mqtt.py b/examples/villas/dpsim-mqtt.py index f50007efe2..b318e1827f 100644 --- a/examples/villas/dpsim-mqtt.py +++ b/examples/villas/dpsim-mqtt.py @@ -1,6 +1,8 @@ # This example demonstrates the export of values calculated by dpsim to a MQTT broker using the VILLASnode interface # Note, that dpsim also expects to read a (complex) reference voltage from MQTT, so the simulation will block on every timestep until this value is provided +import json + import dpsimpy import dpsimpyvillas @@ -40,19 +42,19 @@ sim.set_time_step(time_step) sim.set_final_time(final_time) -mqtt_config = '''{ - "type": "mqtt", - "format": "json", - "host": "mqtt", - "in": { - "subscribe": "/mqtt-dpsim" - }, - "out": { - "publish": "/dpsim-mqtt" - } -}''' - -intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=mqtt_config) +intf_config = { + 'type': 'mqtt', + 'format': 'json', + 'host': 'mqtt', + 'in': { + 'subscribe': '/mqtt-dpsim' + }, + 'out': { + 'publish': '/dpsim-mqtt' + } +} + +intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=json.dumps(intf_config)) intf.import_attribute(evs.attr('V_ref'), 0, True) intf.export_attribute(r12.attr('i_intf').derive_coeff(0, 0), 0) From a4ebda2e9a24e1dd5b3bc9161cb837b429676061 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 15 Feb 2024 17:21:03 +0000 Subject: [PATCH 2/3] villas: Add missing member initialization Signed-off-by: Steffen Vogel --- dpsim/include/dpsim/Interface.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dpsim/include/dpsim/Interface.h b/dpsim/include/dpsim/Interface.h index 29bd0a544c..63366beabb 100644 --- a/dpsim/include/dpsim/Interface.h +++ b/dpsim/include/dpsim/Interface.h @@ -39,7 +39,8 @@ class Interface : public SharedFactory { Interface(std::shared_ptr intf, const String &name = "", UInt downsampling = 1) - : mInterfaceWorker(intf), mName(name), mDownsampling(downsampling) { + : mInterfaceWorker(intf), mName(name), mDownsampling(downsampling), + mOpened(false) { mQueueDpsimToInterface = std::make_shared< moodycamel::BlockingReaderWriterQueue>(); mQueueInterfaceToDpsim = std::make_shared< From 5c3d801b79d2337b4eb8cf1e8da667168179674d Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Mon, 26 Feb 2024 08:59:56 +0000 Subject: [PATCH 3/3] wip: villas: Minor fixes and tweaks for VillasInterface --- .../dpsim-villas/InterfaceWorkerVillas.h | 2 +- dpsim-villas/src/InterfaceWorkerVillas.cpp | 95 +++++++++---------- 2 files changed, 48 insertions(+), 49 deletions(-) diff --git a/dpsim-villas/include/dpsim-villas/InterfaceWorkerVillas.h b/dpsim-villas/include/dpsim-villas/InterfaceWorkerVillas.h index 713b2c590e..b094d17bcf 100644 --- a/dpsim-villas/include/dpsim-villas/InterfaceWorkerVillas.h +++ b/dpsim-villas/include/dpsim-villas/InterfaceWorkerVillas.h @@ -22,7 +22,7 @@ class InterfaceWorkerVillas : public InterfaceWorker, public: using Ptr = std::shared_ptr; - using Sample = struct node::Sample; + using Sample = node::Sample; static UInt villasPriority; static UInt villasAffinity; diff --git a/dpsim-villas/src/InterfaceWorkerVillas.cpp b/dpsim-villas/src/InterfaceWorkerVillas.cpp index 9c7a6c15a4..1e55547e3c 100644 --- a/dpsim-villas/src/InterfaceWorkerVillas.cpp +++ b/dpsim-villas/src/InterfaceWorkerVillas.cpp @@ -12,9 +12,8 @@ #include #include -#include -#include #include +// #include using namespace CPS; using namespace DPsim; @@ -31,10 +30,10 @@ InterfaceWorkerVillas::InterfaceWorkerVillas(const String &nodeConfig, mSampleLength(sampleLength) {} void InterfaceWorkerVillas::open() { - SPDLOG_LOGGER_INFO(mLog, "Opening InterfaceWorkerVillas..."); + SPDLOG_LOGGER_INFO(mLog, "Opening VILLASnode interface worker."); if (!InterfaceWorkerVillas::villasInitialized) { - SPDLOG_LOGGER_INFO(mLog, "Initializing Villas..."); + SPDLOG_LOGGER_INFO(mLog, "Initializing VILLASnode."); initVillas(); InterfaceWorkerVillas::villasInitialized = true; } @@ -58,24 +57,24 @@ void InterfaceWorkerVillas::open() { ret = mNode->parse(config); if (ret < 0) { SPDLOG_LOGGER_ERROR(mLog, - "Error: Node in InterfaceVillas failed to parse " + "Error: Node in VILLASnode interface failed to parse " "config. Parse returned code {}", ret); std::exit(1); } ret = mNode->check(); if (ret < 0) { - SPDLOG_LOGGER_ERROR( - mLog, - "Error: Node in InterfaceVillas failed check. Check returned code {}", - ret); + SPDLOG_LOGGER_ERROR(mLog, + "Error: Node in VILLASnode interface failed check. " + "Check returned code {}", + ret); std::exit(1); } - SPDLOG_LOGGER_INFO(mLog, "Preparing VILLASNode instance..."); + SPDLOG_LOGGER_INFO(mLog, "Preparing VILLASnode node instance."); setupNodeSignals(); prepareNode(); - SPDLOG_LOGGER_INFO(mLog, "Node is ready to send / receive data!"); + SPDLOG_LOGGER_INFO(mLog, "VILLASnode node is ready to send / receive data!"); mOpened = true; mSequence = 0; @@ -93,8 +92,8 @@ void InterfaceWorkerVillas::prepareNode() { sizeof(Sample) + SAMPLE_DATA_LENGTH(mSampleLength)); if (ret < 0) { SPDLOG_LOGGER_ERROR(mLog, - "Error: InterfaceVillas failed to init sample pool. " - "pool_init returned code {}", + "Error: VILLASnode interface failed to init sample " + "pool. pool_init returned code {}", ret); std::exit(1); } @@ -102,20 +101,20 @@ void InterfaceWorkerVillas::prepareNode() { ret = mNode->prepare(); if (ret < 0) { SPDLOG_LOGGER_ERROR(mLog, - "Error: Node in InterfaceVillas failed to prepare. " - "Prepare returned code {}", + "Error: Node in VILLASnode interface failed to " + "prepare. Prepare returned code {}", ret); std::exit(1); } mNode->getFactory()->start( - nullptr); //We have no SuperNode, so just hope type_start doesnt use it... + nullptr); // We have no SuperNode, so just hope type_start doesnt use it... ret = mNode->start(); if (ret < 0) { SPDLOG_LOGGER_ERROR(mLog, - "Fatal error: failed to start node in InterfaceVillas. " - "Start returned code {}", + "Fatal error: failed to start node in VILLASnode " + "interface. Start returned code {}", ret); close(); std::exit(1); @@ -123,10 +122,10 @@ void InterfaceWorkerVillas::prepareNode() { } void InterfaceWorkerVillas::setupNodeSignals() { - mNode->out.path = new node::Path(); - mNode->out.path->signals = std::make_shared(); - node::SignalList::Ptr nodeOutputSignals = - mNode->out.path->getOutputSignals(false); + // mNode->out.path = new node::Path(); + // mNode->out.path->signals = std::make_shared(); + // node::SignalList::Ptr nodeOutputSignals = mNode->out.path->getOutputSignals(false); + node::SignalList::Ptr nodeOutputSignals = mNode->out.signals; nodeOutputSignals->clear(); int idx = 0; for (const auto &[id, signal] : mExportSignals) { @@ -154,21 +153,21 @@ void InterfaceWorkerVillas::setupNodeSignals() { } void InterfaceWorkerVillas::close() { - SPDLOG_LOGGER_INFO(mLog, "Closing InterfaceVillas..."); + SPDLOG_LOGGER_INFO(mLog, "Closing VILLASnode interface."); int ret = mNode->stop(); if (ret < 0) { - SPDLOG_LOGGER_ERROR( - mLog, - "Error: failed to stop node in InterfaceVillas. Stop returned code {}", - ret); + SPDLOG_LOGGER_ERROR(mLog, + "Error: failed to stop node in VILLASnode interface. " + "Stop returned code {}", + ret); std::exit(1); } mOpened = false; ret = node::pool_destroy(&mSamplePool); if (ret < 0) { SPDLOG_LOGGER_ERROR(mLog, - "Error: failed to destroy SamplePool in " - "InterfaceVillas. pool_destroy returned code {}", + "Error: failed to destroy SamplePool in VILLASnode " + "interface. pool_destroy returned code {}", ret); std::exit(1); } @@ -198,7 +197,7 @@ void InterfaceWorkerVillas::readValuesFromEnv( if (ret < 0) { SPDLOG_LOGGER_ERROR(mLog, "Fatal error: failed to read sample from " - "InterfaceVillas. Poll returned code {}", + "VILLASnode interface. Poll returned code {}", ret); close(); std::exit(1); @@ -215,7 +214,7 @@ void InterfaceWorkerVillas::readValuesFromEnv( } } } else { - //If the node does not support pollFds just do a blocking read + // If the node does not support pollFds just do a blocking read shouldRead = true; } @@ -226,7 +225,7 @@ void InterfaceWorkerVillas::readValuesFromEnv( if (ret < 0) { SPDLOG_LOGGER_ERROR(mLog, "Fatal error: failed to read sample from " - "InterfaceVillas. Read returned code {}", + "VILLASnode interface. Read returned code {}", ret); close(); std::exit(1); @@ -244,8 +243,8 @@ void InterfaceWorkerVillas::readValuesFromEnv( } if (!pollFds.empty()) { - //Manually clear the event file descriptor since Villas does not do that for some reason - //See https://github.com/VILLASframework/node/issues/309 + // Manually clear the event file descriptor since VILLASnode does not do that for some reason + // See https://github.com/VILLASframework/node/issues/309 uint64_t result = 0; ret = (int)::read(pollFds[0], &result, 8); if (ret < 0) { @@ -278,14 +277,14 @@ void InterfaceWorkerVillas::readValuesFromEnv( void InterfaceWorkerVillas::writeValuesToEnv( std::vector &updatedAttrs) { - //Update export sequence IDs + // Update export sequence IDs for (const auto &packet : updatedAttrs) { if (std::get<1>(mExports[packet.attributeId]) < packet.sequenceId) { std::get<1>(mExports[packet.attributeId]) = packet.sequenceId; } } - //Remove outdated packets + // Remove outdated packets auto beginOutdated = std::remove_if( updatedAttrs.begin(), updatedAttrs.end(), [this](auto packet) { return std::get<1>(mExports[packet.attributeId]) > packet.sequenceId; @@ -299,17 +298,17 @@ void InterfaceWorkerVillas::writeValuesToEnv( try { sample = node::sample_alloc(&mSamplePool); if (sample == nullptr) { - SPDLOG_LOGGER_ERROR(mLog, "InterfaceVillas could not allocate a new " + SPDLOG_LOGGER_ERROR(mLog, "VILLASnode interface could not allocate a new " "sample! Not sending any data!"); return; } - sample->signals = mNode->getOutputSignals(false); + sample->signals = mNode->out.signals; auto beginExported = std::remove_if( updatedAttrs.begin(), updatedAttrs.end(), [this, &sampleFilled, &sample](auto packet) { if (!std::get<2>(mExports[packet.attributeId])) { - //Write attribute to sample ASAP + // Write attribute to sample ASAP std::get<0>(mExports[packet.attributeId])(packet.value, sample); sampleFilled = true; return true; @@ -318,7 +317,7 @@ void InterfaceWorkerVillas::writeValuesToEnv( }); updatedAttrs.erase(beginExported, updatedAttrs.end()); - //Check if the remaining packets form a complete set + // Check if the remaining packets form a complete set if (((long)updatedAttrs.size()) == std::count_if(mExports.cbegin(), mExports.cend(), [this](auto x) { return std::get<2>(x); })) { @@ -342,8 +341,8 @@ void InterfaceWorkerVillas::writeValuesToEnv( } while (ret == 0); if (ret < 0) SPDLOG_LOGGER_ERROR(mLog, - "Failed to write samples to InterfaceVillas. Write " - "returned code {}", + "Failed to write samples to VILLASnode interface. " + "Write returned code {}", ret); sample_copy(mLastSample, sample); @@ -363,10 +362,10 @@ void InterfaceWorkerVillas::writeValuesToEnv( sample_decref(sample); if (ret < 0) - SPDLOG_LOGGER_ERROR( - mLog, - "Failed to write samples to InterfaceVillas. Write returned code {}", - ret); + SPDLOG_LOGGER_ERROR(mLog, + "Failed to write samples to VILLASnode interface. " + "Write returned code {}", + ret); /* Don't throw here, because we managed to send something */ } @@ -386,7 +385,7 @@ void InterfaceWorkerVillas::configureExport(UInt attributeId, const String &unit) { if (mOpened) { if (mLog != nullptr) { - SPDLOG_LOGGER_WARN(mLog, "InterfaceVillas has already been opened! " + SPDLOG_LOGGER_WARN(mLog, "VILLASnode interface has already been opened! " "Configuration will remain unchanged."); } return; @@ -489,7 +488,7 @@ void InterfaceWorkerVillas::configureImport(UInt attributeId, UInt idx) { if (mOpened) { if (mLog != nullptr) { - SPDLOG_LOGGER_WARN(mLog, "InterfaceVillas has already been opened! " + SPDLOG_LOGGER_WARN(mLog, "VILLASnode interface has already been opened! " "Configuration will remain unchanged."); } return;