Various bug fixes and enhancements (version 0.59a)
Fixed bug whereby incoming gcodes were URI-decoded twice, which could cause problems if a comment contain a % character Fixed bug whereby M109 and M190 waited for all heaters to reach target temperature instead of just the one involved Fixed bug whereby files whose names contain an uppercase letter G could not be uploaded or deleted Increase buffer size for incoming gcodes Removed parameter to set max PWM value in M106 command. Max PWM value is now 255 as per recent RepRapPro change. Changed the code that deals with dropping characters in unimportant messages sent to USB such that we only drop characters at the end of a line (adding ".\n" to whatever we send) or drop whole lines
This commit is contained in:
parent
b7701832bc
commit
a416c367d2
11 changed files with 791 additions and 723 deletions
|
@ -24,8 +24,8 @@ Licence: GPL
|
|||
#define CONFIGURATION_H
|
||||
|
||||
#define NAME "RepRapFirmware"
|
||||
#define VERSION "0.59-dc42"
|
||||
#define DATE "2014-05-08"
|
||||
#define VERSION "0.59a-dc42"
|
||||
#define DATE "2014-05-14"
|
||||
#define LAST_AUTHOR "dc42"
|
||||
|
||||
// Other firmware that we might switch to be compatible with.
|
||||
|
|
164
GCodes.cpp
164
GCodes.cpp
|
@ -68,7 +68,6 @@ void GCodes::Init()
|
|||
dwellTime = longWait;
|
||||
limitAxes = true;
|
||||
axisIsHomed[X_AXIS] = axisIsHomed[Y_AXIS] = axisIsHomed[Z_AXIS] = false;
|
||||
fanMaxPwm = 1.0;
|
||||
coolingInverted = false;
|
||||
}
|
||||
|
||||
|
@ -96,6 +95,9 @@ void GCodes::Reset()
|
|||
cannedCycleMoveCount = 0;
|
||||
cannedCycleMoveQueued = false;
|
||||
gFeedRate = platform->MaxFeedrate(Z_AXIS); // Typically the slowest
|
||||
speedFactor = 1.0/60.0; // default is just to convert from mm/minute to mm/second
|
||||
extrusionFactor = 1.0;
|
||||
|
||||
}
|
||||
|
||||
void GCodes::doFilePrint(GCodeBuffer* gb)
|
||||
|
@ -362,7 +364,7 @@ void GCodes::LoadMoveBufferFromGCode(GCodeBuffer *gb, bool doingG92, bool applyL
|
|||
if (gb->Seen(gCodeLetters[i]))
|
||||
{
|
||||
// Doing an extruder. We need to store the relative distance for this move in moveBuffer and the resulting new position in lastPos.
|
||||
float moveArg = gb->GetFValue() * distanceScale;
|
||||
float moveArg = gb->GetFValue() * distanceScale * extrusionFactor;
|
||||
if (doingG92)
|
||||
{
|
||||
moveBuffer[i] = 0.0; // no move required
|
||||
|
@ -382,10 +384,12 @@ void GCodes::LoadMoveBufferFromGCode(GCodeBuffer *gb, bool doingG92, bool applyL
|
|||
}
|
||||
}
|
||||
|
||||
// Deal with feedrate
|
||||
// Deal with feed rate
|
||||
|
||||
if (gb->Seen(gCodeLetters[DRIVES]))
|
||||
gFeedRate = gb->GetFValue() * distanceScale * 0.016666667; // G Code feedrates are in mm/minute; we need mm/sec
|
||||
{
|
||||
gFeedRate = gb->GetFValue() * distanceScale * speedFactor;
|
||||
}
|
||||
|
||||
moveBuffer[DRIVES] = gFeedRate; // We always set it, as Move may have modified the last one.
|
||||
}
|
||||
|
@ -1456,18 +1460,38 @@ void GCodes::SetHeaterParameters(GCodeBuffer *gb, char reply[STRING_LENGTH])
|
|||
|
||||
bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
||||
{
|
||||
int code;
|
||||
// M-code parameters might contain letters T and G, e.g. in filenames.
|
||||
// I assume that G-and T-code parameters never contain the letter M.
|
||||
// Therefore we must check for an M-code first.
|
||||
if (gb->Seen('M'))
|
||||
{
|
||||
return HandleMcode(gb);
|
||||
}
|
||||
// I don't think a G-code parameter ever contains letter T, or a T-code ever contains letter G.
|
||||
// So it doesn't matter inn which order we look for them.
|
||||
if (gb->Seen('G'))
|
||||
{
|
||||
return HandleGcode(gb);
|
||||
}
|
||||
if (gb->Seen('T'))
|
||||
{
|
||||
return HandleTcode(gb);
|
||||
}
|
||||
|
||||
// An empty buffer gets discarded
|
||||
HandleReply(false, gb == serialGCode, "", 'X', 0, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GCodes::HandleGcode(GCodeBuffer* gb)
|
||||
{
|
||||
bool result = true;
|
||||
bool error = false;
|
||||
bool resend = false;
|
||||
bool seen;
|
||||
char reply[STRING_LENGTH];
|
||||
|
||||
reply[0] = 0;
|
||||
|
||||
if (gb->Seen('G'))
|
||||
{
|
||||
code = gb->GetIValue();
|
||||
int code = gb->GetIValue();
|
||||
switch (code)
|
||||
{
|
||||
case 0: // There are no rapid moves...
|
||||
|
@ -1566,13 +1590,21 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
snprintf(reply, STRING_LENGTH, "invalid G Code: %s", gb->Buffer());
|
||||
}
|
||||
if (result)
|
||||
HandleReply(error, gb == serialGCode, reply, 'G', code, resend);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (gb->Seen('M'))
|
||||
{
|
||||
code = gb->GetIValue();
|
||||
HandleReply(error, gb == serialGCode, reply, 'G', code, resend);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GCodes::HandleMcode(GCodeBuffer* gb)
|
||||
{
|
||||
bool result = true;
|
||||
bool error = false;
|
||||
bool resend = false;
|
||||
char reply[STRING_LENGTH];
|
||||
reply[0] = 0;
|
||||
|
||||
int code = gb->GetIValue();
|
||||
switch (code)
|
||||
{
|
||||
case 0: // Stop
|
||||
|
@ -1681,7 +1713,8 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
break;
|
||||
|
||||
case 92: // Set/report steps/mm for some axes
|
||||
seen = false;
|
||||
{
|
||||
bool seen = false;
|
||||
for (int8_t drive = 0; drive < DRIVES; drive++)
|
||||
{
|
||||
if (gb->Seen(gCodeLetters[drive]))
|
||||
|
@ -1697,6 +1730,7 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
(int) platform->DriveStepsPerUnit(X_AXIS), (int) platform->DriveStepsPerUnit(Y_AXIS),
|
||||
(int) platform->DriveStepsPerUnit(Z_AXIS), (int) platform->DriveStepsPerUnit(AXES)); // FIXME - needs to do multiple extruders
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 98:
|
||||
|
@ -1728,34 +1762,46 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
break;
|
||||
|
||||
case 106: // Fan on or off
|
||||
if (gb->Seen('P'))
|
||||
{
|
||||
// slic3r and Cura expect PWM values to go from 0 to 255, but we expect PWM value to go from 0.0 to 1.0.
|
||||
// So I've added a P parameter to allow the top end of the range to be set, so we can be compatible with those programs.
|
||||
fanMaxPwm = fmax(gb->GetFValue(), 1.0);
|
||||
}
|
||||
if (gb->Seen('I'))
|
||||
{
|
||||
coolingInverted = (gb->GetIValue() > 0);
|
||||
}
|
||||
if (gb->Seen('S'))
|
||||
{
|
||||
float f = gb->GetFValue();
|
||||
f = fmin(f, 255.0);
|
||||
f = fmax(f, 0.0);
|
||||
if (coolingInverted)
|
||||
{
|
||||
platform->CoolingFan(1.0 - fmax(gb->GetFValue(), 0.0)/fanMaxPwm);
|
||||
platform->CoolingFan(255.0 - f);
|
||||
}
|
||||
else
|
||||
{
|
||||
platform->CoolingFan(fmax(gb->GetFValue(), 0.0)/fanMaxPwm);
|
||||
platform->CoolingFan(f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 107: // Fan off - deprecated
|
||||
platform->CoolingFan(coolingInverted ? 1.0 : 0.0);
|
||||
platform->CoolingFan(coolingInverted ? 255.0 : 0.0);
|
||||
break;
|
||||
|
||||
// case 109 is later because it falls through to case 116
|
||||
case 109: // Set extruder temperature and wait - deprecated
|
||||
case 190: // Set bed temperature and wait - deprecated
|
||||
{
|
||||
int8_t heater = (code == 190) ? 0 : 1;
|
||||
if (gb->Seen('S'))
|
||||
{
|
||||
reprap.GetHeat()->SetActiveTemperature(heater, gb->GetFValue());
|
||||
reprap.GetHeat()->Activate(heater);
|
||||
}
|
||||
if (!AllMovesAreFinishedAndMoveBufferIsLoaded())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result = reprap.GetHeat()->HeaterAtSetTemperature(heater);
|
||||
}
|
||||
break;
|
||||
|
||||
case 110: // Set line numbers - line numbers are dealt with in the GCodeBuffer class
|
||||
break;
|
||||
|
@ -1765,7 +1811,8 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
reprap.SetDebug(gb->GetIValue());
|
||||
break;
|
||||
|
||||
case 112: // Emergency stop - acted upon in Webserver
|
||||
case 112: // Emergency stop - acted upon in Webserver, but also here in case it comes from USB etc.
|
||||
reprap.EmergencyStop();
|
||||
break;
|
||||
|
||||
case 114: // Deprecated
|
||||
|
@ -1787,15 +1834,6 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
ELECTRONICS, DATE);
|
||||
break;
|
||||
|
||||
case 109: // Set extruder temperature and wait - deprecated
|
||||
case 190: // Set bed temperature and wait - deprecated
|
||||
if (gb->Seen('S'))
|
||||
{
|
||||
uint8_t heater = (code == 190) ? 0 : 1;
|
||||
reprap.GetHeat()->SetActiveTemperature(heater, gb->GetFValue());
|
||||
reprap.GetHeat()->Activate(heater);
|
||||
}
|
||||
/* no break */
|
||||
case 116: // Wait for everything, especially set temperatures
|
||||
if (!AllMovesAreFinishedAndMoveBufferIsLoaded())
|
||||
{
|
||||
|
@ -1841,7 +1879,7 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
platform->Message(HOST_MESSAGE, "M141 - heated chamber not yet implemented\n");
|
||||
break;
|
||||
|
||||
// case 190 is earlier because it falls through to case 116
|
||||
// case 190 is with case 109 because it used the same code
|
||||
|
||||
case 201: // Set axis accelerations
|
||||
for (int8_t drive = 0; drive < DRIVES; drive++)
|
||||
|
@ -1883,7 +1921,7 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
}
|
||||
break;
|
||||
|
||||
case 210: // Set homing feedrates
|
||||
case 210: // Set homing feed rates
|
||||
for (int8_t axis = 0; axis < AXES; axis++)
|
||||
{
|
||||
if (gb->Seen(gCodeLetters[axis]))
|
||||
|
@ -1894,6 +1932,20 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
}
|
||||
break;
|
||||
|
||||
case 220: // set speed factor override percentage
|
||||
if (gb->Seen('S'))
|
||||
{
|
||||
speedFactor = gb->GetFValue()/(60 * 100.0); // include the conversion from mm/minute to mm/second
|
||||
}
|
||||
break;
|
||||
|
||||
case 221: // set extrusion factor override percentage
|
||||
if (gb->Seen('S'))
|
||||
{
|
||||
extrusionFactor = gb->GetFValue()/100.0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 301: // Set hot end PID values
|
||||
SetPidParameters(gb, 1, reply);
|
||||
break;
|
||||
|
@ -2091,24 +2143,29 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
HandleReply(error, gb == serialGCode, reply, 'M', code, resend);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (gb->Seen('T'))
|
||||
{
|
||||
code = gb->GetIValue();
|
||||
bool GCodes::HandleTcode(GCodeBuffer* gb)
|
||||
{
|
||||
bool error = false;
|
||||
char reply[STRING_LENGTH];
|
||||
reply[0] = 0;
|
||||
|
||||
int code = gb->GetIValue();
|
||||
if (code == selectedHead)
|
||||
{
|
||||
if (result)
|
||||
HandleReply(error, gb == serialGCode, reply, 'T', code, resend);
|
||||
return result;
|
||||
HandleReply(error, gb == serialGCode, reply, 'T', code, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
error = true;
|
||||
for (int8_t i = AXES; i < DRIVES; i++)
|
||||
{
|
||||
if (selectedHead == i - AXES)
|
||||
{
|
||||
reprap.GetHeat()->Standby(selectedHead + 1); // + 1 because 0 is the Bed
|
||||
}
|
||||
}
|
||||
for (int8_t i = AXES; i < DRIVES; i++)
|
||||
{
|
||||
if (code == i - AXES)
|
||||
|
@ -2120,19 +2177,12 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Invalid T Code: %s", gb->Buffer());
|
||||
|
||||
if (result)
|
||||
HandleReply(error, gb == serialGCode, reply, 'T', code, resend);
|
||||
return result;
|
||||
}
|
||||
|
||||
// An empty buffer jumps to here and gets discarded
|
||||
|
||||
if (result)
|
||||
HandleReply(error, gb == serialGCode, reply, 'X', code, resend);
|
||||
|
||||
return result;
|
||||
HandleReply(error, gb == serialGCode, reply, 'T', code, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the amount of filament extruded
|
||||
|
@ -2321,7 +2371,7 @@ const char* GCodeBuffer::GetUnprecedentedString()
|
|||
return gcodeBuffer; // Good idea?
|
||||
}
|
||||
|
||||
char* result = &gcodeBuffer[readPointer + 1];
|
||||
const char* result = &gcodeBuffer[readPointer + 1];
|
||||
readPointer = -1;
|
||||
return result;
|
||||
}
|
||||
|
|
7
GCodes.h
7
GCodes.h
|
@ -27,7 +27,6 @@ Licence: GPL
|
|||
|
||||
#define GCODE_LETTERS { 'X', 'Y', 'Z', 'E', 'F' } // The drives and feedrate in a GCode
|
||||
|
||||
|
||||
// Small class to hold an individual GCode and provide functions to allow it to be parsed
|
||||
|
||||
class GCodeBuffer
|
||||
|
@ -158,6 +157,9 @@ class GCodes
|
|||
bool DoFileCannedCycles(const char* fileName);
|
||||
bool FileCannedCyclesReturn();
|
||||
bool ActOnGcode(GCodeBuffer* gb);
|
||||
bool HandleGcode(GCodeBuffer* gb);
|
||||
bool HandleMcode(GCodeBuffer* gb);
|
||||
bool HandleTcode(GCodeBuffer* gb);
|
||||
int SetUpMove(GCodeBuffer* gb);
|
||||
bool DoDwell(GCodeBuffer *gb);
|
||||
bool DoDwellTime(float dwell);
|
||||
|
@ -232,9 +234,10 @@ class GCodes
|
|||
float longWait;
|
||||
bool limitAxes; // Don't think outside the box.
|
||||
bool axisIsHomed[3]; // these record which of the axes have been homed
|
||||
float fanMaxPwm; // the M106 S value that represents 100% fan speed
|
||||
bool waitingForMoveToComplete;
|
||||
bool coolingInverted;
|
||||
float speedFactor; // speed factor, including the conversion from mm/min to mm/sec, normally 1/60
|
||||
float extrusionFactor; // extrusion factor, normally 1.0
|
||||
};
|
||||
|
||||
//*****************************************************************************************************
|
||||
|
|
27
Heat.cpp
27
Heat.cpp
|
@ -63,31 +63,24 @@ void Heat::Diagnostics()
|
|||
platform->Message(HOST_MESSAGE, "Heat Diagnostics:\n");
|
||||
}
|
||||
|
||||
bool Heat::AllHeatersAtSetTemperatures()
|
||||
bool Heat::AllHeatersAtSetTemperatures() const
|
||||
{
|
||||
float dt;
|
||||
for(int8_t heater = 0; heater < HEATERS; heater++)
|
||||
{
|
||||
dt = GetTemperature(heater);
|
||||
if(pids[heater]->Active())
|
||||
{
|
||||
if(GetActiveTemperature(heater) < TEMPERATURE_LOW_SO_DONT_CARE)
|
||||
dt = 0.0;
|
||||
else
|
||||
dt = fabs(dt - GetActiveTemperature(heater));
|
||||
} else
|
||||
{
|
||||
if(GetStandbyTemperature(heater) < TEMPERATURE_LOW_SO_DONT_CARE)
|
||||
dt = 0.0;
|
||||
else
|
||||
dt = fabs(dt - GetStandbyTemperature(heater));
|
||||
}
|
||||
if(dt > TEMPERATURE_CLOSE_ENOUGH)
|
||||
if (!HeaterAtSetTemperature(heater))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//query an individual heater
|
||||
bool Heat::HeaterAtSetTemperature(int8_t heater) const
|
||||
{
|
||||
float dt = GetTemperature(heater);
|
||||
float target = (pids[heater]->Active()) ? GetActiveTemperature(heater) : GetStandbyTemperature(heater);
|
||||
return (target < TEMPERATURE_LOW_SO_DONT_CARE) || (fabs(dt - target) <= TEMPERATURE_CLOSE_ENOUGH);
|
||||
}
|
||||
|
||||
//******************************************************************************************************
|
||||
|
||||
PID::PID(Platform* p, int8_t h)
|
||||
|
|
47
Heat.h
47
Heat.h
|
@ -28,15 +28,15 @@ class PID
|
|||
PID(Platform* p, int8_t h);
|
||||
void Init();
|
||||
void Spin();
|
||||
void SetActiveTemperature(const float& t);
|
||||
float GetActiveTemperature();
|
||||
void SetStandbyTemperature(const float& t);
|
||||
float GetStandbyTemperature();
|
||||
void SetActiveTemperature(float t);
|
||||
float GetActiveTemperature() const;
|
||||
void SetStandbyTemperature(float t);
|
||||
float GetStandbyTemperature() const;
|
||||
void Activate();
|
||||
void Standby();
|
||||
bool Active();
|
||||
bool Active() const;
|
||||
void ResetFault();
|
||||
float GetTemperature();
|
||||
float GetTemperature() const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -61,15 +61,16 @@ class Heat
|
|||
void Spin();
|
||||
void Init();
|
||||
void Exit();
|
||||
void SetActiveTemperature(int8_t heater, const float& t);
|
||||
float GetActiveTemperature(int8_t heater);
|
||||
void SetStandbyTemperature(int8_t heater, const float& t);
|
||||
float GetStandbyTemperature(int8_t heater);
|
||||
void SetActiveTemperature(int8_t heater, float t);
|
||||
float GetActiveTemperature(int8_t heater) const;
|
||||
void SetStandbyTemperature(int8_t heater, float t);
|
||||
float GetStandbyTemperature(int8_t heater) const;
|
||||
void Activate(int8_t heater);
|
||||
void Standby(int8_t heater);
|
||||
float GetTemperature(int8_t heater);
|
||||
float GetTemperature(int8_t heater) const;
|
||||
void ResetFault(int8_t heater);
|
||||
bool AllHeatersAtSetTemperatures();
|
||||
bool AllHeatersAtSetTemperatures() const;
|
||||
bool HeaterAtSetTemperature(int8_t heater) const; // Is a specific heater at temperature within tolerance?
|
||||
void Diagnostics();
|
||||
|
||||
private:
|
||||
|
@ -85,32 +86,32 @@ class Heat
|
|||
|
||||
//***********************************************************************************************************
|
||||
|
||||
inline bool PID::Active()
|
||||
inline bool PID::Active() const
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
inline void PID::SetActiveTemperature(const float& t)
|
||||
inline void PID::SetActiveTemperature(float t)
|
||||
{
|
||||
activeTemperature = t;
|
||||
}
|
||||
|
||||
inline float PID::GetActiveTemperature()
|
||||
inline float PID::GetActiveTemperature() const
|
||||
{
|
||||
return activeTemperature;
|
||||
}
|
||||
|
||||
inline void PID::SetStandbyTemperature(const float& t)
|
||||
inline void PID::SetStandbyTemperature(float t)
|
||||
{
|
||||
standbyTemperature = t;
|
||||
}
|
||||
|
||||
inline float PID::GetStandbyTemperature()
|
||||
inline float PID::GetStandbyTemperature() const
|
||||
{
|
||||
return standbyTemperature;
|
||||
}
|
||||
|
||||
inline float PID::GetTemperature()
|
||||
inline float PID::GetTemperature() const
|
||||
{
|
||||
return temperature;
|
||||
}
|
||||
|
@ -132,7 +133,7 @@ inline void PID::ResetFault()
|
|||
}
|
||||
|
||||
|
||||
inline void Heat::SetActiveTemperature(int8_t heater, const float& t)
|
||||
inline void Heat::SetActiveTemperature(int8_t heater, float t)
|
||||
{
|
||||
if (heater >= 0 && heater < HEATERS)
|
||||
{
|
||||
|
@ -140,12 +141,12 @@ inline void Heat::SetActiveTemperature(int8_t heater, const float& t)
|
|||
}
|
||||
}
|
||||
|
||||
inline float Heat::GetActiveTemperature(int8_t heater)
|
||||
inline float Heat::GetActiveTemperature(int8_t heater) const
|
||||
{
|
||||
return (heater >= 0 && heater < HEATERS) ? pids[heater]->GetActiveTemperature() : ABS_ZERO;
|
||||
}
|
||||
|
||||
inline void Heat::SetStandbyTemperature(int8_t heater, const float& t)
|
||||
inline void Heat::SetStandbyTemperature(int8_t heater, float t)
|
||||
{
|
||||
if (heater >= 0 && heater < HEATERS)
|
||||
{
|
||||
|
@ -153,12 +154,12 @@ inline void Heat::SetStandbyTemperature(int8_t heater, const float& t)
|
|||
}
|
||||
}
|
||||
|
||||
inline float Heat::GetStandbyTemperature(int8_t heater)
|
||||
inline float Heat::GetStandbyTemperature(int8_t heater) const
|
||||
{
|
||||
return (heater >= 0 && heater < HEATERS) ? pids[heater]->GetStandbyTemperature() : ABS_ZERO;
|
||||
}
|
||||
|
||||
inline float Heat::GetTemperature(int8_t heater)
|
||||
inline float Heat::GetTemperature(int8_t heater) const
|
||||
{
|
||||
return (heater >= 0 && heater < HEATERS) ? pids[heater]->GetTemperature() : ABS_ZERO;
|
||||
}
|
||||
|
|
93
Platform.cpp
93
Platform.cpp
|
@ -988,12 +988,14 @@ void Platform::SetMotorCurrent(byte drive, float current)
|
|||
mcp.setVolatileWiper(potWipes[drive], pot);
|
||||
}
|
||||
|
||||
//Changed to be compatible with existing gcode norms
|
||||
// M106 S0 = fully off M106 S255 = fully on
|
||||
void Platform::CoolingFan(float speed)
|
||||
{
|
||||
if(coolingFanPin > 0)
|
||||
{
|
||||
// The cooling fan output pin gets inverted if HEAT_ON == 0
|
||||
analogWriteNonDue(coolingFanPin, (uint32_t)( ((HEAT_ON == 0) ? (1.0 - speed) : speed) * 255.0));
|
||||
analogWriteNonDue(coolingFanPin, (uint32_t)( (HEAT_ON == 0) ? (255.0 - speed) : speed));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1014,25 +1016,6 @@ void Platform::SetInterrupt(float s) // Seconds
|
|||
NVIC_EnableIRQ(TC3_IRQn);
|
||||
}
|
||||
|
||||
int8_t Line::Status() const
|
||||
{
|
||||
// if(alternateInput != NULL)
|
||||
// return alternateInput->Status();
|
||||
return inputNumChars == 0 ? nothing : byteAvailable;
|
||||
}
|
||||
|
||||
int Line::Read(char& b)
|
||||
{
|
||||
// if(alternateInput != NULL)
|
||||
// return alternateInput->Read(b);
|
||||
|
||||
if (inputNumChars == 0) return 0;
|
||||
b = inBuffer[inputGetIndex];
|
||||
inputGetIndex = (inputGetIndex + 1) % lineInBufsize;
|
||||
--inputNumChars;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
||||
FileStore* Platform::GetFileStore(const char* directory, const char* fileName, bool write)
|
||||
|
@ -1550,12 +1533,32 @@ Line::Line()
|
|||
{
|
||||
}
|
||||
|
||||
int8_t Line::Status() const
|
||||
{
|
||||
// if(alternateInput != NULL)
|
||||
// return alternateInput->Status();
|
||||
return inputNumChars == 0 ? nothing : byteAvailable;
|
||||
}
|
||||
|
||||
int Line::Read(char& b)
|
||||
{
|
||||
// if(alternateInput != NULL)
|
||||
// return alternateInput->Read(b);
|
||||
|
||||
if (inputNumChars == 0) return 0;
|
||||
b = inBuffer[inputGetIndex];
|
||||
inputGetIndex = (inputGetIndex + 1) % lineInBufsize;
|
||||
--inputNumChars;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Line::Init()
|
||||
{
|
||||
inputGetIndex = 0;
|
||||
inputNumChars = 0;
|
||||
outputGetIndex = 0;
|
||||
outputNumChars = 0;
|
||||
ignoringOutputLine = false;
|
||||
SerialUSB.begin(BAUD_RATE);
|
||||
inUsbWrite = false;
|
||||
}
|
||||
|
@ -1583,25 +1586,69 @@ void Line::Spin()
|
|||
TryFlushOutput();
|
||||
}
|
||||
|
||||
// Write a character to USB.
|
||||
// If 'block' is true then we don't return until we have either written it to the USB port of put it in the buffer.
|
||||
// Otherwise, if the buffer is full then we append ".\n" to the end of it, return immediately and ignore the rest
|
||||
// of the data we are asked to print until we get a new line.
|
||||
void Line::Write(char b, bool block)
|
||||
{
|
||||
do
|
||||
if (block)
|
||||
{
|
||||
// We failed to print an unimportant message that (unusually) didn't finish in a newline
|
||||
ignoringOutputLine = false;
|
||||
}
|
||||
|
||||
if (ignoringOutputLine)
|
||||
{
|
||||
// We have already failed to write some characters of this message line, so don't write any of it.
|
||||
// But try to start sending again after this line finishes.
|
||||
if (b == '\n')
|
||||
{
|
||||
ignoringOutputLine = false;
|
||||
}
|
||||
TryFlushOutput(); // this may help free things up
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
TryFlushOutput();
|
||||
if (outputNumChars == 0 && SerialUSB.canWrite() != 0)
|
||||
{
|
||||
// We can write the character directly into the USB output buffer
|
||||
++inUsbWrite;
|
||||
SerialUSB.write(b);
|
||||
--inUsbWrite;
|
||||
break;
|
||||
}
|
||||
else if (outputNumChars < lineOutBufSize)
|
||||
else if ( outputNumChars + 2 < lineOutBufSize // save 2 spaces in the output buffer
|
||||
|| (outputNumChars < lineOutBufSize && (block || b == '\n')) //...unless doing blocking output or writing newline
|
||||
)
|
||||
{
|
||||
outBuffer[(outputGetIndex + outputNumChars) % lineOutBufSize] = b;
|
||||
++outputNumChars;
|
||||
break;
|
||||
}
|
||||
} while (block);
|
||||
else if (!block)
|
||||
{
|
||||
if (outputNumChars + 2 == lineOutBufSize)
|
||||
{
|
||||
// We still have our 2 free characters, so append ".\n" to the line to indicate it was incomplete
|
||||
outBuffer[(outputGetIndex + outputNumChars) % lineOutBufSize] = '.';
|
||||
++outputNumChars;
|
||||
outBuffer[(outputGetIndex + outputNumChars) % lineOutBufSize] = '\n';
|
||||
++outputNumChars;
|
||||
}
|
||||
else
|
||||
{
|
||||
// As we don't have 2 spare characters in the buffer, we can't have written any of the current line.
|
||||
// So ignore the whole line.
|
||||
}
|
||||
ignoringOutputLine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// else discard the character
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ const unsigned int numZProbeReadingsAveraged = 8; // we average this number of r
|
|||
#define MAX_FEEDRATES {50.0, 50.0, 3.0, 16.0} // mm/sec
|
||||
#define ACCELERATIONS {800.0, 800.0, 10.0, 250.0} // mm/sec^2
|
||||
#define DRIVE_STEPS_PER_UNIT {87.4890, 87.4890, 4000.0, 420.0}
|
||||
#define INSTANT_DVS {10.0, 10.0, 0.2, 2.0} // (mm/sec)
|
||||
#define INSTANT_DVS {10.0, 10.0, 0.2, 2.0} // (mm/sec) these are also the minimum feed rates which is why I (dc42) decreased X/Y from 15 to 10
|
||||
|
||||
// AXES
|
||||
|
||||
|
@ -195,10 +195,8 @@ const unsigned int adDisconnectedVirtual = adDisconnectedReal << adOversampleBit
|
|||
#define FILE_LIST_BRACKET '"'
|
||||
#define FILE_LIST_LENGTH (1000) // Maximum length of file list - can't make it much longer unless we also make jsonResponse longer
|
||||
|
||||
#define FLASH_LED 'F' // Type byte of a message that is to flash an LED; the next two bytes define
|
||||
// the frequency and M/S ratio.
|
||||
#define DISPLAY_MESSAGE 'L' // Type byte of a message that is to appear on a local display; the L is
|
||||
// not displayed; \f and \n should be supported.
|
||||
#define FLASH_LED 'F' // Type byte of a message that is to flash an LED; the next two bytes define the frequency and M/S ratio.
|
||||
#define DISPLAY_MESSAGE 'L' // Type byte of a message that is to appear on a local display; the L is not displayed; \f and \n should be supported.
|
||||
#define HOST_MESSAGE 'H' // Type byte of a message that is to be sent to the host; the H is not sent.
|
||||
#define DEBUG_MESSAGE 'D' // Type byte of a message that is to be sent for debugging; the D is not sent.
|
||||
|
||||
|
@ -295,6 +293,7 @@ private:
|
|||
uint16_t outputNumChars;
|
||||
|
||||
uint8_t inUsbWrite;
|
||||
bool ignoringOutputLine;
|
||||
};
|
||||
|
||||
class MassStorage
|
||||
|
|
|
@ -365,7 +365,7 @@ void debugPrintf(const char* fmt, ...)
|
|||
va_start(p, fmt);
|
||||
vsnprintf(scratchString, ARRAY_SIZE(scratchString), fmt, p);
|
||||
va_end(p);
|
||||
scratchString[ARRAY_SIZE(scratchString) - 1] = 0;
|
||||
scratchString[ARRAY_UPB(scratchString)] = 0;
|
||||
reprap.GetPlatform()->Message(DEBUG_MESSAGE, scratchString);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@ int StringContains(const char* string, const char* match);
|
|||
|
||||
// Macro to give us the number of elements in an array
|
||||
#define ARRAY_SIZE(_x) (sizeof(_x)/sizeof(_x[0]))
|
||||
// Macro to give us the highest valid index into an array i.e. one less than the size
|
||||
#define ARRAY_UPB(_x) (ARRAY_SIZE(_x) - 1)
|
||||
|
||||
extern char scratchString[];
|
||||
|
||||
|
|
143
Webserver.cpp
143
Webserver.cpp
|
@ -82,7 +82,7 @@ byte Webserver::ReadGCode()
|
|||
}
|
||||
|
||||
// Process a received string of gcodes
|
||||
void Webserver::LoadGcodeBuffer(const char* gc, bool convertWeb)
|
||||
void Webserver::LoadGcodeBuffer(const char* gc)
|
||||
{
|
||||
char gcodeTempBuf[GCODE_LENGTH];
|
||||
uint16_t gtp = 0;
|
||||
|
@ -97,40 +97,6 @@ void Webserver::LoadGcodeBuffer(const char* gc, bool convertWeb)
|
|||
return;
|
||||
}
|
||||
|
||||
if (c == '+' && convertWeb)
|
||||
{
|
||||
c = ' ';
|
||||
}
|
||||
else if (c == '%' && convertWeb)
|
||||
{
|
||||
c = *gc++;
|
||||
if (c != 0)
|
||||
{
|
||||
unsigned char uc;
|
||||
if (isalpha(c))
|
||||
{
|
||||
uc = 16 * (c - 'A' + 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
uc = 16 * (c - '0');
|
||||
}
|
||||
c = *gc++;
|
||||
if (c != 0)
|
||||
{
|
||||
if (isalpha(c))
|
||||
{
|
||||
uc += c - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
uc += c - '0';
|
||||
}
|
||||
c = uc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
gcodeTempBuf[gtp] = 0;
|
||||
|
@ -145,7 +111,7 @@ void Webserver::LoadGcodeBuffer(const char* gc, bool convertWeb)
|
|||
inComment = true;
|
||||
}
|
||||
|
||||
if (gtp == ARRAY_SIZE(gcodeTempBuf) - 1)
|
||||
if (gtp == ARRAY_UPB(gcodeTempBuf))
|
||||
{
|
||||
// gcode is too long, we haven't room for another character and a null
|
||||
if (c != ' ' && !inComment)
|
||||
|
@ -219,7 +185,7 @@ void Webserver::ProcessGcode(const char* gc)
|
|||
{
|
||||
char c;
|
||||
size_t i = 0;
|
||||
while (i < STRING_LENGTH && configFile->Read(c))
|
||||
while (i < ARRAY_UPB(gcodeReply) && configFile->Read(c))
|
||||
{
|
||||
gcodeReply[i++] = c;
|
||||
}
|
||||
|
@ -360,7 +326,7 @@ void Webserver::JsonReport(bool ok, const char* request)
|
|||
{
|
||||
if (ok)
|
||||
{
|
||||
jsonResponse[STRING_LENGTH] = 0;
|
||||
jsonResponse[ARRAY_UPB(jsonResponse)] = 0;
|
||||
if (reprap.Debug())
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "JSON response: ");
|
||||
|
@ -395,8 +361,8 @@ void Webserver::GetJsonResponse(const char* request)
|
|||
|
||||
if (StringStartsWith(request, "gcode") && StringStartsWith(clientQualifier, "gcode="))
|
||||
{
|
||||
LoadGcodeBuffer(&clientQualifier[6], true);
|
||||
snprintf(jsonResponse, STRING_LENGTH, "{\"buff\":%u}", GetReportedGcodeBufferSpace());
|
||||
LoadGcodeBuffer(&clientQualifier[6]);
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"buff\":%u}", GetReportedGcodeBufferSpace());
|
||||
JsonReport(true, request);
|
||||
return;
|
||||
}
|
||||
|
@ -404,7 +370,7 @@ void Webserver::GetJsonResponse(const char* request)
|
|||
if (StringStartsWith(request, "files"))
|
||||
{
|
||||
const char* fileList = platform->GetMassStorage()->FileList(platform->GetGCodeDir(), false);
|
||||
snprintf(jsonResponse, STRING_LENGTH, "{\"files\":[%s]}", fileList);
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"files\":[%s]}", fileList);
|
||||
JsonReport(true, request);
|
||||
return;
|
||||
}
|
||||
|
@ -416,11 +382,11 @@ void Webserver::GetJsonResponse(const char* request)
|
|||
bool found = GetFileInfo(clientQualifier + 5, length, height, filament);
|
||||
if (found)
|
||||
{
|
||||
snprintf(jsonResponse, STRING_LENGTH, "{\"size\":%lu,\"height\":\"%.2f\",\"filament\":\"%.1f\"}", length, height, filament);
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"size\":%lu,\"height\":\"%.2f\",\"filament\":\"%.1f\"}", length, height, filament);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(jsonResponse, STRING_LENGTH, "{}");
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{}");
|
||||
}
|
||||
JsonReport(true, request);
|
||||
return;
|
||||
|
@ -428,7 +394,7 @@ void Webserver::GetJsonResponse(const char* request)
|
|||
|
||||
if (StringStartsWith(request, "name"))
|
||||
{
|
||||
snprintf(jsonResponse, STRING_LENGTH, "{\"myName\":\"%s\"}", myName);
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"myName\":\"%s\"}", myName);
|
||||
JsonReport(true, request);
|
||||
return;
|
||||
}
|
||||
|
@ -436,21 +402,21 @@ void Webserver::GetJsonResponse(const char* request)
|
|||
if (StringStartsWith(request, "password"))
|
||||
{
|
||||
CheckPassword();
|
||||
snprintf(jsonResponse, STRING_LENGTH, "{\"password\":\"%s\"}", (gotPassword) ? "right" : "wrong");
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"password\":\"%s\"}", (gotPassword) ? "right" : "wrong");
|
||||
JsonReport(true, request);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringStartsWith(request, "axes"))
|
||||
{
|
||||
strncpy(jsonResponse, "{\"axes\":", STRING_LENGTH);
|
||||
strncpy(jsonResponse, "{\"axes\":", ARRAY_UPB(jsonResponse));
|
||||
char ch = '[';
|
||||
for (int8_t drive = 0; drive < AXES; drive++)
|
||||
{
|
||||
sncatf(jsonResponse, STRING_LENGTH, "%c\"%.1f\"", ch, platform->AxisLength(drive));
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c\"%.1f\"", ch, platform->AxisLength(drive));
|
||||
ch = ',';
|
||||
}
|
||||
strncat(jsonResponse, "]}", STRING_LENGTH);
|
||||
strncat(jsonResponse, "]}", ARRAY_UPB(jsonResponse));
|
||||
JsonReport(true, request);
|
||||
return;
|
||||
}
|
||||
|
@ -467,36 +433,36 @@ void Webserver::GetStatusResponse(uint8_t type)
|
|||
// New-style status request
|
||||
// Send the printing/idle status
|
||||
char ch = (reprap.IsStopped()) ? 'S' : (gc->PrintingAFile()) ? 'P' : 'I';
|
||||
snprintf(jsonResponse, STRING_LENGTH, "{\"status\":\"%c\",\"heaters\":", ch);
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"status\":\"%c\",\"heaters\":", ch);
|
||||
|
||||
// Send the heater temperatures
|
||||
ch = '[';
|
||||
for (int8_t heater = 0; heater < HEATERS; heater++)
|
||||
{
|
||||
sncatf(jsonResponse, STRING_LENGTH, "%c\"%.1f\"", ch, reprap.GetHeat()->GetTemperature(heater));
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c\"%.1f\"", ch, reprap.GetHeat()->GetTemperature(heater));
|
||||
ch = ',';
|
||||
}
|
||||
|
||||
// Send XYZ and extruder positions
|
||||
float liveCoordinates[DRIVES + 1];
|
||||
reprap.GetMove()->LiveCoordinates(liveCoordinates);
|
||||
strncat(jsonResponse, "],\"pos\":", STRING_LENGTH); // announce the XYZ position
|
||||
strncat(jsonResponse, "],\"pos\":", ARRAY_UPB(jsonResponse)); // announce the XYZ position
|
||||
ch = '[';
|
||||
// We currently provide the extruder 0 value here as well as XYZ. This is only expected by V0.69 and V0.70 of the web interface so it can be removed soon.
|
||||
for (int8_t drive = 0; drive < AXES + 1; drive++)
|
||||
//for (int8_t drive = 0; drive < AXES; drive++)
|
||||
{
|
||||
sncatf(jsonResponse, STRING_LENGTH, "%c\"%.2f\"", ch, liveCoordinates[drive]);
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c\"%.2f\"", ch, liveCoordinates[drive]);
|
||||
ch = ',';
|
||||
}
|
||||
sncatf(jsonResponse, STRING_LENGTH, "],\"extr\":"); // announce the extruder positions
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "],\"extr\":"); // announce the extruder positions
|
||||
ch = '[';
|
||||
for (int8_t drive = AXES; drive < DRIVES; drive++) // loop through extruders
|
||||
{
|
||||
sncatf(jsonResponse, STRING_LENGTH, "%c\"%.3f\"", ch, gc->GetExtruderPosition(drive - AXES));
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c\"%.3f\"", ch, gc->GetExtruderPosition(drive - AXES));
|
||||
ch = ',';
|
||||
}
|
||||
strncat(jsonResponse, "]", STRING_LENGTH);
|
||||
strncat(jsonResponse, "]", ARRAY_UPB(jsonResponse));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -504,10 +470,10 @@ void Webserver::GetStatusResponse(uint8_t type)
|
|||
// These are all returned in a single vector called "poll".
|
||||
// This is a poor choice of format because we can't easily tell which is which unless we already know the number of heaters and extruders.
|
||||
char c = (gc->PrintingAFile()) ? 'P' : 'I';
|
||||
snprintf(jsonResponse, STRING_LENGTH, "{\"poll\":[\"%c\",", c); // Printing
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"poll\":[\"%c\",", c); // Printing
|
||||
for (int8_t heater = 0; heater < HEATERS; heater++)
|
||||
{
|
||||
sncatf(jsonResponse, STRING_LENGTH, "\"%.1f\",", reprap.GetHeat()->GetTemperature(heater));
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "\"%.1f\",", reprap.GetHeat()->GetTemperature(heater));
|
||||
}
|
||||
// Send XYZ and extruder positions
|
||||
float liveCoordinates[DRIVES + 1];
|
||||
|
@ -515,7 +481,7 @@ void Webserver::GetStatusResponse(uint8_t type)
|
|||
for (int8_t drive = 0; drive < DRIVES; drive++) // loop through extruders
|
||||
{
|
||||
char ch = (drive == DRIVES - 1) ? ']' : ','; // append ] to the last one but , to the others
|
||||
sncatf(jsonResponse, STRING_LENGTH, "\"%.2f\"%c", liveCoordinates[drive], ch);
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "\"%.2f\"%c", liveCoordinates[drive], ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,43 +491,43 @@ void Webserver::GetStatusResponse(uint8_t type)
|
|||
switch (platform->GetZProbeSecondaryValues(v1, v2))
|
||||
{
|
||||
case 1:
|
||||
sncatf(jsonResponse, STRING_LENGTH, ",\"probe\":\"%d (%d)\"", v0, v1);
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), ",\"probe\":\"%d (%d)\"", v0, v1);
|
||||
break;
|
||||
case 2:
|
||||
sncatf(jsonResponse, STRING_LENGTH, ",\"probe\":\"%d (%d, %d)\"", v0, v1, v2);
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), ",\"probe\":\"%d (%d, %d)\"", v0, v1, v2);
|
||||
break;
|
||||
default:
|
||||
sncatf(jsonResponse, STRING_LENGTH, ",\"probe\":\"%d\"", v0);
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), ",\"probe\":\"%d\"", v0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Send the amount of buffer space available for gcodes
|
||||
sncatf(jsonResponse, STRING_LENGTH, ",\"buff\":%u", GetReportedGcodeBufferSpace());
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), ",\"buff\":%u", GetReportedGcodeBufferSpace());
|
||||
|
||||
// Send the home state. To keep the messages short, we send 1 for homed and 0 for not homed, instead of true and false.
|
||||
if (type != 0)
|
||||
{
|
||||
sncatf(jsonResponse, STRING_LENGTH, ",\"homed\":[%d,%d,%d]",
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), ",\"homed\":[%d,%d,%d]",
|
||||
(gc->GetAxisIsHomed(0)) ? 1 : 0,
|
||||
(gc->GetAxisIsHomed(1)) ? 1 : 0,
|
||||
(gc->GetAxisIsHomed(2)) ? 1 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
sncatf(jsonResponse, STRING_LENGTH, ",\"hx\":%d,\"hy\":%d,\"hz\":%d",
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), ",\"hx\":%d,\"hy\":%d,\"hz\":%d",
|
||||
(gc->GetAxisIsHomed(0)) ? 1 : 0,
|
||||
(gc->GetAxisIsHomed(1)) ? 1 : 0,
|
||||
(gc->GetAxisIsHomed(2)) ? 1 : 0);
|
||||
}
|
||||
|
||||
// Send the response sequence number
|
||||
sncatf(jsonResponse, STRING_LENGTH, ",\"seq\":%u", (unsigned int) seq);
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), ",\"seq\":%u", (unsigned int) seq);
|
||||
|
||||
// Send the response to the last command. Do this last because it is long and may need to be truncated.
|
||||
strncat(jsonResponse, ",\"resp\":\"", STRING_LENGTH);
|
||||
size_t jp = strnlen(jsonResponse, STRING_LENGTH);
|
||||
strncat(jsonResponse, ",\"resp\":\"", ARRAY_UPB(jsonResponse));
|
||||
size_t jp = strnlen(jsonResponse, ARRAY_UPB(jsonResponse));
|
||||
const char *p = gcodeReply;
|
||||
while (*p != 0 && jp < STRING_LENGTH - 2) // leave room for the final '"}'
|
||||
while (*p != 0 && jp < ARRAY_SIZE(jsonResponse) - 3) // leave room for the final '"}\0'
|
||||
{
|
||||
char c = *p++;
|
||||
char esc;
|
||||
|
@ -588,7 +554,7 @@ void Webserver::GetStatusResponse(uint8_t type)
|
|||
}
|
||||
if (esc)
|
||||
{
|
||||
if (jp == STRING_LENGTH - 3)
|
||||
if (jp == ARRAY_SIZE(jsonResponse) - 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -601,7 +567,7 @@ void Webserver::GetStatusResponse(uint8_t type)
|
|||
}
|
||||
}
|
||||
jsonResponse[jp] = 0;
|
||||
strncat(jsonResponse, "\"}", STRING_LENGTH);
|
||||
strncat(jsonResponse, "\"}", ARRAY_UPB(jsonResponse));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -629,8 +595,8 @@ void Webserver::ParseGetPost()
|
|||
platform->Message(HOST_MESSAGE, "\n");
|
||||
}
|
||||
|
||||
int i = 5;
|
||||
int j = 0;
|
||||
size_t i = 5;
|
||||
size_t j = 0;
|
||||
clientRequest[j] = 0;
|
||||
clientQualifier[0] = 0;
|
||||
while (clientLine[i] != ' ' && clientLine[i] != '?')
|
||||
|
@ -644,13 +610,17 @@ void Webserver::ParseGetPost()
|
|||
{
|
||||
i++;
|
||||
j = 0;
|
||||
for(;;)
|
||||
while(j < ARRAY_UPB(clientQualifier))
|
||||
{
|
||||
char c = clientLine[i++];
|
||||
if (c == ' ')
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (c == '+')
|
||||
{
|
||||
clientQualifier[j++] = ' ';
|
||||
}
|
||||
else if (c == '%' && isalnum(clientLine[i]) && isalnum(clientLine[i + 1]))
|
||||
{
|
||||
c = clientLine[i++];
|
||||
|
@ -686,7 +656,7 @@ void Webserver::ParseClientLine()
|
|||
postSeen = false;
|
||||
getSeen = true;
|
||||
if (!clientRequest[0])
|
||||
strncpy(clientRequest, INDEX_PAGE, STRING_LENGTH);
|
||||
strncpy(clientRequest, INDEX_PAGE, ARRAY_SIZE(clientRequest));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -698,7 +668,7 @@ void Webserver::ParseClientLine()
|
|||
getSeen = false;
|
||||
if (!clientRequest[0])
|
||||
{
|
||||
strncpy(clientRequest, INDEX_PAGE, STRING_LENGTH);
|
||||
strncpy(clientRequest, INDEX_PAGE, ARRAY_SIZE(clientRequest));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -707,15 +677,15 @@ void Webserver::ParseClientLine()
|
|||
|
||||
if (postSeen && ((bnd = StringContains(clientLine, "boundary=")) >= 0))
|
||||
{
|
||||
if (strlen(&clientLine[bnd]) >= POST_LENGTH - 4)
|
||||
if (strlen(&clientLine[bnd]) >= ARRAY_SIZE(postBoundary) - 4)
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "Post boundary buffer overflow.\n");
|
||||
return;
|
||||
}
|
||||
postBoundary[0] = '-';
|
||||
postBoundary[1] = '-';
|
||||
strncpy(&postBoundary[2], &clientLine[bnd], POST_LENGTH - 3);
|
||||
strncat(postBoundary, "--", POST_LENGTH);
|
||||
strncpy(&postBoundary[2], &clientLine[bnd], ARRAY_SIZE(postBoundary) - 3);
|
||||
strncat(postBoundary, "--", ARRAY_SIZE(postBoundary));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -731,10 +701,11 @@ void Webserver::ParseClientLine()
|
|||
while (clientLine[bnd] && clientLine[bnd] != '"')
|
||||
{
|
||||
postFileName[i++] = clientLine[bnd++];
|
||||
if (i >= POST_LENGTH)
|
||||
if (i >= ARRAY_SIZE(postFileName))
|
||||
{
|
||||
i = 0;
|
||||
platform->Message(HOST_MESSAGE, "Post filename buffer overflow.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
postFileName[i] = 0;
|
||||
|
@ -805,11 +776,11 @@ bool Webserver::CharFromClient(char c)
|
|||
clientLineIsBlank = false;
|
||||
clientLine[clientLinePointer] = c;
|
||||
clientLinePointer++;
|
||||
if (clientLinePointer >= STRING_LENGTH)
|
||||
if (clientLinePointer + 2 >= ARRAY_SIZE(clientLine))
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "Client read buffer overflow. Data:\n");
|
||||
clientLine[STRING_LENGTH] = '\n'; // note that clientLine is now STRING_LENGTH+2 characters long to make room for these
|
||||
clientLine[STRING_LENGTH + 1] = 0;
|
||||
clientLine[ARRAY_SIZE(clientLine) - 2] = '\n';
|
||||
clientLine[ARRAY_SIZE(clientLine) - 1] = 0;
|
||||
platform->Message(HOST_MESSAGE, clientLine);
|
||||
|
||||
reprap.GetNetwork()->SendAndClose(NULL); // close the connection
|
||||
|
@ -942,20 +913,20 @@ void Webserver::HandleReply(const char *s, bool error)
|
|||
if (error)
|
||||
{
|
||||
strcpy(gcodeReply, "Error: ");
|
||||
strncat(gcodeReply, s, STRING_LENGTH);
|
||||
strncat(gcodeReply, s, ARRAY_UPB(gcodeReply));
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(gcodeReply, s, STRING_LENGTH);
|
||||
strncpy(gcodeReply, s, ARRAY_UPB(gcodeReply));
|
||||
}
|
||||
gcodeReply[STRING_LENGTH] = 0; // array is dimensioned to STRING_LENGTH+1
|
||||
gcodeReply[ARRAY_UPB(gcodeReply)] = 0;
|
||||
}
|
||||
++seq;
|
||||
}
|
||||
|
||||
void Webserver::AppendReply(const char *s)
|
||||
{
|
||||
strncat(gcodeReply, s, STRING_LENGTH);
|
||||
strncat(gcodeReply, s, ARRAY_UPB(gcodeReply));
|
||||
}
|
||||
|
||||
// Get the actual amount of gcode buffer space we have
|
||||
|
|
20
Webserver.h
20
Webserver.h
|
@ -33,11 +33,13 @@ Licence: GPL
|
|||
|
||||
#define KO_START "rr_"
|
||||
#define KO_FIRST 3
|
||||
#define POST_LENGTH (1300) // max amount of POST data we can accept
|
||||
|
||||
const unsigned int postLength = 1400; // max amount of POST data we can accept
|
||||
const unsigned int webInputLength = 1400; // max size of web interface requests and related stuff
|
||||
const unsigned int gcodeBufLength = 2048; // size of our gcode ring buffer, ideally a power of 2
|
||||
const unsigned int minReportedFreeBuf = 100; // the minimum free buffer we report if not zero
|
||||
const unsigned int maxReportedFreeBuf = 900; // the max we own up to having free, to avoid overlong messages
|
||||
const unsigned int maxReportedFreeBuf = 1024; // the max we own up to having free, to avoid overlong messages
|
||||
const unsigned int jsopnReplyLength = 1200; // size of buffer used to hold JSON reply
|
||||
|
||||
class Webserver
|
||||
{
|
||||
|
@ -62,7 +64,7 @@ class Webserver
|
|||
void SendFile(const char* nameOfFileToSend);
|
||||
void ParseQualifier();
|
||||
void CheckPassword();
|
||||
void LoadGcodeBuffer(const char* gc, bool convertWeb);
|
||||
void LoadGcodeBuffer(const char* gc);
|
||||
bool PrintHeadString();
|
||||
bool PrintLinkTable();
|
||||
void GetGCodeList();
|
||||
|
@ -86,18 +88,18 @@ class Webserver
|
|||
float lastTime;
|
||||
float longWait;
|
||||
bool receivingPost;
|
||||
char postBoundary[POST_LENGTH];
|
||||
char postBoundary[postLength];
|
||||
int boundaryCount;
|
||||
char postFileName[POST_LENGTH];
|
||||
char postFileName[postLength];
|
||||
FileStore* postFile;
|
||||
bool postSeen;
|
||||
bool getSeen;
|
||||
bool clientLineIsBlank;
|
||||
|
||||
char clientLine[STRING_LENGTH+2]; // 2 chars extra so we can append \n\0
|
||||
char clientRequest[STRING_LENGTH];
|
||||
char clientQualifier[STRING_LENGTH];
|
||||
char jsonResponse[STRING_LENGTH+1];
|
||||
char clientLine[webInputLength];
|
||||
char clientRequest[webInputLength];
|
||||
char clientQualifier[webInputLength];
|
||||
char jsonResponse[jsopnReplyLength];
|
||||
char gcodeBuffer[gcodeBufLength];
|
||||
unsigned int gcodeReadIndex, gcodeWriteIndex; // head and tail indices into gcodeBuffer
|
||||
int clientLinePointer;
|
||||
|
|
Reference in a new issue