void Webserver::GetJsonResponse(const char* request)
{
  jsonPointer = 0;
  writing = true;
  
  if(StringStartsWith(request, "poll"))
  {
    strncpy(jsonResponse, "{\"poll\":[", STRING_LENGTH);
    if(reprap.GetGCodes()->PrintingAFile())
    	strncat(jsonResponse, "\"P\",", STRING_LENGTH); // Printing
    else
    	strncat(jsonResponse, "\"I\",", STRING_LENGTH); // Idle

    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);
    }

    // FIXME: should loop through all Es

    strncat(jsonResponse, "\"", STRING_LENGTH);
    strncat(jsonResponse, ftoa(0, liveCoordinates[AXES], 4), STRING_LENGTH);
    strncat(jsonResponse, "\",", STRING_LENGTH);

    for(int8_t heater = 0; heater < HEATERS; heater++)
    {
      strncat(jsonResponse, "\"", STRING_LENGTH);
      strncat(jsonResponse, ftoa(0, reprap.GetHeat()->GetTemperature(heater), 1), STRING_LENGTH);
      if(heater < HEATERS - 1)
    	  strncat(jsonResponse, "\",", STRING_LENGTH);
      else
    	  strncat(jsonResponse, "\"", STRING_LENGTH);
    }

    strncat(jsonResponse, "]", STRING_LENGTH);

    // Send the Z probe value
    char scratch[SHORT_STRING_LENGTH+1];
    scratch[SHORT_STRING_LENGTH] = 0;
    if (platform->GetZProbeType() == 2)
    {
    	snprintf(scratch, SHORT_STRING_LENGTH, ",\"probe\":\"%d (%d)\"", (int)platform->ZProbe(), platform->ZProbeOnVal());
    }
    else
    {
    	snprintf(scratch, SHORT_STRING_LENGTH, ",\"probe\":\"%d\"", (int)platform->ZProbe());
    }
    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);

    // 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);

    // Send the response sequence number
    strncat(jsonResponse, ",\"seq\":", STRING_LENGTH);
	snprintf(scratch, SHORT_STRING_LENGTH, "%u", (unsigned int)seq);
	strncat(jsonResponse, scratch, STRING_LENGTH);

    // 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);
    const char *p = gcodeReply;
    while (*p != 0 && jp < STRING_LENGTH - 2)	// leave room for the final '"}'
    {
    	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 == STRING_LENGTH - 3)
    			break;
   			jsonResponse[jp++] = '\\';
   			jsonResponse[jp++] = esc;
    	}
    	else
    	{
    		jsonResponse[jp++] = c;
    	}
    }
    strncat(jsonResponse, "\"}", STRING_LENGTH);

    jsonResponse[STRING_LENGTH] = 0;
    JsonReport(true, request);
    return;
  }
  
  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);
    JsonReport(true, request);
    return;
  }
  
  if(StringStartsWith(request, "files"))
  {
    char* fileList = platform->GetMassStorage()->FileList(platform->GetGCodeDir(), false);
    strncpy(jsonResponse, "{\"files\":[", STRING_LENGTH);
    strncat(jsonResponse, fileList, STRING_LENGTH);
    strncat(jsonResponse, "]}", STRING_LENGTH);
    JsonReport(true, request);
    return;
  }
  
  if(StringStartsWith(request, "name"))
  {
    strncpy(jsonResponse, "{\"myName\":\"", STRING_LENGTH);
    strncat(jsonResponse, myName, STRING_LENGTH);
    strncat(jsonResponse, "\"}", STRING_LENGTH);
    JsonReport(true, request);
    return;
  }
  
  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);
    JsonReport(true, request);
    return;
  }
  
  if(StringStartsWith(request, "axes"))
  {
    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);
      if(drive < AXES-1)
        strncat(jsonResponse, "\",", STRING_LENGTH);
      else
        strncat(jsonResponse, "\"", STRING_LENGTH);
    }
    strncat(jsonResponse, "]}", STRING_LENGTH);
    JsonReport(true, request);
    return;
  }
  
  JsonReport(false, request);
}
Example #2
0
// Get the Json response for this command.
// 'value' is null-terminated, but we also pass its length in case it contains embedded nulls, which matter when uploading files.
bool Webserver::GetJsonResponse(const char* request, const char* key, const char* value, size_t valueLength)
{
	bool found = true;	// assume success
	bool keepOpen = false;	// assume we don't want to persist the connection

	if (StringEquals(request, "status"))	// new style status request
	{
		GetStatusResponse(1);
	}
	else if (StringEquals(request, "poll"))		// old style status request
	{
		GetStatusResponse(0);
	}
	else if (StringEquals(request, "gcode") && StringEquals(key, "gcode"))
	{
		LoadGcodeBuffer(value);
		snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"buff\":%u}", GetReportedGcodeBufferSpace());
	}
	else if (StringEquals(request, "upload_begin") && StringEquals(key, "name"))
	{
		CancelUpload();
		FileStore *f = platform->GetFileStore("0:/", value, true);
		if (f != NULL)
		{
			fileBeingUploaded.Set(f);
			uploadState = uploadOK;
		}
		else
		{
			uploadState = uploadError;
		}
		GetJsonUploadResponse();
	}
	else if (StringEquals(request, "upload_data") && StringEquals(key, "data"))
	{
		if (uploadState == uploadOK)
		{
			uploadPointer = value;
			uploadLength = valueLength;
		}
		GetJsonUploadResponse();
		keepOpen = true;
	}
	else if (StringEquals(request, "upload_end") && StringEquals(key, "size"))
	{
		// Write the remaining data
		if (uploadLength != 0)
		{
			if (!fileBeingUploaded.Write(uploadPointer, uploadLength))
			{
				uploadState = uploadError;
			}
		}

		uploadPointer = NULL;
		uploadLength = 0;

		if (uploadState == uploadOK && !fileBeingUploaded.Flush())
		{
			uploadState = uploadError;
		}

		// Check the file length is as expected
		if (uploadState == uploadOK && fileBeingUploaded.Length() != strtoul(value, NULL, 10))
		{
			uploadState = uploadError;
		}

		// Close the file
		if (!fileBeingUploaded.Close())
		{
			uploadState = uploadError;
		}

		GetJsonUploadResponse();

		if (uploadState != uploadOK && strlen(filenameBeingUploaded) != 0)
		{
			platform->GetMassStorage()->Delete("0:/", filenameBeingUploaded);
		}
		filenameBeingUploaded[0] = 0;
	}
	else if (StringEquals(request, "upload_cancel"))
	{
		CancelUpload();
		snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"err\":%d}", 0);
	}
	else if (StringEquals(request, "delete") && StringEquals(key, "name"))
	{
		bool ok = platform->GetMassStorage()->Delete("0:/", value);
		snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"err\":%d}", (ok) ? 0 : 1);
	}
	else if (StringEquals(request, "files"))
	{
		const char* dir = (StringEquals(key, "dir")) ? value : platform->GetGCodeDir();
		const char* fileList = platform->GetMassStorage()->FileList(dir, false);
		snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"files\":[%s]}", fileList);
	}
	else if (StringEquals(request, "fileinfo") && StringEquals(key, "name"))
	{
		unsigned long length;
		float height, filament, layerHeight;
		char generatedBy[50];
		bool found = GetFileInfo(value, length, height, filament, layerHeight, generatedBy, ARRAY_SIZE(generatedBy));
		if (found)
		{
			snprintf(jsonResponse, ARRAY_UPB(jsonResponse),
					"{\"err\":0,\"size\":%lu,\"height\":%.2f,\"filament\":%.1f,\"layerHeight\":%.2f,\"generatedBy\":\"%s\"}",
					length, height, filament, layerHeight, generatedBy);
		}
		else
		{
			snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"err\":1}");
		}
	}
	else if (StringEquals(request, "name"))
	{
		snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"myName\":\"");
		size_t j = strlen(jsonResponse);
		for (size_t i = 0; i < ARRAY_SIZE(myName) - 1; ++i)
		{
			char c = myName[i];
			if (c < ' ')	// if null terminator or bad character
				break;
			if (c == '"' || c == '\\')
			{
				// Need to escape the quote-mark or backslash for JSON
				jsonResponse[j++] = '\\';
			}
			jsonResponse[j++] = c;
		}
		jsonResponse[j++] = '"';
		jsonResponse[j++] = '}';
		jsonResponse[j] = 0;
	}
	else if (StringEquals(request, "password") && StringEquals(key, "password"))
	{
		CheckPassword(value);
		snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"password\":\"%s\"}", (gotPassword) ? "right" : "wrong");
	}
	else if (StringEquals(request, "axes"))
	{
		strncpy(jsonResponse, "{\"axes\":", ARRAY_UPB(jsonResponse));
		char ch = '[';
		for (int8_t drive = 0; drive < AXES; drive++)
		{
			sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c%.1f", ch, platform->AxisTotalLength(drive));
			ch = ',';
		}
		strncat(jsonResponse, "]}", ARRAY_UPB(jsonResponse));
	}
	else if (StringEquals(request, "connect"))
	{
		CancelUpload();
		GetStatusResponse(1);
	}
	else
	{
		found = false;
	}

	JsonReport(found, request);
	return keepOpen;
}