Profile (Thing Model)
A Profile is the "capability template for one kind of device"—it aggregates the Points, Commands, and Events shared by devices of the same model, describing "what this kind of device can sample, control, and report". A Device belongs to exactly one Profile, and many devices can reuse the same Profile.
What it is / why it exists
Imagine onboarding 100 temperature-and-humidity sensors of the same model. Configuring "temperature point, humidity point, calibration command, fault event" on each one separately means 100 rounds of duplicate work—change one thing and you change it 100 times. A Profile solves exactly this: factor the capability definitions out into a single template that device instances merely reference.
An analogy with product vs. physical units: a Profile is like a "product spec sheet / factory specification", and a device is like "one physical unit manufactured to that spec". You write the spec once and can build many units from it. In its own domain language DC3 names this template Profile rather than the industry-generic Product / ThingModel—different name, but it plays exactly the "product / thing model" role (see the design philosophy).
Three pairs that are easy to confuse:
- Profile vs. Device: a Profile is the "class" (defined once); a Device is the "instance" (many onboarded). The point "temperature" is defined on the Profile, while "sensor #3's temperature right now = 25.3℃"—a PointValue—is a device's runtime data.
- Profile vs. Driver: a Profile describes "which capabilities a device has" (business semantics); a Driver describes "which protocol and how to connect" (connectivity). The same Profile can be paired with different drivers; the two are orthogonal.
- Aggregates vs. owns: a Profile does not "store" the data of points / commands / events—it is only their owning root.
Point,Command, andEventeach link back to the Profile viaprofileId.
Key fields
Profile ProfileBO (table dc3_profile):
| Field | Type | Meaning |
|---|---|---|
profileName | String | Profile name (for display) |
profileCode | String | Profile code, unique within a tenant, serves as the model identifier |
profileShareFlag | ProfileShareTypeEnum | Sharing scope, see below |
profileTypeFlag | ProfileTypeEnum | Creation source, see below |
version | Integer | Model version, queryable and set manually |
profileExt | ProfileExt (JSON) | Weakly-structured extension field (designed to carry content such as category, tags) |
enableFlag | EnableFlagEnum | Enabled / disabled state |
tenantId | Long | Owning Tenant |
A Profile does not hold its sub-capabilities as fields
ProfileBO carries no list of points / commands / events—they are independent entities that link back through their own profileId foreign key. To find "which capabilities this Profile has", query Point / Command / Event separately rather than reading a field on ProfileBO.
Enumerations
Sharing scope profileShareFlag (ProfileShareTypeEnum)—controls who can reuse this Profile:
| Enum | code | Meaning |
|---|---|---|
TENANT | tenant | Shared within the tenant; all devices under the tenant may reference it |
DRIVER | driver | Shared within a driver; devices belonging to that driver may reference it |
USER | user | Private to the user; visible only to its creator |
Creation source profileTypeFlag (ProfileTypeEnum):
| Enum | code | Meaning |
|---|---|---|
SYSTEM | system | Built into the system |
DRIVER | driver | Created by a driver |
USER | user | Created by a user |
Relationship with other concepts
A Profile is the owning root of three kinds of capability—Point, Command, and Event—which side by side answer "what this kind of device can do". A Device binds exactly one Profile via profileId—a single foreign key, not a many-to-many relation. How a device connects is decided by its Driver, orthogonal to the Profile.
Lifecycle
First create the Profile and fill in its points / commands / events, then have many devices of the same model bind it; at runtime devices sample point values, receive commands, and report events according to the template; when capabilities change, bump version.
A device can bind only one Profile
Early versions let a device bind multiple Profiles (dc3_profile_bind many-to-many); this has since converged to the single foreign key Device.profileId: a device belongs to exactly one Profile, while one Profile may be reused by many devices. A device's point set comes only from the single Profile its profileId points to—never mixed across Profiles.
Example
Create a Profile for the "ZS-100 temperature-and-humidity sensor": profileCode = ZS-100, profileShareFlag = TENANT (shared within the tenant), version = 1. Under it define two points (temperature, humidity), one command (CALIBRATE), and one event (SENSOR_FAULT). The 100 sensors of this model onboarded afterward each point their Device.profileId at this single Profile to reuse all of its capabilities; next time you add a max constraint to the temperature point, you edit the Profile in one place, all 100 devices take effect at once, and version rises to 2.
API
Profile management endpoints are prefixed with /profile (Manager service):
| Method | Path | Description |
|---|---|---|
| POST | /profile/add | Create a Profile |
| POST | /profile/update | Update Profile metadata |
| POST | /profile/delete | Delete a Profile |
| GET | /profile/get_by_id | Get a Profile by ID |
| POST | /profile/list | Page through Profiles |
| GET | /profile/list_by_device_id | List the Profile bound by a device |
Further reading
- Point — the data / control points a Profile aggregates
- Command — the action-type capabilities a Profile aggregates
- Event — the reporting capabilities a Profile aggregates
- Device — the instance of a Profile, bound via
profileId - Concepts overview — a tour of all core concepts
- Domain model — where Profile sits in DC3's domain language