Skip to content

Commit

Permalink
Merge pull request #14 from c-jimenez/develop
Browse files Browse the repository at this point in the history
Version 1.1.0
  • Loading branch information
c-jimenez authored Mar 1, 2023
2 parents a789d11 + 1b0f8b7 commit e317169
Show file tree
Hide file tree
Showing 16 changed files with 202 additions and 17 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ cp_simu
| |-status
|--cps
| |-simu_cp_XXX
| | |-cmd
| | |-status
| | |-connectors
| | | |-1
Expand All @@ -197,6 +198,7 @@ cp_simu
| | | | |-id_tag
| | | | |-status
| |-simu_cp_YYY
| | |-cmd
| | |-status
| | |-connectors
| | | |-1
Expand Down Expand Up @@ -348,4 +350,17 @@ The expected command payload is :
{
"faulted": false
}
```
```


Each simulated Charge Point are listening to the following topic to execute a certain command: **cp_simu/cps/simu_cp_XXX/cmd**.

The expected command payload is :
```
{
"type": "<cmd>"
}
```
So far there are 2 commands:
* close: ask to end the application
* ocpp_config: ask to send on MQTT topic **cp_simu/cps/simu_cp_XXX/ocpp_config** all the OCPP config of the Charge Point
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ RUN apt-get update && apt-get install build-essential clang cmake python3 python

RUN git clone https://github.com/c-jimenez/open-ocpp.git

RUN cd open-ocpp && git fetch --tags && git checkout v1.1.0 && make gcc && make install-gcc
RUN cd open-ocpp && git fetch --tags && git checkout v1.2.0 && make gcc && make install-gcc

RUN apt-get update && apt-get install pkg-config && apt-get -q autoremove && rm -rf "/var/lib/apt/lists/*"

Expand Down
3 changes: 2 additions & 1 deletion docker/Dockerfile_cp_simulator
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ COPY gcc_native/config.ini /var/chargepoint/config.ini
RUN chown ${simu_uid}:${simu_gid} /var/chargepoint/config.ini

COPY gcc_native /cp_simulator
COPY cp_simu_entrypoint.sh /cp_simu_entrypoint.sh

USER cp_simu

WORKDIR "/var/chargepoint"

ENTRYPOINT ["/cp_simulator/chargepoint"]
ENTRYPOINT ["/cp_simu_entrypoint.sh"]
32 changes: 32 additions & 0 deletions docker/Entrypoint/cp_simu_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash

cp_args=""
diagnostic_file_size=0

for i in "$@"; do
case $i in
--diagnostic_file_size*)
diagnostic_file_size="$2"
shift
;;
-*)
cp_args+=" $i $2"
shift
;;
*)
shift
;;
esac
done

# create big file and add it in diagnostic zip of charge point
if [ $diagnostic_file_size -gt 0 ]
then
echo "generate $diagnostic_file_size random strings in cp config file"
echo "$(tr -dc A-Za-z0-9 < /dev/urandom | head -c $diagnostic_file_size)" >> /var/chargepoint/blob.txt
cp_args+=" -f blob.txt"
fi

# start simulator
echo "start charpoint with arguments : $cp_args"
/cp_simulator/chargepoint $cp_args
Binary file modified imgs/connect.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified imgs/instances.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,12 @@ docker-build-simu-compile:
@${DOCKER_BUILD} -f docker/Dockerfile -t $(DOCKER_COMPILE_IMAGE) $(ROOT_DIR)/docker

docker-build-cp-simulator:
cp docker/Entrypoint/cp_simu_entrypoint.sh $(ROOT_DIR)/bin/
@${DOCKER_BUILD} -f docker/Dockerfile_cp_simulator -t $(DOCKER_SIMULATOR_IMAGE) $(ROOT_DIR)/bin/


run-simu:
docker run $(DOCKER_INTERACTIVE) --rm --network=host --name ocpp-simu $(DOCKER_SIMULATOR_IMAGE) -c test_ocpp
docker run $(DOCKER_INTERACTIVE) --rm --network=host --name ocpp-simu $(DOCKER_SIMULATOR_IMAGE)

run-launcher:
docker run $(DOCKER_INTERACTIVE) --rm --network=host --name ocpp-launcher --entrypoint /cp_simulator/launcher $(DOCKER_SIMULATOR_IMAGE)
Expand Down
2 changes: 1 addition & 1 deletion src/chargepoint/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ SOFTWARE.
#define VERSION_H

/** @brief Firmware version of the simulated charge point */
#define CHARGEPOINT_FW_VERSION "1.0.0"
#define CHARGEPOINT_FW_VERSION "1.1.0"

#endif // VERSION_H
15 changes: 13 additions & 2 deletions src/chargepoint/config/SimulatedChargePointConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,29 @@ SOFTWARE.
#include "OcppConfig.h"

#include <openocpp/IniFile.h>
#include <set>

/** @brief Configuration of the simulated charge point */
class SimulatedChargePointConfig
{
public:
/** @brief Constructor */
SimulatedChargePointConfig(const std::string& working_dir, const std::string& config_file)
: m_working_dir(working_dir), m_config(config_file), m_stack_config(m_config), m_ocpp_config(m_config), m_mqtt_config(m_config)
SimulatedChargePointConfig(const std::string& working_dir, const std::string& config_file, std::set<std::string>& diag_files)
: m_working_dir(working_dir),
m_config(config_file),
m_diag_files(diag_files),
m_stack_config(m_config),
m_ocpp_config(m_config),
m_mqtt_config(m_config)
{
}

/** @brief Working directory */
const std::string& workingDir() const { return m_working_dir; }

/** @brief files to put diagnostic zip */
const std::set<std::string>& diagFiles() const { return m_diag_files; }

/** @brief Stack internal configuration */
ocpp::config::IChargePointConfig& stackConfig() { return m_stack_config; }

Expand All @@ -67,6 +76,8 @@ class SimulatedChargePointConfig
std::string m_working_dir;
/** @brief Configuration file */
ocpp::helpers::IniFile m_config;
/** @brief files to put diagnostic zip */
std::set<std::string> m_diag_files;

/** @brief Stack internal configuration */
ChargePointConfig m_stack_config;
Expand Down
19 changes: 18 additions & 1 deletion src/chargepoint/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ SOFTWARE.
#include <iostream>
#include <string.h>
#include <thread>
#include <set>

using namespace std;

Expand Down Expand Up @@ -73,6 +74,7 @@ int main(int argc, char* argv[])
std::string mqtt_broker_url = "tcp://localhost:1883";
unsigned int max_charge_point_current = 32u;
unsigned int max_connector_current = 32u;
std::set<std::string> diag_files = {"ocpp.db"};

// Check parameters
if (argc > 1)
Expand Down Expand Up @@ -140,6 +142,19 @@ int main(int argc, char* argv[])
argc--;
max_connector_current = static_cast<unsigned int>(std::atoi(*argv));
}
else if ((strcmp(*argv, "-f") == 0) && (argc > 1))
{
argv++;
argc--;
// add all files in diag file list:
diag_files.insert(*argv);
while((argc > 2) && (*argv[1] != '-'))
{
argv++;
argc--;
diag_files.insert(*argv);
}
}
else
{
param = *argv;
Expand Down Expand Up @@ -168,14 +183,16 @@ int main(int argc, char* argv[])
std::cout << " -b : URL of the MQTT broker (Default = tcp://localhost:1883)" << std::endl;
std::cout << " -m : Max current in A for the whole Charge Point (Default = 32A)" << std::endl;
std::cout << " -i : Max current in A for a connector of the Charge Point (Default = 32A)" << std::endl;
std::cout << " -f : Files to put in diagnostic zip. Absolute path or relative path from working directory. " << std::endl;
std::cout << "Default = [ocpp.db]" << std::endl;
return 1;
}
}

// Open configuration file
std::filesystem::path path(working_dir);
path /= "config.ini";
SimulatedChargePointConfig config(working_dir, path.string());
SimulatedChargePointConfig config(working_dir, path.string(), diag_files);

// Update configuration file
std::filesystem::path db_path(working_dir);
Expand Down
60 changes: 52 additions & 8 deletions src/chargepoint/mqtt/MqttManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ SOFTWARE.
*/

#include "MqttManager.h"
#include "MeterSimulator.h"
#include "SimulatedChargePointConfig.h"
#include "Topics.h"
#include "MeterSimulator.h"

#include <openocpp/json.h>
#include <cstring>
#include <filesystem>
#include <iostream>
#include <openocpp/json.h>
#include <sstream>
#include <thread>

Expand Down Expand Up @@ -99,6 +99,10 @@ void MqttManager::mqttMessageReceived(const char* topic, const std::string& mess
std::cout << "Close command received" << std::endl;
m_end = true;
}
else if (strcmp(type, "ocpp_config") == 0)
{
publishOcppConfig();
}
}
else
{
Expand Down Expand Up @@ -205,6 +209,7 @@ void MqttManager::start(unsigned int nb_phases, unsigned int max_charge_point_cu
std::string chargepoint_tag_topics = chargepoint_topic + "connectors/+/id_tag";
std::string chargepoint_faulted_topics = chargepoint_topic + "connectors/+/faulted";
m_status_topic = chargepoint_topic + "status";
m_ocpp_config_topic = chargepoint_topic + "ocpp_config";
m_connectors_topic = chargepoint_topic + "connectors/";

// MQTT client
Expand All @@ -225,8 +230,10 @@ void MqttManager::start(unsigned int nb_phases, unsigned int max_charge_point_cu
std::cout << "Subscribing to charge point's command topic: " << chargepoint_cmd_topic << std::endl;
if (m_mqtt->subscribe(chargepoint_cmd_topic))
{
std::cout << "Subscribing to charge point's connector topics: " << chargepoint_car_topics << " and " << chargepoint_tag_topics << " and " << chargepoint_faulted_topics << std::endl;
if (m_mqtt->subscribe(chargepoint_car_topics) && m_mqtt->subscribe(chargepoint_tag_topics) && m_mqtt->subscribe(chargepoint_faulted_topics))
std::cout << "Subscribing to charge point's connector topics: " << chargepoint_car_topics << " and "
<< chargepoint_tag_topics << " and " << chargepoint_faulted_topics << std::endl;
if (m_mqtt->subscribe(chargepoint_car_topics) && m_mqtt->subscribe(chargepoint_tag_topics) &&
m_mqtt->subscribe(chargepoint_faulted_topics))
{
// Wait for disconnection or end of application
std::cout << "Ready!" << std::endl;
Expand Down Expand Up @@ -326,6 +333,43 @@ bool MqttManager::publishStatus(const std::string& status, unsigned int nb_phase
return ret;
}

/** @brief Publish the ocpp config of the connectors */
void MqttManager::publishOcppConfig()
{
// Check connectivity
if (m_mqtt->isConnected())
{
// Compute topic name
std::stringstream topic;
topic << m_ocpp_config_topic;

// Get vector of key/value for ocpp config
std::vector<ocpp::types::CiStringType<50u>> keys;
std::vector<ocpp::types::KeyValue> values;
std::vector<ocpp::types::CiStringType<50u>> unknown_values;
m_config.ocppConfig().getConfiguration(keys, values, unknown_values);

// Create the JSON message
rapidjson::Document msg;
msg.Parse("{}");
for (const ocpp::types::KeyValue& keyValue : values)
{
if (!keyValue.value.value().empty())
{
rapidjson::Value key(keyValue.key.c_str(), msg.GetAllocator());
rapidjson::Value value(keyValue.value.value().c_str(), msg.GetAllocator());
msg.AddMember(key, value, msg.GetAllocator());
}
}
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
msg.Accept(writer);

// Publish
m_mqtt->publish(topic.str(), buffer.GetString(), IMqttClient::QoS::QOS_0, true);
}
}

/** @brief Publish the data of the connectors */
void MqttManager::publishData(const std::vector<ConnectorData>& connectors)
{
Expand Down Expand Up @@ -358,9 +402,9 @@ void MqttManager::publishData(const std::vector<ConnectorData>& connectors)
msg.AddMember(rapidjson::StringRef("car_ready"), rapidjson::Value(connector.car_ready), msg.GetAllocator());

static const char* consumption_str[] = {"consumption_l1", "consumption_l2", "consumption_l3"};
std::vector<float> currents = connector.meter->getCurrents();
unsigned int nb_phases = connector.meter->getNumberOfPhases();
for (unsigned int i = 0; i < 3 ; i++)
std::vector<float> currents = connector.meter->getCurrents();
unsigned int nb_phases = connector.meter->getNumberOfPhases();
for (unsigned int i = 0; i < 3; i++)
{
if (i < nb_phases)
{
Expand Down Expand Up @@ -389,7 +433,7 @@ std::string MqttManager::buildStatusMessage(const char* status, unsigned int nb_
msg.Parse("{}");
#ifdef _MSC_VER
msg.AddMember(rapidjson::StringRef("pid"), rapidjson::Value(static_cast<uint64_t>(GetCurrentProcessId())), msg.GetAllocator());
#else // _MSC_VER
#else // _MSC_VER
msg.AddMember(rapidjson::StringRef("pid"), rapidjson::Value(getpid()), msg.GetAllocator());
#endif // _MSC_VER
msg.AddMember(rapidjson::StringRef("status"), rapidjson::Value(status, msg.GetAllocator()).Move(), msg.GetAllocator());
Expand Down
5 changes: 5 additions & 0 deletions src/chargepoint/mqtt/MqttManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ class MqttManager : public IMqttClient::IListener
/** @brief Publish the data of the connectors */
void publishData(const std::vector<ConnectorData>& connectors);

/** @brief Publish the ocpp config of the charge point */
void publishOcppConfig();

private:
/** @brief Configuration */
SimulatedChargePointConfig& m_config;
Expand All @@ -92,6 +95,8 @@ class MqttManager : public IMqttClient::IListener
IMqttClient* m_mqtt;
/** @brief Status topic */
std::string m_status_topic;
/** @brief Config topic */
std::string m_ocpp_config_topic;
/** @brief Connectors topic */
std::string m_connectors_topic;

Expand Down
16 changes: 15 additions & 1 deletion src/chargepoint/ocpp/ChargePointEventsHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,21 @@ std::string ChargePointEventsHandler::getDiagnostics(const ocpp::types::Optional
std::string diag_file = "/tmp/diag.zip";

std::stringstream ss;
ss << "zip " << diag_file << " " << m_config.stackConfig().databasePath();
ss << "zip " << diag_file;

for (auto filename : m_config.diagFiles()) {
std::string filepath = filename;
if (filepath[0] != '/') {
filepath = m_config.workingDir() + "/" + filepath;
}
if (std::filesystem::exists(filepath))
{
ss << " " << filepath;
} else {
cout << "Unable to add file " << filepath << " in diagnostic zip: not found" << endl;
}
}

int err = WEXITSTATUS(system(ss.str().c_str()));
cout << "Command line : " << ss.str() << " => " << err << endl;

Expand Down
15 changes: 15 additions & 0 deletions src/supervisor/ChargePointManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,21 @@ def remove_charge_point(self, cp_id: str) -> bool:
""" Send the command to remove the simulated charge point """
ret = self.__remove_charge_points([{"id": cp_id}])

def restart_all_charge_points(self) -> bool:
""" send restart command to all simulated charge points """
ret = True

for cp_id in self.__cps.keys():
ret = ret and self.restart_charge_point(cp_id)

return ret

def kill_all_charge_points(self):
""" send kill command to all simulated charge points """
cp_ids = self.__cps.keys()
for cp_id in cp_ids:
self.kill_charge_point(cp_id)

def restart_charge_point(self, cp_id: str) -> bool:
""" Send the command to restart the simulated charge point """

Expand Down
Loading

0 comments on commit e317169

Please sign in to comment.