generated from sirlilpanda/kicad-project-template-actionless
253 lines
11 KiB
Zig
253 lines
11 KiB
Zig
//! ESP Matter wrapper — Zig interface to the CHIP/Matter C++ SDK via matter_stubs.h.
|
|
//!
|
|
//! Requires the `espressif/esp_matter` managed component.
|
|
//! To add it: `idf.py add-dependency espressif/esp_matter`
|
|
|
|
const sys = @import("sys");
|
|
const errors = @import("error");
|
|
|
|
// ── Re-export core types ─────────────────────────────────────────────────────
|
|
|
|
pub const Node = sys.esp_matter_node_t;
|
|
pub const Endpoint = sys.esp_matter_endpoint_t;
|
|
pub const Cluster = sys.esp_matter_cluster_t;
|
|
pub const Attribute = sys.esp_matter_attribute_t;
|
|
|
|
/// Endpoint creation flags.
|
|
pub const EpFlags = enum(u8) {
|
|
none = sys.ESP_MATTER_EP_FLAG_NONE,
|
|
destroyable = sys.ESP_MATTER_EP_FLAG_DESTROYABLE,
|
|
bridge = sys.ESP_MATTER_EP_FLAG_BRIDGE,
|
|
};
|
|
|
|
/// Attribute value types (Zig enum wrapping the C enum constants).
|
|
pub const ValType = enum(c_uint) {
|
|
invalid = sys.ESP_MATTER_VAL_TYPE_INVALID,
|
|
boolean = sys.ESP_MATTER_VAL_TYPE_BOOLEAN,
|
|
integer = sys.ESP_MATTER_VAL_TYPE_INTEGER,
|
|
float_ = sys.ESP_MATTER_VAL_TYPE_FLOAT,
|
|
array = sys.ESP_MATTER_VAL_TYPE_ARRAY,
|
|
char_string = sys.ESP_MATTER_VAL_TYPE_CHAR_STRING,
|
|
octet_string = sys.ESP_MATTER_VAL_TYPE_OCTET_STRING,
|
|
int8 = sys.ESP_MATTER_VAL_TYPE_INT8,
|
|
uint8 = sys.ESP_MATTER_VAL_TYPE_UINT8,
|
|
int16 = sys.ESP_MATTER_VAL_TYPE_INT16,
|
|
uint16 = sys.ESP_MATTER_VAL_TYPE_UINT16,
|
|
int32 = sys.ESP_MATTER_VAL_TYPE_INT32,
|
|
uint32 = sys.ESP_MATTER_VAL_TYPE_UINT32,
|
|
int64 = sys.ESP_MATTER_VAL_TYPE_INT64,
|
|
uint64 = sys.ESP_MATTER_VAL_TYPE_UINT64,
|
|
enum8 = sys.ESP_MATTER_VAL_TYPE_ENUM8,
|
|
bitmap8 = sys.ESP_MATTER_VAL_TYPE_BITMAP8,
|
|
bitmap16 = sys.ESP_MATTER_VAL_TYPE_BITMAP16,
|
|
bitmap32 = sys.ESP_MATTER_VAL_TYPE_BITMAP32,
|
|
enum16 = sys.ESP_MATTER_VAL_TYPE_ENUM16,
|
|
long_char_string = sys.ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING,
|
|
long_octet_string = sys.ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING,
|
|
_,
|
|
};
|
|
|
|
/// Attribute value (union mirroring esp_matter_val_t).
|
|
pub const Val = sys.esp_matter_val_t;
|
|
|
|
/// Attribute value with type tag.
|
|
pub const AttrVal = sys.esp_matter_attr_val_t;
|
|
|
|
/// Attribute update callback type (Zig enum with named members).
|
|
/// Use e.g. `matter.AttrCbType.ESP_MATTER_ATTR_CB_POST_UPDATE`.
|
|
pub const AttrCbType = enum(c_uint) {
|
|
ESP_MATTER_ATTR_CB_PRE_UPDATE = sys.ESP_MATTER_ATTR_CB_PRE_UPDATE,
|
|
ESP_MATTER_ATTR_CB_POST_UPDATE = sys.ESP_MATTER_ATTR_CB_POST_UPDATE,
|
|
ESP_MATTER_ATTR_CB_READ = sys.ESP_MATTER_ATTR_CB_READ,
|
|
ESP_MATTER_ATTR_CB_WRITE = sys.ESP_MATTER_ATTR_CB_WRITE,
|
|
_,
|
|
};
|
|
|
|
/// Attribute update callback function pointer type.
|
|
/// The callback receives a `?*AttrVal` which at the C ABI boundary is `[*c]AttrVal`.
|
|
/// Return 0 (ESP_OK) to allow, non-zero from PRE_UPDATE to block.
|
|
pub const AttrCallback = ?*const fn (
|
|
AttrCbType,
|
|
u16,
|
|
u32,
|
|
u32,
|
|
?*AttrVal,
|
|
?*anyopaque,
|
|
) callconv(.c) c_int;
|
|
|
|
/// Identify cluster callback type.
|
|
pub const IdentifyCbType = enum(c_uint) {
|
|
ESP_MATTER_IDENTIFY_CB_START = sys.ESP_MATTER_IDENTIFY_CB_START,
|
|
ESP_MATTER_IDENTIFY_CB_STOP = sys.ESP_MATTER_IDENTIFY_CB_STOP,
|
|
ESP_MATTER_IDENTIFY_CB_EFFECT = sys.ESP_MATTER_IDENTIFY_CB_EFFECT,
|
|
_,
|
|
};
|
|
|
|
/// Identify cluster callback function pointer type.
|
|
pub const IdentifyCallback = ?*const fn (IdentifyCbType, u16, u8, u8, ?*anyopaque) callconv(.c) c_int;
|
|
|
|
// ── Attribute value helpers ──────────────────────────────────────────────────
|
|
|
|
/// Convenience wrappers matching esp_matter_val_bool(), esp_matter_uint8(), etc.
|
|
pub const val = struct {
|
|
pub fn boolean(b: bool) AttrVal {
|
|
return sys.esp_matter_val_bool(b);
|
|
}
|
|
pub fn uint8(v: u8) AttrVal {
|
|
return sys.esp_matter_val_uint8(v);
|
|
}
|
|
pub fn uint16(v: u16) AttrVal {
|
|
return sys.esp_matter_val_uint16(v);
|
|
}
|
|
pub fn uint32(v: u32) AttrVal {
|
|
return sys.esp_matter_val_uint32(v);
|
|
}
|
|
pub fn int16(v: i16) AttrVal {
|
|
return sys.esp_matter_val_int16(v);
|
|
}
|
|
pub fn nullable() AttrVal {
|
|
return sys.esp_matter_val_nullable();
|
|
}
|
|
};
|
|
|
|
// ── Core ─────────────────────────────────────────────────────────────────────
|
|
|
|
/// Start the Matter stack (non-blocking; spawns Matter OS task).
|
|
/// Call after building the node + endpoint + cluster data model.
|
|
pub fn start(attr_cb: AttrCallback, identify_cb: IdentifyCallback) !void {
|
|
// @ptrCast converts our typed function pointer to the raw sys type.
|
|
// The types are ABI-compatible: enum(c_uint)↔c_uint, ?*T↔[*c]T.
|
|
try errors.espCheckError(sys.esp_matter_wrapper_start(@ptrCast(attr_cb), @ptrCast(identify_cb)));
|
|
}
|
|
|
|
/// Erase Matter NVS data and reboot. Non-recoverable.
|
|
pub fn factoryReset() !void {
|
|
try errors.espCheckError(sys.esp_matter_wrapper_factory_reset());
|
|
}
|
|
|
|
/// Return true if Matter has been started.
|
|
pub fn isStarted() bool {
|
|
return sys.esp_matter_wrapper_is_started();
|
|
}
|
|
|
|
// ── Node ─────────────────────────────────────────────────────────────────────
|
|
|
|
/// Create the root Matter node (endpoint 0, Root Node device type).
|
|
/// attr_cb fires on every attribute read/write; identify_cb fires on Identify requests.
|
|
/// priv_data is forwarded to both callbacks.
|
|
pub fn nodeCreate(attr_cb: AttrCallback, identify_cb: IdentifyCallback, priv_data: ?*anyopaque) !*Node {
|
|
const n = sys.esp_matter_wrapper_node_create(@ptrCast(attr_cb), @ptrCast(identify_cb), priv_data);
|
|
if (n == null) return error.MatterNodeCreateFailed;
|
|
return @ptrCast(n);
|
|
}
|
|
|
|
// ── Endpoint ─────────────────────────────────────────────────────────────────
|
|
|
|
/// Endpoint operations.
|
|
pub const endpoint = struct {
|
|
/// Create a generic endpoint on the node.
|
|
pub fn create(node: *Node, flags: EpFlags, priv_data: ?*anyopaque) !*Endpoint {
|
|
const ep = sys.esp_matter_wrapper_endpoint_create(node, @intFromEnum(flags), priv_data);
|
|
if (ep == null) return error.MatterEndpointCreateFailed;
|
|
return @ptrCast(ep);
|
|
}
|
|
|
|
/// Destroy a destroyable endpoint.
|
|
pub fn destroy(node: *Node, ep: *Endpoint) !void {
|
|
try errors.espCheckError(sys.esp_matter_wrapper_endpoint_destroy(node, ep));
|
|
}
|
|
|
|
/// Return the endpoint's numeric ID.
|
|
pub fn getId(ep: *Endpoint) u16 {
|
|
return sys.esp_matter_wrapper_endpoint_get_id(ep);
|
|
}
|
|
|
|
/// Associate a Matter device type with this endpoint.
|
|
pub fn addDeviceType(ep: *Endpoint, device_type_id: u32, version: u8) !void {
|
|
try errors.espCheckError(
|
|
sys.esp_matter_wrapper_endpoint_add_device_type(ep, device_type_id, version),
|
|
);
|
|
}
|
|
|
|
/// Enable a dynamically-created endpoint (only after Matter is started).
|
|
pub fn enable(ep: *Endpoint) !void {
|
|
try errors.espCheckError(sys.esp_matter_wrapper_endpoint_enable(ep));
|
|
}
|
|
|
|
// ── Pre-built device-type helpers ─────────────────────────────────────
|
|
|
|
/// Add an On/Off Light endpoint (device type 0x0100).
|
|
pub fn addOnOffLight(node: *Node, flags: EpFlags, priv_data: ?*anyopaque) !*Endpoint {
|
|
const ep = sys.esp_matter_wrapper_add_on_off_light(node, @intFromEnum(flags), priv_data);
|
|
if (ep == null) return error.MatterEndpointCreateFailed;
|
|
return @ptrCast(ep);
|
|
}
|
|
|
|
/// Add an On/Off Switch endpoint (device type 0x0103).
|
|
pub fn addOnOffSwitch(node: *Node, flags: EpFlags, priv_data: ?*anyopaque) !*Endpoint {
|
|
const ep = sys.esp_matter_wrapper_add_on_off_switch(node, @intFromEnum(flags), priv_data);
|
|
if (ep == null) return error.MatterEndpointCreateFailed;
|
|
return @ptrCast(ep);
|
|
}
|
|
|
|
/// Add a Dimmable Light endpoint (device type 0x0101).
|
|
pub fn addDimmableLight(node: *Node, flags: EpFlags, priv_data: ?*anyopaque) !*Endpoint {
|
|
const ep = sys.esp_matter_wrapper_add_dimmable_light(node, @intFromEnum(flags), priv_data);
|
|
if (ep == null) return error.MatterEndpointCreateFailed;
|
|
return @ptrCast(ep);
|
|
}
|
|
|
|
/// Add a Color Temperature Light endpoint (device type 0x010C).
|
|
pub fn addColorTemperatureLight(node: *Node, flags: EpFlags, priv_data: ?*anyopaque) !*Endpoint {
|
|
const ep = sys.esp_matter_wrapper_add_color_temperature_light(node, @intFromEnum(flags), priv_data);
|
|
if (ep == null) return error.MatterEndpointCreateFailed;
|
|
return @ptrCast(ep);
|
|
}
|
|
};
|
|
|
|
// ── Cluster ───────────────────────────────────────────────────────────────────
|
|
|
|
/// Cluster operations.
|
|
pub const cluster = struct {
|
|
/// Cluster flag: server cluster.
|
|
pub const FLAG_SERVER: u8 = 0x40;
|
|
/// Cluster flag: client cluster.
|
|
pub const FLAG_CLIENT: u8 = 0x80;
|
|
|
|
/// Create a cluster on an endpoint.
|
|
pub fn create(ep: *Endpoint, cluster_id: u32, flags: u8) !*Cluster {
|
|
const cl = sys.esp_matter_wrapper_cluster_create(ep, cluster_id, flags);
|
|
if (cl == null) return error.MatterClusterCreateFailed;
|
|
return @ptrCast(cl);
|
|
}
|
|
};
|
|
|
|
// ── Attribute ─────────────────────────────────────────────────────────────────
|
|
|
|
/// Attribute operations.
|
|
pub const attribute = struct {
|
|
/// Create an attribute on a cluster with a default value.
|
|
pub fn create(cl: *Cluster, attribute_id: u32, flags: u16, default_val: AttrVal) !*Attribute {
|
|
const attr = sys.esp_matter_wrapper_attribute_create(cl, attribute_id, flags, default_val);
|
|
if (attr == null) return error.MatterAttributeCreateFailed;
|
|
return @ptrCast(attr);
|
|
}
|
|
|
|
/// Update an attribute value (use after Matter is started).
|
|
pub fn update(endpoint_id: u16, cluster_id: u32, attribute_id: u32, v: *AttrVal) !void {
|
|
try errors.espCheckError(
|
|
sys.esp_matter_wrapper_attribute_update(endpoint_id, cluster_id, attribute_id, v),
|
|
);
|
|
}
|
|
|
|
/// Get the current value of an attribute.
|
|
pub fn getVal(attr: *Attribute, v: *AttrVal) !void {
|
|
try errors.espCheckError(sys.esp_matter_wrapper_attribute_get_val(attr, v));
|
|
}
|
|
|
|
/// Set an attribute value (use before Matter is started).
|
|
pub fn setVal(attr: *Attribute, v: *AttrVal) !void {
|
|
try errors.espCheckError(sys.esp_matter_wrapper_attribute_set_val(attr, v));
|
|
}
|
|
};
|