Handle slot indices out of range correctly at top level
Besides Unload Filament, which only operates on active slot, all other top level state machines check the validity of the command's parameter. If the parameter is out of range for available slots, they return ErrorCode::INVALID_TOOL now.pull/83/head
parent
c14c79f3ac
commit
9ba116e06e
|
|
@ -76,4 +76,12 @@ bool CommandBase::Step() {
|
|||
return StepInner();
|
||||
}
|
||||
|
||||
bool CommandBase::CheckToolIndex(uint8_t index) {
|
||||
if (index >= config::toolCount) {
|
||||
error = ErrorCode::INVALID_TOOL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace logic
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@ public:
|
|||
virtual ErrorCode Error() const { return error; }
|
||||
|
||||
protected:
|
||||
/// @returns true if the slot/tool index is within specified range (0 - config::toolCount)
|
||||
/// If not, it returns false and sets the error to ErrorCode::INVALID_TOOL
|
||||
bool CheckToolIndex(uint8_t index);
|
||||
|
||||
ProgressCode state; ///< current progress state of the state machine
|
||||
ErrorCode error; ///< current error code
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ namespace logic {
|
|||
CutFilament cutFilament;
|
||||
|
||||
void CutFilament::Reset(uint8_t param) {
|
||||
if (!CheckToolIndex(param)) {
|
||||
return;
|
||||
}
|
||||
|
||||
error = ErrorCode::OK;
|
||||
cutSlot = param;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ namespace logic {
|
|||
EjectFilament ejectFilament;
|
||||
|
||||
void EjectFilament::Reset(uint8_t param) {
|
||||
if (!CheckToolIndex(param)) {
|
||||
return;
|
||||
}
|
||||
|
||||
error = ErrorCode::OK;
|
||||
slot = param;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ enum class ErrorCode : uint_fast16_t {
|
|||
|
||||
FILAMENT_ALREADY_LOADED = 0x8005, ///< cannot perform operation LoadFilament or move the selector as the filament is already loaded
|
||||
|
||||
INVALID_TOOL = 0x8006, ///< tool/slot index out of range (typically issuing T5 into an MMU with just 5 slots - valid range 0-4)
|
||||
|
||||
MMU_NOT_RESPONDING = 0x802e, ///< internal error of the printer - communication with the MMU is not working
|
||||
|
||||
INTERNAL = 0x802f, ///< internal runtime error (software)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ namespace logic {
|
|||
LoadFilament loadFilament;
|
||||
|
||||
void LoadFilament::Reset(uint8_t param) {
|
||||
if (!CheckToolIndex(param)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = ProgressCode::EngagingIdler;
|
||||
error = ErrorCode::OK;
|
||||
mg::globals.SetActiveSlot(param);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ namespace logic {
|
|||
ToolChange toolChange;
|
||||
|
||||
void ToolChange::Reset(uint8_t param) {
|
||||
if (!CheckToolIndex(param)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (param == mg::globals.ActiveSlot())
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -90,3 +90,9 @@ TEST_CASE("cut_filament::cut0", "[cut_filament]") {
|
|||
CutSlot(cutSlot);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("cut_filament::invalid_slot", "[cut_filament]") {
|
||||
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
|
||||
InvalidSlot<logic::CutFilament>(config::toolCount, cutSlot);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
using Catch::Matchers::Equals;
|
||||
|
||||
#include "../helpers/helpers.ipp"
|
||||
|
||||
// temporarily disabled
|
||||
TEST_CASE("eject_filament::eject0", "[eject_filament][.]") {
|
||||
using namespace logic;
|
||||
|
|
@ -67,6 +69,12 @@ TEST_CASE("eject_filament::eject0", "[eject_filament][.]") {
|
|||
// the next states are still @@TODO
|
||||
}
|
||||
|
||||
TEST_CASE("eject_filament::invalid_slot", "[eject_filament]") {
|
||||
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
|
||||
InvalidSlot<logic::EjectFilament>(config::toolCount, cutSlot);
|
||||
}
|
||||
}
|
||||
|
||||
// comments:
|
||||
// The tricky part of the whole state machine are the edge cases - filament not loaded, stall guards etc.
|
||||
// ... all the external influence we can get on the real HW
|
||||
|
|
|
|||
|
|
@ -51,3 +51,16 @@ bool VerifyState2(SM &uf, bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t s
|
|||
CHECKED_ELSE(uf.TopLevelState() == topLevelProgress) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename SM>
|
||||
void InvalidSlot(uint8_t invSlot, uint8_t activeSlot){
|
||||
ForceReinitAllAutomata();
|
||||
|
||||
SM logicSM;
|
||||
REQUIRE(VerifyState(logicSM, false, mi::Idler::IdleSlotIndex(), 0, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
|
||||
|
||||
EnsureActiveSlotIndex(activeSlot);
|
||||
|
||||
logicSM.Reset(invSlot);
|
||||
REQUIRE(VerifyState(logicSM, false, mi::Idler::IdleSlotIndex(), activeSlot, false, ml::off, ml::off, ErrorCode::INVALID_TOOL, ProgressCode::OK));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,3 +159,9 @@ TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_fail", "[
|
|||
FailedLoadToFindaResolveHelpFindaDidntTrigger(slot, lf);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("load_filament::invalid_slot", "[load_filament]") {
|
||||
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
|
||||
InvalidSlot<logic::LoadFilament>(config::toolCount, cutSlot);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
using Catch::Matchers::Equals;
|
||||
|
||||
#include "../helpers/helpers.ipp"
|
||||
|
||||
void ToolChange(uint8_t fromSlot, uint8_t toSlot) {
|
||||
ForceReinitAllAutomata();
|
||||
|
||||
|
|
@ -79,3 +81,9 @@ TEST_CASE("tool_change::test0", "[tool_change]") {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("tool_change::invalid_slot", "[tool_change]") {
|
||||
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
|
||||
InvalidSlot<logic::ToolChange>(config::toolCount, cutSlot);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue