BrickSchema / Brick

Uniform metadata schema for buildings
http://brickschema.org/
BSD 3-Clause "New" or "Revised" License
291 stars 79 forks source link

schemas for data coming from sensors #362

Open epaulson opened 2 years ago

epaulson commented 2 years ago

This is somewhat related to #361 but perhaps a bit different.

For basic sensors, the "data" from the sensor is just a number - a temperature sensor spits out floats, and we can either find those floats by reading them from a timeseries database or using a realtime protocol like BACnet or Modbus to read them. In Brick, we put some extra metadata about how to interpret that number as a property on the sensor - is the unit F or C, or for an electrical meter how is it aggregating the data (15 minute demand average, a rolling consumption, etc)

However, as we get into other sensors and other protocols to read data from those sensors, we're going to discover that we can't make everything work with just "a number plus some properties to describe that number." - we'll see more and more sensors, probably emitting data over a message-bus-like channel of MQTT/Kafka, where the sensor reading is actually a complex blob of JSON or Avro or Protobufs, etc.

I think we're going to want another property to add to brick:Point instances that give some information about how to interpret messages from those sensors.

So, we might have something like the below (to be clear, the MQTT stuff is made up it's not in Brick today)

:officeTempSensor a brick:temperatureSensor
     brick:hasMQTTRepresentation [ mqtt:TopicName "floor1/room104/temp"; mqtt:brokerLocation "mqtt://foobar.com/"] 
     brick:messageSchema "https://github.com/faucetsdn/udmi/blob/master/tests/state.tests/example.json"

We may also want to think about how to support a schema registry, like what's commonly found with Kafka setups.

Finally, we may want to think about how to express finding particular elements of messages:

:officeTempSensor a brick:temperatureSensor
     brick:hasMQTTRepresentation [ mqtt:TopicName "floor1/room104/tempsensor"; mqtt:brokerLocation "mqtt://foobar.com/"] 
     brick:messageSchema "https://github.com/faucetsdn/udmi/blob/master/tests/state.tests/example.json"
     brick:hasDataElement "$.status.air_temperature_sensor.present_value",

I don't know what we do if there are two sensors that are glombed together - say we have some fancy sensor pack that spits out messages like

{ "id": "room104sensor",
   "status": {
       "air_temperature_sensor": {"present_value": 72.1, "unit": "F"},
       "rel_humidity": {"present_value": 55},
    }
}

Does the Brick model look like this:

:officeTempSensor a brick:temperatureSensor
     brick:hasMQTTRepresentation [ mqtt:TopicName "floor1/room104/sensor"; mqtt:brokerLocation "mqtt://foobar.com/"] ;
     brick:messageSchema "https://github.com/faucetsdn/udmi/blob/master/tests/state.tests/example.json";
     brick:hasDataElement "$.status.air_temperature_sensor.present_value" ;
     brick:hasUnitElement "$.status.air_temperature_sensor.unit" .
     # or else we just use the regular Brick unit types, since it's unlikely to change?

:officeHumSensor a brick:humiditySensor
     brick:hasMQTTRepresentation [ mqtt:TopicName "floor1/room104/sensor"; mqtt:brokerLocation "mqtt://foobar.com/"]  ;
     brick:messageSchema "https://github.com/faucetsdn/udmi/blob/master/tests/state.tests/example.json" ;
     brick:hasDataElement "$.status.rel_humidity.present_value",

Some starting places to think about here are the work that Google Digital Buildings is doing, CloudEvents, and the MQTT Sparkplug standard. (Along with I'm sure a trillion others)

I think this is a separate issue from 361, but I think we might want to keep both in mind while we tackle them, since maybe we can define some of these properties so we can use them in multiple contexts (like column identifiers/data element selection paths)

nikosandronikos commented 2 months ago

I'd implemented something similar. However I had to add a second topic per point - we output the same data on separate topics (configurable as to which is enabled, both is valid), with one option being simple data values on topics containing the full context, the other is JSON objects where the context is included in the JSON, more data is packed into the same payload, and the topic is usually shorter.

When adding the second JSON topic in, I decided to switch to something based on your definition above.

One thing I realised is that messageSchema, and hasDataElement should probably be within the hasMQTTRepresentation node, so they can be tied to that specific topic.

Here is an excerpt from a graph representing this:

<https://cognian.com/sites/gateways/1000#4aba5a58.0_relayOn>
    <http://www.w3.org/2000/01/rdf-schema#type>
    <https://brickschema.org/schema/Brick#On_Status> ;

    <https://brickschema.org/schema/Brick#isPointOf>
    <https://cognian.com/sites/gateways/1000#4aba5a58.0> ;

    <https://brickschema.org/schema/Brick#timeseries> [
        <https://brickschema.org/schema/Brick#hasTimeseriesId> "1000_4aba5a58.0_relayOn" ;
    ] ;

    <https://cognian.com/brick/extensions#hasMQTTRepresentation> [
        <https://cognian.com/brick/extensions#mqttTopic> "syncromesh/telemetry/1000/devices/4aba5a58/0/relayOn" ;
    ] ;

    <https://cognian.com/brick/extensions#hasMQTTRepresentation> [
        <https://cognian.com/brick/extensions#mqttTopic> "syncromesh/event/1000/devices/4aba5a58/0/deviceStatus" ;
        <https://cognian.com/brick/extensions#dataElement> "$.telemetry.relayOn" ;
    ] .

I'm also wondering if the broker details should be via a relationship to a specific broker connection class, to allow additional metadata beyond what can be encoded into a broker URL.

gtfierro commented 2 months ago

Interesting! I like the idea of having the schema and reference to the element associated with the topic. I think having a separate object to represent the broker is also a nice idea, because it captures some of those other parameter/properties beyond what's in the broker URL.

If you're interested in writing this up into the "ref schema", you can file a PR at https://github.com/gtfierro/ref-schema . I think capturing some of these ideas a SHACL shape would be great for re-use in future Brick models

nikosandronikos commented 2 months ago

Can't promise when, but I'll certainly do so when I get some time.