From f3739d7fd885950bdd1b98c438c06f82544261dc Mon Sep 17 00:00:00 2001 From: Suvir Kumar Date: Sun, 9 May 2021 12:49:54 +0700 Subject: [PATCH] Added traccar gps tracking support contributed by Zoran --- client.go | 12 +- commandkeys.go | 76 +++++- gps.go | 722 ++++++++++++++++++++++++++++++++++++++++++++++--- xmlparser.go | 96 ++++++- 4 files changed, 835 insertions(+), 71 deletions(-) diff --git a/client.go b/client.go index 652b9ab..b1c3473 100644 --- a/client.go +++ b/client.go @@ -62,10 +62,6 @@ var ( origVolume int tempVolume int ConfigXMLFile string - GPSTime string - GPSDate string - GPSLatitude float64 - GPSLongitude float64 Streaming bool ServerHop bool HTTPServRunning bool @@ -73,6 +69,14 @@ var ( isrepeattx bool = true NowStreaming bool MyLedStrip *LedStrip + GPSTime string + GPSDate string + GPSLatitude float64 + GPSLongitude float64 + GPSSpeed float64 + GPSCourse float64 + GPSVariation float64 + m string ) type Talkkonnect struct { diff --git a/commandkeys.go b/commandkeys.go index 5123240..f9b2178 100644 --- a/commandkeys.go +++ b/commandkeys.go @@ -741,7 +741,13 @@ func (b *Talkkonnect) cmdPanicSimulation() { b.SendMessage(fmt.Sprintf("My Username is %s and Ident is %s", b.Username, b.Ident), PRecursive) } - if PSendGpsLocation && GpsEnabled { + // New. Need to allow sending email / text alert on Panic Event even is the GPS is not enabled or working. + // If no GPS is included in email / Mumble text message, it means GPS in not enabled or not working. + + //if PSendGpsLocation && GpsEnabled { + //if GpsEnabled { + + if PSendGpsLocation { var i int = 0 var tries int = 10 @@ -784,21 +790,71 @@ func (b *Talkkonnect) cmdPanicSimulation() { b.TxLockTimer() } + // New. Send email after Panic Event // + if PMailEnabled == true { + b.cmdSendEmail() + log.Println("info: Sending Panic Alert Email To Predefined Email Address") + } + // + + // New. Record ambient audio on Panic Event if recording is enabled + if AudioRecordEnabled == true { + log.Println("info: Running sox for Audio Recording...") + AudioRecordAmbient() + } + // + } else { log.Println("warn: Panic Function Disabled in Config") } IsPlayStream = false b.IsTransmitting = false - if TargetBoard == "rpi" { - if !LedStripEnabled { - b.LEDOff(b.TransmitLED) - } else { - MyLedStripTransmitLEDOff() - } - } - } -} + // New. Decide should TX Led be On or Off during a panic event? I think don't turn off here, + // Want to see PTT key working when testing panic function. + // We shall use another low profile lights/LCD function to turn all the lights and display off during panic event + // They should be dim. Not attracting attention + //if TargetBoard == "rpi" { + //if !LedStripEnabled { + //b.LEDOff(b.TransmitLED) + //} else { + // + //MyLedStripTransmitLEDOff() + //} + //log.Println("--") + + //New. Low Profile Leds and LCD during Panic Event. Turn All Lights Off. + //Heartbeat will be running - disable in xml config? + //Backlight LCD led is dim with a transistor control, but it should work... + //Add another feature to enable all lights back on a PTT press after the panic event is over. To do? + + if PLowProfile == true { + b.LEDOffAll() + log.Println("info: Low Profile Lights Option is Enabled. Turning All Leds Off During Panic Event") + + //b.LEDOff(b.TransmitLED) + //b.LEDOff(b.BackLightLED) + //b.LEDOff(b.OnlineLED) + //b.LEDOff(b.ParticipantsLED) + //b.LEDOff(b.VoiceActivityLED) + // + //b.LEDOff(b.HeartBeatLED) + // + + if LCDEnabled == true { + log.Println("info: Low Profile Lights is Enabled. Turning Off Display During Panic Event") + LcdText = [4]string{"", "", "", ""} + LcdDisplay(LcdText, LCDRSPin, LCDEPin, LCDD4Pin, LCDD5Pin, LCDD6Pin, LCDD7Pin, LCDInterfaceType, LCDI2CAddress) + } + if OLEDEnabled == true { + oledDisplay(true, 0, 0, "") // clear OLED screen. How about HD44780 and heartbit? + } + // End of Low Profile Lights + + } + } + } + func (b *Talkkonnect) cmdRepeatTxLoop() { log.Println("debug: Ctrl-R Pressed") diff --git a/gps.go b/gps.go index 7be282d..9b10246 100644 --- a/gps.go +++ b/gps.go @@ -19,12 +19,17 @@ * * Contributor(s): * - * Suvir Kumar + * Zoran Dimitrijevic * * My Blog is at www.talkkonnect.com * The source code is hosted at github.com/talkkonnect * - * gps.go -> talkkonnect function to interface to USB GPS Neo6M + * gps.go -> talkkonnect function to interface to U-blox Neo-6M, Neo-7 (VK-172), Neo-8 and + * possibly other low cost serial or USB GPS boards from other manufacturers widely used + * with Arduino and Raspberry Pi. + * + * Integration for tracking talkkonnect GPS enabled devices with Traccar + * server from https://www.traccar.org */ package talkkonnect @@ -34,25 +39,41 @@ import ( "encoding/hex" "errors" "fmt" + "github.com/jacobsa/go-serial/serial" + hd44780 "github.com/talkkonnect/go-hd44780" + "github.com/talkkonnect/go-nmea" + "io" "io/ioutil" "log" + "net" "net/http" - - "github.com/jacobsa/go-serial/serial" - "github.com/talkkonnect/go-nmea" + "strings" + "time" + //"encoding/json" // used for testing http api for flespi ) var ( - sendToTracCar bool = true - tracCarURL string = "http://demo.traccar.org" - tracCarPort string = "5060" - tracCarID string = "12345" - tracCarFullURL string = "" + TraccarPortOsmAnd string = "5055" // Traccar Client port 5055 for working with OsmAnd Protocol + TraccarPortT55 string = "5005" // Old Traccar Client port 5005 for working with T55 Protocol + TraccarPortOpenGTS string = "5159" // Traccar Client port 5159 for for working OpenGTS Protocol ) +//A test http request for OsmAnd protocol and passing basic $GPRMC information to Traccar. +//http://10.8.0.1:5055?id=12345×tamp=2019-10-05%20&lat=44.000000&lon=20.000000&speed=0.000&course=0.000000&variation=0.000000 +//More info about OsmAnd for Traccar: https://www.traccar.org/osmand + +//A request example for OpenGTS protocol in Traccar... +//http://10.8.0.1:5159/?id=12345&gprmc=$GPRMC,094852,A,4446.8347,N,02030.9393,E,0.0147,69.114,041019,,*10 + +// Supported protocols for communicating with Traccar: OsmAnd, T55 and OpenGTS. +// OsmAnd and OpenGTS use http. T55 use tcp socket connection (udp is also possible). + var goodGPSRead bool = false +// GPS Serial reading. + func getGpsPosition(verbose bool) (bool, error) { + if GpsEnabled { if Port == "" { @@ -60,7 +81,7 @@ func getGpsPosition(verbose bool) (bool, error) { } if Even && Odd { - return false, errors.New("can't specify both even and odd parity") + return false, errors.New("Can't Specify both Even and Odd Parity") } parity := serial.PARITY_NONE @@ -85,11 +106,12 @@ func getGpsPosition(verbose bool) (bool, error) { } f, err := serial.Open(options) - defer f.Close() if err != nil { GpsEnabled = false return false, errors.New("Cannot Open Serial Port") + } else { + defer f.Close() } if TxData != "" { @@ -97,23 +119,25 @@ func getGpsPosition(verbose bool) (bool, error) { if err != nil { GpsEnabled = false - return false, errors.New("error: Cannot Decode Hex Data") + return false, errors.New("Cannot Decode Hex Data") } - log.Println("debug: Sending: ", hex.EncodeToString(txData)) + log.Println("info: Sending: ", hex.EncodeToString(txData)) count, err := f.Write(txData) if err != nil { - return false, errors.New("error: Error writing to serial port") + return false, errors.New("Error writing to serial port") + } else { + log.Println("info: Wrote %v bytes\n", count) } - log.Println("debug: Wrote %v bytes\n", count) + } if Rx { serialPort, err := serial.Open(options) if err != nil { - log.Println("error: Unable to Open Serial Port Error ", err) + log.Println("warn: Unable to Open Serial Port Error ", err) } defer serialPort.Close() @@ -126,64 +150,674 @@ func getGpsPosition(verbose bool) (bool, error) { s, err := nmea.Parse(scanner.Text()) if err == nil { + + /*if s.DataType() == nmea.TypeGGA { + g := s.(nmea.RMC) + if g.Latitude != 0 && g.Longitude != 0 { + goodGPSRead = true + fmt.Println(...) + */ + // Try to read other sentences containing useful info like $GPGGA, ... + // and print useful info, altitude, number of satellites, fix quality, etc. To Do. + if s.DataType() == nmea.TypeRMC { m := s.(nmea.RMC) if m.Latitude != 0 && m.Longitude != 0 { goodGPSRead = true - tracCarFullURL = fmt.Sprintf(tracCarURL + ":" + tracCarPort + "?" + "id=" + tracCarID + "&" + "lat={" + nmea.FormatGPS(m.Latitude) + "}" + "&" + "lon={" + nmea.FormatGPS(m.Longitude) + "}" + "&" + "timestamp={" + GPSTime + "}" + "&" + "hdop={" + "}" + "&a") - GPSTime = fmt.Sprintf("%v", m.Time) - GPSDate = fmt.Sprintf("%v", m.Date) + + //if m.Speed != 0 && m.Course != 0 { + //isVehicleMoving = true // Report if vehicle moves or overspeeds? + //if m.Speed >> some km/h + // Send a text alert to Mumble or email? + + // Read GGA Info for FixQuality, NumSatellites, Altitude ... To Do.. + // https://github.com/adrianmo/go-nmea/blob/master/gga.go + //... + + /*if TrackEnabled == true { + if TraccarSendTo == true { + if TraccarProto == "osmand" { + TraccarServerFullURL = (fmt.Sprint(TraccarServerURL) + ":" + fmt.Sprint(TraccarPortOsmAnd) + "?" + "id=" + TraccarClientId + "&" + "timestamp=" + date2() + "%20" + time2() + "&" + "lat=" + fmt.Sprintf("%f", m.Latitude)+ "&" + "lon=" + fmt.Sprintf("%f", m.Longitude) + "&" + "speed=" + fmt.Sprintf("%f", m.Speed) + "&" + "course=" + fmt.Sprintf("%f", m.Course) + "&" + "variation=" + fmt.Sprintf("%f", m.Variation)) + } else if TraccarProto == "opengts" { + TraccarServerFullURL = fmt.Sprint(TraccarServerURL) + ":" + fmt.Sprint(TraccarPortOpenGTS) + "/?" + "id=" + TraccarClientId + "&" + "gprmc=" + fmt.Sprint(m) + //TraccarServerFullURL = fmt.Sprint(TraccarServerURL) + ":" + fmt.Sprint(TraccarPortOpenGTS) + "?" + "id=" + TraccarClientId + "&" + "timestamp=" + Date2 + "%20" + Time2 + "&" + "lat=" + fmt.Sprintf("%f", m.Latitude) + "&" + "lon=" + fmt.Sprintf("%f", m.Longitude) + "&" + "speed=" + fmt.Sprint(m.Speed) + "&" + "course=" + fmt.Sprintf("%f", m.Course) + "&" + "variation=" + fmt.Sprintf("%f", m.Variation) + } else if TraccarProto == "t55" { + TraccarServerFullURL = "" + } + } + } + } + */ + + // This is a request example for OpenGTS protocol in Traccar. Use port 5159. + // http://10.8.0.1:5159/?id=12345&gprmc=$GPRMC,094852,A,4446.8347,N,02030.9393,E,0.0147,69.114,041019,,*10 + // http://10.8.0.1:5159/?id=12345&gprmc=$GPRMC,114614.00,A,4446.82735,N,02030.94387,E,0.030,,151019,,,A*70 + + FreqReport := float64(TraccarReportFrequency) // Reporting Frequency + FreqReports := (time.Duration(TraccarReportFrequency) * time.Second) // Frequency of GPS Reporting. Minutes, Seconds or hours? + + //FreqReportm := (FreqReports / 60) // in minutes + //FreqReport := 60 // Reporting Frequency + //FreqReports := (time.Duration(FreqReport) * time.Second) // Frequency of GPS Reporting. Minutes, Seconds or hours? + //FreqReportm := (FreqReport / 60) // minutes + //FreqReportH := (FreqReports/(60*60)) // hours + //FreqReportD := (FreqReports/(60*60*24)) // days + //Improve calc with time/ string to print reporting freq in minutes or seconds, as needed. + + // Position Reporter + + // send GPS position once immediately on start + if TrackEnabled == true && TraccarSendTo == true { + if TraccarProto == "t55" { + go tcpSendT55Traccar2() // Initial Send GPS position to Traccar with old T55 client protocol. No keep-alive. + //tcpSendT55Traccar1() // Initial Send GPS position to Traccar with old T55 client protocol. Keep-alive. + } else { + go httpSendTraccar() // Initial Send GPS position to Traccar over http function for both OsmAnd or OpenGTS protocol. + //flespi() // Test flespi + } + log.Println("info: GPS Position Report Nr (1) Sent to Traccar Server") + } + + // Now, keep sending GPS position and counting how many reports were sent? + + PositionReporter := time.NewTicker(FreqReports) + var TraccarCounter = 1 + go func() { + for _ = range PositionReporter.C { + if TrackEnabled == true && TraccarSendTo == true { + if TraccarProto == "t55" { + tcpSendT55Traccar2() // Send GPS position to Traccar with old T55 client protocol. No keep-alive. + //tcpSendT55Traccar1() // Send GPS position to Traccar with old T55 client protocol. Keep-alive. + } else { + httpSendTraccar() // Send GPS position to Traccar over http function for both OsmAnd or OpenGTS protocol. + //flespi() // Test flespi + } + } + TraccarCounter++ + + if verbose { + if TrackEnabled == true && TraccarSendTo == true { + if TraccarProto == "osmand" { + log.Println("info: OsmAnd: ", TraccarServerURL+":"+fmt.Sprint(TraccarPortOsmAnd)+"?"+"id="+TraccarClientId+"&"+"timestamp="+date2()+"%20"+time2()+"&"+"lat="+fmt.Sprint(m.Latitude)+"&"+"lon="+fmt.Sprint(m.Longitude)+"&"+"speed="+fmt.Sprint(m.Speed)+"&"+"course="+fmt.Sprint(m.Course)+"&"+"variation="+fmt.Sprint(m.Variation)) + } else if TraccarProto == "t55" { + log.Println("info: T55: " + "Sending " + fmt.Sprint(m) + " to " + TraccarServerURL + ":" + fmt.Sprint(TraccarPortT55)) + } else if TraccarProto == "opengts" { + log.Println("info: OpenGTS: ", TraccarServerURL+":"+fmt.Sprint(TraccarPortOpenGTS)+"/?"+"id="+TraccarClientId+"&"+fmt.Sprint(m)) + } + log.Println("info: GPS Position Report Nr " + "(" + fmt.Sprint(TraccarCounter) + ")" + " Sent to Traccar Server. Next Position Report in " + fmt.Sprintf("%.2f", FreqReport/60) + " minute(s)") + } + } + + //Display Show GPS Position. + + if TargetBoard == "rpi" { + if TrackEnabled == true { + if TrackGPSShowLCD == true { + log.Println("info: Showing GPS Info in LCD: " + "Lat: " + fmt.Sprint(m.Latitude) + " Long: " + fmt.Sprint(m.Longitude)) + time.Sleep(5 * time.Second) + t := time.Now() + if LCDEnabled == true { + LcdText = [4]string{"nil", "GPS OK " + t.Format("15:04:05"), "lat:" + fmt.Sprintf("%f", m.Latitude), "lon:" + fmt.Sprintf("%f", m.Longitude) + " s:" + fmt.Sprintf("%.2f", m.Speed*1.852)} // 1 knot = 1.852 km. Take LCD rows 1-3 + // Option: narrow down GPS LCD writing to rows 2-3. Row 2, status, row 3, grid. + go hd44780.LcdDisplay(LcdText, LCDRSPin, LCDEPin, LCDD4Pin, LCDD5Pin, LCDD6Pin, LCDD7Pin, LCDInterfaceType, LCDI2CAddress) // Take LCD rows 2-3. + } + if OLEDEnabled == true { + oledDisplay(false, 4, 1, "GPS OK "+t.Format("15:04:05")) + oledDisplay(false, 5, 1, "lat: "+fmt.Sprintf("%f", m.Latitude)) + oledDisplay(false, 6, 1, "lon: "+fmt.Sprintf("%f", m.Longitude)) + oledDisplay(false, 7, 1, "sp: "+fmt.Sprintf("%.2f", (m.Speed*1.852))) + } + } + } + } + + } + }() + + GPSDate := fmt.Sprintf("%v", m.Date) + GPSTime := fmt.Sprintf("%v", m.Time) + + // Traccar needs timestamp in this format "timestamp=2019-01-15%2021:41:18" + // for OsmAnd protocol. Date and time are concatenated in the same line with escape + // %20 character in the middle. m.Date needs to change from + // 19/10/04 to 2019-10-04, m.Time from GPS 23:27:15.0000s must have ms truncated. + // date and time are parsed as timestapmp= ... and must use this format + // "04-10-19 23:27:15" or "04-10-19%2023:27:15" + + //GPSDate = m.Date + //GPSTime = m.Time + GPSLatitude = m.Latitude GPSLongitude = m.Longitude + GPSSpeed = m.Speed + GPSCourse = m.Course + GPSVariation = m.Variation + + Date1 := fmt.Sprint(gpsdatereorder()) // Reformatted date for Tracar + Time1 := fmt.Sprintf("%s", truncateString(GPSTime, 8)) // Truncate time for Traccar + + currentTime := time.Now() + //Date2 := fmt.Sprintf(currentTime.Format("2006-01-02")) + //Time2 := fmt.Sprintf("%s", currentTime.Format("15:04:05")) + if verbose { - log.Println("info: Time: ", m.Time) + // Testing date and time format + log.Println("info: Date and Time from GPS: ", (GPSDate + " " + GPSTime)) + log.Println("info: Date and Time from GPS Reformatted for Traccar: ", (Date1 + " " + Time1)) // From GPS + //log.Println("info: Date from Helper:", fmt.Sprint(gpsdatereorder())) // Need this date for Traccar + log.Println("info: System Date with time.now Function:", currentTime.Format("2006-01-02")) + log.Println("info: System Time with time.now function:", currentTime.Format("15:04:05")) + log.Println("info: System Date & Time with time.now Function:", currentTime.Format("2006-01-02 15:04:05")) //currentTime.Format("2006-01-02 3:4:5") + // Workaround for date time format. Preferablly always use GPS time, and only if not the system time. + log.Println("info: GPS Date: ", m.Date) + log.Println("info: GPS Time: ", m.Time) log.Println("info: Validity: ", m.Validity) - log.Println("info: Latitude GPS: ", nmea.FormatGPS(m.Latitude)) + log.Println("info: Latitude Decimal: ", m.Latitude) + log.Println("info: Longitude Decimal: ", m.Longitude) log.Println("info: Latitude DMS: ", nmea.FormatDMS(m.Latitude)) - log.Println("info: Longitude GPS: ", nmea.FormatGPS(m.Longitude)) log.Println("info: Longitude DMS: ", nmea.FormatDMS(m.Longitude)) - log.Println("info: Speed: ", m.Speed) + log.Println("info: Latitude GPS: ", nmea.FormatGPS(m.Latitude)) + log.Println("info: Longitude GPS: ", nmea.FormatGPS(m.Longitude)) + log.Println("info: Speed: ", m.Speed) // Is this knots? log.Println("info: Course: ", m.Course) - log.Println("info: Date: ", m.Date) log.Println("info: Variation: ", m.Variation) - log.Println(tracCarFullURL) + log.Println("info: Traccar Cmd Osmand: " + fmt.Sprint(TraccarServerFullURL)) + log.Println("info: Traccar $GPRMC Sentence for T55/OpenGTS: " + fmt.Sprint(m)) + if TrackEnabled == true { + //log.Println("info: GPS Tracking Enabled: " + fmt.Sprint(TrackEnabled)) + if TraccarSendTo == true { + log.Println("info: Sending GPS Position to Traccar Server Enabled") + log.Println("info: Traccar Protocol: " + strings.Title(strings.ToLower(TraccarProto)) + "; " + "Reporting Frequency: " + fmt.Sprintf("%.2f", FreqReport/60) + " minutes;") + //Print GPS message format for sending to Traccar depending on tracking protocol. + + switch TraccarProto { + case "osmand": + log.Println("info: OsmAnd: ", TraccarServerFullURL) + case "opengts": + log.Println("info: OpenGTS: ", TraccarServerIP) + case "t55": + log.Println("info: T55:", fmt.Sprint(m), "...", TraccarServerURL+":"+TraccarPortT55) + default: + log.Println("info: OsmAnd: ", TraccarServerFullURL) + } + } + } + } // + + break + + } else { + log.Println("warn: Got Latitude 0 and Longtitude 0 from GPS") } - if sendToTracCar { - httpSendTracCar() - } - break } else { - log.Println("error: Got Latitude 0 and Longtitude 0 from GPS") + log.Println("warn: GPS Sentence Format Was not nmea.RMC") } } else { - log.Println("error: GPS Sentence Format Was not nmea.RMC") + log.Println("warn: Scanner Function Error ", err) } - } else { - log.Println("error: Scanner Function Error ", err) } - } + + // } // + } else { return false, errors.New("Rx Not Set") } - return goodGPSRead, nil } - return false, errors.New("GPS Not Enabled") + return false, errors.New("GPS Not Enabled. Or Not Connected") +} + +/* +GPS Reporter function. Need more work. +func gpsReporter() { +//ticker := time.NewTicker(60 * time.Second) // send every 60 seconds. +ticker := time.NewTicker(time.Duration(int64(TraccarReportFrequency)) * time.Second) // send every ... seconds. +done := make(chan bool) +go func() { +for { +select { +case <-done: +return +case t := <-ticker.C: +//httpSendTraccar() +//tcpSendT55Traccar1() +//tcpSendT55Traccar2() +log.Println("info: GPS Position Sent to Traccar Server over" + strings.Title(strings.ToLower(TraccarProto)) + "protocol", t) +//log.Println("info: OsmAnd: ", fmt.Sprintf(TraccarServerURL + ":" + TraccarPortOsmAnd + "?" + "id=" + TraccarClientId) + "&" + "timestamp=" + Date2 + "%" + "20" + Time2 + "&" + "lat=" + fmt.Sprintf("%f", m.Latitude) + "&" + "lon=" + fmt.Sprintf("%f", m.Longitude) + "&" + "speed=" + fmt.Sprint(m.Speed) + "&" + "course=" + fmt.Sprintf("%f", m.Course) + "&" + "variation=" + fmt.Sprintf("%f", m.Variation)) +//log.Println("info: GPS Position Sent to Traccar Server. Next Position Report in " + fmt.Sprintf(strconv.Itoa(FreqReportm)) + " minute(s)") } +} +}() +} + +*/ + +/* T55 Protocol. +Info: https://www.traccar.org/traccar-client-protocol +T55 protocol is used by old version of Traccar Client. +New version use OsmAnd protocol. T55 Protocol uses TCP/IP as a transport layer. +It is more simple. Can be UDP also, but it is less reliable. Messages are separated +simply by carriage return and line feed characters (\r\n). + +How to format T55 message for sending to Traccar? + +Login (send once the TCP connection is establshed): +$PGID,12345*0F\r\n (where 12345 - IMEI or other unique id) -func httpSendTracCar() { - response, err := http.Get(tracCarFullURL) +Simple location report format is just a standard NMEA GPRMC sentence: +$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68\r\n + +225446 - Time of fix 22:54:46 UTC +A - Navigation receiver warning A = OK, V = warning +4916.45,N - Latitude 49 deg. 16.45 min North +12311.12,W - Longitude 123 deg. 11.12 min West +000.5 - Speed over ground, Knots +054.7 - Course Made Good, True +191194 - Date of fix 19 November 1994 +020.3,E - Magnetic variation 20.3 deg East +*68 - Checksum + +Extended location report format: + +$TRCCR,20140111000000.000,A,60.000000,60.000000,0.00,0.00,0.00,50,*3a\r\n + +20140111000000.000 - Date and tim of fix 2014-01-11 00:00:00.000 UTC +A - Navigation receiver warning A = OK, V = warning +60.000000 - Latitude in degrees 60 deg (negative for south hemisphere) +60.000000 - Longitude in degrees 60 deg (negative for west hemisphere) +0.00 - Speed over ground, Knots +0.00 - Course Made Good, True +0.00 - Altitude in meters +50 - Battery level +*/ + +//T55 (1) +//A Simple TCP connection. No keep-alive. +//Parse full NMEA sentence from gpspipe to Traccar message, follow with \r\n. + +func tcpSendT55Traccar1() { + + //Hard coded message for testing + //pgid := "$PGID,12345*0F\r\n" // Unique Client ID (e.g. 12345). Follow with carriage return and line feed characters (\r\n). + //gprmc := "$GPRMC,114614.00,A,4446.82735,N,02030.94387,E,0.030,,151019,,,A*70\r\n" // Test sentence. Send after pgid. Follow with \r\n. + + pgid := "$PGID" + "," + TraccarClientId + "*0F" + "\r" + "\n" // Unique Client ID (e.g. 12345). Follow with carriage return and line feed characters (\r\n). + //Seems to be working + gprmc := fmt.Sprint(m) + "\r" + "\n" + log.Println("info: $GPRMC to send is: " + fmt.Sprint(m)) + + //Here is a simple tcp connecton. No keep-alive. + //conn, err := net.Dial("tcp", TraccarServerIP + ":" + TraccarPortT55) // Use port 5005 for T55. No keep-alive. + //if err != nil { + //fmt.Println(err) + //return + //} + + // Connect to Traccar Server tcp socket + conn, _ := net.Dial("tcp", fmt.Sprint(TraccarServerIP)+":"+fmt.Sprint(TraccarPortT55)) // Use port 5005 for T55. No keep-alive. + + // Here is a keep-alive enable option. + err := conn.(*net.TCPConn).SetKeepAlive(true) if err != nil { - log.Println("error: Cannot Read traccar Webpage! Error ", err) + fmt.Println(err) + return + } + err = conn.(*net.TCPConn).SetKeepAlivePeriod(60 * time.Second) + if err != nil { + fmt.Println(err) + return + } + err = conn.(*net.TCPConn).SetNoDelay(false) + if err != nil { + fmt.Println(err) + return + } + err = conn.(*net.TCPConn).SetLinger(0) + if err != nil { + fmt.Println(err) + return + } + // keep-alive + + //log.Println("info: Sending T55 Position Report to Traccar ") + //log.Println("info: Connection Established with Traccar Server :", TraccarServerIP) + //log.Println("info: Remote Traccar Server Address :", conn.RemoteAddr().String()) + //log.Println("info: Local Traccar Client Address :", conn.LocalAddr().String()) + + log.Println("info: Traccar Client:", conn.LocalAddr().String(), "Connected to Server:", conn.RemoteAddr().String()) + + // Connection seems to be working OK. + + // Send a T55 position report... + + fmt.Fprintf(conn, pgid) // Send ID + time.Sleep(1 * time.Second) + fmt.Fprintf(conn, gprmc) // Send $GPRMC + log.Println("info: Sending position message to Traccar over Protocol: " + strings.Title(strings.ToLower(TraccarProto))) + + // Decode HEX messages in Traccar server log to verify sending working? + // TCP dialer disconnects after sending a message and client reports as "offline" in Traccar GUI between sending. + // Client will be seen briefly "online" in Traccar GUI only for a few seconds during connection. + // Note: Use port 5005 for T55. + // Do some error logging if tcp connection drops or sending message fails? +} + +//T55(1) + +//T55(2) +//Another T55 TCP Connection with keep-alive. EOF for indicating a connection drop. +//Keep-alive. Client stays connected between sending position. + +func tcpSendT55Traccar2() { + + //Hard coded for testing + //pgid := "$PGID,12345*0F\r\n" // Unique Client ID (e.g. 12345). Follow with carriage return and line feed characters (\r\n). + //gprmc := "$GPRMC,114614.00,A,4446.82735,N,02030.94387,E,0.030,,151019,,,A*70\r\n" // Test sentence. Send after pgid. Follow \r\n. + + pgid := "$PGID" + "," + TraccarClientId + "*0F" + "\r" + "\n" // Unique Client ID (e.g. 12345). Follow with carriage return and line feed $ + gprmc := fmt.Sprint(m) + "\r" + "\n" + log.Println("info: $GPRMC to send is: " + fmt.Sprint(m)) + fmt.Println(m) + + conn, _ := net.Dial("tcp", TraccarServerIP+":"+fmt.Sprint(TraccarPortT55)) // Use port 5005 for T55. Keep-alive. + err := conn.(*net.TCPConn).SetKeepAlive(true) + if err != nil { + fmt.Println(err) + return + } + err = conn.(*net.TCPConn).SetKeepAlivePeriod(60 * time.Second) + if err != nil { + fmt.Println(err) + return + } + err = conn.(*net.TCPConn).SetNoDelay(false) + if err != nil { + fmt.Println(err) + return + } + err = conn.(*net.TCPConn).SetLinger(0) + if err != nil { + fmt.Println(err) + return + } + + //log.Println("info: Sending T55 Position Report to Traccar ") + //log.Println("info: Connection established with Traccar Server :", TraccarServerIP) + //log.Println("info: Traccar Server Address :", conn.RemoteAddr().String()) + //log.Println("info: Traccar Client Address :", conn.LocalAddr().String()) + + log.Println("info: Traccar Client:", conn.LocalAddr().String(), "Connected to Server:", conn.RemoteAddr().String()) + + // Send a T55 position report... + + fmt.Fprintf(conn, pgid) // Send ID + time.Sleep(1 * time.Second) + fmt.Fprintf(conn, gprmc) // send $GPRMC + log.Println("info: Sending position message to Traccar over Protocol: " + strings.Title(strings.ToLower(TraccarProto))) + + notify := make(chan error) + + // error checking for a closed connection. dispatch a goroutine to read from the connection until there's an EOF error. + + go func() { + buf := make([]byte, 1024) + for { + n, err := conn.Read(buf) + if err != nil { + notify <- err + if io.EOF == err { + close(notify) + return + } + } + + if n > 0 { + log.Println("Unexpected Data: %s", buf[:n]) + //fmt.Println("Unexpected Data: %s", buf[:n]) + } + } + }() + + for { + select { + case err := <-notify: + log.Println("info: Traccar Server Connection dropped message", err) + //fmt.Println("Traccar Server Connection dropped message", err) + + if err == io.EOF { + log.Println("Connection to Traccar Server was closed") + //fmt.Println("Connection to Traccar Server was closed") + return + } + break + case <-time.After(time.Second * 60): + log.Println("Traccar Server Connection Timeout 60. Still Alive") + //fmt.Println("Traccar Server Connection Timeout 60. Still Alive") + } + } +} +// T55(2) End + + +// Sending over OsmAnd and OpenGTS. +// OsmAnd is primary Traccar protocol for sending position over http api. + +// OpenGTS currently not working. Need to check if format parsing is correct? +// Traccar returns 400 http error. +// A request example for OpenGTS protocol in Traccar is... +// http://10.8.0.1:5159/?id=12345&gprmc=$GPRMC,094852,A,4446.8347,N,02030.9393,E,0.0147,69.114,041019,,*10 +// This is correct format for OpenGTS. Works directly from a web browser. +// For troubleshooting this problem check /opt/traccar/logs/tracker-server.log in the Traccar server +// Message will be HEX coded. Decode with calculator +// OsmAnd is working OK. + +func httpSendTraccar() { + +//Date1 := fmt.Sprint(gpsdatereorder()) // Reformatted date for Tracar +//Time1 := fmt.Sprint("%s", truncateString(GPSTime, 8)) // Truncate time for Traccar + + if TrackEnabled == true { + if TraccarSendTo == true { + if TraccarProto == "osmand" { + TraccarServerFullURL = (fmt.Sprint(TraccarServerURL) + ":" + fmt.Sprint(TraccarPortOsmAnd) + "?" + "id=" + TraccarClientId + "&" + "timestamp=" + date2() + "%20" + time2() + "&" + "lat=" + fmt.Sprintf("%f", GPSLatitude) + "&" + "lon=" + fmt.Sprintf("%f", GPSLongitude) + "&" + "speed=" + fmt.Sprintf("%f", GPSSpeed) + "&" + "course=" + fmt.Sprintf("%f", GPSCourse) + "&" + "variation=" + fmt.Sprintf("%f", GPSVariation)) + } else if TraccarProto == "opengts" { + TraccarServerFullURL = fmt.Sprint(TraccarServerURL) + ":" + fmt.Sprint(TraccarPortOpenGTS) + "/" + "?" + "id=" + TraccarClientId + "&" + "gprmc=" + fmt.Sprint(m) + + //gprmctest = "$GPRMC,081753.00,A,4446.82690,N,02030.95217,E,0.285,,011219,,,A*73" + //TraccarServerFullURL := `http://10.8.0.1:5055?id=tk-demo-04×tamp=2019-10-05%2011:30:00&lat=44.000000&lon=20.000000&speed=0.000&course=0.000000&variation=0.000000` + //TraccarServerFullURL := (fmt.Sprint(TraccarServerURL) + ":" + fmt.Sprint(TraccarPortOsmAnd) + "?" + "id=" + TraccarClientId + "&" + "timestamp=" + fmt.Sprint(gpsdatereorder()) + "%20" + time2() + "&" + "lat=" + fmt.Sprint(GPSLatitude) + "&" + "lon=" + fmt.Sprint(GPSLongitude) + "&" + "speed=" + fmt.Sprint(GPSSpeed) + "&" + "course=" + fmt.Sprint(GPSCourse) + "&" + "variation=" + fmt.Sprint(GPSVariation)) + //http://10.8.0.1:5159/?id=12345&gprmc=$GPRMC,094852,A,4446.8347,N,02030.9393,E,0.0147,69.114,041019,,*10 //URL for testing openGTS + + } + } + } // + + response, err := http.Get(TraccarServerFullURL) + + if err != nil { + + log.Println("error: Cannot Establish Connection with Traccar Server! Error ", err) + // Print to LCD "TRACK ERR 1". Error 1 for network connectivity problems with Traccar server. Check why the connectivity failed? + currentTime := time.Now() + if TargetBoard == "rpi" { + if TrackEnabled == true { + if TrackGPSShowLCD == true { + if LCDEnabled == true { + LcdText = [4]string{"nil", "TRACK ERR1 " + currentTime.Format("15:04:05"), "nil", "nil"} + go hd44780.LcdDisplay(LcdText, LCDRSPin, LCDEPin, LCDD4Pin, LCDD5Pin, LCDD6Pin, LCDD7Pin, LCDInterfaceType, LCDI2CAddress) + } + if OLEDEnabled == true { + oledDisplay(false, 4, 1, "TRACK ERR1 "+currentTime.Format("15:04:05")) + } + } + } + } + // LCD TRACK ERR1 to screen + return + } else { - defer response.Body.Close() contents, err := ioutil.ReadAll(response.Body) + // if it's no error then defer the call for closing body + defer response.Body.Close() + if err != nil { - log.Println("error: Error Sending Data to traccar Webpage!") + log.Println("error: Error Sending Data to Traccar Server!") + } + + // if http request response body is empty + if response.ContentLength == 0 { + log.Println("info: Empty Request Response Body") + } else { + // + log.Println("info: Traccar Web Server Response -->\n" + "-------------------------------------------------------------\n" + string(contents) + "-------------------------------------------------------------") + } + // Added code to read http response status code, 2xx, 4xx. + log.Println("info: HTTP Response Status from Traccar:", response.StatusCode, http.StatusText(response.StatusCode)) + if response.StatusCode >= 200 && response.StatusCode <= 299 { + log.Println("info: HTTP Status Code from Traccar is in the 2xx range. This is OK.") + + // "TRACK OK" Message To LCD. + // Print LCD message "TRACK OK" to LCD, overwrite row with "GPS OK" + timestamp to report a + // position had been successfully transferred to Traccar (after 200 OK). + // time.Sleep(1 * time.Second) + currentTime := time.Now() + if TargetBoard == "rpi" { + if TrackEnabled == true { + if TrackGPSShowLCD == true { + if LCDEnabled == true { + LcdText = [4]string{"nil", "TRACK OK " + currentTime.Format("15:04:05"), "nil", "nil"} + go hd44780.LcdDisplay(LcdText, LCDRSPin, LCDEPin, LCDD4Pin, LCDD5Pin, LCDD6Pin, LCDD7Pin, LCDInterfaceType, LCDI2CAddress) + } + if OLEDEnabled == true { + oledDisplay(false, 4, 1, "TRACK OK "+currentTime.Format("15:04:05")) + } + } + } + } + // "TRACK OK" Message. } else { - log.Println("debug: traccar web response ", string(contents)) + // "TRACK ERR 2" Message to LCD. Error 2 means connectivity is working, but something else went wrong (Response Status 400), like data is corrupted. HEX decode Traccar Server log message. Keep trying. + currentTime := time.Now() + if TargetBoard == "rpi" { + if TrackEnabled == true { + if TrackGPSShowLCD == true { + if LCDEnabled == true { + LcdText = [4]string{"nil", "TRACK ERR2 " + currentTime.Format("15:04:05"), "nil", "nil"} + go hd44780.LcdDisplay(LcdText, LCDRSPin, LCDEPin, LCDD4Pin, LCDD5Pin, LCDD6Pin, LCDD7Pin, LCDInterfaceType, LCDI2CAddress) + } + if OLEDEnabled == true { + oledDisplay(false, 4, 1, "TRACK ERR2 "+currentTime.Format("15:04:05")) + } + } + } + } } + // "TRACK ERR2" Message. + } // + // Note: When sending over Traccar client ports 5055, 5159 response code should be 200 OK. No "body text" is visible. + // If using Trccar web port 8082 to test, code 200 OK and "body text" from Traccar server will show. +} +// OsmAnd End + + +// Some helper functons to use with GPS + +// Truncate function. Need to truncate .0000 / milliseconds time from GPSTime. Is there a more simple way? +// example: Time := fmt.Sprint(truncateString(GPSTime,8)) -> show only the first 8 characters, ending with seconds. +// Should gps time be different type? int64? + +func truncateString(str string, num int) string { + shortstr := str + if len(str) > num { + shortstr = str[0:num] } - return + return shortstr +} + +// Or trim string like this fmt... (string[:num])... num from which character. + +// helper to reorder gps date from dd/mm/yy to yyyy/mm/dd format + +func gpsdatereorder() string { + GPSDate := "01/12/19" // Works with hard coded date for test. How to make date from GPS visible to helper? + //GPSDate := fmt.Sprintf("%s", m.Date) + dd := GPSDate[0:2] + //fmt.Println(yy) //test + //runtime error: slice bounds out of range! But works in Go Playground. Need to fix this error. + mm := GPSDate[3:5] + //fmt.Println(mm) // test + yy := GPSDate[6:8] + //fmt.Println(dd) //test + yyyy := "20" + yy + //fmt.Println(yyyy) //test + Date1reorder := yyyy + "-" + mm + "-" + dd + //fmt.Println(Date1reorder) + return Date1reorder +} + +// "errchk" checks if an error is nil and if it isn't calls log.Fatalln(err) + +func errchk(err error) { + if err != nil { + log.Fatalln(err) + } +} + +// current time system stamp +func time2() string { + currentTime := time.Now() + Time2 := fmt.Sprintf("%s", currentTime.Format("15:04:05")) + return Time2 +} + +// current date system +func date2() string { + currentTime := time.Now() + Date2 := fmt.Sprintf("%s", currentTime.Format("2006-01-02")) + return Date2 +} + +//gps date formatted for Traccar +func date1() string { + Date1 := fmt.Sprintf("%s", gpsdatereorder()) // Reformatted date for Tracar + return Date1 +} + + +// Test working with Wialon/ Gurtam flespi +// Wialon is very popular in Europe for GPS tracking. +// Just have a quick check of Wialon and flespi? +// https://flespi.com +// https://flespi.com/kb +// https://flespi.com/mqtt-broker +// https://gurtam.com/en/wialon +// Not needed for Traccar, doesnt need to be in this version of gps.go +// Can play with Wialon integration later if any use cases show up. + +func flespi() { + +flespiURL := "http://gw.flespi.io:26050" + +//test flespi channel. json array. +//how to use GPS variable in json array? + +flespipayload := strings.NewReader(`[{"ident": "tk-demo-04", "position.latitude":44.780457,"position.longitude":20.515696,"message.type": "position"}]`) +//flespipayload1 := ("ident:" + TraccarClientId + "," + "position.latitude:" + fmt.Sprint(GPSLatitude) + "," + "position.longitude:" + "," + fmt.Sprint(GPSLongitude)) + +// add err handling +// if err != nil { } + +req, _ := http.NewRequest("POST", flespiURL, flespipayload) + +log.Println("flespi:", "| ident:", fmt.Sprint(TraccarClientId), "| position.latitude:", fmt.Sprint(GPSLatitude), "| position.longitude:", fmt.Sprint(GPSLongitude), "| message.type:", "position", "->" , flespiURL) +req.Header.Add("content-type", "application/x-www-form-URLencoded") +req.Header.Add("cache-control", "no-cache") + +res, _ := http.DefaultClient.Do(req) +defer res.Body.Close() + +body, _ := ioutil.ReadAll(res.Body) +fmt.Println(string(body)) + } diff --git a/xmlparser.go b/xmlparser.go index 014d83a..d1274d8 100644 --- a/xmlparser.go +++ b/xmlparser.go @@ -50,8 +50,8 @@ import ( //version and release date const ( - talkkonnectVersion string = "1.62.02" - talkkonnectReleased string = "April 04 2021" + talkkonnectVersion string = "1.63.01" + talkkonnectReleased string = "May 09 2021" ) // Generic Global Variables @@ -248,6 +248,7 @@ var ( PrintLcd bool PrintOled bool PrintGps bool + PrintTraccar bool PrintPanic bool PrintAudioRecord bool PrintMQTT bool @@ -373,6 +374,20 @@ var ( CharTimeOut uint MinRead uint Rx bool + GpsInfoVerbose bool +) + +var ( + TrackEnabled bool + TraccarSendTo bool + TraccarServerURL string + TraccarServerIP string + TraccarClientId string + TraccarReportFrequency int64 + TraccarProto string + TraccarServerFullURL string + TrackGPSShowLCD bool + TrackVerbose bool ) //panic function settings @@ -380,15 +395,16 @@ var ( PEnabled bool PFilenameAndPath string PMessage string + PMailEnabled bool PRecursive bool PVolume float32 PSendIdent bool PSendGpsLocation bool PTxLockEnabled bool PTxlockTimeOutSecs uint + PLowProfile bool ) -//audio recording settings // New var ( AudioRecordEnabled bool AudioRecordOnStart bool @@ -406,13 +422,14 @@ var ( AudioRecordChunkSize string ) -//other global variables used for state tracking var ( txcounter int togglecounter int isTx bool isPlayStream bool CancellableStream bool = true + StreamOnStart bool + StreamStartAfter uint ) type Document struct { @@ -439,10 +456,12 @@ type Document struct { Logging string `xml:"logging"` Loglevel string `xml:"loglevel"` Daemonize bool `xml:"daemonize"` - CancellableStream bool `xml:"cancellablestream"` - SimplexWithMute bool `xml:"simplexwithmute"` - TxCounter bool `xml:"txcounter"` - NextServerIndex int `xml:"nextserverindex"` + + CancellableStream bool `xml:"cancellablestream"` + StreamOnStart bool `xml:"streamonstart"` + SimplexWithMute bool `xml:"simplexwithmute"` + TxCounter bool `xml:"txcounter"` + NextServerIndex int `xml:"nextserverindex"` } `xml:"settings"` AutoProvisioning struct { Enabled bool `xml:"enabled,attr"` @@ -597,6 +616,7 @@ type Document struct { PrintLcd bool `xml:"printlcd"` PrintOled bool `xml:"printoled"` PrintGps bool `xml:"printgps"` + PrintTraccar bool `xml:"printtraccar"` PrintPanic bool `xml:"printpanic"` PrintAudioRecord bool `xml:"printaudiorecord"` PrintMQTT bool `xml:"printmqtt"` @@ -689,22 +709,38 @@ type Document struct { CharTimeOut uint `xml:"chartimeout"` MinRead uint `xml:"minread"` Rx bool `xml:"rx"` + GpsInfoVerbose bool `xml:"gpsinfoverbose"` } `xml:"gps"` + GPSTrackingFunction struct { + TrackEnabled bool `xml:"enabled,attr"` + TraccarSendTo bool `xml:"traccarsendto"` + TraccarServerURL string `xml:"traccarserverurl"` + TraccarServerIP string `xml:"traccarserverip"` + TraccarClientId string `xml:"traccarclientid"` + TraccarReportFrequency int64 `xml:"traccarreportfrequency"` + TraccarProto string `xml:"traccarproto"` + TraccarServerFullURL string `xml:"traccarserverfullurl"` + TrackGPSShowLCD bool `xml:"trackgpsshowlcd"` + TrackVerbose bool `xml:"trackverbose"` + } `xml:"gpstrackingfunction"` PanicFunction struct { Enabled bool `xml:"enabled,attr"` FilenameAndPath string `xml:"filenameandpath"` Volume float32 `xml:"volume"` SendIdent bool `xml:"sendident"` Message string `xml:"panicmessage"` + PMailEnabled bool `xml:"panicemail"` + PEavesdropEnabled bool `xml:"eavesdrop"` RecursiveSendMessage string `xml:"recursivesendmessage"` SendGpsLocation bool `xml:"sendgpslocation"` TxLockEnabled bool `xml:"txlockenabled"` TxLockTimeOutSecs uint `xml:"txlocktimeoutsecs"` + PLowProfile bool `xml:"lowprofile"` } `xml:"panicfunction"` AudioRecordFunction struct { Enabled bool `xml:"enabled,attr"` RecordOnStart bool `xml:"recordonstart"` - RecordSystem string `xml:"recordsystem"` // New + RecordSystem string `xml:"recordsystem"` RecordMode string `xml:"recordmode"` RecordTimeout int64 `xml:"recordtimeout"` RecordFromOutput string `xml:"recordfromoutput"` @@ -837,7 +873,10 @@ func readxmlconfig(file string) error { } Daemonize = document.Global.Software.Settings.Daemonize + CancellableStream = document.Global.Software.Settings.CancellableStream + StreamOnStart = document.Global.Software.Settings.StreamOnStart + SimplexWithMute = document.Global.Software.Settings.SimplexWithMute TxCounter = document.Global.Software.Settings.TxCounter NextServerIndex = document.Global.Software.Settings.NextServerIndex @@ -853,7 +892,7 @@ func readxmlconfig(file string) error { } if APEnabled && SaveFilename == "" { - SaveFilename = filepath.Base(exec) + ".xml" //Should default to talkkonnect.xml + SaveFilename = filepath.Base(exec) + "talkkonnect.xml" } BeaconEnabled = document.Global.Software.Beacon.Enabled @@ -1225,7 +1264,6 @@ func readxmlconfig(file string) error { MQTTStore = document.Global.Software.MQTT.MQTTStore PrintHTTPAPI = document.Global.Software.PrintVariables.PrintHTTPAPI - PrintTargetboard = document.Global.Software.PrintVariables.PrintTargetBoard PrintLeds = document.Global.Software.PrintVariables.PrintLeds PrintHeartbeat = document.Global.Software.PrintVariables.PrintHeartbeat @@ -1234,6 +1272,7 @@ func readxmlconfig(file string) error { PrintLcd = document.Global.Software.PrintVariables.PrintLcd PrintOled = document.Global.Software.PrintVariables.PrintOled PrintGps = document.Global.Software.PrintVariables.PrintGps + PrintTraccar = document.Global.Software.PrintVariables.PrintTraccar PrintPanic = document.Global.Software.PrintVariables.PrintPanic PrintAudioRecord = document.Global.Software.PrintVariables.PrintAudioRecord PrintMQTT = document.Global.Software.PrintVariables.PrintMQTT @@ -1323,7 +1362,17 @@ func readxmlconfig(file string) error { CharTimeOut = document.Global.Hardware.GPS.CharTimeOut MinRead = document.Global.Hardware.GPS.MinRead Rx = document.Global.Hardware.GPS.Rx - + GpsInfoVerbose = document.Global.Hardware.GPS.GpsInfoVerbose + TrackEnabled = document.Global.Hardware.GPSTrackingFunction.TrackEnabled + TraccarSendTo = document.Global.Hardware.GPSTrackingFunction.TraccarSendTo + TraccarServerURL = document.Global.Hardware.GPSTrackingFunction.TraccarServerURL + TraccarServerIP = document.Global.Hardware.GPSTrackingFunction.TraccarServerIP + TraccarClientId = document.Global.Hardware.GPSTrackingFunction.TraccarClientId + TraccarReportFrequency = document.Global.Hardware.GPSTrackingFunction.TraccarReportFrequency + TraccarProto = document.Global.Hardware.GPSTrackingFunction.TraccarProto + TraccarServerFullURL = document.Global.Hardware.GPSTrackingFunction.TraccarServerFullURL + TrackGPSShowLCD = document.Global.Hardware.GPSTrackingFunction.TrackGPSShowLCD + TrackVerbose = document.Global.Hardware.GPSTrackingFunction.TrackVerbose PEnabled = document.Global.Hardware.PanicFunction.Enabled PFilenameAndPath = document.Global.Hardware.PanicFunction.FilenameAndPath @@ -1335,12 +1384,13 @@ func readxmlconfig(file string) error { } PMessage = document.Global.Hardware.PanicFunction.Message + PMailEnabled = document.Global.Hardware.PanicFunction.PMailEnabled PVolume = document.Global.Hardware.PanicFunction.Volume PSendIdent = document.Global.Hardware.PanicFunction.SendIdent PSendGpsLocation = document.Global.Hardware.PanicFunction.SendGpsLocation PTxLockEnabled = document.Global.Hardware.PanicFunction.TxLockEnabled PTxlockTimeOutSecs = document.Global.Hardware.PanicFunction.TxLockTimeOutSecs - + PLowProfile = document.Global.Hardware.PanicFunction.PLowProfile AudioRecordEnabled = document.Global.Hardware.AudioRecordFunction.Enabled AudioRecordOnStart = document.Global.Hardware.AudioRecordFunction.RecordOnStart AudioRecordSystem = document.Global.Hardware.AudioRecordFunction.RecordSystem @@ -1404,6 +1454,7 @@ func printxmlconfig() { log.Println("info: Loglevel " + Loglevel) log.Println("info: Daemonize " + fmt.Sprintf("%t", Daemonize)) log.Println("info: CancellableStream " + fmt.Sprintf("%t", CancellableStream)) + log.Println("info: StreamOnStart " + fmt.Sprintf("%t", StreamOnStart)) log.Println("info: SimplexWithMute " + fmt.Sprintf("%t", SimplexWithMute)) log.Println("info: TxCounter " + fmt.Sprintf("%t", TxCounter)) log.Println("info: NextServerIndex " + fmt.Sprintf("%v", NextServerIndex)) @@ -1668,17 +1719,36 @@ func printxmlconfig() { log.Println("info: ------------ GPS ------------------------ SKIPPED ") } + if PrintTraccar { + log.Println("info: ------------ TRACCAR Info ----------------------- ") + log.Println("info: Track Enabled " + fmt.Sprintf("%t", TrackEnabled)) + log.Println("info: Traccar Send To " + fmt.Sprintf("%t", TraccarSendTo)) + log.Println("info: Traccar Server URL " + fmt.Sprintf("%s", TraccarServerURL)) + log.Println("info: Traccar Server IP " + fmt.Sprintf("%s", TraccarServerIP)) + log.Println("info: Traccar Client ID " + fmt.Sprintf("%s", TraccarClientId)) + log.Println("info: Traccar Report Frequency " + fmt.Sprintf("%v", TraccarReportFrequency)) + log.Println("info: Traccar Proto " + fmt.Sprintf("%s", TraccarProto)) + log.Println("info: Traccar Server Full URL " + fmt.Sprintf("%s", TraccarServerFullURL)) + log.Println("info: Track GPS Show Lcd " + fmt.Sprintf("%t", TrackGPSShowLCD)) + log.Println("info: Track Verbose " + fmt.Sprintf("%t", TrackVerbose)) + + } else { + log.Println("info: ------------ TRACCAR Info ------------------------ SKIPPED ") + } + if PrintPanic { log.Println("info: ------------ PANIC Function -------------- ") log.Println("info: Panic Function Enable " + fmt.Sprintf("%t", PEnabled)) log.Println("info: Panic Sound Filename and Path " + fmt.Sprintf("%s", PFilenameAndPath)) log.Println("info: Panic Message " + fmt.Sprintf("%s", PMessage)) + log.Println("info: Panic Email Send " + fmt.Sprintf("%t", PMailEnabled)) log.Println("info: Panic Message Send Recursively " + fmt.Sprintf("%t", PRecursive)) log.Println("info: Panic Volume " + fmt.Sprintf("%v", PVolume)) log.Println("info: Panic Send Ident " + fmt.Sprintf("%t", PSendIdent)) log.Println("info: Panic Send GPS Location " + fmt.Sprintf("%t", PSendGpsLocation)) log.Println("info: Panic TX Lock Enabled " + fmt.Sprintf("%t", PTxLockEnabled)) log.Println("info: Panic TX Lock Timeout Secs " + fmt.Sprintf("%v", PTxlockTimeOutSecs)) + log.Println("info: Panic Low Profile Lights Enable" + fmt.Sprintf("%v", PLowProfile)) } else { log.Println("info: ------------ PANIC Function -------------- SKIPPED ") }