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();
|
return StepInner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CommandBase::CheckToolIndex(uint8_t index) {
|
||||||
|
if (index >= config::toolCount) {
|
||||||
|
error = ErrorCode::INVALID_TOOL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace logic
|
} // namespace logic
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,10 @@ public:
|
||||||
virtual ErrorCode Error() const { return error; }
|
virtual ErrorCode Error() const { return error; }
|
||||||
|
|
||||||
protected:
|
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
|
ProgressCode state; ///< current progress state of the state machine
|
||||||
ErrorCode error; ///< current error code
|
ErrorCode error; ///< current error code
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ namespace logic {
|
||||||
CutFilament cutFilament;
|
CutFilament cutFilament;
|
||||||
|
|
||||||
void CutFilament::Reset(uint8_t param) {
|
void CutFilament::Reset(uint8_t param) {
|
||||||
|
if (!CheckToolIndex(param)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
error = ErrorCode::OK;
|
error = ErrorCode::OK;
|
||||||
cutSlot = param;
|
cutSlot = param;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ namespace logic {
|
||||||
EjectFilament ejectFilament;
|
EjectFilament ejectFilament;
|
||||||
|
|
||||||
void EjectFilament::Reset(uint8_t param) {
|
void EjectFilament::Reset(uint8_t param) {
|
||||||
|
if (!CheckToolIndex(param)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
error = ErrorCode::OK;
|
error = ErrorCode::OK;
|
||||||
slot = param;
|
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
|
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
|
MMU_NOT_RESPONDING = 0x802e, ///< internal error of the printer - communication with the MMU is not working
|
||||||
|
|
||||||
INTERNAL = 0x802f, ///< internal runtime error (software)
|
INTERNAL = 0x802f, ///< internal runtime error (software)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ namespace logic {
|
||||||
LoadFilament loadFilament;
|
LoadFilament loadFilament;
|
||||||
|
|
||||||
void LoadFilament::Reset(uint8_t param) {
|
void LoadFilament::Reset(uint8_t param) {
|
||||||
|
if (!CheckToolIndex(param)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
state = ProgressCode::EngagingIdler;
|
state = ProgressCode::EngagingIdler;
|
||||||
error = ErrorCode::OK;
|
error = ErrorCode::OK;
|
||||||
mg::globals.SetActiveSlot(param);
|
mg::globals.SetActiveSlot(param);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ namespace logic {
|
||||||
ToolChange toolChange;
|
ToolChange toolChange;
|
||||||
|
|
||||||
void ToolChange::Reset(uint8_t param) {
|
void ToolChange::Reset(uint8_t param) {
|
||||||
|
if (!CheckToolIndex(param)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (param == mg::globals.ActiveSlot())
|
if (param == mg::globals.ActiveSlot())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,3 +90,9 @@ TEST_CASE("cut_filament::cut0", "[cut_filament]") {
|
||||||
CutSlot(cutSlot);
|
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;
|
using Catch::Matchers::Equals;
|
||||||
|
|
||||||
|
#include "../helpers/helpers.ipp"
|
||||||
|
|
||||||
// temporarily disabled
|
// temporarily disabled
|
||||||
TEST_CASE("eject_filament::eject0", "[eject_filament][.]") {
|
TEST_CASE("eject_filament::eject0", "[eject_filament][.]") {
|
||||||
using namespace logic;
|
using namespace logic;
|
||||||
|
|
@ -67,6 +69,12 @@ TEST_CASE("eject_filament::eject0", "[eject_filament][.]") {
|
||||||
// the next states are still @@TODO
|
// 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:
|
// comments:
|
||||||
// The tricky part of the whole state machine are the edge cases - filament not loaded, stall guards etc.
|
// 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
|
// ... 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; }
|
CHECKED_ELSE(uf.TopLevelState() == topLevelProgress) { return false; }
|
||||||
return true;
|
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);
|
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;
|
using Catch::Matchers::Equals;
|
||||||
|
|
||||||
|
#include "../helpers/helpers.ipp"
|
||||||
|
|
||||||
void ToolChange(uint8_t fromSlot, uint8_t toSlot) {
|
void ToolChange(uint8_t fromSlot, uint8_t toSlot) {
|
||||||
ForceReinitAllAutomata();
|
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