func main() { var verbose bool flag.BoolVar(&verbose, "verbose", false, "make noise") var output string flag.StringVar(&output, "output", "output", "output directory") var network string flag.StringVar(&network, "network", "../../network", "base network directory") var install string flag.StringVar(&install, "install", "../../install", "base install directory") flag.Usage = func() { fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Build a RINEX configuration site XML file from delta meta information\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Usage:\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, " %s [options]\n", os.Args[0]) fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Options:\n") fmt.Fprintf(os.Stderr, "\n") flag.PrintDefaults() fmt.Fprintf(os.Stderr, "\n") } flag.Parse() var firmwareHistoryList meta.FirmwareHistoryList if err := meta.LoadList(filepath.Join(install, "firmware.csv"), &firmwareHistoryList); err != nil { fmt.Fprintf(os.Stderr, "error: unable to load firmware history: %v\n", err) os.Exit(-1) } firmwareHistory := make(map[string]map[string][]meta.FirmwareHistory) for _, i := range firmwareHistoryList { if _, ok := firmwareHistory[i.Model]; !ok { firmwareHistory[i.Model] = make(map[string][]meta.FirmwareHistory) } firmwareHistory[i.Model][i.Serial] = append(firmwareHistory[i.Model][i.Serial], i) } for j, _ := range firmwareHistory { for k, _ := range firmwareHistory[j] { sort.Sort(meta.FirmwareHistoryList(firmwareHistory[j][k])) } } var installedAntennaList meta.InstalledAntennaList if err := meta.LoadList(filepath.Join(install, "antennas.csv"), &installedAntennaList); err != nil { fmt.Fprintf(os.Stderr, "error: unable to load antenna installs: %v\n", err) os.Exit(-1) } installedAntenna := make(map[string][]meta.InstalledAntenna) for _, i := range installedAntennaList { installedAntenna[i.Mark] = append(installedAntenna[i.Mark], i) } for i, _ := range installedAntenna { sort.Sort(meta.InstalledAntennaList(installedAntenna[i])) } var deployedReceiverList meta.DeployedReceiverList if err := meta.LoadList(filepath.Join(install, "receivers.csv"), &deployedReceiverList); err != nil { fmt.Fprintf(os.Stderr, "error: unable to load receiver installs: %v\n", err) os.Exit(-1) } deployedReceivers := make(map[string][]meta.DeployedReceiver) for _, i := range deployedReceiverList { deployedReceivers[i.Mark] = append(deployedReceivers[i.Mark], i) } for i, _ := range deployedReceivers { sort.Sort(meta.DeployedReceiverList(deployedReceivers[i])) } var installedRadomeList meta.InstalledRadomeList if err := meta.LoadList(filepath.Join(install, "radomes.csv"), &installedRadomeList); err != nil { fmt.Fprintf(os.Stderr, "error: unable to load radome installs: %v\n", err) os.Exit(-1) } installedRadomes := make(map[string][]meta.InstalledRadome) for _, i := range installedRadomeList { installedRadomes[i.Mark] = append(installedRadomes[i.Mark], i) } for i, _ := range installedRadomes { sort.Sort(meta.InstalledRadomeList(installedRadomes[i])) } var markList meta.MarkList if err := meta.LoadList(filepath.Join(network, "marks.csv"), &markList); err != nil { fmt.Fprintf(os.Stderr, "error: unable to load mark list: %v\n", err) os.Exit(-1) } var sessionList meta.SessionList if err := meta.LoadList(filepath.Join(install, "sessions.csv"), &sessionList); err != nil { fmt.Fprintf(os.Stderr, "error: unable to load session list: %v\n", err) os.Exit(-1) } sessions := make(map[string][]meta.Session) for _, s := range sessionList { sessions[s.Mark] = append(sessions[s.Mark], s) } for _, m := range markList { if _, ok := sessions[m.Code]; !ok { continue } if _, ok := installedAntenna[m.Code]; !ok { continue } if _, ok := deployedReceivers[m.Code]; !ok { continue } var list []CGPSSessionXML for _, s := range sessions[m.Code] { for _, a := range installedAntenna[m.Code] { if a.Start.After(s.End) || a.End.Before(s.Start) { continue } if _, ok := IGSModels[a.Model]; !ok { fmt.Fprintf(os.Stderr, "%s: no igs designation for: %s [%s], skipping\n", m.Code, a.Model, a.Serial) continue } for _, r := range deployedReceivers[m.Code] { if r.Start.After(a.End) || r.End.Before(a.Start) { continue } if _, ok := IGSModels[r.Model]; !ok { fmt.Fprintf(os.Stderr, "%s: no igs designation for: %s [%s]", m.Code, r.Model, r.Serial) continue } radome := "NONE" if _, ok := installedRadomes[m.Code]; ok { for _, v := range installedRadomes[m.Code] { if v.Start.After(a.End) || v.Start.After(r.End) { continue } if v.End.Before(a.Start) || v.End.Before(r.Start) { continue } if _, ok := IGSModels[v.Model]; !ok { fmt.Fprintf(os.Stderr, "%s: no igs designation for: %s [%s]", m.Code, v.Model, v.Serial) continue } radome = IGSModels[v.Model] } } var firmware []FirmwareHistoryXML if _, ok := firmwareHistory[r.Model]; ok { if _, ok := firmwareHistory[r.Model][r.Serial]; ok { for i, _ := range firmwareHistory[r.Model][r.Serial] { v := firmwareHistory[r.Model][r.Serial][len(firmwareHistory[r.Model][r.Serial])-i-1] if v.End.Before(r.Start) || v.Start.After(r.End) { continue } firmware = append(firmware, FirmwareHistoryXML{ StartTime: v.Start.Format(meta.DateTimeFormat), StopTime: func() string { if time.Now().After(v.End) { return v.End.Format(meta.DateTimeFormat) } else { return "open" } }(), Version: v.Version, }) } } } list = append(list, CGPSSessionXML{ StartTime: func() string { if r.Start.After(a.Start) { return r.Start.Format(meta.DateTimeFormat) } else if a.Start.After(s.Start) { return a.Start.Format(meta.DateTimeFormat) } else { return s.Start.Format(meta.DateTimeFormat) } }(), StopTime: func() string { if r.End.Before(a.End) { if time.Now().After(r.End) { return r.End.Format(meta.DateTimeFormat) } else { return "open" } } else if a.End.Before(s.End) { if time.Now().After(a.End) { return a.End.Format(meta.DateTimeFormat) } else { return "open" } } else { if time.Now().After(s.End) { return s.End.Format(meta.DateTimeFormat) } else { return "open" } } }(), Receiver: ReceiverXML{ SerialNumber: r.Serial, IGSDesignation: IGSModels[r.Model], FirmwareHistories: firmware, }, InstalledCGPSAntenna: InstalledCGPSAntennaXML{ Height: Number{Units: "m", Value: a.Vertical}, OffsetNorth: Number{Units: "m", Value: a.North}, OffsetEast: Number{Units: "m", Value: a.East}, Radome: radome, CGPSAntenna: CGPSAntennaXML{ SerialNumber: a.Serial, IGSDesignation: IGSModels[a.Model], }, }, ObservationInterval: Number{ Units: "s", Value: s.Interval.Seconds(), }, Operator: OperatorXML{ Name: s.Operator, Agency: s.Agency, }, Rinex: RinexXML{ HeaderCommentName: s.HeaderComment, HeaderCommentText: func() string { if t, ok := HeaderComments[s.HeaderComment]; ok { return strings.Join(strings.Fields(t), " ") } return "" }(), }, DataFormat: func() string { if f, ok := DataFormats[r.Model]; ok { return f } return "unknown" }(), DownloadNameFormat: func() DownloadNameFormatXML { if f, ok := DownloadNameFormats[r.Model]; ok { return f } return DownloadNameFormatXML{} }(), }) } } } x := NewSiteXML( MarkXML{ GeodeticCode: m.Code, //DomesNumber: m.DomesNumber, }, LocationXML{ Latitude: m.Latitude, Longitude: m.Longitude, Height: m.Elevation, Datum: m.Datum, }, list, ) s, err := x.Marshal() if err != nil { fmt.Fprintf(os.Stderr, "error: unable to marsh xml: %v\n", err) os.Exit(-1) } xmlfile := filepath.Join(output, m.Code+".xml") if err := os.MkdirAll(filepath.Dir(xmlfile), 0755); err != nil { fmt.Fprintf(os.Stderr, "error: unable to create dir: %v\n", err) os.Exit(-1) } if err := ioutil.WriteFile(xmlfile, s, 0644); err != nil { fmt.Fprintf(os.Stderr, "error: unable to write file: %v\n", err) os.Exit(-1) } } }
func main() { var verbose bool flag.BoolVar(&verbose, "verbose", false, "make noise") var output string flag.StringVar(&output, "output", "output", "output directory") var logs string flag.StringVar(&logs, "logs", "logs", "logs output directory") var network string flag.StringVar(&network, "network", "../../network", "base network directory") var install string flag.StringVar(&install, "install", "../../install", "base install directory") flag.Usage = func() { fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Build GNSS SiteLog XML files from delta meta information\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Usage:\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, " %s [options]\n", os.Args[0]) fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Options:\n") fmt.Fprintf(os.Stderr, "\n") flag.PrintDefaults() fmt.Fprintf(os.Stderr, "\n") } flag.Parse() var tplFuncMap template.FuncMap = template.FuncMap{ "empty": func(d, s string) string { if s != "" { return s } return d }, "tolower": func(s string) string { switch t := strings.ToLower(s); t { case "wyatt/agnew drilled-braced": return "Deep Wyatt/Agnew drilled-braced" default: return t } }, "lines": func(p, s string) string { switch s { case "": return s default: return strings.Join(strings.Split(s, "\n"), "\n"+p) } }, "plus": func(n int) string { return fmt.Sprintf("%-2s", strconv.Itoa(n+1)) }, "lat": func(s string) string { if f, err := strconv.ParseFloat(s, 64); err == nil { m := math.Abs(f-float64(int(f))) * 60.0 return fmt.Sprintf("%+3d%02d%05.2f", int(f), int(m), (m-float64(int(m)))*60.0) } return "" }, "lon": func(s string) string { if f, err := strconv.ParseFloat(s, 64); err == nil { m := math.Abs(f-float64(int(f))) * 60.0 return fmt.Sprintf("%+3d%02d%05.2f", int(f), int(m), (m-float64(int(m)))*60.0) } return "" }, } tmpl, err := template.New("").Funcs(tplFuncMap).Parse(sitelogTemplate) if err != nil { log.Fatalf("error: unable to compile template: %v", err) } var firmwareHistoryList meta.FirmwareHistoryList if err := meta.LoadList(filepath.Join(install, "firmware.csv"), &firmwareHistoryList); err != nil { log.Fatalf("error: unable to load firmware history: %v", err) } firmwareHistory := make(map[string]map[string][]meta.FirmwareHistory) for _, i := range firmwareHistoryList { if _, ok := firmwareHistory[i.Model]; !ok { firmwareHistory[i.Model] = make(map[string][]meta.FirmwareHistory) } firmwareHistory[i.Model][i.Serial] = append(firmwareHistory[i.Model][i.Serial], i) } for j, _ := range firmwareHistory { for k, _ := range firmwareHistory[j] { sort.Sort(meta.FirmwareHistoryList(firmwareHistory[j][k])) } } var installedAntennaList meta.InstalledAntennaList if err := meta.LoadList(filepath.Join(install, "antennas.csv"), &installedAntennaList); err != nil { log.Fatalf("error: unable to load antenna installs: %v", err) } installedAntenna := make(map[string][]meta.InstalledAntenna) for _, i := range installedAntennaList { installedAntenna[i.Mark] = append(installedAntenna[i.Mark], i) } for i, _ := range installedAntenna { sort.Sort(meta.InstalledAntennaList(installedAntenna[i])) } var deployedReceiverList meta.DeployedReceiverList if err := meta.LoadList(filepath.Join(install, "receivers.csv"), &deployedReceiverList); err != nil { log.Fatalf("error: unable to load receiver installs: %v", err) } deployedReceivers := make(map[string][]meta.DeployedReceiver) for _, i := range deployedReceiverList { deployedReceivers[i.Mark] = append(deployedReceivers[i.Mark], i) } for i, _ := range deployedReceivers { sort.Sort(meta.DeployedReceiverList(deployedReceivers[i])) } var installedRadomeList meta.InstalledRadomeList if err := meta.LoadList(filepath.Join(install, "radomes.csv"), &installedRadomeList); err != nil { log.Fatalf("error: unable to load radome installs: %v", err) } installedRadomes := make(map[string][]meta.InstalledRadome) for _, i := range installedRadomeList { installedRadomes[i.Mark] = append(installedRadomes[i.Mark], i) } for i, _ := range installedRadomes { sort.Sort(meta.InstalledRadomeList(installedRadomes[i])) } var installedMetSensorList meta.InstalledMetSensorList if err := meta.LoadList(filepath.Join(install, "metsensors.csv"), &installedMetSensorList); err != nil { log.Fatalf("error: unable to load metsensors list: %v", err) } installedMetSensors := make(map[string][]meta.InstalledMetSensor) for _, i := range installedMetSensorList { installedMetSensors[i.Mark] = append(installedMetSensors[i.Mark], i) } for i, _ := range installedMetSensors { sort.Sort(meta.InstalledMetSensorList(installedMetSensors[i])) } var markList meta.MarkList if err := meta.LoadList(filepath.Join(network, "marks.csv"), &markList); err != nil { log.Fatalf("error: unable to load mark list: %v", err) } var sessionList meta.SessionList if err := meta.LoadList(filepath.Join(install, "sessions.csv"), &sessionList); err != nil { log.Fatalf("error: unable to load session list: %v", err) } sessions := make(map[string][]meta.Session) for _, s := range sessionList { sessions[s.Mark] = append(sessions[s.Mark], s) } var monumentList meta.MonumentList if err := meta.LoadList(filepath.Join(network, "monuments.csv"), &monumentList); err != nil { log.Fatalf("error: unable to load monument list: %v", err) } monuments := make(map[string]meta.Monument) for _, m := range monumentList { monuments[m.Mark] = m } for _, m := range markList { if _, ok := monuments[m.Code]; !ok { continue } if _, ok := sessions[m.Code]; !ok { continue } if _, ok := installedAntenna[m.Code]; !ok { continue } if _, ok := deployedReceivers[m.Code]; !ok { continue } var receivers []GnssReceiver var antennas []GnssAntenna var metsensors []GnssMetSensor for _, m := range installedMetSensors[m.Reference.Code] { var session *meta.Session for i, s := range sessions[m.Mark] { if m.Start.After(s.End) || m.End.Before(s.Start) { continue } session = &sessions[m.Mark][i] break } if session == nil { continue } metsensors = append(metsensors, GnssMetSensor{ Manufacturer: m.Make, MetSensorModel: m.Model, SerialNumber: m.Serial, DataSamplingInterval: "360 sec", EffectiveDates: "2000-02-05/CCYY-MM-DD", Notes: "", }) } for _, a := range installedAntenna[m.Code] { var session *meta.Session for i, s := range sessions[m.Code] { if a.Start.After(s.End) || a.End.Before(s.Start) { continue } session = &sessions[m.Code][i] break } if session == nil { continue } radome := "NONE" serial := "" if _, ok := installedRadomes[m.Code]; ok { for _, v := range installedRadomes[m.Code] { if v.Start.After(a.End) || v.End.Before(a.Start) { continue } radome = v.Model serial = v.Serial } } antennas = append(antennas, GnssAntenna{ AntennaType: a.Model, SerialNumber: a.Serial, AntennaReferencePoint: "BAM", MarkerArpUpEcc: strconv.FormatFloat(a.Vertical, 'f', 4, 64), MarkerArpNorthEcc: strconv.FormatFloat(a.North, 'f', 4, 64), MarkerArpEastEcc: strconv.FormatFloat(a.East, 'f', 4, 64), AlignmentFromTrueNorth: "0", AntennaRadomeType: radome, RadomeSerialNumber: serial, AntennaCableType: "", AntennaCableLength: "", DateInstalled: a.Start.Format(DateTimeFormat), DateRemoved: func() string { if time.Now().After(a.End) { return a.End.Format(DateTimeFormat) } else { return "" } }(), Notes: "", }) } for _, r := range deployedReceivers[m.Code] { if _, ok := firmwareHistory[r.Model]; ok { if _, ok := firmwareHistory[r.Model][r.Serial]; ok { for i, _ := range firmwareHistory[r.Model][r.Serial] { v := firmwareHistory[r.Model][r.Serial][len(firmwareHistory[r.Model][r.Serial])-i-1] if v.End.Before(r.Start) || v.Start.After(r.End) { continue } var session *meta.Session for i, s := range sessions[m.Code] { if r.Start.After(s.End) || r.End.Before(s.Start) { continue } if v.Start.After(s.End) || v.End.Before(s.Start) { continue } session = &sessions[m.Code][i] break } if session == nil { continue } start := r.Start /* if start.Before(s.Start) { start = s.Start } */ if start.Before(v.Start) { start = v.Start } end := r.End /* if end.After(s.End) { end = s.End } */ if end.After(v.End) { end = v.End } receivers = append(receivers, GnssReceiver{ ReceiverType: r.Model, SatelliteSystem: session.SatelliteSystem, SerialNumber: r.Serial, FirmwareVersion: v.Version, ElevationCutoffSetting: strconv.FormatFloat(session.ElevationMask, 'g', -1, 64), DateInstalled: start.Format(DateTimeFormat), /* DateInstalled: func() string { if v.Start.Before(r.Start) { return r.Start.Format(DateTimeFormat) } else { return v.Start.Format(DateTimeFormat) } }(), */ DateRemoved: func() string { /* if v.End.After(r.End) { if time.Now().After(r.End) { return r.End.Format(DateTimeFormat) } else { return "" } } else { if time.Now().After(v.End) { return v.End.Format(DateTimeFormat) } else { return "" } } */ if time.Now().After(end) { return end.Format(DateTimeFormat) } else { return "" } }(), TemperatureStabilization: "", Notes: "", }) } } } } sort.Sort(GnssReceivers(receivers)) sort.Sort(GnssAntennas(antennas)) monument := monuments[m.Code] X, Y, Z := WGS842ITRF(m.Latitude, m.Longitude, m.Elevation) x := SiteLog{ EquipNameSpace: equipNameSpace, ContactNameSpace: contactNameSpace, MiNameSpace: miNameSpace, LiNameSpace: liNameSpace, XmlNameSpace: xmlNameSpace, XsiNameSpace: xsiNameSpace, SchemaLocation: schemaLocation, FormInformation: FormInformation{ PreparedBy: preparedBy, DatePrepared: time.Now().Format(DateFormat), ReportType: "DYNAMIC", }, SiteIdentification: SiteIdentification{ SiteName: m.Name, FourCharacterID: m.Code, MonumentInscription: "", IersDOMESNumber: monument.DomesNumber, CdpNumber: "", MonumentDescription: monument.Type, HeightOfTheMonument: strconv.FormatFloat(-monument.GroundRelationship, 'g', -1, 64), MonumentFoundation: monument.FoundationType, FoundationDepth: strconv.FormatFloat(monument.FoundationDepth, 'f', 1, 64), MarkerDescription: func() string { switch monument.MarkType { case "Forced Centering": return "Forced Centering" default: return "unknown" } }(), DateInstalled: m.Start.Format(DateTimeFormat), GeologicCharacteristic: "", BedrockType: "", BedrockCondition: "", FractureSpacing: "", FaultZonesNearby: "", DistanceActivity: "", Notes: "", }, SiteLocation: SiteLocation{ /* City: m.Place, State: m.Region, */ Country: func(lat, lon float64) string { X, Y, _ := WGS842ITRF(lat, lon, 0.0) dist := float64(-1.0) country := "Unknown" for _, v := range countryList { x, y, _ := WGS842ITRF(v.lat, v.lon, 0.0) r := math.Sqrt((x-X)*(x-X) + (y-Y)*(y-Y)) if dist < 0.0 || r < dist { country = v.name dist = r } } return country }(m.Latitude, m.Longitude), TectonicPlate: TectonicPlate(m.Latitude, m.Longitude), ApproximatePositionITRF: ApproximatePositionITRF{ XCoordinateInMeters: strconv.FormatFloat(X, 'f', 1, 64), YCoordinateInMeters: strconv.FormatFloat(Y, 'f', 1, 64), ZCoordinateInMeters: strconv.FormatFloat(Z, 'f', 1, 64), LatitudeNorth: strconv.FormatFloat(m.Latitude, 'g', -1, 64), LongitudeEast: strconv.FormatFloat(m.Longitude, 'g', -1, 64), ElevationMEllips: strconv.FormatFloat(m.Elevation, 'f', 1, 64), }, Notes: "", }, GnssReceivers: receivers, GnssAntennas: antennas, GnssMetSensors: metsensors, ContactAgency: contactAgency, ResponsibleAgency: func() Agency { switch m.Network { case "LI": return responsibleAgency default: return Agency{ MailingAddress: "\n", } } }(), MoreInformation: MoreInformation{ PrimaryDataCenter: primaryDatacentre, SecondaryDataCenter: "", UrlForMoreInformation: urlForMoreInformation, HardCopyOnFile: "", SiteMap: "", SiteDiagram: "", HorizonMask: "", MonumentDescription: "", SitePictures: "", Notes: extraNotes + " " + m.Code, AntennaGraphicsWithDimensions: func() string { var graphs []string models := make(map[string]interface{}) for _, a := range antennas { if _, ok := models[a.AntennaType]; ok { continue } if g, ok := antennaGraphs[a.AntennaType]; ok { b, err := hex.DecodeString(g) if err != nil { log.Printf("error: unable to decode antenna graph for: \"%s\"", a.AntennaType) continue } graphs = append(graphs, strings.Join([]string{a.AntennaType, string(b)}, "\n")) } else { log.Printf("warning: missing antenna graph for: \"%s\"", a.AntennaType) } models[a.AntennaType] = true } return strings.Join(graphs, "\n") + "\n" }(), InsertTextGraphicFromAntenna: "", }, } s, err := x.Marshal() if err != nil { log.Fatalf("error: unable to marshal xml: %v", err) } xmlfile := filepath.Join(output, strings.ToLower(m.Code)+".xml") if err := os.MkdirAll(filepath.Dir(xmlfile), 0755); err != nil { log.Fatalf("error: unable to create dir: %v", err) } if err := ioutil.WriteFile(xmlfile, s, 0644); err != nil { log.Fatalf("error: unable to write file: %v", err) } logfile := filepath.Join(logs, strings.ToLower(m.Code)+".log") if err := os.MkdirAll(filepath.Dir(logfile), 0755); err != nil { log.Fatalf("error: unable to create logs dir: %v", err) } f, err := os.Create(logfile) if err != nil { log.Fatalf("error: unable to create log file: %v", err) } defer f.Close() if err := tmpl.Execute(f, x); err != nil { log.Fatalf("error: unable to write log file: %v", err) } } }