Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,12 @@ The status message has the following payload :
"max_setpoint":32.0,
"ocpp_setpoint":32.0,
"setpoint":0.0,
"consumption":0.0,
"car_consumption":0.0,
"consumption_l1":0.0,
"consumption_l2":0.0,
"consumption_l3":0.0,
"car_consumption_l1":0.0,
"car_consumption_l2":0.0,
"car_consumption_l3":0.0,
"car_cable_capacity":0.0,
"car_ready":true
}
Expand All @@ -318,9 +322,11 @@ The expected command payload is :

```
{
"cable": 32,
"cable": 32.0,
"ready": true,
"consumption": 10
"consumption_l1": 10.0,
"consumption_l2": 10.0,
"consumption_l3": 10.0
}
```

Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ARG gid=1000
RUN echo "APT::Get::Assume-Yes "true";" >> /etc/apt/apt.conf.d/aptconf


RUN apt-get update && apt-get install build-essential clang cmake python3 python3-pip python3-venv wget libpaho-mqtt-dev git openssl libssl-dev sqlite3 libsqlite3-dev\
RUN apt-get update && apt-get install build-essential clang cmake python3 python3-pip python3-venv wget libpaho-mqtt-dev git openssl libssl-dev sqlite3 libsqlite3-dev zip curl \
&& apt-get -q autoremove && rm -rf "/var/lib/apt/lists/*"

RUN git clone https://github.com/c-jimenez/open-ocpp.git
Expand Down
10 changes: 6 additions & 4 deletions src/chargepoint/ConnectorData.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ struct ConnectorData
max_setpoint(0.f),
ocpp_setpoint(0.f),
setpoint(0.f),
car_consumption(0.f),
car_consumption_l1(0.f),
car_consumption_l2(0.f),
car_consumption_l3(0.f),
car_cable_capacity(0.f),
car_ready(true),
preparing_start(),
Expand All @@ -63,10 +65,10 @@ struct ConnectorData
float ocpp_setpoint;
/** @brief Setpoint */
float setpoint;
/** @brief Consumption */
float consumption;
/** @brief Car consumption */
float car_consumption;
float car_consumption_l1;
float car_consumption_l2;
float car_consumption_l3;
/** @brief Car cable capacity */
float car_cable_capacity;
/** @brief Indicate that the car is ready to charge */
Expand Down
32 changes: 28 additions & 4 deletions src/chargepoint/SimulatedChargePoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,17 +650,41 @@ void SimulatedChargePoint::computeSetpoints(ocpp::chargepoint::IChargePoint& cha
void SimulatedChargePoint::computeCurrentConsumption(ConnectorData& connector)
{
// Default is no consumption
connector.consumption = 0.f;
float consumption_l1 = 0.f;
float consumption_l2 = 0.f;
float consumption_l3 = 0.f;

// Check if charging
if (connector.status == ChargePointStatus::Charging)
{
// Consumption must match both setpoint and car needs
connector.consumption = std::min(connector.car_consumption, connector.setpoint);
unsigned int nb_phases = connector.meter->getNumberOfPhases();
switch (nb_phases)
{
case 1:
consumption_l1 = std::min(connector.car_consumption_l1, connector.setpoint);
break;

case 2:
consumption_l1 = std::min(connector.car_consumption_l1, connector.setpoint);
consumption_l2 = std::min(connector.car_consumption_l2, connector.setpoint);
break;

case 3:
consumption_l1 = std::min(connector.car_consumption_l1, connector.setpoint);
consumption_l2 = std::min(connector.car_consumption_l2, connector.setpoint);
consumption_l3 = std::min(connector.car_consumption_l3, connector.setpoint);
break;

default:
break;
}
}

// Apply consumption in the meter
std::vector<float> currents(connector.meter->getNumberOfPhases());
currents.assign(currents.size(), connector.consumption);
std::vector<float> currents;
currents.push_back(consumption_l1);
currents.push_back(consumption_l2);
currents.push_back(consumption_l3);
connector.meter->setCurrents(currents);
}
2 changes: 1 addition & 1 deletion src/chargepoint/config/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ AuthorizationCacheEnabled=true
AuthorizeRemoteTxRequests=true
BlinkRepeat=10
ClockAlignedDataInterval=0
ConnectionTimeOut=3600
ConnectionTimeOut=30
ConnectorPhaseRotation=1.RST,2.RST,3.RST
ConnectorPhaseRotationMaxLength=3
GetConfigurationMaxKeys=150
Expand Down
49 changes: 40 additions & 9 deletions src/chargepoint/mqtt/MqttManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ SOFTWARE.
#include "MqttManager.h"
#include "SimulatedChargePointConfig.h"
#include "Topics.h"
#include "MeterSimulator.h"
#include "json.h"

#include <cstring>
Expand Down Expand Up @@ -58,6 +59,8 @@ void MqttManager::mqttMessageReceived(const char* topic, const std::string& mess
(void)qos;
(void)retained;

std::cout << "MQTT message received!" << std::endl;

// Decode message
bool valid = false;
rapidjson::Document payload;
Expand All @@ -75,6 +78,7 @@ void MqttManager::mqttMessageReceived(const char* topic, const std::string& mess
}
else
{
std::cout << "topic: " << topic << std::endl << "payload: " << message << std::endl;
// Split topic name
std::filesystem::path topic_path(topic);

Expand Down Expand Up @@ -128,12 +132,28 @@ void MqttManager::mqttMessageReceived(const char* topic, const std::string& mess
connector_data.car_ready = ready.GetBool();
}
}
if (payload.HasMember("consumption"))
if (payload.HasMember("consumption_l1"))
{
rapidjson::Value& consumption_l1 = payload["consumption_l1"];
if (consumption_l1.IsFloat())
{
connector_data.car_consumption_l1 = consumption_l1.GetFloat();
}
}
if (payload.HasMember("consumption_l2"))
{
rapidjson::Value& consumption_l2 = payload["consumption_l2"];
if (consumption_l2.IsFloat())
{
connector_data.car_consumption_l2 = consumption_l2.GetFloat();
}
}
if (payload.HasMember("consumption_l3"))
{
rapidjson::Value& consumption = payload["consumption"];
if (consumption.IsFloat())
rapidjson::Value& consumption_l3 = payload["consumption_l3"];
if (consumption_l3.IsFloat())
{
connector_data.car_consumption = consumption.GetFloat();
connector_data.car_consumption_l3 = consumption_l3.GetFloat();
}
}
}
Expand Down Expand Up @@ -185,10 +205,10 @@ void MqttManager::start(unsigned int nb_phases, unsigned int max_charge_point_cu
std::cout << "Connecting to the broker (" << m_config.mqttConfig().brokerUrl() << ")..." << std::endl;
if (m_mqtt->connect(m_config.mqttConfig().brokerUrl()))
{
std::cout << "Subscribing to charge point's command topic..." << std::endl;
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..." << std::endl;
std::cout << "Subscribing to charge point's connector topics: " << chargepoint_car_topics << " and " << chargepoint_tag_topics << std::endl;
if (m_mqtt->subscribe(chargepoint_car_topics) && m_mqtt->subscribe(chargepoint_tag_topics))
{
// Wait for disconnection or end of application
Expand Down Expand Up @@ -267,7 +287,9 @@ void MqttManager::updateData(std::vector<ConnectorData>& connectors) const
const ConnectorData& mqtt_data = m_connectors[connector.id - 1u];
connector.car_cable_capacity = mqtt_data.car_cable_capacity;
connector.car_ready = mqtt_data.car_ready;
connector.car_consumption = mqtt_data.car_consumption;
connector.car_consumption_l1 = mqtt_data.car_consumption_l1;
connector.car_consumption_l2 = mqtt_data.car_consumption_l2;
connector.car_consumption_l3 = mqtt_data.car_consumption_l3;
connector.fault_pending = mqtt_data.fault_pending;
}
}
Expand Down Expand Up @@ -312,11 +334,20 @@ void MqttManager::publishData(const std::vector<ConnectorData>& connectors)
msg.AddMember(rapidjson::StringRef("max_setpoint"), rapidjson::Value(connector.max_setpoint), msg.GetAllocator());
msg.AddMember(rapidjson::StringRef("ocpp_setpoint"), rapidjson::Value(connector.ocpp_setpoint), msg.GetAllocator());
msg.AddMember(rapidjson::StringRef("setpoint"), rapidjson::Value(connector.setpoint), msg.GetAllocator());
msg.AddMember(rapidjson::StringRef("consumption"), rapidjson::Value(connector.consumption), msg.GetAllocator());
msg.AddMember(rapidjson::StringRef("car_consumption"), rapidjson::Value(connector.car_consumption), msg.GetAllocator());
msg.AddMember(rapidjson::StringRef("car_consumption_l1"), rapidjson::Value(connector.car_consumption_l1), msg.GetAllocator());
msg.AddMember(rapidjson::StringRef("car_consumption_l2"), rapidjson::Value(connector.car_consumption_l2), msg.GetAllocator());
msg.AddMember(rapidjson::StringRef("car_consumption_l3"), rapidjson::Value(connector.car_consumption_l3), msg.GetAllocator());
msg.AddMember(rapidjson::StringRef("car_cable_capacity"), rapidjson::Value(connector.car_cable_capacity), msg.GetAllocator());
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 < nb_phases ; i++)
{
msg.AddMember(rapidjson::StringRef(consumption_str[i]), rapidjson::Value(currents[i]), msg.GetAllocator());
}

rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
msg.Accept(writer);
Expand Down
20 changes: 14 additions & 6 deletions src/supervisor/ChargePointManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,13 @@ def __init__(self, id: int) -> None:
# Setpoint
self.setpoint = 0
# Consumption
self.consumption = 0
self.consumption_l1 = 0
self.consumption_l2 = 0
self.consumption_l3 = 0
# Car consumption
self.car_consumption = 0
self.car_consumption_l1 = 0
self.car_consumption_l2 = 0
self.car_consumption_l3 = 0
# Car cable capacity
self.car_cable_capacity = 0
# Car ready for charging
Expand Down Expand Up @@ -138,7 +142,7 @@ def stop(self) -> bool:

return ret

def send_connector_values(self, cp_id: str, con_id: int, car_consumption: float, car_cable: float, car_ready: bool) -> bool:
def send_connector_values(self, cp_id: str, con_id: int, car_consumption_l1: float, car_consumption_l2: float, car_consumption_l3: float, car_cable: float, car_ready: bool) -> bool:
""" Send new connector values for a Charge Point """

ret = False
Expand All @@ -150,7 +154,7 @@ def send_connector_values(self, cp_id: str, con_id: int, car_consumption: float,

# Build message
payload = {"cable": car_cable, "ready": car_ready,
"consumption": car_consumption}
"consumption_l1": car_consumption_l1, "consumption_l2": car_consumption_l2, "consumption_l3": car_consumption_l3}

# Publish message
ret = self.__client.publish(topic_name, json.dumps(payload))
Expand Down Expand Up @@ -352,8 +356,12 @@ def __on_message_received(self, topic: str, payload: str, qos: int, retained: bo
con.max_setpoint = data["max_setpoint"]
con.ocpp_setpoint = data["ocpp_setpoint"]
con.setpoint = data["setpoint"]
con.consumption = data["consumption"]
con.car_consumption = data["car_consumption"]
con.consumption_l1 = data["consumption_l1"]
con.consumption_l2 = data["consumption_l2"]
con.consumption_l3 = data["consumption_l3"]
con.car_consumption_l1 = data["car_consumption_l1"]
con.car_consumption_l2 = data["car_consumption_l2"]
con.car_consumption_l3 = data["car_consumption_l3"]
con.car_cable_capacity = data["car_cable_capacity"]
con.car_ready = data["car_ready"]

Expand Down
10 changes: 7 additions & 3 deletions src/supervisor/ui/ConnectorWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,18 @@ class ConnectorWidget(BoxLayout):
con_id = NumericProperty(None)
status = StringProperty(None)
max_current = NumericProperty(None)
car_consumption = NumericProperty(None)
car_consumption_l1 = NumericProperty(None)
car_consumption_l2 = NumericProperty(None)
car_consumption_l3 = NumericProperty(None)
car_cable = NumericProperty(None)
car_ready = BooleanProperty(None)
id_tag = StringProperty(None)

def set_properties(self, car_consumption: float, car_cable: float, car_ready: bool, id_tag: str) -> None:
def set_properties(self, car_consumption_l1: float, car_consumption_l2: float, car_consumption_l3: float, car_cable: float, car_ready: bool, id_tag: str) -> None:
""" Set the properties values """
self.sl_car_consumption.value = car_consumption
self.sl_car_consumption_l1.value = car_consumption_l1
self.sl_car_consumption_l2.value = car_consumption_l2
self.sl_car_consumption_l3.value = car_consumption_l3
self.sl_car_cable.value = car_cable
self.tb_car_ready.active = not car_ready
self.ti_id_tag.text = id_tag
18 changes: 13 additions & 5 deletions src/supervisor/ui/SupervisorScreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ def __on_cp_update(self, cp: ChargePoint, deleted: bool) -> None:
connector_widget = self.stk_connectors.children[con_index]
if isinstance(connector_widget, ConnectorWidget) and connector_widget.con_id == con_id:
connector_widget.status = connector.status
connector_widget.consumption = connector.consumption
connector_widget.consumption_l1 = connector.consumption_l1
connector_widget.consumption_l2 = connector.consumption_l2
connector_widget.consumption_l3 = connector.consumption_l3
break

else:
Expand Down Expand Up @@ -302,13 +304,19 @@ def on_cp_selection_changed(self, value, *args):
widget.con_id = connector.id
widget.status = connector.status
widget.max_current = connector.max_setpoint
widget.consumption = connector.consumption
widget.set_properties(connector.car_consumption, connector.car_cable_capacity,
widget.consumption_l1 = connector.consumption_l1
widget.consumption_l2 = connector.consumption_l2
widget.consumption_l3 = connector.consumption_l3
widget.set_properties(connector.car_consumption_l1, connector.car_consumption_l2, connector.car_consumption_l3, connector.car_cable_capacity,
connector.car_ready, connector.id_tag)

# Bind to events
widget.bind(
car_consumption=self.on_connector_value_changed)
car_consumption_l1=self.on_connector_value_changed)
widget.bind(
car_consumption_l2=self.on_connector_value_changed)
widget.bind(
car_consumption_l3=self.on_connector_value_changed)
widget.bind(
car_cable=self.on_connector_value_changed)
widget.bind(
Expand All @@ -323,7 +331,7 @@ def on_connector_value_changed(self, connector, *args):
""" Called when a value in the connector has changed """
# Send new connector values
self.__cp_mgr.send_connector_values(
self.__selected_cp_id, connector.con_id, connector.car_consumption, connector.car_cable, connector.car_ready)
self.__selected_cp_id, connector.con_id, connector.car_consumption_l1, connector.car_consumption_l2, connector.car_consumption_l3, connector.car_cable, connector.car_ready)

def on_connector_id_tag_passed(self, connector, *args):
""" Called when an id tag has been passed on a connector """
Expand Down
Loading