﻿<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="EkConfigSchema"
    targetNamespace="http://olfasense.com/ek250/Schema"
    elementFormDefault="qualified"
    xmlns="http://olfasense.com/ek250/Schema"
    xmlns:ek="http://olfasense.com/ek250/Schema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <!-- parity settings for a serial connection, directly parsable for the Parity Enum -->
  <xs:simpleType name="parity">
    <xs:restriction base="xs:string">
      <xs:enumeration value="None"/>
      <xs:enumeration value="Odd"/>
      <xs:enumeration value="Even"/>
      <xs:enumeration value="Mark"/>
      <xs:enumeration value="Space"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- stop bits settings, as parity above -->
  <xs:simpleType name="stopBits">
    <xs:restriction base="xs:string">
      <xs:enumeration value="None"/>
      <xs:enumeration value="One"/>
      <xs:enumeration value="Two"/>
      <xs:enumeration value="OnePointFive"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- supported data types for a modbus quantity -->
  <xs:simpleType name="DataType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Integer16"/>
      <xs:enumeration value="Integer32"/>
      <xs:enumeration value="Float32"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- some devices require some byte shuffling tricks -->
  <xs:simpleType name="ConversionRule">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Identity"/>
      <xs:enumeration value="Reverse"/>
      <xs:enumeration value="FlipWords"/>
      <xs:enumeration value="ReverseFlip"/>      
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="Protocol">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Modbus"/>
      <xs:enumeration value="Custom"/>
      <xs:enumeration value="NetworkCustom"/>
    </xs:restriction>
  </xs:simpleType>
  
  <xs:simpleType name="NewLine">
    <xs:restriction base="xs:string">
      <xs:enumeration value="LineFeed"/>
      <xs:enumeration value="CarriageReturn"/>
      <xs:enumeration value="CarriageReturnLineFeed"/>
      <xs:enumeration value="ETX"/>
    </xs:restriction>
  </xs:simpleType>
  
  <!-- some picky devices require you to read specifically from read-only registers -->
  <xs:simpleType name="RegisterType">
    <xs:restriction base="xs:string">
      <!-- r/w -->
      <xs:enumeration value="HoldingRegister"/>
      <!-- read-only -->
      <xs:enumeration value="InputRegister"/>
    </xs:restriction>
  </xs:simpleType>
  
  <!-- modbus specific settings on connector level -->
  <xs:complexType name="connectorSettingsModbus">
    <xs:attribute name="slaveAddress" type="xs:unsignedByte" default="1" />
    <xs:attribute name="singleWrite" type="xs:boolean" default="false"/>
  </xs:complexType>
  
  <!-- serial connection settings, modbus fixes data bits at 8, start bit is not even
       set-able -->
  <xs:complexType name="serialSettings">
    <xs:attribute name="baud" type="xs:int" default="9600"/>
    <xs:attribute name="stopBits" type="ek:stopBits" default="One"/>
    <xs:attribute name="parity" type="ek:parity" default="None"/>
    <xs:attribute name="newLine" type="ek:NewLine" default="LineFeed" use="optional"/>
  </xs:complexType>
 

  <xs:complexType name="quantity">        
    
    <xs:sequence>
      <xs:element name="modbus" type="ek:quantityConfigurationModbus" minOccurs="0"/>
      <xs:element name="binder" type="ek:quantityCANIDConfiguration" minOccurs="0"/>
    </xs:sequence>
    
    <!-- format string for conversion to string, used in String.Format(...) -->
    <xs:attribute name="formatString" default="{}" type="xs:string"/>
    <!-- human readable, localized label -->
    <xs:attribute name="label" type="xs:string" default="quantityLabelUnset"/>
    <!-- human readable, localized unit -->
    <xs:attribute name="unit" type="xs:string" default="?"/>
    <!-- can we define a set point for this quantity? -->
    <xs:attribute name="readonly" type="xs:boolean" default="true"/>
    <!-- once after connect, read the set point (from the sink!) -->
    <xs:attribute name="readSetPointOnConnect" type="xs:boolean" default="false"/>
    <xs:attribute name="maxSetPoint" type="xs:float"/>
    <xs:attribute name="minSetPoint" type="xs:float"/>
    <xs:attribute name="options" type="xs:string"/>
    
    <!-- factor applied to raw reading before displaying/logging it -->
    <xs:attribute name="factor" type="xs:float" default="1.0"/>
    <!-- an optional additive offset, applied after the factor -->
    <xs:attribute name="offset" type="xs:float" default="0.0"/>

    <!-- set point warning mechanism, warn if warnLimits is true and the user defined set
        point is either below warnLow or above warnHigh
    -->
    
    <xs:attribute name="warnLimits" type="xs:boolean" default="false"/>
    <xs:attribute name="warnLow" type="xs:float" default="0.0"/>
    <xs:attribute name="warnHigh" type="xs:float" default="0.0"/>
    <!-- datatype is part of the base quantity, since this is used for string parsing -->
    <xs:attribute name="dataType" type="ek:DataType"/>
  </xs:complexType>

  <!-- modbus specifics on quantity level -->
  <xs:complexType name="quantityConfigurationModbus">
    
    <!-- start register for reading and writing -->
    <xs:attribute name="source" type="xs:int"/>
    <xs:attribute name="sink" type="xs:int"/>

    <xs:attribute name="pvRegisterType" type="ek:RegisterType" default="HoldingRegister"/>
    <xs:attribute name="conversionRule" type="ek:ConversionRule" default="Reverse"/>    
  </xs:complexType>
  
  <xs:complexType name="quantityCANIDConfiguration">
    <xs:attribute name="readCanId" type="xs:string"/>
    <xs:attribute name="writeCanId" use="optional" type="xs:string"/>
  </xs:complexType>
  
  <xs:complexType name="connector">

    <xs:sequence>
      <xs:element name="serial" type="ek:serialSettings" minOccurs="0" maxOccurs="1"/>
      <xs:element name="modbus" maxOccurs="1" minOccurs="0" type="ek:connectorSettingsModbus"/>

      <!-- list of connected measurable/writable quantities -->

      <xs:element name="quantities"  minOccurs="1" maxOccurs="1">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="quantity" type="ek:quantity" minOccurs="0" maxOccurs="unbounded"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>

    </xs:sequence>
    
    <!-- human readable connector name -->
    <xs:attribute name="name" type="xs:string"/>
    <xs:attribute name="type" type="xs:string" use="required"/>
    
    <xs:attribute name="protocol" use="required" type="ek:Protocol" />
    <xs:attribute name="driver" type="xs:string" default=""/>

    <xs:attribute name="options" type="xs:string"/>
    
  </xs:complexType>

  <xs:element name="ekConfiguration">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="connectors" maxOccurs="1" minOccurs="1">                    
          <xs:complexType>
            <xs:sequence>
              <xs:element name="connector" type="ek:connector" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>            
          </xs:complexType>
        </xs:element>

      </xs:sequence>
      <xs:attribute name="dtPattern" type="xs:string" default="yyyy-MM-dd HH:mm:ss"/>
      <xs:attribute name="baseName" type="xs:string" use="required"/>
    </xs:complexType>  
  </xs:element>

</xs:schema>
