Home Security

Last Updated on : 2023-09-06 10:40:14download

Home security capabilities support arming, disarming, and alarming. This topic describes how to implement home security capabilities with TuyaOS Gateway Development Framework.

Background

The gateway supports three arming modes: arm stay, arm away, and disarm. End users can change the mode using the remote controls or the mobile app.

There are two options to arm the system.

  • Arm delay: The end user can specify a time period before the system is armed.

  • Arm ignore: When the end user switches the arming mode to arm stay or arm away, the gateway alerts the end user if there is an issue that could prevent arming, such as an unusual event reported by a sensor. In this case, the end user is prompted with three options.

    • Option 1: Ignore the issue and continue arming. The sensor still reports the unusual event, but the gateway will not trigger an alarm accordingly.
    • Option 2: Cancel arming. The gateway is restored to the previous arming state.
    • Option 3: Address the issue and continue arming. The gateway will trigger an alarm when the sensor reports an unusual event.

There are three types of alarms.

  • Arming alarms: The gateway is in an armed state. When a security sensor (such as a contact sensor and motion sensor) is triggered, the gateway issues an alarm.
  • Environmental alarms: The gateway is in armed or disarmed state. When an environmental sensor (such as flood, gas, smoke, and carbon monoxide sensors) is triggered, the gateway issues an alarm.
  • Active alarms: The gateway is in an armed or disarmed state. When the end user triggers an alarm through the mobile app, SOS button, or remote controls, the gateway issues an alarm.

When you create a gateway product on the Tuya IoT Development Platform, choose the following data points (DPs) for the home security capabilities.

DP ID DP name Data type Property
4 Alarm sound Boolean -
32 Master state Enum Enum value: normal and alarm
34 Factory reset Boolean -
45 Active alarm String -

How it works

In a home security system, arming and disarming are considered a special type of linkage, where an alarm is triggered when the specified condition is met.

TuyaOS provides the API for home security service callback. This allows you to focus on application innovation. For example, you can play a sound or turn on an LED according to the arming mode and alarming state.

Implementation

Call tuya_iot_gw_home_security_start to enable the home security service.

This API must be called before TuyaOS initialization and gateway pre-initialization. Otherwise, the home security service cannot work well.

TuyaOS provides two methods for registration. You can use either of them as needed.

  • Method 1: When you start tuya_iot_gw_home_security_start with the parameter set to NULL, TuyaOS internally implements the API for home security service callback and the DP handler. You can call tuya_iot_gw_home_security_reg_ops_cb to register a notification callback. This method lowers the barrier to development but is restricted by TuyaOS.
  • Method 2: When you start tuya_iot_gw_home_security_start with the parameter set to a non-NULL value, you need to implement the API for home security service callback and use it as the parameter. This method requires expertise in coding but allows for more flexibility in development.

Example

Implementation method 1

#include "tuya_home_security_api.h"

/**
 * @brief Alarm callback.
 *
 * @param[in] volume Alarm volume.
 * @param[in] time Alarm duration.
 */
STATIC VOID __home_security_alarm_cb(INT_T volume, UINT_T time)
{
    PR_DEBUG("home security alarm cb, volume: %d, time: %d", volume, time);
}

/**
 * @brief The callback for silencing the alarm.
 *
 * @param[in] mute_on TRUE: Mute. FALSE: Play.
 */
STATIC VOID __home_security_alarm_mute_cb(INT_T mute_on)
{
    PR_DEBUG("home security alarm mute cb, mute_on: %d", mute_on);
}

/**
 * @brief The callback for canceling the alarm.
 */
STATIC VOID __home_security_alarm_cancel_cb(VOID)
{
    PR_DEBUG("home security alarm cancel cb");
}

/**
 * @brief The callback for disarming the system.
 *
 * @param[in] volume Alarm volume.
 */
STATIC VOID __home_security_disarmed_cb(INT_T volume)
{
    PR_DEBUG("home security disarmed cb, volume: %d", volume);
}

/**
 * @brief The callback for activating arm away.
 *
 * @param[in] volume Alarm volume.
 */
STATIC VOID __home_security_away_and_armed_cb(INT_T volume)
{
    PR_DEBUG("home security away armed cb, volume: %d", volume);
}

/**
 * @brief The callback for activating arm stay.
 *
 * @param[in] volume Alarm volume.
 */
STATIC VOID __home_security_home_and_armed_cb(INT_T volume)
{
    PR_DEBUG("home security home armed cb, volume: %d", volume);
}

/**
 * @brief The callback for bypassing arm.
 *
 * @param[in] volume Alarm volume.
 */
STATIC VOID __home_security_arm_ignore_cb(INT_T volume)
{
    PR_DEBUG("home security arm ignore cb, volume: %d", volume);
}

/**
 * @brief The callback for arm delay.
 *
 * @param[in] volume Alarm volume.
 * @param[in] time The delay time, in seconds.
 */
STATIC VOID __home_security_arm_countdown_cb(INT_T volume, UINT_T time)
{
    PR_DEBUG("home security arm delay cb, volume: %d, time: %d", volume, time);
}

/**
 * @brief The callback for alarm delay.
 *
 * @param[in] volume Alarm volume.
 * @param[in] time   The delay time, in seconds.
 */
STATIC VOID __home_security_alarm_countdown_cb(INT_T volume, UINT_T time)
{
    PR_DEBUG("home security alarm delay cb, volume: %d, time: %d", volume, time);
}

OPERATE_RET demo_home_security(VOID)
{
    OPERATE_RET rt = OPRT_OK;
    TY_HOME_SECURITY_OPS_CB_S security_alarm_ops_cb = {
        .alarm_cb           = __home_security_alarm_cb,
        .alarm_mute_cb      = __home_security_alarm_mute_cb,
        .alarm_cancel_cb    = __home_security_alarm_cancel_cb,
        .disarmed_cb        = __home_security_disarmed_cb,
        .away_and_armed_cb  = __home_security_away_and_armed_cb,
        .home_and_armed_cb  = __home_security_home_and_armed_cb,
        .arm_ignore_cb      = __home_security_arm_ignore_cb,
        .arm_countdown_cb   = __home_security_arm_countdown_cb,
        .alarm_countdown_cb = __home_security_alarm_countdown_cb,
    };

    // TuyaOS initialization.
    TUYA_CALL_ERR_RETURN(tuya_iot_init("./"));

    // Register callbacks.
    TUYA_CALL_ERR_RETURN(tuya_iot_gw_home_security_reg_ops_cb(&security_alarm_ops_cb));
	// Enable home security service.
    TUYA_CALL_ERR_RETURN(tuya_iot_gw_home_security_start(NULL));

    // Gateway pre-initialization.
	tuya_iot_sdk_pre_init(TRUE);

    return OPRT_OK;
}

Implementation method 2

#include "tuya_home_security_api.h"

/**
 * @brief The callback for caching DP data when the gateway goes offline.
 * @note When the gateway goes offline, this callback is invoked to notify the gateway of DP data reporting. The gateway can cache the received data and send them to the cloud when it gets back online.
 *       If your product does not require this feature, leave it as it is.
 *
 * @param[in] dev_id The unique ID of the device, used to identify the device that reports the data.
 * @param[in] dps  An array of DP data.
 * @param[in] dp_cnt The length of the array of DP data.
 *
 * @return OPRT_OK on success. Others on error. See tuya_error_code.h
 */
STATIC OPERATE_RET __home_security_save_dp_cb(IN CONST CHAR_T *dev_id, IN CONST TY_OBJ_DP_S *dps, IN CONST UINT_T dp_cnt)
{
    return OPRT_OK;
}

/**
 * @brief The callback for switching between arming and disarming.
 *
 * @param[in] mode_str "0": Disarm. "1": Arm stay. "2": Arm away.
 * @param[in] time     The delay time.
 * @param[in] is_sound TRUE: Make a sound. FALSE: Not make a sound.
 */
STATIC VOID __home_security_set_mode_cb(IN CONST CHAR_T *mode_str, IN CONST UINT_T time, BOOL_T is_sound)
{
    return;
}

/**
 * @brief The callback for alarm delay.
 *
 * @param[in] status The delay status: begin, in progress, end
 */
STATIC VOID __home_security_alarm_delay_status_cb(IN ALARM_DELAY_STATE status)
{
    return;
}

/**
 * @brief The callback for home security events.
 *
 * @param[in] event Event: DISARMED_EVENT (Disarmed)
 *                       ARMED_EVENT (Armed)
 *                       BYPASS_EVNET (Bypass arm)
 *                       WARING_COUNTDOWN (Alarm delay)
 * @param[in] data  The data.
 *                  When an event is WARING_COUNTDOWN, the data type of the data is UINT_T, indicating the delay time.
 *                  For other events, the data is NULL.
 */
STATIC VOID __home_security_event_cb(IN SECURITY_EVENT_E event, PVOID_T data)
{
    return;
}

/**
 * @brief The callback for canceling an alarm.
 */
STATIC VOID __home_security_cancel_alarm_cb(VOID)
{
    return;
}

/**
 * @brief The callback for device-triggered alarms.
 *
 * @param[in] cid     The ID of the device that triggers the alarm.
 * @param[in] dp_info The device's DP that triggers the alarm.
 * @param[in] type    The type of the device. NO_ENV_DEV: Non-environmental sensor.  ENV_DEV: Environmental sensor.
 */
STATIC VOID __home_security_device_alarm_cb(IN CONST CHAR_T *cid, IN ty_cJSON *dp_info, SECURITY_DEV_TYPE_E type)
{
    return;
}

/**
 * @brief Alarm callback.
 *
 * @param[in] alarm_on   The alarm status. TRUE: Alarming. FALSE: All good.
 * @param[in] alarm_info The alarm information.
 */
STATIC VOID __home_security_enter_alarm_cb(IN BOOL_T alarm_on, IN CHAR_T *alarm_info)
{
    return;
}

/**
 * @brief Process home security related DPs.
 */
STATIC OPERATE_RET __home_security_dp_obj_cmd(IN TY_OBJ_DP_S dp)
{
    BYTE_T dpid = dp.dpid;
    switch (dpid) {
        case 4: {
            // Alarm sound on/off
            break;
        }
        case 32: {
            // A device triggers the alarm.
            break;
        }
        case 34: {
            // Restart
            break;
        }
        case 45: {
            // The mobile app triggers the alarm.
            break;
        }
        default: {
            break;
        }
    }

    return OPRT_OK;
}

/**
 * @brief The callback for gateway DPs handler.
 */
VOID __gw_dp_cmd_obj(IN CONST TY_RECV_OBJ_DP_S *dp)
{
    UINT_T i = 0;

    PR_DEBUG("gw obj dp cmd");

    // Use the data reported by the sub-device as a response to the request.
    dev_report_dp_json_async(dp->cid, dp->dps, dp->dps_cnt);

    for (i = 0; i < dp->dps_cnt; i++) {
        __home_security_dp_obj_cmd(dp->dps[i]);
    }
}

OPERATE_RET demo_home_security(VOID)
{
    OPERATE_RET rt = OPRT_OK;
    TY_GW_HOME_SECURITY_APP_CBS_S security_app_cbs = {
        .gw_offline_dp_save_cb                  = __home_security_save_dp_cb,
        .gw_home_security_if_cb                 = __home_security_set_mode_cb,
        .gw_home_security_alarm_delay_status_cb = __home_security_alarm_delay_status_cb,
        .gw_home_security_event_cb              = __home_security_event_cb,
        .gw_home_security_cancel_alarm          = __home_security_cancel_alarm_cb,
        .gw_home_security_alarm_dev_new_cb      = __home_security_device_alarm_cb,
        .gw_home_security_enter_alarm_cb        = __home_security_enter_alarm_cb,
    };

    TY_GW_DP_CBS_S dp_cbs = {
        .obj   = __gw_dp_cmd_obj,
    };

    // TuyaOS initialization.
    TUYA_CALL_ERR_RETURN(tuya_iot_init("./"));

    // Register the data reception of gateway's DPs.
    TUYA_CALL_ERR_RETURN(tuya_gw_user_dp_reg(&dp_cbs));

	// Enable home security service between TuyaOS initialization and gateway pre-initialization.
    TUYA_CALL_ERR_RETURN(tuya_iot_gw_home_security_start(&security_app_cbs));

    // Gateway pre-initialization.
	tuya_iot_sdk_pre_init(TRUE);

    return OPRT_OK;
}

Data type

ALARM_DELAY_STATE

typedef enum  {
    ALARM_DELAY_DONOT_CREATE=0, // Delay begins.
    ALARM_DELAY_COUNTDOWN,      // Delay is in progress.
    ALARM_DELAY_END,            // Delay ends.
} ALARM_DELAY_STATE;

ALARM_INFO_S

typedef struct {
    CHAR_T alarm_mode[ALARM_SECURITY_MODE_STR_LEN_MAX+1];  // The arming mode. "0": Disarm. "1": Arm stay. "2": Arm away.
    BOOL_T alarm_status; // The alarm status. TRUE: Alarming. FALSE: All good.
    BOOL_T enable_countdown_status; // Specifies whether a delay is in progress.  TRUE: In progress. FALSE: No delay activated.
} ALARM_INFO_S;

SECURITY_EVENT_E

typedef enum {
    DISARMED_EVENT,     // Disarmed
    ARMED_EVENT,        // Armed in stay mode or away mode.
    BYPASS_EVNET,       // Bypass arm
    WARING_COUNTDOWN,   // Alarm delay
} SECURITY_EVENT_E;

SECURITY_DEV_TYPE_E

typedef enum  {
    NO_ENV_DEV,   // A non-environmental sensor, such as a contact sensor or motion sensor.
    ENV_DEV,      // An environmental sensor, such as a flood detector or smoke detector.
} SECURITY_DEV_TYPE_E;

TY_HOME_SECURITY_OPS_CB_S

typedef struct {
    VOID (*alarm_cb)(INT_T volume, UINT_T time); // Alarm callback.
    VOID (*alarm_mute_cb)(INT_T mute_on); // The callback for silencing the alarm.
    VOID (*alarm_cancel_cb)(VOID); // The callback for canceling the alarm.
    VOID (*disarmed_cb)(INT_T volume);  // The callback for disarming the system.
    VOID (*away_and_armed_cb)(INT_T volume); // The callback for activating arm away.
    VOID (*home_and_armed_cb)(INT_T volume); // The callback for activating arm stay.
    VOID (*arm_ignore_cb)(INT_T volume); // The callback for bypassing arm.
    VOID (*arm_countdown_cb)(INT_T volume, UINT_T countdown_time); // The callback for arm delay.
    VOID (*alarm_countdown_cb)(INT_T volume, UINT_T countdown_time); // The callback for alarm delay.
    VOID (*alarm_door_cb)(INT_T volume); // Deprecated
    VOID (*alarm_devname_cb)(INT_T volume, CHAR_T *name); // Deprecated
} TY_HOME_SECURITY_OPS_CB_S;

TY_GW_HOME_SECURITY_APP_CBS_S

typedef struct {
    GW_OFFLINE_DP_SAVE gw_offline_dp_save_cb; // The callback for caching DP data when the gateway goes offline.
    GW_HOME_SECURITY_IF_CB gw_home_security_if_cb; // The callback for switching between arming and disarming.
    GW_HOME_SECURITY_ALARM_DELAY_STATUS_CB gw_home_security_alarm_delay_status_cb; // The callback for alarm delay.
    GW_HOME_SECURITY_EVENT_CB gw_home_security_event_cb; // The callback for home security events.
    GW_HOME_SECURITY_CANCEL_ALARM_CB gw_home_security_cancel_alarm; // The callback for canceling an alarm.
    GW_HOME_SECURITY_ALARM_DEV_NEW_CB gw_home_security_alarm_dev_new_cb; // The callback for device-triggered alarms.
	GW_HOME_SECURITY_ENTER_ALARM_CB gw_home_security_enter_alarm_cb; // Alarm callback.
} TY_GW_HOME_SECURITY_APP_CBS_S;

Callback

GW_OFFLINE_DP_SAVE

/**
 * @brief The callback for caching DP data when the gateway goes offline.
 * @note When the gateway goes offline, this callback is invoked to notify the gateway of DP data reporting. The gateway can cache the received data and send them to the cloud when it gets back online.
 *       If your product does not require this feature, leave it as it is.
 *
 * @param[in] dev_id The unique ID of the device, used to identify the device that reports the data.
 * @param[in] dps An array of DP data.
 * @param[in] dp_cnt The length of the array of DP data.
 *
 * @return OPRT_OK on success. Others on error. See tuya_error_code.h
 */
typedef OPERATE_RET (*GW_OFFLINE_DP_SAVE)(IN CONST CHAR_T *dev_id, IN CONST TY_OBJ_DP_S *dp_data, IN CONST UINT_T cnt);

GW_HOME_SECURITY_IF_CB

/**
 * @brief The callback for switching between arming and disarming.
 *
 * @param[in] mode_str "0": Disarm. "1": Arm stay. "2": Arm away.
 * @param[in] time     The delay time.
 * @param[in] is_sound TRUE: Make a sound. FALSE: Not make a sound.
 */
typedef VOID (*GW_HOME_SECURITY_IF_CB)(IN CONST CHAR_T *mode_str, IN CONST UINT_T time, BOOL_T is_sound);

GW_HOME_SECURITY_ALARM_DELAY_STATUS_CB

/**
 * @brief The callback for alarm delay.
 *
 * @param[in] status The delay status: begin, in progress, end
 */
typedef VOID (*GW_HOME_SECURITY_ALARM_DELAY_STATUS_CB)(IN ALARM_DELAY_STATE alarm_status);

GW_HOME_SECURITY_EVENT_CB

/**
 * @brief The callback for home security events.
 *
 * @param[in] event Event: DISARMED_EVENT (Disarmed)
 *                       ARMED_EVENT (Armed)
 *                       BYPASS_EVNET (Bypass arm)
 *                       WARING_COUNTDOWN(Alarm delay)
 * @param[in] data  The data.
 *                  When an event is WARING_COUNTDOWN, the data type of the data is UINT_T, indicating the delay time.
 *                  For other events, the data is NULL.
 */
typedef VOID (*GW_HOME_SECURITY_EVENT_CB)(IN SECURITY_EVENT_E security_event_status, PVOID_T data);

GW_HOME_SECURITY_CANCEL_ALARM_CB

/**
 * @brief The callback for canceling an alarm.
 */
typedef VOID (*GW_HOME_SECURITY_CANCEL_ALARM_CB)(VOID);

GW_HOME_SECURITY_ALARM_DEV_NEW_CB

/**
 * @brief The callback for device-triggered alarms.
 *
 * @param[in] cid     The ID of the device that triggers the alarm.
 * @param[in] dp_info The device's DP that triggers the alarm.
 * @param[in] type    The type of the device. NO_ENV_DEV: Non-environmental sensor.  ENV_DEV: Environmental sensor.
 */
typedef VOID (*GW_HOME_SECURITY_ALARM_DEV_NEW_CB)(IN CONST CHAR_T *cid, IN ty_cJSON *dp_inf, SECURITY_DEV_TYPE_E dev_type);

GW_HOME_SECURITY_ENTER_ALARM_CB

/**
 * @brief Alarm callback.
 *
 * @param[in] alarm_on   The alarm status. TRUE: Alarming. FALSE: All good.
 * @param[in] alarm_info The alarm information.
 */
typedef VOID (*GW_HOME_SECURITY_ENTER_ALARM_CB)(IN BOOL_T alarm_status, IN CHAR_T *alarm_info);

API description

Enable home security service

/**
 * @brief Enable home security service.
 * @note This interface must be called between TuyaOS initialization and gateway pre-initialization.
 *
 * @param[in] iot_alarm_cbs See TY_GW_HOME_SECURITY_APP_CBS_S
 *            If this parameter is empty, you can call `tuya_iot_gw_home_security_reg_ops_cb` to register an additional callback.
 *           If this parameter is not empty, you need to implement the callback interface.
 *
 * @return OPRT_OK for success. For other error codes, see tuya_error_code.h
 */
OPERATE_RET tuya_iot_gw_home_security_start(TY_GW_HOME_SECURITY_APP_CBS_S *iot_alarm_cbs);

Register callbacks

/**
 * @brief Register home security service callbacks.
 *
 * @param[in] cbs See TY_HOME_SECURITY_OPS_CB_S
 *
 * @return OPRT_OK for success. For other error codes, see tuya_error_code.h
 */
OPERATE_RET tuya_iot_gw_home_security_reg_ops_cb(TY_HOME_SECURITY_OPS_CB_S *cbs);

Set the arming mode

/**
 * @brief Set the arming mode.
 *
 * @param[in] mode_str  "0": Disarm. "1": Arm stay. "2": Arm away.
 * @param[in] node_id The ID of the device that executes the specified arming mode. It is NULL generally, indicating the gateway.
 * @param[in] delay_str The delay time, a JSON string. For example: "{\"1\":1000}", indicating arm stay with a delay time of 1,000 seconds.
 *
 * @return OPRT_OK for success. For other error codes, see tuya_error_code.h
 */
OPERATE_RET tuya_iot_home_secruity_info_set(IN CONST CHAR_T *mode_str, IN CONST CHAR_T *node_id, IN CONST CHAR_T *delay_str);

Get the arming/alarming state

/**
 * @brief Get the arming mode or alarm information.
 *
 * @param[out] alarm_info See ALARM_INFO_S
 *
 * @return OPRT_OK for success. For other error codes, see tuya_error_code.h
 */
OPERATE_RET tuya_iot_home_secruity_get_alarm_info(OUT ALARM_INFO_S *alarm_info);