Make Parse take raw NFC UID and 1K image.
Drop zip/JSON from the root API. dump remains an adapter for the Android app format; inventory and an AMS wand both call Parse(uid, image).
This commit is contained in:
@@ -1,16 +1,17 @@
|
|||||||
# bambu-nfc
|
# bambu-nfc
|
||||||
|
|
||||||
Go library for Bambu Lab filament NFC dumps produced by the Filament NFC dump Android app.
|
Go library for Bambu Lab filament NFC. Input is **raw NFC**: chip UID bytes and the 1024-byte MIFARE Classic 1K image — not a phone dump format.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import bambunfc "git.s1d3sw1ped.com/s1d3sw1ped/bambu-nfc"
|
import bambunfc "git.s1d3sw1ped.com/s1d3sw1ped/bambu-nfc"
|
||||||
|
|
||||||
tags, err := bambunfc.ParseZip(r)
|
tag, err := bambunfc.Parse(uid, image) // uid from ISO 14443, image is 1K
|
||||||
|
keys, err := bambunfc.KeysA(uid) // 16 Key-A values to dump the tag
|
||||||
spools, err := bambunfc.Merge(tags)
|
spools, err := bambunfc.Merge(tags)
|
||||||
keys, err := bambunfc.KeysA(uid)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- `dump` — brand-blind `filanfc-dump/v1` JSON/zip
|
`dump` can still decode the Android app's `filanfc-dump/v1` zip if you need that adapter; the inventory site should call `Parse` with UID + image (phone, AMS wand, or anything else).
|
||||||
|
|
||||||
- `mifare` — Classic 1K layout helpers
|
- `mifare` — Classic 1K layout helpers
|
||||||
- root package — Bambu Key-A HKDF, block parse, merge by `tray_uid`
|
- root package — Bambu Key-A HKDF, block parse, merge by `tray_uid`
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
// Package bambunfc parses Bambu Lab filament NFC dumps and derives MIFARE Key-A from a chip UID.
|
// Package bambunfc parses raw Bambu Lab filament NFC (ISO UID + MIFARE Classic 1K image)
|
||||||
|
// and derives MIFARE Key-A from a chip UID.
|
||||||
package bambunfc
|
package bambunfc
|
||||||
|
|||||||
@@ -158,10 +158,10 @@ type Spool struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func KeysA(uid []byte) ([16][6]byte, error)
|
func KeysA(uid []byte) ([16][6]byte, error)
|
||||||
func ParseImage(chipUID string, image []byte, fail []int) (Tag, error)
|
func Parse(uid, image []byte) (Tag, error) // raw ISO UID + 1024-byte 1K image
|
||||||
func ParseDump(d dump.Dump) (Tag, error)
|
|
||||||
func ParseZip(r io.Reader) ([]Tag, error)
|
|
||||||
func Merge(tags []Tag) ([]Spool, error)
|
func Merge(tags []Tag) ([]Spool, error)
|
||||||
|
|
||||||
|
The website and any AMS wand feed `Parse` with raw NFC. The `dump` package is only an adapter for the Android zip/JSON format; it is not the library’s input surface.
|
||||||
```
|
```
|
||||||
|
|
||||||
### KeysA
|
### KeysA
|
||||||
@@ -194,9 +194,9 @@ B4AEB23473E3
|
|||||||
BAF630CCBFD3
|
BAF630CCBFD3
|
||||||
```
|
```
|
||||||
|
|
||||||
### ParseImage
|
### Parse
|
||||||
|
|
||||||
MIFARE Classic 1K Bambu map (little-endian). Required sectors: **0, 1, 2, 4, 5, 9**. If any of those are in `fail` → `ErrIncomplete`.
|
MIFARE Classic 1K Bambu map (little-endian). Input is raw NFC only: `uid` is the ISO 14443 chip ID; `image` is 1024 bytes. Empty UID → `ErrUID`. Wrong image length → `ErrImageSize`. All-zero tray UID (block 9) → `ErrIncomplete`. No dump `sectors_fail` list — missing data is whatever is in the image (typically zeros).
|
||||||
|
|
||||||
| Block | Field |
|
| Block | Field |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -210,18 +210,12 @@ MIFARE Classic 1K Bambu map (little-endian). Required sectors: **0, 1, 2, 4, 5,
|
|||||||
| 12 | Produced ASCII (optional) |
|
| 12 | Produced ASCII (optional) |
|
||||||
| 14 | length meters `uint16` @4 (optional) |
|
| 14 | length meters `uint16` @4 (optional) |
|
||||||
|
|
||||||
`chipUID` argument is normalized to lowercase hex. If image block 0 bytes 0–3 decode to a different UID than `chipUID` (when sector 0 is OK), still trust `chipUID` from the dump metadata and keep parsing (cloned magic tags can rewrite block 0; v1 does not error).
|
`uid` is encoded to lowercase hex on `Tag.ChipUID`. Block 0 UID is not compared (cloned magic tags can rewrite it).
|
||||||
|
|
||||||
Not Bambu: if Type and Material are both empty after NUL-trim → `ErrNotBambu`.
|
Not Bambu: if Type and Material are both empty after NUL-trim → `ErrNotBambu`.
|
||||||
|
|
||||||
Brand is always `BrandBambuLab` on success.
|
Brand is always `BrandBambuLab` on success.
|
||||||
|
|
||||||
Optional sectors missing → leave those fields zero/empty, not an error.
|
|
||||||
|
|
||||||
### ParseDump / ParseZip
|
|
||||||
|
|
||||||
`ParseDump` uses `d.Image` and `d.SectorsFail` (`nil` fail list means none failed). `ParseZip` is `dump.ParseZip` then `ParseDump` each entry. A zip with one bad sticker returns error (no partial zip success in v1).
|
|
||||||
|
|
||||||
### Merge
|
### Merge
|
||||||
|
|
||||||
Group by `Brand + TrayUID`. Empty `TrayUID` → `ErrIncomplete` (do not invent ids). Different brands never share a group.
|
Group by `Brand + TrayUID`. Empty `TrayUID` → `ErrIncomplete` (do not invent ids). Different brands never share a group.
|
||||||
@@ -234,13 +228,14 @@ Output spool order: sorted by TrayUID.
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
var (
|
var (
|
||||||
ErrInvalidDump = errors.New("invalid dump")
|
|
||||||
ErrImageSize = errors.New("image size")
|
ErrImageSize = errors.New("image size")
|
||||||
ErrIncomplete = errors.New("incomplete tag")
|
ErrIncomplete = errors.New("incomplete tag")
|
||||||
ErrNotBambu = errors.New("not bambu")
|
ErrNotBambu = errors.New("not bambu")
|
||||||
ErrUID = errors.New("uid")
|
ErrUID = errors.New("uid")
|
||||||
ErrConflict = errors.New("tag conflict")
|
ErrConflict = errors.New("tag conflict")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Dump JSON/zip errors live in package `dump` (`dump.ErrInvalidDump`, `dump.ErrImageSize`).
|
||||||
```
|
```
|
||||||
|
|
||||||
Wrap with `%w`. Error strings lowercase, no punctuation.
|
Wrap with `%w`. Error strings lowercase, no punctuation.
|
||||||
@@ -254,13 +249,13 @@ Fixtures: copy from dump-app `docs/dumps/2026-08-23-filanfc-last-scans/` (and th
|
|||||||
| Test | Expect |
|
| Test | Expect |
|
||||||
|---|---|
|
|---|---|
|
||||||
| KeysA(`11223344`) | 16 keys matching Android/Python golden list |
|
| KeysA(`11223344`) | 16 keys matching Android/Python golden list |
|
||||||
| ParseZip of that testdata zip | 6 tags, all `BrandBambuLab` |
|
| Parse each testdata `.bin` with UID from the filename | 6 tags, all `BrandBambuLab` |
|
||||||
| Merge those tags | 3 spools; Translucent tray `2fb8e0e972084e74bf737393b28e7b12` has chips `52d60177`, `e27be276`; second Translucent `aa42f322172c48e99c0ece895346ea9f`; Basic `3cb568b7af4f41819412fe60afc5c446` |
|
| Merge those tags | 3 spools; Translucent tray `2fb8e0e972084e74bf737393b28e7b12` has chips `52d60177`, `e27be276`; second Translucent `aa42f322172c48e99c0ece895346ea9f`; Basic `3cb568b7af4f41819412fe60afc5c446` |
|
||||||
| Colors | `#61B0FF80` and `#000000FF` |
|
| Colors | `#61B0FF80` and `#000000FF` |
|
||||||
| Diameter | `1.75` |
|
| Diameter | `1.75` |
|
||||||
| Types | `PETG Translucent` ×4 tags, `PETG Basic` ×2 |
|
| Types | `PETG Translucent` ×4 tags, `PETG Basic` ×2 |
|
||||||
| 1023-byte image | `ErrImageSize` |
|
| 1023-byte image | `ErrImageSize` |
|
||||||
| missing block 9 in fail list | `ErrIncomplete` |
|
| image with block 9 all zeros | `ErrIncomplete` |
|
||||||
| empty UID KeysA | `ErrUID` |
|
| empty UID KeysA | `ErrUID` |
|
||||||
| Merge two tags same tray different Type | `ErrConflict` |
|
| Merge two tags same tray different Type | `ErrConflict` |
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package bambunfc
|
|||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrInvalidDump = errors.New("invalid dump")
|
|
||||||
ErrImageSize = errors.New("image size")
|
ErrImageSize = errors.New("image size")
|
||||||
ErrIncomplete = errors.New("incomplete tag")
|
ErrIncomplete = errors.New("incomplete tag")
|
||||||
ErrNotBambu = errors.New("not bambu")
|
ErrNotBambu = errors.New("not bambu")
|
||||||
|
|||||||
+5
-8
@@ -2,21 +2,18 @@ package bambunfc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMergeFixtures(t *testing.T) {
|
func TestMergeFixtures(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
f, err := os.Open("testdata/dumps.zip")
|
uids := []string{
|
||||||
if err != nil {
|
"e27be276", "52d60177", "92a80577", "b2d32177", "92b6fb31", "f28c58ed",
|
||||||
t.Fatal(err)
|
|
||||||
}
|
}
|
||||||
defer f.Close()
|
tags := make([]Tag, 0, len(uids))
|
||||||
tags, err := ParseZip(f)
|
for _, id := range uids {
|
||||||
if err != nil {
|
tags = append(tags, parseFile(t, id))
|
||||||
t.Fatal(err)
|
|
||||||
}
|
}
|
||||||
spools, err := Merge(tags)
|
spools, err := Merge(tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -5,24 +5,18 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.s1d3sw1ped.com/s1d3sw1ped/bambu-nfc/dump"
|
|
||||||
"git.s1d3sw1ped.com/s1d3sw1ped/bambu-nfc/mifare"
|
"git.s1d3sw1ped.com/s1d3sw1ped/bambu-nfc/mifare"
|
||||||
)
|
)
|
||||||
|
|
||||||
const BrandBambuLab = "Bambu Lab"
|
const BrandBambuLab = "Bambu Lab"
|
||||||
|
|
||||||
// requiredSectors must not appear in SectorsFail (blocks 0–2, 4–6, 8–9).
|
// Tag is one Bambu sticker parsed from a raw MIFARE Classic 1K image.
|
||||||
var requiredSectors = []int{0, 1, 2}
|
|
||||||
|
|
||||||
// Tag is one Bambu sticker after parsing the 1K image.
|
|
||||||
type Tag struct {
|
type Tag struct {
|
||||||
Brand string
|
Brand string
|
||||||
ChipUID string
|
ChipUID string // lowercase hex of the ISO UID
|
||||||
TrayUID string
|
TrayUID string // 32 lowercase hex chars (block 9)
|
||||||
Type string
|
Type string
|
||||||
Material string
|
Material string
|
||||||
MaterialID string
|
MaterialID string
|
||||||
@@ -40,14 +34,6 @@ type Tag struct {
|
|||||||
SpoolWidthRaw uint16
|
SpoolWidthRaw uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func failedSet(fail []int) map[int]bool {
|
|
||||||
s := make(map[int]bool, len(fail))
|
|
||||||
for _, n := range fail {
|
|
||||||
s[n] = true
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func block(image []byte, n int) []byte {
|
func block(image []byte, n int) []byte {
|
||||||
off := n * mifare.BlockSize
|
off := n * mifare.BlockSize
|
||||||
return image[off : off+mifare.BlockSize]
|
return image[off : off+mifare.BlockSize]
|
||||||
@@ -60,34 +46,24 @@ func cstr(b []byte) string {
|
|||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeUID(uid string) (string, error) {
|
func allZero(b []byte) bool {
|
||||||
uid = strings.ToLower(strings.TrimSpace(uid))
|
for _, v := range b {
|
||||||
if uid == "" || len(uid)%2 != 0 {
|
if v != 0 {
|
||||||
return "", fmt.Errorf("%w: %q", ErrUID, uid)
|
return false
|
||||||
}
|
}
|
||||||
if _, err := hex.DecodeString(uid); err != nil {
|
|
||||||
return "", fmt.Errorf("%w: %v", ErrUID, err)
|
|
||||||
}
|
}
|
||||||
return uid, nil
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseImage parses a Bambu MIFARE Classic 1K image.
|
// Parse reads a Bambu tag from raw NFC: ISO chip UID and the 1024-byte Classic 1K image.
|
||||||
// fail is the dump's sectors_fail list (sector indexes 0–15).
|
func Parse(uid, image []byte) (Tag, error) {
|
||||||
func ParseImage(chipUID string, image []byte, fail []int) (Tag, error) {
|
|
||||||
var zero Tag
|
var zero Tag
|
||||||
uid, err := normalizeUID(chipUID)
|
if len(uid) == 0 {
|
||||||
if err != nil {
|
return zero, fmt.Errorf("%w: empty", ErrUID)
|
||||||
return zero, err
|
|
||||||
}
|
}
|
||||||
if len(image) != mifare.Size1K {
|
if len(image) != mifare.Size1K {
|
||||||
return zero, fmt.Errorf("%w: want %d got %d", ErrImageSize, mifare.Size1K, len(image))
|
return zero, fmt.Errorf("%w: want %d got %d", ErrImageSize, mifare.Size1K, len(image))
|
||||||
}
|
}
|
||||||
failed := failedSet(fail)
|
|
||||||
for _, s := range requiredSectors {
|
|
||||||
if failed[s] {
|
|
||||||
return zero, fmt.Errorf("%w: sector %d", ErrIncomplete, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b1 := block(image, 1)
|
b1 := block(image, 1)
|
||||||
b2 := block(image, 2)
|
b2 := block(image, 2)
|
||||||
@@ -95,16 +71,22 @@ func ParseImage(chipUID string, image []byte, fail []int) (Tag, error) {
|
|||||||
b5 := block(image, 5)
|
b5 := block(image, 5)
|
||||||
b6 := block(image, 6)
|
b6 := block(image, 6)
|
||||||
b9 := block(image, 9)
|
b9 := block(image, 9)
|
||||||
|
b10 := block(image, 10)
|
||||||
|
b12 := block(image, 12)
|
||||||
|
b14 := block(image, 14)
|
||||||
|
|
||||||
material := cstr(b2)
|
material := cstr(b2)
|
||||||
typ := cstr(b4)
|
typ := cstr(b4)
|
||||||
if material == "" && typ == "" {
|
if material == "" && typ == "" {
|
||||||
return zero, ErrNotBambu
|
return zero, ErrNotBambu
|
||||||
}
|
}
|
||||||
|
if allZero(b9) {
|
||||||
|
return zero, fmt.Errorf("%w: tray uid", ErrIncomplete)
|
||||||
|
}
|
||||||
|
|
||||||
tag := Tag{
|
return Tag{
|
||||||
Brand: BrandBambuLab,
|
Brand: BrandBambuLab,
|
||||||
ChipUID: uid,
|
ChipUID: hex.EncodeToString(uid),
|
||||||
VariantID: cstr(b1[0:8]),
|
VariantID: cstr(b1[0:8]),
|
||||||
MaterialID: cstr(b1[8:16]),
|
MaterialID: cstr(b1[8:16]),
|
||||||
Material: material,
|
Material: material,
|
||||||
@@ -120,37 +102,8 @@ func ParseImage(chipUID string, image []byte, fail []int) (Tag, error) {
|
|||||||
BedC: int(binary.LittleEndian.Uint16(b6[6:8])),
|
BedC: int(binary.LittleEndian.Uint16(b6[6:8])),
|
||||||
MaxHotendC: int(binary.LittleEndian.Uint16(b6[8:10])),
|
MaxHotendC: int(binary.LittleEndian.Uint16(b6[8:10])),
|
||||||
MinHotendC: int(binary.LittleEndian.Uint16(b6[10:12])),
|
MinHotendC: int(binary.LittleEndian.Uint16(b6[10:12])),
|
||||||
}
|
SpoolWidthRaw: binary.LittleEndian.Uint16(b10[4:6]),
|
||||||
if !failed[2] {
|
Produced: cstr(b12),
|
||||||
b10 := block(image, 10)
|
LengthM: int(binary.LittleEndian.Uint16(b14[4:6])),
|
||||||
tag.SpoolWidthRaw = binary.LittleEndian.Uint16(b10[4:6])
|
}, nil
|
||||||
}
|
|
||||||
if !failed[3] {
|
|
||||||
tag.Produced = cstr(block(image, 12))
|
|
||||||
b14 := block(image, 14)
|
|
||||||
tag.LengthM = int(binary.LittleEndian.Uint16(b14[4:6]))
|
|
||||||
}
|
|
||||||
return tag, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseDump parses one dump JSON record as a Bambu tag.
|
|
||||||
func ParseDump(d dump.Dump) (Tag, error) {
|
|
||||||
return ParseImage(d.ChipUID, d.Image, d.SectorsFail)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseZip reads a filanfc-dump zip and parses every sticker as Bambu.
|
|
||||||
func ParseZip(r io.Reader) ([]Tag, error) {
|
|
||||||
dumps, err := dump.ParseZip(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%w: %v", ErrInvalidDump, err)
|
|
||||||
}
|
|
||||||
tags := make([]Tag, 0, len(dumps))
|
|
||||||
for _, d := range dumps {
|
|
||||||
tag, err := ParseDump(d)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("chip %s: %w", d.ChipUID, err)
|
|
||||||
}
|
|
||||||
tags = append(tags, tag)
|
|
||||||
}
|
|
||||||
return tags, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-54
@@ -1,33 +1,51 @@
|
|||||||
package bambunfc
|
package bambunfc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.s1d3sw1ped.com/s1d3sw1ped/bambu-nfc/dump"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseZipFixtures(t *testing.T) {
|
func loadRaw(t *testing.T, uidHex string) (uid, image []byte) {
|
||||||
|
t.Helper()
|
||||||
|
var err error
|
||||||
|
uid, err = hex.DecodeString(uidHex)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
image, err = os.ReadFile(filepath.Join("testdata", "dumps", uidHex+".bin"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return uid, image
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFile(t *testing.T, uidHex string) Tag {
|
||||||
|
t.Helper()
|
||||||
|
uid, image := loadRaw(t, uidHex)
|
||||||
|
tag, err := Parse(uid, image)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseRawFixtures(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
f, err := os.Open("testdata/dumps.zip")
|
uids := []string{
|
||||||
if err != nil {
|
"e27be276", "52d60177", "92a80577", "b2d32177", "92b6fb31", "f28c58ed",
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
tags, err := ParseZip(f)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(tags) != 6 {
|
|
||||||
t.Fatalf("len(tags) = %d; want 6", len(tags))
|
|
||||||
}
|
}
|
||||||
var translucent, basic int
|
var translucent, basic int
|
||||||
for _, tag := range tags {
|
for _, id := range uids {
|
||||||
|
tag := parseFile(t, id)
|
||||||
if tag.Brand != BrandBambuLab {
|
if tag.Brand != BrandBambuLab {
|
||||||
t.Errorf("chip %s brand %q", tag.ChipUID, tag.Brand)
|
t.Errorf("chip %s brand %q", tag.ChipUID, tag.Brand)
|
||||||
}
|
}
|
||||||
|
if tag.ChipUID != id {
|
||||||
|
t.Errorf("chip UID %q; want %q", tag.ChipUID, id)
|
||||||
|
}
|
||||||
if tag.DiameterMM != 1.75 {
|
if tag.DiameterMM != 1.75 {
|
||||||
t.Errorf("chip %s diameter %v", tag.ChipUID, tag.DiameterMM)
|
t.Errorf("chip %s diameter %v", tag.ChipUID, tag.DiameterMM)
|
||||||
}
|
}
|
||||||
@@ -49,53 +67,30 @@ func TestParseZipFixtures(t *testing.T) {
|
|||||||
if translucent != 4 || basic != 2 {
|
if translucent != 4 || basic != 2 {
|
||||||
t.Errorf("translucent=%d basic=%d", translucent, basic)
|
t.Errorf("translucent=%d basic=%d", translucent, basic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a := parseFile(t, "e27be276")
|
||||||
|
if a.TrayUID != "2fb8e0e972084e74bf737393b28e7b12" {
|
||||||
|
t.Errorf("TrayUID = %s", a.TrayUID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseImageErrors(t *testing.T) {
|
func TestParseErrors(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
raw, err := os.ReadFile("testdata/dumps/e27be276.bin")
|
uid, image := loadRaw(t, "e27be276")
|
||||||
if err != nil {
|
if _, err := Parse(uid, image[:1023]); !errors.Is(err, ErrImageSize) {
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if _, err := ParseImage("e27be276", raw[:1023], nil); !errors.Is(err, ErrImageSize) {
|
|
||||||
t.Errorf("short image err = %v; want ErrImageSize", err)
|
t.Errorf("short image err = %v; want ErrImageSize", err)
|
||||||
}
|
}
|
||||||
if _, err := ParseImage("e27be276", raw, []int{2}); !errors.Is(err, ErrIncomplete) {
|
|
||||||
t.Errorf("fail sector 2 err = %v; want ErrIncomplete", err)
|
|
||||||
}
|
|
||||||
blank := make([]byte, 1024)
|
blank := make([]byte, 1024)
|
||||||
if _, err := ParseImage("e27be276", blank, nil); !errors.Is(err, ErrNotBambu) {
|
if _, err := Parse(uid, blank); !errors.Is(err, ErrNotBambu) {
|
||||||
t.Errorf("blank image err = %v; want ErrNotBambu", err)
|
t.Errorf("blank image err = %v; want ErrNotBambu", err)
|
||||||
}
|
}
|
||||||
|
if _, err := Parse(nil, image); !errors.Is(err, ErrUID) {
|
||||||
|
t.Errorf("empty uid err = %v; want ErrUID", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseDumpJSON(t *testing.T) {
|
noTray := append([]byte(nil), image...)
|
||||||
t.Parallel()
|
copy(noTray[9*16:10*16], make([]byte, 16))
|
||||||
f, err := os.Open("testdata/dumps/e27be276.json")
|
if _, err := Parse(uid, noTray); !errors.Is(err, ErrIncomplete) {
|
||||||
if err != nil {
|
t.Errorf("zero tray err = %v; want ErrIncomplete", err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
d, err := dump.ParseJSON(f)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
tag, err := ParseDump(d)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if tag.TrayUID != "2fb8e0e972084e74bf737393b28e7b12" {
|
|
||||||
t.Errorf("TrayUID = %s", tag.TrayUID)
|
|
||||||
}
|
|
||||||
if tag.ChipUID != "e27be276" {
|
|
||||||
t.Errorf("ChipUID = %s", tag.ChipUID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseImageEmptyUID(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
_, err := ParseImage("", bytes.Repeat([]byte{1}, 1024), nil)
|
|
||||||
if !errors.Is(err, ErrUID) {
|
|
||||||
t.Errorf("err = %v; want ErrUID", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user