Implemented M105 S1 command
This commit is contained in:
parent
dc17099d68
commit
19d8e625ea
7 changed files with 235 additions and 228 deletions
|
@ -24,8 +24,8 @@ Licence: GPL
|
||||||
#define CONFIGURATION_H
|
#define CONFIGURATION_H
|
||||||
|
|
||||||
#define NAME "RepRapFirmware"
|
#define NAME "RepRapFirmware"
|
||||||
#define VERSION "0.78v-dc42"
|
#define VERSION "0.78w-dc42"
|
||||||
#define DATE "2014-11-01"
|
#define DATE "2014-11-10"
|
||||||
#define AUTHORS "reprappro, dc42, zpl"
|
#define AUTHORS "reprappro, dc42, zpl"
|
||||||
|
|
||||||
// Other firmware that we might switch to be compatible with.
|
// Other firmware that we might switch to be compatible with.
|
||||||
|
|
23
GCodes.cpp
23
GCodes.cpp
|
@ -2165,16 +2165,23 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 105: // Deprecated...
|
case 105: // Deprecated...
|
||||||
reply.copy("T:");
|
if (gb->Seen('S') && gb->GetIValue() == 2)
|
||||||
for(int8_t heater = 1; heater < HEATERS; heater++)
|
|
||||||
{
|
{
|
||||||
Heat::HeaterStatus hs = reprap.GetHeat()->GetStatus(heater);
|
reprap.GetStatusResponse(reply, 2); // send JSON-formatted status response
|
||||||
if(hs != Heat::HS_off && hs != Heat::HS_fault)
|
}
|
||||||
{
|
else
|
||||||
reply.catf("%.1f ", reprap.GetHeat()->GetTemperature(heater));
|
{
|
||||||
}
|
reply.copy("T:");
|
||||||
|
for(int8_t heater = 1; heater < HEATERS; heater++)
|
||||||
|
{
|
||||||
|
Heat::HeaterStatus hs = reprap.GetHeat()->GetStatus(heater);
|
||||||
|
if(hs != Heat::HS_off && hs != Heat::HS_fault)
|
||||||
|
{
|
||||||
|
reply.catf("%.1f ", reprap.GetHeat()->GetTemperature(heater));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply.catf("B: %.1f ", reprap.GetHeat()->GetTemperature(HOT_BED));
|
||||||
}
|
}
|
||||||
reply.catf("B: %.1f ", reprap.GetHeat()->GetTemperature(HOT_BED));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 106: // Set/report fan values
|
case 106: // Set/report fan values
|
||||||
|
|
|
@ -478,6 +478,211 @@ void RepRap::Tick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the JSON status response for the web server or M105 command.
|
||||||
|
// Type 0 is the old-style webserver status response (we should be able to bet rid of this soon).
|
||||||
|
// Type 1 is the new-style webserver status response.
|
||||||
|
// Type 2 is the M105 S2 response, which is like the new-style status response but some fields are omitted.
|
||||||
|
// 'seq' is the response sequence number, not needed for the type 2 response because that field is omitted.
|
||||||
|
void RepRap::GetStatusResponse(StringRef& response, uint8_t type) const
|
||||||
|
{
|
||||||
|
const GCodes *gc = reprap.GetGCodes();
|
||||||
|
if (type != 0)
|
||||||
|
{
|
||||||
|
// New-style status request
|
||||||
|
// Send the printing/idle status
|
||||||
|
char ch = (reprap.IsStopped()) ? 'S' : (gc->PrintingAFile()) ? 'P' : 'I';
|
||||||
|
response.printf("{\"status\":\"%c\",\"heaters\":", ch);
|
||||||
|
|
||||||
|
// Send the heater actual temperatures
|
||||||
|
const Heat *heat = reprap.GetHeat();
|
||||||
|
ch = '[';
|
||||||
|
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
||||||
|
{
|
||||||
|
response.catf("%c%.1f", ch, heat->GetTemperature(heater));
|
||||||
|
ch = ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the heater active temperatures
|
||||||
|
response.catf("],\"active\":");
|
||||||
|
ch = '[';
|
||||||
|
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
||||||
|
{
|
||||||
|
response.catf("%c%.1f", ch, heat->GetActiveTemperature(heater));
|
||||||
|
ch = ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the heater standby temperatures
|
||||||
|
response.catf("],\"standby\":");
|
||||||
|
ch = '[';
|
||||||
|
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
||||||
|
{
|
||||||
|
response.catf("%c%.1f", ch, heat->GetStandbyTemperature(heater));
|
||||||
|
ch = ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the heater statuses (0=off, 1=standby, 2=active)
|
||||||
|
response.cat("],\"hstat\":");
|
||||||
|
ch = '[';
|
||||||
|
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
||||||
|
{
|
||||||
|
response.catf("%c%d", ch, (int)heat->GetStatus(heater));
|
||||||
|
ch = ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send XYZ positions
|
||||||
|
float liveCoordinates[DRIVES + 1];
|
||||||
|
reprap.GetMove()->LiveCoordinates(liveCoordinates);
|
||||||
|
const Tool* currentTool = reprap.GetCurrentTool();
|
||||||
|
if (currentTool != NULL)
|
||||||
|
{
|
||||||
|
const float *offset = currentTool->GetOffset();
|
||||||
|
for (size_t i = 0; i < AXES; ++i)
|
||||||
|
{
|
||||||
|
liveCoordinates[i] += offset[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.catf("],\"pos\":"); // announce the XYZ position
|
||||||
|
ch = '[';
|
||||||
|
for (int8_t drive = 0; drive < AXES; drive++)
|
||||||
|
{
|
||||||
|
response.catf("%c%.2f", ch, liveCoordinates[drive]);
|
||||||
|
ch = ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send extruder total extrusion since power up, last G92 or last M23
|
||||||
|
response.catf("],\"extr\":"); // announce the extruder positions
|
||||||
|
ch = '[';
|
||||||
|
for (int8_t drive = 0; drive < reprap.GetExtrudersInUse(); drive++) // loop through extruders
|
||||||
|
{
|
||||||
|
response.catf("%c%.1f", ch, gc->GetExtruderPosition(drive));
|
||||||
|
ch = ',';
|
||||||
|
}
|
||||||
|
response.cat("]");
|
||||||
|
|
||||||
|
// Send the speed and extruder override factors
|
||||||
|
response.catf(",\"sfactor\":%.2f,\"efactor\":", gc->GetSpeedFactor() * 100.0);
|
||||||
|
const float *extrusionFactors = gc->GetExtrusionFactors();
|
||||||
|
for (unsigned int i = 0; i < reprap.GetExtrudersInUse(); ++i)
|
||||||
|
{
|
||||||
|
response.catf("%c%.2f", (i == 0) ? '[' : ',', extrusionFactors[i] * 100.0);
|
||||||
|
}
|
||||||
|
response.cat("]");
|
||||||
|
|
||||||
|
// Send the current tool number
|
||||||
|
int toolNumber = (currentTool == NULL) ? 0 : currentTool->Number();
|
||||||
|
response.catf(",\"tool\":%d", toolNumber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The old (deprecated) 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.
|
||||||
|
// RRP reversed the order at version 0.65 to send the positions before the heaters, but we haven't yet done that.
|
||||||
|
char c = (gc->PrintingAFile()) ? 'P' : 'I';
|
||||||
|
response.printf("{\"poll\":[\"%c\",", c); // Printing
|
||||||
|
for (int8_t heater = 0; heater < HEATERS; heater++)
|
||||||
|
{
|
||||||
|
response.catf("\"%.1f\",", reprap.GetHeat()->GetTemperature(heater));
|
||||||
|
}
|
||||||
|
// Send XYZ and extruder positions
|
||||||
|
float liveCoordinates[DRIVES + 1];
|
||||||
|
reprap.GetMove()->LiveCoordinates(liveCoordinates);
|
||||||
|
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
|
||||||
|
response.catf("\"%.2f\"%c", liveCoordinates[drive], ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the Z probe value
|
||||||
|
int v0 = platform->ZProbe();
|
||||||
|
int v1, v2;
|
||||||
|
switch (platform->GetZProbeSecondaryValues(v1, v2))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
response.catf(",\"probe\":\"%d (%d)\"", v0, v1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
response.catf(",\"probe\":\"%d (%d, %d)\"", v0, v1, v2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
response.catf(",\"probe\":\"%d\"", v0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send fan RPM value
|
||||||
|
response.catf(",\"fanRPM\":%u", (unsigned int)platform->GetFanRPM());
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
response.catf(",\"homed\":[%d,%d,%d]",
|
||||||
|
(gc->GetAxisIsHomed(0)) ? 1 : 0,
|
||||||
|
(gc->GetAxisIsHomed(1)) ? 1 : 0,
|
||||||
|
(gc->GetAxisIsHomed(2)) ? 1 : 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.catf(",\"hx\":%d,\"hy\":%d,\"hz\":%d",
|
||||||
|
(gc->GetAxisIsHomed(0)) ? 1 : 0,
|
||||||
|
(gc->GetAxisIsHomed(1)) ? 1 : 0,
|
||||||
|
(gc->GetAxisIsHomed(2)) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != 2)
|
||||||
|
{
|
||||||
|
response.catf(",\"buff\":%u", webserver->GetGcodeBufferSpace()); // send the amount of buffer space available for gcodes
|
||||||
|
response.catf(",\"seq\":%u", webserver->GetReplySeq()); // send the response sequence number
|
||||||
|
const char *p = webserver->GetGcodeReply().Pointer(); // retrieve the gcode reply buffer from Webserver
|
||||||
|
|
||||||
|
// Send the response to the last command. Do this last because it is long and may need to be truncated.
|
||||||
|
response.cat(",\"resp\":\"");
|
||||||
|
size_t jp = response.strlen();
|
||||||
|
while (*p != 0 && jp < response.Length() - 3) // leave room for the final '"}\0'
|
||||||
|
{
|
||||||
|
char c = *p++;
|
||||||
|
char esc;
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '\r':
|
||||||
|
esc = 'r';
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
esc = 'n';
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
esc = 't';
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
esc = '"';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
esc = '\\';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
esc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (esc)
|
||||||
|
{
|
||||||
|
if (jp == response.Length() - 4)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
response[jp++] = '\\';
|
||||||
|
response[jp++] = esc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response[jp++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response[jp] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.cat("\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//*************************************************************************************************
|
//*************************************************************************************************
|
||||||
// StringRef class member implementations
|
// StringRef class member implementations
|
||||||
|
|
|
@ -66,7 +66,7 @@ int StringContains(const char* string, const char* match);
|
||||||
#define ARRAY_INIT(_dest, _init) _dest = _init
|
#define ARRAY_INIT(_dest, _init) _dest = _init
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Class to describe a string buffer, including its length. This saved passing buffer lengths around everywhere.
|
// Class to describe a string buffer, including its length. This saves passing buffer lengths around everywhere.
|
||||||
class StringRef
|
class StringRef
|
||||||
{
|
{
|
||||||
char *p; // pointer to the storage
|
char *p; // pointer to the storage
|
||||||
|
|
1
Reprap.h
1
Reprap.h
|
@ -58,6 +58,7 @@ class RepRap
|
||||||
uint16_t GetTicksInSpinState() const;
|
uint16_t GetTicksInSpinState() const;
|
||||||
uint16_t GetExtrudersInUse() const;
|
uint16_t GetExtrudersInUse() const;
|
||||||
uint16_t GetHeatersInUse() const;
|
uint16_t GetHeatersInUse() const;
|
||||||
|
void GetStatusResponse(StringRef& response, uint8_t type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
220
Webserver.cpp
220
Webserver.cpp
|
@ -355,7 +355,7 @@ void Webserver::ProcessGcode(const char* gc)
|
||||||
configFile->Close();
|
configFile->Close();
|
||||||
gcodeReply[i] = 0;
|
gcodeReply[i] = 0;
|
||||||
|
|
||||||
httpInterpreter->ReceivedGcodeReply();
|
++seq;
|
||||||
telnetInterpreter->HandleGcodeReply(gcodeReply.Pointer());
|
telnetInterpreter->HandleGcodeReply(gcodeReply.Pointer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,7 +527,7 @@ void Webserver::MessageStringToWebInterface(const char *s, bool error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
httpInterpreter->ReceivedGcodeReply();
|
++seq;
|
||||||
telnetInterpreter->HandleGcodeReply(s);
|
telnetInterpreter->HandleGcodeReply(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,7 +539,7 @@ void Webserver::AppendReplyToWebInterface(const char *s, bool error)
|
||||||
}
|
}
|
||||||
|
|
||||||
gcodeReply.cat(s);
|
gcodeReply.cat(s);
|
||||||
httpInterpreter->ReceivedGcodeReply();
|
++seq;
|
||||||
telnetInterpreter->HandleGcodeReply(s);
|
telnetInterpreter->HandleGcodeReply(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,7 +699,7 @@ bool ProtocolInterpreter::DebugEnabled() const
|
||||||
|
|
||||||
|
|
||||||
Webserver::HttpInterpreter::HttpInterpreter(Platform *p, Webserver *ws)
|
Webserver::HttpInterpreter::HttpInterpreter(Platform *p, Webserver *ws)
|
||||||
: ProtocolInterpreter(p, ws), state(doingCommandWord), seq(0), webDebug(false)
|
: ProtocolInterpreter(p, ws), state(doingCommandWord), webDebug(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,11 +837,11 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, StringRef&
|
||||||
|
|
||||||
if (StringEquals(request, "status")) // new style status request
|
if (StringEquals(request, "status")) // new style status request
|
||||||
{
|
{
|
||||||
GetStatusResponse(response, 1);
|
reprap.GetStatusResponse(response, 1);
|
||||||
}
|
}
|
||||||
else if (StringEquals(request, "poll")) // old style status request
|
else if (StringEquals(request, "poll")) // old style status request
|
||||||
{
|
{
|
||||||
GetStatusResponse(response, 0);
|
reprap.GetStatusResponse(response, 0);
|
||||||
}
|
}
|
||||||
else if (StringEquals(request, "gcode") && StringEquals(key, "gcode"))
|
else if (StringEquals(request, "gcode") && StringEquals(key, "gcode"))
|
||||||
{
|
{
|
||||||
|
@ -998,7 +998,7 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, StringRef&
|
||||||
else if (StringEquals(request, "connect"))
|
else if (StringEquals(request, "connect"))
|
||||||
{
|
{
|
||||||
CancelUpload();
|
CancelUpload();
|
||||||
GetStatusResponse(response, 1);
|
reprap.GetStatusResponse(response, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1013,207 +1013,6 @@ void Webserver::HttpInterpreter::GetJsonUploadResponse(StringRef& response)
|
||||||
response.printf("{\"ubuff\":%u,\"err\":%d}", webUploadBufferSize, (uploadState == uploadOK) ? 0 : 1);
|
response.printf("{\"ubuff\":%u,\"err\":%d}", webUploadBufferSize, (uploadState == uploadOK) ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Webserver::HttpInterpreter::GetStatusResponse(StringRef& response, uint8_t type)
|
|
||||||
{
|
|
||||||
GCodes *gc = reprap.GetGCodes();
|
|
||||||
if (type == 1)
|
|
||||||
{
|
|
||||||
// New-style status request
|
|
||||||
// Send the printing/idle status
|
|
||||||
char ch = (reprap.IsStopped()) ? 'S' : (gc->PrintingAFile()) ? 'P' : 'I';
|
|
||||||
response.printf("{\"status\":\"%c\",\"heaters\":", ch);
|
|
||||||
|
|
||||||
// Send the heater actual temperatures
|
|
||||||
const Heat *heat = reprap.GetHeat();
|
|
||||||
ch = '[';
|
|
||||||
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
|
||||||
{
|
|
||||||
response.catf("%c%.1f", ch, heat->GetTemperature(heater));
|
|
||||||
ch = ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the heater active temperatures
|
|
||||||
response.catf("],\"active\":");
|
|
||||||
ch = '[';
|
|
||||||
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
|
||||||
{
|
|
||||||
response.catf("%c%.1f", ch, heat->GetActiveTemperature(heater));
|
|
||||||
ch = ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the heater standby temperatures
|
|
||||||
response.catf("],\"standby\":");
|
|
||||||
ch = '[';
|
|
||||||
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
|
||||||
{
|
|
||||||
response.catf("%c%.1f", ch, heat->GetStandbyTemperature(heater));
|
|
||||||
ch = ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the heater statuses (0=off, 1=standby, 2=active)
|
|
||||||
response.cat("],\"hstat\":");
|
|
||||||
ch = '[';
|
|
||||||
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
|
||||||
{
|
|
||||||
response.catf("%c%d", ch, (int)heat->GetStatus(heater));
|
|
||||||
ch = ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send XYZ positions
|
|
||||||
float liveCoordinates[DRIVES + 1];
|
|
||||||
reprap.GetMove()->LiveCoordinates(liveCoordinates);
|
|
||||||
const Tool* currentTool = reprap.GetCurrentTool();
|
|
||||||
if (currentTool != NULL)
|
|
||||||
{
|
|
||||||
const float *offset = currentTool->GetOffset();
|
|
||||||
for (size_t i = 0; i < AXES; ++i)
|
|
||||||
{
|
|
||||||
liveCoordinates[i] += offset[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response.catf("],\"pos\":"); // announce the XYZ position
|
|
||||||
ch = '[';
|
|
||||||
for (int8_t drive = 0; drive < AXES; drive++)
|
|
||||||
{
|
|
||||||
response.catf("%c%.2f", ch, liveCoordinates[drive]);
|
|
||||||
ch = ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send extruder total extrusion since power up, last G92 or last M23
|
|
||||||
response.catf("],\"extr\":"); // announce the extruder positions
|
|
||||||
ch = '[';
|
|
||||||
for (int8_t drive = 0; drive < reprap.GetExtrudersInUse(); drive++) // loop through extruders
|
|
||||||
{
|
|
||||||
response.catf("%c%.1f", ch, gc->GetExtruderPosition(drive));
|
|
||||||
ch = ',';
|
|
||||||
}
|
|
||||||
response.cat("]");
|
|
||||||
|
|
||||||
// Send the speed and extruder override factors
|
|
||||||
response.catf(",\"sfactor\":%.2f,\"efactor\":", gc->GetSpeedFactor() * 100.0);
|
|
||||||
const float *extrusionFactors = gc->GetExtrusionFactors();
|
|
||||||
for (unsigned int i = 0; i < reprap.GetExtrudersInUse(); ++i)
|
|
||||||
{
|
|
||||||
response.catf("%c%.2f", (i == 0) ? '[' : ',', extrusionFactors[i] * 100.0);
|
|
||||||
}
|
|
||||||
response.cat("]");
|
|
||||||
|
|
||||||
// Send the current tool number
|
|
||||||
int toolNumber = (currentTool == NULL) ? 0 : currentTool->Number();
|
|
||||||
response.catf(",\"tool\":%d", toolNumber);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The old (deprecated) 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.
|
|
||||||
// RRP reversed the order at version 0.65 to send the positions before the heaters, but we haven't yet done that.
|
|
||||||
char c = (gc->PrintingAFile()) ? 'P' : 'I';
|
|
||||||
response.printf("{\"poll\":[\"%c\",", c); // Printing
|
|
||||||
for (int8_t heater = 0; heater < HEATERS; heater++)
|
|
||||||
{
|
|
||||||
response.catf("\"%.1f\",", reprap.GetHeat()->GetTemperature(heater));
|
|
||||||
}
|
|
||||||
// Send XYZ and extruder positions
|
|
||||||
float liveCoordinates[DRIVES + 1];
|
|
||||||
reprap.GetMove()->LiveCoordinates(liveCoordinates);
|
|
||||||
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
|
|
||||||
response.catf("\"%.2f\"%c", liveCoordinates[drive], ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the Z probe value
|
|
||||||
int v0 = platform->ZProbe();
|
|
||||||
int v1, v2;
|
|
||||||
switch (platform->GetZProbeSecondaryValues(v1, v2))
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
response.catf(",\"probe\":\"%d (%d)\"", v0, v1);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
response.catf(",\"probe\":\"%d (%d, %d)\"", v0, v1, v2);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
response.catf(",\"probe\":\"%d\"", v0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send fan RPM value
|
|
||||||
response.catf(",\"fanRPM\":%u", (unsigned int)platform->GetFanRPM());
|
|
||||||
|
|
||||||
// Send the amount of buffer space available for gcodes
|
|
||||||
response.catf(",\"buff\":%u", webserver->GetGcodeBufferSpace());
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
response.catf(",\"homed\":[%d,%d,%d]",
|
|
||||||
(gc->GetAxisIsHomed(0)) ? 1 : 0,
|
|
||||||
(gc->GetAxisIsHomed(1)) ? 1 : 0,
|
|
||||||
(gc->GetAxisIsHomed(2)) ? 1 : 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response.catf(",\"hx\":%d,\"hy\":%d,\"hz\":%d",
|
|
||||||
(gc->GetAxisIsHomed(0)) ? 1 : 0,
|
|
||||||
(gc->GetAxisIsHomed(1)) ? 1 : 0,
|
|
||||||
(gc->GetAxisIsHomed(2)) ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the gcode buffer from Webserver
|
|
||||||
const char *p = webserver->gcodeReply.Pointer();
|
|
||||||
|
|
||||||
// Send the response sequence number
|
|
||||||
response.catf(",\"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.
|
|
||||||
response.cat(",\"resp\":\"");
|
|
||||||
size_t jp = response.strlen();
|
|
||||||
while (*p != 0 && jp < response.Length() - 3) // leave room for the final '"}\0'
|
|
||||||
{
|
|
||||||
char c = *p++;
|
|
||||||
char esc;
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '\r':
|
|
||||||
esc = 'r';
|
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
esc = 'n';
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
esc = 't';
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
esc = '"';
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
esc = '\\';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
esc = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (esc)
|
|
||||||
{
|
|
||||||
if (jp == response.Length() - 4)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
response[jp++] = '\\';
|
|
||||||
response[jp++] = esc;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response[jp++] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response[jp] = 0;
|
|
||||||
response.cat("\"}");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Webserver::HttpInterpreter::ResetState()
|
void Webserver::HttpInterpreter::ResetState()
|
||||||
{
|
{
|
||||||
clientPointer = 0;
|
clientPointer = 0;
|
||||||
|
@ -1245,11 +1044,6 @@ bool Webserver::HttpInterpreter::FlushUploadData()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Webserver::HttpInterpreter::ReceivedGcodeReply()
|
|
||||||
{
|
|
||||||
// We need to increase seq whenever a new G-Code reply is available.
|
|
||||||
seq++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process a character from the client
|
// Process a character from the client
|
||||||
// Rewritten as a state machine by dc42 to increase capability and speed, and reduce RAM requirement.
|
// Rewritten as a state machine by dc42 to increase capability and speed, and reduce RAM requirement.
|
||||||
|
|
|
@ -141,6 +141,9 @@ class Webserver
|
||||||
void ConnectionLost(const ConnectionState *cs);
|
void ConnectionLost(const ConnectionState *cs);
|
||||||
void ConnectionError();
|
void ConnectionError();
|
||||||
void WebDebug(bool wdb);
|
void WebDebug(bool wdb);
|
||||||
|
const StringRef& GetGcodeReply() const { return gcodeReply; }
|
||||||
|
unsigned int GetReplySeq() const { return seq; }
|
||||||
|
unsigned int GetGcodeBufferSpace() const;
|
||||||
|
|
||||||
friend class Platform;
|
friend class Platform;
|
||||||
|
|
||||||
|
@ -166,7 +169,6 @@ class Webserver
|
||||||
bool CharFromClient(const char c);
|
bool CharFromClient(const char c);
|
||||||
void ResetState();
|
void ResetState();
|
||||||
bool FlushUploadData();
|
bool FlushUploadData();
|
||||||
void ReceivedGcodeReply();
|
|
||||||
virtual bool DebugEnabled() /*override*/ const { return webDebug; }
|
virtual bool DebugEnabled() /*override*/ const { return webDebug; }
|
||||||
void SetDebug(bool b) { webDebug = b; }
|
void SetDebug(bool b) { webDebug = b; }
|
||||||
|
|
||||||
|
@ -202,7 +204,6 @@ class Webserver
|
||||||
void SendJsonResponse(const char* command);
|
void SendJsonResponse(const char* command);
|
||||||
bool GetJsonResponse(const char* request, StringRef& response, const char* key, const char* value, size_t valueLength, bool& keepOpen);
|
bool GetJsonResponse(const char* request, StringRef& response, const char* key, const char* value, size_t valueLength, bool& keepOpen);
|
||||||
void GetJsonUploadResponse(StringRef& response);
|
void GetJsonUploadResponse(StringRef& response);
|
||||||
void GetStatusResponse(StringRef& response, uint8_t type);
|
|
||||||
bool ProcessMessage();
|
bool ProcessMessage();
|
||||||
bool RejectMessage(const char* s, unsigned int code = 500);
|
bool RejectMessage(const char* s, unsigned int code = 500);
|
||||||
|
|
||||||
|
@ -231,7 +232,6 @@ class Webserver
|
||||||
|
|
||||||
// Buffers to hold reply
|
// Buffers to hold reply
|
||||||
char decodeChar;
|
char decodeChar;
|
||||||
uint16_t seq; // reply sequence number, so that the client can tell if a json reply is new or not
|
|
||||||
bool webDebug;
|
bool webDebug;
|
||||||
};
|
};
|
||||||
HttpInterpreter *httpInterpreter;
|
HttpInterpreter *httpInterpreter;
|
||||||
|
@ -305,7 +305,6 @@ class Webserver
|
||||||
TelnetInterpreter *telnetInterpreter;
|
TelnetInterpreter *telnetInterpreter;
|
||||||
|
|
||||||
// G-Code processing
|
// G-Code processing
|
||||||
unsigned int GetGcodeBufferSpace() const;
|
|
||||||
void ProcessGcode(const char* gc);
|
void ProcessGcode(const char* gc);
|
||||||
void LoadGcodeBuffer(const char* gc);
|
void LoadGcodeBuffer(const char* gc);
|
||||||
void StoreGcodeData(const char* data, size_t len);
|
void StoreGcodeData(const char* data, size_t len);
|
||||||
|
@ -322,6 +321,7 @@ class Webserver
|
||||||
unsigned int gcodeReadIndex, gcodeWriteIndex; // head and tail indices into gcodeBuffer
|
unsigned int gcodeReadIndex, gcodeWriteIndex; // head and tail indices into gcodeBuffer
|
||||||
char gcodeReplyBuffer[2048];
|
char gcodeReplyBuffer[2048];
|
||||||
StringRef gcodeReply;
|
StringRef gcodeReply;
|
||||||
|
uint16_t seq; // reply sequence number, so that the client can tell if a json reply is new or not
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
char password[SHORT_STRING_LENGTH + 1];
|
char password[SHORT_STRING_LENGTH + 1];
|
||||||
|
|
Reference in a new issue