Source: bemap-model/bemap-coordinateSat.js

/**
 * BeNomad BeMap JavaScript API - CoordinateSat class
 */

/**
 * @classdesc
 * GPS coordinate with satellite-derived metadata.
 *
 * Extends bemap.Coordinate with altitude, heading, speed, time and satellite count.
 * Used by TraceRoute and other GPS-trace-oriented services introduced in v1.5.
 *
 * @public
 * @constructor
 * @extends {bemap.Coordinate}
 * @since 1.5.0
 * @param {Object} options
 * @param {Number} options.lon Longitude in degrees decimal (WGS84).
 * @param {Number} options.lat Latitude in degrees decimal (WGS84).
 * @param {Number} [options.alt] Altitude in metres above mean sea level.
 * @param {Number} [options.heading] Heading in degrees clockwise from north (0–360).
 * @param {Number} [options.speed] Speed in metres per second.
 * @param {Number|String|Date} [options.time] GPS timestamp (epoch ms, ISO-8601 string or Date).
 * @param {Number} [options.satellites] Number of satellites visible at the fix.
 */
bemap.CoordinateSat = function(options) {
    var opts = options || {};

    bemap.Coordinate.call(this, opts.lon, opts.lat);

    /**
     * @type {Number|null}
     * @protected
     */
    this.alt = (opts.alt !== undefined && opts.alt !== null) ? opts.alt : null;

    /**
     * @type {Number|null}
     * @protected
     */
    this.heading = (opts.heading !== undefined && opts.heading !== null) ? opts.heading : null;

    /**
     * @type {Number|null}
     * @protected
     */
    this.speed = (opts.speed !== undefined && opts.speed !== null) ? opts.speed : null;

    /**
     * @type {Number|String|Date|null}
     * @protected
     */
    this.time = (opts.time !== undefined && opts.time !== null) ? opts.time : null;

    /**
     * @type {Number|null}
     * @protected
     */
    this.satellites = (opts.satellites !== undefined && opts.satellites !== null) ? opts.satellites : null;
};
bemap.inherits(bemap.CoordinateSat, bemap.Coordinate);

/* Getters and setters */

bemap.CoordinateSat.prototype.getAlt = function() { return this.alt; };
bemap.CoordinateSat.prototype.setAlt = function(alt) { this.alt = alt; return this; };

bemap.CoordinateSat.prototype.getHeading = function() { return this.heading; };
bemap.CoordinateSat.prototype.setHeading = function(heading) { this.heading = heading; return this; };

bemap.CoordinateSat.prototype.getSpeed = function() { return this.speed; };
bemap.CoordinateSat.prototype.setSpeed = function(speed) { this.speed = speed; return this; };

bemap.CoordinateSat.prototype.getTime = function() { return this.time; };
bemap.CoordinateSat.prototype.setTime = function(time) { this.time = time; return this; };

bemap.CoordinateSat.prototype.getSatellites = function() { return this.satellites; };
bemap.CoordinateSat.prototype.setSatellites = function(sat) { this.satellites = sat; return this; };

/**
 * Return a wire-format JSON object suitable for inclusion in a BeMap request body.
 * Only non-null fields are emitted.
 *
 * Wire field names mirror the BeMap server contract (cross-checked against the
 * Flutter SDK `bemap-flutter-api/lib/service/map/model/coordinate_sat.dart`):
 *   - `lon` / `lat` (not longitude / latitude)
 *   - `sat` (not satellites)
 *   - `time` as epoch milliseconds (integer) — Dates and ISO strings are coerced
 *
 * @public
 * @return {Object}
 */
bemap.CoordinateSat.prototype.toJson = function() {
    var json = { lon: this.lon, lat: this.lat };
    if (this.alt !== null) json.alt = this.alt;
    if (this.heading !== null) json.heading = this.heading;
    if (this.speed !== null) json.speed = this.speed;
    if (this.time !== null) {
        if (this.time instanceof Date) {
            json.time = this.time.getTime();
        } else if (typeof this.time === 'string') {
            var parsed = Date.parse(this.time);
            json.time = isNaN(parsed) ? this.time : parsed;
        } else {
            json.time = this.time;
        }
    }
    if (this.satellites !== null) json.sat = this.satellites;
    return json;
};

/**
 * Hydrate a CoordinateSat from a plain JSON object (typically from a BeMap response).
 * Accepts both the modern `sat` field and the legacy `satellites` field.
 *
 * @public
 * @static
 * @param {Object} json
 * @return {bemap.CoordinateSat}
 */
bemap.CoordinateSat.fromJson = function(json) {
    if (!json) return null;
    return new bemap.CoordinateSat({
        lon:        (json.lon !== undefined) ? json.lon : json.longitude,
        lat:        (json.lat !== undefined) ? json.lat : json.latitude,
        alt:        json.alt,
        heading:    json.heading,
        speed:      json.speed,
        time:       json.time,
        satellites: (json.sat !== undefined) ? json.sat : json.satellites
    });
};