Protos – Project Haystack




Prototypes, or simply protos, are dict templates. A proto is just a normal dict of name/value pairs along with a special tag expansion mechanism.

Protos are primarily used to declare typical sub-parts of an entity via the children tag. For example, we use protos to answer questions such as "what points might be contained by a chiller?" Protos are generated into Project Haystack documentation. They are also used to power menu options in vendor tools.


The children tag for an entity is a list of prototype dicts:

def: ^pipe
children: [
  {valve actuator equip},
  {flow sensor point},
  {temp sensor point},

You can see these children protos in the docs for pipe.


Entities with children protos can specify that specific tags are flattened into their children. For example, Haystack convention dictates that points within a specific pipe include tags to indicate the pipe section and the fluid being sensed:

// parent pipe
steam leaving pipe equip

// child points
steam leaving valve actuator equip
steam leaving temp sensor point
steam leaving flow sensor point

This convention makes it easy to query points using tag combinations without regard to if or how parent pipes are modeled.

We use the childrenFlatten tag to indicate that these tags should be flattened into their children. In our pipe example:

def: ^pipe
conveys: ^fluid
childrenFlatten: [^fluid, ^pipeSection]
children: [
  {valve actuator equip},
  {flow point},
  {temp point},

Flattening occurs when we are given an instance of a parent pipe and want to generate the children protos. We walk each symbol in the childrenFlattens list and, if the parent implements the def, then it is flattened into each child proto. Lets look at some concrete examples:

First, lets look at a parent pipe that implements neither a fluid term nor a pipeSection term:

// parent pipe
pipe equip

// children protos, no tags to flatten
valve actuator equip
flow point
temp point

In the following example, the parent pipe implements the fluid subtype of hot-water

// parent pipe
hot water pipe equip

// children protos include hot-water conjunct
hot water valve actuator equip
hot water flow point
hot water temp point

In the following example, the parent pipe implements both fluid via the subtype naturalGas and also pipeSection via the subtype entering:

// parent pipe
leaving naturalGas pipe equip

// children protos include both leaving and naturalGas
leaving naturalGas valve actuator equip
leaving naturalGas flow point
leaving naturalGas temp point

This technique becomes a powerful tool to auto-expand tag combinations when used with equipment containing known children:

def: ^chiller
children: [
  {chilled water leaving pipe equip},
  {chilled water entering pipe equip},
  {condenser water leaving pipe equip},
  {condenser water entering pipe equip},

In the chiller example above, it is not necessary to enumerate every possible combination of chiller point. Rather, we declare that chillers have four specific pipes. Using indirection, we can then derive the various points by flattening the generic pipe definition.