diff --git a/Configuration.h b/Configuration.h index 554da3d..d582812 100644 --- a/Configuration.h +++ b/Configuration.h @@ -24,8 +24,8 @@ Licence: GPL #define CONFIGURATION_H #define NAME "RepRapFirmware" -#define VERSION "0.57w-dc42" -#define DATE "2014-03-25" +#define VERSION "0.57x-dc42" +#define DATE "2014-03-26" #define LAST_AUTHOR "dc42" // Other firmware that we might switch to be compatible with. diff --git a/GCodes.cpp b/GCodes.cpp index 4316266..f4abe28 100644 --- a/GCodes.cpp +++ b/GCodes.cpp @@ -55,7 +55,7 @@ void GCodes::Init() moveAvailable = false; drivesRelative = true; axesRelative = false; - checkEndStops = noEndstopCheck; + checkEndStops = false; gCodeLetters = GCODE_LETTERS; distanceScale = 1.0; for (int8_t i = 0; i < DRIVES - AXES; i++) @@ -305,7 +305,7 @@ bool GCodes::Pop() gFeedRate = feedrateStack[stackPointer]; moveBuffer[DRIVES] = gFeedRate; - checkEndStops = noEndstopCheck; + checkEndStops = false; moveAvailable = true; return true; } @@ -394,24 +394,23 @@ int GCodes::SetUpMove(GCodeBuffer *gb) if (!reprap.GetMove()->GetCurrentState(moveBuffer)) return 0; - bool doEndstopCheck = false; + checkEndStops = false; if (gb->Seen('S')) { if (gb->GetIValue() == 1) { - doEndstopCheck = true; + checkEndStops = true; } } - checkEndStops = (doEndstopCheck) ? checkAtEndstop : noEndstopCheck; - LoadMoveBufferFromGCode(gb, false, !doEndstopCheck); + LoadMoveBufferFromGCode(gb, false, !checkEndStops); moveAvailable = true; - return (doEndstopCheck) ? 2 : 1; + return (checkEndStops) ? 2 : 1; } // The Move class calls this function to find what to do next. -bool GCodes::ReadMove(float m[], EndstopMode& ce) +bool GCodes::ReadMove(float m[], bool& ce) { if (!moveAvailable) return false; @@ -419,7 +418,7 @@ bool GCodes::ReadMove(float m[], EndstopMode& ce) m[i] = moveBuffer[i]; ce = checkEndStops; moveAvailable = false; - checkEndStops = noEndstopCheck; + checkEndStops = false; return true; } @@ -498,7 +497,7 @@ bool GCodes::FileCannedCyclesReturn() // be ignored. Recall that moveToDo[DRIVES] should contain the feedrate // you want (if action[DRIVES] is true). -bool GCodes::DoCannedCycleMove(EndstopMode ce) +bool GCodes::DoCannedCycleMove(bool ce) { // Is the move already running? @@ -585,7 +584,7 @@ bool GCodes::OffsetAxes(GCodeBuffer* gb) offSetSet = true; } - if (DoCannedCycleMove(noEndstopCheck)) + if (DoCannedCycleMove(false)) { //LoadMoveBufferFromArray(record); for (int drive = 0; drive <= DRIVES; drive++) @@ -659,7 +658,7 @@ bool GCodes::DoHome(char* reply, bool& error) // Should never get here - checkEndStops = noEndstopCheck; + checkEndStops = false; moveAvailable = false; return true; @@ -680,19 +679,19 @@ bool GCodes::DoSingleZProbeAtPoint() switch (cannedCycleMoveCount) { - case 0: // This only does anything on the first move; on all the others Z is already there + case 0: // Raise Z to 5mm. This only does anything on the first move; on all the others Z is already there moveToDo[Z_AXIS] = Z_DIVE; activeDrive[Z_AXIS] = true; moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS); activeDrive[DRIVES] = true; - if (DoCannedCycleMove(noEndstopCheck)) + reprap.GetMove()->SetZProbing(false); + if (DoCannedCycleMove(false)) { cannedCycleMoveCount++; - reprap.GetMove()->SetZProbing(true); // we only want to call this once } return false; - case 1: + case 1: // Move to the correct XY coordinates GetProbeCoordinates(probeCount, moveToDo[X_AXIS], moveToDo[Y_AXIS], moveToDo[Z_AXIS]); activeDrive[X_AXIS] = true; activeDrive[Y_AXIS] = true; @@ -700,48 +699,33 @@ bool GCodes::DoSingleZProbeAtPoint() moveToDo[DRIVES] = platform->HomeFeedRate(X_AXIS); activeDrive[DRIVES] = true; reprap.GetMove()->SetZProbing(false); - if (DoCannedCycleMove(noEndstopCheck)) + if (DoCannedCycleMove(false)) { cannedCycleMoveCount++; + platform->SetZProbing(true); // do this here because we only want to call it once } return false; - case 2: + case 2: // Probe the bed moveToDo[Z_AXIS] = -2.0 * platform->AxisLength(Z_AXIS); activeDrive[Z_AXIS] = true; moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS); activeDrive[DRIVES] = true; reprap.GetMove()->SetZProbing(true); - if (DoCannedCycleMove(checkApproachingEndstop)) - { - cannedCycleMoveCount++; - } - return false; - - case 3: - { - float liveCoordinates[DRIVES + 1]; - reprap.GetMove()->LiveCoordinates(liveCoordinates); - moveToDo[Z_AXIS] = liveCoordinates[Z_AXIS] - 10.0; // move down at most another 10mm - } - activeDrive[Z_AXIS] = true; - moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS) * 0.2; - activeDrive[DRIVES] = true; - reprap.GetMove()->SetZProbing(true); - if (DoCannedCycleMove(checkAtEndstop)) + if (DoCannedCycleMove(true)) { cannedCycleMoveCount++; platform->SetZProbing(false); } return false; - case 4: + case 3: // Raise the head 5mm moveToDo[Z_AXIS] = Z_DIVE; activeDrive[Z_AXIS] = true; moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS); activeDrive[DRIVES] = true; reprap.GetMove()->SetZProbing(false); - if (DoCannedCycleMove(noEndstopCheck)) + if (DoCannedCycleMove(false)) { cannedCycleMoveCount++; } @@ -775,22 +759,7 @@ bool GCodes::DoSingleZProbe() activeDrive[Z_AXIS] = true; moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS); activeDrive[DRIVES] = true; - if (DoCannedCycleMove(checkApproachingEndstop)) - { - cannedCycleMoveCount++; - } - return false; - - case 2: - { - float liveCoordinates[DRIVES + 1]; - reprap.GetMove()->LiveCoordinates(liveCoordinates); - moveToDo[Z_AXIS] = liveCoordinates[Z_AXIS] - 10.0; // move down at most another 10mm - } - activeDrive[Z_AXIS] = true; - moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS) * 0.2; - activeDrive[DRIVES] = true; - if (DoCannedCycleMove(checkAtEndstop)) + if (DoCannedCycleMove(true)) { cannedCycleMoveCount++; probeCount = 0; @@ -1656,11 +1625,9 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb) strncpy(reply, "T:", STRING_LENGTH); for (int8_t heater = HEATERS - 1; heater > 0; heater--) { - strncat(reply, ftoa(0, reprap.GetHeat()->GetTemperature(heater), 1), STRING_LENGTH); - strncat(reply, " ", STRING_LENGTH); + sncatf(reply, STRING_LENGTH, "%.1f ", reprap.GetHeat()->GetTemperature(heater)); } - strncat(reply, "B:", STRING_LENGTH); - strncat(reply, ftoa(0, reprap.GetHeat()->GetTemperature(0), 1), STRING_LENGTH); + sncatf(reply, STRING_LENGTH, "B:%.1f", reprap.GetHeat()->GetTemperature(0)); break; case 106: // Fan on or off diff --git a/GCodes.h b/GCodes.h index 9cc3567..c43433e 100644 --- a/GCodes.h +++ b/GCodes.h @@ -27,10 +27,6 @@ Licence: GPL #define GCODE_LETTERS { 'X', 'Y', 'Z', 'E', 'F' } // The drives and feedrate in a GCode -// Enumeration to define the mode in which we check endstops - -enum EndstopMode { noEndstopCheck, checkApproachingEndstop, checkAtEndstop}; - // Small class to hold an individual GCode and provide functions to allow it to be parsed @@ -77,7 +73,7 @@ class GCodes void Init(); void Exit(); bool RunConfigurationGCodes(); - bool ReadMove(float* m, EndstopMode& ce); + bool ReadMove(float* m, bool& ce); void QueueFileToPrint(const char* fileName); void DeleteFile(const char* fileName); bool GetProbeCoordinates(int count, float& x, float& y, float& z); @@ -92,7 +88,7 @@ class GCodes void doFilePrint(GCodeBuffer* gb); bool AllMovesAreFinishedAndMoveBufferIsLoaded(); - bool DoCannedCycleMove(EndstopMode ce); + bool DoCannedCycleMove(bool ce); bool DoFileCannedCycles(const char* fileName); bool FileCannedCyclesReturn(); bool ActOnGcode(GCodeBuffer* gb); @@ -133,7 +129,7 @@ class GCodes GCodeBuffer* cannedCycleGCode; bool moveAvailable; float moveBuffer[DRIVES+1]; // Last is feed rate - EndstopMode checkEndStops; + bool checkEndStops; bool drivesRelative; // All except X, Y and Z bool axesRelative; // X, Y and Z bool drivesRelativeStack[STACK]; diff --git a/Heat.cpp b/Heat.cpp index 63f78af..2a9296c 100644 --- a/Heat.cpp +++ b/Heat.cpp @@ -128,12 +128,8 @@ void PID::Spin() { platform->SetHeater(heater, 0.0); temperatureFault = true; - platform->Message(HOST_MESSAGE, "Temperature measurement fault on heater "); - snprintf(scratchString, STRING_LENGTH, "%d", heater); + snprintf(scratchString, STRING_LENGTH, "Temperature measurement fault on heater %d, T = %.1f\n", heater, temperature); platform->Message(HOST_MESSAGE, scratchString); - platform->Message(HOST_MESSAGE, ", T = "); - platform->Message(HOST_MESSAGE, ftoa(scratchString, temperature, 1)); - platform->Message(HOST_MESSAGE, "\n"); } } else diff --git a/Move.cpp b/Move.cpp index b1f6e63..3a6ac8c 100644 --- a/Move.cpp +++ b/Move.cpp @@ -94,7 +94,7 @@ void Move::Init() liveCoordinates[i] = 0.0; } - lastMove->Init(ep, platform->HomeFeedRate(Z_AXIS), platform->InstantDv(Z_AXIS), noEndstopCheck, zMove); // Typically Z is the slowest Axis + lastMove->Init(ep, platform->HomeFeedRate(Z_AXIS), platform->InstantDv(Z_AXIS), false, zMove); // Typically Z is the slowest Axis lastMove->Release(); liveCoordinates[DRIVES] = platform->HomeFeedRate(Z_AXIS); @@ -167,7 +167,7 @@ void Move::Spin() // If there's a G Code move available, add it to the look-ahead // ring for processing. - EndstopMode checkEndStopsOnNextMove; + bool checkEndStopsOnNextMove; if(gCodes->ReadMove(nextMove, checkEndStopsOnNextMove)) { Transform(nextMove); @@ -572,7 +572,7 @@ void Move::Interrupt() } -bool Move::LookAheadRingAdd(const long ep[], float feedRate, float vv, EndstopMode ce, int8_t mt) +bool Move::LookAheadRingAdd(const long ep[], float feedRate, float vv, bool ce, int8_t mt) { if(LookAheadRingFull()) return false; @@ -600,7 +600,7 @@ LookAhead* Move::LookAheadRingGet() } // Note that we don't set the tan values to 0 here. This means that the bed probe -// values will be a fraction of a millimeter out in X and Y, which, as the bed should +// values will be a fraction of a millimetre out in X and Y, which, as the bed should // be nearly flat (and the probe doesn't coincide with the nozzle anyway), won't matter. // But it means that the tan values can be set for the machine // at the start in the configuration file and be retained, without having to know and reset @@ -614,7 +614,6 @@ void Move::SetIdentityTransform() secondDegreeCompensation = false; } - void Move::Transform(float xyzPoint[]) { xyzPoint[X_AXIS] = xyzPoint[X_AXIS] + tanXY*xyzPoint[Y_AXIS] + tanXZ*xyzPoint[Z_AXIS]; @@ -1099,7 +1098,7 @@ void DDA::Step() // Hit anything? - if(checkEndStops != noEndstopCheck) + if(checkEndStops) { switch(platform->Stopped(drive)) { @@ -1112,11 +1111,7 @@ void DDA::Step() active = false; break; case lowNear: - if (checkEndStops == checkApproachingEndstop) - { - move->NearLowStop(drive, myLookAheadEntry, this); - active = false; - } + velocity = instantDv; // slow down because we are getting close break; default: break; @@ -1180,7 +1175,7 @@ LookAhead::LookAhead(Move* m, Platform* p, LookAhead* n) next = n; } -void LookAhead::Init(const long ep[], float f, float vv, EndstopMode ce, int8_t mt) +void LookAhead::Init(const long ep[], float f, float vv, bool ce, int8_t mt) { v = vv; movementType = mt; diff --git a/Move.h b/Move.h index f60cadf..9f11b38 100644 --- a/Move.h +++ b/Move.h @@ -70,7 +70,7 @@ public: protected: LookAhead(Move* m, Platform* p, LookAhead* n); - void Init(const long ep[], float feedRate, float vv, EndstopMode ce, int8_t mt); + void Init(const long ep[], float feedRate, float vv, bool ce, int8_t mt); LookAhead* Next(); LookAhead* Previous(); const long* MachineEndPoints() const; @@ -85,7 +85,7 @@ protected: int8_t Processed() const; void SetProcessed(MovementState ms); void SetDriveCoordinateAndZeroEndSpeed(float a, int8_t drive); - EndstopMode CheckEndStops() const; + bool CheckEndStops() const; void Release(); private: @@ -97,7 +97,7 @@ private: long endPoint[DRIVES+1]; // Should never use the +1, but safety first int8_t movementType; float Cosine(); - EndstopMode checkEndStops; + bool checkEndStops; float cosine; float v; // The feedrate we can actually do float feedRate; // The requested feedrate @@ -135,7 +135,7 @@ private: bool directions[DRIVES]; long totalSteps; long stepCount; - EndstopMode checkEndStops; + bool checkEndStops; float timeStep; float velocity; long stopAStep; @@ -164,7 +164,6 @@ class Move void ResumeMoving(); void DoLookAhead(); void HitLowStop(int8_t drive, LookAhead* la, DDA* hitDDA); - void NearLowStop(int8_t drive, LookAhead* la, DDA* hitDDA); void HitHighStop(int8_t drive, LookAhead* la, DDA* hitDDA); void SetPositions(float move[]); void SetLiveCoordinates(float coords[]); @@ -204,7 +203,7 @@ class Move void ReleaseDDARingLock(); bool LookAheadRingEmpty() const; bool LookAheadRingFull() const; - bool LookAheadRingAdd(const long ep[], float feedRate, float vv, EndstopMode ce, int8_t movementType); + bool LookAheadRingAdd(const long ep[], float feedRate, float vv, bool ce, int8_t movementType); LookAhead* LookAheadRingGet(); int8_t GetMovementType(const long sp[], const long ep[]) const; @@ -304,7 +303,7 @@ inline void LookAhead::Release() processed = released; } -inline EndstopMode LookAhead::CheckEndStops() const +inline bool LookAhead::CheckEndStops() const { return checkEndStops; } @@ -583,11 +582,6 @@ inline void Move::HitHighStop(int8_t drive, LookAhead* la, DDA* hitDDA) gCodes->SetAxisIsHomed(drive); } -inline void Move::NearLowStop(int8_t drive, LookAhead* la, DDA* hitDDA) -{ - la->SetDriveCoordinateAndZeroEndSpeed(1.0, drive); // say we are at 1mm -} - inline float Move::ComputeCurrentCoordinate(int8_t drive, LookAhead* la, DDA* runningDDA) { float previous = la->Previous()->MachineToEndPoint(drive); diff --git a/Platform.cpp b/Platform.cpp index b3a04a2..47e8341 100644 --- a/Platform.cpp +++ b/Platform.cpp @@ -770,6 +770,16 @@ void Platform::PrintMemoryUsage() snprintf(scratchString, STRING_LENGTH, "Error status: %u\n", errorCodeBits); reprap.GetWebserver()->AppendReply(scratchString); Message(HOST_MESSAGE, scratchString); + + // Show the current probe position heights + strncpy(scratchString, "Bed probe heights:", STRING_LENGTH); + for (size_t i = 0; i < NUMBER_OF_PROBE_POINTS; ++i) + { + sncatf(scratchString, STRING_LENGTH, " %.3f", reprap.GetMove()->zBedProbePoint(i)); + } + strncat(scratchString, "\n", STRING_LENGTH); + reprap.GetWebserver()->AppendReply(scratchString); + Message(HOST_MESSAGE, scratchString); } void Platform::ClassReport(char* className, float &lastTime) diff --git a/Release/RepRapFirmware-057x-dc42.bin b/Release/RepRapFirmware-057x-dc42.bin new file mode 100644 index 0000000..1787c8c Binary files /dev/null and b/Release/RepRapFirmware-057x-dc42.bin differ diff --git a/RepRapFirmware.cpp b/RepRapFirmware.cpp index 28b5852..3672693 100644 --- a/RepRapFirmware.cpp +++ b/RepRapFirmware.cpp @@ -302,11 +302,13 @@ void RepRap::SetDebug(int d) // Utilities and storage not part of any class +char scratchString[STRING_LENGTH]; + +#if 0 // no longer used, we use snprinf or sncatf instead // Float to a string. static long precision[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000}; -char scratchString[STRING_LENGTH]; char* ftoa(char *a, const float& f, int prec) { @@ -326,6 +328,23 @@ char* ftoa(char *a, const float& f, int prec) snprintf(a, STRING_LENGTH, "%0*d", prec, decimal); return ret; } +#endif + +// This behaves like snprintf but appends to an existing string +// The second parameter is the length of the entire destination buffer, not the length remaining +int sncatf(char *dst, size_t len, const char* fmt, ...) +{ + size_t n = strnlen(dst, len); + if (n + 1 < len) + { + va_list p; + va_start(p, fmt); + int ret = vsnprintf(dst + n, len - n, fmt, p); + va_end(p); + return ret; + } + return 0; +} // String testing diff --git a/RepRapFirmware.h b/RepRapFirmware.h index 27e8749..3f75f90 100644 --- a/RepRapFirmware.h +++ b/RepRapFirmware.h @@ -22,6 +22,9 @@ Licence: GPL #ifndef REPRAPFIRMWARE_H #define REPRAPFIRMWARE_H +#include // for size_t +#include + // Warn of what's to come, so we can use pointers to classes... class Platform; @@ -37,7 +40,10 @@ extern RepRap reprap; // Functions and globals not part of any class +int sncatf(char *dst, size_t len, const char* fmt, ...); +#if 0 // n longer used char* ftoa(char *a, const float& f, int prec); +#endif bool StringEndsWith(const char* string, const char* ending); bool StringStartsWith(const char* string, const char* starting); bool StringEquals(const char* s1, const char* s2); @@ -46,8 +52,6 @@ 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])) -#include - extern char scratchString[]; #include "Configuration.h" @@ -59,7 +63,6 @@ extern char scratchString[]; #include "Reprap.h" - #endif diff --git a/Webserver.cpp b/Webserver.cpp index ad234d7..ef81039 100644 --- a/Webserver.cpp +++ b/Webserver.cpp @@ -390,6 +390,7 @@ void Webserver::JsonReport(bool ok, const char* request) { if(reprap.Debug()) { + jsonResponse[STRING_LENGTH] = 0; platform->Message(HOST_MESSAGE, "JSON response: "); platform->Message(HOST_MESSAGE, jsonResponse); platform->Message(HOST_MESSAGE, " queued\n"); @@ -410,68 +411,65 @@ void Webserver::GetJsonResponse(const char* request) if(StringStartsWith(request, "poll")) { + // The poll response lists the status, then all the heater temperatures, then the XYZ positions, then all the extruder positions. + // 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, + // but we're stuck with it if we want to retain compatibility with existing web server javascript files. strncpy(jsonResponse, "{\"poll\":[", STRING_LENGTH); if(reprap.GetGCodes()->PrintingAFile()) + { strncat(jsonResponse, "\"P\",", STRING_LENGTH); // Printing + } else + { strncat(jsonResponse, "\"I\",", STRING_LENGTH); // Idle + } for(int8_t heater = 0; heater < HEATERS; heater++) { - strncat(jsonResponse, "\"", STRING_LENGTH); - strncat(jsonResponse, ftoa(0, reprap.GetHeat()->GetTemperature(heater), 1), STRING_LENGTH); - strncat(jsonResponse, "\",", STRING_LENGTH); + sncatf(jsonResponse, STRING_LENGTH, "\"%.1f\",", reprap.GetHeat()->GetTemperature(heater)); } float liveCoordinates[DRIVES+1]; reprap.GetMove()->LiveCoordinates(liveCoordinates); for(int8_t drive = 0; drive < AXES; drive++) { - strncat(jsonResponse, "\"", STRING_LENGTH); - strncat(jsonResponse, ftoa(0, liveCoordinates[drive], 2), STRING_LENGTH); - strncat(jsonResponse, "\",", STRING_LENGTH); + sncatf(jsonResponse, STRING_LENGTH, "\"%.2f\",", liveCoordinates[drive]); } - // FIXME: should loop through all Es - - strncat(jsonResponse, "\"", STRING_LENGTH); - strncat(jsonResponse, ftoa(0, liveCoordinates[AXES], 4), STRING_LENGTH); - strncat(jsonResponse, "\"", STRING_LENGTH); - strncat(jsonResponse, "]", STRING_LENGTH); + for(int8_t drive = AXES; drive < DRIVES; drive++) // loop through extruders + { + char ch = (drive == DRIVES - 1) ? ']' : ','; // append ] to the last one but , to the others + sncatf(jsonResponse, STRING_LENGTH, "\"%.f4\"%c", liveCoordinates[drive], ch); + } + // All the other values we send back are in separate variables. // Send the Z probe value - char scratch[SHORT_STRING_LENGTH+1]; - scratch[SHORT_STRING_LENGTH] = 0; int v0 = platform->ZProbe(); int v1, v2; switch(platform->GetZProbeSecondaryValues(v1, v2)) { case 1: - snprintf(scratch, SHORT_STRING_LENGTH, ",\"probe\":\"%d (%d)\"", v0, v1); + sncatf(jsonResponse, STRING_LENGTH, ",\"probe\":\"%d (%d)\"", v0, v1); break; case 2: - snprintf(scratch, SHORT_STRING_LENGTH, ",\"probe\":\"%d (%d, %d)\"", v0, v1, v2); + sncatf(jsonResponse, STRING_LENGTH, ",\"probe\":\"%d (%d, %d)\"", v0, v1, v2); break; default: - snprintf(scratch, SHORT_STRING_LENGTH, ",\"probe\":\"%d\"", v0); + sncatf(jsonResponse, STRING_LENGTH, ",\"probe\":\"%d\"", v0); break; } - strncat(jsonResponse, scratch, STRING_LENGTH); // Send the amount of buffer space available for gcodes - snprintf(scratch, SHORT_STRING_LENGTH, ",\"buff\":%u", GetReportedGcodeBufferSpace()); - strncat(jsonResponse, scratch, STRING_LENGTH); + sncatf(jsonResponse, STRING_LENGTH, ",\"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. - strncat(jsonResponse, ",\"hx\":", STRING_LENGTH); - strncat(jsonResponse, (reprap.GetGCodes()->GetAxisIsHomed(0)) ? "1" : "0", STRING_LENGTH); - strncat(jsonResponse, ",\"hy\":", STRING_LENGTH); - strncat(jsonResponse, (reprap.GetGCodes()->GetAxisIsHomed(1)) ? "1" : "0", STRING_LENGTH); - strncat(jsonResponse, ",\"hz\":", STRING_LENGTH); - strncat(jsonResponse, (reprap.GetGCodes()->GetAxisIsHomed(2)) ? "1" : "0", STRING_LENGTH); + sncatf(jsonResponse, STRING_LENGTH, ",\"hx\":%d,\"hy\":%d,\"hz\":%d", + (reprap.GetGCodes()->GetAxisIsHomed(0)) ? 1 : 0, + (reprap.GetGCodes()->GetAxisIsHomed(1)) ? 1 : 0, + (reprap.GetGCodes()->GetAxisIsHomed(2)) ? 1 : 0 + ); // Send the response sequence number - strncat(jsonResponse, ",\"seq\":", STRING_LENGTH); - snprintf(scratch, SHORT_STRING_LENGTH, "%u", (unsigned int)seq); - strncat(jsonResponse, scratch, STRING_LENGTH); + sncatf(jsonResponse, STRING_LENGTH, ",\"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); @@ -510,7 +508,6 @@ void Webserver::GetJsonResponse(const char* request) } strncat(jsonResponse, "\"}", STRING_LENGTH); - jsonResponse[STRING_LENGTH] = 0; JsonReport(true, request); return; } @@ -518,10 +515,7 @@ void Webserver::GetJsonResponse(const char* request) if(StringStartsWith(request, "gcode")) { LoadGcodeBuffer(&clientQualifier[6], true); - char scratch[SHORT_STRING_LENGTH+1]; - scratch[SHORT_STRING_LENGTH] = 0; - snprintf(scratch, SHORT_STRING_LENGTH, "{\"buff\":%u}", GetReportedGcodeBufferSpace()); - strncat(jsonResponse, scratch, STRING_LENGTH); + sncatf(jsonResponse, STRING_LENGTH, "{\"buff\":%u}", GetReportedGcodeBufferSpace()); JsonReport(true, request); return; } @@ -529,18 +523,14 @@ void Webserver::GetJsonResponse(const char* request) if(StringStartsWith(request, "files")) { const char* fileList = platform->GetMassStorage()->FileList(platform->GetGCodeDir(), false); - strncpy(jsonResponse, "{\"files\":[", STRING_LENGTH); - strncat(jsonResponse, fileList, STRING_LENGTH); - strncat(jsonResponse, "]}", STRING_LENGTH); + snprintf(jsonResponse, STRING_LENGTH, "{\"files\":[%s]}", fileList); JsonReport(true, request); return; } if(StringStartsWith(request, "name")) { - strncpy(jsonResponse, "{\"myName\":\"", STRING_LENGTH); - strncat(jsonResponse, myName, STRING_LENGTH); - strncat(jsonResponse, "\"}", STRING_LENGTH); + snprintf(jsonResponse, STRING_LENGTH, "{\"myName\":\"%s\"}", myName); JsonReport(true, request); return; } @@ -548,12 +538,7 @@ void Webserver::GetJsonResponse(const char* request) if(StringStartsWith(request, "password")) { CheckPassword(); - strncpy(jsonResponse, "{\"password\":\"", STRING_LENGTH); - if(gotPassword) - strncat(jsonResponse, "right", STRING_LENGTH); - else - strncat(jsonResponse, "wrong", STRING_LENGTH); - strncat(jsonResponse, "\"}", STRING_LENGTH); + snprintf(jsonResponse, STRING_LENGTH, "{\"password\":\"%s\"}", (gotPassword) ? "right" : "wrong"); JsonReport(true, request); return; } @@ -563,12 +548,11 @@ void Webserver::GetJsonResponse(const char* request) strncpy(jsonResponse, "{\"axes\":[", STRING_LENGTH); for(int8_t drive = 0; drive < AXES; drive++) { - strncat(jsonResponse, "\"", STRING_LENGTH); - strncat(jsonResponse, ftoa(0, platform->AxisLength(drive), 1), STRING_LENGTH); + sncatf(jsonResponse, STRING_LENGTH, "\"%.1f\"", platform->AxisLength(drive)); if(drive < AXES-1) - strncat(jsonResponse, "\",", STRING_LENGTH); - else - strncat(jsonResponse, "\"", STRING_LENGTH); + { + strncat(jsonResponse, ",", STRING_LENGTH); + } } strncat(jsonResponse, "]}", STRING_LENGTH); JsonReport(true, request);