Bonrix 7-Inch Smart Retail Dynamic QR Code USB Portrait Display (Model: BEI-SRD-001-USB)

C# Example:


using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Management;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    internal class Program
    {
        static string RandomString(int length)
        {
            var random = new Random();
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            var str = new char[length];
            for (int i = 0; i < length; i++)
            {
                str[i] = chars[random.Next(chars.Length)];
            }
            return new string(str);
        }

        static string RandomNumber(int length)
        {
            var random = new Random();
            string number = "";
            for (int i = 0; i < length; i++)
                number += random.Next(0, 10).ToString();
            return number;
        }
        private static string GetVendorId(string portName)
        {
            try
            {
                using (var searcher = new ManagementObjectSearcher(
                    "SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(" + portName + ")%'"))
                {
                    foreach (var obj in searcher.Get())
                    {
                        string deviceId = obj["PNPDeviceID"]?.ToString();
                        if (deviceId != null)
                        {
                            var vidIndex = deviceId.IndexOf("VID_");
                            if (vidIndex >= 0)
                            {
                                return deviceId.Substring(vidIndex + 4, 4);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to get vendor ID: " + ex.Message);
            }
            return null;
        }
        static void Main(string[] args)
        {
            //Console.WriteLine(GetVendorId("COM3"));
            string[] portNames = SerialPort.GetPortNames();
            string selectedPort = null;
            foreach (string port in portNames)
            {
                string vendorId = GetVendorId(port);

                var knownVendors = new Dictionary
                    {
                        { "0483", "STM32" },
                        { "0403", "FTDI" },
                        { "10C4", "Silicon Labs CP210x" },
                        { "067B", "Prolific" },
                        { "1A86", "QinHeng CH340" },
                        { "16C0", "VOTI" }
                    };

                if (vendorId != null && knownVendors.ContainsKey(vendorId.ToUpper()))
                {
                    selectedPort = port;
                    break;
                }
            }
            if (selectedPort == null && portNames.Length > 0)
            {
                selectedPort = portNames[0];
            }

            int baudRate = 921600;     // Replace with appropriate baud rate

            using (SerialPort serialPort = new SerialPort(selectedPort, baudRate, Parity.None, 8, StopBits.One))
            {
                serialPort.Open();

                // Initialize commands dictionary
                var commands = new Dictionary
            {
                { "1", "welcome" },
                { "2", "final" },
                { "3", "to_pay" },
                { "4", "success" },
                { "5", "fail" },
                { "6", "cancel" },
                { "7", "billjson" },
                { "8", "newbill" },
                { "0", "exit" }
            };

                Console.WriteLine("Press '0' to Exit.");
                Console.WriteLine("Press '1' for Welcome Message.");
                Console.WriteLine("Press '2' for Final Invoice Message.");
                Console.WriteLine("Press '3' for To Pay QR.");
                Console.WriteLine("Press '4' for Payment Success Message.");
                Console.WriteLine("Press '5' for Payment Fail Message.");
                Console.WriteLine("Press '6' for Payment Cancel Message.");
                Console.WriteLine("Press '7' for Display Bill.");
                Console.WriteLine("Press '8' for Display Single Item.");

                while (true)
                {
                    Console.Write("Enter command number (0-8): ");
                    string choice = Console.ReadLine()?.Trim();

                    if (!commands.ContainsKey(choice))
                    {
                        Console.WriteLine("Invalid choice, try again.");
                        continue;
                    }

                    string commandKey = commands[choice];

                    if (commandKey == "exit")
                    {
                        Console.WriteLine("Exiting...");
                        break;
                    }

                    string command = "";

                    switch (commandKey)
                    {
                        case "welcome":
                            Console.Write("Enter company name: ");
                            string company = Console.ReadLine();
                            command = $"WelcomeScreen**{company}";
                            break;

                        case "final":
                            Console.Write("Enter total: ");
                            string total = Console.ReadLine();
                            Console.Write("Enter discount: ");
                            string discount = Console.ReadLine();
                            Console.Write("Enter tax: ");
                            string tax = Console.ReadLine();
                            Console.Write("Enter grand total: ");
                            string grandTotal = Console.ReadLine();
                            command = $"DisplayTotalScreen**{total}**{discount}**{tax}**{grandTotal}";
                            break;

                        case "to_pay":
                            Console.Write("Enter UPI string: ");
                            string upi = Console.ReadLine();
                            Console.Write("Enter amount: ");
                            string amt = Console.ReadLine();
                            Console.Write("Enter VPA: ");
                            string vpa = Console.ReadLine();
                            command = $"DisplayQRCodeScreen**{upi}**{amt}**{vpa}";
                            break;

                        case "success":
                        case "fail":
                        case "cancel":
                            Console.Write("Enter bank RRN (leave empty to generate): ");
                            string bankRrn = Console.ReadLine();
                            if (string.IsNullOrEmpty(bankRrn)) bankRrn = RandomNumber(10);

                            Console.Write("Enter Order ID (leave empty to generate): ");
                            string orderId = Console.ReadLine();
                            if (string.IsNullOrEmpty(orderId)) orderId = "ORD" + RandomNumber(6);

                            Console.Write("Enter Date (dd-MM-yyyy, leave empty for today): ");
                            string date = Console.ReadLine();
                            if (string.IsNullOrEmpty(date)) date = DateTime.Now.ToString("dd-MM-yyyy");

                            Console.Write("Enter Amount: ");
                            string amt2 = Console.ReadLine();

                            if (commandKey == "success")
                                command = $"DisplaySuccessQRCodeScreen**{bankRrn}**{orderId}**{date}**{amt2}";
                            else if (commandKey == "fail")
                                command = $"DisplayFailQRCodeScreen**{bankRrn}**{orderId}**{date}**{amt2}";
                            else
                                command = $"DisplayCancelQRCodeScreen**{bankRrn}**{orderId}**{date}**{amt2}";
                            break;

                        case "billjson":
                            string json = "{\"storeInfo\": {\"storeName\": \"Test Store\",\"address\": \"123 Test Street\",\"phone\": \"123-456-7890\",\"gstin\": \"TEST123456\"},\"billInfo\": {\"billNo\": \"1\",\"date\": \"2025-02-17\",\"time\": \"12:00\",\"cashier\": \"Test Cashier\"},\"customerInfo\": {\"customerName\": \"John Doe\",\"customerPhone\": \"987-654-3210\"},\"items\": [{\"itemName\": \"Item 1\",\"quantity\": 2,\"pricePerUnit\": 10.0,\"total\": 20.0},{\"itemName\": \"Item 2\",\"quantity\": 1,\"pricePerUnit\": 15.0,\"total\": 15.0},{\"itemName\": \"Item 3\",\"quantity\": 1,\"pricePerUnit\": 15.0,\"total\": 15.0}],\"totals\": {\"subTotal\": 50.0,\"tax\": 5.0,\"discount\": 0.0,\"totalAmount\": 55.0,\"amountPaid\": 55.0,\"paymentMethod\": \"Cash\"},\"footer\": {\"message\": \"Thank you for testing!\",\"website\": \"www.teststore.com\"}}";
                            command = $"billjson**{json}";
                            break;
                        case "newbill":
                            Console.Write("Enter item name: ");
                            string itemName = Console.ReadLine();
                            Console.Write("Enter item code: ");
                            string itemCode = Console.ReadLine();
                            Console.Write("Enter price: ");
                            string price = Console.ReadLine();
                            Console.Write("Enter quantity: ");
                            string qty = Console.ReadLine();
                            Console.Write("Enter unit: ");
                            string unit = Console.ReadLine();
                            Console.Write("Enter subtotal: ");
                            string subtotal = Console.ReadLine();
                            Console.Write("Enter grand total: ");
                            string grandTotal2 = Console.ReadLine();
                            command = $"newbill**{itemName}**{itemCode}**{price}**{qty}**{unit}**{subtotal}**{grandTotal2}";
                            break;
                    }

                    serialPort.WriteLine(command);
                    Console.WriteLine($"Sent: {command}");
                }

                serialPort.Close();
            }
        }
    }
}


  

Python Example:


import serial
import time
from serial.tools import list_ports

VENDOR_ID  = 0x1A86  # CH340
PRODUCT_ID = 0x7523  # CH340

class SMDController:
    def __init__(self, port=None, baudrate=921600):
        """
        Initialize SMD Controller with serial communication.
        If 'port' is None, we'll try auto-detect via VID/PID.
        """
        self.port = port
        self.baudrate = baudrate
        self.serial_conn = None

        # Static commands that don't need user input
        self.static_commands = {
            1: "WelcomeScreen**bonrix",
            3: "DisplayFailQRCodeScreen**1234567890**ORD10594565**29-03-2023**10",
            4: "DisplayCancelQRCodeScreen**1234567890**ORD10594565**29-03-2023**10",
        }

    @staticmethod
    def find_port_by_vid_pid(vid, pid):
        """
        Scan available serial ports and return the first one matching VID/PID.
        Returns the device name (e.g., 'COM5' on Windows or '/dev/ttyUSB0' on Linux),
        or None if not found.
        """
        for p in list_ports.comports():
            # On most systems p.vid and p.pid exist; fall back to checking hwid if needed.
            if (getattr(p, "vid", None) == vid) and (getattr(p, "pid", None) == pid):
                return p.device
            # Fallback: parse HWID string if vid/pid attributes not populated
            if p.hwid:
                hwid = p.hwid.upper()
                if f"VID_{vid:04X}" in hwid and f"PID_{pid:04X}" in hwid:
                    return p.device
        return None

    def connect(self):
        """Establish serial connection"""
        try:
            self.serial_conn = serial.Serial(
                port=self.port,
                baudrate=self.baudrate,
                timeout=1,
                bytesize=serial.EIGHTBITS,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
            )
            # Optional: stabilize some CH340 boards on Windows
            self.serial_conn.reset_input_buffer()
            self.serial_conn.reset_output_buffer()
            print(f"Connected to {self.port} at {self.baudrate} baud")
            return True
        except serial.SerialException as e:
            print(f"Error connecting to {self.port}: {e}")
            return False

    def disconnect(self):
        """Close serial connection"""
        if self.serial_conn and self.serial_conn.is_open:
            self.serial_conn.close()
            print("Serial connection closed")

    def send_command(self, command):
        """Send command via serial connection"""
        if not self.serial_conn or not self.serial_conn.is_open:
            print("Error: Serial connection not established")
            return False

        try:
            command_with_newline = command + "\n"
            self.serial_conn.write(command_with_newline.encode("utf-8"))
            print(f"Command sent: {command}")

            time.sleep(0.1)
            if self.serial_conn.in_waiting:
                response = self.serial_conn.readline().decode("utf-8", "ignore").strip()
                if response:
                    print(f"Response: {response}")

            return True
        except Exception as e:
            print(f"Error sending command: {e}")
            return False

    def get_success_command(self):
        """Get success command with user input for amount"""
        try:
            amount = input("Enter amount in rupees (e.g., 10, 50, 100): ").strip()
            if not amount.isdigit():
                print("Invalid amount. Please enter a valid number.")
                return None
            return f"DisplaySuccessQRCodeScreen**1234567890**ORD10594565**29-03-2023**{amount}"
        except KeyboardInterrupt:
            print("\nOperation cancelled.")
            return None

    def get_qr_command(self):
        """Get QR code command with user input for UPI details"""
        try:
            upi_id = input("Enter UPI ID (e.g., 63270083167.payswiff@indus): ").strip()
            if not upi_id:
                print("UPI ID cannot be empty.")
                return None

            amount = input("Enter amount in rupees: ").strip()
            if not amount.isdigit():
                print("Invalid amount. Please enter a valid number.")
                return None

            merchant_name = input("Enter merchant name (e.g., Bonrix): ").strip() or "Bonrix"
            upi_url = f"upi://pay?pa={upi_id}&pn={merchant_name}&cu=INR&am={amount}"
            return f"DisplayQRCodeScreen**{upi_url}**{amount}**{upi_id}"
        except KeyboardInterrupt:
            print("\nOperation cancelled.")
            return None

    def execute_command(self, input_number):
        """Execute command based on input number"""
        if input_number in self.static_commands:
            return self.send_command(self.static_commands[input_number])
        if input_number == 2:
            cmd = self.get_success_command()
            return self.send_command(cmd) if cmd else False
        if input_number == 5:
            cmd = self.get_qr_command()
            return self.send_command(cmd) if cmd else False

        valid_inputs = list(self.static_commands.keys()) + [2, 5]
        print(f"Invalid input: {input_number}. Valid inputs are: {valid_inputs}")
        return False

    def show_menu(self):
        """Display available commands"""
        print("\n=== 7-inch SMD Controller ===")
        print("Available commands:")
        print("1. Welcome Screen")
        print("2. Success QR Code Screen (asks for amount)")
        print("3. Fail QR Code Screen")
        print("4. Cancel QR Code Screen")
        print("5. Payment QR Code Screen (asks for UPI ID, amount, merchant name)")
        print("0. Exit")
        print("================================")

def main():
    print("=== 7-inch SMD Controller Setup ===")

    # Auto-detect COM port by VID/PID
    auto_port = SMDController.find_port_by_vid_pid(VENDOR_ID, PRODUCT_ID)
    if auto_port:
        print(f"Auto-detected device: {auto_port} (VID=0x{VENDOR_ID:04X}, PID=0x{PRODUCT_ID:04X})")
        controller = SMDController(port=auto_port, baudrate=921600)
    else:
        print("No port matched the specified VID/PID.")
        # Show available ports to help user pick one
        ports = list(list_ports.comports())
        if not ports:
            print("No serial ports found. Please connect your device and try again.")
            return
        print("Available ports:")
        for p in ports:
            print(f"  - {p.device} | {p.description} | HWID={p.hwid}")
        # Fallback to manual input
        while True:
            try:
                com_port = input("Enter COM port (e.g., COM5 or /dev/ttyUSB0): ").strip()
                if com_port:
                    break
            except KeyboardInterrupt:
                print("\nExiting...")
                return
        controller = SMDController(port=com_port, baudrate=921600)

    print(f"Attempting to connect to {controller.port} at {controller.baudrate} baud...")
    if not controller.connect():
        print("Failed to connect. Please check:")
        print("1. Device is connected")
        print("2. Correct driver installed (CH340)")
        print("3. No other application is using the port")
        print("4. Permissions (on Linux: add user to 'dialout' or use udev rule)")
        return

    try:
        while True:
            controller.show_menu()
            try:
                user_input = input("\nEnter your choice (0-5): ").strip()
                if user_input == "0":
                    print("Exiting...")
                    break
                choice = int(user_input)
                if 1 <= choice <= 5:
                    controller.execute_command(choice)
                else:
                    print("Invalid choice. Please enter a number between 0-5.")
            except ValueError:
                print("Invalid input. Please enter a valid number.")
            except KeyboardInterrupt:
                print("\nExiting...")
                break
            except Exception as e:
                print(f"Unexpected error: {e}")
    finally:
        controller.disconnect()

if __name__ == "__main__":
    main()