Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/api/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Authoritative global UI state changed. Sent when event opens, updates, is replac

Host platform and all connected clients may render same event in parallel. First valid response wins. A terminal update removes event from `events` and describes it in `resolved`, instructing every renderer to close.

`ui.changed` is latest-wins coalescible. Clients that reconnect or suspect missed notifications should query [`ui`](./methods#ui).
`ui.changed` is latest-wins coalescible. Clients that reconnect or suspect missed notifications should query [`ui`](./methods.md#ui).

#### Parameters

Expand All @@ -99,7 +99,7 @@ Host platform and all connected clients may render same event in parallel. First
| events | object[] | Yes | Complete active event snapshot. Initial implementation contains zero or one event. |
| resolved | object[] | Yes | Terminal resolutions associated with this transition. |

Event and resolution fields are defined under [`ui`](./methods#ui-event-object) and [`ui.respond`](./methods#ui-resolution-object).
Event and resolution fields are defined under [`ui`](./methods.md#ui-event-object) and [`ui.respond`](./methods.md#ui-resolution-object).

#### Picker opened

Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,5 @@ require (
periph.io/x/conn/v3 v3.7.3 // indirect
periph.io/x/host/v3 v3.8.5 // indirect
)

replace github.com/ZaparooProject/go-pn532 => ../go-pn532
58 changes: 58 additions & 0 deletions pkg/readers/pn532/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Zaparoo Core
// Copyright (c) 2026 The Zaparoo Project Contributors.
// SPDX-License-Identifier: GPL-3.0-or-later
//
// This file is part of Zaparoo Core.
//
// Zaparoo Core is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Zaparoo Core is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Zaparoo Core. If not, see <http://www.gnu.org/licenses/>.

package pn532

import (
"strings"
"sync"

pn532 "github.com/ZaparooProject/go-pn532"
"github.com/rs/zerolog/log"
)

// debugWriterOnce ensures the go-pn532 debug writer is only installed once,
// even if multiple PN532 readers are opened.
var debugWriterOnce sync.Once

// zerologDebugWriter forwards go-pn532's always-on debug output into Core's
// zerolog logger at debug level. go-pn532 writes the exact bytes it reads from
// tags (e.g. "NTAG readNDEFHeader: user data = [...]") through this path, which
// is otherwise never captured because Core creates no session log file.
type zerologDebugWriter struct{}

func (zerologDebugWriter) Write(p []byte) (int, error) {
for line := range strings.Lines(string(p)) {
line = strings.TrimRight(line, "\r\n")
if line == "" {
continue
}
log.Debug().Str("src", "pn532").Msg(line)
}
return len(p), nil
}

// enablePN532DebugLogging routes go-pn532 debug output into Core's logger when
// debug logging is enabled in the config. This is how raw NDEF/TLV byte dumps
// reach Core's log for diagnosing tag read failures.
func enablePN532DebugLogging() {
debugWriterOnce.Do(func() {
pn532.SetDebugWriter(zerologDebugWriter{})
})
}
7 changes: 7 additions & 0 deletions pkg/readers/pn532/pn532.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,13 @@ func (r *Reader) Open(device config.ReadersConnect, iq chan<- readers.Scan, opts
r.name = device.ConnectionString()
log.Debug().Msgf("opening PN532 device: %s", r.name)

// When debug logging is enabled, forward go-pn532's raw tag byte dumps
// (readNDEFHeader / TLV scan output) into Core's log for diagnosing NDEF
// read failures. Safe to call repeatedly; installs the writer once.
if r.cfg != nil && r.cfg.DebugLogging() {
enablePN532DebugLogging()
}

// Create PN532 device
r.device, err = r.deviceFactory(transport)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions scripts/tasks/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ tasks:
sh: go env GOMODCACHE || echo "{{.HOME}}/go"
IMG_BUILDCACHE: /home/build/.cache/go-build
IMG_GOCACHE: /home/build/go
# TEMPORARY: mount a sibling ../go-pn532 checkout at /go-pn532 so a local
# `replace => ../go-pn532` in go.mod resolves inside the container. Inert
# when the directory does not exist. Remove with the go.mod replace.
GOPN532_MOUNT:
sh: 'DIR="${PWD}/../go-pn532"; if [ -d "$DIR" ]; then echo "-v $(cd "$DIR" && pwd):/go-pn532"; fi'
cmds:
- '{{if eq OS "windows"}}cmd /c if not exist "{{.BUILDCACHE}}" mkdir "{{.BUILDCACHE}}"{{else}}mkdir -p "{{.BUILDCACHE}}"{{end}}'
- '{{if eq OS "windows"}}cmd /c if not exist "{{.GOCACHE}}" mkdir "{{.GOCACHE}}"{{else}}mkdir -p "{{.GOCACHE}}"{{end}}'
Expand All @@ -73,6 +78,7 @@ tasks:
-v "{{.BUILDCACHE}}:{{.IMG_BUILDCACHE}}"
-v "{{.GOCACHE}}:{{.IMG_GOCACHE}}"
-v "${PWD}:/build"
{{.GOPN532_MOUNT}}
-e PLATFORM={{.PLATFORM}}
-e APP_BIN={{.APP_BIN}}
-e APP_VERSION="{{.APP_VERSION}}"
Expand Down
Loading