Define a Custom Entity Type
Hands-on: create a new entity type and fields with the Schema Editor.
In this tutorial you will use the Schema Editor to define a brand-new entity type from scratch, give it a parent to inherit from, and add a handful of fields with the correct data kinds and storage scopes. By the end you will have a persisted entity type with both inherited and direct fields, ready to hold real entity instances. We will model a simple Pump type as the running example, but the same steps apply to any type you want to define.
Looking for full details?
This is a hands-on tutorial. For the complete reference (every field, option, and edge case), see the Schema Editor reference.
What you'll need
- Access to the ControlBird platform UI with the
schema.editpermission and theDebugresponsibility. The Schema Editor will not open without both. - A desktop browser. The editor opens in a two-panel layout.
- A name in mind for your new type and a short list of fields you want it to carry. For this walkthrough we will create a
Pumptype with a setpoint, an enabled flag, and a live status.
Decide on scope before you start
The most important decision for each field is its storage scope. Configuration-scoped fields are saved persistently and survive restarts, while Runtime-scoped fields live only in memory. Sketch out which of your fields are persistent settings and which are live, derived values before you begin: it makes every step below faster.
Step by step
Open the Schema Editor. Launch it from the platform UI. The editor shows the list of entity types and loads each type's schema when you select it.
Expected result: a two-panel layout, with a searchable, paginated tree of entity types on the left (25, 50, or 100 root types per page) and an empty detail panel on the right.
Create the new entity type. Click New Entity Type (or press
Ctrl+N) to open the create form. Enter the type namePump, and in the parent selector chooseObjectso your type inherits the base structural fields.Expected result: the create form shows
PumpwithObjectlisted as its parent.Create the type. Click Create. ControlBird registers the new type with
Objectas its parent, and the type appears in the tree nested underObject.Expected result:
Pumpis visible in the type tree. Selecting it shows an entity header with its name, type ID, parent name (Object), and field counts.Review what you inherited. With
Pumpselected, look at the read-only Inherited Fields table. BecausePumpinherits fromObject, you will seeDescriptionandFaceplatescontributed by the parent. The Direct Fields table is still empty: that is what you fill in next.Inherited fields are read-only here
You cannot edit
DescriptionorFaceplatesfrom thePumpview. To change an inherited field, edit the parent type (Object) directly. The structural fieldsName,Parent, andChildrenare handled separately and never appear in the schema tables.Add a persistent setpoint field. In the Add Field section, enter the field name
Setpoint, select the kindFloat, set the rank to1, and set the storage scope toConfiguration. Optionally enter a default value such as0.0. Click Add Field.Expected result:
Setpointappears immediately in the Direct Fields table, sorted by its rank.Add an enabled flag. Add another field named
Enabledwith kindBoolean, rank2, and storage scopeConfiguration. Click Add Field. ABoolfield defaults tofalseunless you set a default.Expected result:
Enabledjoins the Direct Fields table belowSetpoint.Add a live status as a Choice field. Add a field named
Statuswith kindChoice. For a Choice field, enter the options as a comma-separated list (Idle,Running,Fault) and pick the default index0(which selectsIdle). Set the rank to3and the storage scope toRuntime, because status is a live, derived value rather than a saved setting. Click Add Field.Expected result:
Statusappears with its three options listed andIdleselected by default.Choice fields have strict rules
A
Choicefield must have at least one option, and the default index must fall within the valid range of options, here that means0to2. An out-of-range default or an empty options list will be rejected when you save.Tidy up ranks if needed. You can edit field properties inline. If two fields share the same rank, they are sorted alphabetically by name as a tie-breaker, which can produce an order you did not intend. Adjust the rank values so the fields display in the order you want.
Save your changes. Click Save Changes. The editor saves your Configuration-scoped fields persistently and updates the live schema so the tree and field counts stay accurate. To throw away unsaved edits instead, click Reset to reload from the server.
Expected result: the entity header's field counts update, and your two Configuration-scoped fields (
Setpoint,Enabled) are now saved persistently on thePumptype. The Runtime-scopedStatusfield exists only in memory.
What you built
After saving, your Pump type has the shape below. Configuration-scoped fields are stored persistently and survive restarts, while the Runtime-scoped field lives only in memory:
| Field | Kind | Scope | Where it lives |
|---|---|---|---|
Setpoint | Float | Configuration | Saved persistently |
Enabled | Bool | Configuration | Saved persistently |
Status | Choice | Runtime | In memory only |
Two things you cannot undo easily
Removing a direct field takes effect immediately, with no confirmation dialog, so double-check before removing anything, especially Configuration-scoped fields whose data is saved persistently. And once a type or field is created, it cannot be renamed. Choose names deliberately.
Next steps
Now that Pump exists, create and lay out instances of it in the Model Builder, then inspect the resulting rows in the Database Browser. To understand how field writes propagate to other services, read Notifications & Reactivity. When you need every option and edge case, return to the Schema Editor reference.