# floor, ceil, trunc and casting

I left a Wisnode Track Lite RAK7200 outside on the deck for a day and the way the positions “snapped” to a grid caught my attention. Based on the size of my property the grid looked to be roughly 10 x 10 meters

The sample Cayenne Low Power Payload Mbed C code uses a cast which is I think is the same as a floor.

```uint8_t CayenneLPP::addGPS(uint8_t channel, float latitude, float longitude, float meters) {
if ((cursor + LPP_GPS_SIZE) > maxsize) {
return 0;
}
int32_t lat = latitude * 10000;
int32_t lon = longitude * 10000;
int32_t alt = meters * 100;

buffer[cursor++] = channel;
buffer[cursor++] = LPP_GPS;

buffer[cursor++] = lat >> 16;
buffer[cursor++] = lat >> 8;
buffer[cursor++] = lat;
buffer[cursor++] = lon >> 16;
buffer[cursor++] = lon >> 8;
buffer[cursor++] = lon;
buffer[cursor++] = alt >> 16;
buffer[cursor++] = alt >> 8;
buffer[cursor++] = alt;

return cursor;
}
```

“These functions round x downwards to the nearest integer, returning that value as a `double`. Thus, `floor (1.5)` is `1.0` and `floor (-1.5)` is `-2.0`.”

In the C code the latitude and longitude values are truncated to four decimal places and the altitude to two decimal places. In my C# code I used Math.Round and I wondered what impact that could have…

```public void GpsLocationAdd(byte channel, float latitude, float longitude, float altitude)
{
IsChannelNumberValid(channel);
IsBfferSizeSufficient(Enumerations.DataType.Gps);

if ((latitude < Constants.LatitudeMinimum ) || (latitude > Constants.LatitudeMaximum))
{
throw new ArgumentException(\$"Latitude must be between {Constants.LatitudeMinimum} and {Constants.LatitudeMaximum}", "latitude");
}

if ((latitude < Constants.LongitudeMinimum) || (latitude > Constants.LongitudeMaximum))
{
throw new ArgumentException(\$"Longitude must be between {Constants.LongitudeMinimum} and {Constants.LongitudeMaximum}", "latitude");
}

if ((altitude < Constants.AltitudeMinimum) || (altitude > Constants.AltitudeMaximum))
{
throw new ArgumentException(\$"Altitude must be between {Constants.AltitudeMinimum} and {Constants.AltitudeMaximum}", "altitude");
}

int lat = (int)Math.Round(latitude * 10000.0f);
int lon = (int)Math.Round(longitude * 10000.0f);
int alt = (int)Math.Round(altitude * 100.0f);

buffer[index++] = channel;
buffer[index++] = (byte)Enumerations.DataType.Gps;

buffer[index++] = (byte)(lat >> 16);
buffer[index++] = (byte)(lat >> 8);
buffer[index++] = (byte)lat;
buffer[index++] = (byte)(lon >> 16);
buffer[index++] = (byte)(lon >> 8);
buffer[index++] = (byte)lon;
buffer[index++] = (byte)(alt >> 16);
buffer[index++] = (byte)(alt >> 8);
buffer[index++] = (byte)alt;
}
```

Using the WGS84 World Geodetic System Distance Calculator to calculate the distance where the Greenwich Meridian and the Equator cross off the coast of Ghana the theoretical maximum error is 15.69m.

I live in Christchurch New Zealand and the theoretical maximum distance is 13.6 m. So, in summary the LPP latitude and longitude values are most probably fine for tracking applications.

# Xively GPS Location data upload V2

In the previous post I assembled the xively request XML using a StringBuilder rather than using the XML support available in the NetMF. To use the NetMF XML library I needed to add a reference to the DPWS extensions (MFDpwsExtensions) and change the using statement at the top of the module from System.Text to System.Ext.Xml
``` static void xivelyFeedUpdate(string ApiKey, string feedId, string channel, double latitude, double longitude, double altitude) { byte[] buffer; ```
```using (XmlMemoryWriter xmlwriter = XmlMemoryWriter.Create()) { xmlwriter.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\""); xmlwriter.WriteStartElement("eeml"); xmlwriter.WriteStartElement("environment"); xmlwriter.WriteStartElement("location"); ```
```xmlwriter.WriteStartAttribute("domain"); xmlwriter.WriteString("physical"); xmlwriter.WriteEndAttribute();```

```xmlwriter.WriteStartAttribute("exposure"); xmlwriter.WriteString("outdoor"); xmlwriter.WriteEndAttribute(); ```
```xmlwriter.WriteStartAttribute("disposition"); xmlwriter.WriteString("mobile"); xmlwriter.WriteEndAttribute(); ```
```xmlwriter.WriteStartElement("name"); xmlwriter.WriteString("Location"); xmlwriter.WriteEndElement(); ```
```xmlwriter.WriteStartElement("lat"); xmlwriter.WriteString(latitude.ToString("F5")); xmlwriter.WriteEndElement(); ```
```xmlwriter.WriteStartElement("lon"); xmlwriter.WriteString(longitude.ToString("F5")); xmlwriter.WriteEndElement(); ```
```xmlwriter.WriteStartElement("ele"); xmlwriter.WriteString(altitude.ToString("F1")); xmlwriter.WriteEndElement(); ```
```xmlwriter.WriteEndElement(); xmlwriter.WriteEndElement(); xmlwriter.WriteEndElement(); ```
```buffer = xmlwriter.ToArray(); } ```
```try { ``````using (HttpWebRequest request = (HttpWebRequest)WebRequest.Create(xivelyApiBaseUrl + feedId + ".xml")) { request.Method = "PUT"; request.ContentLength = buffer.Length; request.ContentType = "text/xml"; request.Headers.Add("X-ApiKey", xivelyApiKey); request.KeepAlive = false; request.Timeout = 5000; request.ReadWriteTimeout = 5000; ```
```// request body using (Stream stream = request.GetRequestStream()) { stream.Write(buffer, 0, buffer.Length);                } using (var response = (HttpWebResponse)request.GetResponse()) { Debug.Print("HTTP Status:" + response.StatusCode + " : " + response.StatusDescription); } } } catch (Exception ex) { Debug.Print(ex.Message); } } ```

I was expecting the XML libraries to be quite chunky, but on my Netduino Plus 2 there wasn’t a huge size difference, the StringBuilder download was 49K8 bytes and the XMLWiter download was 56K1 bytes.

When I ran the StringBuilder and XMLWriter versions they both had roughly 92K6 bytes of free memory.

Realistically there was little to separate the two implementations

# Xively GPS Location data upload V1

For one of the code club projects we looked at the National Marine Electronics Association (NMEA) 0183 output of my iteadStudio GPS Shield + Active Antenna. We used the NetMF Toolbox NMEA GPS processing code with a couple of modifications detailed here.

For another project we had used Xively a “Public Cloud for the Internet of Things”. The Xively API has support for storing the position of a “thing” and it didn’t look like it would take much effort to extend the original GPS demo to trial this. The xively Location & waypoints API is RESTful and supports JSON & XML

```void xivelyFeedUpdate(string ApiKey, string feedId, string channel, double latitude, double longitude, double altitude) { try { using (HttpWebRequest request = (HttpWebRequest)WebRequest.Create(xivelyApiBaseUrl + feedId + ".xml")) { StringBuilder payload = new StringBuilder(); ````payload.Append(@"<?xml version=""1.0"" encoding=""UTF-8""?><eeml><environment><location domain=""physical"" exposure=""outdoor"" disposition=""mobile""><name>Location</name><lat>");`
```payload.Append(latitude.ToString("F5")); payload.Append("</lat><lon>"); payload.Append(longitude.ToString("F5")); payload.Append("</lon><ele>"); payload.Append(altitude.ToString("F1")); payload.Append("</ele></location></environment></eeml>");```

`byte[] buffer = Encoding.UTF8.GetBytes(payload.ToString());`
``` request.Method = "PUT"; request.ContentLength = buffer.Length; request.ContentType = "text/xml"; request.Headers.Add("X-ApiKey", xivelyApiKey); request.KeepAlive = false; request.Timeout = 5000; request.ReadWriteTimeout = 5000; ```

```// request body using (Stream stream = request.GetRequestStream()) { stream.Write(buffer, 0, buffer.Length); } ``````using (var response = (HttpWebResponse)request.GetResponse()) { Debug.Print("HTTP Status:" + response.StatusCode + " : " + response.StatusDescription); } } } catch (Exception ex) { Debug.Print(ex.Message); } } ```

The position of the “thing” is displayed like this

The position of my car

The XML was constructed using a stringbuilder (NetMF 4.2) as this appeared easier/smaller than using the baked in XML functionality.

# SeeedStudio Grove GPS IteadStudio Shield Comparison

I use the SeeedStudio Grove system for prototyping and teaching. One of the modules is a Global Positioning System (GPS) unit based on the u-blox 5 engine. To get this unit to work you just plug it into the UART socket on the base shield and load the necessary software onto an Arduino (or compatible) board. My day job is working on Microsoft .Net applications so I use a Netduino Plus or a Netduino plus 2.

SeeedStudio base shield and GPS unit

The Seeedstudio 4 wire connector system has some advantages but for a couple of projects I was looking at I needed to be able to run on a different serial port and access the one pulse per second output. I had a look at several other vendors and the iteadstudio GPS Shield + Active Antenna which is based on the u-blox 6 engine looked like a reasonable alternative.

After some testing I found that the Iteadstudio GPS shield appears to have a shorter time to first fix after a power cycle, I averaged 10 sets of readings for each device and found that in my backyard it took on average 46sec for the Iteadstudio shield and 55sec for the SeeedStudio device.

Both devices output National Marine Electronics Association (NMEA) 0183 sentences and I use the NetMF Toolbox NMEA code to process the data streams. I have modified the NetMF toolbox code with an additional event handler which empties the serial input buffer if there is an error and one of the validation checks needed to be tweaked as it was possible to get an exception due to an empty string.

Around line 45
``` this._Uart = newSerialPort(SerialPort, BaudRate); this._Uart.ErrorReceived += newSerialErrorReceivedEventHandler(_Uart_ErrorReceived); this._Uart.DataReceived += newSerialDataReceivedEventHandler(_Uart_DataReceived); ```

``` void _Uart_ErrorReceived(object sender, SerialErrorReceivedEventArgs e) { if (_Uart.IsOpen) { _Uart.Flush(); } } ```

Around line 323
``` // Have we received a full line of data? int Pos = this._Buffer.IndexOf("\r\n"); if (Pos >= 1) { ```

With these modifications my Netduino Plus 2 can runs for days at a time without buffer overflows or other issues, you just need to be careful to make your event handlers block for as little time as possible.

I have been looking at building an NetMF NMEA driver which runs on a background thread and doesn’t use any string manipulation methods e.g. string.splt so the garbage collector has less to do, but this will be a topic for a future post.