Разработка мобильного приложения для управления 3D-принтером

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Разработка мобильного приложения для управления 3D-принтером
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Разработка мобильного приложения для управления 3D-принтером

Большинство современных 3D-принтеров на Marlin или Klipper прошивке управляются через OctoPrint или Moonraker — REST API + WebSocket поверх G-code. Задача мобильного приложения: загрузить G-code файл, запустить печать, следить за температурами и прогрессом, смотреть в веб-камеру и останавливать при проблемах. Всё это — уже решённые задачи на уровне API, основная сложность в UX и надёжной обработке нестабильного WiFi-соединения (принтер в мастерской, телефон — где угодно).

OctoPrint API: основные эндпоинты

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" для немедленного старта
    ): 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 через WebSocket

Температуры и прогресс — через OctoPrint WebSocket (/sockjs/websocket). События приходят каждые 1-2 секунды:

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) {
                    // Авторизация через первый 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 {
        // Типы событий: "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
        }
    }
}

Камера: MJPEG-стрим

OctoPrint транслирует MJPEG через /webcam/?action=stream. Coil и Glide не умеют MJPEG — нужен специальный компонент:

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 маркер конца (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) как альтернатива

Принтеры на Klipper используют Moonraker API — более современный REST + WebSocket (/websocket с JSON-RPC). Концепции те же, эндпоинты другие: /printer/objects/query для состояния, /printer/gcode/script для G-code команд, Fluidd/Mainsail как веб-интерфейс.

Загрузка большого G-code файла (100+ MB) через Moonraker с прогрессом:

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();
  // Прогресс по Content-Length и bytes received из stream
}

Разработка мобильного приложения для управления 3D-принтером (OctoPrint/Moonraker): 4–6 недель. Поддержка нескольких принтеров, исторические данные температур и уведомления о завершении: 7–10 недель. Стоимость рассчитывается индивидуально.