// Set the DHCP hostname. Removes all whitespaces and converts the name to lower-case.
void Network::SetHostname(const char *name)
{
	size_t i = 0;
	while (*name && i < ARRAY_UPB(hostname))
	{
		char c = *name++;
		if (c >= 'A' && c <= 'Z')
		{
			c += 'a' - 'A';
		}

		if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '-') || (c == '_'))
		{
			hostname[i++] = c;
		}
	}

	if (i)
	{
		hostname[i] = 0;
	}
	else
	{
		strcpy(hostname, HOSTNAME);
	}
}
Exemple #2
0
void Webserver::GetStatusResponse(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';
		snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"status\":\"%c\",\"heaters\":", ch);

		// Send the heater temperatures
		ch = '[';
		for (int8_t heater = 0; heater < HEATERS; 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\":", ARRAY_UPB(jsonResponse));		// announce the XYZ position
		ch = '[';
		for (int8_t drive = 0; drive < AXES; drive++)
		{
			sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c%.2f", ch, liveCoordinates[drive]);
			ch = ',';
		}
		sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "],\"extr\":");		// announce the extruder positions
		ch = '[';
		for (int8_t drive = AXES; drive < DRIVES; drive++)		// loop through extruders
		{
			sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c%.3f", ch, gc->GetExtruderPosition(drive - AXES));
			ch = ',';
		}
		strncat(jsonResponse, "]", ARRAY_UPB(jsonResponse));

		// Send the speed and extruder override factors
		sncatf(jsonResponse, ARRAY_UPB(jsonResponse), ",\"sfactor\":%.2f,\"efactor:\":", gc->GetSpeedFactor() * 100.0);
		const float *extrusionFactors = gc->GetExtrusionFactors();
		for (unsigned int i = 0; i < DRIVES - AXES; ++i)
		{
			sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c%.2f", (i == 0) ? '[' : ',', extrusionFactors[i] * 100.0);
		}
		strncat(jsonResponse, "]", ARRAY_UPB(jsonResponse));
	}
Exemple #3
0
// Process a received string of gcodes
void Webserver::LoadGcodeBuffer(const char* gc)
{
	char gcodeTempBuf[GCODE_LENGTH];
	uint16_t gtp = 0;
	bool inComment = false;
	for (;;)
	{
		char c = *gc++;
		if (c == 0)
		{
			gcodeTempBuf[gtp] = 0;
			ProcessGcode(gcodeTempBuf);
			return;
		}

		if (c == '\n')
		{
			gcodeTempBuf[gtp] = 0;
			ProcessGcode(gcodeTempBuf);
			gtp = 0;
			inComment = false;
		}
		else
		{
			if (c == ';')
			{
				inComment = true;
			}

			if (gtp == ARRAY_UPB(gcodeTempBuf))
			{
				// gcode is too long, we haven't room for another character and a null
				if (c != ' ' && !inComment)
				{
					platform->Message(HOST_MESSAGE, "Webserver: GCode local buffer overflow.\n");
					HandleReply("Webserver: GCode local buffer overflow", true);
					return;
				}
				// else we're either in a comment or the current character is a space.
				// If we're in a comment, we'll silently truncate it.
				// If the current character is a space, we'll wait until we see a non-comment character before reporting an error,
				// in case the next character is end-of-line or the start of a comment.
			}
			else
			{
				gcodeTempBuf[gtp++] = c;
			}
		}
	}
}
Exemple #4
0
void Webserver::ProcessGcode(const char* gc)
{
	if (StringStartsWith(gc, "M30 "))		// delete SD card file
	{
		reprap.GetGCodes()->DeleteFile(&gc[4]);
	}
	else if (StringStartsWith(gc, "M23 "))	// select SD card file to print next
	{
		reprap.GetGCodes()->QueueFileToPrint(&gc[4]);
	}
	else if (StringStartsWith(gc, "M112") && !isdigit(gc[4]))	// emergency stop
	{
		reprap.EmergencyStop();
		gcodeReadIndex = gcodeWriteIndex;		// clear the buffer
		reprap.GetGCodes()->Reset();
	}
	else if (StringStartsWith(gc, "M503") && !isdigit(gc[4]))	// echo config.g file
	{
		FileStore *configFile = platform->GetFileStore(platform->GetSysDir(), platform->GetConfigFile(), false);
		if (configFile == NULL)
		{
			HandleReply("Configuration file not found", true);
		}
		else
		{
			char c;
			size_t i = 0;
			while (i < ARRAY_UPB(gcodeReply) && configFile->Read(c))
			{
				gcodeReply[i++] = c;
			}
			configFile->Close();
			gcodeReply[i] = 0;
			++seq;
		}
	}
	else if (StringStartsWith(gc, "M25") && !isDigit(gc[3]))	// pause SD card print
	{
		reprap.GetGCodes()->PauseSDPrint();
	}
	else
	{
		StoreGcodeData(gc, strlen(gc) + 1);
	}
}
Exemple #5
0
void Webserver::JsonReport(bool ok, const char* request)
{
	if (ok)
	{
		jsonResponse[ARRAY_UPB(jsonResponse)] = 0;
		if (reprap.Debug())
		{
			platform->Message(HOST_MESSAGE, "JSON response: ");
			platform->Message(HOST_MESSAGE, jsonResponse);
			platform->Message(HOST_MESSAGE, " queued\n");
		}
	}
	else
	{
		jsonResponse[0] = 0;
		platform->Message(HOST_MESSAGE, "KnockOut request: ");
		platform->Message(HOST_MESSAGE, request);
		platform->Message(HOST_MESSAGE, " not recognised\n");
	}
}
Exemple #6
0
void Webserver::GetJsonUploadResponse()
{
	snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"ubuff\":%u,\"err\":%d}", GetReportedUploadBufferSpace(), (uploadState == uploadOK) ? 0 : 1);
}
Exemple #7
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;
}