ข้ามไปยังเนื้อหาหลัก

Telpo C9D Cash Drawer

This page records the hardware details found on the Android POS terminal used for cash drawer integration.

Verified device​

Checked over ADB on 2026-07-08.

FieldValue
ADB serialA65C009P00400034
ManufacturerTelpo
Android modelC9D
Android version14
Build display idC9D_A14_V1.1.3_202603250221

The device may be referred to operationally as CPOS TH C9PD, but Android reports the hardware as Telpo C9D.

Installed helper packages​

Relevant packages found on the terminal:

PackageNotes
com.cpos.helperInstalled helper app. APK strings identify it as Telpo Drawer Helper.
com.telpo.omcserviceTelpo privileged system service.
th.co.boonsiri.posterminalPOS terminal app.
com.boonsiri.printerconfigPrinter configuration app/package with Android PrintService and PrinterContentProvider.

com.cpos.helper was installed from Files (com.google.android.apps.nbu.files) and reports version 1.1.1.

com.boonsiri.printerconfig reports version 1.0.0, declares com.boonsiri.printerconfig.READ_PRINTERS, and exposes:

  • com.boonsiri.printerconfig/.print.BoonsiriPrintService
  • com.boonsiri.printerconfig/.provider.PrinterContentProvider
  • provider authority com.boonsiri.printerconfig.provider

Verified USB peripherals​

adb -s A65C009P00400034 shell dumpsys usb found two USB peripherals.

Receipt printer​

FieldValue
USB path/dev/bus/usb/001/005
ManufacturerICOD
ProductICOD_Thermal_Printer
Vendor ID1155
Product ID30016
USB class7 (Printer)
Interface class7
Interface subclass1
Interface protocol2
Serial number000000000005920ca2
OUT endpointaddress 3, max packet size 64
IN endpointaddress 129, max packet size 64

The USB settings also register com.cpos.helper/.MainActivity for attached USB devices with class 7, so the Telpo drawer helper is expected to handle USB printer attach events.

Scanner / keyboard wedge​

FieldValue
USB path/dev/bus/usb/001/003
ManufacturerHID .
ProductDECODER-KEYBOARD
Vendor ID7554
Product ID23712
USB classHID class 3

This device appears as a keyboard-style scanner and should not be treated as the receipt printer.

Drawer capabilities found​

The helper APK contains cash drawer specific code and text, including:

  • Telpo Drawer Helper
  • com.cpos.helper.Drawer
  • com.cpos.helper.PrinterProxyService
  • com.cpos.helper.TEST_DRAWER
  • ACTION_TEST_DRAWER
  • Drawer Proxy
  • Drawer Mode
  • MODE_TELPO
  • MODE_USB
  • MODE_PRINTER
  • Telpo only (GPIO/SDK)
  • USB only (drawer on printer)
  • Auto (printer + Telpo)
  • Standard printer (drawer connected to printer)

The APK also includes Telpo SDK classes relevant to direct drawer control:

  • com.telpo.tps550.api.moneybox.MoneyBox
  • com.common.apiutil.moneybox.MoneyBox
  • com.common.apiutil.util.TelpoLib

Native libraries found in the helper APK:

  • libtelpo-lib.so
  • libserial-util.so
  • libusb-util.so

libtelpo-lib.so references /dev/telpo_gpio and exposes JNI symbol Java_com_common_apiutil_util_TelpoLib_ioctlControlJNI, which suggests the Telpo SDK can drive GPIO-level drawer control.

Printer drawer kick command​

The helper APK also contains an ESC/POS drawer kick path for drawers connected through a receipt printer.

Command bytes found:

1B 70 00 19 FA

Equivalent byte array:

[0x1b, 0x70, 0x00, 0x19, 0xfa]

Send these bytes directly to a printer only when the cash drawer is connected to that printer's drawer port, usually RJ11/RJ12. Sending the same bytes to the CPOS Helper's localhost proxy is a separate path: Telpo mode interprets them as a MoneyBox command instead of forwarding them to a printer.

For the verified ICOD USB thermal printer, raw USB ESC/POS output should target the printer device, not the scanner:

  • expected target product: ICOD_Thermal_Printer
  • expected USB path at time of inspection: /dev/bus/usb/001/005
  • expected OUT endpoint: address 3

Verified helper interface and app integration​

Rechecked on 2026-10-21 on the same C9D, with com.cpos.helper version 1.1.1 (version code 3). The helper APK and running service confirm:

  • PrinterProxyService is not exported. Other apps cannot invoke its com.cpos.helper.TEST_DRAWER service action directly.
  • The running service listens at 127.0.0.1:9100, not a LAN interface.
  • It parses ESC/POS drawer commands. In Telpo only (GPIO/SDK) mode it strips the printer command and calls com.common.apiutil.moneybox.MoneyBox.open(1, pulseMs).
  • Automatic (printer + Telpo) also calls MoneyBox but forwards the printer bytes. Standard printer mode does not call MoneyBox. For a drawer wired directly to this POS, select Telpo only (GPIO/SDK) in CPOS Helper.
  • The helper initializes the Telpo SDK in its Application and clamps MoneyBox pulses to 120–800 ms. A direct /dev/telpo_gpio path was not present on this device; the library string alone is not a usable app integration contract.

An ADB-forwarded connection to this proxy was used to send a single 1B 70 00 19 FA command per test. The operator reported a drawer response and requested another test after unlocking the drawer. A successful socket write confirms delivery to the helper; its protocol has no physical-open acknowledgement.

Terminal uses CashDrawerModule in android/app/src/main/java/th/co/boonsiri/posterminal/cashdrawer and the TypeScript wrapper src/native/cashDrawer.ts. It supports the verified Telpo C9D when CPOS Helper is installed and enabled. The helper must already be running; the module uses only its localhost TCP interface. No printer fallback, SDK binary copying, root access, or exported helper service is needed.

StorefrontOrderPaymentStep sends a command after payOrder succeeds, before the detail refresh, and when the current waiting order becomes CONFIRMED through a server/QR update. Entering an already-confirmed order does not send a command. Each order is requested once per mounted payment flow, and native code rejects overlapping requests and suppresses pulses less than 1.5 seconds apart. Unsupported devices skip this action. A connection failure reports the drawer problem separately without resubmitting payment or automatically retrying a pulse.

Verification uses mocked payment APIs; no real financial transaction is needed to test the native drawer module on the connected terminal.

After installing the updated debug build on this C9D, calling the app's openCashDrawer() wrapper twice concurrently returned [true, false]: one command was sent through the native socket, and the immediate duplicate was suppressed. Terminal typecheck, 56 payment/native-wrapper tests, Kotlin compile, and Android build/install passed. This test did not create a payment transaction.

Safety notes​

  • Testing the command can physically open the drawer.
  • Ask the operator before running drawer tests on a live terminal.
  • Avoid repeated rapid pulses. Add debounce/rate limiting in app code.
  • Do not assume every POS terminal has the same helper app or GPIO path. Check the Android model and installed packages before enabling direct Telpo mode.

Useful ADB commands​

Identify the connected POS device:

adb devices
adb -s A65C009P00400034 shell getprop ro.product.manufacturer
adb -s A65C009P00400034 shell getprop ro.product.model
adb -s A65C009P00400034 shell getprop ro.build.display.id
adb -s A65C009P00400034 shell getprop ro.build.version.release

Inspect helper packages:

adb -s A65C009P00400034 shell pm list packages
adb -s A65C009P00400034 shell dumpsys package com.cpos.helper
adb -s A65C009P00400034 shell pm path com.cpos.helper

Inspect printer and scanner USB devices:

adb -s A65C009P00400034 shell dumpsys usb
adb -s A65C009P00400034 shell dumpsys package com.boonsiri.printerconfig