[webthrottle] Added option for immediate speed control, bypassing acceleration/deceleration.

Dieser Commit ist enthalten in:
Reinder Feenstra 2025-03-22 10:53:01 +01:00
Ursprung e3ae8f309d
Commit 95808edd4c
7 geänderte Dateien mit 83 neuen und 19 gelöschten Zeilen

Datei anzeigen

@ -87,14 +87,21 @@ Throttle::Throttle(World& world, std::string_view _id)
return false; return false;
}} }}
, stop{*this, "stop", , stop{*this, "stop",
[this]() [this](bool immediate)
{ {
if(acquired()) if(acquired())
{ {
if(train) if(train)
{ {
train->emergencyStop = false; train->emergencyStop = false;
train->stop(); if(immediate)
{
train->setSpeed(*this, 0.0);
}
else
{
train->setTargetSpeed(*this, 0.0);
}
} }
if(m_decoder) if(m_decoder)
{ {
@ -106,32 +113,50 @@ Throttle::Throttle(World& world, std::string_view _id)
return false; return false;
}} }}
, faster{*this, "faster", , faster{*this, "faster",
[this]() [this](bool immediate)
{ {
if(acquired()) if(acquired())
{ {
if(train) if(train)
{ {
const double value = train->throttleSpeed.value();
const double step = getValueStep(value, train->throttleSpeed.unit());
train->emergencyStop = false; train->emergencyStop = false;
train->setTargetSpeed(*this, valueStepUp(value, step)); if(immediate)
{
const double value = train->speed.value();
const double step = getValueStep(value, train->speed.unit());
train->setSpeed(*this, valueStepUp(value, step));
}
else
{
const double value = train->throttleSpeed.value();
const double step = getValueStep(value, train->throttleSpeed.unit());
train->setTargetSpeed(*this, valueStepUp(value, step));
}
} }
return true; return true;
} }
return false; return false;
}} }}
, slower{*this, "slower", , slower{*this, "slower",
[this]() [this](bool immediate)
{ {
if(acquired()) if(acquired())
{ {
if(train) if(train)
{ {
const double value = train->throttleSpeed.value();
const double step = getValueStep(value, train->throttleSpeed.unit());
train->emergencyStop = false; train->emergencyStop = false;
train->setTargetSpeed(*this, valueStepDown(value, step)); if(immediate)
{
const double value = train->speed.value();
const double step = getValueStep(value, train->speed.unit());
train->setSpeed(*this, valueStepDown(value, step));
}
else
{
const double value = train->throttleSpeed.value();
const double step = getValueStep(value, train->throttleSpeed.unit());
train->setTargetSpeed(*this, valueStepDown(value, step));
}
} }
return true; return true;
} }

Datei anzeigen

@ -72,9 +72,9 @@ class Throttle : public IdObject
Property<float> throttle; Property<float> throttle;
ObjectProperty<Train> train; ObjectProperty<Train> train;
Method<bool()> emergencyStop; Method<bool()> emergencyStop;
Method<bool()> stop; Method<bool(bool)> stop;
Method<bool()> faster; Method<bool(bool)> faster;
Method<bool()> slower; Method<bool(bool)> slower;
Method<bool(Direction)> setDirection; Method<bool(Direction)> setDirection;
#ifndef NDEBUG #ifndef NDEBUG

Datei anzeigen

@ -301,15 +301,15 @@ void WebThrottleConnection::processMessage(const nlohmann::json& message)
} }
else if(action == "stop") else if(action == "stop")
{ {
throttle->stop(); throttle->stop(message.value("immediate", false));
} }
else if(action == "faster") else if(action == "faster")
{ {
throttle->faster(); throttle->faster(message.value("immediate", false));
} }
else if(action == "slower") else if(action == "slower")
{ {
throttle->slower(); throttle->slower(message.value("immediate", false));
} }
else if(action == "reverse" || action == "forward") else if(action == "reverse" || action == "forward")
{ {

Datei anzeigen

@ -501,6 +501,30 @@ std::error_code Train::release(Throttle& throttle)
return {}; return {};
} }
std::error_code Train::setSpeed(Throttle& throttle, double value)
{
if(m_throttle.get() != &throttle)
{
return make_error_code(TrainError::InvalidThrottle);
}
assert(active);
value = std::clamp(value, Attributes::getMin(speed), Attributes::getMax(speed));
setSpeed(convertUnit(value, speed.unit(), SpeedUnit::KiloMeterPerHour));
throttleSpeed.setValue(convertUnit(value, speed.unit(), throttleSpeed.unit()));
m_speedTimer.cancel();
m_speedState = SpeedState::Idle;
const bool currentValue = isStopped;
isStopped.setValueInternal(m_speedState == SpeedState::Idle && almostZero(speed.value()) && almostZero(throttleSpeed.value()));
if(currentValue != isStopped)
{
updateEnabled();
}
return {};
}
std::error_code Train::setTargetSpeed(Throttle& throttle, double value) std::error_code Train::setTargetSpeed(Throttle& throttle, double value)
{ {
if(m_throttle.get() != &throttle) if(m_throttle.get() != &throttle)

Datei anzeigen

@ -124,6 +124,7 @@ class Train : public IdObject
std::string throttleName() const; std::string throttleName() const;
std::error_code acquire(Throttle& throttle, bool steal = false); std::error_code acquire(Throttle& throttle, bool steal = false);
std::error_code release(Throttle& throttle); std::error_code release(Throttle& throttle);
std::error_code setSpeed(Throttle& throttle, double value);
std::error_code setTargetSpeed(Throttle& throttle, double value); std::error_code setTargetSpeed(Throttle& throttle, double value);
std::error_code setDirection(Throttle& throttle, Direction value); std::error_code setDirection(Throttle& throttle, Direction value);

Datei anzeigen

@ -35,10 +35,15 @@ function Throttle(parent, id)
e.setAttribute('action', action); e.setAttribute('action', action);
e.onclick = function () e.onclick = function ()
{ {
tm.send({ var msg = {
'throttle_id': parseInt(this.getAttribute('throttle-id')), 'throttle_id': parseInt(this.getAttribute('throttle-id')),
'action': this.getAttribute('action'), 'action': this.getAttribute('action'),
}); };
if(msg.action == 'faster' || msg.action == 'slower' || msg.action == 'stop')
{
msg.immediate = localStorage.immediateSpeedControl != 'false';
}
tm.send(msg);
}; };
return e; return e;
}; };
@ -331,6 +336,10 @@ var tm = new function ()
{ {
document.getElementById('stop_train_on_release').value = localStorage.throttleStopOnRelease; document.getElementById('stop_train_on_release').value = localStorage.throttleStopOnRelease;
} }
if(localStorage.immediateSpeedControl)
{
document.getElementById('immediate_speed_control').value = localStorage.immediateSpeedControl;
}
document.getElementById('open_settings').onclick = function () document.getElementById('open_settings').onclick = function ()
{ {
@ -348,7 +357,8 @@ var tm = new function ()
document.getElementById('close_settings').onclick = function () document.getElementById('close_settings').onclick = function ()
{ {
localStorage.throttleName = document.getElementById('throttle_name').value; localStorage.throttleName = document.getElementById('throttle_name').value;
localStorage.throttleStopOnRelease = document.getElementById('stop_train_on_release').value == 'on'; localStorage.throttleStopOnRelease = document.getElementById('stop_train_on_release').checked;
localStorage.immediateSpeedControl = document.getElementById('immediate_speed_control').checked;
document.getElementById('settings').classList.add('hide'); document.getElementById('settings').classList.add('hide');
tm.connect(); tm.connect();
}; };

Datei anzeigen

@ -24,6 +24,10 @@
<label class="flex-resize">Stop train on release</label> <label class="flex-resize">Stop train on release</label>
<input class="toggle_switch" type="checkbox" id="stop_train_on_release" checked="checked"><label class="toggle_switch" for="stop_train_on_release"></label> <input class="toggle_switch" type="checkbox" id="stop_train_on_release" checked="checked"><label class="toggle_switch" for="stop_train_on_release"></label>
</div> </div>
<div class="flex-row">
<label class="flex-resize">Immediate speed control</label>
<input class="toggle_switch" type="checkbox" id="immediate_speed_control" checked="checked"><label class="toggle_switch" for="immediate_speed_control"></label>
</div>
<div class="text-center"> <div class="text-center">
<button id="close_settings">Close</button> <button id="close_settings">Close</button>
</div> </div>