module ietf-geo-location {
  yang-version 1.1;
  namespace "urn:ietf:params:xml:ns:yang:ietf-geo-location";
  prefix geo;
  import ietf-yang-types {
    prefix yang;
    reference "RFC 6991: Common YANG Data Types";
  }

  organization
    "IETF NETMOD Working Group (NETMOD)";
  contact
   "WG Web:   <https://datatracker.ietf.org/wg/netmod/>
    WG List:  <mailto:netmod@ietf.org>

    Editor:   Christian Hopps
              <mailto:chopps@chopps.org>";

  description
    "This module defines a grouping of a container object for
     specifying a location on or around an astronomical object (e.g.,
     'earth').

     The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
     NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
     'MAY', and 'OPTIONAL' in this document are to be interpreted as
     described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
     they appear in all capitals, as shown here.

     Copyright (c) 2022 IETF Trust and the persons identified as
     authors of the code.  All rights reserved.

     Redistribution and use in source and binary forms,
     with or without modification, is permitted pursuant to,
     and subject to the license terms contained in, the
     Revised BSD License set forth in Section 4.c of the
     IETF Trust's Legal Provisions Relating to IETF Documents
     (https://trustee.ietf.org/license-info).

     This version of this YANG module is part of RFC 9179
     (https://www.rfc-editor.org/info/rfc9179); see the RFC itself
     for full legal notices.";

  revision 2022-02-11 {
    description
      "Initial Revision";
    reference
      "RFC 9179: A YANG Grouping for Geographic Locations";
  }

  feature alternate-systems {
    description
      "This feature means the device supports specifying locations
       using alternate systems for reference frames.";
  }

  grouping geo-location {
    description
      "Grouping to identify a location on an astronomical object.";

    container geo-location {
      description
        "A location on an astronomical body (e.g., 'earth')
         somewhere in a universe.";

      container reference-frame {
        description
          "The Frame of Reference for the location values.";

        leaf alternate-system {
          if-feature "alternate-systems";
          type string;
          description
            "The system in which the astronomical body and
             geodetic-datum is defined.  Normally, this value is not
             present and the system is the natural universe; however,
             when present, this value allows for specifying alternate
             systems (e.g., virtual realities).  An alternate-system
             modifies the definition (but not the type) of the other
             values in the reference frame.";
        }
        leaf astronomical-body {
          type string {
            pattern '[ -@\[-\^_-~]*';
          }
          default "earth";
          description
            "An astronomical body as named by the International
             Astronomical Union (IAU) or according to the alternate
             system if specified.  Examples include 'sun' (our star),
             'earth' (our planet), 'moon' (our moon), 'enceladus' (a
             moon of Saturn), 'ceres' (an asteroid), and
             '67p/churyumov-gerasimenko (a comet).  The ASCII value
             SHOULD have uppercase converted to lowercase and not
             include control characters (i.e., values 32..64, and
             91..126).  Any preceding 'the' in the name SHOULD NOT be
             included.";
          reference
            "https://www.iau.org/";
        }
        container geodetic-system {
          description
            "The geodetic system of the location data.";
          leaf geodetic-datum {
            type string {
              pattern '[ -@\[-\^_-~]*';
            }
            description
              "A geodetic-datum defining the meaning of latitude,
               longitude, and height.  The default when the
               astronomical body is 'earth' is 'wgs-84', which is
               used by the Global Positioning System (GPS).  The
               ASCII value SHOULD have uppercase converted to
               lowercase and not include control characters
               (i.e., values 32..64, and 91..126).  The IANA registry
               further restricts the value by converting all spaces
               (' ') to dashes ('-').
               The specification for the geodetic-datum indicates
               how accurately it models the astronomical body in
               question, both for the 'horizontal'
               latitude/longitude coordinates and for height
               coordinates.";
            reference
              "RFC 9179: A YANG Grouping for Geographic Locations,
               Section 6.1";
          }
          leaf coord-accuracy {
            type decimal64 {
              fraction-digits 6;
            }
            description
              "The accuracy of the latitude/longitude pair for
               ellipsoidal coordinates, or the X, Y, and Z components
               for Cartesian coordinates.  When coord-accuracy is
               specified, it indicates how precisely the coordinates
               in the associated list of locations have been
               determined with respect to the coordinate system
               defined by the geodetic-datum.  For example, there
               might be uncertainty due to measurement error if an
               experimental measurement was made to determine each
               location.";
          }
          leaf height-accuracy {
            type decimal64 {
              fraction-digits 6;
            }
            units "meters";
            description
              "The accuracy of the height value for ellipsoidal
               coordinates; this value is not used with Cartesian
               coordinates.  When height-accuracy is specified, it
               indicates how precisely the heights in the
               associated list of locations have been determined
               with respect to the coordinate system defined by the
               geodetic-datum.  For example, there might be
               uncertainty due to measurement error if an
               experimental measurement was made to determine each
               location.";
          }
        }
      }
      choice location {
        description
          "The location data either in latitude/longitude or
           Cartesian values";
        case ellipsoid {
          leaf latitude {
            type decimal64 {
              fraction-digits 16;
            }
            units "decimal degrees";
            description
              "The latitude value on the astronomical body.  The
               definition and precision of this measurement is
               indicated by the reference-frame.";
          }
          leaf longitude {
            type decimal64 {
              fraction-digits 16;
            }
            units "decimal degrees";
            description
              "The longitude value on the astronomical body.  The
               definition and precision of this measurement is
               indicated by the reference-frame.";
          }
          leaf height {
            type decimal64 {
              fraction-digits 6;
            }
            units "meters";
            description
              "Height from a reference 0 value.  The precision and
               '0' value is defined by the reference-frame.";
          }
        }
        case cartesian {
          leaf x {
            type decimal64 {
              fraction-digits 6;
            }
            units "meters";
            description
              "The X value as defined by the reference-frame.";
          }
          leaf y {
            type decimal64 {
              fraction-digits 6;
            }
            units "meters";
            description
              "The Y value as defined by the reference-frame.";
          }
          leaf z {
            type decimal64 {
              fraction-digits 6;
            }
            units "meters";
            description
              "The Z value as defined by the reference-frame.";
          }
        }
      }
      container velocity {
        description
          "If the object is in motion, the velocity vector describes
           this motion at the time given by the timestamp.  For a
           formula to convert these values to speed and heading, see
           RFC 9179.";
        reference
          "RFC 9179: A YANG Grouping for Geographic Locations";

        leaf v-north {
          type decimal64 {
            fraction-digits 12;
          }
          units "meters per second";
          description
            "v-north is the rate of change (i.e., speed) towards
             true north as defined by the geodetic-system.";
        }

        leaf v-east {
          type decimal64 {
            fraction-digits 12;
          }
          units "meters per second";
          description
            "v-east is the rate of change (i.e., speed) perpendicular
             to the right of true north as defined by
             the geodetic-system.";
        }

        leaf v-up {
          type decimal64 {
            fraction-digits 12;
          }
          units "meters per second";
          description
            "v-up is the rate of change (i.e., speed) away from the
             center of mass.";
        }
      }
      leaf timestamp {
        type yang:date-and-time;
        description
          "Reference time when location was recorded.";
      }
      leaf valid-until {
        type yang:date-and-time;
        description
          "The timestamp for which this geo-location is valid until.
           If unspecified, the geo-location has no specific
           expiration time.";
      }
    }
  }
}
