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

NP- 327 emscripten communication #2131

Merged
merged 36 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5ea8d8f
Use smart pointer for communication
jellespijker Aug 1, 2024
1d066a4
Introduce EmscriptenCommunication class
jellespijker Aug 1, 2024
0533f8c
Enable Emscripten support in communication module
jellespijker Aug 2, 2024
cf6ef1f
Applied clang-format.
jellespijker Aug 2, 2024
f291338
Enable slice info callback for Emscripten communication
jellespijker Aug 5, 2024
e3a14ab
Switch to smart pointers
jellespijker Aug 6, 2024
c788fae
Applied clang-format.
jellespijker Aug 6, 2024
b96cf27
Switch to shared_ptr for better memory management
jellespijker Aug 7, 2024
40c342c
Merge remote-tracking branch 'origin/NP-327_emscripten_communication'…
jellespijker Aug 7, 2024
35ffb22
Merge branch 'main' into NP-327_emscripten_communication
jellespijker Aug 7, 2024
eb3eda6
Document EmscriptenCommunication class.
jellespijker Aug 15, 2024
e3d815c
Merge remote-tracking branch 'origin/NP-327_emscripten_communication'…
jellespijker Aug 15, 2024
9b4a913
Apply review suggestions
jellespijker Aug 15, 2024
6697713
build: add bigint flag to cmake for emscripten
0x5844 Aug 20, 2024
0f8e04f
refactor(FffGcodeWriter): fix extruder order calculation bug
0x5844 Aug 20, 2024
18cf586
Add GCode prefix handling in Emscripten communication
saumyaj3 Aug 21, 2024
ee99fda
Applied clang-format.
saumyaj3 Aug 21, 2024
77db867
fixing typo in .h file
saumyaj3 Aug 21, 2024
2a6b939
Np 351 adding gcode header to emscription (#2136)
jellespijker Aug 21, 2024
463df70
Merge branch 'main' into NP-327_emscripten_communication
jellespijker Aug 21, 2024
b45dd95
Apply review suggestions
jellespijker Aug 21, 2024
714f3e8
Fix UT
jellespijker Aug 22, 2024
cabaa89
Merge remote-tracking branch 'origin/NP-343-slicing-for-a-method-xl-p…
jellespijker Aug 22, 2024
63a84d0
Communication isn't sequential
jellespijker Aug 22, 2024
f87791a
Applied clang-format.
jellespijker Aug 22, 2024
d5afe4f
Refactor GCode handler variable and command line flag names
jellespijker Aug 22, 2024
38c59c3
Fix GCode prefix formatting in EmscriptenCommunication
saumyaj3 Aug 22, 2024
e5b17f9
Fix GCode prefix handler name in EmscriptenCommunication
saumyaj3 Aug 22, 2024
b9d5ef6
refactor: remove unnecessary type cast
0x5844 Aug 22, 2024
030ee68
Merge branch 'NP-327_emscripten_communication' of github.com:Ultimake…
0x5844 Aug 22, 2024
5c564a3
Add base64 encoding for GCode prefix handling.
saumyaj3 Aug 22, 2024
1177f6f
Applied clang-format.
saumyaj3 Aug 22, 2024
bf76f58
Rename handler for GCode prefix transmission.
saumyaj3 Aug 22, 2024
a45a607
Update include/communication/EmscriptenCommunication.h
jellespijker Aug 22, 2024
98cb105
Refactor to use existing mesh group object
saumyaj3 Aug 26, 2024
b719a42
Np 351 header containing extruder info (#2138)
HellAholic Aug 27, 2024
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
24 changes: 23 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ set(engine_SRCS # Except main.cpp.
src/communication/ArcusCommunication.cpp
src/communication/ArcusCommunicationPrivate.cpp
src/communication/CommandLine.cpp
src/communication/EmscriptenCommunication.cpp
src/communication/Listener.cpp

src/infill/ImageBasedDensityProvider.cpp
Expand Down Expand Up @@ -270,7 +271,28 @@ endif ()

if (CMAKE_CXX_PLATFORM_ID STREQUAL "emscripten")
message(STATUS "Building for Emscripten")
target_link_options(_CuraEngine PUBLIC -Wno-unused-command-line-argument -sINVOKE_RUN=0 -sEXPORT_NAME=CuraEngine -sEXPORTED_RUNTIME_METHODS=[callMain,FS] -sFORCE_FILESYSTEM=1 -sALLOW_MEMORY_GROWTH=1 -sEXPORT_ES6=1 -sMODULARIZE=1 -sSINGLE_FILE=1 -sENVIRONMENT=worker -sERROR_ON_UNDEFINED_SYMBOLS=0 -lembind --embind-emit-tsd CuraEngine.d.ts)
target_link_options(_CuraEngine
PUBLIC
"SHELL:-sINVOKE_RUN=0"
"SHELL:-sEXPORT_NAME=CuraEngine"
"SHELL:-sEXPORTED_RUNTIME_METHODS=[callMain,FS]"
"SHELL:-sFORCE_FILESYSTEM=1"
"SHELL:-sALLOW_MEMORY_GROWTH=1"
"SHELL:-sEXPORT_ES6=1"
"SHELL:-sMODULARIZE=1"
"SHELL:-sSINGLE_FILE=1"
"SHELL:-sENVIRONMENT=web"
"SHELL:-sERROR_ON_UNDEFINED_SYMBOLS=0"
"SHELL:-sWASM_BIGINT=1"
"SHELL:-sSTACK_SIZE=196608"
$<$<CONFIG:Debug>:SHELL:-sASSERTIONS=2>
$<$<CONFIG:Debug>:SHELL:-sSAFE_HEAP=1>
$<$<CONFIG:Debug>:SHELL:-sSTACK_OVERFLOW_CHECK=2>
$<$<CONFIG:Debug>:SHELL:-g3>
$<$<CONFIG:Debug>:SHELL:-gsource-map>
"SHELL:-lembind"
"SHELL:--embind-emit-tsd CuraEngine.d.ts"
)
endif ()

target_link_libraries(CuraEngine PRIVATE
Expand Down
5 changes: 3 additions & 2 deletions include/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <cassert>
#include <cstddef>
#include <memory>
#include <string>

#include "utils/NoCopy.h"
Expand Down Expand Up @@ -38,14 +39,14 @@ class Application : NoCopy
* can assume that it is safe to access this without checking whether it is
* initialised.
*/
Communication* communication_ = nullptr;
std::shared_ptr<Communication> communication_;

/*
* \brief The slice that is currently ongoing.
*
* If no slice has started yet, this will be a nullptr.
*/
Slice* current_slice_ = nullptr;
std::shared_ptr<Slice> current_slice_;

/*!
* \brief ThreadPool with lifetime tied to Application
Expand Down
13 changes: 6 additions & 7 deletions include/communication/CommandLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ using container_setting_map = std::unordered_map<std::string, setting_map>;
class CommandLine : public Communication
{
public:
CommandLine() = default;

/*
* \brief Construct a new communicator that interprets the command line to
* start a slice.
Expand Down Expand Up @@ -155,18 +157,15 @@ class CommandLine : public Communication
*/
void sliceNext() override;

private:
#ifdef __EMSCRIPTEN__
std::string progressHandler;
#endif

std::vector<std::filesystem::path> search_directories_;

protected:
/*
* \brief The command line arguments that the application was called with.
*/
std::vector<std::string> arguments_;

private:
std::vector<std::filesystem::path> search_directories_;

/*
* The last progress update that we output to stdcerr.
*/
Expand Down
65 changes: 65 additions & 0 deletions include/communication/EmscriptenCommunication.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) 2024 UltiMaker
// CuraEngine is released under the terms of the AGPLv3 or higher

#ifndef EMSCRIPTENCOMMUNICATION_H
#define EMSCRIPTENCOMMUNICATION_H
#ifdef __EMSCRIPTEN__

#include "communication/CommandLine.h"

namespace cura
{

/**
* \class EmscriptenCommunication
* \brief A class for handling communication in an Emscripten environment.
*
* This class extends the CommandLine class and provides specific implementations
* for sending progress and handling slice information in an Emscripten environment.
*/
class EmscriptenCommunication : public CommandLine
jellespijker marked this conversation as resolved.
Show resolved Hide resolved
{
private:
std::string progress_handler_; ///< Handler for progress messages.
std::string gcode_header_handler_; ///< Handler for getting the GCode handler.
std::string slice_info_handler_; ///< Handler for slice information messages.

/**
* \brief Creates a message containing slice information.
* \return A string containing the slice information message.
*/
[[nodiscard]] static std::string createSliceInfoMessage();

public:
/**
* \brief Constructor for EmscriptenCommunication.
* \param arguments A vector of strings containing the command line arguments.
*/
EmscriptenCommunication(const std::vector<std::string>& arguments);

/**
* \brief Sends the progress of the current operation.
* \param progress A double representing the progress percentage.
*/
void sendProgress(double progress) const override;

/**
* \brief Sends GcodeHeader
*/
void sendGCodePrefix(const std::string& prefix) const override;

/**
* \brief Initiates the slicing of the next item.
*/
void sliceNext() override;

bool isSequential() const override
{
return false;
}
};

} // namespace cura

#endif // __EMSCRIPTEN__
#endif // EMSCRIPTENCOMMUNICATION_H
27 changes: 27 additions & 0 deletions include/utils/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include <ctype.h>
#include <sstream> // ostringstream

#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/ostream_iterator.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <spdlog/spdlog.h>

namespace cura
Expand All @@ -27,6 +30,30 @@ static inline int stringcasecompare(const char* a, const char* b)
return *a - *b;
}

// Convert string to base64 string.
// This function is useful to forward string through javascript even if they contain any special strings
//
[[maybe_unused]] static std::string convertTobase64(const std::string& input)
{
using namespace boost::archive::iterators;
// prepare the stream to hold the encoded data
std::stringstream output;

// encode data
typedef base64_from_binary<transform_width<std::string::const_iterator, 6, 8>> base64_enc;
std::copy(base64_enc(input.begin()), base64_enc(input.end()), ostream_iterator<char>(output));

// Retrieve the encoded string
std::string output_encoded = output.str();

// ensure padding if needed
size_t num = (3 - input.length() % 3) % 3;
for (size_t i = 0; i < num; i++)
{
output_encoded.push_back('=');
}
return output_encoded;
}
/*!
* Efficient conversion of micron integer type to millimeter string.
*
Expand Down
12 changes: 8 additions & 4 deletions src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>

#include "Slice.h"
#include "communication/ArcusCommunication.h" //To connect via Arcus to the front-end.
#include "communication/CommandLine.h" //To use the command line to slice stuff.
#include "communication/EmscriptenCommunication.h" // To use Emscripten to slice stuff.
#include "progress/Progress.h"
#include "utils/ThreadPool.h"
#include "utils/string.h" //For stringcasecompare.
Expand All @@ -45,7 +47,6 @@ Application::Application()

Application::~Application()
{
delete communication_;
delete thread_pool_;
}

Expand Down Expand Up @@ -100,7 +101,7 @@ void Application::connect()
}
}

ArcusCommunication* arcus_communication = new ArcusCommunication();
auto arcus_communication = std::make_shared<ArcusCommunication>();
arcus_communication->connect(ip, port);
communication_ = arcus_communication;
}
Expand Down Expand Up @@ -214,8 +215,11 @@ void Application::slice()
{
arguments.emplace_back(argv_[argument_index]);
}

communication_ = new CommandLine(arguments);
#ifdef __EMSCRIPTEN__
communication_ = std::make_shared<EmscriptenCommunication>(arguments);
#else
communication_ = std::make_shared<CommandLine>(arguments);
#endif
wawanbreton marked this conversation as resolved.
Show resolved Hide resolved
}

void Application::run(const size_t argc, char** argv)
Expand Down
4 changes: 2 additions & 2 deletions src/LayerPlan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1982,7 +1982,7 @@ void LayerPlan::processFanSpeedAndMinimalLayerTime(Point2LL starting_position)

void LayerPlan::writeGCode(GCodeExport& gcode)
{
Communication* communication = Application::getInstance().communication_;
auto communication = Application::getInstance().communication_;
communication->setLayerForSend(layer_nr_);
communication->sendCurrentPosition(gcode.getPositionXY());
gcode.setLayerNr(layer_nr_);
Expand Down Expand Up @@ -2544,7 +2544,7 @@ bool LayerPlan::writePathWithCoasting(

Point2LL prev_pt = gcode.getPositionXY();
{ // write normal extrude path:
Communication* communication = Application::getInstance().communication_;
auto communication = Application::getInstance().communication_;
for (size_t point_idx = 0; point_idx <= point_idx_before_start; point_idx++)
{
auto [_, time] = extruder_plan.getPointToPointTime(prev_pt, path.points[point_idx], path);
Expand Down
16 changes: 8 additions & 8 deletions src/communication/ArcusCommunication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ void ArcusCommunication::sliceNext()

// Handle the main Slice message.
const cura::proto::Slice* slice_message = dynamic_cast<cura::proto::Slice*>(message.get()); // See if the message is of the message type Slice. Returns nullptr otherwise.
if (! slice_message)
if (slice_message == nullptr)
{
return;
}
Expand Down Expand Up @@ -553,15 +553,15 @@ void ArcusCommunication::sliceNext()
}
#endif // ENABLE_PLUGINS

Slice slice(slice_message->object_lists().size());
Application::getInstance().current_slice_ = &slice;
auto slice = std::make_shared<Slice>(slice_message->object_lists().size());
Application::getInstance().current_slice_ = slice;
jellespijker marked this conversation as resolved.
Show resolved Hide resolved

private_data->readGlobalSettingsMessage(slice_message->global_settings());
private_data->readExtruderSettingsMessage(slice_message->extruders());

// Broadcast the settings to the plugins
slots::instance().broadcast<plugins::v0::SlotID::SETTINGS_BROADCAST>(*slice_message);
const size_t extruder_count = slice.scene.extruders.size();
const size_t extruder_count = slice->scene.extruders.size();

// For each setting, register what extruder it should be obtained from (if this is limited to an extruder).
for (const cura::proto::SettingExtruder& setting_extruder : slice_message->limit_to_extruder())
Expand All @@ -572,8 +572,8 @@ void ArcusCommunication::sliceNext()
// If it's -1 it should be ignored as per the spec. Let's also ignore it if it's beyond range.
continue;
}
ExtruderTrain& extruder = slice.scene.extruders[setting_extruder.extruder()];
slice.scene.limit_to_extruder.emplace(setting_extruder.name(), &extruder);
ExtruderTrain& extruder = slice->scene.extruders[setting_extruder.extruder()];
slice->scene.limit_to_extruder.emplace(setting_extruder.name(), &extruder);
}

// Load all mesh groups, meshes and their settings.
Expand All @@ -584,9 +584,9 @@ void ArcusCommunication::sliceNext()
}
spdlog::debug("Done reading Slice message.");

if (! slice.scene.mesh_groups.empty())
if (! slice->scene.mesh_groups.empty())
{
slice.compute();
slice->compute();
FffProcessor::getInstance()->finalize();
flushGCode();
sendPrintTimeMaterialEstimates();
Expand Down
4 changes: 2 additions & 2 deletions src/communication/ArcusCommunicationPrivate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ std::shared_ptr<proto::LayerOptimized> ArcusCommunication::Private::getOptimized

void ArcusCommunication::Private::readGlobalSettingsMessage(const proto::SettingList& global_settings_message)
{
Slice* slice = Application::getInstance().current_slice_;
auto slice = Application::getInstance().current_slice_;
for (const cura::proto::Setting& setting_message : global_settings_message.settings())
{
slice->scene.settings.add(setting_message.name(), setting_message.value());
Expand All @@ -57,7 +57,7 @@ void ArcusCommunication::Private::readGlobalSettingsMessage(const proto::Setting
void ArcusCommunication::Private::readExtruderSettingsMessage(const google::protobuf::RepeatedPtrField<proto::Extruder>& extruder_messages)
{
// Make sure we have enough extruders added currently.
Slice* slice = Application::getInstance().current_slice_;
auto slice = Application::getInstance().current_slice_;
const size_t extruder_count = slice->scene.settings.get<size_t>("machine_extruder_count");
for (size_t extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++)
{
Expand Down
Loading
Loading