Merge branch feat/printer-agent-infra into feat/printer-agent-impl

This commit is contained in:
Ian Chua
2026-09-18 15:59:25 +08:00
13 changed files with 287 additions and 396 deletions
+1 -1
View File
@@ -583,7 +583,7 @@ namespace Slic3r
<< " printer_agent_id=" << it->second->printer_agent_id << " printer_agent_id=" << it->second->printer_agent_id
<< " connection_type=" << it->second->connection_type() << " connection_type=" << it->second->connection_type()
<< " dev_connection_type=" << it->second->dev_connection_type; << " dev_connection_type=" << it->second->dev_connection_type;
} else { } else if (!dev_id.empty()) {
BOOST_LOG_TRIVIAL(warning) << "Orca diagnostic: target machine was not found in the current agent's machine list"; BOOST_LOG_TRIVIAL(warning) << "Orca diagnostic: target machine was not found in the current agent's machine list";
return false; return false;
} }
-20
View File
@@ -3,10 +3,6 @@
#include <wx/mediactrl.h> #include <wx/mediactrl.h>
#include <wx/uri.h> #include <wx/uri.h>
#include <memory>
#include <slic3r/Utils/IPrinterAgent.hpp>
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
class IMediaController class IMediaController
@@ -16,13 +12,6 @@ public:
virtual void Load(wxURI url) = 0; virtual void Load(wxURI url) = 0;
// The default keeps existing media controllers unaware of camera-specific modes.
virtual void Load(wxURI url, CameraStreamMode mode)
{
(void) mode;
Load(url);
}
virtual void Play() = 0; virtual void Play() = 0;
virtual void Stop() = 0; virtual void Stop() = 0;
@@ -32,15 +21,6 @@ public:
virtual int GetLastError() const { return {}; }; virtual int GetLastError() const { return {}; };
virtual wxSize GetVideoSize() const { return {}; }; virtual wxSize GetVideoSize() const { return {}; };
virtual void StartSession(std::unique_ptr<ICameraSignalingChannel> channel)
{
(void) channel;
}
virtual void StopSession() {}
private:
}; };
}} // namespace Slic3r::GUI }} // namespace Slic3r::GUI
+151 -148
View File
@@ -1,4 +1,6 @@
#include "MediaPlayCtrl.h" #include "MediaPlayCtrl.h"
#include "WebMediaController.hpp"
#include "IPrinterAgent.hpp"
#include "Widgets/Button.hpp" #include "Widgets/Button.hpp"
#include "Widgets/CheckBox.hpp" #include "Widgets/CheckBox.hpp"
#include "Widgets/Label.hpp" #include "Widgets/Label.hpp"
@@ -24,6 +26,7 @@
#include <boost/nowide/fstream.hpp> #include <boost/nowide/fstream.hpp>
#include <boost/nowide/utf8_codecvt.hpp> #include <boost/nowide/utf8_codecvt.hpp>
#include <slic3r/GUI/DeviceManager.hpp> #include <slic3r/GUI/DeviceManager.hpp>
#include <wx/mediactrl.h>
#undef pid_t #undef pid_t
#include <boost/process.hpp> #include <boost/process.hpp>
#ifdef __WIN32__ #ifdef __WIN32__
@@ -52,6 +55,7 @@ namespace GUI {
MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos, const wxSize &size) MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos, const wxSize &size)
: wxPanel(parent, wxID_ANY, pos, size) : wxPanel(parent, wxID_ANY, pos, size)
, m_media_ctrl(media_ctrl) , m_media_ctrl(media_ctrl)
, m_active_media_controller(media_ctrl)
{ {
SetLabel("MediaPlayCtrl"); SetLabel("MediaPlayCtrl");
SetBackgroundColour(*wxWHITE); SetBackgroundColour(*wxWHITE);
@@ -98,7 +102,10 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const w
}); });
m_button_play->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { TogglePlay(); }); m_button_play->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { TogglePlay(); });
m_button_play->Bind(wxEVT_RIGHT_UP, [this](auto & e) { m_media_ctrl->Play(); }); m_button_play->Bind(wxEVT_RIGHT_UP, [this](auto & e) {
if (m_active_media_controller)
m_active_media_controller->Play();
});
// Orca: live-view FAQ link binding removed (vendor URL) // Orca: live-view FAQ link binding removed (vendor URL)
Bind(wxEVT_RIGHT_UP, [this](auto & e) { Bind(wxEVT_RIGHT_UP, [this](auto & e) {
@@ -143,14 +150,12 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const w
MediaPlayCtrl::~MediaPlayCtrl() MediaPlayCtrl::~MediaPlayCtrl()
{ {
m_webrtc_stopping = true;
if (m_webrtc_ctrl) if (m_webrtc_ctrl)
m_webrtc_ctrl->StopSession(); m_webrtc_ctrl->Stop();
m_media_ctrl->EndExternalStream(); m_media_ctrl->EndExternalStream();
m_webrtc_stopping = false;
{ {
boost::unique_lock lock(m_mutex); boost::unique_lock lock(m_mutex);
m_tasks.push_back("<exit>"); m_tasks.push_back({"<exit>", nullptr});
m_cond.notify_all(); m_cond.notify_all();
} }
while (!m_thread.try_join_for(boost::chrono::milliseconds(10))) { while (!m_thread.try_join_for(boost::chrono::milliseconds(10))) {
@@ -163,6 +168,33 @@ MediaPlayCtrl::~MediaPlayCtrl()
void MediaPlayCtrl::SetWebMediaController(IMediaController *ctrl) void MediaPlayCtrl::SetWebMediaController(IMediaController *ctrl)
{ {
m_web_ctrl = ctrl; m_web_ctrl = ctrl;
set_active_media_controller(current_mode());
}
void MediaPlayCtrl::set_active_media_controller(CameraStreamMode mode)
{
switch (mode) {
case CameraStreamMode::http_snapshot:
if (auto *web_ctrl = dynamic_cast<WebMediaController *>(m_web_ctrl))
web_ctrl->set_mode(mode);
m_active_media_controller = m_web_ctrl;
break;
case CameraStreamMode::webrtc:
if (!m_webrtc_ctrl) {
m_webrtc_ctrl = std::make_unique<WebRtcMediaController>(
[this](const wxImage& image, wxSize size) { m_media_ctrl->SetExternalFrame(image, size); },
[this, token = std::weak_ptr<int>(m_token)](WebRtcMediaController::Status status) {
if (token.expired())
return;
CallAfter([this, status] { on_webrtc_status(status); });
});
}
m_active_media_controller = m_webrtc_ctrl.get();
break;
default:
m_active_media_controller = m_media_ctrl;
break;
}
} }
CameraStreamMode MediaPlayCtrl::current_mode() const CameraStreamMode MediaPlayCtrl::current_mode() const
@@ -181,57 +213,31 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
} }
m_last_mode = mode; m_last_mode = mode;
} }
set_active_media_controller(mode);
switch (mode) { const bool uses_local_camera_url = mode == CameraStreamMode::http || mode == CameraStreamMode::https ||
case CameraStreamMode::http: mode == CameraStreamMode::http_snapshot || mode == CameraStreamMode::rtsp;
case CameraStreamMode::https: const bool uses_webrtc = mode == CameraStreamMode::webrtc;
case CameraStreamMode::http_snapshot: const std::string machine = obj ? obj->get_dev_id() : "";
case CameraStreamMode::rtsp: { bool changed = false;
std::string machine = obj ? obj->get_dev_id() : "";
if (uses_local_camera_url) {
auto agent = wxGetApp().getAgent(); auto agent = wxGetApp().getAgent();
std::string url = agent ? agent->get_local_camera_stream_url() : ""; std::string url = agent ? agent->get_local_camera_stream_url() : "";
m_camera_exists = !url.empty(); m_camera_exists = !url.empty();
Enable(obj && m_camera_exists); Enable(obj && m_camera_exists);
bool changed = machine != m_machine || url != m_agent_camera_url; changed = machine != m_machine || url != m_agent_camera_url;
m_machine = machine;
m_agent_camera_url = url; m_agent_camera_url = url;
m_url = from_u8(url); m_url = from_u8(url);
if (!changed) { } else if (uses_webrtc) {
return;
}
// A genuine machine/URL switch: not a failure, so drop any pending
// failure back-off before (re)starting on the new target.
m_web_user_stopped = false;
m_failed_code = 0;
m_failed_retry = 0;
m_next_retry = wxDateTime();
if (m_last_state != MEDIASTATE_IDLE)
Stop(" ");
return;
}
case CameraStreamMode::webrtc: {
std::string machine = obj ? obj->get_dev_id() : "";
m_camera_exists = obj != nullptr; m_camera_exists = obj != nullptr;
Enable(obj != nullptr); Enable(obj != nullptr);
const bool changed = machine != m_machine; changed = machine != m_machine;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetMachineObject webrtc: changed=" << changed BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetMachineObject webrtc: changed=" << changed
<< " last_state=" << m_last_state << " web_user_stopped=" << m_web_user_stopped; << " last_state=" << m_last_state << " web_user_stopped=" << m_web_user_stopped;
m_machine = machine;
m_url.clear(); m_url.clear();
m_agent_camera_url.clear(); m_agent_camera_url.clear();
if (!changed) { } else {
return;
}
m_web_user_stopped = false;
if (m_last_state != MEDIASTATE_IDLE)
Stop(" ");
return;
}
default:
break;
}
std::string machine = obj ? obj->get_dev_id() : "";
if (obj) { if (obj) {
m_camera_exists = obj->has_ipcam; m_camera_exists = obj->has_ipcam;
m_dev_ver = obj->get_ota_version(); m_dev_ver = obj->get_ota_version();
@@ -259,9 +265,9 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
m_device_busy = false; m_device_busy = false;
} }
Enable(obj && obj->is_info_ready() && obj->m_push_count > 0); Enable(obj && obj->is_info_ready() && obj->m_push_count > 0);
if (machine == m_machine) { if (machine == m_machine)
return; return;
}
m_machine = machine; m_machine = machine;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine;
m_disable_lan = false; m_disable_lan = false;
@@ -280,6 +286,23 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2); m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2);
else else
SetStatus("", false); SetStatus("", false);
return;
}
m_machine = machine;
if (!changed)
return;
// A genuine target switch is not a stream failure and should clear the
// manual-stop state before the new target is allowed to play.
m_web_user_stopped = false;
if (uses_local_camera_url) {
m_failed_code = 0;
m_failed_retry = 0;
m_next_retry = wxDateTime();
}
if (m_last_state != MEDIASTATE_IDLE)
Stop(" ");
} }
wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t length = -1) wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t length = -1)
@@ -330,97 +353,71 @@ void refresh_agora_url(char const* device, char const* dev_ver, char const* chan
void MediaPlayCtrl::Play() void MediaPlayCtrl::Play()
{ {
switch (current_mode()) { if ((m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry) || !IsShownOnScreen() || m_last_state != MEDIASTATE_IDLE)
case CameraStreamMode::http_snapshot:
if (!m_next_retry.IsValid() || wxDateTime::Now() < m_next_retry)
return; return;
if (!IsShownOnScreen()) return;
if (m_last_state != MEDIASTATE_IDLE) return; const CameraStreamMode mode = current_mode();
if (m_machine.empty() || !IsEnabled() || !m_camera_exists || m_url.IsEmpty() || !m_web_ctrl) { set_active_media_controller(mode);
Stop(_L("Please confirm if the printer is connected.")); m_last_mode = mode;
return;
}
m_button_play->SetIcon("media_stop");
m_web_ctrl->Load(wxURI(m_url), current_mode());
m_web_ctrl->Play();
m_last_state = wxMEDIASTATE_PLAYING;
SetStatus(_L("Playing..."), false);
return;
case CameraStreamMode::http:
case CameraStreamMode::https:
case CameraStreamMode::rtsp:
if (m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry)
return;
if (!IsShownOnScreen()) return;
if (m_last_state != MEDIASTATE_IDLE) return;
m_failed_code = 0;
if (m_machine.empty() || !IsEnabled() || !m_camera_exists || m_url.IsEmpty()) {
Stop(_L("Please confirm if the printer is connected."));
return;
}
m_button_play->SetIcon("media_stop");
load();
return;
case CameraStreamMode::webrtc: {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play webrtc: last_state=" << m_last_state
<< " next_retry_valid=" << m_next_retry.IsValid()
<< " next_retry_future=" << (m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry)
<< " failed_retry=" << m_failed_retry << " shown=" << IsShownOnScreen();
if (m_webrtc_ctrl && m_webrtc_ctrl->is_active()) {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play webrtc: session already active, ignoring";
return;
}
if (m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry)
return;
if (!IsShownOnScreen() || m_last_state != MEDIASTATE_IDLE)
return;
m_failed_code = 0;
if (m_machine.empty() || !IsEnabled() || !m_camera_exists) {
Stop(_L("Please confirm if the printer is connected."));
return;
}
auto agent = wxGetApp().getAgent(); auto agent = wxGetApp().getAgent();
auto printer_agent = agent ? agent->get_printer_agent() : nullptr;
const bool is_bbl = (printer_agent ? printer_agent->get_agent_info().id : "") == BBL_PRINTER_AGENT_ID;
if (!is_bbl) {
const bool is_webrtc = mode == CameraStreamMode::webrtc;
const bool is_snapshot = mode == CameraStreamMode::http_snapshot;
const bool is_http_stream = mode == CameraStreamMode::http || mode == CameraStreamMode::https || mode == CameraStreamMode::rtsp;
if (!is_webrtc && !is_snapshot && !is_http_stream)
return;
auto *webrtc_ctrl = is_webrtc ? dynamic_cast<WebRtcMediaController *>(m_active_media_controller) : nullptr;
if (is_webrtc && (!webrtc_ctrl || !m_media_ctrl)) {
Stop(_L("Please confirm if the printer is connected."));
return;
}
if (webrtc_ctrl && webrtc_ctrl->is_active())
return;
m_failed_code = 0;
if (!m_active_media_controller || m_machine.empty() || !IsEnabled() || !m_camera_exists ||
(!is_webrtc && m_url.IsEmpty())) {
Stop(_L("Please confirm if the printer is connected."));
return;
}
if (is_webrtc) {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play webrtc: last_state=" << m_last_state << " failed_retry=" << m_failed_retry
<< " shown=" << IsShownOnScreen();
auto channel = agent ? agent->create_camera_signaling_channel(m_machine) : nullptr; auto channel = agent ? agent->create_camera_signaling_channel(m_machine) : nullptr;
if (!channel) { if (!channel) {
Stop(_L("Sign in to OrcaCloud to view the camera.")); Stop(_L("Sign in to OrcaCloud to view the camera."));
return; return;
} }
if (!m_webrtc_ctrl) { webrtc_ctrl->set_signalling_channel(std::move(channel));
m_webrtc_ctrl = std::make_unique<WebRtcMediaController>(
[this](const wxImage& image, wxSize size) { m_media_ctrl->SetExternalFrame(image, size); },
[this, token = std::weak_ptr<int>(m_token)](WebRtcMediaController::Status status) {
if (token.expired())
return;
CallAfter([this, status] { on_webrtc_status(status); });
});
}
m_button_play->SetIcon("media_stop");
m_media_ctrl->BeginExternalStream(); m_media_ctrl->BeginExternalStream();
m_last_state = MEDIASTATE_INITIALIZING; m_last_state = MEDIASTATE_INITIALIZING;
SetStatus(_L("Initializing..."), false); SetStatus(_L("Initializing..."), false);
m_webrtc_stopping = false; } else if (is_snapshot) {
m_webrtc_ctrl->StartSession(std::move(channel)); m_last_state = wxMEDIASTATE_PLAYING;
m_webrtc_epoch = m_webrtc_ctrl->epoch(); SetStatus(_L("Playing..."), false);
return;
}
default: // assumed to be CameraStreamMode::none
if (NetworkAgent* agent = wxGetApp().getAgent()) {
if (auto printer_agent = agent->get_printer_agent()) {
if (printer_agent->get_agent_info().id != BBL_PRINTER_AGENT_ID) {
return;
}
}
}
break;
} }
if (!m_next_retry.IsValid() || wxDateTime::Now() < m_next_retry) m_button_play->SetIcon("media_stop");
return; if (m_active_media_controller == m_media_ctrl) {
if (!IsShownOnScreen()) // wxMediaCtrl3 reports when it has a decoded frame; load() waits for
return; // that event before queuing Play so the stream is not marked stopped.
if (m_last_state != MEDIASTATE_IDLE) { load();
} else {
m_active_media_controller->Load(wxURI(m_url));
m_active_media_controller->Play();
}
if (webrtc_ctrl) {
m_webrtc_epoch = webrtc_ctrl->epoch();
}
return; return;
} }
m_failed_code = 0; m_failed_code = 0;
if (m_machine.empty()) { if (m_machine.empty()) {
Stop(_L("Please confirm if the printer is connected.")); Stop(_L("Please confirm if the printer is connected."));
@@ -441,7 +438,6 @@ void MediaPlayCtrl::Play()
} }
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play: " << m_lan_proto << m_remote_proto << m_disable_lan; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play: " << m_lan_proto << m_remote_proto << m_disable_lan;
NetworkAgent *agent = wxGetApp().getAgent();
std::string agent_version = agent ? agent->get_version() : ""; std::string agent_version = agent ? agent->get_version() : "";
if (m_lan_proto > LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) { if (m_lan_proto > LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
m_disable_lan = m_remote_proto && !m_lan_mode; // try remote next time m_disable_lan = m_remote_proto && !m_lan_mode; // try remote next time
@@ -545,8 +541,8 @@ void MediaPlayCtrl::StopWebStream()
{ {
if (m_last_state == MEDIASTATE_IDLE) if (m_last_state == MEDIASTATE_IDLE)
return; return;
if (m_web_ctrl) if (m_active_media_controller && m_active_media_controller == m_web_ctrl)
m_web_ctrl->Stop(); m_active_media_controller->Stop();
m_button_play->SetIcon("media_play"); m_button_play->SetIcon("media_play");
m_last_state = MEDIASTATE_IDLE; m_last_state = MEDIASTATE_IDLE;
SetStatus(_L("Video Stopped."), false); SetStatus(_L("Video Stopped."), false);
@@ -554,15 +550,14 @@ void MediaPlayCtrl::StopWebStream()
void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2) void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
{ {
const bool webrtc_active = m_webrtc_ctrl && m_last_mode == CameraStreamMode::webrtc; const bool webrtc_active = m_last_mode == CameraStreamMode::webrtc &&
dynamic_cast<WebRtcMediaController *>(m_active_media_controller) != nullptr;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Stop: last_state=" << m_last_state BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Stop: last_state=" << m_last_state
<< " webrtc_active=" << webrtc_active << " failed_code=" << m_failed_code << " webrtc_active=" << webrtc_active << " failed_code=" << m_failed_code
<< " msg='" << msg.ToUTF8().data() << "'"; << " msg='" << msg.ToUTF8().data() << "'";
if (webrtc_active) { if (webrtc_active) {
m_webrtc_stopping = true; m_active_media_controller->Stop();
m_webrtc_ctrl->StopSession();
m_media_ctrl->EndExternalStream(); m_media_ctrl->EndExternalStream();
m_webrtc_stopping = false;
} }
switch (m_last_mode) { switch (m_last_mode) {
case CameraStreamMode::http: case CameraStreamMode::http:
@@ -571,13 +566,14 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
const bool snapshot = m_last_mode == CameraStreamMode::http_snapshot; const bool snapshot = m_last_mode == CameraStreamMode::http_snapshot;
if (m_last_state != MEDIASTATE_IDLE) { if (m_last_state != MEDIASTATE_IDLE) {
if (snapshot) { if (snapshot) {
if (m_web_ctrl) m_web_ctrl->Stop(); if (m_active_media_controller)
m_active_media_controller->Stop();
} else { } else {
// http/https mode plays through the ffmpeg backend (m_media_ctrl), not // http/https mode plays through the ffmpeg backend (m_media_ctrl), not
// the webview - tear its read thread down too, otherwise it keeps // the webview - tear its read thread down too, otherwise it keeps
// pulling and painting frames after the UI says "Video Stopped". // pulling and painting frames after the UI says "Video Stopped".
boost::unique_lock lock(m_mutex); boost::unique_lock lock(m_mutex);
m_tasks.push_back("<stop>"); m_tasks.push_back({"<stop>", m_active_media_controller});
m_cond.notify_all(); m_cond.notify_all();
} }
m_button_play->SetIcon("media_play"); m_button_play->SetIcon("media_play");
@@ -611,7 +607,8 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
m_media_ctrl->InvalidateBestSize(); m_media_ctrl->InvalidateBestSize();
m_button_play->SetIcon("media_play"); m_button_play->SetIcon("media_play");
boost::unique_lock lock(m_mutex); boost::unique_lock lock(m_mutex);
m_tasks.push_back("<stop>"); if (!webrtc_active)
m_tasks.push_back({"<stop>", m_active_media_controller});
m_cond.notify_all(); m_cond.notify_all();
if (!msg.IsEmpty()) if (!msg.IsEmpty())
SetStatus(msg); SetStatus(msg);
@@ -678,7 +675,7 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
void MediaPlayCtrl::on_webrtc_status(WebRtcMediaController::Status status) void MediaPlayCtrl::on_webrtc_status(WebRtcMediaController::Status status)
{ {
// Drop CallAfter-queued events from a superseded StartSession attempt. // Drop CallAfter-queued events from a superseded Play attempt.
if (status.epoch != m_webrtc_epoch) if (status.epoch != m_webrtc_epoch)
return; return;
if (status.kind == WebRtcMediaController::Status::Connecting) { if (status.kind == WebRtcMediaController::Status::Connecting) {
@@ -839,7 +836,9 @@ void MediaPlayCtrl::jump_to_play()
void MediaPlayCtrl::onStateChanged(wxMediaEvent &event) void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
{ {
auto last_state = m_last_state; auto last_state = m_last_state;
auto state = m_media_ctrl->GetState(); if (m_active_media_controller != m_media_ctrl)
return;
auto state = m_active_media_controller->GetState();
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: " << state << ", last_state: " << last_state; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: " << state << ", last_state: " << last_state;
if ((int) state < 0) return; if ((int) state < 0) return;
{ {
@@ -851,14 +850,14 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
} }
if ((last_state == MEDIASTATE_IDLE || last_state == MEDIASTATE_INITIALIZING) && state == wxMEDIASTATE_STOPPED) { return; } if ((last_state == MEDIASTATE_IDLE || last_state == MEDIASTATE_INITIALIZING) && state == wxMEDIASTATE_STOPPED) { return; }
if ((last_state == wxMEDIASTATE_PAUSED || last_state == wxMEDIASTATE_PLAYING) && state == wxMEDIASTATE_STOPPED) { if ((last_state == wxMEDIASTATE_PAUSED || last_state == wxMEDIASTATE_PLAYING) && state == wxMEDIASTATE_STOPPED) {
m_failed_code = m_media_ctrl->GetLastError(); m_failed_code = m_active_media_controller->GetLastError();
Stop(); Stop();
return; return;
} }
if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED)) { if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED)) {
wxSize size = m_media_ctrl->GetVideoSize(); wxSize size = m_active_media_controller->GetVideoSize();
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
m_failed_code = m_media_ctrl->GetLastError(); m_failed_code = m_active_media_controller->GetLastError();
if (size.GetWidth() >= 320) { if (size.GetWidth() >= 320) {
m_last_state = state; m_last_state = state;
m_failed_code = 0; m_failed_code = 0;
@@ -868,7 +867,7 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
m_failed_retry = 0; m_failed_retry = 0;
m_disable_lan = false; m_disable_lan = false;
boost::unique_lock lock(m_mutex); boost::unique_lock lock(m_mutex);
m_tasks.push_back("<play>"); m_tasks.push_back({"<play>", m_active_media_controller});
m_cond.notify_all(); m_cond.notify_all();
} else if (event.GetId()) { } else if (event.GetId()) {
if (m_failed_code == 0) if (m_failed_code == 0)
@@ -923,7 +922,7 @@ void MediaPlayCtrl::load()
m_url = m_url + "&dump_info=" + boost::lexical_cast<std::string>(dump_info_file); m_url = m_url + "&dump_info=" + boost::lexical_cast<std::string>(dump_info_file);
} }
boost::unique_lock lock(m_mutex); boost::unique_lock lock(m_mutex);
m_tasks.push_back(m_url); m_tasks.push_back({m_url, m_active_media_controller});
m_cond.notify_all(); m_cond.notify_all();
} }
@@ -943,30 +942,34 @@ void MediaPlayCtrl::media_proc()
while (m_tasks.empty()) { while (m_tasks.empty()) {
m_cond.wait(lock); m_cond.wait(lock);
} }
wxString url = m_tasks.front(); MediaTask task = m_tasks.front();
if (m_tasks.size() >= 2 && !url.IsEmpty() && url[0] != '<' && m_tasks[1] == "<stop>") { if (m_tasks.size() >= 2 && !task.command.IsEmpty() && task.command[0] != '<' &&
BOOST_LOG_TRIVIAL(trace) << "MediaPlayCtrl: busy skip url: " << url; m_tasks[1].command == "<stop>" && task.controller == m_tasks[1].controller) {
BOOST_LOG_TRIVIAL(trace) << "MediaPlayCtrl: busy skip url: " << task.command;
m_tasks.pop_front(); m_tasks.pop_front();
m_tasks.pop_front(); m_tasks.pop_front();
continue; continue;
} }
lock.unlock(); lock.unlock();
if (url == "<stop>") { if (task.command == "<stop>") {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start stop"; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start stop";
m_media_ctrl->Stop(); if (task.controller)
task.controller->Stop();
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end stop"; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end stop";
} }
else if (url == "<exit>") { else if (task.command == "<exit>") {
break; break;
} }
else if (url == "<play>") { else if (task.command == "<play>") {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start play"; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start play";
m_media_ctrl->Play(); if (task.controller)
task.controller->Play();
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end play"; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end play";
} }
else { else {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load"; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
m_media_ctrl->Load(wxURI(url)); if (task.controller)
task.controller->Load(wxURI(task.command));
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end load"; BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end load";
} }
lock.lock(); lock.lock();
+7 -2
View File
@@ -75,6 +75,7 @@ private:
static bool get_stream_url(std::string *url = nullptr); static bool get_stream_url(std::string *url = nullptr);
CameraStreamMode current_mode() const; CameraStreamMode current_mode() const;
void set_active_media_controller(CameraStreamMode mode);
private: private:
static inline const wxMediaState MEDIASTATE_IDLE = static_cast<wxMediaState>(3); static inline const wxMediaState MEDIASTATE_IDLE = static_cast<wxMediaState>(3);
@@ -86,10 +87,10 @@ private:
std::shared_ptr<int> m_token = std::make_shared<int>(0); std::shared_ptr<int> m_token = std::make_shared<int>(0);
wxMediaCtrl3 * m_media_ctrl; wxMediaCtrl3 * m_media_ctrl;
IMediaController * m_active_media_controller = nullptr;
IMediaController * m_web_ctrl = nullptr; IMediaController * m_web_ctrl = nullptr;
std::unique_ptr<WebRtcMediaController> m_webrtc_ctrl; std::unique_ptr<WebRtcMediaController> m_webrtc_ctrl;
CameraStreamMode m_last_mode = CameraStreamMode::none; CameraStreamMode m_last_mode = CameraStreamMode::none;
bool m_webrtc_stopping = false;
std::uint64_t m_webrtc_epoch = 0; std::uint64_t m_webrtc_epoch = 0;
std::string m_agent_camera_url; std::string m_agent_camera_url;
bool m_web_user_stopped = false; bool m_web_user_stopped = false;
@@ -108,7 +109,11 @@ private:
bool m_disable_lan = false; bool m_disable_lan = false;
wxString m_url; wxString m_url;
std::deque<wxString> m_tasks; struct MediaTask {
wxString command;
IMediaController *controller = nullptr;
};
std::deque<MediaTask> m_tasks;
boost::mutex m_mutex; boost::mutex m_mutex;
boost::condition_variable m_cond; boost::condition_variable m_cond;
boost::thread m_thread; boost::thread m_thread;
+5 -3
View File
@@ -13,11 +13,13 @@ WebMediaController::WebMediaController(wxWebView* webview) : m_webview(webview)
m_webview->SetPage("<html><head><style>html,body{margin:0;height:100%;background:#000;}</style></head><body></body></html>", ""); m_webview->SetPage("<html><head><style>html,body{margin:0;height:100%;background:#000;}</style></head><body></body></html>", "");
} }
void WebMediaController::Load(wxURI url) { Load(url, CameraStreamMode::http); } void WebMediaController::Load(wxURI url)
void WebMediaController::Load(wxURI url, CameraStreamMode mode)
{ {
m_url = url.BuildURI().ToStdString(); m_url = url.BuildURI().ToStdString();
}
void WebMediaController::set_mode(CameraStreamMode mode)
{
m_stream_mode = mode; m_stream_mode = mode;
} }
+2 -1
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <slic3r/GUI/IMediaController.hpp> #include <slic3r/GUI/IMediaController.hpp>
#include <slic3r/Utils/IPrinterAgent.hpp>
#include <string> #include <string>
@@ -15,7 +16,7 @@ public:
void Load(wxURI url) override; void Load(wxURI url) override;
void Load(wxURI url, CameraStreamMode mode) override; void set_mode(CameraStreamMode mode);
void Play() override; void Play() override;
+9 -3
View File
@@ -31,7 +31,7 @@ WebRtcMediaController::WebRtcMediaController(std::function<void(const wxImage&,
WebRtcMediaController::~WebRtcMediaController() WebRtcMediaController::~WebRtcMediaController()
{ {
StopSession(); Stop();
} }
void WebRtcMediaController::report(Status status) void WebRtcMediaController::report(Status status)
@@ -52,8 +52,14 @@ void WebRtcMediaController::report(Status status)
m_on_status(status); m_on_status(status);
} }
void WebRtcMediaController::StartSession(std::unique_ptr<ICameraSignalingChannel> channel) void WebRtcMediaController::set_signalling_channel(std::unique_ptr<ICameraSignalingChannel> channel)
{ {
m_pending_signaling = std::move(channel);
}
void WebRtcMediaController::Play()
{
std::unique_ptr<ICameraSignalingChannel> channel = std::move(m_pending_signaling);
// Tear down any previous attempt WITHOUT notifying: the Stopped that would // Tear down any previous attempt WITHOUT notifying: the Stopped that would
// otherwise be delivered (async, via CallAfter) races the new attempt's // otherwise be delivered (async, via CallAfter) races the new attempt's
// Connecting and makes the consumer cancel a session that is mid-connect. // Connecting and makes the consumer cancel a session that is mid-connect.
@@ -101,7 +107,7 @@ void WebRtcMediaController::StartSession(std::unique_ptr<ICameraSignalingChannel
signaling->open(); signaling->open();
} }
void WebRtcMediaController::StopSession() void WebRtcMediaController::Stop()
{ {
teardown(true); teardown(true);
} }
+6 -5
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "IMediaController.hpp" #include "IMediaController.hpp"
#include <slic3r/Utils/IPrinterAgent.hpp>
#include <wx/image.h> #include <wx/image.h>
@@ -36,7 +37,7 @@ public:
DECODE_ERROR, DECODE_ERROR,
TIMEOUT, TIMEOUT,
} code = ICE_FAILED; } code = ICE_FAILED;
// Identifies the StartSession attempt this status belongs to, so the // Identifies the Play attempt this status belongs to, so the
// consumer can drop CallAfter-queued events from a superseded attempt. // consumer can drop CallAfter-queued events from a superseded attempt.
std::uint64_t epoch = 0; std::uint64_t epoch = 0;
}; };
@@ -45,14 +46,13 @@ public:
std::function<void(Status)> on_status); std::function<void(Status)> on_status);
~WebRtcMediaController() override; ~WebRtcMediaController() override;
void StartSession(std::unique_ptr<ICameraSignalingChannel> channel) override; void set_signalling_channel(std::unique_ptr<ICameraSignalingChannel> channel);
void StopSession() override;
std::uint64_t epoch() const { return m_epoch.load(); } std::uint64_t epoch() const { return m_epoch.load(); }
bool is_active() const { return m_alive.load(); } bool is_active() const { return m_alive.load(); }
void Load(wxURI) override {} void Load(wxURI) override {}
void Play() override {} void Play() override;
void Stop() override { StopSession(); } void Stop() override;
wxMediaState GetState() override; wxMediaState GetState() override;
wxSize GetVideoSize() const override; wxSize GetVideoSize() const override;
@@ -75,6 +75,7 @@ private:
// addRemoteCandidate until a remote description is set, so buffer them. // addRemoteCandidate until a remote description is set, so buffer them.
std::vector<std::pair<std::string, std::string>> m_pending_candidates; std::vector<std::pair<std::string, std::string>> m_pending_candidates;
bool m_remote_description_set = false; bool m_remote_description_set = false;
std::unique_ptr<ICameraSignalingChannel> m_pending_signaling;
std::unique_ptr<ICameraSignalingChannel> m_signaling; std::unique_ptr<ICameraSignalingChannel> m_signaling;
std::shared_ptr<rtc::PeerConnection> m_peer_connection; std::shared_ptr<rtc::PeerConnection> m_peer_connection;
std::shared_ptr<rtc::DataChannel> m_data_channel; std::shared_ptr<rtc::DataChannel> m_data_channel;
+2 -2
View File
@@ -163,13 +163,13 @@ wxMediaState wxMediaCtrl3::GetState()
return m_state; return m_state;
} }
int wxMediaCtrl3::GetLastError() int wxMediaCtrl3::GetLastError() const
{ {
std::unique_lock<std::mutex> lk(m_mutex); std::unique_lock<std::mutex> lk(m_mutex);
return m_error; return m_error;
} }
wxSize wxMediaCtrl3::GetVideoSize() wxSize wxMediaCtrl3::GetVideoSize() const
{ {
std::unique_lock<std::mutex> lk(m_mutex); std::unique_lock<std::mutex> lk(m_mutex);
return m_video_size; return m_video_size;
+10 -9
View File
@@ -13,6 +13,7 @@
#include "wx/bitmap.h" #include "wx/bitmap.h"
#include "wx/uri.h" #include "wx/uri.h"
#include "wx/mediactrl.h" #include "wx/mediactrl.h"
#include "IMediaController.hpp"
wxDECLARE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent); wxDECLARE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent);
@@ -27,18 +28,18 @@ void wxMediaCtrl_OnSize(wxWindow * ctrl, wxSize const & videoSize, int width, in
class AVVideoDecoder; class AVVideoDecoder;
class wxMediaCtrl3 : public wxWindow, BambuLib class wxMediaCtrl3 : public wxWindow, public Slic3r::GUI::IMediaController, BambuLib
{ {
public: public:
wxMediaCtrl3(wxWindow *parent); wxMediaCtrl3(wxWindow *parent);
~wxMediaCtrl3(); ~wxMediaCtrl3() override;
void Load(wxURI url); void Load(wxURI url) override;
void Play(); void Play() override;
void Stop(); void Stop() override;
// Render frames supplied by a controller which owns its own transport. // Render frames supplied by a controller which owns its own transport.
// The frame is copied while m_mutex is held; callers may release it after // The frame is copied while m_mutex is held; callers may release it after
@@ -52,11 +53,11 @@ public:
void SetIdleImage(wxString const & image); void SetIdleImage(wxString const & image);
wxMediaState GetState(); wxMediaState GetState() override;
int GetLastError(); int GetLastError() const override;
wxSize GetVideoSize(); wxSize GetVideoSize() const override;
protected: protected:
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
@@ -93,7 +94,7 @@ private:
std::uint64_t m_last_PTS{0}; std::uint64_t m_last_PTS{0};
std::chrono::system_clock::time_point m_last_PTS_expected; std::chrono::system_clock::time_point m_last_PTS_expected;
std::chrono::system_clock::time_point m_last_PTS_practical; std::chrono::system_clock::time_point m_last_PTS_practical;
std::mutex m_mutex; mutable std::mutex m_mutex;
std::condition_variable m_cond; std::condition_variable m_cond;
std::thread m_thread; std::thread m_thread;
std::atomic_bool m_refresh_pending{false}; std::atomic_bool m_refresh_pending{false};
-146
View File
@@ -148,152 +148,6 @@ void BBLPrinterAgent::set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud)
// Communication // Communication
// ============================================================================ // ============================================================================
std::string BBLPrinterAgent::ams_refresh_rfid_gcode(const std::string& tray_id)
{
return (boost::format("M620 R%1% \n") % tray_id).str();
}
std::string BBLPrinterAgent::ams_calibrate_gcode(int ams_id)
{
return (boost::format("M620 C%1% \n") % ams_id).str();
}
std::string BBLPrinterAgent::ams_select_tray_gcode(const std::string& tray_id)
{
return (boost::format("M620 P%1% \n") % tray_id).str();
}
int BBLPrinterAgent::command_ams_refresh_rfid(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode)
{
const std::string gcode = ams_refresh_rfid_gcode(tray_id);
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode;
nlohmann::json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = gcode;
j["print"]["sequence_id"] = std::to_string(sequence_id);
return publish(dev_id, j, lan_mode);
}
int BBLPrinterAgent::command_ams_calibrate(std::string dev_id, int ams_id, int sequence_id, bool lan_mode)
{
const std::string gcode = ams_calibrate_gcode(ams_id);
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode;
nlohmann::json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = gcode;
j["print"]["sequence_id"] = std::to_string(sequence_id);
return publish(dev_id, j, lan_mode);
}
int BBLPrinterAgent::command_ams_select_tray(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode)
{
const std::string gcode = ams_select_tray_gcode(tray_id);
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode;
nlohmann::json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = gcode;
j["print"]["sequence_id"] = std::to_string(sequence_id);
return publish(dev_id, j, lan_mode);
}
int BBLPrinterAgent::command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode)
{
nlohmann::json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = "G90 \n";
j["print"]["sequence_id"] = std::to_string(sequence_id);
return publish(dev_id, j, lan_mode);
}
int BBLPrinterAgent::command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode)
{
nlohmann::json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = "G29 \n";
j["print"]["sequence_id"] = std::to_string(sequence_id);
return publish(dev_id, j, lan_mode);
}
int BBLPrinterAgent::command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing, int sequence_id, bool lan_mode)
{
nlohmann::json j;
j["print"]["sequence_id"] = std::to_string(sequence_id);
if (supports_mqtt_homing) {
j["print"]["command"] = "back_to_center";
return publish(dev_id, j, lan_mode);
}
j["print"]["command"] = "gcode_line";
j["print"]["param"] = is_printing ? "G28 X\n" : "G28 \n";
return publish(dev_id, j, lan_mode);
}
int BBLPrinterAgent::command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl, int sequence_id, bool lan_mode)
{
nlohmann::json j;
j["print"]["sequence_id"] = std::to_string(sequence_id);
if (supports_mqtt_bed_ctrl) {
j["print"]["command"] = "set_bed_temp";
j["print"]["temp"] = temp;
return publish(dev_id, j, lan_mode);
}
j["print"]["command"] = "gcode_line";
j["print"]["param"] = (boost::format("M140 S%1%\n") % temp).str();
return publish(dev_id, j, lan_mode);
}
int BBLPrinterAgent::command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode)
{
nlohmann::json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = (boost::format("M104 S%1%\n") % temp).str();
j["print"]["sequence_id"] = std::to_string(sequence_id);
return publish(dev_id, j, lan_mode);
}
int BBLPrinterAgent::command_axis_control(std::string dev_id, std::string axis, double unit, double input_val, int speed,
bool is_core_xy, bool supports_mqtt_axis_control, int sequence_id, bool lan_mode)
{
nlohmann::json j;
j["print"]["sequence_id"] = std::to_string(sequence_id);
if (supports_mqtt_axis_control) {
int dir = input_val > 0 ? 1 : -1;
// i3-arch printers move the bed for Y/Z, so the on-screen direction is
// reversed -- same negation the g-code fallback below applies.
if (!is_core_xy && (axis == "Y" || axis == "Z")) {
dir = -dir;
}
j["print"]["command"] = "xyz_ctrl";
j["print"]["axis"] = axis;
j["print"]["dir"] = dir;
j["print"]["mode"] = (std::abs(input_val) >= 10) ? 1 : 0;
return publish(dev_id, j, lan_mode);
}
double value = input_val;
if (!is_core_xy && (axis == "Y" || axis == "Z")) {
value = -1.0 * input_val;
}
std::string value_str = (boost::format("%.1f") % (value * unit)).str();
std::string gcode;
if (axis == "X" || axis == "Y" || axis == "Z") {
gcode = (boost::format("M211 S \nM211 X1 Y1 Z1\nM1002 push_ref_mode\nG91 \nG1 %1%%2% F%3%\nM1002 pop_ref_mode\nM211 R\n")
% axis % value_str % speed).str();
} else if (axis == "E") {
gcode = (boost::format("M83 \nG0 %1%%2% F%3%\n") % axis % value_str % speed).str();
} else {
return -1;
}
j["print"]["command"] = "gcode_line";
j["print"]["param"] = gcode;
return publish(dev_id, j, lan_mode);
}
int BBLPrinterAgent::publish(const std::string& dev_id, const nlohmann::json& j, bool lan_mode) int BBLPrinterAgent::publish(const std::string& dev_id, const nlohmann::json& j, bool lan_mode)
{ {
const int rtn = lan_mode ? send_message_to_printer(dev_id, j.dump(), 0, 0) : send_message(dev_id, j.dump(), 0, 0); const int rtn = lan_mode ? send_message_to_printer(dev_id, j.dump(), 0, 0) : send_message(dev_id, j.dump(), 0, 0);
+1 -14
View File
@@ -29,23 +29,10 @@ public:
// Communication // Communication
int send_message(std::string dev_id, std::string json_str, int qos, int flag) override; int send_message(std::string dev_id, std::string json_str, int qos, int flag) override;
static std::string ams_refresh_rfid_gcode(const std::string& tray_id); std::string default_lan_username() const override { return "bblp"; }
static std::string ams_calibrate_gcode(int ams_id);
static std::string ams_select_tray_gcode(const std::string& tray_id);
int command_ams_refresh_rfid(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode) override;
int command_ams_calibrate(std::string dev_id, int ams_id, int sequence_id, bool lan_mode) override;
int command_ams_select_tray(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode) override;
int command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode) override;
int command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode) override;
int command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing, int sequence_id, bool lan_mode) override;
int command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl, int sequence_id, bool lan_mode) override;
int command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode) override;
int command_axis_control(std::string dev_id, std::string axis, double unit, double input_val, int speed,
bool is_core_xy, bool supports_mqtt_axis_control, int sequence_id, bool lan_mode) override;
int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl) override; int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl) override;
int disconnect_printer() override; int disconnect_printer() override;
int send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag) override; int send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag) override;
std::string default_lan_username() const override { return "bblp"; }
// Certificates // Certificates
int check_cert() override; int check_cert() override;
+56 -5
View File
@@ -14,6 +14,9 @@
#include <vector> #include <vector>
#include <functional> #include <functional>
#include <cstdint> #include <cstdint>
#include <cmath>
#include <nlohmann/json.hpp>
#include <boost/format.hpp>
#include "ICameraSignalingChannel.hpp" #include "ICameraSignalingChannel.hpp"
namespace Slic3r { namespace Slic3r {
@@ -109,16 +112,64 @@ public:
virtual int command_start_camera(std::string) virtual int command_start_camera(std::string)
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; } { return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
private:
int publish_command_json(std::string dev_id, const nlohmann::json& j, bool lan_mode)
{
return lan_mode ? send_message_to_printer(dev_id, j.dump(), 0, 0)
: send_message(dev_id, j.dump(), 0, 0);
}
public:
virtual int command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode) virtual int command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode)
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; } {
nlohmann::json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = "G90 \n";
j["print"]["sequence_id"] = std::to_string(sequence_id);
return publish_command_json(dev_id, j, lan_mode);
}
virtual int command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode) virtual int command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode)
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; } {
nlohmann::json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = "G29 \n";
j["print"]["sequence_id"] = std::to_string(sequence_id);
return publish_command_json(dev_id, j, lan_mode);
}
virtual int command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing, int sequence_id, bool lan_mode) virtual int command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing, int sequence_id, bool lan_mode)
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; } {
nlohmann::json j;
j["print"]["sequence_id"] = std::to_string(sequence_id);
if (supports_mqtt_homing) {
j["print"]["command"] = "back_to_center";
} else {
j["print"]["command"] = "gcode_line";
j["print"]["param"] = is_printing ? "G28 X\n" : "G28 \n";
}
return publish_command_json(dev_id, j, lan_mode);
}
virtual int command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl, int sequence_id, bool lan_mode) virtual int command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl, int sequence_id, bool lan_mode)
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; } {
nlohmann::json j;
j["print"]["sequence_id"] = std::to_string(sequence_id);
if (supports_mqtt_bed_ctrl) {
j["print"]["command"] = "set_bed_temp";
j["print"]["temp"] = temp;
} else {
j["print"]["command"] = "gcode_line";
j["print"]["param"] = (boost::format("M140 S%1%\n") % temp).str();
}
return publish_command_json(dev_id, j, lan_mode);
}
virtual int command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode) virtual int command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode)
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; } {
nlohmann::json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = (boost::format("M104 S%1%\n") % temp).str();
j["print"]["sequence_id"] = std::to_string(sequence_id);
return publish_command_json(dev_id, j, lan_mode);
}
virtual int command_axis_control(std::string dev_id, std::string axis, double unit, double input_val, int speed, virtual int command_axis_control(std::string dev_id, std::string axis, double unit, double input_val, int speed,
bool is_core_xy, bool supports_mqtt_axis_control, int sequence_id, bool lan_mode) bool is_core_xy, bool supports_mqtt_axis_control, int sequence_id, bool lan_mode)
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; } { return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }