Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix YetiDriver and include binary firmware image. #595

Merged
merged 2 commits into from
Mar 21, 2024
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
2 changes: 2 additions & 0 deletions modules/YetiDriver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ target_sources(${MODULE_NAME}

# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1
# insert other things like install cmds etc here
install(FILES yetiR1_2.0-1_firmware.bin DESTINATION ${CMAKE_INSTALL_DATADIR}/everest/modules/YetiDriver/firmware)

# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1
46 changes: 32 additions & 14 deletions modules/YetiDriver/board_support/evse_board_supportImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,28 +71,39 @@ void evse_board_supportImpl::init() {
std::lock_guard<std::mutex> lock(capsMutex);

caps.min_current_A_import = mod->config.caps_min_current_A;
caps.max_current_A_import = 6;
caps.max_current_A_import = 16;
caps.min_phase_count_import = 1;
caps.max_phase_count_import = 3;
caps.supports_changing_phases_during_charging = false;
caps.connector_type = types::evse_board_support::Connector_type::IEC62196Type2Cable;

caps.min_current_A_export = mod->config.caps_min_current_A;
caps.max_current_A_export = 6;
caps.max_current_A_export = 16;
caps.min_phase_count_export = 1;
caps.max_phase_count_export = 3;
caps.supports_changing_phases_during_charging = false;
}

mod->serial.signalCPState.connect([this](CpState cp_state) {
publish_event(cast_event_type(cp_state));

if (cp_state == CpState_STATE_A) {
mod->clear_errors_on_unplug();
if (cp_state not_eq last_cp_state) {
auto event_cp_state = cast_event_type(cp_state);
EVLOG_info << "CP state changed: " << types::board_support_common::event_to_string(event_cp_state.event);
publish_event(event_cp_state);

if (cp_state == CpState_STATE_A) {
mod->clear_errors_on_unplug();
}
last_cp_state = cp_state;
}
});
mod->serial.signalRelaisState.connect([this](bool relais_state) {
if (last_relais_state not_eq relais_state) {
publish_event(cast_event_type(relais_state));
last_relais_state = relais_state;
}
});
mod->serial.signalRelaisState.connect([this](bool relais_state) { publish_event(cast_event_type(relais_state)); });

mod->serial.signalPPState.connect([this](PpState pp_state) {
std::lock_guard<std::mutex> lock(capsMutex);
last_pp = cast_pp_type(pp_state);
publish_ac_pp_ampacity(last_pp);
});
Expand All @@ -113,20 +124,26 @@ void evse_board_supportImpl::init() {
caps.max_phase_count_export = l.hwcap_max_phase_count;

caps.supports_changing_phases_during_charging = l.supports_changing_phases_during_charging;
if (not caps_received) {
EVLOG_info << "Yeti Controller Configuration:";
EVLOG_info << " Hardware revision: " << l.hw_revision;
EVLOG_info << " Firmware version: " << l.sw_version_string;
EVLOG_info << " Current Limit: " << l.hwcap_max_current;
}
caps_received = true;
});
}

void evse_board_supportImpl::ready() {
wait_for_caps();
}

void evse_board_supportImpl::wait_for_caps() {
// Wait for caps to be received at least once
int i;
for (i = 0; i < 50; i++) {
{
std::lock_guard<std::mutex> lock(capsMutex);
if (caps_received)
break;
}

if (caps_received)
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
if (i == 49) {
Expand All @@ -136,6 +153,7 @@ void evse_board_supportImpl::ready() {
}

types::evse_board_support::HardwareCapabilities evse_board_supportImpl::handle_get_hw_capabilities() {
wait_for_caps();
std::lock_guard<std::mutex> lock(capsMutex);
return caps;
}
Expand Down
7 changes: 5 additions & 2 deletions modules/YetiDriver/board_support/evse_board_supportImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,12 @@
// ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1
// insert your private definitions here
types::evse_board_support::HardwareCapabilities caps;
bool caps_received{false};
std::atomic_bool caps_received{false};
std::mutex capsMutex;
types::board_support_common::ProximityPilot last_pp;
CpState last_cp_state{CpState::CpState_STATE_E};
bool last_relais_state{false};

Check notice on line 65 in modules/YetiDriver/board_support/evse_board_supportImpl.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/YetiDriver/board_support/evse_board_supportImpl.hpp#L65

class member 'evse_board_supportImpl::last_relais_state' is never used.
types::board_support_common::ProximityPilot last_pp{types::board_support_common::Ampacity::None};
void wait_for_caps();
// ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1
};

Expand Down
Binary file added modules/YetiDriver/yetiR1_2.0-1_firmware.bin
Binary file not shown.
4 changes: 4 additions & 0 deletions modules/YetiDriver/yeti_comms/evSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ bool evSerial::reset(const int reset_pin) {
system(cmd);
sprintf(cmd, "echo 0 > /sys/class/gpio/gpio%i/value", reset_pin);
system(cmd);

// clear uart input and output buffer
// tcflush(fd, TCIOFLUSH);

sprintf(cmd, "echo 1 > /sys/class/gpio/gpio%i/value", reset_pin);
system(cmd);
} else {
Expand Down
111 changes: 111 additions & 0 deletions modules/YetiDriver/yeti_comms/firmware_version.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#ifndef YETI_FIRMWARE_VERSION
#define YETI_FIRMWARE_VERSION

#include <regex>
#include <string>

/*
Helper class to handle yeti Firmware Versions of the following style:

Reported by MCU: 2.0-1-g2d51638
Included in file name: yetiR1_2.0-1_firmware.bin

*/

static std::vector<std::string> split_by_delimeters(const std::string& s, const std::string& delimeters) {
std::regex re("[" + delimeters + "]");
std::sregex_token_iterator first{s.begin(), s.end(), re, -1}, last;
return {first, last};
}

// parse version string from filename
static std::string from_filename(const std::string& v) {
auto tokens = split_by_delimeters(v, "_");
if (tokens.size() >= 2) {

Check notice on line 26 in modules/YetiDriver/yeti_comms/firmware_version.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/YetiDriver/yeti_comms/firmware_version.hpp#L26

Condition 'tokens.size()>=2' is always true
return tokens[1];
}
return "0.0-0";
}

class YetiFirmwareVersion {

public:
YetiFirmwareVersion() {
}

YetiFirmwareVersion(const std::string& _version_string) {

Check notice on line 38 in modules/YetiDriver/yeti_comms/firmware_version.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/YetiDriver/yeti_comms/firmware_version.hpp#L38

Class 'YetiFirmwareVersion' has a constructor with 1 argument that is not explicit.
from_string(_version_string);
}

std::string to_string() {
return std::to_string(major) + "." + std::to_string(minor) + "-" + std::to_string(revision);
}

void from_string(const std::string& _version_string) {
std::string version_string;
// Is it a full filename or just a version string from the MCU?
if (_version_string.rfind("yetiR", 0) == 0) {
version_string = from_filename(_version_string);
} else {
version_string = _version_string;
}

auto tokens = split_by_delimeters(version_string, ".-");

// parse into major, minor and revision
if (tokens.size() >= 1) {

Check notice on line 58 in modules/YetiDriver/yeti_comms/firmware_version.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/YetiDriver/yeti_comms/firmware_version.hpp#L58

Condition 'tokens.size()>=1' is always true
major = std::stoi(tokens[0]);
}

if (tokens.size() >= 2) {
minor = std::stoi(tokens[1]);
}

if (tokens.size() >= 3) {

Check notice on line 66 in modules/YetiDriver/yeti_comms/firmware_version.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/YetiDriver/yeti_comms/firmware_version.hpp#L66

Condition 'tokens.size()>=3' is always false
revision = std::stoi(tokens[2]);
}
}

YetiFirmwareVersion& operator=(const std::string& s) {
from_string(s);
return *this;
}

friend bool operator<(const YetiFirmwareVersion& l, const YetiFirmwareVersion& r) {
if (l.major < r.major) {
return true;
} else if (l.major > r.major) {
return false;
} else if (l.minor < r.minor) {
return true;
} else if (l.minor > r.minor) {
return false;
} else if (l.revision < r.revision) {
return true;
} else if (l.revision > r.revision) {
return false;
}
// they are identical
return false;
}

friend bool operator>(const YetiFirmwareVersion& lhs, const YetiFirmwareVersion& rhs) {
return rhs < lhs;
}

friend bool operator<=(const YetiFirmwareVersion& lhs, const YetiFirmwareVersion& rhs) {
return not(lhs > rhs);
}
friend bool operator>=(const YetiFirmwareVersion& lhs, const YetiFirmwareVersion& rhs) {
return not(lhs < rhs);
}

private:
int major{0};
int minor{0};
int revision{0};
};

#endif
3 changes: 1 addition & 2 deletions modules/YetiDriver/yeti_fwupdate/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ add_executable(yeti_fwupdate main.cpp)
target_include_directories(yeti_fwupdate PUBLIC "${PROJECT_BINARY_DIR}" PUBLIC "../yeti_comms/nanopb" PUBLIC "../yeti_comms/protobuf" PUBLIC "../yeti_comms")
target_link_libraries(yeti_fwupdate PRIVATE Pal::Sigslot Threads::Threads yeti_comms everest::framework)

install(TARGETS yeti_fwupdate
DESTINATION ${EVEREST_MOD_YETIDRIVER_DESTINATION})
install(TARGETS yeti_fwupdate)


25 changes: 20 additions & 5 deletions modules/YetiDriver/yeti_fwupdate/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@
#include <string.h>

#include "evSerial.h"
#include <filesystem>
#include <unistd.h>

#include "firmware_version.hpp"
#include "yeti.pb.h"
#include <sigslot/signal.hpp>

volatile bool sw_version_received = false;
std::atomic_bool sw_version_received = false;
YetiFirmwareVersion installed_fw_version;
std::string installed_fw_version_orig;

void recvKeepAliveLo(KeepAliveLo s) {
printf("Current Yeti SW Version: %s (Protocol %i.%i)\n", s.sw_version_string, s.protocol_version_major,
s.protocol_version_minor);
installed_fw_version = s.sw_version_string;
installed_fw_version_orig = s.sw_version_string;
sw_version_received = true;
}

Expand All @@ -29,7 +33,7 @@ int main(int argc, char* argv[]) {
exit(0);
}
const char* device = argv[1];
const char* filename = argv[2];
std::filesystem::path filename = argv[2];

evSerial* p = new evSerial();

Expand All @@ -42,6 +46,17 @@ int main(int argc, char* argv[]) {
break;
usleep(100);
}

YetiFirmwareVersion update_file_fw_version{filename.filename()};
printf("Installed Yeti Firmware Version: %s (%s)\n", installed_fw_version.to_string().c_str(),
installed_fw_version_orig.c_str());
printf("Update File Firmware Version: %s\n", update_file_fw_version.to_string().c_str());

if (installed_fw_version >= update_file_fw_version) {
printf("Latest version already installed. Exiting.\n");
exit(1);
}

printf("\nRebooting Yeti in ROM Bootloader mode...\n");
// send some dummy commands to make sure protocol is in sync
p->keepAlive();
Expand All @@ -54,7 +69,7 @@ int main(int argc, char* argv[]) {

sleep(1);
char cmd[1000];
sprintf(cmd, "stm32flash -b 115200 %.100s -v -w %.100s -R", device, filename);
sprintf(cmd, "stm32flash -b 115200 %.100s -v -w %.100s -R", device, filename.string().c_str());
// sprintf(cmd, "stm32flash -b115200 %.100s", device);
printf("Executing %s ...\n", cmd);
system(cmd);
Expand Down
Loading