Add bambu-nfc dump parse, Key-A HKDF, and spool merge.
Parse filanfc-dump/v1 zip/JSON, Bambu 1K images, and merge stickers by tray UID. dump and mifare packages stay importable for a later common library.
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
package bambunfc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// Spool is one physical filament roll (both stickers merged).
|
||||
type Spool struct {
|
||||
Brand string
|
||||
TrayUID string
|
||||
ChipUIDs []string
|
||||
Type string
|
||||
Material string
|
||||
MaterialID string
|
||||
VariantID string
|
||||
Color Color
|
||||
WeightG int
|
||||
DiameterMM float32
|
||||
LengthM int
|
||||
MinHotendC int
|
||||
MaxHotendC int
|
||||
BedC int
|
||||
DryC int
|
||||
DryHours int
|
||||
Produced string
|
||||
SpoolWidthRaw uint16
|
||||
}
|
||||
|
||||
func spoolKey(t Tag) string {
|
||||
return t.Brand + "\x00" + t.TrayUID
|
||||
}
|
||||
|
||||
func sameFilament(a, b Tag) bool {
|
||||
return a.Type == b.Type &&
|
||||
a.Material == b.Material &&
|
||||
a.Color == b.Color &&
|
||||
a.WeightG == b.WeightG
|
||||
}
|
||||
|
||||
func tagToSpool(t Tag) Spool {
|
||||
return Spool{
|
||||
Brand: t.Brand,
|
||||
TrayUID: t.TrayUID,
|
||||
ChipUIDs: []string{t.ChipUID},
|
||||
Type: t.Type,
|
||||
Material: t.Material,
|
||||
MaterialID: t.MaterialID,
|
||||
VariantID: t.VariantID,
|
||||
Color: t.Color,
|
||||
WeightG: t.WeightG,
|
||||
DiameterMM: t.DiameterMM,
|
||||
LengthM: t.LengthM,
|
||||
MinHotendC: t.MinHotendC,
|
||||
MaxHotendC: t.MaxHotendC,
|
||||
BedC: t.BedC,
|
||||
DryC: t.DryC,
|
||||
DryHours: t.DryHours,
|
||||
Produced: t.Produced,
|
||||
SpoolWidthRaw: t.SpoolWidthRaw,
|
||||
}
|
||||
}
|
||||
|
||||
// Merge groups tags by brand + tray UID into spools.
|
||||
func Merge(tags []Tag) ([]Spool, error) {
|
||||
order := make([]string, 0)
|
||||
groups := make(map[string][]Tag)
|
||||
for _, t := range tags {
|
||||
if t.TrayUID == "" {
|
||||
return nil, fmt.Errorf("%w: empty tray uid chip %s", ErrIncomplete, t.ChipUID)
|
||||
}
|
||||
k := spoolKey(t)
|
||||
if _, ok := groups[k]; !ok {
|
||||
order = append(order, k)
|
||||
}
|
||||
groups[k] = append(groups[k], t)
|
||||
}
|
||||
|
||||
spools := make([]Spool, 0, len(order))
|
||||
for _, k := range order {
|
||||
g := groups[k]
|
||||
s := tagToSpool(g[0])
|
||||
uids := map[string]struct{}{g[0].ChipUID: {}}
|
||||
for _, t := range g[1:] {
|
||||
if !sameFilament(g[0], t) {
|
||||
return nil, fmt.Errorf("%w: tray %s", ErrConflict, t.TrayUID)
|
||||
}
|
||||
uids[t.ChipUID] = struct{}{}
|
||||
}
|
||||
s.ChipUIDs = make([]string, 0, len(uids))
|
||||
for u := range uids {
|
||||
s.ChipUIDs = append(s.ChipUIDs, u)
|
||||
}
|
||||
slices.Sort(s.ChipUIDs)
|
||||
spools = append(spools, s)
|
||||
}
|
||||
slices.SortFunc(spools, func(a, b Spool) int {
|
||||
if a.TrayUID < b.TrayUID {
|
||||
return -1
|
||||
}
|
||||
if a.TrayUID > b.TrayUID {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
return spools, nil
|
||||
}
|
||||
Reference in New Issue
Block a user