IAP/MQ Data Schema

This page shows the IAP/MQ Data Schema.  You can download the schema file by clicking this link:  iap-data-schema.js.


/*
 * A schema for IAP Data Types.
 * (http://json-schema.org)
 *
 * This file implements the IAP Data Type schema in Javascript for direct
 * consumption by JavaScript or Node.JS tools and JSON schema validators.
 *
 * The schemata defined herein govern meta data for datapoint or property
 * types and profiles. Schemata which govern the value for datapoints or
 * properties are not defined here but may be derived from meta data that
 * implements the schemata defined in this module.
 *
 * Copyright (c) Echelon Corporation 2018
 */
"use strict";

/*
 * Note (A):
 *
 * Many definitions share the same set of properties, such as a required name
 * or optional comment or unit strings for base types. These common properties
 * are not declared as inherited properties, because JSON schema cannot inherit
 * the "required" designation.
 */

/*
 * Note (B):
 *
 * Comments in the following definitions refer to the presentation and the
 * implementation of data. The presentation describes how data is presented
 * to a tool or a human, the implementation describes how the same data is
 * encoded for communication within the edge protocol. Data implementation is
 * sometimes also called "raw data" and data presentation is sometimes known
 * as "scaled" or "formatted data."
 */

/*
 * Note (C):
 *
 * Note JSON schema allows all additional properties (those which are not
 * governed by the schema) unless explicitly forbidden. Many types described
 * with the IAP Data Type language defined here will report additional
 * properties not governed by this schema; this IAP Data Type schema defines
 * the common denominator of all IAP Data Type languages.
 */

/*
 * Note (D):
 *
 * Several definitions include "name", "id" and "comment" values. In some
 * definitions, such as "profile", some keys also define names. These behave
 * as follows:
 *
 * The member name as defined with a key, for example within a profile's
 * datapoints and properties listing, is typically but not necessarily the
 * same as the "id" value reported within the same member.
 * The "id" field is the programmatic name; a C language "typedef struct"
 * would include fields named after the "id". The member name can be longer,
 * use more human- and documentation-friendly capitalization and spelling.
 *
 * The "name" key refers to a value which is often the same or similar to
 * the member name or "id" value. The "name" value can be more human-friendly
 * and documentation-friendly however, and it can be localized for different
 * natural (human) languages. The "name" value is a name however, and does not
 * include punctuation.
 *
 * The optional "comment" is a terse human-readable description of the purpose
 * of the item to which the comment applies. The comment can be localized into
 * different languages. 
 * The comment consists or one or more complete sentences including correct
 * capitalization and punctuation.
 */

/*
 * Base types are defined in this section. An application cannot directly
 * implement a base type, but datapoint and property types implement a base
 * type.
 */

const localizableString = {
    /*
     * Many definitions support localizable strings, often used to implement
     * comments and descriptions, or human-friendly names.
     *
     * Such a string can be a constant string such as "this is a comment",
     * or it an be a reference to a string resource using a string resource
     * identifier. The string resource identifier can then be used to locate
     * a translation, thus localizing the string.
     *
     * The localizableString schema describes such a string type.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/localizableString",
    title: "localizableString",
    description: "A constant string or reference to a localizable string",

    oneOf: [{
            "type": "string"
        },
        {
            "type": "object",
            properties: {
                id: {
                    type: "string"
                }
            },
            required: [
                "id"
            ]
        }
    ]
}; // localizableString


const baseScalar = {
    /*
     * A base type for integer items.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseScalar",
    title: "baseScalar",
    description: "An integer data type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "scalar"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"
        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"
        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"
        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        /*
         * Scalar properties.
         */
        min: {
            /*
             * The numerically smallest valid value for this type.
             * This may be greater than the native minimum of the base
             * type. The invalid value, if declared, may be numerically
             * less than the minimum value.
             * The minimum is expressed as implementation data.
             */
            type: "number"
        },
        max: {
            /*
             * The numerically largest valid value for this type.
             * This may be less than the native maximum of the base
             * type. The invalid value, if declared, may be numerically
             * greater than the maximum value.
             * The maximum is expressed as implementation data.
             */
            type: "number"
        },
        invalid: {
            /*
             * The optional invalid value can be within or outside the
             * range defined by min, max so long as it can be stored
             * in the base type.
             * When an item's value matches the invalid value, the item
             * indicates that it does not currently hold a valid value.
             * The invalid value is expressed as implementation data.
             */
            type: "number"
        },
        "array-size": {
            type: "integer",
            minimum: 0, // 0, 1: not an array, 2...max: array
            default: 0
        },
        base: {
            /*
             * The base type indicates how the data is implemented in the
             * edge protocol. Also see byte-order.
             */
            enum: [
                "uint8", "int8",
                "uint16", "int16",
                "uint32", "int32",
                "uint64", "int64"
            ]
        },
        "byte-order": {
            /*
             * This describes the implementation byte order. The property
             * is optional and defaults to a big endian network byte order.
             */
            enum: [
                "big-endian", "little-endian"
            ],
            default: "big-endian"
        },
        encoding: {
            /*
             * A presentation guide.
             */
            enum: [
                "binary", // present as number to base 2
                "decimal", // display as number to base 10
                "hex", // display as number to base 16
                "base-36", // display as number to base 36 (0-9A-Z)
                "base-62", // display as number to base 62 (0-9A-Za-z)
                "ascii", // display as character, ASCII encoding
                "utf-8", // display as UTF-8 character
                "utf-16" // display as UTF-16 character
            ],
            default: "decimal"
        },
        scaling: {
            /*
             * The scaling object guides the transformation between
             * implementation and presentation.
             */
            "$ref": "#/definitions/scaling"
        },
        values: {
            /*
             * When present, values enumerates a discrete list of acceptable
             * values for this scalar. For example, one property type could
             * implement a scalar to represent the number of stop bits in an
             * asynchronous serial communications port. This could be described
             * as a scalar based on uint8 with scaling factors a, b, c of
             * +1, -1, 0 and a discrete value list of [ 1, 1.5, 2 ]
             */
            type: "array",
            items: {
                type: "number"
            },
            uniqueItems: true
        }
    }, // properties
    required: [
        "type", "base"
    ],
    definitions: {
        scaling: {
            /*
             * The scaling object guides the transformation between integer data
             * implementation value ("raw value") I and presentation value P using
             * scaling factors A, B and C. This is used to implement fixed-point
             * arithmetic for precise arithmetic with finite resolution.
             *
             * P := A * 10^B * (C + I)
             * I := P / (A * 10^B) - C
             *
             * The resolution value s (for "step") equals P(A, B, C, I) for I = 1.
             *
             * For example, scaling factors A, B, C of +1, -1, 0 support a
             * fixed-point presentation value with a resolution of 0.1.
             */
            type: "object",
            properties: {
                a: {
                    type: "integer",
                    minimum: -32768,
                    maximum: 32767,
                    default: 1
                },
                b: {
                    type: "integer",
                    minimum: -32768,
                    maximum: 32767,
                    default: 0
                },
                c: {
                    type: "integer",
                    minimum: -32768,
                    maximum: 32767,
                    default: 0
                },
                s: {
                    type: "number"
                }
            }, // scaling properties
            required: [
                "a", "b", "c"
            ]
        } // scaling
    } // definitions
}; // scalar


const baseFloat = {
    /*
     * A base type for floating point items.
     *
     * Float types do not support an explicit "invalid value" due to the
     * intrinsic difficulty of comparing two floating point values for
     * equality. Use NaN (not a number) instead.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseFloat",
    title: "baseFloat",
    description: "A floating point data type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "float"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"
        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        /*
         * Float properties.
         */
        min: {
            /*
             * The numerically smallest valid value for this type.
             * This may be greater than the native minimum of the base
             * type.
             */
            type: "number"
        },
        max: {
            /*
             * The numerically largest valid value for this type.
             * This may be less than the native maximum of the base
             * type.
             */
            type: "number"
        },
        "array-size": {
            type: "integer",
            minimum: 0, // 0, 1: not an array, 2...max: array
            default: 0
        },
        base: {
            /*
             * The base type indicates how the data is implemented in the
             * edge protocol. Also see byte-order.
             */
            enum: [
                "half", // IEEE 754 half precision
                "float", // IEEE 754 single precision
                "double", // IEEE 754 double precision
                "double double" // IEEE 754 quadruple precision
            ],
            default: "float"
        },
        "byte-order": {
            /*
             * This describes the implementation byte order. The property
             * is optional and defaults to a big endian network byte order.
             */
            enum: [
                "big-endian", "little-endian"
            ],
            default: "big-endian"
        }
    }, // properties
    required: [
        "type", "base"
    ]
}; // float


const baseEnum = {
    /*
     * A base type for enumerations. An enumeration is understood as a
     * set of literals, each mapping to a numerical value. All enumerations
     * map to signed integers.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseEnum",
    title: "baseEnum",
    description: "An enumeration data type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "enum"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"
        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        /*
         * Enum properties.
         */
        min: {
            /*
             * The numerically smallest valid value for this type.
             * This may be greater than the native minimum of the base
             * type.
             */
            type: "number"
        },
        max: {
            /*
             * The numerically largest valid value for this type.
             * This may be less than the native maximum of the base
             * type.
             */
            type: "number"
        },
        invalid: {
            /*
             * The optional invalid value can be within or outside the
             * range defined by min, max so long as it can be stored
             * in the base type.
             * When an item's value matches the invalid value, the item
             * indicates that it does not currently hold a valid value.
             * The invalid value is expressed as implementation data.
             */
            type: "number"
        },
        "array-size": {
            type: "integer",
            minimum: 0, // 0, 1: not an array, 2...max: array
            default: 0
        },
        base: {
            /*
             * The base type indicates how the data is implemented in the
             * edge protocol. Also see byte-order.
             */
            enum: [
                "int8",
                "int16",
                "int32",
                "int64"
            ],
            default: "int8"
        },
        enum: {
            /*
             * A type reference to enumeration type.
             */
            type: "string",
            minLength: 1
        },
        "byte-order": {
            /*
             * This describes the implementation byte order. The property
             * is optional and defaults to a big endian network byte order.
             */
            enum: [
                "big-endian", "little-endian"
            ],
            default: "big-endian"
        }
    }, // properties
    required: [
        "type", "enum"
    ]
}; // enum


const baseReference = {
    /*
     * A base type for type references, how one type can be defined to derive from
     * another. Such a type can impose further restrictions, for example by
     * specifying a minimum value larger than that of the referenced type.
     * A referring type should not allow data in violation of the referred type.
     *
     * A reference may refer to any applicable datapoint type.
     *
     * Applicable are all datapoint types which are available from the profile's
     * definition standpoint of view, subject to protocol-specific visibility rules.
     * Data types derived from LonMark Resource Files, for example, define their
     * visibility rules through program Id mask and scope selector values.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseReference",
    title: "baseReference",
    description: "A data type reference",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "reference"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"
        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        /*
         * Reference properties:
         *
         * min, max and invalid are allowed but have no restrictions
         * or data type, because the referenced data type could implement
         * a numerical or a non-numerical minimum value, for example.
         */
        "array-size": {
            type: "integer",
            minimum: 0, // 0, 1: not an array, 2...max: array
            default: 0
        },
        reference: {
            /*
             * A type reference to the referenced type.
             */
            type: "string",
            minLength: 1
        }
    }, // properties
    required: [
        "type", "reference"
    ]
}; // reference


const baseBitfield = {
    /*
     * A base type for bitfields similar to C bitfields.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseBitfield",
    title: "baseBitfield",
    description: "A bitfield type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "bitfield"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        /*
         * Bitfield properties:
         */
        size: {
            /*
             * The size of this bit field in bits. A bitfield size of zero
             * skips to the next container.
             */
            type: "integer",
            minimum: 0,
            maximum: 64,
            default: 1
        },
        signed: {
            /*
             * Whether the field implements a signed value.
             */
            type: "boolean",
            default: false
        },
        min: {
            /*
             * Numerically smallest valid value, expressed in implementation
             * data.
             */
            type: "number"
        },
        max: {
            /*
             * Numerically largest valid value, expressed in implementation
             * data.
             */
            type: "number"
        },
        invalid: {
            /*
             * A designated "invalid" value, expressed in implementation data.
             * May be outside the min, max range but is subject to size and signed
             * constraints.
             */
            type: "number"
        },
        base: {
            /*
             * The container within which the bitfield is implemented.
             */
            enum: [
                "uint8",
                "uint16",
                "uint32",
                "uint64"
            ],
            default: "uint8"
        },
        offset: {
            /*
             * The bitfield position within the container. Offset 0
             * aligns the most significant bitfield bit with the most
             * significant container bit for big-endian byte orientation.
             * For little-endian orientation, offset 0 aligns the least
             * significant bitfield bit with the least significant
             * containiner bit.
             */
            type: "integer",
            minimum: 0,
            maximum: 63
        },
        "byte-order": {
            /*
             * This describes the implementation byte order. The property
             * is optional and defaults to a big endian network byte order.
             */
            enum: [
                "big-endian", "little-endian"
            ],
            default: "big-endian"
        },
        scaling: {
            /*
             * The scaling object guides the transformation between
             * implementation and presentation.
             */
            "$ref": "#/definitions/scaling"
        }
    }, // properties
    required: [
        "type", "offset"
    ],
    definitions: {
        scaling: {
            /*
             * The scaling object guides the transformation between integer data
             * implementation value I and presentation value P using scaling
             * factors A, B and C:
             *
             * P := A * 10^B + (C + I)
             *
             * The resolution value s (for "step") equals P(A, B, C, I) for I == 1.
             */
            type: "object",
            properties: {
                a: {
                    type: "integer",
                    minimum: -32768,
                    maximum: 32767,
                    default: 0
                },
                b: {
                    type: "integer",
                    minimum: -32768,
                    maximum: 32767,
                    default: 0
                },
                c: {
                    type: "integer",
                    minimum: -32768,
                    maximum: 32767,
                    default: 0
                },
                s: {
                    type: "number"
                }
            }, // scaling properties
            required: [
                "a", "b", "c"
            ]
        } // scaling
    } // definitions
}; // bitfield


const baseBoolean = {
    /*
     * A base type for simple booleans.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseBoolean",
    title: "baseBoolean",
    description: "A Boolean type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "boolean"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"
        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        /*
         * Boolean properties:
         */
        "array-size": {
            type: "integer",
            minimum: 0, // 0, 1: not an array, 2...max: array
            default: 0
        },
        base: {
            /*
             * The container within which the Boolean is implemented.
             */
            enum: [
                "int8",
                "int16",
                "int32",
                "int64"
            ],
            default: "int8"
        },
        "byte-order": {
            /*
             * This describes the implementation byte order. The property
             * is optional and defaults to a big endian network byte order.
             */
            enum: [
                "big-endian", "little-endian"
            ],
            default: "big-endian"
        }
    }, // properties
    required: [
        "type"
    ]
}; // boolean


const baseBCD = {
    /*
     * A base type for binary encoded decimal numbers (BCD).
     * Negative numbers are not supported.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseBCD",
    title: "baseBCD",
    description: "A BCD type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "bcd"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        /*
         * BCD properties:
         */
        min: {
            type: "integer",
            default: 0
        },
        max: {
            type: "integer"
        },
        invalid: {
            type: "integer"
        },
        "array-size": {
            type: "integer",
            minimum: 0, // 0, 1: not an array, 2...max: array
            default: 0
        },

        base: {
            /*
             * The container within which the data is implemented.
             */
            enum: [
                "uint8",
                "uint16",
                "uint32",
                "uint64"
            ],
            default: "uint16"
        },
        "byte-order": {
            /*
             * This describes the implementation byte order. The property
             * is optional and defaults to a big endian network byte order.
             */
            enum: [
                "big-endian", "little-endian"
            ],
            default: "big-endian"
        },
        "nibble-order": {
            /*
             * In big endian nibble order the most significant BCD digit
             * aligns with the most significant nibble in a byte.
             */
            enum: [
                "big-endian", "little-endian"
            ],
            default: "big-endian"
        },
        packed: {
            /*
             * Packed BCD uses one nibble per digit, unpacked BCD uses
             * a byte per digit.
             */
            type: "boolean",
            default: true
        }
    }, // properties
    required: [
        "type"
    ]
}; // bcd


const baseString = {
    /*
     * A base type for strings.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseString",
    title: "baseString",
    description: "A string type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "string"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        /*
         * String properties:
         */
        min: {
            /*
             * The minimum string length in characters.
             */
            type: "integer",
            default: 0
        },
        max: {
            /*
             * The maximum string length in characters.
             */
            type: "integer"
        },
        invalid: {
            type: "null"
        },
        regex: {
            /*
             * A regular expression. The string value must match
             * this regular expression.
             * The regular expression must conform to the Perl
             * programming language, release 5.8.8.
             */
            type: "string"
        },
        "array-size": {
            type: "integer",
            minimum: 0, // 0, 1: not an array, 2...max: array
            default: 0
        },
        encoding: {
            enum: [
                "ascii",
                "utf-8",
                "utf-16"
            ],
            default: "utf-8"
        },
        "runtime-encoding": {
            /*
             * "runtime-encoding" is true if the string encoding may change from
             * the default at runtime. The "encoding" property provides the default
             * encoding.
             * Strings which support different encoding types at runtime require
             * comprehension in context with another data field, typically an
             * enumeration, which reports the current encoding.
             */
            type: "boolean",
            default: false
        },
        termination: {
            enum: [
                "padded", // string is right-filled with 0x00 to max length
                "truncated" // variable length string terminated with 0x00
            ],
            default: "padded"
        }
    }, // properties
    required: [
        "type"
    ]
}; // string


const baseAggregate = {
    /*
     * A base type for structures and unions.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseAggregate",
    title: "baseAggregate",
    description: "A structure or union data type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "aggregate"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        /*
         * Aggregate properties:
         */
        cat: {
            enum: [
                "oneOf",
                "allOf"
            ]
        },

        "array-size": {
            type: "integer",
            minimum: 0, // 0, 1: not an array, 2...max: array
            default: 0
        },

        members: {
            type: "array",
            items: {
                anyOf: [{
                    "$ref": "http://glp-data-types.echelon.com/schema/baseScalar"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseFloat"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseEnum"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseReference"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseBitfield"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseBoolean"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseBCD"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseString"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseAggregate"
                }
            ]
            }
        },

        packing: {
            /*
             * Packing controls whether a gap must be inserted between one member A and the
             * next member B. The packing value indicates by which value the offset
             * address of member B must be divisible without remainder:
             *
             * Packing of one indicates byte frames, allowing B to appear at any offset.
             * Packing of two indicates a 16 bit frame, allowing B only to appear at even
             * addresses. A filler of 0x00 bytes may be inserted between A and B.
             * Packing of 3 or 4 indicates 32 or 64 byte frames, requiring that B must be
             * at an offset address divisible by 4 or 8 without remainder, respectively.
             */
            enum: [
                1,
                2,
                4,
                8
            ],
            default: 1
        },
        padding: {
            /*
             * Padding controls how two adjacent structures A and B within an array are addressed.
             * Padding of one indicates byte frames, allowing B to start at any offset address.
             * A padding of two indicates a 16-bit word frame, requiring B to start at an offset
             * address divisible by 2, and so on.
             */
            enum: [
                1,
                2,
                4,
                8
            ],
            default: 1
        },
        alignment : {
            /*
             * This describes the implementation alignment. The property
             * is optional and defaults to a big endian network byte order.
             */
            enum: [
                "big-endian", "little-endian"
            ],
            default: "big-endian"
        },
    }, // properties
    required: [
        "type", "cat", "members"
    ]
    
}; // aggregate


const baseInheriting = {
    /*
     * An inheriting base type for use with property types.
     *
     * A property defined with an inheriting type has no data type on its
     * onw but inherits the data type from the datapoint the property
     * applies to. This is useful to define generic semantics such as
     * properties for value overrides once for all datapoint types the
     * property may apply to.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/baseInheriting",
    title: "baseInheriting",
    description: "An inheriting property type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        type: {
            const: "inheriting"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * An optional programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        }
    }, // properties
    required: [
        "type"
    ]
}; // inheriting


/*
 * Enumerations are maps between literals and their numerical value.
 * Profiles cannot implement enumerations directly but may implement
 * datapoint and property types which in turn may reference or include
 * an enumeration.
 */
const enumeration = {
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/enumeration",
    title: "enumeration",
    description: "An enumeration type",
    type: "object",
    properties: {
        "class": {
            const: "enumeration"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        id: {
            /*
             * A programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        members: {
            type: "array",
            items: {
                "$ref": "#/definitions/member"
            }
        }
    }, // properties
    required: [
        "id", "members"
    ],
    definitions: {
        member: {
            type: "object",
            properties: {
                id: {
                    type: "string"
                },
                value: {
                    type: "integer"
                },
                comment: {
                    "$ref": "http://glp-data-types.echelon.com/schema/localizableString"
                },
                name: {
                    "$ref": "http://glp-data-types.echelon.com/schema/localizableString"
                }
            }, // properties
            required: [
                "id", "value"
            ]
        } // member
    } // definitions
}; // enumeration



/*
 * Datapoint and property types are defined in this section.
 *
 * Applications implement datapoints and properties through the
 * implementation of a profile. Datapoint and property types provide
 * semantics and additional detail to the base type they implement,
 * profiles group datapoint and properties into units of functionality.
 */


const datapoint = {
    /*
     * A datapoint type. Datapoints can generally be read and written.
     * Because datapoint values can change as an application output or
     * due to peer-to-peer datapoint connections, they can be monitored
     * for change. Datapoints are typically volatile and do not preserve
     * their most recent value over a reset or power cycle.
     *
     * Datapoint values and fields within datapoints which implement
     * an aggregate type can be assigned and may report a value that
     * meets the type described with the schema indicated by the "type"
     * property.
     * Implementations also support the assignment of the keyword "invalid"
     * and might present the value with the keyword "invalid" to indicate
     * that the item has no valid value. Edge processors translate the
     * "invalid" keyword to the designated numeric value where available.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/datapoint",
    title: "datapoint",
    description: "A datapoint type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        "class": {
            const: "datapoint"
        },
        name: {
            /*
            * A type name fit for human consumption and display in a user interface.
            */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"
        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"
        },
        id: {
            /*
             * A programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        key: {
            /*
             * A numeric identifier for this type, unique within its type class,
             * program ID and scope. For example, a set of type definitions grouped
             * under program ID and scope 8001020304050607-4 has a set of datapoint,
             * property and profile types. Each datapoint, property and profile
             * has a unique key within its class.
             * The "key" acts as a key and its numeric value has no other significance.
             *
             * Some applications require a type key, primarily those which support
             * interface changes at runtime (dynamic interfaces or changeable-type
             * interfaces) and those which support development of applications or
             * related artifacts based on IAP/MQ data types. Those applications
             * may be prevented from using a data type unless a "key" is provided.
             */
            type: "integer",
            minimum: 0
        },
        type: {
            anyOf: [
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseScalar"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseFloat"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseEnum"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseReference"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseBitfield"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseBoolean"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseBCD"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseString"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseAggregate"
                }
            ]
        },
        default: {
            /*
             * An optional default value, must match type.
             * A default value define here overrides a default defined
             * with the base type, but must still meet the base type's
             * requirements.
             */
        },
        alarms: {
            "$ref": "http://glp-data-types.echelon.com/schema/applicationAlarms"
        }
    }, // properties
    required: [
        "class", "id", "type"
    ]
}; // datapoint


const property = {
    /*
     * A property is an expansion on a datapoint through the addition of
     * semantics. For example, a datapoint might decribe a temperature value.
     * A property might implement the same temperature value, typically using
     * a reference to the datapoint type, but define the property as the lower
     * temperature threshold for a cooler device. Another property might have
     * a similar definition, controlling the higher setpoint of a cooler device.
     *
     * Most properties do not support unsolicited value changes as typically
     * is the case for datapoints, but some applications may update certain
     * properties.
     * Property values are typically changing very infrequently and are preserved
     * over a reset or power cycle.
     *
     * Property values and fields within properties which implement
     * an aggregate type can be assigned and may report a value that
     * meets the type described with the schema indicated by the "type"
     * property.
     * Implementations also support the assignment of the keyword "invalid"
     * and might present the value with the keyword "invalid" to indicate
     * that the item has no valid value. Edge processors translate the
     * "invalid" keyword to the designated numeric value where available.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/property",
    title: "property",
    description: "A property type",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        "class": {
            const: "property"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        unit: {
            /*
             * An optional unit of measurement.
             * Where applicable, the unit should be a non-localizable unit of
             * measurement expressed in a SI or derived SI unit such as kg, s
             * or m for kilogram, seconds and meters. Non-SI units such as F
             * (Fahrenheit) or mph (miles per hour) are acceptable where
             * appropriate.
             */
            type: "string"

        },
        id: {
            /*
             * A programmatic name, a type name for use with software
             * code or machine readers. This may differ from the type name, for
             * example by using underscore characters where the type name may
             * include a space.
             */
            type: "string"
        },
        key: {
            /*
             * A numeric identifier for this type, unique within its type class,
             * program ID and scope. For example, a set of type definitions grouped
             * under program ID and scope 8001020304050607-4 has a set of datapoint,
             * property and profile types. Each datapoint, property and profile
             * has a unique key within its class.
             * The "key" acts as a key and its numeric value has no other significance.
             *
             * Some applications require a type key, primarily those which support
             * interface changes at runtime (dynamic interfaces or changeable-type
             * interfaces) and those which support development of applications or
             * related artifacts based on IAP/MQ data types. Those applications
             * may be prevented from using a data type unless a "key" is provided.
             */
            type: "integer",
            minimum: 0
        },
        type: {
            anyOf: [
                // {
                //     "$ref": "http://glp-data-types.echelon.com/schema/baseFloat"
                // },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseScalar"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseFloat"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseEnum"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseReference"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseBitfield"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseBoolean"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseBCD"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseString"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseAggregate"
                },
                {
                    "$ref": "http://glp-data-types.echelon.com/schema/baseInheriting"
                }
            ]
        },
        default: {
            /*
             * An optional default value, must match type.
             * A default value define here overrides a default defined
             * with the base type, but must still meet the base type's
             * requirements.
             */
        },
        min: {
            /*
             * An optional minimum value override.
             * A minimum value overrides the minimum value defined with the
             * base type, but must meet the base type's requirements.
             * The minimum value override can further restrict but must not
             * expand the base type's range.
             */
        },
        max: {
            /*
             * An optional maximum value override.
             * A maximum value overrides the maximum value defined with the
             * base type, but must meet the base type's requirements.
             * The maximum value override can further restrict but must not
             * expand the base type's range.
             */
        },
        invalid: {
            /*
             * An optional invalid value override.
             * An invalid value override overrides the invalid value defined
             * with the base type, but must meet the base type's requirements.
             */
        }
    }, // properties
    required: [
        "class", "id", "type"
    ]
}; // property


const applicationAlarms = {
    /*
     * The alarms property lists properties within the object
     * described by this schema which indicate simple application-
     * specific alarm conditions. Examples include a "day burner"
     * alarm from an outdoor lighting device, or a "door
     * open" alarm from a cabinet in an application's status object,
     * or an alarm condition flag in an output datapoint.
     * Tools consider the alarm to be active when the
     * property value evaluates to a logical True, and the alarm
     * to be inactive when the the property value evaluates to
     * a logical False. Simple application-specific alarm
     * conditions are generally implemented as Booleans, strings
     * or numbers.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/applicationAlarms",
    title: "ApplicationAlarms",
    description: "Simple application-specific alarm conditions",
    type: "array",
    items: {
        type: "string"
    }
}; // applicationAlarms


/*
 * Profiles refine datapoints and properties for a specific application as a
 * profile datapoint type or profile property type and combine these into a
 * profile with well-defined behavior and either a specific application such
 * as a indoor electric water heater control unit, or into a generic application
 * with well-defined behavior such as a general-purpose PID-T2 digital controller.
 *
 * Applications implement profiles as blocks. Each block is an implementation of
 * a profile including all mandatory profile property and datapoint members and
 * any of the optional profile property and datapoint members.
 * Implementations of property datapoint and property members are governed by the
 * rules defined with the profile.
 */

const memberDatapoint = {
    /*
     * A profile datapoint member may applicable datapoint types, or may implement
     * a wildcard datapoint type.
     *
     * Applicable are all datapoint types which are available from the profile's
     * definition standpoint of view, subject to protocol-specific visibility rules.
     * Data types derived from LonMark Resource Files, for example, define their
     * visibility rules through program Id mask and scope selector values.
     *
     * Wildcard types are known as "SNVT_xxx" in LonMark Resource Files. These
     * are placeholders within a profile, to be replaced with an actual datapoint
     * type when the profile is implemented as a block. Wildcards allow for generic
     * profile definitions such as a generic PID controller whose setpoint, process
     * value and control value datapoints could implement a temperature datapoint
     * type in one block, and a velocity datapoint type in another.
     *
     * Profiles may declare more than one datapoint member to use the wildcard type,
     * but implementations of the profile must use the same datapoint type to
     * instantiate all wildcard types within the block.
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/memberDatapoint",
    title: "MemberDatapoint",
    description: "Profile member datapoint",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        id: {
            /*
             * A programmatic name, a member name for use with software
             * code or machine readers. This may differ from the name, for
             * example by using underscore characters where the name may
             * include a space.
             */
            type: "string"
        },
        type: {
            /*
             * The type for a member that is not a wildcard is a simple type reference,
             * such as "SNVT_volt".
             *
             * Member types can also declare wildcard types. Any compatible type
             * may be used to implement such a wildcard member.
             * Wildcard members report their type with a Perl 5 regular expression,
             * embedded within a pair of forward slash characters, such as
             * "/SNVT.+/".
             *
             * The pair of forward slash characters is not part of the regular
             * expression, but everything within that character pair is.
             *
             * The regular expression is case-sensitive. Any type matching the
             * regular expression may be used to implement the wildcard
             * member.
             */
            type: "string",
            format: "regex"
        },
        dir: {
            /*
             * direction is network-centric: an input datapoint is an input
             * from the network into the profile or block, often corresponding
             * to a physical output such as a lamp dimmer. An output datapoint
             * is an output from the block, often corresponding to a computed
             * value or one obtained from a physical input such as a temperature
             * sensor.
             * A bidirectional datapoint can act as both input and output.
             */
            enum: [
                "input",
                "output",
                "inout"
            ]
        },
        mandatory: {
            /*
             * A block implementing a profile must implement all mandatory profile
             * members, and may implement any of the optional members. Optional
             * members are those reported as not mandatory.
             */
            type: "boolean"
        },
        min: {
            /*
             * An optional minimum value override.
             * A minimum value overrides the minimum value defined with the
             * base type, but must meet the base type's requirements.
             * The minimum value override can further restrict but must not
             * expand the base type's range.
             */
        },
        max: {
            /*
             * An optional maximum value override.
             * A maximum value overrides the maximum value defined with the
             * base type, but must meet the base type's requirements.
             * The maximum value override can further restrict but must not
             * expand the base type's range.
             */
        },
        invalid: {
            /*
             * An optional invalid value override.
             * An invalid value override overrides the invalid value defined
             * with the base type, but must meet the base type's requirements.
             */
        },
        descriptor :{
            type: "string", 
            pattern: "^[#|][0-9]+$"
        },
        unit: {
            type: "string"
        }

    }, // properties
    required: [
        "id", "type", "mandatory", "dir"
    ]
}; // memberDatapoint


const memberProperty = {
    /*
     * A profile property member may implement applicable property types.
     * Because properties convey semantics, a wildcard property type cannot
     * exist, but inheriting property types automatically derive their type from
     * the datapoint they apply to.
     *
     * Applicable are property types which are available from the profile's
     * definition standpoint of view, subject to protocol-specific visibility rules.
     * Data types derived from LonMark Resource Files, for example, define their
     * visibility rules through program Id mask and scope selector values.
     *
     */
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/memberProperty",
    title: "MemberProperty",
    description: "Profile member property",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        id: {
            /*
             * A programmatic name, a member name for use with software
             * code or machine readers. This may differ from the name, for
             * example by using underscore characters where the name may
             * include a space.
             */
            type: "string"
        },
        type: {
            /*
             * The member type is defined as a Perl 5 regular expression, with an implied
             * ^ at the start and $ at the end, matching the type for use with this member.
             * For example, a value of "SCPTlocation" matches that type exactly.
             * The standard resource set identifier is 0000000000000000-0, and is never
             * included.
             * However, some profile members may not be limited to a specific type.
             * ".*" allows for any type to implement the member, but other expressions
             * could restrict the choice to a well-defined set of allowed types, or to a
             * range of types.
             */
            type: "string",
            format: "regex"
        },
        mandatory: {
            /*
             * A block implementing a profile must implement all mandatory profile
             * members, and may implement any of the optional members. Optional
             * members are those reported as not mandatory.
             */
            type: "boolean"
        },
        min: {
            /*
             * An optional minimum value override.
             * A minimum value overrides the minimum value defined with the
             * base type, but must meet the base type's requirements.
             * The minimum value override can further restrict but must not
             * expand the base type's range.
             */
        },
        max: {
            /*
             * An optional maximum value override.
             * A maximum value overrides the maximum value defined with the
             * base type, but must meet the base type's requirements.
             * The maximum value override can further restrict but must not
             * expand the base type's range.
             */
        },
        invalid: {
            /*
             * An optional invalid value override.
             * An invalid value override overrides the invalid value defined
             * with the base type, but must meet the base type's requirements.
             */
        },
        default: {
            /*
             * An optional default value override.
             * A default value overrides the default value defined with the
             * base type, but must meet the base type's requirements.
             * The default value override can further restrict but must not
             * expand the base type's range.
             */
        },
        applies: {
            /*
             * A property applies to the block or to a specific datapoint member
             * implemented in the same block. The item to which the property applies
             * is also known as the property's application set. The application set
             * is defined with this attribute, which lists the profile name
             * for properties applying to the block, or the datapoint member name for
             * those applying to a datapoint member.
             *
             * A given property implementation may apply to multiple blocks or to
             * multiple datapoints, known as a shared property. Within a profile,
             * the property is never explicitly shared but always applies to a single
             * item. However, properties which explicitly apply to the block often
             * implicitly govern one or more of its members as evident from the
             * property's semantics.
             */
            type: "string",
            minLength: 1
        },
        array: {
            /*
             * Member properties are often singletons, but some profiles also
             * allow or even require the implementation as a property array.
             * Profiles can require a specific size for that array, or can
             * define a minimum and maximum array size.
             *
             * When the array property is not present or null, the property
             * may not be implemented as an array. Otherwise the array object
             * details the array implementation requirements.
             */
            "$ref": "#/definitions/array",
            default: null
        },
        restrictions: {
            /*
             * Properties may carry flags which restrict their use.
             * These are optional; properties not reporting restrictions
             * or reporting these as null are unrestricted.
             */
            "$ref": "#/definitions/restrictions",
            default: null
        },
        presentation: {
            /*
             * Simple properties can be presented as plain block members. For
             * example a digital output block may include an "invert" option,
             * which it might present as a plain Boolean property of the block.
             *
             * More complex properties might include definitions of default values
             * or override values and similar detail. These complex properties would
             * be presented with a IAP Datapoint object.
             *
             * The 'presentation' attribute reports how the property is implemented,
             * allowing the generic tool to recognize its implementation within the
             * block.
             *
             * Because a "plain" property does not include a type declaration, tools
             * must deduce the type of plain property from the profile.
             */
            enum: [
                "plain",
                "datapoint"
            ],
            default: "datapoint"
        },
        descriptor :{
            type: "string", 
            pattern: "^[#|][0-9]+$"
        },
        unit: {
            type: "string"
        }
    }, // properties
    required: [
        "id", "type", "mandatory"
    ],
    definitions: {
        array: {
            /*
             * The array object details a property member's implementation
             * as an array.
             */
            type: "object",
            properties: {
                is: {
                    enum: [
                        "prohibited",
                        "permitted",
                        "required"
                    ],
                    default: "prohibited"
                },
                min: {
                    /*
                     * The minimum array size.
                     */
                    type: "integer",
                    minimum: 2,
                    default: 2
                },
                max: {
                    /*
                     * The maximum array size. When equal to the minimum size,
                     * the array must be implemented with this exact number of
                     * elements. When greater than the minimum size, the array
                     * may be implemented with any number of elements from min
                     * to max, both inclusive.
                     * When a maximum is not defined, the maximum size is infinite.
                     */
                    type: "integer",
                    minimum: 2
                }
            },
            required: [
                "is"
            ]
        }, // array
        restrictions: {
            type: "object",
            properties: {
                "device-specific": {
                    /*
                     * The application on the device that implements a device-specific
                     * property may change this property value without notice, for
                     * example to report calibration data.
                     * A network tool must not rely upon cached values for this property.
                     */
                    type: "boolean"
                },
                "manufacturing-only": {
                    /*
                     * A manufacturing only property may only be changed during manufacture.
                     * Network tools do not modify this property during normal operation.
                     */
                    type: "boolean"
                },
                "reset-required": {
                    /*
                     * A property can request that the device or application that implements
                     * it is reset after a change to the property value and before the new
                     * value takes effect.
                     */
                    type: "boolean"
                },
                "offline-required": {
                    /*
                     * A property can request that the device or application be put in offline
                     * mode while the property is modified.
                     *
                     * The new property value may not take effect until the device is in online
                     * mode again. Note that resetting the device also clears offline mode.
                     */
                    type: "boolean"
                },
                "disable-required": {
                    /*
                     * A property can request that the device, application or block that implements
                     * the property be disabled before the property is changed, and be enabled
                     * again before the new property value takes effect.
                     */
                    type: "boolean"
                },
                "const": {
                    /*
                     * A constant property cannot be changed and is used to report constant
                     * properties such as an application version number.
                     */
                    type: "boolean"
                }
            } // properties
        } // restrictions
    } // definitions
}; // memberProperty


const profile = {
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/profile",
    title: "profile",
    description: "Profile",
    type: "object",
    properties: {
        /*
         * Common properties
         */
        "class": {
            const: "profile"
        },
        name: {
            /*
             * A type name fit for human consumption and display in a user interface.
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        comment: {
            /*
             * An optional comment
             */
            "$ref": "http://glp-data-types.echelon.com/schema/localizableString"

        },
        id: {
            /*
             * A programmatic name, a member name for use with software
             * code or machine readers. This may differ from the name, for
             * example by using underscore characters where the name may
             * include a space.
             */
            type: "string"
        },
        key: {
            /*
             * A numeric identifier for this type, unique within its type class,
             * program ID and scope. For example, a set of type definitions grouped
             * under program ID and scope 8001020304050607-4 has a set of datapoint,
             * property and profile types. Each datapoint, property and profile
             * has a unique key within its class.
             * The "key" acts as a key and its numeric value has no other significance.
             *
             * Some applications require a type key, primarily those which support
             * interface changes at runtime (dynamic interfaces or changeable-type
             * interfaces) and those which support development of applications or
             * related artifacts based on IAP/MQ data types. Those applications
             * may be prevented from using a data type unless a "key" is provided.
             */
            type: "integer",
            minimum: 0
        },
        inheriting: {
            /*
             * A profile may inherit from another applicable profile.
             * Applicable are profiles which are available from this profile's
             * definition standpoint of view, subject to protocol-specific
             * visibility rules.
             * Data types derived from LonMark Resource Files, for example,
             * define their visibility rules through program Id mask and
             * scope selector values.
             */
            type: "string"
        },
        principal: {
            /*
             * A profile may nominate one of its member datapoints as the
             * principal datapoint through the member id value.
             *
             * A principal datapoint nomination can guide generic user
             * interfaces and defines the application set for some properties
             * which are explicitly applied to the block but semantically
             * apply to a datapoint, such as a default value or override
             * control property.
             */
            type: "string"
        },
        datapoints: {
            type: "object",
            additionalProperties: {
                "$ref": "http://glp-data-types.echelon.com/schema/memberDatapoint"
            }
        },
        properties: {
            type: "object",
            additionalProperties: {
                "$ref": "http://glp-data-types.echelon.com/schema/memberProperty"
            }
        }
    }, // properties
    required: [
        "class", "id"
    ]
}; // profile

/*
 * The Application schema describes capabilities of the application, keyed by the
 * device type. One application declaration may be shared among different versions
 * of the same application, provided that none of the aspects reported for the
 * application changes. To facilitate this, the type key is evaluated not as an
 * exact match but as a match for the start of the key.
 *
 * Consider for example a device which reports its type within the feedback channel's
 * status object as "type": "80000112345604". This device might be described with a
 * type of "8000011234560", matching only the first 15 characters.
 *
 * Tools prefer a longer type match over a shorter match.
 */
const application = {
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$id": "http://glp-data-types.echelon.com/schema/application",
    title: "application",
    description: "Application",
    type: "object",
    properties: {
        "class": {
            const: "application"
        },
        classification: {
            /*
             * Classification classifies the application as one of several groups.
             * This information is optional.
             *
             * Tools with interfaces to human users might chose this information to
             * guide selective display of items according to their classification.
             *
             */
            enum: [
                "infrastructure", // For routers, network adapters, and so on.
                "configuration", // For applications to help configure and manage services.
                "diagnostics", // For tools for diagnostics and servicing.
                "application" // For all other application types.
            ],
            default: "application"

        },
        description: {
            /*
             * A short description
             */
            type: "string"
        },
        documentation: {
            /*
             * A reference to comprehensive documentation in form of a website URL.
             */
            type: "string",
            format: "uri"
        },
        interface: {
            /*
             * An alphanumeric identifier of the application type aimed at a human
             * user, often including the device's product name and manufacturer name.
             */
            type: "string",
                minLength: 1
        },
        manufacturer: {
            type: "string",
            minLength: 1
        },
        multiplicity: {
            enum: [
                "singleton",
                "unlimited"
            ],
            default: "unlimited"
        },
        product: {
            type: "string",
            minLength: 1
        },
        protocol: {
            type: "string",
            minLength: 1
        },
        status: {
            /*
             * The status property reports non-standard items
             * which appear in the device's status object.
             * Tools accept (and typically ignore) all non-standard
             * properties not declared with this property.
             */
            "$ref": "#/definitions/status"
        },
        actions: {
            /*
             * The actions property reports actions available
             * with the "do" request channel endpoint for this
             * device type.
             * When no actions are defined here, the tools
             * assume that the device supports all standard IAP
             * actions.
             * Actions listed here are in addition to standard
             * actions. Standard actions may also be overridden
             * by adding additional arguments, but removing or
             * re-defining standard actions is not supported.
             */
            "$ref": "#/definitions/actions"
        }
    }, // properties
    required: [
        "class", "interface", "manufacturer", "product"
    ],
    definitions: {
        status: {
            type: "object",
            properties: {
                alarms: {
                    "$ref": "http://glp-data-types.echelon.com/schema/applicationAlarms"
                },
            }
        }, // status
        actions: {
            /*
             * actions is a list of action objects supported by this device.
             * Devices which declare actions are expected only to support
             * the actions declared here. Devices which do not declare actions
             * are expected to support all standard IAP actions, however,
             * devices may still fail an action with an error event if the
             * action may not be performed for any reason.
             */
            type: "array",
            items: {
                "$ref": "#/definitions/action"
            }
        }, // actions
        action: {
            /*
             * Each action is defined with the action name and its arguments.
             * Standard actions must support the arguments defined with the
             * action in the IAP specification. Implementations of standard
             * actions may not remove any of the standard arguments, but
             * specific implementations may add additional arguments if
             * declared here. When declared, all action arguments including
             * the standard action arguments must be declared.
             */
            type: "object",
            properties: {
                id: {
                    /*
                     * The action name such as "load", "test", "wink".
                     */
                    type: "string"
                },
                description: {
                    /*
                     * A brief description for human consumption.
                     */
                    type: "string"
                },
                args: {
                    /*
                     * A JSON schema for the action's arguments.
                     */
                    type: "object"
                }
            }, // properties
            required: [
                "id"
            ]
        } // action
    } // definitions
}; // application

exports.base = {
    aggregate: baseAggregate,
    bcd: baseBCD,
    bitfield: baseBitfield,
    boolean: baseBoolean,
    enumeration: baseEnum,
    float: baseFloat,
    reference: baseReference,
    scalar: baseScalar,
    string: baseString
};

exports.application = application;
exports.datapoint = datapoint;
exports.enum = enumeration;
exports.profile = profile;
exports.property = property;

exports.all = [
    localizableString, 
    baseScalar, 
    baseFloat, 
    baseEnum,
    baseReference,
    baseBitfield, 
    baseBoolean,
    baseBCD, 
    baseString,
    baseAggregate, 
    baseInheriting,
    applicationAlarms,
    memberDatapoint,
    memberProperty
];