3D Printer Control Mobile App Development

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
3D Printer Control Mobile App Development
Medium
~1-2 weeks
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Developing a Mobile App for 3D Printer Control

Most modern 3D printers running Marlin or Klipper firmware are controlled through OctoPrint or Moonraker—REST API + WebSocket on top of G-code. The mobile app task: upload G-code file, start print, monitor temperatures and progress, watch the webcam stream, and stop if issues arise. All of this is already solved at the API level; the main complexity lies in UX and robust handling of unstable WiFi connections (printer in the workshop, phone anywhere).

OctoPrint API: Core Endpoints

interface OctoPrintApi {
    @GET("api/printer")
    suspend fun getPrinterState(): PrinterState

    @GET("api/job")
    suspend fun getCurrentJob(): JobInfo

    @POST("api/job")
    suspend fun controlJob(@Body command: JobCommand): Response<Unit>

    @GET("api/files/{location}")
    suspend fun getFiles(@Path("location") location: String = "local"): FilesResponse

    @Multipart
    @POST("api/files/{location}")
    suspend fun uploadFile(
        @Path("location") location: String,
        @Part file: MultipartBody.Part,
        @Part("print") print: RequestBody,  // "true" for immediate start
    ): UploadResponse

    @POST("api/printer/command")
    suspend fun sendGCode(@Body command: GCodeCommand): Response<Unit>
}

data class PrinterState(
    val temperature: TemperatureState,
    val state: StateFlags,
)

data class TemperatureState(
    val tool0: ToolTemp,
    val bed: ToolTemp,
)

data class ToolTemp(
    val actual: Double,
    val target: Double,
    val offset: Double,
)

Real-time via WebSocket

Temperatures and progress arrive through OctoPrint WebSocket (/sockjs/websocket). Events come every 1-2 seconds:

class OctoPrintSocket(private val baseUrl: String, private val apiKey: String) {
    fun observe(): Flow<OctoPrintEvent> = callbackFlow {
        val client = OkHttpClient()
        val ws = client.newWebSocket(
            Request.Builder().url("ws://$baseUrl/sockjs/websocket")
                .header("X-Api-Key", apiKey).build(),
            object : WebSocketListener() {
                override fun onOpen(webSocket: WebSocket, response: Response) {
                    // Auth via first message
                    webSocket.send("""{"auth": "$apiKey"}""")
                }

                override fun onMessage(webSocket: WebSocket, text: String) {
                    val event = parseEvent(text)
                    trySend(event)
                }
            }
        )
        awaitClose { ws.close(1000, null) }
    }

    private fun parseEvent(json: String): OctoPrintEvent {
        // Event types: "current", "history", "event", "plugin"
        val root = JsonParser.parseString(json).asJsonObject
        return when {
            root.has("current") -> OctoPrintEvent.Current(
                parsePrinterState(root["current"].asJsonObject))
            root.has("event") -> OctoPrintEvent.PrintEvent(
                root["event"].asJsonObject["type"].asString)
            else -> OctoPrintEvent.Unknown
        }
    }
}

Camera: MJPEG Stream

OctoPrint broadcasts MJPEG via /webcam/?action=stream. Coil and Glide don't support MJPEG—a specialized component is needed:

class MjpegStream(private val url: String) {
    fun frames(): Flow<Bitmap> = flow {
        val connection = URL(url).openConnection() as HttpURLConnection
        val inputStream = BufferedInputStream(connection.inputStream)
        val buffer = ByteArrayOutputStream()

        while (true) {
            val byte = inputStream.read()
            if (byte == -1) break

            buffer.write(byte)
            val data = buffer.toByteArray()

            // JPEG end marker (FF D9)
            if (data.size >= 2 &&
                data[data.size - 2] == 0xFF.toByte() &&
                data[data.size - 1] == 0xD9.toByte()) {
                val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
                if (bitmap != null) emit(bitmap)
                buffer.reset()
            }
        }
    }.flowOn(Dispatchers.IO)
}

Moonraker (Klipper) as Alternative

Klipper-based printers use Moonraker API—a more modern REST + WebSocket (/websocket with JSON-RPC). The concepts are the same, endpoints differ: /printer/objects/query for state, /printer/gcode/script for G-code commands, Fluidd/Mainsail as web interfaces.

Uploading large G-code files (100+ MB) via Moonraker with progress:

Future<void> uploadGCode(File file, void Function(double) onProgress) async {
  final stream = http.ByteStream(file.openRead());
  final length = await file.length();
  final request = http.MultipartRequest('POST',
      Uri.parse('$baseUrl/server/files/upload'));
  request.files.add(http.MultipartFile('file', stream, length,
      filename: file.path.split('/').last));

  final response = await request.send();
  // Progress tracked via Content-Length and bytes received from stream
}

Developing a mobile app for 3D printer control (OctoPrint/Moonraker): 4–6 weeks. Multi-printer support, temperature history, and completion notifications: 7–10 weeks. Cost is individually quoted.