Thursday, June 25, 2026

Menelpon keluar negeri berdasarkan operator dan NATO phonetic alphabet

Menelpon keluar negeri berdasarkan operator 

  1.  telkomsel/by.u
    1. 01017+[nomor_lengkap] tarif Rp. 350 per menit terbatas negara: Australia, Bangladesh, Brunei Darussalam, China, Hong Kong, India, Malaysia, Singapura, Korea Selatan, Thailand, dan Amerika Serikat/Kanada (tidak termasuk destinasi Hawaii)
    2. 007+[nomor_lengkap] tarif Rp. 4.550 per menit
  2. indosat im3
    1. 001+[nomor_lengkap] atau 008+[nomor_lengkap] tarif cek https://im3.id/portal/id/psinternationalcallandsms contoh australia Rp. 5.000 per menit.
    2. 01016+[nomor_lengkap] tarif cek https://im3.id/portal/id/psinternationalcallandsms contoh australia Rp. 1.500 per menit.
  3. xl (tidak diinformasikan secara resmi di xl.co.id
    • 01000+[nomor_lengkap] atau 01017 +[nomor_lengkap], memerlukan paket Nelpon Internasional XL
  4. three/3
    1. 001+[nomor_lengkap] atau 008+[nomor_lengkap], memerlukan paket Paket Nelpon Luar Negeri, contoh australia Rp. 7.350 per menit 
    2. 01016+[nomor_lengkap], memerlukan paket Paket Nelpon Luar Negeri, contoh australia Rp. 1.500 per menit.  
    3. paket yang tersedia https://tri.co.id/nelpon-luar-negeri
      1. Nelpon Luar Negeri     30     1 Hari     30 Menit
      2. Nelpon Luar Negeri     100     30 Hari     100 Menit 

 

NATO phonetic alphabet:

  1. A – Alfa
  2. B – Bravo
  3. C – Charlie
  4. D – Delta
  5. E – Echo
  6. F – Foxtrot
  7. G – Golf
  8. H – Hotel
  9. I – India
  10. J – Juliett
  11. K – Kilo
  12. L – Lima
  13. M – Mike
  14. N – November
  15. O – Oscar
  16. P – Papa
  17. Q – Quebec
  18. R – Romeo
  19. S – Sierra
  20. T – Tango
  21. U – Uniform
  22. V – Victor
  23. W – Whiskey
  24. X – X-ray
  25. Y – Yankee
  26. Z – Zulu  

 

ETLE dan stnk terblokir saat perpanjangan

Sebelum perpanjangan stnk coba cek dulu, apakah kendaraan di blok terkait etle (Electronic Traffic Law Enforcement). jangan sampai di samsat baru buka blokiran ya, lama banget. 

Siapkan 

  1. Nomor kendaraan
  2. Nomor kerangka kendaraan
  3. Nomor mesin kendaraan

Buka internet melalui browser lalu cari "ETLE PMJ" melalui mesin pencari. ini link-nya https://etle-pmj.id/ , namun bisa berubah tergantung kondisi.

Masuk menu cek data, dan masukan data yang telah disiapkan. bila kendaraan kamu terkena etle, pastikan itu memang kendaraan milik anda. bila benar anda bisa melakukan konfirmasi. bila tidak benar anda bisa menyanggahnya.

Bila kendaraan terkena etle saat konfirmasi anda akan diminta melengkapi data pribadi untuk dapat dihubungi. berikan data yang benar. Setelah itu anda akan menerima surat perintah bayar dengan nomor "BRIVA" yang berupa 15 angka. Lakukan deposit denda melalui bank bri atau aplikasi bri. Dari bank lain, jumlah tidak muncul. setelah pembayaran, blokir stnk terbuka. 

Note: pastikan anda telah membayar semua pelanggaran yang tertangkap etle.

Setelah dibayar, akan muncul konfirmasi dan anda akan menerima pesan tanggal sidang dan "No Blanko Tilang". 

melalui browser cari "ETLE kejaksaan" atau https://tilang.kejaksaan.go.id/be/ untuk mengecek sidang anda.

setelah tanggal sidang anda bisa melihat besaran denda tilang yang dibebankan ke anda. bisa kurang atau lebih bayar tergantung putusan sidang.  bila lebih bayar, ada 2 pilihan, pengambilan tunai atau transfer ke bank bri.

Wednesday, June 17, 2026

Android java: migrate build to gradle version catalog

create a new gradle catalog, project -> gradle -> new -> Version Catalog, it will prompt "lib" and press enter.

fill libs.version.toml with agp version


[versions]
agp = "9.2.1"
appcompat = "1.7.1"
material = "1.14.0"
constraintlayout = "2.2.1"
junit = "4.13.2"
androidx-junit = "1.3.0"
espresso-core = "3.7.0"
play-services-ads-lite = "25.0.0"

[libraries]
appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
material = { module = "com.google.android.material:material", version.ref = "material" }
constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }

junit4 = { module = "junit:junit", version.ref = "junit" }
androidx-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-junit" }
espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso-core" }

play-services-ads-lite = { module = "com.google.android.gms:play-services-ads-lite", version.ref = "play-services-ads-lite" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }

agp in [version] and [plugin] must exist.

edit build.gradle.kts

change


dependencies {

    implementation("androidx.appcompat:appcompat:1.7.0")
    implementation("com.google.android.material:material:1.12.0")
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.2.1")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
    implementation("com.google.android.gms:play-services-ads-lite:23.3.0")
}

 to


dependencies {

    implementation(libs.appcompat)
    implementation(libs.material)
    implementation(libs.constraintlayout)

    implementation(libs.play.services.ads.lite)

    testImplementation(libs.junit4)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.espresso.core)
}

Synchronize project and change


plugins {
    id("com.android.application")
}

to


plugins {
    alias(libs.plugins.android.application)
} 



Wednesday, June 10, 2026

Java: reading config.conf file

example config.conf


# http and https ports configuration
http_port = 48001
https_port = 48001

# printer port
printer_port=/dev/rfcomm0
# printer size
printer_size=80mm

java code


    // configuration file config.conf
    static final String linux_file_path = "/etc/dddtescpos/config.conf";
    static final String file_path = "./config.conf";

    public static String printer_port = null;
    public static String printer_size = null;
    
    public static int http_port = -1;
    public static int https_port = -1;
    
    public static void readConfig() {
        Path configFile = Paths.get(linux_file_path);
        
        if (Files.notExists(configFile)) {
            configFile = Paths.get(file_path);
        }
        
        // comment in config file will # or !
        Properties props = new Properties();

        try (InputStream input = Files.newInputStream(configFile)) {
            props.load(input);
        
            printer_port = props.getProperty("printer_port");
            printer_size = props.getProperty("printer_size");
            if (printer_size == null || printer_size.isBlank()) {
                printer_size = "80mm";   // default
            } else {
                printer_size = printer_size.trim().toLowerCase();

                if (!printer_size.equals("58mm")
                        && !printer_size.equals("80mm")) {
                    printer_size = "80mm";   // default for invalid value
                }
            }


            String tmpPort = props.getProperty("http_port","48001");
            try {
                int intTmpPort = Integer.parseInt(tmpPort); 
                if (intTmpPort<48000 || intTmpPort>65535)
                    intTmpPort = 48001;
                    http_port = intTmpPort;
            } catch (NumberFormatException ex) {
                http_port = 48001;
            }
            tmpPort = props.getProperty("https_port","48002");
            try {
                int intTmpPort = Integer.parseInt(tmpPort); 
                if (intTmpPort<48000 || intTmpPort>65535)
                    intTmpPort = 48002;
                https_port = intTmpPort;
            } catch (NumberFormatException ex) {
                https_port = 48002;
            }
            // if ports hava equal value, set default
            if (http_port == https_port) {
                http_port = 48001;
                https_port = 48002;
            }
        } catch (IOException ex) {
            System.out.println("No Configuration file found");
            http_port = 48001;
            https_port = 48002;            
        }
        
    }

 

Monday, June 8, 2026

Java: http and https (self sign certificate)

install mkcert


# apt install mkcert

go to root of netbeans project and create self sign certificate


$ mkcert localhost
Created a new local CA 💥
Note: the local CA is not installed in the system trust store.
Note: the local CA is not installed in the Firefox and/or Chrome/Chromium trust store.
Run "mkcert -install" for certificates to be trusted automatically ⚠️

Created a new certificate valid for the following names 📜
 - "localhost"

The certificate is at "./localhost.pem" and the key at "./localhost-key.pem" ✅

It will expire on 8 September 2028 🗓

Convert to PKCS 12


$ openssl pkcs12 -export \
  -in localhost.pem \
  -inkey localhost-key.pem \
  -out localhost.p12 \
  -name localhost
Enter Export Password:
Verifying - Enter Export Password:

main java code


/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 */

package com.dedetok.ddtescpos;

import com.alibaba.fastjson2.JSONObject;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsExchange;
import com.sun.net.httpserver.HttpsServer;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;


/**
 *
 * @author dedetok
 */
public class DdtEscPos {

    final static String serviceString = "DdtEscPos";
    final static String serviceVersion = "1.0";
    
    public static void main(String[] args) {
        System.out.println("DdtEscPos reading configuration file");
        MyController.readConfig(); // if configuration not available, use hard code config
        
        System.out.println(serviceString+" "+serviceVersion);
        
        // ================= 
        try {
            HttpServer httpServer = createHttpService(MyController.http_port);
            HttpsServer httpsServer = createHttpsService(MyController.https_port);
            
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                System.out.println("Stopping HTTP & HTTPS server...");
                httpServer.stop(5); // stop 5 second
                System.out.println("HTTP server stopped");
                httpsServer.stop(5); // stop 5 second
                System.out.println("HTTPS server stopped");

            }));
            httpServer.start();
            System.out.println("HTTP server running on http://localhost:" + MyController.http_port);
            httpsServer.start();
            System.out.println("HTTPS server running on http://localhost:" + MyController.https_port);

        } catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException ex) {
            System.getLogger(DdtEscPos.class.getName()).log(System.Logger.Level.ERROR, (String) null, ex);
        }
    }

    /*
     * create http service in httpPort
     */
    static HttpsServer createHttpsService(int httpsPort) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
        // Load PKCS12 keystore
        char[] password = "escpos".toCharArray();
        KeyStore ks = KeyStore.getInstance("PKCS12");
        try (FileInputStream fis = new FileInputStream("localhost.p12")) {
            ks.load(fis, password);
        }

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        
        kmf.init(ks, password);

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);

        // Create HTTPS server
        HttpsServer httpsServer =
                HttpsServer.create(
                        new InetSocketAddress("localhost", httpsPort),
                        0);        
    
        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
        
        // Register endpoints
        httpsServer.createContext("/", DdtEscPos::handleHttpRequest);
        httpsServer.createContext("/printjson", DdtEscPos::handlePrintJson);        
        
        return httpsServer;
    }
    
    /*
     * create http service in httpPort
     */
    static HttpServer createHttpService(int httpPort) throws IOException {
        HttpServer httpServer =
                HttpServer.create(new InetSocketAddress("localhost", httpPort), 0);
        
        httpServer.createContext("/", DdtEscPos::handleHttpRequest);
        httpServer.createContext("/printjson", DdtEscPos::handlePrintJson);
        return httpServer;
    }

    /*
     * handling /
     */
    static void handleHttpRequest(HttpExchange exchange) throws IOException {
        // CORS
        exchange.getResponseHeaders().add(
                "Access-Control-Allow-Origin", "*");

        exchange.getResponseHeaders().add(
                "Access-Control-Allow-Headers",
                "Content-Type, Authorization");

        exchange.getResponseHeaders().add(
        "Access-Control-Allow-Methods",
        "GET, POST, OPTIONS");

        if ("OPTIONS".equalsIgnoreCase(exchange.getRequestMethod())) {
            exchange.sendResponseHeaders(204, -1);
            return;
        }
        
        // UTF-8 text response
        exchange.getResponseHeaders().add(
                "Content-Type",
                "text/plain; charset=UTF-8");
        
        String response = infoService(exchange).toString();

        byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8);

        exchange.sendResponseHeaders(200, responseBytes.length);

        
        try (OutputStream os = exchange.getResponseBody()) {
            os.write(responseBytes);
        }
        System.out.println("Servicing client done"); // debug
    }

    /*
     * handling /printjson
     */
    static void handlePrintJson(HttpExchange exchange) throws IOException {
        // CORS
        exchange.getResponseHeaders().add(
                "Access-Control-Allow-Origin", "*");

        exchange.getResponseHeaders().add(
                "Access-Control-Allow-Headers",
                "Content-Type, Authorization");

        exchange.getResponseHeaders().add(
        "Access-Control-Allow-Methods",
        "GET, POST, OPTIONS");

        if ("OPTIONS".equalsIgnoreCase(exchange.getRequestMethod())) {
            exchange.sendResponseHeaders(204, -1);
            return;
        }
        
        // UTF-8 text response
        exchange.getResponseHeaders().add(
                "Content-Type",
                "text/plain; charset=UTF-8");
        // get json from request
        // Read request body
        String requestBody;
        try (InputStream is = exchange.getRequestBody()) {
            requestBody = new String(is.readAllBytes(), StandardCharsets.UTF_8);
            // Parse JSON
            // Parse JSON and process
            JSONObject json = JSONObject.parseObject(requestBody);

            JSONObject responseJson = infoService(exchange);
            
            try {
                MyController.printJson(json.toString());


                responseJson.put("status", "printing done");
            } catch (IOException ex) {
                responseJson.put("status", "printing fail");
                responseJson.put("error", ex.getMessage());
                
            }
            
            byte[] bytes =
                responseJson.toString().getBytes(StandardCharsets.UTF_8);

            exchange.sendResponseHeaders(200, bytes.length);
            OutputStream os = exchange.getResponseBody();
            os.write(bytes);
            os.flush();

        }
    }
    
    /* 
     * standard info response 
     */
    static JSONObject infoService(HttpExchange exchange) {
        JSONObject jsonObj = new JSONObject();
        
        jsonObj.put("version", serviceVersion);
        jsonObj.put("service", serviceString);
        jsonObj.put("status", "running");
        String host = exchange.getLocalAddress().getHostString();
        int port = exchange.getLocalAddress().getPort();

        String scheme = (exchange instanceof HttpsExchange)
        ? "https://"
        : "http://";
        
        String baseUrl = scheme + host + ":" + port;
        jsonObj.put("endpoint",baseUrl+"/printjson");
        
        return jsonObj;
    }
}

to run service


$ java -jar target/DdtEscPos-1.0.jar 
Hello World!
HTTP server running on http://localhost:50001
HTTPS server running on https://localhost:50002
Serviing client done
Serviing client done

using curl to send json to print http


$ curl -H "Content-Type: application/json" \
     -d @exampleescpos.json \
     http://localhost:50001/printjson

https


$ curl -k \
  -H "Content-Type: application/json" \
  -d @exampleescpos.json \
  https://localhost:50002/printjson

or 


$ curl --insecure \
  -H "Content-Type: application/json" \
  -d @exampleescpos.json \
  https://localhost:50002/printjson

Credit: esc html using https://www.freeformatter.com/html-escape.html 

Saturday, June 6, 2026

Java: using thermal printer 6106 - 80mm esc/pos java in debian 13 bluetooth

Install bluetooth software


$ apt install firmware-misc-nonfree bluez bluez-tools blueman screen

linux user groups: bluetooth, lp, netdev, sudo, and plugdev

add linux user to group


# usermod -aG sudo username

check your bluetooth adapter has been recognize by debian


$ lsusb
...
Bus 001 Device 003: ID 0489:e0cd Foxconn / Hon Hai MediaTek Bluetooth Adapter
...

pair your device, if you don't hook it in boot, you need to rebind after boot. 


$ bluetoothctl pair 86:67:7A:1D:C2:E3
Attempting to pair with 86:67:7A:1D:C2:E3
[CHG] Device 86:67:7A:1D:C2:E3 Connected: yes
Failed to pair: org.bluez.Error.AuthenticationFailed

using bluetoothctl to handle bluetooth password


$ bluetoothctl
Agent registered
[bluetoothctl]> agent KeyboardOnly
Agent is already registered
[bluetoothctl]> default-agent
Default agent request successful
[bluetoothctl]> scan on
SetDiscoveryFilter success
Discovery started
[CHG] Controller BC:F4:D4:12:4C:28 Discovering: yes
[NEW] Device 4D:F9:CE:48:C4:1B 4D-F9-CE-48-C4-1B
[NEW] Device 62:FE:E1:08:CD:73 62-FE-E1-08-CD-73
[NEW] Device 6D:AC:09:7B:A7:F3 6D-AC-09-7B-A7-F3
[NEW] Device 86:67:7A:1D:C2:E3 RPP02N
[bluetoothctl]> pair 86:67:7A:1D:C2:E3
Attempting to pair with 86:67:7A:1D:C2:E3
[CHG] Device 86:67:7A:1D:C2:E3 Connected: yes
[CHG] Device 86:67:7A:1D:C2:E3 Bonded: yes
[CHG] Device 86:67:7A:1D:C2:E3 Modalias: usb:v05ACp0239d0644
[CHG] Device 86:67:7A:1D:C2:E3 ServicesResolved: yes
[CHG] Device 86:67:7A:1D:C2:E3 Paired: yes
Pairing successful
[DEL] Device 6D:AC:09:7B:A7:F3 6D-AC-09-7B-A7-F3
[CHG] Device 86:67:7A:1D:C2:E3 ServicesResolved: no
[CHG] Device 86:67:7A:1D:C2:E3 Connected: no
[DEL] Device 4D:F9:CE:48:C4:1B 4D-F9-CE-48-C4-1B
[DEL] Device 62:FE:E1:08:CD:73 62-FE-E1-08-CD-73
[bluetoothctl]> trust 86:67:7A:1D:C2:E3
[CHG] Device 86:67:7A:1D:C2:E3 Trusted: yes
Changing 86:67:7A:1D:C2:E3 trust succeeded

busctl output


$ busctl introspect org.bluez /org/bluez/hci0/dev_86_67_7A_1D_C2_E3
NAME                                TYPE      SIGNATURE RESULT/VALUE                             FLAGS
org.bluez.Device1                   interface -         -                                        -
.CancelPairing                      method    -         -                                        -
.Connect                            method    -         -                                        -
.ConnectProfile                     method    s         -                                        -
.Disconnect                         method    -         -                                        -
.DisconnectProfile                  method    s         -                                        -
.Pair                               method    -         -                                        -
.Adapter                            property  o         "/org/bluez/hci0"                        emits-change
.Address                            property  s         "86:67:7A:1D:C2:E3"                      emits-change
.AddressType                        property  s         "public"                                 emits-change
.AdvertisingData                    property  a{yv}     -                                        emits-change
.AdvertisingFlags                   property  ay        -                                        emits-change
.Alias                              property  s         "RPP02N"                                 emits-change writable
.Appearance                         property  q         -                                        emits-change
.Blocked                            property  b         false                                    emits-change writable
.Bonded                             property  b         true                                     emits-change
.Class                              property  u         263808                                   emits-change
.Connected                          property  b         false                                    emits-change
.Icon                               property  s         "printer"                                emits-change
.LegacyPairing                      property  b         false                                    emits-change
.ManufacturerData                   property  a{qv}     -                                        emits-change
.Modalias                           property  s         "usb:v05ACp0239d0644"                    emits-change
.Name                               property  s         "RPP02N"                                 emits-change
.Paired                             property  b         true                                     emits-change
.RSSI                               property  n         -                                        emits-change
.ServiceData                        property  a{sv}     -                                        emits-change
.ServicesResolved                   property  b         false                                    emits-change
.Sets                               property  a{oa{sv}} -                                        emits-change
.Trusted                            property  b         true                                     emits-change writable
.TxPower                            property  n         -                                        emits-change
.UUIDs                              property  as        7 "00000001-0000-1000-8000-00805f9b34fb… emits-change
.WakeAllowed                        property  b         -                                        emits-change writable
org.freedesktop.DBus.Introspectable interface -         -                                        -
.Introspect                         method    -         s                                        -
org.freedesktop.DBus.Properties     interface -         -                                        -
.Get                                method    ss        v                                        -
.GetAll                             method    s         a{sv}                                    -
.Set                                method    ssv       -                                        -
.PropertiesChanged                  signal    sa{sv}as  -                                        -

bind to rfcomm (sudo), if you don't hook it in boot, you need to rebind after boot. if you already trust the printer, just bind it.


  # rfcomm bind rfcomm0 86:67:7A:1D:C2:E3

or with sudo


  $ sudo  rfcomm bind rfcomm0 86:67:7A:1D:C2:E3

your dev access point


$ ls /dev/ | grep rfcomm
rfcomm0

get your bluetooth device info


$ bluetoothctl info 86:67:7A:1D:C2:E3
Device 86:67:7A:1D:C2:E3 (public)
	Name: RPP02N
	Alias: RPP02N
	Class: 0x00040680 (263808)
	Icon: printer
	Paired: yes
	Bonded: yes
	Trusted: yes
	Blocked: no
	Connected: no
	LegacyPairing: no
	UUID: SDP                       (00000001-0000-1000-8000-00805f9b34fb)
	UUID: RFCOMM                    (00000003-0000-1000-8000-00805f9b34fb)
	UUID: L2CAP                     (00000100-0000-1000-8000-00805f9b34fb)
	UUID: Serial Port               (00001101-0000-1000-8000-00805f9b34fb)
	UUID: PnP Information           (00001200-0000-1000-8000-00805f9b34fb)
	UUID: Unknown                   (000018f0-0000-1000-8000-00805f9b34fb)
	UUID: Vendor specific           (e7810a71-73ae-499d-8c15-faa9aef0c3f2)
	Modalias: usb:v05ACp0239d0644

Optional: to let systemd handling pair device

create/edit bluetooth-printer.service (or any name you wish), at /etc/systemd/system/, e.g   /etc/systemd/system/bluetooth-printer.service.


[Unit]
Description=Bind Bluetooth Thermal Printer to rfcomm0
After=bluetooth.service
Requires=bluetooth.service

[Service]
Type=oneshot
ExecStart=/usr/bin/rfcomm bind rfcomm0 86:67:7A:1D:C2:E3
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

After that use systemd to handle pairing

  • sudo systemctl daemon-reload
  • sudo systemctl enable bluetooth-printer.service
  • sudo systemctl start bluetooth-printer.service
  • systemctl status bluetooth-printer.service 

you can try previous code https://dedetoknotes.blogspot.com/2026/06/java-using-thermal-printer-6106-80mm.html by change 

devicePath = "/dev/usb/lp1" 

to

devicePath = "/dev/rfcomm0" 

Credit: https://www.freeformatter.com/html-escape.html#before-output to esc html 

Monday, June 1, 2026

Java: using thermal printer 6106 - 80mm esc/pos java in debian 13 usb

insert your printer using usb cable


# lsusb
...
Bus 008 Device 002: ID 28e9:0289 GDMicroelectronics micro-printer
Bus 009 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
# dmesg
[   70.532011] usb 8-1: new full-speed USB device number 2 using xhci_hcd
[   70.688254] usb 8-1: New USB device found, idVendor=28e9, idProduct=0289, bcdDevice= 2.00
[   70.688270] usb 8-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[   70.688276] usb 8-1: Product: micro-printer
[   70.688282] usb 8-1: Manufacturer: GEZHI
[   70.688286] usb 8-1: SerialNumber: 000000000004
[   70.730721] usblp 8-1:1.0: usblp1: USB Bidirectional printer dev 2 if 0 alt 0 proto 2 vid 0x28E9 pid 0x0289
[   70.730783] usbcore: registered new interface driver usblp
use nl80211
# ls -al /dev/usb/
total 0
drwxr-xr-x  2 root root     80 May 31 14:31 .
drwxr-xr-x 20 root root   3840 May 31 14:31 ..
crw-------  1 root root 180, 0 May 31 14:30 hiddev0
crw-rw----  1 root lp   180, 1 May 31 14:31 lp1
# ls -al /dev/usb/lp1
crw-rw---- 1 root lp 180, 1 May 31 14:31 /dev/usb/lp1

we found the device known as usb lp1 i.e. /dev/usb/lp1. test to print something.


# printf '\x1b\x40Hello World\n\n\n' > /dev/usb/lp1

your printer should print "Hello World"

add your account or linux user as lp group 


# usermod -aG lp [username]

you need to sign out and re sign in, then try to print as [username]


$ printf '\x1b\x40Hello World\n\n\n' > /dev/usb/lp1

if everything work, now you can work as [username]. this is simple netbeans 30 - maven, to test your printer.

This is pom.xml for your project.


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.dedetok</groupId>
    <artifactId>EnumComPort</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.release>21</maven.compiler.release>
        <exec.mainClass>com.dedetok.enumcomport.EnumComPort</exec.mainClass>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.fazecast</groupId>
            <artifactId>jSerialComm</artifactId>
            <version>2.11.0</version>
            <type>jar</type>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.5.0</version>

                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>

                        <configuration>
                            <createDependencyReducedPom>false</createDependencyReducedPom>

                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.dedetok.enumcomport.EnumComPort</mainClass>
                                </transformer>
                            </transformers>

                        </configuration>
                    </execution>
                </executions>

            </plugin>

        </plugins>
    </build>
</project>

This is the java code


package com.dedetok.enumcomport;

import com.fazecast.jSerialComm.SerialPort;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 *
 * @author dedetok
 */
public class EnumComPort {

    public static void main(String[] args) throws IOException {
        System.out.println("Hello World!");
        System.out.println(System.getProperty("user.name"));
        Process p = Runtime.getRuntime().exec("id");
        p.getInputStream().transferTo(System.out);
        
        SerialPort[] ports = SerialPort.getCommPorts();

        if (ports.length == 0) {
            System.out.println("No serial ports detected.");
        }

        System.out.println("Available Serial Ports:");
        System.out.println("------------------------");

        for (SerialPort port : ports) {

            System.out.println("System Port Name : " + port.getSystemPortName());
            System.out.println("Descriptive Name: " + port.getDescriptivePortName());
            System.out.println("Port Description: " + port.getPortDescription());
            System.out.println("System Location : " + port.getSystemPortPath());
            System.out.println("------------------------");
        }
        
        String devicePath = "/dev/usb/lp1";
        // Open file in read-write mode for raw bidirectional access
        RandomAccessFile deviceFile = new RandomAccessFile(devicePath, "rw");
        FileDescriptor fd = deviceFile.getFD();
        
        try (OutputStream out = new FileOutputStream(fd)) {
            // ESC @ (initialize)
            out.write(new byte[]{0x1B, 0x40});

            out.write("Hello World\n".getBytes());

            // Feed
            out.write("\n\n".getBytes());

            // Cut
            out.write(new byte[]{0x1D, 0x56, 0x00});

            out.flush();
            out.close(); // NO NEED
        } catch (FileNotFoundException ex) {
            System.getLogger(EnumComPort.class.getName()).log(System.Logger.Level.ERROR, (String) null, ex);
        }
        System.out.println("End");
    }
}

In my test, you can run inside your netbeans, Run -> Build Project or Run -> Clean and Run Project. to run the jar, you go to project root and run like this


$ java -jar ./target/EnumComPort-1.0.jar 
Hello World!
[username]
uid=1000([username]) gid=1000([username]) groups=1000([username]),7(lp),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),33(www-data),44(video),46(plugdev),100(users),106(netdev),111(bluetooth),113(lpadmin),116(scanner),124(libvirt)
No serial ports detected.
Available Serial Ports:
------------------------
End

your printer should print "Hello World". "No serial ports" means, you can use com.fazecast.jSerialComm library for lp printer.

Credit: https://www.freeformatter.com/html-escape.html for free html escape