b38f7f643b
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.
108 lines
2.3 KiB
Go
108 lines
2.3 KiB
Go
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
|
|
}
|