{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://heartcortex.ai/schemas/1.0/signal-table.schema.json",
  "title": "Signal table",
  "description": "Every signal a HEART may read, and how (HEART Signal Tables 1.0). A signal not listed here is never served or sent anywhere.",
  "type": "object",
  "required": [
    "format",
    "system",
    "signals"
  ],
  "additionalProperties": false,
  "properties": {
    "$comment": {
      "description": "Free text for people, such as a licence line. Ignored by HEART.",
      "type": "string",
      "maxLength": 500
    },
    "format": {
      "const": "heart-signals/1"
    },
    "system": {
      "$ref": "common.schema.json#/$defs/systemId"
    },
    "template": {
      "type": "string",
      "pattern": "^heart/embeddedstandard/[a-z0-9-]+/v[0-9]+\\.[0-9]+(\\.[0-9]+)?$"
    },
    "reviewed": {
      "description": "Set only when a person has reviewed every signal. A HEART MUST NOT load a table without it.",
      "type": "object",
      "required": [
        "by",
        "at"
      ],
      "additionalProperties": false,
      "properties": {
        "by": {
          "type": "string",
          "minLength": 1
        },
        "at": {
          "type": "string",
          "format": "date"
        }
      }
    },
    "signals": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/signal"
      }
    }
  },
  "$defs": {
    "signal": {
      "type": "object",
      "required": [
        "name",
        "title",
        "type",
        "source",
        "privacy"
      ],
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string",
          "pattern": "^[a-z0-9]+(\\.[a-z0-9-]+)+\\.[a-z0-9_]+$"
        },
        "title": {
          "type": "string",
          "minLength": 1
        },
        "description": {
          "type": "string"
        },
        "type": {
          "enum": [
            "number",
            "integer",
            "boolean",
            "string",
            "enum"
          ]
        },
        "values": {
          "description": "Allowed values when type is enum.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "unit": {
          "description": "UCUM unit code, such as Cel, V, A, %, /min.",
          "type": "string"
        },
        "range": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "min": {
              "type": "number"
            },
            "max": {
              "type": "number"
            }
          }
        },
        "source": {
          "$ref": "#/$defs/source"
        },
        "sampleSec": {
          "type": "number",
          "exclusiveMinimum": 0,
          "default": 5
        },
        "historySec": {
          "type": "integer",
          "minimum": 0,
          "default": 3600
        },
        "privacy": {
          "enum": [
            "public",
            "internal",
            "private",
            "never-share"
          ]
        },
        "writable": {
          "type": "boolean",
          "default": false
        },
        "physical": {
          "description": "Writing it moves, heats, powers or switches something.",
          "type": "boolean",
          "default": false
        },
        "safety": {
          "description": "Part of a safety function: read-only, always (Part 6, Section 9).",
          "type": "boolean",
          "default": false
        },
        "derive": {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "$ref": "common.schema.json#/$defs/statistic"
          },
          "description": "Statistics the HEART keeps for this signal, from the shared statistic list (value, min, max, mean, stddev, trend, overshoot, count)."
        },
        "alerts": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "when",
              "code"
            ],
            "additionalProperties": false,
            "properties": {
              "when": {
                "enum": [
                  "outside-range",
                  "stuck",
                  "no-reading",
                  "noisy"
                ]
              },
              "afterSec": {
                "type": "integer",
                "minimum": 1
              },
              "code": {
                "type": "string",
                "pattern": "^[a-z0-9]+(\\.[a-z0-9-]+)+$"
              },
              "severity": {
                "enum": [
                  "info",
                  "warning",
                  "error",
                  "critical"
                ]
              }
            }
          }
        },
        "draft": {
          "description": "Set by a generator. A person removes it after checking the signal.",
          "const": true
        },
        "notes": {
          "description": "Questions for the reviewer, left by a generator.",
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "safety": {
                "const": true
              }
            },
            "required": [
              "safety"
            ]
          },
          "then": {
            "properties": {
              "writable": {
                "const": false
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "enum"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "required": [
              "values"
            ]
          }
        }
      ]
    },
    "source": {
      "description": "Where the value comes from. Bus sources follow the adapter names of API Standard 14.3; on-chip sources are read by the device's own HEART.",
      "type": "object",
      "required": [
        "protocol"
      ],
      "properties": {
        "protocol": {
          "type": "string",
          "pattern": "^[a-z0-9-]+(\\.[a-z0-9-]+)*$"
        },
        "target": {
          "type": "string"
        },
        "register": {
          "type": "integer",
          "minimum": 0,
          "description": "Modbus: the 0-based protocol address within table, as sent on the wire (holding register 40001 in the old reference numbering is register 0 of table holding). Reference numbers such as 40021 MUST NOT be used.",
          "maximum": 65535
        },
        "table": {
          "enum": [
            "holding",
            "input",
            "coil",
            "discrete"
          ]
        },
        "count": {
          "type": "integer",
          "minimum": 1,
          "maximum": 4
        },
        "frameId": {
          "type": "string",
          "pattern": "^0x[0-9A-Fa-f]{1,8}$"
        },
        "startBit": {
          "type": "integer",
          "minimum": 0
        },
        "bits": {
          "type": "integer",
          "minimum": 1,
          "maximum": 64
        },
        "byteOrder": {
          "enum": [
            "little",
            "big"
          ]
        },
        "signed": {
          "type": "boolean"
        },
        "symbol": {
          "description": "Firmware variable, for on-chip sources.",
          "type": "string"
        },
        "channel": {
          "description": "ADC channel or GPIO pin, for on-chip sources.",
          "type": "integer",
          "minimum": 0
        },
        "scale": {
          "type": "number",
          "default": 1
        },
        "offset": {
          "type": "number",
          "default": 0
        }
      }
    }
  }
}
