New tg ID schema and initial importer #35
2 changed files with 142 additions and 0 deletions
|
@ -20,6 +20,7 @@ func (tga *talkgroupAPI) Subrouter() http.Handler {
|
|||
r.Put("/{system:\\d+}/{id:\\d+}", tga.put)
|
||||
r.Get("/{system:\\d+}/", tga.get)
|
||||
r.Get("/", tga.get)
|
||||
r.Put("/import", tga.tgImport)
|
||||
|
||||
return r
|
||||
}
|
||||
|
@ -106,3 +107,19 @@ func (tga *talkgroupAPI) put(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
respond(w, r, record)
|
||||
}
|
||||
|
||||
func (tga *talkgroupAPI) tgImport(w http.ResponseWriter, r *http.Request) {
|
||||
var impJob talkgroups.ImportJob
|
||||
err := forms.Unmarshal(r, &impJob, forms.WithTag("json"), forms.WithAcceptBlank(), forms.WithOmitEmpty())
|
||||
if err != nil {
|
||||
wErr(w, r, badRequest(err))
|
||||
return
|
||||
}
|
||||
recs, err := impJob.Import()
|
||||
if err != nil {
|
||||
wErr(w, r, autoError(err))
|
||||
return
|
||||
}
|
||||
|
||||
respond(w, r, recs)
|
||||
}
|
||||
|
|
125
pkg/talkgroups/import.go
Normal file
125
pkg/talkgroups/import.go
Normal file
|
@ -0,0 +1,125 @@
|
|||
package talkgroups
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"dynatron.me/x/stillbox/pkg/database"
|
||||
)
|
||||
|
||||
type ImportSource string
|
||||
|
||||
const (
|
||||
ImportSrcRadioReference ImportSource = "radioreference"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrBadImportType = errors.New("unknown import type")
|
||||
)
|
||||
|
||||
type importer interface {
|
||||
importTalkgroups(sys int, r io.Reader) ([]Talkgroup, error)
|
||||
}
|
||||
|
||||
type ImportJob struct {
|
||||
Type ImportSource `json:"type"`
|
||||
SystemID int `json:"systemID"`
|
||||
Body string `json:"body"`
|
||||
|
||||
importer `json:"-"`
|
||||
}
|
||||
|
||||
func (ij *ImportJob) Import() ([]Talkgroup, error) {
|
||||
r := bytes.NewReader([]byte(ij.Body))
|
||||
|
||||
switch ij.Type {
|
||||
case ImportSrcRadioReference:
|
||||
ij.importer = &radioReferenceImporter{}
|
||||
default:
|
||||
return nil, ErrBadImportType
|
||||
}
|
||||
return ij.importTalkgroups(ij.SystemID, r)
|
||||
}
|
||||
|
||||
type radioReferenceImporter struct {
|
||||
}
|
||||
|
||||
type rrState int
|
||||
const (
|
||||
rrsInitial rrState = iota
|
||||
rrsGroupDesc
|
||||
rrsTG
|
||||
)
|
||||
|
||||
var rrRE = regexp.MustCompile(`DEC\s+HEX\s+Mode\s+Alpha Tag\s+Description\s+Tag`)
|
||||
|
||||
func (rr *radioReferenceImporter) importTalkgroups(sys int, r io.Reader) ([]Talkgroup, error) {
|
||||
sc := bufio.NewScanner(r)
|
||||
tgs := make([]Talkgroup, 0, 8)
|
||||
|
||||
var groupName string
|
||||
state := rrsInitial
|
||||
for sc.Scan() {
|
||||
ln := strings.Trim(sc.Text(), " \t\r\n")
|
||||
|
||||
switch state {
|
||||
case rrsInitial:
|
||||
groupName = ln
|
||||
state++
|
||||
case rrsGroupDesc:
|
||||
if rrRE.MatchString(ln) {
|
||||
state++
|
||||
}
|
||||
case rrsTG:
|
||||
fields := strings.Split(ln, "\t")
|
||||
if len(fields) < 6 {
|
||||
state = rrsGroupDesc
|
||||
groupName = ln
|
||||
continue
|
||||
}
|
||||
tgid, err := strconv.Atoi(fields[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var metadata []byte
|
||||
tgt := TG(sys, tgid)
|
||||
mode := fields[2]
|
||||
if strings.Contains(mode, "E") {
|
||||
metadata, _ = json.Marshal(&struct{
|
||||
Encrypted bool `json:"encrypted"`
|
||||
}{true})
|
||||
}
|
||||
tags := []string{fields[5]}
|
||||
tgs = append(tgs, Talkgroup{
|
||||
Talkgroup: database.Talkgroup{
|
||||
ID: tgt.Pack(),
|
||||
Tgid: int32(tgt.Talkgroup),
|
||||
SystemID: int32(tgt.System),
|
||||
Name: &fields[4],
|
||||
AlphaTag: &fields[3],
|
||||
TgGroup: &groupName,
|
||||
Metadata: metadata,
|
||||
Tags: tags,
|
||||
Weight: 1.0,
|
||||
},
|
||||
System: database.System{
|
||||
ID: sys,
|
||||
Name: "<imported>",
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if err := sc.Err(); err != nil {
|
||||
return tgs, err
|
||||
}
|
||||
|
||||
return tgs, nil
|
||||
}
|
Loading…
Reference in a new issue