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()