From 719e227ba4182e04ced09f94d8dcefe027b86006 Mon Sep 17 00:00:00 2001 From: Shiro-Nek0 Date: Tue, 17 Mar 2026 16:13:57 -0300 Subject: [PATCH] golang scanner imp --- ScannerGO/go.mod | 40 +++++- ScannerGO/go.sum | 82 ++++++++++++- ScannerGO/main.go | 301 ++++++++++++++++++++++++---------------------- 3 files changed, 275 insertions(+), 148 deletions(-) diff --git a/ScannerGO/go.mod b/ScannerGO/go.mod index f68832d..7fb341a 100644 --- a/ScannerGO/go.mod +++ b/ScannerGO/go.mod @@ -2,6 +2,42 @@ module ScannerGO go 1.25.7 -require github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 +require ( + fyne.io/fyne/v2 v2.7.3 + github.com/google/gousb v1.1.3 +) -require golang.org/x/sys v0.41.0 // indirect +require ( + fyne.io/systray v1.12.0 // indirect + github.com/BurntSushi/toml v1.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fredbi/uri v1.1.1 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/fyne-io/gl-js v0.2.0 // indirect + github.com/fyne-io/glfw-js v0.3.0 // indirect + github.com/fyne-io/image v0.1.1 // indirect + github.com/fyne-io/oksvg v0.2.0 // indirect + github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect + github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect + github.com/go-text/render v0.2.0 // indirect + github.com/go-text/typesetting v0.3.3 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/hack-pad/go-indexeddb v0.3.2 // indirect + github.com/hack-pad/safejs v0.1.0 // indirect + github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect + github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect + github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rymdport/portal v0.4.2 // indirect + github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect + github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/yuin/goldmark v1.7.8 // indirect + golang.org/x/image v0.24.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.22.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/ScannerGO/go.sum b/ScannerGO/go.sum index 8dd0c8a..296ba6c 100644 --- a/ScannerGO/go.sum +++ b/ScannerGO/go.sum @@ -1,4 +1,82 @@ -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +fyne.io/fyne/v2 v2.7.3 h1:xBT/iYbdnNHONWO38fZMBrVBiJG8rV/Jypmy4tVfRWE= +fyne.io/fyne/v2 v2.7.3/go.mod h1:gu+dlIcZWSzKZmnrY8Fbnj2Hirabv2ek+AKsfQ2bBlw= +fyne.io/systray v1.12.0 h1:CA1Kk0e2zwFlxtc02L3QFSiIbxJ/P0n582YrZHT7aTM= +fyne.io/systray v1.12.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= +github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko= +github.com/fredbi/uri v1.1.1/go.mod h1:4+DZQ5zBjEwQCDmXW5JdIjz0PUA+yJbvtBv+u+adr5o= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs= +github.com/fyne-io/gl-js v0.2.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI= +github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk= +github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk= +github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA= +github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM= +github.com/fyne-io/oksvg v0.2.0 h1:mxcGU2dx6nwjJsSA9PCYZDuoAcsZ/OuJlvg/Q9Njfo8= +github.com/fyne-io/oksvg v0.2.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI= +github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA= +github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc= +github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU= +github.com/go-text/typesetting v0.3.3 h1:ihGNJU9KzdK2QRDy1Bm7FT5RFQoYb+3n3EIhI/4eaQc= +github.com/go-text/typesetting v0.3.3/go.mod h1:vIRUT25mLQaSh4C8H/lIsKppQz/Gdb8Pu/tNwpi52ts= +github.com/go-text/typesetting-utils v0.0.0-20250618110550-c820a94c77b8 h1:4KCscI9qYWMGTuz6BpJtbUSRzcBrUSSE0ENMJbNSrFs= +github.com/go-text/typesetting-utils v0.0.0-20250618110550-c820a94c77b8/go.mod h1:3/62I4La/HBRX9TcTpBj4eipLiwzf+vhI+7whTc9V7o= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/gousb v1.1.3 h1:xt6M5TDsGSZ+rlomz5Si5Hmd/Fvbmo2YCJHN+yGaK4o= +github.com/google/gousb v1.1.3/go.mod h1:GGWUkK0gAXDzxhwrzetW592aOmkkqSGcj5KLEgmCVUg= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A= +github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0= +github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8= +github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio= +github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE= +github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o= +github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= +github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk= +github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= +github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU= +github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= +github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= +github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= +github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= +github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= +github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= +golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ScannerGO/main.go b/ScannerGO/main.go index 615a70f..62d1f8a 100644 --- a/ScannerGO/main.go +++ b/ScannerGO/main.go @@ -1,175 +1,188 @@ package main import ( - "bufio" - "bytes" - "encoding/json" - "flag" "fmt" - "io" + "image/color" "net/http" - "net/url" - "os" - "strings" "time" - "github.com/tarm/serial" + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/app" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/widget" + "github.com/google/gousb" ) -type Config struct { - Port string `json:"port"` - URL string `json:"url"` - BaudRate int `json:"baud"` - Delimiter string `json:"delimiter"` - FlowControl string `json:"flow_control"` +const ( + VendorID = 0xFFFF + ProductID = 0x0035 +) + +var hidMap = map[byte]string{ + 4: "a", 5: "b", 6: "c", 7: "d", 8: "e", 9: "f", 10: "g", 11: "h", 12: "i", + 13: "j", 14: "k", 15: "l", 16: "m", 17: "n", 18: "o", 19: "p", 20: "q", + 21: "r", 22: "s", 23: "t", 24: "u", 25: "v", 26: "w", 27: "x", 28: "y", 29: "z", + 30: "1", 31: "2", 32: "3", 33: "4", 34: "5", 35: "6", 36: "7", 37: "8", 38: "9", 39: "0", + 44: " ", 45: "-", 46: "=", 55: ".", 56: "/", } -var defaultConfig = Config{ - Port: "/dev/ttyACM0", - URL: "https://scanner.sekidesu.xyz/scan", - BaudRate: 115200, - Delimiter: "\n", - FlowControl: "none", +type BridgeApp struct { + urlEntry *widget.Entry + status *canvas.Text + logList *widget.List + logs []string + window fyne.Window } -const configPath = "config.json" - func main() { - cfg := loadConfig() + a := app.New() + w := a.NewWindow("POS Hardware Bridge (Go)") - portName := flag.String("port", cfg.Port, "Serial port name") - endpoint := flag.String("url", cfg.URL, "Target URL endpoint") - baudRate := flag.Int("baud", cfg.BaudRate, "Baud rate") - delim := flag.String("delim", cfg.Delimiter, "Line delimiter") - flow := flag.String("flow", cfg.FlowControl, "Flow control: none, hardware, software") - save := flag.Bool("save", false, "Save current parameters to config.json") - flag.Parse() - - cfg.Port = *portName - cfg.URL = *endpoint - cfg.BaudRate = *baudRate - cfg.Delimiter = *delim - cfg.FlowControl = *flow - - if *save { - saveConfig(cfg) - fmt.Println("Settings saved to", configPath) + bridge := &BridgeApp{ + urlEntry: widget.NewEntry(), + status: canvas.NewText("Status: Booting...", color.Black), + window: w, } - serialConfig := &serial.Config{ - Name: cfg.Port, - Baud: cfg.BaudRate, - ReadTimeout: time.Millisecond * 500, - } + bridge.status.TextSize = 14 + bridge.urlEntry.SetText("https://scanner.sekidesu.xyz/scan") - // tarm/serial uses boolean flags for flow control if available in the version used - // If your version doesn't support these fields, you may need to update the package - // or manage the lines manually via the file descriptor. - /* Note: tarm/serial usually requires specific fork or version - for full RTS/CTS hardware flow control support. - */ + // UI Layout + bridge.logList = widget.NewList( + func() int { return len(bridge.logs) }, + func() fyne.CanvasObject { return widget.NewLabel("template") }, + func(i widget.ListItemID, o fyne.CanvasObject) { + o.(*widget.Label).SetText(bridge.logs[len(bridge.logs)-1-i]) + }, + ) - port, err := serial.OpenPort(serialConfig) - if err != nil { - fmt.Printf("Error opening port %s: %v\n", cfg.Port, err) - os.Exit(1) - } - defer port.Close() + content := container.NewBorder( + container.NewVBox( + widget.NewLabel("Target POS Endpoint:"), + bridge.urlEntry, + bridge.status, + widget.NewLabel("Activity Log:"), + ), + nil, nil, nil, + bridge.logList, + ) - fmt.Printf("Listening on %s (Baud: %d, Flow: %s)...\n", cfg.Port, cfg.BaudRate, cfg.FlowControl) + w.SetContent(content) + w.Resize(fyne.NewSize(500, 400)) - scanner := bufio.NewScanner(port) + go bridge.usbListenLoop() - scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) { - if atEOF && len(data) == 0 { - return 0, nil, nil + w.ShowAndRun() +} + +func (b *BridgeApp) addLog(msg string) { + fyne.DoAndWait(func() { + ts := time.Now().Format("15:04:05") + b.logs = append([]string{fmt.Sprintf("[%s] %s", ts, msg)}, b.logs...) + if len(b.logs) > 15 { + b.logs = b.logs[:15] } - if i := bytes.Index(data, []byte(cfg.Delimiter)); i >= 0 { - return i + len(cfg.Delimiter), data[0:i], nil - } - if atEOF { - return len(data), data, nil - } - return 0, nil, nil + b.logList.Refresh() }) - - for scanner.Scan() { - rawContent := scanner.Text() - content := strings.TrimFunc(rawContent, func(r rune) bool { - return r < 32 || r > 126 - }) - - if content != "" { - sendToEndpoint(cfg.URL, content) - } - } - - if err := scanner.Err(); err != nil { - fmt.Printf("Scanner error: %v\n", err) - } } -func loadConfig() Config { - if _, err := os.Stat(configPath); os.IsNotExist(err) { - saveConfig(defaultConfig) - return defaultConfig - } - - file, err := os.Open(configPath) +func (b *BridgeApp) sendToPos(barcode string) { + b.addLog(fmt.Sprintf("Captured: %s. Sending...", barcode)) + client := http.Client{Timeout: 3 * time.Second} + resp, err := client.Get(b.urlEntry.Text + "?content=" + barcode) if err != nil { - return defaultConfig - } - defer file.Close() - - var cfg Config - decoder := json.NewDecoder(file) - if err := decoder.Decode(&cfg); err != nil { - return defaultConfig - } - if cfg.Delimiter == "" { - cfg.Delimiter = "\n" - } - if cfg.FlowControl == "" { - cfg.FlowControl = "none" - } - return cfg -} - -func saveConfig(cfg Config) { - file, err := os.Create(configPath) - if err != nil { - fmt.Printf("Failed to create/save config: %v\n", err) - return - } - defer file.Close() - - encoder := json.NewEncoder(file) - encoder.SetIndent("", " ") - encoder.Encode(cfg) -} - -func sendToEndpoint(baseURL, content string) { - client := &http.Client{ - Timeout: 5 * time.Second, - } - - fullURL := fmt.Sprintf("%s?content=%s", baseURL, url.QueryEscape(content)) - resp, err := client.Get(fullURL) - if err != nil { - fmt.Printf("Network Error: %v\n", err) + b.addLog("HTTP Error: Backend unreachable") return } defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - fmt.Printf("Error reading response: %v\n", err) - return - } - - fmt.Printf("Data: [%s] | Status: %s\n", content, resp.Status) - if len(body) > 0 { - fmt.Printf("Response: %s\n", string(body)) - } - fmt.Println(strings.Repeat("-", 30)) + b.addLog(fmt.Sprintf("Success: POS returned %d", resp.StatusCode)) +} + +func (b *BridgeApp) usbListenLoop() { + ctx := gousb.NewContext() + defer ctx.Close() + + for { + dev, err := ctx.OpenDeviceWithVIDPID(gousb.ID(VendorID), gousb.ID(ProductID)) + + if err != nil || dev == nil { + fyne.DoAndWait(func() { + b.status.Text = "Status: Scanner unplugged. Waiting..." + b.status.Color = color.NRGBA{R: 200, G: 0, B: 0, A: 255} + b.status.Refresh() + }) + time.Sleep(2 * time.Second) + continue + } + + fyne.DoAndWait(func() { + b.status.Text = "Status: Scanner Locked & Ready" + b.status.Color = color.NRGBA{R: 0, G: 180, B: 0, A: 255} + b.status.Refresh() + }) + + intf, done, err := dev.DefaultInterface() + if err != nil { + b.addLog("Error claiming interface") + dev.Close() + time.Sleep(2 * time.Second) + continue + } + + var inEp *gousb.InEndpoint + for _, epDesc := range intf.Setting.Endpoints { + if epDesc.Direction == gousb.EndpointDirectionIn { + inEp, _ = intf.InEndpoint(epDesc.Number) + break + } + } + + if inEp == nil { + b.addLog("No IN endpoint found") + done() + dev.Close() + continue + } + + currentBarcode := "" + buf := make([]byte, inEp.Desc.MaxPacketSize) + + for { + n, err := inEp.Read(buf) + if err != nil { + // This usually happens when the device is unplugged + break + } + if n < 3 { + continue + } + + modifier := buf[0] + keycode := buf[2] + isShift := (modifier == 2 || modifier == 32) + + if keycode == 0 { + continue + } + + if keycode == 40 { // Enter + if currentBarcode != "" { + // Capture the barcode to avoid race conditions + code := currentBarcode + go b.sendToPos(code) + currentBarcode = "" + } + } else if val, ok := hidMap[keycode]; ok { + if isShift && len(val) == 1 && val[0] >= 'a' && val[0] <= 'z' { + val = string(val[0] - 32) + } + currentBarcode += val + } + } + + done() + dev.Close() + b.addLog("Hardware connection lost. Reconnecting...") + } }