The Gravio platform provides an easy way of adding new sensors to the infrastructure. So called SDD files (Serial Data Definition) describe how serial data should be interpreted and parametrised by Gravio. Here you can learn about how to create such SDD files.

Note: SDD files are specific to a particular manufacturer. So if you like to create an SDD file for a manufacturer or standard that isn’t yet supported by Gravio, please let us know via support@gravio.com and we will investigate the support of the new device range.

As of September 2018, we support EnOcean devices for custom SDD creation.

Step-by-step Creation of an SDD File

Sample Data:

Data Length and Expected Data:

In this document, we talk about the SDD file structure and creating sample SDD files using the data structure above.

The SDD file allows Gravio to register a serial device, or in this case a serial device’s sensor, and give instructions as to how to interpret the data received from a serial device.

SDD Basic Structure

The SDD file is a valid JSON file. The basic structure looks like this:

{
  "Name": "Device Name",
  "DataPoints": [],
  "DataPackageSpec": {
    "Fields": [],
    "Validations": [],
    "Mappings": []
  }
}

We will discuss each portion of this structure as we go along this document.

DataPackageSpec

"DataPackageSpec": {}

The DataPackage spec contains the information needed for Gravio to understand the format of the packet sent by the device. Serial data is usually very detailed and the SDD file allows us to handle virtually any kind of data.

In order to create the DataPackageSpec for this device, we only need the above sample data as a guide.

DataPackageSpec – Fields

"DataPackageSpec": {
    "Fields": [],
  }

The fields allow us to specify each portion of the message packet.

The first three parts of the packet, which are the Head, Type and Data length fields, all have a constant size of 1 byte each. We can directly write these three as constants.

{
    "Name": “Head”,
    "Size": {
      "SizeType": "Constant",
      "Size": 1
    }
  },
  {
    "Name": “Type",
    "Size": {
      "SizeType": "Constant",
      "Size": 1
    }
  },
  {
    "Name": “DataLength",
    "Size": {
      "SizeType": "Constant",
      "Size": 1
    }
  }

Next is the actual Data payload. Since the Data’s size is variable, but is indicated by the DataLength field, we can use that as the reference for the Data field.

  {
    "Name": “Data",
    "Size": {
      "SizeType": “Reference",
      "SizeRef": "DataLength"
    }
  }

The rest of the packet, including the Foot and CRC fields, are also 1 byte constants each.

  {
    "Name": “Foot",
    "Size": {
      "SizeType": "Constant",
      "Size": 1
    }
  },
  {
    "Name": “CRC”,
    "Size": {
      "SizeType": "Constant",
      "Size": 1
    }
  }

Our three SDD files will have all of these Fields in common because they have the same packet instructions. However since the Data is different, the other parts of the SDD file which we will discuss now are also different.

Name Node

This is the identifier for the device to register to Gravio. You may choose your own name for the device, but the name for must also be the same name for the SDD file. We will choose our own name for the three SDD files based on the function:

Door:

 "Name": “SampleDoor”,

Temp:

  "Name": “SampleTemperature”,

Accelerometer:

  "Name": “SampleAccelerometer”,

The DataPoints node comes next, but since it depends on another feature of this JSON structure, we will discuss DataPoints after we have covered that.

DataPackageSpec – Validation


  "DataPackageSpec": {
    “Validations": [],
  }

Since the lengths of fields are the same for all devices save for the data portion, most of the validation is the same for all three:

 {
        "ValidationType": "Equals",
        "Input": "Head",
        "Output": “FE"
}
 {
        "ValidationType": "Equals",
        "Input": "Foot",
        "Output": “FF”
}
      {
        "ValidationType": "CRC8",
        "Inputs": [
          "Head",
          “Type",
          "DataLength",
          "Data",
          “Foot"
        ],
        "Output": "CRC"
      }

The main difference between the three SDD files that we have to validate for is the DataLength. We can compare using the “Equals” ValidationType and use the actual number in byte-hex value.

Door:

 {
        "ValidationType": "Equals",
        "Input": "DataLength",
        "Output": “01”
}

Temp:

 {
        "ValidationType": "Equals",
        "Input": "DataLength",
        "Output": “04”
}

Accelerometer:

{
        "ValidationType": "Equals",
        "Input": “DataLength",
        "Output": “0C”
}

DataPackageSpec – MappingSpecification

Mappings define the data we actually want to receive in Gravio. The most important difference between the three SDD files would be the data to send to Gravio.

The Door and Temperature sensors both send 1 type of data, while the Accelerometer sends three different types of data. The Door sensor uses an integer while both Temperature and Accelerometer uses

Door:

{
  "MappingType": "Byte",
  "Mapper": {
    "MapperType": "Straight"
  },
  "Name": “Contact status",
  "OutputType": 3,
  "Size": 0,
  "Start": 0,
  "TargetField": “Data"
}

Temp:

{
  "MappingType": "Byte",
  "Mapper": {
    "MapperType": "Straight"
  },
  "Name": “Ambient temperature”,
  "OutputType": 4,
  "Size": 0,
  "Start": 0,
  "TargetField": “Data"
}

Accelerometer:

{
  "MappingType": "Byte",
  "Mapper": {
    "MapperType": "Straight"
  },
  "Name": “Accelerometer X”,
  "OutputType": 4,
  "Size": 4,
  "Start": 0,
  "TargetField": “Data"
}
{
  "MappingType": "Byte",
  "Mapper": {
    "MapperType": "Straight"
  },
  "Name": “Accelerometer Y”,
  "OutputType": 4,
  "Size": 4,
  "Start": 4,
  "TargetField": “Data"
}
{
  "MappingType": "Byte",
  "Mapper": {
    "MapperType": "Straight"
  },
  "Name": “Accelerometer Z”,
  "OutputType": 4,
  "Size": 4,
  "Start": 8,
  "TargetField": “Data"
}

DataPoints node

This is the data that is expected to be read as a reading. While this is written on the top of the SDD file, we needed to discuss the mapping first in order to understand how to get this data and thus discuss it lastly in this document.

We can use the mapped data in order to get a final data to store as a reading. DataPoint Data Rules are also useful to make fixed data more human-readable by defining set labels for specific values.

Since the Door sensor is the only fixed value sensor (only 0 as closed and 1 as opened), this is the only sensor we can write DataRules for.

Door:

  "DataPoints": [
    {
      "Name": "Contact status",
      "Type": "int",
      "DataRule": {
        "RuleType": "set",
        "Values": [
          {
            "Label": "Contact closed",
            "Value": 1
          },
          {
            "Label": "Contact open",
            "Value": 0
          }
        ]
      }
    }
  ]

Temp:

  "DataPoints": [
    {
      "Name": “Ambient temperature",
      "Type": “float",
    }
  ]

Accelerometer:

 "DataPoints": [
    {
      "Name": “Accelerometer X",
      "Type": “float",
    },
    {
      "Name": “Accelerometer Y",
      "Type": “float",
    },
    {
      "Name": “Accelerometer Z”,
      "Type": “float",
    }
  ]

Appendix: Resulting SDD files

SampleDoor.sdd

{
  "Name": "SampleDoor",
  "DataPoints": [
    {
      "Name": "Contact status",
      "Type": "int",
      "DataRule": {
        "RuleType": "set",
        "Values": [
          {
            "Label": "Contact closed",
            "Value": 1
          },
          {
            "Label": "Contact open",
            "Value": 0
          }
        ]
      }
    }
],
  "DataPackageSpec": {
    "Fields": [
      {
        "Name": "Head",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "Type",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "DataLength",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "Data",
        "Size": {
          "SizeType": "Reference",
          "SizeRef": "DataLength"
        }
      },
      {
        "Name": "Foot",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "CRC",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      }
    ],
    "Validations": [
      {
        "ValidationType": "Equals",
        "Input": "Head",
        "Output": "FE"
      },
      {
        "ValidationType": "Equals",
        "Input": "Foot",
        "Output": "FF"
      },
      {
        "ValidationType": "CRC8",
        "Inputs": [
          "Head",
          "Type",
          "DataLength",
          "Data",
          "Foot"
        ],
        "Output": "CRC"
      },
	{
        "ValidationType": "Equals",
        "Input": "DataLength",
        "Output": “01”
	}
    ],
    "Mappings": [
	 {
 	     "MappingType": "Byte",
  	     "Mapper": {
 	     "MapperType": "Straight"
 	 	},
 	 "Name": “Contact status",
 	 "OutputType": 3,
 	 "Size": 0,
 	 "Start": 0,
 	 "TargetField": “Data"
	}
]
  }
}

SampleTemperature.sdd

{
  "Name": “SampleTemperature",
  "DataPoints": [
    {
      "Name": “Ambient temperature",
      "Type": “float",
    }
  ],
  "DataPackageSpec": {
    "Fields": [
      {
        "Name": "Head",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "Type",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "DataLength",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "Data",
        "Size": {
          "SizeType": "Reference",
          "SizeRef": "DataLength"
        }
      },
      {
        "Name": "Foot",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "CRC",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      }
    ],
    "Validations": [
      {
        "ValidationType": "Equals",
        "Input": "Head",
        "Output": "FE"
      },
      {
        "ValidationType": "Equals",
        "Input": "Foot",
        "Output": "FF"
      },
      {
        "ValidationType": "CRC8",
        "Inputs": [
          "Head",
          "Type",
          "DataLength",
          "Data",
          "Foot"
        ],
        "Output": "CRC"
      },
	{
        "ValidationType": "Equals",
        "Input": "DataLength",
        "Output": “04”
	}
    ],
    "Mappings": [
	{
  	"MappingType": "Byte",
  	"Mapper": {
    	"MapperType": "Straight"
  	},
  	"Name": “Ambient temperature”,
  	"OutputType": 4,
  	"Size": 0,
  	"Start": 0,
  	"TargetField": “Data"
	}
	]
  }
}

SampleAccelerometer.sdd

{
  "Name": "SampleAccelerometer",
  "DataPoints": [
    {
      "Name": “Accelerometer X",
      "Type": “float",
    },
    {
      "Name": “Accelerometer Y",
      "Type": “float",
    },
    {
      "Name": “Accelerometer Z”,
      "Type": “float",
    }
  ],
  "DataPackageSpec": {
    "Fields": [
      {
        "Name": "Head",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "Type",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "DataLength",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "Data",
        "Size": {
          "SizeType": "Reference",
          "SizeRef": "DataLength"
        }
      },
      {
        "Name": "Foot",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      },
      {
        "Name": "CRC",
        "Size": {
          "SizeType": "Constant",
          "Size": 1
        }
      }
    ],
    "Validations": [
      {
        "ValidationType": "Equals",
        "Input": "Head",
        "Output": "FE"
      },
      {
        "ValidationType": "Equals",
        "Input": "Foot",
        "Output": "FF"
      },
      {
        "ValidationType": "CRC8",
        "Inputs": [
          "Head",
          "Type",
          "DataLength",
          "Data",
          "Foot"
        ],
        "Output": "CRC"
      },
	{
        "ValidationType": "Equals",
        "Input": “DataLength",
        "Output": “0C”
	}
    ],
    "Mappings": [
{
  	"MappingType": "Byte",
  	"Mapper": {
    	"MapperType": "Straight"
  	},
  	"Name": “Accelerometer X”,
  	"OutputType": 4,
  	"Size": 4,
  	"Start": 0,
  	"TargetField": “Data"
},
{
  	"MappingType": "Byte",
  	"Mapper": {
    	"MapperType": "Straight"
  	},
  	"Name": “Accelerometer Y”,
  	"OutputType": 4,
  	"Size": 4,
  	"Start": 4,
  	"TargetField": “Data"
},
{
  "MappingType": "Byte",
  "Mapper": {
    	"MapperType": "Straight"
 	 },
  	"Name": “Accelerometer Z”,
  	"OutputType": 4,
  	"Size": 4,
  	"Start": 8,
 	 "TargetField": “Data"
	}
	]
  }
}

Feedback

Was this helpful?

Yes No
You indicated this topic was not helpful to you ...
Could you please leave a comment telling us why? Thank you!
Thanks for your feedback.

Post your comment on this topic.

Post Comment